diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp index 85f8e35e86f56ca379750635fd6f530963858d7a..7ff994b0c6a6852bf8f58080b65759b9d6f2994c 100644 --- a/intern/cycles/graph/node_xml.cpp +++ b/intern/cycles/graph/node_xml.cpp @@ -7,429 +7,552 @@ #include "util/foreach.h" #include "util/string.h" #include "util/transform.h" +#include "util/path.h" -CCL_NAMESPACE_BEGIN - -static bool xml_read_boolean(const char *value) -{ - return string_iequals(value, "true") || (atoi(value) != 0); -} +#include "scene/object.h" -static const char *xml_write_boolean(bool value) -{ - return (value) ? "true" : "false"; -} +CCL_NAMESPACE_BEGIN -template<int VECTOR_SIZE, typename T> -static void xml_read_float_array(T &value, xml_attribute attr) +// Function to write an array to a binary file +template<typename T> +string write_array_to_binary_file(XMLWriter& writer, const array<T>& data) { - vector<string> tokens; - string_split(tokens, attr.value()); + std::stringstream ss; + ss << writer.offset; - if (tokens.size() % VECTOR_SIZE != 0) { - return; - } + // Write the size of the vector first + size_t data_size = data.size(); + writer.file.write(reinterpret_cast<const char*>(&data_size), sizeof(size_t)); + writer.offset += sizeof(size_t); - value.resize(tokens.size() / VECTOR_SIZE); - for (size_t i = 0; i < value.size(); i++) { - float *value_float = (float *)&value[i]; + // Write the actual data to the file + writer.file.write(reinterpret_cast<const char*>(data.data()), data_size * sizeof(T)); + writer.offset += data_size * sizeof(T); - for (size_t j = 0; j < VECTOR_SIZE; j++) { - value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str()); - } - } + return ss.str(); } -void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node) -{ - xml_attribute name_attr = xml_node.attribute("name"); - if (name_attr) { - node->name = ustring(name_attr.value()); - } +bool xml_pointer_to_name_check(Node* node) { + if (node->name == "default_background" || + node->name == "default_empty" || + node->name == "default_light" || + node->name == "default_surface" || + node->name == "default_volume") { - foreach (const SocketType &socket, node->type->inputs) { - if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) { - continue; + return false; } - if (socket.flags & SocketType::INTERNAL) { - continue; - } - - xml_attribute attr = xml_node.attribute(socket.name.c_str()); - - if (!attr) { - continue; - } - - switch (socket.type) { - case SocketType::BOOLEAN: { - node->set(socket, xml_read_boolean(attr.value())); - break; - } - case SocketType::BOOLEAN_ARRAY: { - vector<string> tokens; - string_split(tokens, attr.value()); - array<bool> value; - value.resize(tokens.size()); - for (size_t i = 0; i < value.size(); i++) { - value[i] = xml_read_boolean(tokens[i].c_str()); - } - node->set(socket, value); - break; - } - case SocketType::FLOAT: { - node->set(socket, (float)atof(attr.value())); - break; - } - case SocketType::FLOAT_ARRAY: { - array<float> value; - xml_read_float_array<1>(value, attr); - node->set(socket, value); - break; - } - case SocketType::INT: { - node->set(socket, (int)atoi(attr.value())); - break; - } - case SocketType::UINT: { - node->set(socket, (uint)atoi(attr.value())); - break; - } - case SocketType::UINT64: { - node->set(socket, (uint64_t)strtoull(attr.value(), nullptr, 10)); - break; - } - case SocketType::INT_ARRAY: { - vector<string> tokens; - string_split(tokens, attr.value()); + return true; +} +string xml_pointer_to_name(void *ptr) +{ + // Convert void* to name + size_t ptrAsSizeT = reinterpret_cast<size_t>(ptr); + std::string ptrAsString = std::to_string(ptrAsSizeT); + return ptrAsString; +} - array<int> value; - value.resize(tokens.size()); - for (size_t i = 0; i < value.size(); i++) { - value[i] = (int)atoi(attr.value()); - } - node->set(socket, value); - break; - } - case SocketType::COLOR: - case SocketType::VECTOR: - case SocketType::POINT: - case SocketType::NORMAL: { - array<float3> value; - xml_read_float_array<3>(value, attr); - if (value.size() == 1) { - node->set(socket, value[0]); - } - break; - } - case SocketType::COLOR_ARRAY: - case SocketType::VECTOR_ARRAY: - case SocketType::POINT_ARRAY: - case SocketType::NORMAL_ARRAY: { - array<float3> value; - xml_read_float_array<3>(value, attr); - node->set(socket, value); - break; - } - case SocketType::POINT2: { - array<float2> value; - xml_read_float_array<2>(value, attr); - if (value.size() == 1) { - node->set(socket, value[0]); - } - break; - } - case SocketType::POINT2_ARRAY: { - array<float2> value; - xml_read_float_array<2>(value, attr); - node->set(socket, value); - break; - } - case SocketType::STRING: { - node->set(socket, attr.value()); - break; - } - case SocketType::ENUM: { - ustring value(attr.value()); - if (socket.enum_values->exists(value)) { - node->set(socket, value); - } - else { - fprintf(stderr, - "Unknown value \"%s\" for attribute \"%s\".\n", - value.c_str(), - socket.name.c_str()); - } - break; - } - case SocketType::STRING_ARRAY: { - vector<string> tokens; - string_split(tokens, attr.value()); +string xml_fix_tag(ustring tag) +{ + string str = tag.string(); + std::replace(str.begin(), str.end(), ' ', '_'); - array<ustring> value; - value.resize(tokens.size()); - for (size_t i = 0; i < value.size(); i++) { - value[i] = ustring(tokens[i]); - } - node->set(socket, value); - break; - } - case SocketType::TRANSFORM: { - array<Transform> value; - xml_read_float_array<12>(value, attr); - if (value.size() == 1) { - node->set(socket, value[0]); - } - break; - } - case SocketType::TRANSFORM_ARRAY: { - array<Transform> value; - xml_read_float_array<12>(value, attr); - node->set(socket, value); - break; - } - case SocketType::NODE: { - ustring value(attr.value()); - map<ustring, Node *>::iterator it = reader.node_map.find(value); - if (it != reader.node_map.end()) { - Node *value_node = it->second; - if (value_node->is_a(socket.node_type)) { - node->set(socket, it->second); - } - } - break; - } - case SocketType::NODE_ARRAY: { - vector<string> tokens; - string_split(tokens, attr.value()); + return str; +} - array<Node *> value; - value.resize(tokens.size()); - for (size_t i = 0; i < value.size(); i++) { - map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i])); - if (it != reader.node_map.end()) { - Node *value_node = it->second; - value[i] = (value_node->is_a(socket.node_type)) ? value_node : NULL; - } - else { - value[i] = NULL; - } - } - node->set(socket, value); - break; - } - case SocketType::CLOSURE: - case SocketType::UNDEFINED: - case SocketType::NUM_TYPES: - break; - } - } +//static bool xml_read_boolean(const char *value) +//{ +// return string_iequals(value, "true") || (atoi(value) != 0); +//} - if (!node->name.empty()) { - reader.node_map[node->name] = node; - } +static const char *xml_write_boolean(bool value) +{ + return (value) ? "true" : "false"; } -xml_node xml_write_node(Node *node, xml_node xml_root) -{ - xml_node xml_node = xml_root.append_child(node->type->name.c_str()); +//template<int VECTOR_SIZE, typename T> +//static void xml_read_float_array(T &value, xml_attribute attr) +//{ +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// if (tokens.size() % VECTOR_SIZE != 0) { +// return; +// } +// +// value.resize(tokens.size() / VECTOR_SIZE); +// for (size_t i = 0; i < value.size(); i++) { +// float *value_float = (float *)&value[i]; +// +// for (size_t j = 0; j < VECTOR_SIZE; j++) { +// value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str()); +// } +// } +//} - xml_node.append_attribute("name") = node->name.c_str(); +//void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node) +//{ +// xml_attribute name_attr = xml_node.attribute("name"); +// if (name_attr) { +// node->name = ustring(name_attr.value()); +// } +// +// foreach (const SocketType &socket, node->type->inputs) { +// if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) { +// continue; +// } +// if (socket.flags & SocketType::INTERNAL) { +// continue; +// } +// +// xml_attribute attr = xml_node.attribute(socket.ui_name.c_str()); +// +// if (!attr) { +// continue; +// } +// +// switch (socket.type) { +// case SocketType::BOOLEAN: { +// node->set(socket, xml_read_boolean(attr.value())); +// break; +// } +// case SocketType::BOOLEAN_ARRAY: { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// array<bool> value; +// value.resize(tokens.size()); +// for (size_t i = 0; i < value.size(); i++) { +// value[i] = xml_read_boolean(tokens[i].c_str()); +// } +// node->set(socket, value); +// break; +// } +// case SocketType::FLOAT: { +// node->set(socket, (float)atof(attr.value())); +// break; +// } +// case SocketType::FLOAT_ARRAY: { +// array<float> value; +// xml_read_float_array<1>(value, attr); +// node->set(socket, value); +// break; +// } +// case SocketType::INT: { +// node->set(socket, (int)atoi(attr.value())); +// break; +// } +// case SocketType::UINT: { +// node->set(socket, (uint)atoi(attr.value())); +// break; +// } +// case SocketType::UINT64: { +// node->set(socket, (uint64_t)strtoull(attr.value(), nullptr, 10)); +// break; +// } +// case SocketType::INT_ARRAY: { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// array<int> value; +// value.resize(tokens.size()); +// for (size_t i = 0; i < value.size(); i++) { +// value[i] = (int)atoi(attr.value()); +// } +// node->set(socket, value); +// break; +// } +// case SocketType::COLOR: +// case SocketType::VECTOR: +// case SocketType::POINT: +// case SocketType::NORMAL: { +// array<float3> value; +// xml_read_float_array<3>(value, attr); +// if (value.size() == 1) { +// node->set(socket, value[0]); +// } +// break; +// } +// case SocketType::COLOR_ARRAY: +// case SocketType::VECTOR_ARRAY: +// case SocketType::POINT_ARRAY: +// case SocketType::NORMAL_ARRAY: { +// array<float3> value; +// xml_read_float_array<3>(value, attr); +// node->set(socket, value); +// break; +// } +// case SocketType::POINT2: { +// array<float2> value; +// xml_read_float_array<2>(value, attr); +// if (value.size() == 1) { +// node->set(socket, value[0]); +// } +// break; +// } +// case SocketType::POINT2_ARRAY: { +// array<float2> value; +// xml_read_float_array<2>(value, attr); +// node->set(socket, value); +// break; +// } +// case SocketType::STRING: { +// node->set(socket, attr.value()); +// break; +// } +// case SocketType::ENUM: { +// ustring value(attr.value()); +// if (socket.enum_values->exists(value)) { +// node->set(socket, value); +// } +// else { +// fprintf(stderr, +// "Unknown value \"%s\" for attribute \"%s\".\n", +// value.c_str(), +// socket.ui_name.c_str()); +// } +// break; +// } +// case SocketType::STRING_ARRAY: { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// array<ustring> value; +// value.resize(tokens.size()); +// for (size_t i = 0; i < value.size(); i++) { +// value[i] = ustring(tokens[i]); +// } +// node->set(socket, value); +// break; +// } +// case SocketType::TRANSFORM: { +// array<Transform> value; +// xml_read_float_array<12>(value, attr); +// if (value.size() == 1) { +// node->set(socket, value[0]); +// } +// break; +// } +// case SocketType::TRANSFORM_ARRAY: { +// array<Transform> value; +// xml_read_float_array<12>(value, attr); +// node->set(socket, value); +// break; +// } +// case SocketType::NODE: { +// ustring value(attr.value()); +// map<ustring, Node *>::iterator it = reader.node_map.find(value); +// if (it != reader.node_map.end()) { +// Node *value_node = it->second; +// if (value_node->is_a(socket.node_type)) { +// node->set(socket, it->second); +// } +// } +// break; +// } +// case SocketType::NODE_ARRAY: { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// array<Node *> value; +// value.resize(tokens.size()); +// for (size_t i = 0; i < value.size(); i++) { +// map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i])); +// if (it != reader.node_map.end()) { +// Node *value_node = it->second; +// value[i] = (value_node->is_a(socket.node_type)) ? value_node : NULL; +// } +// else { +// value[i] = NULL; +// } +// } +// node->set(socket, value); +// break; +// } +// case SocketType::CLOSURE: +// case SocketType::UNDEFINED: +// case SocketType::NUM_TYPES: +// break; +// } +// } +// +// if (!node->name.empty()) { +// reader.node_map[node->name] = node; +// } +//} - foreach (const SocketType &socket, node->type->inputs) { +void xml_write_node_socket(XMLWriter& writer, Node* node, xml_node xml_root, const SocketType& socket, xml_node xml_node_main, string xml_node_name) +{ if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) { - continue; + return; } if (socket.flags & SocketType::INTERNAL) { - continue; + return; } - if (node->has_default_value(socket)) { - continue; + if (socket.default_value && node->has_default_value(socket)) { + return; } - xml_attribute attr = xml_node.append_attribute(socket.name.c_str()); + string attr; switch (socket.type) { - case SocketType::BOOLEAN: { + case SocketType::BOOLEAN: { attr = xml_write_boolean(node->get_bool(socket)); break; - } - case SocketType::BOOLEAN_ARRAY: { + } + case SocketType::BOOLEAN_ARRAY: { std::stringstream ss; - const array<bool> &value = node->get_bool_array(socket); - for (size_t i = 0; i < value.size(); i++) { - ss << xml_write_boolean(value[i]); - if (i != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<bool>& value = node->get_bool_array(socket); + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::FLOAT: { - attr = (double)node->get_float(socket); + } + case SocketType::FLOAT: { + std::stringstream ss; + ss << (double)node->get_float(socket); + attr = ss.str(); break; - } - case SocketType::FLOAT_ARRAY: { + } + case SocketType::FLOAT_ARRAY: { std::stringstream ss; - const array<float> &value = node->get_float_array(socket); - for (size_t i = 0; i < value.size(); i++) { - ss << value[i]; - if (i != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<float>& value = node->get_float_array(socket); + //for (size_t i = 0; i < value.size(); i++) { + // ss << value[i]; + // if (i != value.size() - 1) { + // ss << " "; + // } + //} + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::INT: { - attr = node->get_int(socket); + } + case SocketType::INT: { + std::stringstream ss; + ss << node->get_int(socket); + attr = ss.str(); break; - } - case SocketType::UINT: { - attr = node->get_uint(socket); + } + case SocketType::UINT: { + std::stringstream ss; + ss << node->get_uint(socket); + attr = ss.str(); break; - } - case SocketType::UINT64: { - attr = node->get_uint64(socket); + } + case SocketType::UINT64: { + std::stringstream ss; + ss << node->get_uint64(socket); + attr = ss.str(); break; - } - case SocketType::INT_ARRAY: { + } + case SocketType::INT_ARRAY: { std::stringstream ss; - const array<int> &value = node->get_int_array(socket); - for (size_t i = 0; i < value.size(); i++) { - ss << value[i]; - if (i != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<int>& value = node->get_int_array(socket); + //for (size_t i = 0; i < value.size(); i++) { + // ss << value[i]; + // if (i != value.size() - 1) { + // ss << " "; + // } + //} + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::COLOR: - case SocketType::VECTOR: - case SocketType::POINT: - case SocketType::NORMAL: { + } + case SocketType::COLOR: + case SocketType::VECTOR: + case SocketType::POINT: + case SocketType::NORMAL: { float3 value = node->get_float3(socket); attr = - string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str(); + string_printf("%g %g %g %g", (double)value.x, (double)value.y, (double)value.z, (double)value.w); break; - } - case SocketType::COLOR_ARRAY: - case SocketType::VECTOR_ARRAY: - case SocketType::POINT_ARRAY: - case SocketType::NORMAL_ARRAY: { + } + case SocketType::COLOR_ARRAY: + case SocketType::VECTOR_ARRAY: + case SocketType::POINT_ARRAY: + case SocketType::NORMAL_ARRAY: { std::stringstream ss; - const array<float3> &value = node->get_float3_array(socket); - for (size_t i = 0; i < value.size(); i++) { - ss << string_printf( - "%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z); - if (i != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<float3>& value = node->get_float3_array(socket); + //for (size_t i = 0; i < value.size(); i++) { + // ss << string_printf( + // "%g %g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z, (double)value[i].w); + // if (i != value.size() - 1) { + // ss << " "; + // } + //} + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::POINT2: { + } + case SocketType::POINT2: { float2 value = node->get_float2(socket); - attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str(); + attr = string_printf("%g %g", (double)value.x, (double)value.y); break; - } - case SocketType::POINT2_ARRAY: { + } + case SocketType::POINT2_ARRAY: { std::stringstream ss; - const array<float2> &value = node->get_float2_array(socket); - for (size_t i = 0; i < value.size(); i++) { - ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y); - if (i != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<float2>& value = node->get_float2_array(socket); + //for (size_t i = 0; i < value.size(); i++) { + // ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y); + // if (i != value.size() - 1) { + // ss << " "; + // } + //} + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::STRING: - case SocketType::ENUM: { - attr = node->get_string(socket).c_str(); + } + case SocketType::ENUM: + case SocketType::STRING: { + std::stringstream ss; + ss << node->get_string(socket); + attr = ss.str(); break; - } - case SocketType::STRING_ARRAY: { + } + //case SocketType::ENUM: { + // std::stringstream ss; + // ss << node->get_int(socket); + // attr = ss.str(); + // break; + //} + case SocketType::STRING_ARRAY: { std::stringstream ss; - const array<ustring> &value = node->get_string_array(socket); + const array<ustring>& value = node->get_string_array(socket); for (size_t i = 0; i < value.size(); i++) { - ss << value[i]; - if (i != value.size() - 1) { - ss << " "; - } + ss << value[i]; + if (i != value.size() - 1) { + ss << " "; + } } - attr = ss.str().c_str(); + attr = ss.str(); break; - } - case SocketType::TRANSFORM: { + } + case SocketType::TRANSFORM: { Transform tfm = node->get_transform(socket); - std::stringstream ss; - for (int i = 0; i < 3; i++) { - ss << string_printf("%g %g %g %g ", - (double)tfm[i][0], - (double)tfm[i][1], - (double)tfm[i][2], - (double)tfm[i][3]); + + Object* ob = dynamic_cast<Object*>(node); + if (!ob || ob->get_geometry() && (ob->get_geometry()->geometry_type == Geometry::Type::VOLUME || !ob->get_geometry()->transform_applied)) { + std::stringstream ss; + for (int i = 0; i < 3; i++) { + if (i == 2) + ss << string_printf("%g %g %g %g", + (double)tfm[i][0], + (double)tfm[i][1], + (double)tfm[i][2], + (double)tfm[i][3]); + else + ss << string_printf("%g %g %g %g ", + (double)tfm[i][0], + (double)tfm[i][1], + (double)tfm[i][2], + (double)tfm[i][3]); + } + //ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); + attr = ss.str(); } - ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); - attr = ss.str().c_str(); break; - } - case SocketType::TRANSFORM_ARRAY: { + } + case SocketType::TRANSFORM_ARRAY: { std::stringstream ss; - const array<Transform> &value = node->get_transform_array(socket); - for (size_t j = 0; j < value.size(); j++) { - const Transform &tfm = value[j]; - - for (int i = 0; i < 3; i++) { - ss << string_printf("%g %g %g %g ", - (double)tfm[i][0], - (double)tfm[i][1], - (double)tfm[i][2], - (double)tfm[i][3]); - } - ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); - if (j != value.size() - 1) { - ss << " "; - } - } - attr = ss.str().c_str(); + const array<Transform>& value = node->get_transform_array(socket); + //for (size_t j = 0; j < value.size(); j++) { + // const Transform &tfm = value[j]; + + // for (int i = 0; i < 3; i++) { + // if (i == 2) + // ss << string_printf("%g %g %g %g", + // (double)tfm[i][0], + // (double)tfm[i][1], + // (double)tfm[i][2], + // (double)tfm[i][3]); + // else + // ss << string_printf("%g %g %g %g ", + // (double)tfm[i][0], + // (double)tfm[i][1], + // (double)tfm[i][2], + // (double)tfm[i][3]); + // } + // //ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0); + // if (j != value.size() - 1) { + // ss << " "; + // } + //} + ss << write_array_to_binary_file(writer, value); + attr = ss.str(); break; - } - case SocketType::NODE: { - Node *value = node->get_node(socket); + } + case SocketType::NODE: { + Node* value = node->get_node(socket); if (value) { - attr = value->name.c_str(); + if (xml_pointer_to_name_check(value)) + attr = xml_pointer_to_name(value); + else + attr = value->name.string(); } break; - } - case SocketType::NODE_ARRAY: { + } + case SocketType::NODE_ARRAY: { std::stringstream ss; - const array<Node *> &value = node->get_node_array(socket); + const array<Node*>& value = node->get_node_array(socket); for (size_t i = 0; i < value.size(); i++) { - if (value[i]) { - ss << value[i]->name.c_str(); - } - if (i != value.size() - 1) { - ss << " "; - } + if (value[i]) { + if (xml_pointer_to_name_check(value[i])) + ss << xml_pointer_to_name(value[i]); + else + ss << value[i]->name; + } + if (i != value.size() - 1) { + ss << " "; + } } - attr = ss.str().c_str(); + attr = ss.str(); break; - } - case SocketType::CLOSURE: - case SocketType::UNDEFINED: - case SocketType::NUM_TYPES: + } + case SocketType::CLOSURE: + case SocketType::UNDEFINED: + case SocketType::NUM_TYPES: break; } + + if (attr.empty()) + return; + + string socket_file = xml_node_name + "_" + socket.name.string(); + + xml_node xml_node_socket = xml_node_main.append_child("socket"); + + xml_attribute attr_name = xml_node_socket.append_attribute("name"); + attr_name = socket.name.c_str(); + + xml_attribute attr_ui_name = xml_node_socket.append_attribute("ui_name"); + attr_ui_name = socket.ui_name.c_str(); + + xml_attribute attr_value = xml_node_socket.append_attribute("value"); + attr_value = attr.c_str(); + + xml_attribute attr_type_name = xml_node_socket.append_attribute("type_name"); + attr_type_name = SocketType::type_name(socket.type).c_str(); +} + +xml_node xml_write_node(XMLWriter& writer, Node* node, xml_node xml_root) +{ + xml_node xml_node_main = xml_root.append_child(node->type->name.c_str()); + + string xml_node_name = node->name.string(); + if (xml_pointer_to_name_check(node)) + xml_node_name = xml_pointer_to_name(node); + + xml_node_main.append_attribute("name") = xml_node_name.c_str(); + xml_node_main.append_attribute("ui_name") = node->name.string().c_str(); + + foreach (const SocketType &socket, node->type->inputs) { + xml_write_node_socket(writer, node, xml_root, socket, xml_node_main, xml_node_name); } - return xml_node; + //foreach(const SocketType& socket, node->type->outputs) { + // xml_write_node_socket(writer, node, xml_root, socket, xml_node_main, xml_node_name); + //} + + return xml_node_main; } CCL_NAMESPACE_END diff --git a/intern/cycles/graph/node_xml.h b/intern/cycles/graph/node_xml.h index 56dd200dfcaa419ed37f39ec9d066cdd55b1dbfe..761dc0a60154cb11472ecc1e1148568f86c6e703 100644 --- a/intern/cycles/graph/node_xml.h +++ b/intern/cycles/graph/node_xml.h @@ -12,11 +12,19 @@ CCL_NAMESPACE_BEGIN -struct XMLReader { - map<ustring, Node *> node_map; +//struct XMLReader { +// map<ustring, Node *> node_map; +//}; + +struct XMLWriter { + //std::string base; /* Base path to current file. */ + size_t offset = 0; + std::ofstream file; }; -void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node); -xml_node xml_write_node(Node *node, xml_node xml_root); +//void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node); +xml_node xml_write_node(XMLWriter &writer, Node *node, xml_node xml_root); +string xml_pointer_to_name(void* ptr); +bool xml_pointer_to_name_check(Node* node); CCL_NAMESPACE_END diff --git a/intern/cycles/scene/CMakeLists.txt b/intern/cycles/scene/CMakeLists.txt index 874b38525ed2b20115cd43e22150e010725a70db..a17af79891f14d7399525d28f0c1e42722064329 100644 --- a/intern/cycles/scene/CMakeLists.txt +++ b/intern/cycles/scene/CMakeLists.txt @@ -41,6 +41,8 @@ set(SRC pass.cpp curves.cpp scene.cpp + scene_read_xml.cpp + scene_write_xml.cpp shader.cpp shader_graph.cpp shader_nodes.cpp @@ -80,6 +82,8 @@ set(SRC_HEADERS pointcloud.h curves.h scene.h + scene_read_xml.h + scene_write_xml.h shader.h shader_graph.h shader_nodes.h diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp index 1f4d129950d142a9867e830df291a48a8890250d..5b53901c6371f198a571e572a23d887ee0537f1e 100644 --- a/intern/cycles/scene/image.cpp +++ b/intern/cycles/scene/image.cpp @@ -809,7 +809,10 @@ void ImageManager::device_load_image(Device *device, Scene *scene, size_t slot, } /* Cleanup memory in image loader. */ - img->loader->cleanup(); + const char* filepath_xml = getenv("CYCLES_XML_PATH"); + if (filepath_xml == nullptr) { + img->loader->cleanup(); + } img->need_load = false; } diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index 341e6ec37a74ba4efbb6eae357f93e4d51819d72..8e931f140971ccb2d9631a322e0d7d09a5aa5d07 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -28,6 +28,8 @@ #include "scene/volume.h" #include "session/session.h" +#include "scene/scene_write_xml.h" + #include "util/foreach.h" #include "util/guarded_allocator.h" #include "util/log.h" @@ -357,6 +359,12 @@ void Scene::device_update(Device *device_, Progress &progress) << " Peak: " << string_human_readable_number(mem_peak) << " (" << string_human_readable_size(mem_peak) << ")"; } + + //////////////////////////////EXPORT///////////////////////////////////// + //static void xml_read_scene(XMLReadState & state, xml_node scene_node) + const char* filepath_xml = getenv("CYCLES_XML_PATH"); + scene_write_xml_file(this, filepath_xml); + ///////////////////////////////////////////////////////////////////////// } Scene::MotionType Scene::need_motion() const diff --git a/intern/cycles/scene/scene_read_xml.cpp b/intern/cycles/scene/scene_read_xml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf6ca83a11dd5ad4a1eedc915f5f21b0b2ce6692 --- /dev/null +++ b/intern/cycles/scene/scene_read_xml.cpp @@ -0,0 +1,855 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#include "scene_read_xml.h" + +#include <stdio.h> + +#include <algorithm> +#include <iterator> +#include <sstream> + +#include "graph/node_xml.h" + +#include "scene/alembic.h" +#include "scene/background.h" +#include "scene/camera.h" +#include "scene/film.h" +#include "scene/integrator.h" +#include "scene/light.h" +#include "scene/mesh.h" +#include "scene/object.h" +#include "scene/osl.h" +#include "scene/scene.h" +#include "scene/shader.h" +#include "scene/shader_graph.h" +#include "scene/shader_nodes.h" + +#include "subd/patch.h" +#include "subd/split.h" + +#include "util/foreach.h" +#include "util/path.h" +#include "util/projection.h" +#include "util/transform.h" +#include "util/xml.h" + + /* macros for importing */ +#define RAD2DEGF(_rad) ((_rad) * (float)(180.0 / M_PI)) +#define DEG2RADF(_deg) ((_deg) * (float)(M_PI / 180.0)) + +CCL_NAMESPACE_BEGIN + +/* Attribute Reading */ + +//bool scene_read_xml_int(int* value, xml_node node, const char* name) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// *value = atoi(attr.value()); +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_int_array(vector<int>& value, xml_node node, const char* name) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// foreach(const string & token, tokens) +// value.push_back(atoi(token.c_str())); +// +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_float(float* value, xml_node node, const char* name) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// *value = (float)atof(attr.value()); +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_float_array(vector<float>& value, xml_node node, const char* name) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// vector<string> tokens; +// string_split(tokens, attr.value()); +// +// foreach(const string & token, tokens) +// value.push_back((float)atof(token.c_str())); +// +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_float3(float3* value, xml_node node, const char* name) +//{ +// vector<float> array; +// +// if (scene_read_xml_float_array(array, node, name) && array.size() == 3) { +// *value = make_float3(array[0], array[1], array[2]); +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_float3_array(vector<float3>& value, xml_node node, const char* name) +//{ +// vector<float> array; +// +// if (scene_read_xml_float_array(array, node, name)) { +// for (size_t i = 0; i < array.size(); i += 3) { +// value.push_back(make_float3(array[i + 0], array[i + 1], array[i + 2])); +// } +// +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_float4(float4* value, xml_node node, const char* name) +//{ +// vector<float> array; +// +// if (scene_read_xml_float_array(array, node, name) && array.size() == 4) { +// *value = make_float4(array[0], array[1], array[2], array[3]); +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_string(string* str, xml_node node, const char* name) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// *str = attr.value(); +// return true; +// } +// +// return false; +//} +// +//bool scene_read_xml_equal_string(xml_node node, const char* name, const char* value) +//{ +// xml_attribute attr = node.attribute(name); +// +// if (attr) { +// return string_iequals(attr.value(), value); +// } +// +// return false; +//} +// +///* Camera */ +// +//void scene_read_xml_camera(XMLReadState& state, xml_node node) +//{ +// Camera* cam = state.scene->camera; +// +// int width = -1, height = -1; +// scene_read_xml_int(&width, node, "width"); +// scene_read_xml_int(&height, node, "height"); +// +// cam->set_full_width(width); +// cam->set_full_height(height); +// +// xml_read_node(state, cam, node); +// +// cam->set_matrix(state.tfm); +// +// cam->need_flags_update = true; +// cam->update(state.scene); +//} +// +///* Alembic */ +// +//#ifdef WITH_ALEMBIC +//void scene_read_xml_alembic(XMLReadState& state, xml_node graph_node) +//{ +// AlembicProcedural* proc = state.scene->create_node<AlembicProcedural>(); +// xml_read_node(state, proc, graph_node); +// +// for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { +// if (string_iequals(node.name(), "object")) { +// string path; +// if (scene_read_xml_string(&path, node, "path")) { +// ustring object_path(path, 0); +// AlembicObject* object = static_cast<AlembicObject*>( +// proc->get_or_create_object(object_path)); +// +// array<Node*> used_shaders = object->get_used_shaders(); +// used_shaders.push_back_slow(state.shader); +// object->set_used_shaders(used_shaders); +// } +// } +// } +//} +//#endif +// +///* Shader */ +// +//void scene_read_xml_shader_graph(XMLReadState& state, Shader* shader, xml_node graph_node) +//{ +// xml_read_node(state, shader, graph_node); +// +// ShaderGraph* graph = new ShaderGraph(); +// +// /* local state, shader nodes can't link to nodes outside the shader graph */ +// XMLReader graph_reader; +// graph_reader.node_map[ustring("output")] = graph->output(); +// +// for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { +// ustring node_name(node.name()); +// +// if (node_name == "connect") { +// /* connect nodes */ +// vector<string> from_tokens, to_tokens; +// +// string_split(from_tokens, node.attribute("from").value()); +// string_split(to_tokens, node.attribute("to").value()); +// +// if (from_tokens.size() == 2 && to_tokens.size() == 2) { +// ustring from_node_name(from_tokens[0]); +// ustring from_socket_name(from_tokens[1]); +// ustring to_node_name(to_tokens[0]); +// ustring to_socket_name(to_tokens[1]); +// +// /* find nodes and sockets */ +// ShaderOutput* output = NULL; +// ShaderInput* input = NULL; +// +// if (graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) { +// ShaderNode* fromnode = (ShaderNode*)graph_reader.node_map[from_node_name]; +// +// foreach(ShaderOutput * out, fromnode->outputs) +// if (string_iequals(out->socket_type.name.string(), from_socket_name.string())) { +// output = out; +// } +// +// if (!output) { +// fprintf(stderr, +// "Unknown output socket name \"%s\" on \"%s\".\n", +// from_node_name.c_str(), +// from_socket_name.c_str()); +// } +// } +// else { +// fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str()); +// } +// +// if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) { +// ShaderNode* tonode = (ShaderNode*)graph_reader.node_map[to_node_name]; +// +// foreach(ShaderInput * in, tonode->inputs) +// if (string_iequals(in->socket_type.name.string(), to_socket_name.string())) { +// input = in; +// } +// +// if (!input) { +// fprintf(stderr, +// "Unknown input socket name \"%s\" on \"%s\".\n", +// to_socket_name.c_str(), +// to_node_name.c_str()); +// } +// } +// else { +// fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str()); +// } +// +// /* connect */ +// if (output && input) { +// graph->connect(output, input); +// } +// } +// else { +// fprintf(stderr, "Invalid from or to value for connect node.\n"); +// } +// +// continue; +// } +// +// ShaderNode* snode = NULL; +// +//#ifdef WITH_OSL +// if (node_name == "osl_shader") { +// ShaderManager* manager = state.scene->shader_manager; +// +// if (manager->use_osl()) { +// std::string filepath; +// +// if (scene_read_xml_string(&filepath, node, "src")) { +// if (path_is_relative(filepath)) { +// filepath = path_join(state.base, filepath); +// } +// +// snode = OSLShaderManager::osl_node(graph, manager, filepath, ""); +// +// if (!snode) { +// fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str()); +// continue; +// } +// } +// else { +// fprintf(stderr, "OSL node missing \"src\" attribute.\n"); +// continue; +// } +// } +// else { +// fprintf(stderr, "OSL node without using --shadingsys osl.\n"); +// continue; +// } +// } +// else +//#endif +// { +// /* exception for name collision */ +// if (node_name == "background") { +// node_name = "background_shader"; +// } +// +// const NodeType* node_type = NodeType::find(node_name); +// +// if (!node_type) { +// fprintf(stderr, "Unknown shader node \"%s\".\n", node.name()); +// continue; +// } +// else if (node_type->type != NodeType::SHADER) { +// fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str()); +// continue; +// } +// else if (node_type->create == NULL) { +// fprintf(stderr, "Can't create abstract node type \"%s\".\n", node_type->name.c_str()); +// continue; +// } +// +// snode = (ShaderNode*)node_type->create(node_type); +// snode->set_owner(graph); +// } +// +// xml_read_node(graph_reader, snode, node); +// +// if (node_name == "image_texture") { +// ImageTextureNode* img = (ImageTextureNode*)snode; +// ustring filename(path_join(state.base, img->get_filename().string())); +// img->set_filename(filename); +// } +// else if (node_name == "environment_texture") { +// EnvironmentTextureNode* env = (EnvironmentTextureNode*)snode; +// ustring filename(path_join(state.base, env->get_filename().string())); +// env->set_filename(filename); +// } +// +// if (snode) { +// /* add to graph */ +// graph->add(snode); +// } +// } +// +// shader->set_graph(graph); +// shader->tag_update(state.scene); +//} +// +//void scene_read_xml_shader(XMLReadState& state, xml_node node) +//{ +// Shader* shader = new Shader(); +// scene_read_xml_shader_graph(state, shader, node); +// state.scene->shaders.push_back(shader); +//} +// +///* Background */ +// +//void scene_read_xml_background(XMLReadState& state, xml_node node) +//{ +// /* Background Settings */ +// xml_read_node(state, state.scene->background, node); +// +// /* Background Shader */ +// Shader* shader = state.scene->default_background; +// scene_read_xml_shader_graph(state, shader, node); +//} +// +///* Mesh */ +// +//Mesh* xml_add_mesh(Scene* scene, const Transform& tfm, Object* object) +//{ +// if (object && object->get_geometry()->is_mesh()) { +// /* Use existing object and mesh */ +// object->set_tfm(tfm); +// Geometry* geometry = object->get_geometry(); +// return static_cast<Mesh*>(geometry); +// } +// else { +// /* Create mesh */ +// Mesh* mesh = new Mesh(); +// scene->geometry.push_back(mesh); +// +// /* Create object. */ +// Object* object = new Object(); +// object->set_geometry(mesh); +// object->set_tfm(tfm); +// scene->objects.push_back(object); +// +// return mesh; +// } +//} +// +//void scene_read_xml_mesh(const XMLReadState& state, xml_node node) +//{ +// /* add mesh */ +// Mesh* mesh = xml_add_mesh(state.scene, state.tfm, state.object); +// array<Node*> used_shaders = mesh->get_used_shaders(); +// used_shaders.push_back_slow(state.shader); +// mesh->set_used_shaders(used_shaders); +// +// /* read state */ +// int shader = 0; +// bool smooth = state.smooth; +// +// /* read vertices and polygons */ +// vector<float3> P; +// vector<float3> VN; /* Vertex normals */ +// vector<float> UV; +// vector<float> T; /* UV tangents */ +// vector<float> TS; /* UV tangent signs */ +// vector<int> verts, nverts; +// +// scene_read_xml_float3_array(P, node, "P"); +// scene_read_xml_int_array(verts, node, "verts"); +// scene_read_xml_int_array(nverts, node, "nverts"); +// +// if (scene_read_xml_equal_string(node, "subdivision", "catmull-clark")) { +// mesh->set_subdivision_type(Mesh::SUBDIVISION_CATMULL_CLARK); +// } +// else if (scene_read_xml_equal_string(node, "subdivision", "linear")) { +// mesh->set_subdivision_type(Mesh::SUBDIVISION_LINEAR); +// } +// +// array<float3> P_array; +// P_array = P; +// +// if (mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE) { +// /* create vertices */ +// +// mesh->set_verts(P_array); +// +// size_t num_triangles = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// num_triangles += nverts[i] - 2; +// } +// mesh->reserve_mesh(mesh->get_verts().size(), num_triangles); +// +// /* create triangles */ +// int index_offset = 0; +// +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = verts[index_offset]; +// int v1 = verts[index_offset + j + 1]; +// int v2 = verts[index_offset + j + 2]; +// +// assert(v0 < (int)P.size()); +// assert(v1 < (int)P.size()); +// assert(v2 < (int)P.size()); +// +// mesh->add_triangle(v0, v1, v2, shader, smooth); +// } +// +// index_offset += nverts[i]; +// } +// +// /* Vertex normals */ +// if (scene_read_xml_float3_array(VN, node, Attribute::standard_name(ATTR_STD_VERTEX_NORMAL))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); +// float3* fdata = attr->data_float3(); +// +// /* Loop over the normals */ +// for (auto n : VN) { +// fdata[0] = n; +// fdata++; +// } +// } +// +// /* UV map */ +// if (scene_read_xml_float_array(UV, node, "UV") || +// scene_read_xml_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) +// { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV); +// float2* fdata = attr->data_float2(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 * 2 + 1 < (int)UV.size()); +// assert(v1 * 2 + 1 < (int)UV.size()); +// assert(v2 * 2 + 1 < (int)UV.size()); +// +// fdata[0] = make_float2(UV[v0 * 2], UV[v0 * 2 + 1]); +// fdata[1] = make_float2(UV[v1 * 2], UV[v1 * 2 + 1]); +// fdata[2] = make_float2(UV[v2 * 2], UV[v2 * 2 + 1]); +// fdata += 3; +// } +// +// index_offset += nverts[i]; +// } +// } +// +// /* Tangents */ +// if (scene_read_xml_float_array(T, node, Attribute::standard_name(ATTR_STD_UV_TANGENT))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV_TANGENT); +// float3* fdata = attr->data_float3(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 * 3 + 2 < (int)T.size()); +// assert(v1 * 3 + 2 < (int)T.size()); +// assert(v2 * 3 + 2 < (int)T.size()); +// +// fdata[0] = make_float3(T[v0 * 3], T[v0 * 3 + 1], T[v0 * 3 + 2]); +// fdata[1] = make_float3(T[v1 * 3], T[v1 * 3 + 1], T[v1 * 3 + 2]); +// fdata[2] = make_float3(T[v2 * 3], T[v2 * 3 + 1], T[v2 * 3 + 2]); +// fdata += 3; +// } +// index_offset += nverts[i]; +// } +// } +// +// /* Tangent signs */ +// if (scene_read_xml_float_array(TS, node, Attribute::standard_name(ATTR_STD_UV_TANGENT_SIGN))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN); +// float* fdata = attr->data_float(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 < (int)TS.size()); +// assert(v1 < (int)TS.size()); +// assert(v2 < (int)TS.size()); +// +// fdata[0] = TS[v0]; +// fdata[1] = TS[v1]; +// fdata[2] = TS[v2]; +// fdata += 3; +// } +// index_offset += nverts[i]; +// } +// } +// } +// else { +// /* create vertices */ +// mesh->set_verts(P_array); +// +// size_t num_ngons = 0; +// size_t num_corners = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// num_ngons += (nverts[i] == 4) ? 0 : 1; +// num_corners += nverts[i]; +// } +// mesh->reserve_subd_faces(nverts.size(), num_ngons, num_corners); +// +// /* create subd_faces */ +// int index_offset = 0; +// +// for (size_t i = 0; i < nverts.size(); i++) { +// mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth); +// index_offset += nverts[i]; +// } +// +// /* UV map */ +// if (scene_read_xml_float_array(UV, node, "UV") || +// scene_read_xml_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) +// { +// Attribute* attr = mesh->subd_attributes.add(ATTR_STD_UV); +// float3* fdata = attr->data_float3(); +// +//#if 0 +// if (subdivide_uvs) { +// attr->flags |= ATTR_SUBDIVIDED; +// } +//#endif +// +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i]; j++) { +// *(fdata++) = make_float3(UV[index_offset++]); +// } +// } +// } +// +// /* setup subd params */ +// float dicing_rate = state.dicing_rate; +// scene_read_xml_float(&dicing_rate, node, "dicing_rate"); +// dicing_rate = std::max(0.1f, dicing_rate); +// +// mesh->set_subd_dicing_rate(dicing_rate); +// mesh->set_subd_objecttoworld(state.tfm); +// } +// +// /* we don't yet support arbitrary attributes, for now add vertex +// * coordinates as generated coordinates if requested */ +// if (mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_GENERATED); +// memcpy( +// attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size()); +// } +//} +// +///* Light */ +// +//void scene_read_xml_light(XMLReadState& state, xml_node node) +//{ +// Light* light = new Light(); +// +// light->set_shader(state.shader); +// xml_read_node(state, light, node); +// +// state.scene->lights.push_back(light); +//} +// +///* Transform */ +// +//void scene_read_xml_transform(xml_node node, Transform& tfm) +//{ +// if (node.attribute("matrix")) { +// vector<float> matrix; +// if (scene_read_xml_float_array(matrix, node, "matrix") && matrix.size() == 16) { +// ProjectionTransform projection = *(ProjectionTransform*)&matrix[0]; +// tfm = tfm * projection_to_transform(projection_transpose(projection)); +// } +// } +// +// if (node.attribute("translate")) { +// float3 translate = zero_float3(); +// scene_read_xml_float3(&translate, node, "translate"); +// tfm = tfm * transform_translate(translate); +// } +// +// if (node.attribute("rotate")) { +// float4 rotate = zero_float4(); +// scene_read_xml_float4(&rotate, node, "rotate"); +// tfm = tfm * transform_rotate(DEG2RADF(rotate.x), make_float3(rotate.y, rotate.z, rotate.w)); +// } +// +// if (node.attribute("scale")) { +// float3 scale = zero_float3(); +// scene_read_xml_float3(&scale, node, "scale"); +// tfm = tfm * transform_scale(scale); +// } +//} +// +///* State */ +// +//void scene_read_xml_state(XMLReadState& state, xml_node node) +//{ +// /* Read shader */ +// string shadername; +// +// if (scene_read_xml_string(&shadername, node, "shader")) { +// bool found = false; +// +// foreach(Shader * shader, state.scene->shaders) { +// if (shader->name == shadername) { +// state.shader = shader; +// found = true; +// break; +// } +// } +// +// if (!found) { +// fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str()); +// } +// } +// +// /* Read object */ +// string objectname; +// +// if (scene_read_xml_string(&objectname, node, "object")) { +// bool found = false; +// +// foreach(Object * object, state.scene->objects) { +// if (object->name == objectname) { +// state.object = object; +// found = true; +// break; +// } +// } +// +// if (!found) { +// fprintf(stderr, "Unknown object \"%s\".\n", objectname.c_str()); +// } +// } +// +// scene_read_xml_float(&state.dicing_rate, node, "dicing_rate"); +// +// /* read smooth/flat */ +// if (scene_read_xml_equal_string(node, "interpolation", "smooth")) { +// state.smooth = true; +// } +// else if (scene_read_xml_equal_string(node, "interpolation", "flat")) { +// state.smooth = false; +// } +//} +// +///* Object */ +// +//void scene_read_xml_object(XMLReadState& state, xml_node node) +//{ +// Scene* scene = state.scene; +// +// /* create mesh */ +// Mesh* mesh = new Mesh(); +// scene->geometry.push_back(mesh); +// +// /* create object */ +// Object* object = new Object(); +// object->set_geometry(mesh); +// object->set_tfm(state.tfm); +// +// xml_read_node(state, object, node); +// +// scene->objects.push_back(object); +//} +// +///* Scene */ +// +//void scene_read_xml_scene(XMLReadState& state, xml_node scene_node) +//{ +// for (xml_node node = scene_node.first_child(); node; node = node.next_sibling()) { +// if (string_iequals(node.name(), "film")) { +// xml_read_node(state, state.scene->film, node); +// } +// else if (string_iequals(node.name(), "integrator")) { +// xml_read_node(state, state.scene->integrator, node); +// } +// else if (string_iequals(node.name(), "camera")) { +// scene_read_xml_camera(state, node); +// } +// else if (string_iequals(node.name(), "shader")) { +// scene_read_xml_shader(state, node); +// } +// else if (string_iequals(node.name(), "background")) { +// scene_read_xml_background(state, node); +// } +// else if (string_iequals(node.name(), "mesh")) { +// scene_read_xml_mesh(state, node); +// } +// else if (string_iequals(node.name(), "light")) { +// scene_read_xml_light(state, node); +// } +// else if (string_iequals(node.name(), "transform")) { +// XMLReadState substate = state; +// +// scene_read_xml_transform(node, substate.tfm); +// scene_read_xml_scene(substate, node); +// } +// else if (string_iequals(node.name(), "state")) { +// XMLReadState substate = state; +// +// scene_read_xml_state(substate, node); +// scene_read_xml_scene(substate, node); +// } +// else if (string_iequals(node.name(), "include")) { +// string src; +// +// if (scene_read_xml_string(&src, node, "src")) { +// scene_read_xml_include(state, src); +// } +// } +// else if (string_iequals(node.name(), "object")) { +// XMLReadState substate = state; +// +// scene_read_xml_object(substate, node); +// scene_read_xml_scene(substate, node); +// } +//#ifdef WITH_ALEMBIC +// else if (string_iequals(node.name(), "alembic")) { +// scene_read_xml_alembic(state, node); +// } +//#endif +// else { +// fprintf(stderr, "Unknown node \"%s\".\n", node.name()); +// } +// } +//} +// +///* Include */ +// +//void scene_read_xml_include(XMLReadState& state, const string& src) +//{ +// /* open XML document */ +// xml_document doc; +// xml_parse_result parse_result; +// +// string path = path_join(state.base, src); +// parse_result = doc.load_file(path.c_str()); +// +// if (parse_result) { +// XMLReadState substate = state; +// substate.base = path_dirname(path); +// +// xml_node cycles = doc.child("cycles"); +// scene_read_xml_scene(substate, cycles); +// } +// else { +// fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description()); +// exit(EXIT_FAILURE); +// } +//} +// +///* File */ +// +//void scene_read_xml_file(Scene* scene, const char* filepath) +//{ +// XMLReadState state; +// +// state.scene = scene; +// state.tfm = transform_identity(); +// state.shader = scene->default_surface; +// state.smooth = false; +// state.dicing_rate = 1.0f; +// state.base = path_dirname(filepath); +// +// scene_read_xml_include(state, path_filename(filepath)); +// +// scene->params.bvh_type = BVH_TYPE_STATIC; +//} + +CCL_NAMESPACE_END diff --git a/intern/cycles/scene/scene_read_xml.h b/intern/cycles/scene/scene_read_xml.h new file mode 100644 index 0000000000000000000000000000000000000000..bcb3d00311e7cf3e72d662a9713ddcf411a7f3cc --- /dev/null +++ b/intern/cycles/scene/scene_read_xml.h @@ -0,0 +1,53 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + +#include "graph/node_xml.h" + +#include "scene/scene.h" + +CCL_NAMESPACE_BEGIN + +/* XML reading state */ + +//struct XMLReadState : public XMLReader { +// Scene* scene; /* Scene pointer. */ +// Transform tfm; /* Current transform state. */ +// bool smooth; /* Smooth normal state. */ +// Shader* shader; /* Current shader. */ +// string base; /* Base path to current file. */ +// float dicing_rate; /* Current dicing rate. */ +// Object* object; /* Current object. */ +// +// XMLReadState() : scene(NULL), smooth(false), shader(NULL), dicing_rate(1.0f), object(NULL) +// { +// tfm = transform_identity(); +// } +//}; +// +//bool scene_read_xml_int(int* value, xml_node node, const char* name); +//bool scene_read_xml_int_array(vector<int>& value, xml_node node, const char* name); +//bool scene_read_xml_float(float* value, xml_node node, const char* name); +//bool scene_read_xml_float_array(vector<float>& value, xml_node node, const char* name); +//bool scene_read_xml_float3(float3* value, xml_node node, const char* name); +//bool scene_read_xml_float3_array(vector<float3>& value, xml_node node, const char* name); +//bool scene_read_xml_float4(float4* value, xml_node node, const char* name); +//bool scene_read_xml_string(string* str, xml_node node, const char* name); +//void scene_read_xml_camera(XMLReadState& state, xml_node node); +//void scene_read_xml_alembic(XMLReadState& state, xml_node graph_node); +//void scene_read_xml_shader_graph(XMLReadState& state, Shader* shader, xml_node graph_node); +//void scene_read_xml_shader(XMLReadState& state, xml_node node); +//void scene_read_xml_background(XMLReadState& state, xml_node node); +//void scene_read_xml_mesh(const XMLReadState& state, xml_node node); +//void scene_read_xml_light(XMLReadState& state, xml_node node); +//void scene_read_xml_transform(xml_node node, Transform& tfm); +//void scene_read_xml_state(XMLReadState& state, xml_node node); +//void scene_read_xml_object(XMLReadState& state, xml_node node); +//void scene_read_xml_include(XMLReadState& state, const string& src); +//void scene_read_xml_scene(XMLReadState& state, xml_node scene_node); +//void scene_read_xml_include(XMLReadState& state, const string& src); +//void scene_read_xml_file(Scene* scene, const char* filepath); + +CCL_NAMESPACE_END diff --git a/intern/cycles/scene/scene_write_xml.cpp b/intern/cycles/scene/scene_write_xml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb036fe8e2e5a8da76e55191f8bba46ed9b839b9 --- /dev/null +++ b/intern/cycles/scene/scene_write_xml.cpp @@ -0,0 +1,1404 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#include "scene_write_xml.h" + +#include <stdio.h> + +#include <algorithm> +#include <iterator> +#include <sstream> + +#include "graph/node_xml.h" + +#include "scene/alembic.h" +#include "scene/background.h" +#include "scene/camera.h" +#include "scene/film.h" +#include "scene/integrator.h" +#include "scene/light.h" +#include "scene/mesh.h" +#include "scene/object.h" +#include "scene/osl.h" +#include "scene/scene.h" +#include "scene/shader.h" +#include "scene/shader_graph.h" +#include "scene/shader_nodes.h" +#include "scene/image_vdb.h" + +#include "subd/patch.h" +#include "subd/split.h" + +#include "util/foreach.h" +#include "util/path.h" +#include "util/projection.h" +#include "util/transform.h" +#include "util/xml.h" +#include "util/string.h" + +#include <OpenImageIO/imageio.h> +#include <OpenImageIO/imagebuf.h> +#include <OpenImageIO/imagebufalgo.h> +#include <OpenImageIO/filesystem.h> + +#include <openvdb/io/Stream.h> + +#define ADD_ATTR(name) \ + xml_attribute attr_##name = node_attribute.append_attribute(#name); \ + attr_##name = attr.##name; + +#define ADD_ATTR_STR(name) \ + xml_attribute attr_##name = node_attribute.append_attribute(#name); \ + attr_##name = attr.##name.c_str(); + +#define ADD_ATTR_DTYPE(type, name) \ + xml_attribute attr_##name = node_attribute.append_attribute(#name); \ + attr_##name = type.##name; + +CCL_NAMESPACE_BEGIN + +/* XML writing state */ + +struct XMLWriteState : public XMLWriter { + Scene* scene; /* Scene pointer. */ + + XMLWriteState() : + scene(NULL) + { + } +}; + +template<typename T> +string write_vector_to_binary_file(XMLWriter& writer, const vector<T>& data) +{ + std::stringstream ss; + ss << writer.offset; + + // Write the size of the vector first + size_t data_size = data.size(); + writer.file.write(reinterpret_cast<const char*>(&data_size), sizeof(size_t)); + writer.offset += sizeof(size_t); + + // Write the actual data to the file + writer.file.write(reinterpret_cast<const char*>(data.data()), data_size * sizeof(T)); + writer.offset += data_size * sizeof(T); + + return ss.str(); +} + +void save_image_to_memory(device_texture* dt, vector<char>& output_buffer) { +#if 0 + TypeDesc image_type; + switch (dt->data_type) { + case ImageDataType::IMAGE_DATA_TYPE_FLOAT4: + case ImageDataType::IMAGE_DATA_TYPE_FLOAT: + image_type = TypeDesc::FLOAT; + break; + case ImageDataType::IMAGE_DATA_TYPE_BYTE4: + case ImageDataType::IMAGE_DATA_TYPE_BYTE: + image_type = TypeDesc::UCHAR; + break; + case ImageDataType::IMAGE_DATA_TYPE_HALF4: + case ImageDataType::IMAGE_DATA_TYPE_HALF: + image_type = TypeDesc::HALF; + break; + case ImageDataType::IMAGE_DATA_TYPE_USHORT4: + case ImageDataType::IMAGE_DATA_TYPE_USHORT: + image_type = TypeDesc::USHORT; + break; + default: + std::cerr << "Wrong image type" << std::endl; + return; + } + + int width = dt->data_width; + int height = dt->data_height; + int channels = dt->data_elements; + ImageSpec spec(width, height, channels, image_type); + + // Use OpenImageIO's ImageBuf for flipping + ImageBuf img_buf(spec, dt->host_pointer); + ImageBuf flipped_buf; + if (!ImageBufAlgo::flip(flipped_buf, img_buf)) { + std::cerr << "Error flipping the image" << std::endl; + return; + } + + // Create an in-memory image writer using IOVecOutput + std::unique_ptr<ImageOutput> image_output = ImageOutput::create("image.exr"); + if (!image_output) { + std::cerr << "Failed to create image output for memory buffer" << std::endl; + return; + } + + std::vector<unsigned char> io_buffer; + Filesystem::IOVecOutput io_vec_output(io_buffer); + //void* ptr = &io_vec_output; + //spec.attribute("oiio:ioproxy", TypeDesc::PTR, &ptr); + image_output->set_ioproxy(&io_vec_output); + image_output->open("image.exr", spec); + + if (!image_output->write_image(image_type, flipped_buf.localpixels())) { //flipped_buf + std::cerr << "Error writing image" << std::endl; + return; + } + image_output->close(); +#endif + +#if 0 + struct TempMetaData { + int width; + int height; + int channels; + TypeDesc image_type; + }; + TempMetaData temp_meta_data; + temp_meta_data.width = width; + temp_meta_data.height = height; + temp_meta_data.channels = channels; + temp_meta_data.image_type = image_type; + + // Get the buffer as a vector<char> + output_buffer.resize(sizeof(TempMetaData)); + memcpy(output_buffer.data(), &temp_meta_data, sizeof(TempMetaData)); + + output_buffer.insert(output_buffer.end(), io_buffer.begin(), io_buffer.end()); + //output_buffer.assign(io_buffer.begin(), io_buffer.end()); +#endif + + output_buffer.resize(dt->memory_size()); + memcpy(output_buffer.data(), dt->host_pointer, dt->memory_size()); +} + +/* Attribute Reading */ + +void scene_write_xml_int(int value, xml_node node, const char* name) +{ + xml_attribute attr = node.append_attribute(name); + + attr.set_value(value); +} + +void scene_write_xml_int_array(vector<int>& value, xml_node node, const char* name) +{ + xml_attribute attr = node.append_attribute(name); + + std::ostringstream oss; + + for (size_t i = 0; i < value.size(); ++i) { + if (i != 0 && i != value.size() - 1) { + oss << ";"; // Add separator before each number except the first and the last + } + oss << value[i]; + } + + attr.set_value(oss.str().c_str()); +} + +void scene_write_xml_float(float value, xml_node node, const char* name) +{ + xml_attribute attr = node.append_attribute(name); + + attr.set_value(value); +} + +void scene_write_xml_float_array(vector<float>& value, xml_node node, const char* name) +{ + xml_attribute attr = node.append_attribute(name); + + std::ostringstream oss; + + for (size_t i = 0; i < value.size(); ++i) { + if (i != 0 && i != value.size() - 1) { + oss << ";"; // Add separator before each number except the first and the last + } + oss << value[i]; + } + + attr.set_value(oss.str().c_str()); +} + +void scene_write_xml_float3(float3 value, xml_node node, const char* name) +{ + vector<float> array; + array.push_back(value[0]); + array.push_back(value[1]); + array.push_back(value[2]); + + scene_write_xml_float_array(array, node, name); +} + +void scene_write_xml_float3_array(vector<float3>& value, xml_node node, const char* name) +{ + vector<float> array; + + foreach(float3 v, value) { + array.push_back(v[0]); + array.push_back(v[1]); + array.push_back(v[2]); + } + + scene_write_xml_float_array(array, node, name); +} + +void scene_write_xml_float4(float4 value, xml_node node, const char* name) +{ + vector<float> array; + array.push_back(value[0]); + array.push_back(value[1]); + array.push_back(value[2]); + array.push_back(value[3]); + + scene_write_xml_float_array(array, node, name); +} + +void scene_write_xml_string(string str, xml_node node, const char* name) +{ + xml_attribute attr = node.append_attribute(name); + attr.set_value(str.c_str()); +} + +//bool scene_write_xml_equal_string(xml_node node, const char* name, const char* value) +//{ +// xml_attribute attr = node.append_attribute(name); +// +// if (attr) { +// return string_iequals(attr.value(), value); +// } +// +// return false; +//} + +/* Camera */ + +//void scene_write_xml_camera(Scene* scene, xml_node node) +//{ +// Camera* cam = scene->camera; +// +// int width = cam->get_full_width(), height = cam->get_full_height(); +// scene_write_xml_int(width, node, "width"); +// scene_write_xml_int(height, node, "height"); +// +// //cam->set_full_width(width); +// //cam->set_full_height(height); +// +// xml_write_node(cam, node); +// +// //cam->set_matrix(state.tfm); +// +// //cam->need_flags_update = true; +// //cam->update(state.scene); +//} + +/* Alembic */ + +//#ifdef WITH_ALEMBIC +//void scene_write_xml_alembic(XMLReadState& state, xml_node graph_node) +//{ +// AlembicProcedural* proc = state.scene->create_node<AlembicProcedural>(); +// xml_write_node(state, proc, graph_node); +// +// for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { +// if (string_iequals(node.name(), "object")) { +// string path; +// if (scene_write_xml_string(&path, node, "path")) { +// ustring object_path(path, 0); +// AlembicObject* object = static_cast<AlembicObject*>( +// proc->get_or_create_object(object_path)); +// +// array<Node*> used_shaders = object->get_used_shaders(); +// used_shaders.push_back_slow(state.shader); +// object->set_used_shaders(used_shaders); +// } +// } +// } +//} +//#endif + +/* Shader */ + +void scene_write_xml_shader_graph(XMLWriteState& state, Shader* shader, xml_node xml_root) +{ + //xml_node graph_node = xml_root;// .append_child(shader->type->name.c_str()); + //xml_write_node(shader, graph_node); + + foreach(ShaderNode * node, shader->graph->nodes) { + if (node->name == "output") + continue; // skip + + //xml_node xml_node = xml_root.append_child(node->type->name.c_str()); + xml_node xnode = xml_write_node(state, node, xml_root); + if (node->type->name == "image_texture" || node->type->name == "environment_texture") { + + bool socket_found = false; + + xml_node xml_node_socket_found; + xml_attribute attr_name_found; + xml_attribute attr_name_ui_found; + xml_attribute attr_value_found; + + for (xml_node xml_node_socket : xnode.children("socket")) { + + xml_attribute attr_name = xml_node_socket.attribute("name"); + xml_attribute attr_name_ui = xml_node_socket.attribute("ui_name"); + xml_attribute attr_value = xml_node_socket.attribute("value"); + + //ustring xml_socket_name(attr_name.value()); + + if (attr_name && ustring(attr_name.value()) == "filename" || + attr_name_ui && ustring(attr_name_ui.value()) == "Filename") { + //std::string str_filename(attr.value()); + //if (!str_filename.empty()) { + + xml_node_socket_found = xml_node_socket; + attr_name_found = attr_name; + attr_name_ui_found = attr_name_ui; + attr_value_found = attr_value; + + socket_found = true; + break; + //} + } + } + + //if (socket_found) + // continue; + + //xml_attribute attr_filename = xnode.attribute("filename"); + //if (attr_filename) { + // std::string str_filename(attr_filename.value()); + // if (!str_filename.empty()) + // continue; + //} + //else { + // attr_filename = xnode.append_attribute("filename"); + //} + + //xml_node xml_node_socket_found; + //xml_attribute attr_name_found; + //xml_attribute attr_name_ui_found; + //xml_attribute attr_value_found; + + if (!socket_found) { + xml_node_socket_found = xnode.append_child("socket"); + attr_name_found = xml_node_socket_found.append_attribute("name"); + attr_name_found = "filename"; + + attr_name_ui_found = xml_node_socket_found.append_attribute("ui_name"); + attr_name_ui_found = "Filename"; + + attr_value_found = xml_node_socket_found.append_attribute("value"); + } + + ImageSlotTextureNode* img = (ImageSlotTextureNode*)node; + //ImageMetaData metadata = img->handle.metadata(); + + device_texture* dt = img->handle.image_memory(0); + if (dt && dt->host_pointer) { +#if 0 + std::stringstream ss; + + ss << xml_pointer_to_name(dt->host_pointer) << ".exr"; + std::string str = ss.str(); + std::replace(str.begin(), str.end(), ' ', '_'); + string filename(path_join(state.base, str)); + + unique_ptr<ImageOutput> image_output(ImageOutput::create(filename)); + if (!image_output) { + fprintf(stderr, "Failed to create image output for %s\n", filename.c_str()); + return; + } + + TypeDesc image_type; + switch (metadata.type) { + case ImageDataType::IMAGE_DATA_TYPE_FLOAT4: + case ImageDataType::IMAGE_DATA_TYPE_FLOAT: + image_type = TypeDesc::FLOAT; + break; + case ImageDataType::IMAGE_DATA_TYPE_BYTE4: + case ImageDataType::IMAGE_DATA_TYPE_BYTE: + image_type = TypeDesc::UCHAR; + break; + case ImageDataType::IMAGE_DATA_TYPE_HALF4: + case ImageDataType::IMAGE_DATA_TYPE_HALF: + image_type = TypeDesc::HALF; + break; + case ImageDataType::IMAGE_DATA_TYPE_USHORT4: + case ImageDataType::IMAGE_DATA_TYPE_USHORT: + image_type = TypeDesc::USHORT; + break; + //case ImageDataType::IMAGE_DATA_TYPE_NANOVDB_FLOAT: + //case ImageDataType::IMAGE_DATA_TYPE_NANOVDB_FLOAT3: + //case ImageDataType::IMAGE_DATA_TYPE_NANOVDB_FPN: + //case ImageDataType::IMAGE_DATA_TYPE_NANOVDB_FP16: + default: + fprintf(stderr, "Wrong image type"); + return; + } + + // Setup image specification + int width = metadata.width; + int height = metadata.height; + ImageSpec spec(width, height, metadata.channels, image_type); + + // Use OpenImageIO's ImageBuf for flipping + ImageBuf img_buf(spec, dt->host_pointer); + ImageBuf flipped_buf; + + if (!ImageBufAlgo::flip(flipped_buf, img_buf)) { + fprintf(stderr, "Error flipping the image"); + return; + } + + if (!image_output->open(filename, spec)) { + fprintf(stderr, "Failed to open image file for %s\n", filename.c_str()); + return; + } + + if (!image_output->write_image(image_type, flipped_buf.localpixels())) { + fprintf(stderr, "Error writing image"); + return; + } + + // Close the file + if (!image_output->close()) { + fprintf(stderr, "Error closing file"); + return; + } + attr_filename = filename.c_str(); +#endif + vector<char> output_buffer; + save_image_to_memory(dt, output_buffer); + std::string soffset = write_vector_to_binary_file(state, output_buffer); + attr_value_found = soffset.c_str(); + + // MetaData + xml_node node_attribute = xnode; + ImageMetaData attr = img->handle.metadata(); + + bool is_rgba = (attr.type == IMAGE_DATA_TYPE_FLOAT4 || + attr.type == IMAGE_DATA_TYPE_HALF4 || + attr.type == IMAGE_DATA_TYPE_BYTE4 || + attr.type == IMAGE_DATA_TYPE_USHORT4); + + if (is_rgba) + attr.channels = 4; //ImageManager::file_load_image + + //int channels; + ADD_ATTR(channels); + + //size_t width, height, depth; + ADD_ATTR(width); + ADD_ATTR(height); + ADD_ATTR(depth); + //size_t byte_size; + //ADD_ATTR(byte_size); + //ImageDataType type; + //int itype = attr.type; + ADD_ATTR(type); + + ///* Optional color space, defaults to raw. */ + //ustring colorspace; + ADD_ATTR_STR(colorspace); + //string colorspace_file_hint; + ADD_ATTR_STR(colorspace_file_hint); + //const char* colorspace_file_format; + ADD_ATTR(colorspace_file_format); + + ///* Optional transform for 3D images. */ + //bool use_transform_3d; + //Transform transform_3d; + + ///* Automatically set. */ + //bool compress_as_srgb; + } + } + } + + foreach(ShaderNode * node, shader->graph->nodes) { + foreach(ShaderOutput * output, node->outputs) { + foreach(ShaderInput * input, output->links) { + xml_node connect_node = xml_root.append_child("connect"); + + xml_attribute attr_from_node = connect_node.append_attribute("from_node"); + attr_from_node = xml_pointer_to_name(output->parent).c_str(); + + xml_attribute attr_from_socket = connect_node.append_attribute("from_socket"); + attr_from_socket = output->socket_type.name.c_str(); + + xml_attribute attr_from_socket_ui = connect_node.append_attribute("from_socket_ui"); + attr_from_socket_ui = output->socket_type.ui_name.c_str(); + + xml_attribute attr_to_node = connect_node.append_attribute("to_node"); + string to_name = xml_pointer_to_name(input->parent); + if (dynamic_cast<OutputNode*>(input->parent)) + to_name = input->parent->name.string(); // output + attr_to_node = to_name.c_str(); + + xml_attribute attr_to_socket = connect_node.append_attribute("to_socket"); + attr_to_socket = input->socket_type.name.c_str(); + + xml_attribute attr_to_socket_ui = connect_node.append_attribute("to_socket_ui"); + attr_to_socket_ui = input->socket_type.ui_name.c_str(); + } + } + } + // + // + // xml_write_node(state, shader, graph_node); + // + // ShaderGraph* graph = new ShaderGraph(); + // + // /* local state, shader nodes can't link to nodes outside the shader graph */ + // XMLReader graph_reader; + // graph_reader.node_map[ustring("output")] = graph->output(); + // + // for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) { + // ustring node_name(node.name()); + // + // if (node_name == "connect") { + // /* connect nodes */ + // vector<string> from_tokens, to_tokens; + // + // string_split(from_tokens, node.append_attribute("from").value()); + // string_split(to_tokens, node.append_attribute("to").value()); + // + // if (from_tokens.size() == 2 && to_tokens.size() == 2) { + // ustring from_node_name(from_tokens[0]); + // ustring from_socket_name(from_tokens[1]); + // ustring to_node_name(to_tokens[0]); + // ustring to_socket_name(to_tokens[1]); + // + // /* find nodes and sockets */ + // ShaderOutput* output = NULL; + // ShaderInput* input = NULL; + // + // if (graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) { + // ShaderNode* fromnode = (ShaderNode*)graph_reader.node_map[from_node_name]; + // + // foreach(ShaderOutput * out, fromnode->outputs) + // if (string_iequals(out->socket_type.name.string(), from_socket_name.string())) { + // output = out; + // } + // + // if (!output) { + // fprintf(stderr, + // "Unknown output socket name \"%s\" on \"%s\".\n", + // from_node_name.c_str(), + // from_socket_name.c_str()); + // } + // } + // else { + // fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str()); + // } + // + // if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) { + // ShaderNode* tonode = (ShaderNode*)graph_reader.node_map[to_node_name]; + // + // foreach(ShaderInput * in, tonode->inputs) + // if (string_iequals(in->socket_type.name.string(), to_socket_name.string())) { + // input = in; + // } + // + // if (!input) { + // fprintf(stderr, + // "Unknown input socket name \"%s\" on \"%s\".\n", + // to_socket_name.c_str(), + // to_node_name.c_str()); + // } + // } + // else { + // fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str()); + // } + // + // /* connect */ + // if (output && input) { + // graph->connect(output, input); + // } + // } + // else { + // fprintf(stderr, "Invalid from or to value for connect node.\n"); + // } + // + // continue; + // } + // + // ShaderNode* snode = NULL; + // + //#ifdef WITH_OSL + // if (node_name == "osl_shader") { + // ShaderManager* manager = state.scene->shader_manager; + // + // if (manager->use_osl()) { + // std::string filepath; + // + // if (scene_write_xml_string(&filepath, node, "src")) { + // if (path_is_relative(filepath)) { + // filepath = path_join(state.base, filepath); + // } + // + // snode = OSLShaderManager::osl_node(graph, manager, filepath, ""); + // + // if (!snode) { + // fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str()); + // continue; + // } + // } + // else { + // fprintf(stderr, "OSL node missing \"src\" attribute.\n"); + // continue; + // } + // } + // else { + // fprintf(stderr, "OSL node without using --shadingsys osl.\n"); + // continue; + // } + // } + // else + //#endif + // { + // /* exception for name collision */ + // if (node_name == "background") { + // node_name = "background_shader"; + // } + // + // const NodeType* node_type = NodeType::find(node_name); + // + // if (!node_type) { + // fprintf(stderr, "Unknown shader node \"%s\".\n", node.name()); + // continue; + // } + // else if (node_type->type != NodeType::SHADER) { + // fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str()); + // continue; + // } + // else if (node_type->create == NULL) { + // fprintf(stderr, "Can't create abstract node type \"%s\".\n", node_type->name.c_str()); + // continue; + // } + // + // snode = (ShaderNode*)node_type->create(node_type); + // snode->set_owner(graph); + // } + // + // xml_write_node(graph_reader, snode, node); + // + // if (node_name == "image_texture") { + // ImageTextureNode* img = (ImageTextureNode*)snode; + // ustring filename(path_join(state.base, img->get_filename().string())); + // img->set_filename(filename); + // } + // else if (node_name == "environment_texture") { + // EnvironmentTextureNode* env = (EnvironmentTextureNode*)snode; + // ustring filename(path_join(state.base, env->get_filename().string())); + // env->set_filename(filename); + // } + // + // if (snode) { + // /* add to graph */ + // graph->add(snode); + // } + // } + // + // shader->set_graph(graph); + // shader->tag_update(state.scene); +} + +void scene_write_xml_shader(XMLWriteState& state, xml_node node) +{ + //Shader* shader = new Shader(); + foreach(Shader * shader, state.scene->shaders) { + + //if (shader->name == "default_background" || + // shader->name == "default_empty" || + // shader->name == "default_light" || + // shader->name == "default_surface" || + // shader->name == "default_volume") + // continue; + + //xml_node xml_shader = node.append_child(shader->type->name.c_str()); + xml_node xml_shader = xml_write_node(state, shader, node); + + //if (shader->name == "default_background" || + // shader->name == "default_empty" || + // shader->name == "default_light" || + // shader->name == "default_surface" || + // shader->name == "default_volume") { + + // xml_attribute name_attr = xml_shader.attribute("name"); + // name_attr = shader->name.c_str(); + //} + + scene_write_xml_shader_graph(state, shader, xml_shader); + } + //state.scene->shaders.push_back(shader); +} + +/* Background */ + +//void scene_write_xml_background(Scene* scene, xml_node node) +//{ +// /* Background Settings */ +// xml_write_node(scene->background, node); +// +// /* Background Shader */ +// Shader* shader = scene->default_background; +// xml_node xml_shader = node.append_child(shader->type->name.c_str()); +// xml_write_node(shader, xml_shader); +// +// scene_write_xml_shader_graph(shader, node); +//} + +/* Mesh */ + +//Mesh* xml_add_mesh(Scene* scene, const Transform& tfm, Object* object) +//{ +// if (object && object->get_geometry()->is_mesh()) { +// /* Use existing object and mesh */ +// object->set_tfm(tfm); +// Geometry* geometry = object->get_geometry(); +// return static_cast<Mesh*>(geometry); +// } +// else { +// /* Create mesh */ +// Mesh* mesh = new Mesh(); +// scene->geometry.push_back(mesh); +// +// /* Create object. */ +// Object* object = new Object(); +// object->set_geometry(mesh); +// object->set_tfm(tfm); +// scene->objects.push_back(object); +// +// return mesh; +// } +//} +// + +void scene_write_xml_geom(XMLWriteState& state, xml_node node) +{ + foreach(Geometry * geom, state.scene->geometry) { + //xml_node xml_node = node.append_child(mesh->type->name.c_str()); + xml_node xml_node_geom = xml_write_node(state, geom, node); + + //Type geometry_type; + xml_attribute attr_gt = xml_node_geom.append_attribute("geometry_type"); + attr_gt = geom->geometry_type; + + if (geom->attributes.attributes.size() > 0) { + //AttributeSet attributes; + //xml_node node_attributes = xml_node_geom.append_child("attributes"); + foreach(Attribute & attr, geom->attributes.attributes) { + xml_node node_attribute = xml_node_geom.append_child("attribute"); + + //ustring name; + //ADD_ATTR_STR(name); + xml_attribute attr_name = node_attribute.append_attribute("name"); + attr_name = attr.name.string().c_str();//(xml_pointer_to_name(&attr) + "_" + attr.name.string()).c_str(); + + //AttributeStandard std; + ADD_ATTR(std); + + //TypeDesc type; + //ADD_ATTR(type); + ADD_ATTR_DTYPE(attr.type, basetype); ///< C data type at the heart of our type + ADD_ATTR_DTYPE(attr.type, aggregate); ///< What kind of AGGREGATE is it? + ADD_ATTR_DTYPE(attr.type, vecsemantics); ///< Hint: What does the aggregate represent? + ADD_ATTR_DTYPE(attr.type, reserved); ///< Reserved for future expansion + ADD_ATTR_DTYPE(attr.type, arraylen); ///< Array length, 0 = not array, -1 = unsized + + //AttributeElement element; + ADD_ATTR(element); + + //uint flags; + ADD_ATTR(flags); + + //vector<char> buffer; + xml_attribute attr_buffer = node_attribute.append_attribute("buffer"); + + std::string str_buffer = xml_pointer_to_name(&attr) + "_" + attr.name.string(); + + std::stringstream ss; + + if (attr.element == AttributeElement::ATTR_ELEMENT_VOXEL) { + ImageHandle handle = attr.data_voxel(); + VDBImageLoader *vdb_loader = handle.vdb_loader(); + + //vector<char> buffer; + //// Convert the stringstream to a vector<char> + //std::ostringstream stream(std::ios_base::binary); + //openvdb::io::Stream(stream).write({ vdb_loader->get_grid() }); + //stream.flush(); + //const std::string& str = stream.str(); + //buffer.assign(str.begin(), str.end()); + + //ss << write_vector_to_binary_file(state, geom, string("buffer"), buffer); + + //std::stringstream ss; + //ss << geom->type->name << "_" << geom->name << "_" << attr.name.string() + string("_") + string("buffer") << ".vdb"; + //ss << attr_name.value() << ".vdb"; + //std::replace(str.begin(), str.end(), ' ', '_'); + //ss << str_buffer << ".vdb"; + //string filename(path_join(state.base, ss.str())); + //openvdb::io::File(filename).write({ vdb_loader->get_grid() }); + + // Convert the stringstream to a vector<char> + vector<char> file_content; + std::ostringstream stream(std::ios_base::binary); + openvdb::io::Stream(stream).write({ vdb_loader->get_grid() }); + stream.flush(); + const std::string& str = stream.str(); + file_content.assign(str.begin(), str.end()); + ss << write_vector_to_binary_file(state, file_content); + + xml_attribute attr_volume_type = node_attribute.append_attribute("volume_type"); + attr_volume_type = "openvdb"; + } + else { + ss << write_vector_to_binary_file(state, attr.buffer); + } + + attr_buffer = ss.str().c_str(); + } + } + + //BoundBox bounds; + //Transform transform_normal; + } + +// /* add mesh */ +// Mesh* mesh = xml_add_mesh(state.scene, state.tfm, state.object); +// array<Node*> used_shaders = mesh->get_used_shaders(); +// used_shaders.push_back_slow(state.shader); +// mesh->set_used_shaders(used_shaders); +// +// /* read state */ +// int shader = 0; +// bool smooth = state.smooth; +// +// /* read vertices and polygons */ +// vector<float3> P; +// vector<float3> VN; /* Vertex normals */ +// vector<float> UV; +// vector<float> T; /* UV tangents */ +// vector<float> TS; /* UV tangent signs */ +// vector<int> verts, nverts; +// +// scene_write_xml_float3_array(P, node, "P"); +// scene_write_xml_int_array(verts, node, "verts"); +// scene_write_xml_int_array(nverts, node, "nverts"); +// +// if (scene_write_xml_equal_string(node, "subdivision", "catmull-clark")) { +// mesh->set_subdivision_type(Mesh::SUBDIVISION_CATMULL_CLARK); +// } +// else if (scene_write_xml_equal_string(node, "subdivision", "linear")) { +// mesh->set_subdivision_type(Mesh::SUBDIVISION_LINEAR); +// } +// +// array<float3> P_array; +// P_array = P; +// +// if (mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE) { +// /* create vertices */ +// +// mesh->set_verts(P_array); +// +// size_t num_triangles = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// num_triangles += nverts[i] - 2; +// } +// mesh->reserve_mesh(mesh->get_verts().size(), num_triangles); +// +// /* create triangles */ +// int index_offset = 0; +// +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = verts[index_offset]; +// int v1 = verts[index_offset + j + 1]; +// int v2 = verts[index_offset + j + 2]; +// +// assert(v0 < (int)P.size()); +// assert(v1 < (int)P.size()); +// assert(v2 < (int)P.size()); +// +// mesh->add_triangle(v0, v1, v2, shader, smooth); +// } +// +// index_offset += nverts[i]; +// } +// +// /* Vertex normals */ +// if (scene_write_xml_float3_array(VN, node, Attribute::standard_name(ATTR_STD_VERTEX_NORMAL))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); +// float3* fdata = attr->data_float3(); +// +// /* Loop over the normals */ +// for (auto n : VN) { +// fdata[0] = n; +// fdata++; +// } +// } +// +// /* UV map */ +// if (scene_write_xml_float_array(UV, node, "UV") || +// scene_write_xml_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) +// { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV); +// float2* fdata = attr->data_float2(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 * 2 + 1 < (int)UV.size()); +// assert(v1 * 2 + 1 < (int)UV.size()); +// assert(v2 * 2 + 1 < (int)UV.size()); +// +// fdata[0] = make_float2(UV[v0 * 2], UV[v0 * 2 + 1]); +// fdata[1] = make_float2(UV[v1 * 2], UV[v1 * 2 + 1]); +// fdata[2] = make_float2(UV[v2 * 2], UV[v2 * 2 + 1]); +// fdata += 3; +// } +// +// index_offset += nverts[i]; +// } +// } +// +// /* Tangents */ +// if (scene_write_xml_float_array(T, node, Attribute::standard_name(ATTR_STD_UV_TANGENT))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV_TANGENT); +// float3* fdata = attr->data_float3(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 * 3 + 2 < (int)T.size()); +// assert(v1 * 3 + 2 < (int)T.size()); +// assert(v2 * 3 + 2 < (int)T.size()); +// +// fdata[0] = make_float3(T[v0 * 3], T[v0 * 3 + 1], T[v0 * 3 + 2]); +// fdata[1] = make_float3(T[v1 * 3], T[v1 * 3 + 1], T[v1 * 3 + 2]); +// fdata[2] = make_float3(T[v2 * 3], T[v2 * 3 + 1], T[v2 * 3 + 2]); +// fdata += 3; +// } +// index_offset += nverts[i]; +// } +// } +// +// /* Tangent signs */ +// if (scene_write_xml_float_array(TS, node, Attribute::standard_name(ATTR_STD_UV_TANGENT_SIGN))) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN); +// float* fdata = attr->data_float(); +// +// /* Loop over the triangles */ +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i] - 2; j++) { +// int v0 = index_offset; +// int v1 = index_offset + j + 1; +// int v2 = index_offset + j + 2; +// +// assert(v0 < (int)TS.size()); +// assert(v1 < (int)TS.size()); +// assert(v2 < (int)TS.size()); +// +// fdata[0] = TS[v0]; +// fdata[1] = TS[v1]; +// fdata[2] = TS[v2]; +// fdata += 3; +// } +// index_offset += nverts[i]; +// } +// } +// } +// else { +// /* create vertices */ +// mesh->set_verts(P_array); +// +// size_t num_ngons = 0; +// size_t num_corners = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// num_ngons += (nverts[i] == 4) ? 0 : 1; +// num_corners += nverts[i]; +// } +// mesh->reserve_subd_faces(nverts.size(), num_ngons, num_corners); +// +// /* create subd_faces */ +// int index_offset = 0; +// +// for (size_t i = 0; i < nverts.size(); i++) { +// mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth); +// index_offset += nverts[i]; +// } +// +// /* UV map */ +// if (scene_write_xml_float_array(UV, node, "UV") || +// scene_write_xml_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) +// { +// Attribute* attr = mesh->subd_attributes.add(ATTR_STD_UV); +// float3* fdata = attr->data_float3(); +// +//#if 0 +// if (subdivide_uvs) { +// attr->flags |= ATTR_SUBDIVIDED; +// } +//#endif +// +// index_offset = 0; +// for (size_t i = 0; i < nverts.size(); i++) { +// for (int j = 0; j < nverts[i]; j++) { +// *(fdata++) = make_float3(UV[index_offset++]); +// } +// } +// } +// +// /* setup subd params */ +// float dicing_rate = state.dicing_rate; +// scene_write_xml_float(&dicing_rate, node, "dicing_rate"); +// dicing_rate = std::max(0.1f, dicing_rate); +// +// mesh->set_subd_dicing_rate(dicing_rate); +// mesh->set_subd_objecttoworld(state.tfm); +// } +// +// /* we don't yet support arbitrary attributes, for now add vertex +// * coordinates as generated coordinates if requested */ +// if (mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) { +// Attribute* attr = mesh->attributes.add(ATTR_STD_GENERATED); +// memcpy( +// attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size()); +// } +} + +/* Light */ + +void scene_write_xml_light(XMLWriteState& state, xml_node node) +{ + //Light* light = new Light(); + + //light->set_shader(state.shader); + foreach(Light * light, state.scene->lights) { + //xml_node xml_node = node.append_child(light->type->name.c_str()); + //if (light->get_light_type() != LIGHT_BACKGROUND) + xml_write_node(state, light, node); + } + + //state.scene->lights.push_back(light); +} + +void scene_write_xml_particle_systems(XMLWriteState& state, xml_node node) +{ + foreach(ParticleSystem * ps, state.scene->particle_systems) { + xml_write_node(state, ps, node); + } +} + +//void scene_write_xml_passes(XMLWriteState& state, xml_node node) +//{ +// foreach(Pass * pass, scene->passes) { +// xml_write_node(pass, node); +// } +//} +// +//void scene_write_xml_procedurals(XMLWriteState& state, xml_node node) +//{ +// foreach(Procedural * p, scene->procedurals) { +// xml_write_node(p, node); +// } +//} + +/* Transform */ + +//void scene_write_xml_transform(xml_node node, Transform& tfm) +//{ +// if (node.append_attribute("matrix")) { +// vector<float> matrix; +// if (scene_write_xml_float_array(matrix, node, "matrix") && matrix.size() == 16) { +// ProjectionTransform projection = *(ProjectionTransform*)&matrix[0]; +// tfm = tfm * projection_to_transform(projection_transpose(projection)); +// } +// } +// +// if (node.append_attribute("translate")) { +// float3 translate = zero_float3(); +// scene_write_xml_float3(&translate, node, "translate"); +// tfm = tfm * transform_translate(translate); +// } +// +// if (node.append_attribute("rotate")) { +// float4 rotate = zero_float4(); +// scene_write_xml_float4(&rotate, node, "rotate"); +// tfm = tfm * transform_rotate(DEG2RADF(rotate.x), make_float3(rotate.y, rotate.z, rotate.w)); +// } +// +// if (node.append_attribute("scale")) { +// float3 scale = zero_float3(); +// scene_write_xml_float3(&scale, node, "scale"); +// tfm = tfm * transform_scale(scale); +// } +//} + +/* State */ + +//void scene_write_xml_state(XMLReadState& state, xml_node node) +//{ +// /* Read shader */ +// string shadername; +// +// if (scene_write_xml_string(&shadername, node, "shader")) { +// bool found = false; +// +// foreach(Shader * shader, state.scene->shaders) { +// if (shader->name == shadername) { +// state.shader = shader; +// found = true; +// break; +// } +// } +// +// if (!found) { +// fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str()); +// } +// } +// +// /* Read object */ +// string objectname; +// +// if (scene_write_xml_string(&objectname, node, "object")) { +// bool found = false; +// +// foreach(Object * object, state.scene->objects) { +// if (object->name == objectname) { +// state.object = object; +// found = true; +// break; +// } +// } +// +// if (!found) { +// fprintf(stderr, "Unknown object \"%s\".\n", objectname.c_str()); +// } +// } +// +// scene_write_xml_float(&state.dicing_rate, node, "dicing_rate"); +// +// /* read smooth/flat */ +// if (scene_write_xml_equal_string(node, "interpolation", "smooth")) { +// state.smooth = true; +// } +// else if (scene_write_xml_equal_string(node, "interpolation", "flat")) { +// state.smooth = false; +// } +//} + +/* Object */ + +void scene_write_xml_object(XMLWriteState& state, xml_node node) +{ +// Scene* scene = state.scene; +// +// /* create mesh */ +// Mesh* mesh = new Mesh(); +// scene->geometry.push_back(mesh); +// +// /* create object */ +// Object* object = new Object(); +// object->set_geometry(mesh); +// object->set_tfm(state.tfm); +// +// xml_write_node(state, object, node); +// +// scene->objects.push_back(object); + + foreach(Object * object, state.scene->objects) { + xml_node xml_node_obj = xml_write_node(state, object, node); + + if (object->attributes.size() > 0) { + //AttributeSet attributes; + //xml_node node_attributes = xml_node_obj.append_child("attributes"); + foreach(ParamValue & param_value, object->attributes) { + xml_node node_attribute = xml_node_obj.append_child("attribute"); + + //ustring m_name; ///< data name + xml_attribute attr_name = node_attribute.append_attribute("name"); + attr_name = (xml_pointer_to_name(¶m_value) + "_" + param_value.name().string()).c_str(); + + //TypeDesc m_type; ///< data type, which may itself be an array + //xml_attribute attr_type = node_attribute.append_attribute("type"); + //attr_type = (int)param_value.type();// .c_str(); + + //ADD_ATTR(type); + ADD_ATTR_DTYPE(param_value.type(), basetype); ///< C data type at the heart of our type + ADD_ATTR_DTYPE(param_value.type(), aggregate); ///< What kind of AGGREGATE is it? + ADD_ATTR_DTYPE(param_value.type(), vecsemantics); ///< Hint: What does the aggregate represent? + ADD_ATTR_DTYPE(param_value.type(), reserved); ///< Reserved for future expansion + ADD_ATTR_DTYPE(param_value.type(), arraylen); ///< Array length, 0 = not array, -1 = unsized + + //union { + // char localval[16]; + // const void* ptr; + //} m_data; ///< Our data, either a pointer or small local value + + vector<char> data(param_value.datasize()); + memcpy(data.data(), param_value.data(), param_value.datasize()); + xml_attribute attr_data = node_attribute.append_attribute("data"); + std::stringstream ss; + ss << write_vector_to_binary_file(state, data); + attr_data = ss.str().c_str(); + + //int m_nvalues = 0; ///< number of values of the given type + //unsigned char m_interp = INTERP_CONSTANT; ///< Interpolation type + xml_attribute attr_interp = node_attribute.append_attribute("interp"); + attr_interp = param_value.interp(); + //bool m_copy = false; + //bool m_nonlocal = false; + //xml_attribute attr_nonlocal = node_attribute.append_attribute("nonlocal"); + //attr_nonlocal = param_value.is_nonlocal(); + } + } + } +} + +/* Scene */ + +void scene_write_xml_scene(XMLWriteState& state, xml_node scene_node) +{ + //for (xml_node node = scene_node.first_child(); node; node = node.next_sibling()) { + //if (string_iequals(node.name(), "film")) { + //xml_node film = scene_node.append_child(scene->film->type->name.c_str()); + xml_write_node(state, state.scene->film, scene_node).attribute("name") = "film"; + //} +// else if (string_iequals(node.name(), "integrator")) { + //xml_node integrator = scene_node.append_child("integrator"); + xml_write_node(state, state.scene->integrator, scene_node).attribute("name") = "integrator"; + //} + //else if (string_iequals(node.name(), "camera")) { + //xml_node camera = scene_node.append_child("camera"); + xml_write_node(state, state.scene->camera, scene_node).attribute("name") = "camera"; + //} + // else if (string_iequals(node.name(), "background")) { + //xml_node background = scene_node.append_child("background"); + //scene_write_xml_background(scene, background); + xml_write_node(state, state.scene->background, scene_node).attribute("name") = "background"; + // } + // else if (string_iequals(node.name(), "shader")) { + //xml_node shader = scene_node.append_child("shader"); + scene_write_xml_shader(state, scene_node); + // } + // else if (string_iequals(node.name(), "light")) { + scene_write_xml_light(state, scene_node); + // } + // else if (string_iequals(node.name(), "mesh")) { + //xml_node mesh = scene_node.append_child("mesh"); + scene_write_xml_geom(state, scene_node); + + scene_write_xml_particle_systems(state, scene_node); + //scene_write_xml_passes(scene, scene_node); + //scene_write_xml_procedurals(scene, scene_node); + + // } + // else if (string_iequals(node.name(), "transform")) { + // XMLReadState substate = state; + // + // xml_node transform = scene_node.append_child("transform"); + //scene_write_xml_transform(transform, scene/*substate.tfm*/); + //scene_write_xml_scene(scene, transform); + // } + // else if (string_iequals(node.name(), "state")) { + // XMLReadState substate = state; + // + // xml_node state = scene_node.append_child("state"); + //scene_write_xml_state(scene, state); + //scene_write_xml_scene(scene, state); + // } + // else if (string_iequals(node.name(), "include")) { + // string src; + //xml_node node_include = scene_node.append_child("include"); + + // if (scene_write_xml_string(&src, node, "src")) { + // scene_write_xml_include(state, src); + // } + // } + // else if (string_iequals(node.name(), "object")) { + // XMLReadState substate = state; + // + // xml_node object = scene_node.append_child("object"); + scene_write_xml_object(state, scene_node); + //scene_write_xml_scene(scene, object); + // } + //#ifdef WITH_ALEMBIC + // else if (string_iequals(node.name(), "alembic")) { + // scene_write_xml_alembic(state, node); + // } + //#endif + // else { + // fprintf(stderr, "Unknown node \"%s\".\n", node.name()); + // } + //} +} + +/* Include */ + +void scene_write_xml_include(XMLWriteState &state, const string& filename_xml) +{ + /* open XML document */ + xml_document doc; + //xml_parse_result parse_result; + + //string path = path_join(state.base, src); + //parse_result = doc.load_file(path.c_str()); + + //if (parse_result) { + //XMLReadState substate = state; + //substate.base = path_dirname(path); + + string filename_bin = string(filename_xml) + string(".bin"); + + // Open the file in binary write mode + state.file.open(filename_bin, std::ios::binary); + if (!state.file.is_open()) { + std::cerr << "Error: Could not open file for writing: " << filename_bin << "\n"; + return; + } + + xml_node cycles = doc.append_child("cycles"); + scene_write_xml_scene(state, cycles); + //} + //else { + // fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description()); + // exit(EXIT_FAILURE); + //} + + // Save the XML to a file + doc.save_file(filename_xml.c_str()); + + state.file.close(); +} + +/* File */ + +void scene_write_xml_file(Scene* scene, const char* filepath) +{ + if (scene == nullptr || filepath == nullptr) + return; + + XMLWriteState state; + + state.scene = scene; + //std::string base = path_dirname(filepath); + + scene_write_xml_include(state, filepath); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/scene/scene_write_xml.h b/intern/cycles/scene/scene_write_xml.h new file mode 100644 index 0000000000000000000000000000000000000000..164c82a0920caf67ad482089a4d79a63cb9cb5e0 --- /dev/null +++ b/intern/cycles/scene/scene_write_xml.h @@ -0,0 +1,38 @@ +/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation + * + * SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + +#include "graph/node_xml.h" +#include "scene/scene.h" + +CCL_NAMESPACE_BEGIN + +#if 0 +void scene_write_xml_int(int value, xml_node node, const char* name); +void scene_write_xml_int_array(vector<int>& value, xml_node node, const char* name); +void scene_write_xml_float(float value, xml_node node, const char* name); +void scene_write_xml_float_array(vector<float>& value, xml_node node, const char* name); +void scene_write_xml_float3(float3 value, xml_node node, const char* name); +void scene_write_xml_float3_array(vector<float3>& value, xml_node node, const char* name); +void scene_write_xml_float4(float4 value, xml_node node, const char* name); +void scene_write_xml_string(string str, xml_node node, const char* name); +void scene_write_xml_camera(Scene *scene, xml_node node); +//void scene_write_xml_alembic(Scene *scene, xml_node graph_node); +void scene_write_xml_shader_graph(Scene *scene, Shader* shader, xml_node graph_node); +void scene_write_xml_shader(Scene *scene, xml_node node); +void scene_write_xml_background(Scene *scene, xml_node node); +//void scene_write_xml_mesh(const Scene *scene, xml_node node); +void scene_write_xml_light(Scene *scene, xml_node node); +void scene_write_xml_transform(xml_node node, Transform& tfm); +void scene_write_xml_state(Scene *scene, xml_node node); +void scene_write_xml_object(Scene *scene, xml_node node); +void scene_write_xml_include(Scene *scene, const string& src); +void scene_write_xml_scene(Scene *scene, xml_node scene_node); +void scene_write_xml_include(Scene *scene, const string& src); +#endif + +void scene_write_xml_file(Scene* scene, const char* filepath); + +CCL_NAMESPACE_END