Blender V5.0
cycles_xml.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <cstdio>
6
7#include <algorithm>
8
9#include "graph/node_xml.h"
10
11#include "scene/background.h"
12#include "scene/camera.h"
13#include "scene/film.h"
14#include "scene/integrator.h"
15#include "scene/light.h"
16#include "scene/mesh.h"
17#include "scene/object.h"
18#include "scene/osl.h"
19#include "scene/scene.h"
20#include "scene/shader.h"
21#include "scene/shader_graph.h"
22#include "scene/shader_nodes.h"
23
24#include "util/log.h"
25#include "util/path.h"
26#include "util/projection.h"
27#include "util/string.h"
28#include "util/transform.h"
29#include "util/xml.h"
30
31#include "app/cycles_xml.h"
32
34
35/* XML reading state */
36
37struct XMLReadState : public XMLReader {
38 Scene *scene = nullptr; /* Scene pointer. */
39 Transform tfm; /* Current transform state. */
40 bool smooth = false; /* Smooth normal state. */
41 Shader *shader = nullptr; /* Current shader. */
42 string base; /* Base path to current file. */
43 float dicing_rate = 1.0f; /* Current dicing rate. */
44 Object *object = nullptr; /* Current object. */
45
47 {
49 }
50};
51
52/* Attribute Reading */
53
54static bool xml_read_int(int *value, const xml_node node, const char *name)
55{
56 const xml_attribute attr = node.attribute(name);
57
58 if (attr) {
59 *value = atoi(attr.value());
60 return true;
61 }
62
63 return false;
64}
65
66static bool xml_read_int_array(vector<int> &value, const xml_node node, const char *name)
67{
68 const xml_attribute attr = node.attribute(name);
69
70 if (attr) {
71 vector<string> tokens;
72 string_split(tokens, attr.value());
73
74 for (const string &token : tokens) {
75 value.push_back(atoi(token.c_str()));
76 }
77
78 return true;
79 }
80
81 return false;
82}
83
84static bool xml_read_float(float *value, const xml_node node, const char *name)
85{
86 const xml_attribute attr = node.attribute(name);
87
88 if (attr) {
89 *value = (float)atof(attr.value());
90 return true;
91 }
92
93 return false;
94}
95
96static bool xml_read_float_array(vector<float> &value, const xml_node node, const char *name)
97{
98 const xml_attribute attr = node.attribute(name);
99
100 if (attr) {
101 vector<string> tokens;
102 string_split(tokens, attr.value());
103
104 for (const string &token : tokens) {
105 value.push_back((float)atof(token.c_str()));
106 }
107
108 return true;
109 }
110
111 return false;
112}
113
114static bool xml_read_float3(float3 *value, const xml_node node, const char *name)
115{
117
118 if (xml_read_float_array(array, node, name) && array.size() == 3) {
119 *value = make_float3(array[0], array[1], array[2]);
120 return true;
121 }
122
123 return false;
124}
125
126static bool xml_read_float3_array(vector<float3> &value, const xml_node node, const char *name)
127{
129
130 if (xml_read_float_array(array, node, name)) {
131 for (size_t i = 0; i < array.size(); i += 3) {
132 value.push_back(make_float3(array[i + 0], array[i + 1], array[i + 2]));
133 }
134
135 return true;
136 }
137
138 return false;
139}
140
141static bool xml_read_float4(float4 *value, const xml_node node, const char *name)
142{
144
145 if (xml_read_float_array(array, node, name) && array.size() == 4) {
146 *value = make_float4(array[0], array[1], array[2], array[3]);
147 return true;
148 }
149
150 return false;
151}
152
153static bool xml_read_string(string *str, const xml_node node, const char *name)
154{
155 const xml_attribute attr = node.attribute(name);
156
157 if (attr) {
158 *str = attr.value();
159 return true;
160 }
161
162 return false;
163}
164
165static bool xml_equal_string(const xml_node node, const char *name, const char *value)
166{
167 const xml_attribute attr = node.attribute(name);
168
169 if (attr) {
170 return string_iequals(attr.value(), value);
171 }
172
173 return false;
174}
175
176/* Camera */
177
178static void xml_read_camera(XMLReadState &state, const xml_node node)
179{
180 Camera *cam = state.scene->camera;
181
182 int width = -1;
183 int height = -1;
184 xml_read_int(&width, node, "width");
185 xml_read_int(&height, node, "height");
186
187 cam->set_full_width(width);
188 cam->set_full_height(height);
189
190 xml_read_node(state, cam, node);
191
192 cam->set_matrix(state.tfm);
193
194 cam->need_flags_update = true;
195 cam->update(state.scene);
196}
197
198/* Shader */
199
200static void xml_read_shader_graph(XMLReadState &state, Shader *shader, const xml_node graph_node)
201{
202 xml_read_node(state, shader, graph_node);
203
204 unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
205
206 /* local state, shader nodes can't link to nodes outside the shader graph */
207 XMLReader graph_reader;
208 graph_reader.node_map[ustring("output")] = graph->output();
209
210 for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
211 ustring node_name(node.name());
212
213 if (node_name == "connect") {
214 /* connect nodes */
215 vector<string> from_tokens;
216 vector<string> to_tokens;
217
218 string_split(from_tokens, node.attribute("from").value());
219 string_split(to_tokens, node.attribute("to").value());
220
221 if (from_tokens.size() == 2 && to_tokens.size() == 2) {
222 const ustring from_node_name(from_tokens[0]);
223 const ustring from_socket_name(from_tokens[1]);
224 const ustring to_node_name(to_tokens[0]);
225 const ustring to_socket_name(to_tokens[1]);
226
227 /* find nodes and sockets */
228 ShaderOutput *output = nullptr;
229 ShaderInput *input = nullptr;
230
231 if (graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) {
232 ShaderNode *fromnode = (ShaderNode *)graph_reader.node_map[from_node_name];
233
234 for (ShaderOutput *out : fromnode->outputs) {
235 if (string_iequals(out->socket_type.name.string(), from_socket_name.string())) {
236 output = out;
237 }
238 }
239
240 if (!output) {
241 LOG_ERROR << "Unknown output socket name \"" << from_node_name << "\" on \""
242 << from_socket_name << "\".";
243 }
244 }
245 else {
246 LOG_ERROR << "Unknown shader node name \"" << from_node_name << "\"";
247 }
248
249 if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) {
250 ShaderNode *tonode = (ShaderNode *)graph_reader.node_map[to_node_name];
251
252 for (ShaderInput *in : tonode->inputs) {
253 if (string_iequals(in->socket_type.name.string(), to_socket_name.string())) {
254 input = in;
255 }
256 }
257
258 if (!input) {
259 LOG_ERROR << "Unknown input socket name \"" << to_socket_name << "\" on \""
260 << to_node_name << "\"";
261 }
262 }
263 else {
264 LOG_ERROR << "Unknown shader node name \"" << to_node_name << "\"";
265 }
266
267 /* connect */
268 if (output && input) {
269 graph->connect(output, input);
270 }
271 }
272 else {
273 LOG_ERROR << "Invalid from or to value for connect node.";
274 }
275
276 continue;
277 }
278
279 ShaderNode *snode = nullptr;
280
281#ifdef WITH_OSL
282 if (node_name == "osl_shader") {
283 ShaderManager *manager = state.scene->shader_manager.get();
284
285 if (manager->use_osl()) {
286 std::string filepath;
287
288 if (xml_read_string(&filepath, node, "src")) {
289 if (path_is_relative(filepath)) {
290 filepath = path_join(state.base, filepath);
291 }
292
293 snode = OSLShaderManager::osl_node(graph.get(), state.scene, filepath, "");
294
295 if (!snode) {
296 LOG_ERROR << "Failed to create OSL node from \"" << filepath << "\"";
297 continue;
298 }
299 }
300 else {
301 LOG_ERROR << "OSL node missing \"src\" attribute.";
302 continue;
303 }
304 }
305 else {
306 LOG_ERROR << "OSL node without using --shadingsys osl.";
307 continue;
308 }
309 }
310 else
311#endif
312 {
313 /* exception for name collision */
314 if (node_name == "background") {
315 node_name = "background_shader";
316 }
317
318 const NodeType *node_type = NodeType::find(node_name);
319
320 if (!node_type) {
321 LOG_ERROR << "Unknown shader node \"" << node.name() << "\"";
322 continue;
323 }
324 if (node_type->type != NodeType::SHADER) {
325 LOG_ERROR << "Node type \"" << node_type->name << "\" is not a shader node";
326 continue;
327 }
328 if (node_type->create == nullptr) {
329 LOG_ERROR << "Can't create abstract node type \""
330 << "\"";
331 continue;
332 }
333
334 snode = graph->create_node(node_type);
335 }
336
337 xml_read_node(graph_reader, snode, node);
338
339 if (node_name == "image_texture") {
340 ImageTextureNode *img = (ImageTextureNode *)snode;
341 const ustring filename(path_join(state.base, img->get_filename().string()));
342 img->set_filename(filename);
343 }
344 else if (node_name == "environment_texture") {
346 const ustring filename(path_join(state.base, env->get_filename().string()));
347 env->set_filename(filename);
348 }
349 }
350
351 shader->set_graph(std::move(graph));
352 shader->tag_update(state.scene);
353}
354
355static void xml_read_shader(XMLReadState &state, const xml_node node)
356{
357 Shader *shader = state.scene->create_node<Shader>();
358 xml_read_shader_graph(state, shader, node);
359}
360
361/* Background */
362
363static void xml_read_background(XMLReadState &state, const xml_node node)
364{
365 /* Background Settings */
366 xml_read_node(state, state.scene->background, node);
367
368 /* Background Shader */
369 Shader *shader = state.scene->default_background;
370 xml_read_shader_graph(state, shader, node);
371}
372
373/* Mesh */
374
375static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm, Object *object)
376{
377 if (object && object->get_geometry()->is_mesh()) {
378 /* Use existing object and mesh */
379 object->set_tfm(tfm);
380 Geometry *geometry = object->get_geometry();
381 return static_cast<Mesh *>(geometry);
382 }
383
384 /* Create mesh */
385 Mesh *mesh = scene->create_node<Mesh>();
386
387 /* Create object. */
388 object = scene->create_node<Object>();
389 object->set_geometry(mesh);
390 object->set_tfm(tfm);
391
392 return mesh;
393}
394
395static void xml_read_mesh(const XMLReadState &state, const xml_node node)
396{
397 /* add mesh */
398 Mesh *mesh = xml_add_mesh(state.scene, state.tfm, state.object);
399 array<Node *> used_shaders = mesh->get_used_shaders();
400 used_shaders.push_back_slow(state.shader);
401 mesh->set_used_shaders(used_shaders);
402
403 /* read state */
404 const int shader = 0;
405 const bool smooth = state.smooth;
406
407 /* read vertices and polygons */
409 vector<float3> VN; /* Vertex normals */
410 vector<float> UV;
411 vector<float> T; /* UV tangents */
412 vector<float> TS; /* UV tangent signs */
414 vector<int> nverts;
415
416 xml_read_float3_array(P, node, "P");
417 xml_read_int_array(verts, node, "verts");
418 xml_read_int_array(nverts, node, "nverts");
419
420 if (xml_equal_string(node, "subdivision", "catmull-clark")) {
421 mesh->set_subdivision_type(Mesh::SUBDIVISION_CATMULL_CLARK);
422 }
423 else if (xml_equal_string(node, "subdivision", "linear")) {
424 mesh->set_subdivision_type(Mesh::SUBDIVISION_LINEAR);
425 }
426
427 array<float3> P_array;
428 P_array = P;
429
430 if (mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE) {
431 /* create vertices */
432
433 mesh->set_verts(P_array);
434
435 size_t num_triangles = 0;
436 for (size_t i = 0; i < nverts.size(); i++) {
437 num_triangles += nverts[i] - 2;
438 }
439 mesh->reserve_mesh(mesh->get_verts().size(), num_triangles);
440
441 /* create triangles */
442 int index_offset = 0;
443
444 for (size_t i = 0; i < nverts.size(); i++) {
445 for (int j = 0; j < nverts[i] - 2; j++) {
446 const int v0 = verts[index_offset];
447 const int v1 = verts[index_offset + j + 1];
448 const int v2 = verts[index_offset + j + 2];
449
450 assert(v0 < (int)P.size());
451 assert(v1 < (int)P.size());
452 assert(v2 < (int)P.size());
453
454 mesh->add_triangle(v0, v1, v2, shader, smooth);
455 }
456
457 index_offset += nverts[i];
458 }
459
460 /* Vertex normals */
463 float3 *fdata = attr->data_float3();
464
465 /* Loop over the normals */
466 for (auto n : VN) {
467 fdata[0] = n;
468 fdata++;
469 }
470 }
471
472 /* UV map */
473 if (xml_read_float_array(UV, node, "UV") ||
475 {
476 Attribute *attr = mesh->attributes.add(ATTR_STD_UV);
477 float2 *fdata = attr->data_float2();
478
479 /* Loop over the triangles */
480 index_offset = 0;
481 for (size_t i = 0; i < nverts.size(); i++) {
482 for (int j = 0; j < nverts[i] - 2; j++) {
483 const int v0 = index_offset;
484 const int v1 = index_offset + j + 1;
485 const int v2 = index_offset + j + 2;
486
487 assert(v0 * 2 + 1 < (int)UV.size());
488 assert(v1 * 2 + 1 < (int)UV.size());
489 assert(v2 * 2 + 1 < (int)UV.size());
490
491 fdata[0] = make_float2(UV[v0 * 2], UV[v0 * 2 + 1]);
492 fdata[1] = make_float2(UV[v1 * 2], UV[v1 * 2 + 1]);
493 fdata[2] = make_float2(UV[v2 * 2], UV[v2 * 2 + 1]);
494 fdata += 3;
495 }
496
497 index_offset += nverts[i];
498 }
499 }
500
501 /* Tangents */
504 float3 *fdata = attr->data_float3();
505
506 /* Loop over the triangles */
507 index_offset = 0;
508 for (size_t i = 0; i < nverts.size(); i++) {
509 for (int j = 0; j < nverts[i] - 2; j++) {
510 const int v0 = index_offset;
511 const int v1 = index_offset + j + 1;
512 const int v2 = index_offset + j + 2;
513
514 assert(v0 * 3 + 2 < (int)T.size());
515 assert(v1 * 3 + 2 < (int)T.size());
516 assert(v2 * 3 + 2 < (int)T.size());
517
518 fdata[0] = make_float3(T[v0 * 3], T[v0 * 3 + 1], T[v0 * 3 + 2]);
519 fdata[1] = make_float3(T[v1 * 3], T[v1 * 3 + 1], T[v1 * 3 + 2]);
520 fdata[2] = make_float3(T[v2 * 3], T[v2 * 3 + 1], T[v2 * 3 + 2]);
521 fdata += 3;
522 }
523 index_offset += nverts[i];
524 }
525 }
526
527 /* Tangent signs */
530 float *fdata = attr->data_float();
531
532 /* Loop over the triangles */
533 index_offset = 0;
534 for (size_t i = 0; i < nverts.size(); i++) {
535 for (int j = 0; j < nverts[i] - 2; j++) {
536 const int v0 = index_offset;
537 const int v1 = index_offset + j + 1;
538 const int v2 = index_offset + j + 2;
539
540 assert(v0 < (int)TS.size());
541 assert(v1 < (int)TS.size());
542 assert(v2 < (int)TS.size());
543
544 fdata[0] = TS[v0];
545 fdata[1] = TS[v1];
546 fdata[2] = TS[v2];
547 fdata += 3;
548 }
549 index_offset += nverts[i];
550 }
551 }
552 }
553 else {
554 /* create vertices */
555 mesh->set_verts(P_array);
556
557 size_t num_corners = 0;
558 for (size_t i = 0; i < nverts.size(); i++) {
559 num_corners += nverts[i];
560 }
561 mesh->reserve_subd_faces(nverts.size(), num_corners);
562
563 /* create subd_faces */
564 int index_offset = 0;
565
566 for (size_t i = 0; i < nverts.size(); i++) {
567 mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth);
568 index_offset += nverts[i];
569 }
570
571 /* UV map */
572 if (xml_read_float_array(UV, node, "UV") ||
574 {
576 float3 *fdata = attr->data_float3();
577
578 index_offset = 0;
579 for (size_t i = 0; i < nverts.size(); i++) {
580 for (int j = 0; j < nverts[i]; j++) {
581 *(fdata++) = make_float3(UV[index_offset++]);
582 }
583 }
584 }
585
586 /* setup subd params */
587 float dicing_rate = state.dicing_rate;
588 xml_read_float(&dicing_rate, node, "dicing_rate");
589 dicing_rate = std::max(0.1f, dicing_rate);
590
591 mesh->set_subd_dicing_rate(dicing_rate);
592 mesh->set_subd_objecttoworld(state.tfm);
593 }
594
595 /* we don't yet support arbitrary attributes, for now add vertex
596 * coordinates as generated coordinates if requested */
597 if (mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) {
599 std::copy_n(mesh->get_verts().data(), mesh->get_verts().size(), attr->data_float3());
600 }
601}
602
603/* Light */
604
605static void xml_read_light(XMLReadState &state, const xml_node node)
606{
607 Scene *scene = state.scene;
608
609 /* Create light. */
610 Light *light = scene->create_node<Light>();
611
612 array<Node *> used_shaders;
613 used_shaders.push_back_slow(state.shader);
614 light->set_used_shaders(used_shaders);
615
616 /* Create object. */
617 Object *object = scene->create_node<Object>();
618 object->set_tfm(state.tfm);
619 object->set_visibility(PATH_RAY_ALL_VISIBILITY & ~PATH_RAY_CAMERA);
620 object->set_geometry(light);
621
622 xml_read_node(state, light, node);
623}
624
625/* Transform */
626
627static void xml_read_transform(const xml_node node, Transform &tfm)
628{
629 if (node.attribute("matrix")) {
630 vector<float> matrix;
631 if (xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16) {
632 const ProjectionTransform projection = *(ProjectionTransform *)matrix.data();
633 tfm = tfm * projection_to_transform(projection_transpose(projection));
634 }
635 }
636
637 if (node.attribute("translate")) {
638 float3 translate = zero_float3();
639 xml_read_float3(&translate, node, "translate");
640 tfm = tfm * transform_translate(translate);
641 }
642
643 if (node.attribute("rotate")) {
645 xml_read_float4(&rotate, node, "rotate");
647 }
648
649 if (node.attribute("scale")) {
650 float3 scale = zero_float3();
651 xml_read_float3(&scale, node, "scale");
652 tfm = tfm * transform_scale(scale);
653 }
654}
655
656/* State */
657
658static void xml_read_state(XMLReadState &state, const xml_node node)
659{
660 /* Read shader */
661 string shadername;
662
663 if (xml_read_string(&shadername, node, "shader")) {
664 bool found = false;
665
666 for (Shader *shader : state.scene->shaders) {
667 if (shader->name == shadername) {
668 state.shader = shader;
669 found = true;
670 break;
671 }
672 }
673
674 if (!found) {
675 LOG_ERROR << "Unknown shader \"" << shadername << "\"";
676 }
677 }
678
679 /* Read object */
680 string objectname;
681
682 if (xml_read_string(&objectname, node, "object")) {
683 bool found = false;
684
685 for (Object *object : state.scene->objects) {
686 if (object->name == objectname) {
687 state.object = object;
688 found = true;
689 break;
690 }
691 }
692
693 if (!found) {
694 LOG_ERROR << "Unknown object \"" << objectname << "\"";
695 }
696 }
697
698 xml_read_float(&state.dicing_rate, node, "dicing_rate");
699
700 /* read smooth/flat */
701 if (xml_equal_string(node, "interpolation", "smooth")) {
702 state.smooth = true;
703 }
704 else if (xml_equal_string(node, "interpolation", "flat")) {
705 state.smooth = false;
706 }
707}
708
709/* Object */
710
711static void xml_read_object(XMLReadState &state, const xml_node node)
712{
713 Scene *scene = state.scene;
714
715 /* create mesh */
716 Mesh *mesh = scene->create_node<Mesh>();
717
718 /* create object */
719 Object *object = scene->create_node<Object>();
720 object->set_geometry(mesh);
721 object->set_tfm(state.tfm);
722
723 xml_read_node(state, object, node);
724}
725
726/* Scene */
727
728static void xml_read_include(XMLReadState &state, const string &src);
729
730static void xml_read_scene(XMLReadState &state, const xml_node scene_node)
731{
732 for (xml_node node = scene_node.first_child(); node; node = node.next_sibling()) {
733 if (string_iequals(node.name(), "film")) {
734 xml_read_node(state, state.scene->film, node);
735 }
736 else if (string_iequals(node.name(), "integrator")) {
737 xml_read_node(state, state.scene->integrator, node);
738 }
739 else if (string_iequals(node.name(), "camera")) {
740 xml_read_camera(state, node);
741 }
742 else if (string_iequals(node.name(), "shader")) {
743 xml_read_shader(state, node);
744 }
745 else if (string_iequals(node.name(), "background")) {
747 }
748 else if (string_iequals(node.name(), "mesh")) {
749 xml_read_mesh(state, node);
750 }
751 else if (string_iequals(node.name(), "light")) {
752 xml_read_light(state, node);
753 }
754 else if (string_iequals(node.name(), "transform")) {
755 XMLReadState substate = state;
756
757 xml_read_transform(node, substate.tfm);
758 xml_read_scene(substate, node);
759 }
760 else if (string_iequals(node.name(), "state")) {
761 XMLReadState substate = state;
762
763 xml_read_state(substate, node);
764 xml_read_scene(substate, node);
765 }
766 else if (string_iequals(node.name(), "include")) {
767 string src;
768
769 if (xml_read_string(&src, node, "src")) {
771 }
772 }
773 else if (string_iequals(node.name(), "object")) {
774 XMLReadState substate = state;
775
776 xml_read_object(substate, node);
777 xml_read_scene(substate, node);
778 }
779 else {
780 LOG_ERROR << "Unknown node \"" << node.name() << "\"";
781 }
782 }
783}
784
785/* Include */
786
787static void xml_read_include(XMLReadState &state, const string &src)
788{
789 /* open XML document */
790 xml_document doc;
791 xml_parse_result parse_result;
792
793 const string path = path_join(state.base, src);
794 parse_result = doc.load_file(path.c_str());
795
796 if (parse_result) {
797 XMLReadState substate = state;
798 substate.base = path_dirname(path);
799
800 const xml_node cycles = doc.child("cycles");
801 xml_read_scene(substate, cycles);
802 }
803 else {
804 LOG_ERROR << "\"" << src << "\" read error: " << parse_result.description();
805 exit(EXIT_FAILURE);
806 }
807}
808
809/* File */
810
811void xml_read_file(Scene *scene, const char *filepath)
812{
814
815 state.scene = scene;
817 state.shader = scene->default_surface;
818 state.smooth = false;
819 state.dicing_rate = 1.0f;
820 state.base = path_dirname(filepath);
821
823
825}
826
#define DEG2RADF(_deg)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
Attribute * add(ustring name, const TypeDesc type, AttributeElement element)
bool need_attribute(Scene *scene, AttributeStandard std)
AttributeSet attributes
BVHType bvh_type
Definition scene.h:67
virtual bool use_osl()
unique_ptr_vector< ShaderInput > inputs
unique_ptr_vector< ShaderOutput > outputs
void set_graph(unique_ptr< ShaderGraph > &&graph)
void tag_update(Scene *scene)
size_t size() const
void push_back_slow(const T &t)
nullptr float
ccl_device_inline Transform projection_to_transform(const ProjectionTransform &a)
ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform a)
static void xml_read_object(XMLReadState &state, const xml_node node)
static bool xml_read_float3(float3 *value, const xml_node node, const char *name)
static bool xml_read_int_array(vector< int > &value, const xml_node node, const char *name)
static bool xml_read_float(float *value, const xml_node node, const char *name)
static void xml_read_include(XMLReadState &state, const string &src)
static void xml_read_background(XMLReadState &state, const xml_node node)
static bool xml_read_string(string *str, const xml_node node, const char *name)
static void xml_read_transform(const xml_node node, Transform &tfm)
static bool xml_read_int(int *value, const xml_node node, const char *name)
static Mesh * xml_add_mesh(Scene *scene, const Transform &tfm, Object *object)
void xml_read_file(Scene *scene, const char *filepath)
static void xml_read_scene(XMLReadState &state, const xml_node scene_node)
static bool xml_read_float4(float4 *value, const xml_node node, const char *name)
static void xml_read_state(XMLReadState &state, const xml_node node)
static void xml_read_shader_graph(XMLReadState &state, Shader *shader, const xml_node graph_node)
static bool xml_read_float_array(vector< float > &value, const xml_node node, const char *name)
static void xml_read_camera(XMLReadState &state, const xml_node node)
static void xml_read_light(XMLReadState &state, const xml_node node)
static bool xml_equal_string(const xml_node node, const char *name, const char *value)
static void xml_read_mesh(const XMLReadState &state, const xml_node node)
static bool xml_read_float3_array(vector< float3 > &value, const xml_node node, const char *name)
static void xml_read_shader(XMLReadState &state, const xml_node node)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define str(s)
static float verts[][3]
#define input
#define assert(assertion)
#define in
#define out
#define output
@ ATTR_STD_UV
@ ATTR_STD_VERTEX_NORMAL
@ ATTR_STD_UV_TANGENT
@ ATTR_STD_UV_TANGENT_SIGN
@ ATTR_STD_GENERATED
@ PATH_RAY_ALL_VISIBILITY
@ PATH_RAY_CAMERA
#define LOG_ERROR
Definition log.h:101
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
Definition math_float4.h:13
static ulong state[N]
#define T
static void rotate(float new_co[3], float a, const float ax[3], const float co[3])
@ BVH_TYPE_STATIC
Definition params.h:40
string path_dirname(const string &path)
Definition path.cpp:401
bool path_is_relative(const string &path)
Definition path.cpp:444
string path_join(const string &dir, const string &file)
Definition path.cpp:415
string path_filename(const string &path)
Definition path.cpp:378
const char * name
#define make_float2
#define make_float4
bool string_iequals(const string &a, const string &b)
Definition string.cpp:55
void string_split(vector< string > &tokens, const string &str, const string &separators, bool skip_empty_tokens)
Definition string.cpp:70
static const char * standard_name(AttributeStandard std)
float * data_float()
float3 * data_float3()
float2 * data_float2()
bool need_flags_update
void update(Scene *scene)
void add_triangle(const int v0, const int v1, const int v2, const int shader, bool smooth)
AttributeSet subd_attributes
Definition scene/mesh.h:174
void reserve_mesh(const int numverts, const int numtris)
@ SUBDIVISION_NONE
Definition scene/mesh.h:118
@ SUBDIVISION_LINEAR
Definition scene/mesh.h:119
@ SUBDIVISION_CATMULL_CLARK
Definition scene/mesh.h:120
void add_subd_face(const int *corners, const int num_corners, const int shader_, bool smooth_)
void reserve_subd_faces(const int numfaces, const int numcorners)
Type type
Definition node_type.h:126
static const NodeType * find(ustring name)
CreateFunc create
Definition node_type.h:130
ustring name
Definition node_type.h:125
ustring name
Definition graph/node.h:177
SceneParams params
Definition scene.h:168
Shader * default_surface
Definition scene.h:157
T * create_node(Args &&...)=delete
Scene * scene
Transform tfm
Shader * shader
float dicing_rate
i
Definition text_draw.cc:230
ccl_device_inline Transform transform_rotate(const float angle, float3 axis)
Definition transform.h:290
ccl_device_inline Transform transform_identity()
Definition transform.h:322
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:280
ccl_device_inline Transform transform_translate(const float3 t)
Definition transform.h:270