From 356d49faf4384d83af7a91557fc81ca8363fccbd Mon Sep 17 00:00:00 2001 From: howetuft Date: Fri, 12 Jan 2024 21:44:52 +0100 Subject: [PATCH] Cycles Standalone - Expose Object node in XML API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Object node is not currently exposed in XML API (see https://devtalk.blender.org/t/cycles-standalone-caustics/32861/2). At now, Object nodes are only implicitly created when Mesh nodes are read. This prevents users of the XML API from accessing features that are dependent on this node, in particular caustics. This commit implements the following solution: - Add a function for reading Object XML nodes - Provide the XML Read State with an object property, which allows to set the current Object for state’s sub-nodes. - When creating a Mesh, if the object of the Read State is set, use that object rather than creating a new one. Otherwise, follow the previous behaviour (implicit creation). An example scene is also provided, illustrating how caustics can be rendered using this functionality. --- examples/scene_caustics.xml | 65 ++++++++++++++++++++++++++++++ src/app/cycles_xml.cpp | 80 +++++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 examples/scene_caustics.xml diff --git a/examples/scene_caustics.xml b/examples/scene_caustics.xml new file mode 100644 index 000000000..f7cc32990 --- /dev/null +++ b/examples/scene_caustics.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/cycles_xml.cpp b/src/app/cycles_xml.cpp index 086351972..5f134e88d 100644 --- a/src/app/cycles_xml.cpp +++ b/src/app/cycles_xml.cpp @@ -46,8 +46,9 @@ struct XMLReadState : public XMLReader { 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) + XMLReadState() : scene(NULL), smooth(false), shader(NULL), dicing_rate(1.0f), object(NULL) { tfm = transform_identity(); } @@ -405,25 +406,33 @@ static void xml_read_background(XMLReadState &state, xml_node node) /* Mesh */ -static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm) +static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm, Object *object) { - /* create mesh */ - Mesh *mesh = new Mesh(); - scene->geometry.push_back(mesh); + if (object && object->get_geometry()->is_mesh()) { + /* Use existing object and mesh */ + object->set_tfm(tfm); + Geometry *geometry = object->get_geometry(); + return static_cast(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); + /* Create object. */ + Object *object = new Object(); + object->set_geometry(mesh); + object->set_tfm(tfm); + scene->objects.push_back(object); - return mesh; + return mesh; + } } static void xml_read_mesh(const XMLReadState &state, xml_node node) { /* add mesh */ - Mesh *mesh = xml_add_mesh(state.scene, state.tfm); + Mesh *mesh = xml_add_mesh(state.scene, state.tfm, state.object); array used_shaders = mesh->get_used_shaders(); used_shaders.push_back_slow(state.shader); mesh->set_used_shaders(used_shaders); @@ -613,7 +622,7 @@ static void xml_read_transform(xml_node node, Transform &tfm) static void xml_read_state(XMLReadState &state, xml_node node) { - /* read shader */ + /* Read shader */ string shadername; if (xml_read_string(&shadername, node, "shader")) { @@ -632,6 +641,25 @@ static void xml_read_state(XMLReadState &state, xml_node node) } } + /* Read object */ + string objectname; + + if (xml_read_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()); + } + } + xml_read_float(&state.dicing_rate, node, "dicing_rate"); /* read smooth/flat */ @@ -643,6 +671,26 @@ static void xml_read_state(XMLReadState &state, xml_node node) } } +/* Object */ + +static void xml_read_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 */ static void xml_read_include(XMLReadState &state, const string &src); @@ -690,6 +738,12 @@ static void xml_read_scene(XMLReadState &state, xml_node scene_node) xml_read_include(state, src); } } + else if (string_iequals(node.name(), "object")) { + XMLReadState substate = state; + + xml_read_object(substate, node); + xml_read_scene(substate, node); + } #ifdef WITH_ALEMBIC else if (string_iequals(node.name(), "alembic")) { xml_read_alembic(state, node); -- 2.30.2