// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "scenegraph.h" #include "xml_loader.h" #include "xml_writer.h" #include "obj_loader.h" #include "ply_loader.h" #include "corona_loader.h" namespace embree { extern "C" RTCDevice g_device; void (*SceneGraph::opaque_geometry_destruction)(void*) = nullptr; Ref SceneGraph::load(const FileName& filename, const bool singleObject) { if (toLowerCase(filename.ext()) == std::string("obj" )) return loadOBJ(filename, false, singleObject); else if (toLowerCase(filename.ext()) == std::string("ply" )) return loadPLY(filename); else if (toLowerCase(filename.ext()) == std::string("xml" )) return loadXML(filename); else if (toLowerCase(filename.ext()) == std::string("scn" )) return loadCorona(filename); else throw std::runtime_error("unknown scene format: " + filename.ext()); } void SceneGraph::store(Ref root, const FileName& filename, bool embedTextures, bool referenceMaterials, bool binaryFormat) { if (toLowerCase(filename.ext()) == std::string("xml")) { storeXML(root,filename,embedTextures,referenceMaterials,binaryFormat); } else throw std::runtime_error("unknown scene format: " + filename.ext()); } void SceneGraph::PerspectiveCameraNode::print(std::ostream& cout, int depth) { cout << "PerspectiveCameraNode @ " << this << " { " << std::endl; if (name != "") { tab(cout, depth+1); cout << "name = " << name << std::endl; } tab(cout, depth+1); cout << "from = " << data.from << std::endl; tab(cout, depth+1); cout << "to = " << data.to << std::endl; tab(cout, depth+1); cout << "up = " << data.up << std::endl; tab(cout, depth+1); cout << "fov = " << data.fov << std::endl; tab(cout, depth); cout << "}" << std::endl; } void SceneGraph::AnimatedPerspectiveCameraNode::print(std::ostream& cout, int depth) { cout << "AnimatedPerspectiveCameraNode @ " << this << " { " << std::endl; if (name != "") { tab(cout, depth+1); cout << "name = " << name << std::endl; } for (size_t i=0; iprint(cout,depth+1); } tab(cout, depth); cout << "}" << std::endl; } void SceneGraph::TransformNode::print(std::ostream& cout, int depth) { cout << "TransformNode @ " << this << " { " << std::endl; tab(cout, depth+1); cout << "closed = " << closed << std::endl; tab(cout, depth+1); cout << "numTimeSteps = " << spaces.size() << std::endl; tab(cout, depth+1); cout << "child = "; child->print(cout,depth+1); tab(cout, depth); cout << "}" << std::endl; } void SceneGraph::MultiTransformNode::print(std::ostream& cout, int depth) { cout << "MultiTransformNode @ " << this << " { " << std::endl; tab(cout, depth+1); cout << "closed = " << closed << std::endl; tab(cout, depth+1); cout << "numInstances = " << spaces.size() << std::endl; if (spaces.size() > 0) { tab(cout, depth+1); cout << "numTimeSteps = " << spaces[0].size() << std::endl; } tab(cout, depth+1); cout << "child = "; child->print(cout,depth+1); tab(cout, depth); cout << "}" << std::endl; } void SceneGraph::GroupNode::print(std::ostream& cout, int depth) { cout << "GroupNode @ " << this << " { " << std::endl; tab(cout, depth+1); cout << "closed = " << closed << std::endl; for (size_t i=0; icalculateStatistics(stat); } } void SceneGraph::QuadMeshNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { stat.numQuadMeshes++; stat.numQuads += numPrimitives(); stat.numQuadBytes += numBytes(); material->calculateStatistics(stat); } } void SceneGraph::SubdivMeshNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { stat.numSubdivMeshes++; stat.numPatches += numPrimitives(); stat.numSubdivBytes += numBytes(); material->calculateStatistics(stat); } } void SceneGraph::HairSetNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { stat.numCurveSets++; stat.numCurves += numPrimitives(); stat.numCurveBytes += numBytes(); material->calculateStatistics(stat); } } void SceneGraph::PointSetNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { stat.numCurveSets++; stat.numCurves += numPrimitives(); stat.numCurveBytes += numBytes(); material->calculateStatistics(stat); } } void SceneGraph::GridMeshNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { stat.numGridMeshNodes++; stat.numGrids += numPrimitives(); stat.numGridBytes += numBytes(); material->calculateStatistics(stat); } } void SceneGraph::TransformNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { child->calculateStatistics(stat); stat.numTransformNodes++; if (child->indegree == 1) stat.numTransformedObjects++; if (spaces.size() > 1) child->calculateStatistics(stat); // break instance up when motion blur is used } } void SceneGraph::MultiTransformNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { child->calculateStatistics(stat); for (size_t i = 0; i < spaces.size(); ++i) { stat.numTransformNodes++; if (child->indegree == 1) stat.numTransformedObjects++; if (spaces[i].size() > 1) child->calculateStatistics(stat); // break instance up when motion blur is used } } } void SceneGraph::GroupNode::calculateStatistics(Statistics& stat) { indegree++; if (indegree == 1) { for (auto& c : children) c->calculateStatistics(stat); } } SceneGraph::Statistics SceneGraph::calculateStatistics(Ref node) { SceneGraph::Statistics stat; node->calculateStatistics(stat); node->resetInDegree(); return stat; } void SceneGraph::Statistics::print() { std::cout << " # transform nodes : " << numTransformNodes << std::endl; std::cout << " # objects : " << numTransformedObjects << std::endl; std::cout << " # triangle meshes : " << numTriangleMeshes << " ( " << 1E-6*numTriangleBytes << " MB )" << std::endl; std::cout << " # triangles : " << numTriangles << std::endl; std::cout << " # quad meshes : " << numQuadMeshes << " ( " << 1E-6*numQuadBytes << " MB )" << std::endl; std::cout << " # quads : " << numQuads << std::endl; std::cout << " # subdiv meshes : " << numSubdivMeshes << " ( " << 1E-6*numSubdivBytes << " MB )" << std::endl; std::cout << " # patches : " << numPatches << std::endl; std::cout << " # curve sets : " << numCurveSets << " ( " << 1E-6*numCurveBytes << " MB )" << std::endl; std::cout << " # curves : " << numCurves << std::endl; std::cout << " # grid meshes : " << numGridMeshNodes << " ( " << 1E-6*numGridBytes << " MB )" << std::endl; std::cout << " # grids : " << numGrids << std::endl; std::cout << " # point sets : " << numPointSets << " ( " << 1E-6*numPointBytes << " MB )" << std::endl; std::cout << " # points : " << numPoints << std::endl; std::cout << " # lights : " << numLights << std::endl; std::cout << " # cameras : " << numCameras << std::endl; std::cout << " # materials : " << numMaterials << std::endl; } void SceneGraph::Node::calculateInDegree() { indegree++; } void SceneGraph::TriangleMeshNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::QuadMeshNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::SubdivMeshNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::HairSetNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::PointSetNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::GridMeshNode::calculateInDegree() { indegree++; if (indegree == 1) material->calculateInDegree(); } void SceneGraph::TransformNode::calculateInDegree() { indegree++; if (indegree == 1) { child->calculateInDegree(); if (spaces.size() > 1) child->calculateInDegree(); // break instance up when motion blur is used } } void SceneGraph::MultiTransformNode::calculateInDegree() { indegree++; if (indegree == 1) { child->calculateInDegree(); for (size_t i = 0; i < spaces.size(); ++i) if (spaces[i].size() > 1) child->calculateInDegree(); // break instance up when motion blur is used } } void SceneGraph::GroupNode::calculateInDegree() { indegree++; if (indegree == 1) { for (auto& c : children) c->calculateInDegree(); } } bool SceneGraph::Node::calculateClosed(bool group_instancing) { assert(indegree); closed = true; hasLightOrCamera = false; return indegree == 1; } bool SceneGraph::LightNode::calculateClosed(bool group_instancing) { assert(indegree); closed = true; hasLightOrCamera = true; return indegree == 1; } bool SceneGraph::PerspectiveCameraNode::calculateClosed(bool group_instancing) { assert(indegree); closed = true; hasLightOrCamera = true; return indegree == 1; } bool SceneGraph::AnimatedPerspectiveCameraNode::calculateClosed(bool group_instancing) { assert(indegree); closed = true; hasLightOrCamera = true; return indegree == 1; } bool SceneGraph::TransformNode::calculateClosed(bool group_instancing) { assert(indegree); if (!closed) { closed = group_instancing; closed &= child->calculateClosed(group_instancing); hasLightOrCamera = child->hasLightOrCamera; } return closed && (indegree == 1); } bool SceneGraph::MultiTransformNode::calculateClosed(bool group_instancing) { assert(indegree); if (!closed) { closed = group_instancing; closed &= child->calculateClosed(group_instancing); hasLightOrCamera = child->hasLightOrCamera; } return closed && (indegree == 1); } bool SceneGraph::GroupNode::calculateClosed(bool group_instancing) { assert(indegree); if (!closed) { closed = group_instancing; hasLightOrCamera = false; for (auto& c : children) { closed &= c->calculateClosed(group_instancing); hasLightOrCamera |= c->hasLightOrCamera; } } return closed && (indegree == 1); } void SceneGraph::Node::resetInDegree() { closed = false; indegree--; } void SceneGraph::TriangleMeshNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::QuadMeshNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::SubdivMeshNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::HairSetNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::PointSetNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::GridMeshNode::resetInDegree() { closed = false; if (indegree == 1) material->resetInDegree(); indegree--; } void SceneGraph::TransformNode::resetInDegree() { closed = false; if (indegree == 1) { child->resetInDegree(); if (spaces.size() > 1) child->resetInDegree(); // break instance up when motion blur is used } indegree--; } void SceneGraph::MultiTransformNode::resetInDegree() { closed = false; if (indegree == 1) { child->resetInDegree(); if (spaces.size() > 1) child->resetInDegree(); // break instance up when motion blur is used } indegree--; } void SceneGraph::GroupNode::resetInDegree() { closed = false; if (indegree == 1) { for (auto& c : children) c->resetInDegree(); } indegree--; } void SceneGraph::TriangleMeshNode::verify() const { const size_t N = numVertices(); if (normals.size() && normals.size() != positions.size()) THROW_RUNTIME_ERROR("incompatible number of time steps"); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); for (const auto& n : normals) if (n.size() && n.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); if (texcoords.size() && texcoords.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); for (auto& tri : triangles) { if (size_t(tri.v0) >= N || size_t(tri.v1) >= N || size_t(tri.v2) >= N) THROW_RUNTIME_ERROR("invalid triangle"); } } void SceneGraph::QuadMeshNode::verify() const { const size_t N = numVertices(); if (normals.size() && normals.size() != positions.size()) THROW_RUNTIME_ERROR("incompatible number of time steps"); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); for (const auto& n : normals) if (n.size() && n.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); if (texcoords.size() && texcoords.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); for (auto& quad : quads) { if (size_t(quad.v0) >= N || size_t(quad.v1) >= N || size_t(quad.v2) >= N || size_t(quad.v3) >= N) THROW_RUNTIME_ERROR("invalid quad"); } } void SceneGraph::GridMeshNode::verify() const { const size_t N = numVertices(); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); for (auto& grid : grids) { if (size_t(grid.startVtx) >= N || size_t(grid.lineStride) >= N || size_t(grid.resX) >= 0x7fff || size_t(grid.resY) >= 0x7fff) THROW_RUNTIME_ERROR("invalid grid"); } } void SceneGraph::SubdivMeshNode::verify() const { const size_t N = numPositions(); if (normals.size() && normals.size() != positions.size()) THROW_RUNTIME_ERROR("incompatible number of time steps"); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible position array sizes"); for (auto i : position_indices) if (size_t(i) >= N) THROW_RUNTIME_ERROR("invalid position index array"); if (normal_indices.size()) for (auto i : normal_indices) if (size_t(i) >= normals[0].size()) THROW_RUNTIME_ERROR("invalid normal index array"); for (auto i : texcoord_indices) if (size_t(i) >= texcoords.size()) THROW_RUNTIME_ERROR("invalid texcoord index array"); for (auto i : holes) if (size_t(i) >= verticesPerFace.size()) THROW_RUNTIME_ERROR("invalid hole index array"); for (auto& crease : edge_creases) if (max(size_t(crease.x),size_t(crease.y)) >= N) THROW_RUNTIME_ERROR("invalid edge crease array"); if (edge_crease_weights.size() != edge_creases.size()) THROW_RUNTIME_ERROR("invalid edge crease weight array"); for (auto crease : vertex_creases) if (size_t(crease) >= N) THROW_RUNTIME_ERROR("invalid vertex crease array"); if (vertex_crease_weights.size() != vertex_creases.size()) THROW_RUNTIME_ERROR("invalid vertex crease weight array"); } void SceneGraph::HairSetNode::verify() const { const size_t N = numVertices(); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); if (type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE || type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE || type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE || type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE) { if (!normals.size()) THROW_RUNTIME_ERROR("normal array required for oriented curve"); for (const auto& n : normals) if (n.size() != N) { THROW_RUNTIME_ERROR("incompatible normal array size"); } } else { if (normals.size()) THROW_RUNTIME_ERROR("normal array not supported for this geometry type"); } if (type == RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE || type == RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE || type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE) { for (const auto& t : tangents) if (t.size() != N) THROW_RUNTIME_ERROR("incompatible tangent array size"); } else { if (tangents.size()) THROW_RUNTIME_ERROR("tangent array not supported for this geometry type"); } if (type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE) { if (!dnormals.size()) THROW_RUNTIME_ERROR("normal derivative array required for oriented hermite curve"); for (const auto& n : dnormals) if (n.size() != N) THROW_RUNTIME_ERROR("incompatible normal derivative array size"); } else { if (dnormals.size()) THROW_RUNTIME_ERROR("normal derivative array not supported for this geometry type"); } if (type == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE || type == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE || type == RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE || //type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_LINEAR_CURVE || type == RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE || type == RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE || type == RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE) { for (auto& hair : hairs) if (size_t(hair.vertex+1) >= N) THROW_RUNTIME_ERROR("invalid hair"); } else { for (auto& hair : hairs) if (size_t(hair.vertex+3) >= N) THROW_RUNTIME_ERROR("invalid hair"); } if (flags.size() != 0 && flags.size() != hairs.size()) THROW_RUNTIME_ERROR("size of flags array does not match size of curve array"); } void SceneGraph::PointSetNode::verify() const { const size_t N = numVertices(); for (const auto& p : positions) if (p.size() != N) THROW_RUNTIME_ERROR("incompatible vertex array sizes"); if (type == RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT) { if (!normals.size()) THROW_RUNTIME_ERROR("normal array required for oriented disc"); for (const auto& n : normals) if (n.size() != N) THROW_RUNTIME_ERROR("incompatible normal array size"); } else { if (normals.size()) THROW_RUNTIME_ERROR("normal array not supported for this geometry type"); } } avector bspline_to_bezier_helper(const std::vector& indices, const avector& positions) { avector positions_o; positions_o.resize(4*indices.size()); for (size_t i=0; i bezier_to_bspline_helper(const std::vector& indices, const avector& positions) { avector positions_o; positions_o.resize(4*indices.size()); for (size_t i=0; i,avector> bezier_to_hermite_helper(const std::vector& indices, const avector& positions) { avector positions_o; positions_o.resize(2*indices.size()); avector tangents_o; tangents_o.resize(2*indices.size()); for (size_t i=0; i>& in, ssize_t ipos, std::vector>& out, ssize_t opos) { if (opos < 0) return false; for (ssize_t i=ipos, j=opos; i 0.01f*(vfloat4)max(abs(in[k][i]),abs(out[k][j])).m128)) return false; } } return true; } void SceneGraph::HairSetNode::compact_vertices() { std::vector> positions_o(positions.size()); for (size_t i=0; i node0, Ref node1) { if (node0 == node1) return; if (Ref xfmNode0 = node0.dynamicCast()) { if (Ref xfmNode1 = node1.dynamicCast()) { xfmNode0->spaces.add(xfmNode1->spaces); extend_animation(xfmNode0->child, xfmNode1->child); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref groupNode0 = node0.dynamicCast()) { if (Ref groupNode1 = node1.dynamicCast()) { if (groupNode0->children.size() != groupNode1->children.size()) THROW_RUNTIME_ERROR("incompatible scene graph"); for (size_t i=0; ichildren.size(); i++) extend_animation(groupNode0->children[i],groupNode1->children[i]); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref mesh0 = node0.dynamicCast()) { if (Ref mesh1 = node1.dynamicCast()) { if (mesh0->numVertices() != mesh1->numVertices()) THROW_RUNTIME_ERROR("incompatible scene graph"); for (auto& p : mesh1->positions) mesh0->positions.push_back(std::move(p)); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref mesh0 = node0.dynamicCast()) { if (Ref mesh1 = node1.dynamicCast()) { if (mesh0->numVertices() != mesh1->numVertices()) THROW_RUNTIME_ERROR("incompatible scene graph"); for (auto& p : mesh1->positions) mesh0->positions.push_back(std::move(p)); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref mesh0 = node0.dynamicCast()) { if (Ref mesh1 = node1.dynamicCast()) { if (mesh0->numVertices() != mesh1->numVertices()) THROW_RUNTIME_ERROR("incompatible scene graph"); for (auto& p : mesh1->positions) mesh0->positions.push_back(std::move(p)); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref mesh0 = node0.dynamicCast()) { if (Ref mesh1 = node1.dynamicCast()) { if (mesh0->numVertices() != mesh1->numVertices()) THROW_RUNTIME_ERROR("incompatible scene graph"); for (auto& p : mesh1->positions) mesh0->positions.push_back(std::move(p)); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } else if (Ref mesh0 = node0.dynamicCast()) { if (Ref mesh1 = node1.dynamicCast()) { if (mesh0->numPositions() != mesh1->numPositions()) THROW_RUNTIME_ERROR("incompatible scene graph"); if (mesh0->verticesPerFace != mesh1->verticesPerFace) THROW_RUNTIME_ERROR("incompatible scene graph"); for (auto& p : mesh1->positions) mesh0->positions.push_back(std::move(p)); } else THROW_RUNTIME_ERROR("incompatible scene graph"); } } void SceneGraph::optimize_animation(Ref node) { if (Ref xfmNode = node.dynamicCast()) optimize_animation(xfmNode->child); else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) optimize_animation(child); } else if (Ref mesh = node.dynamicCast()) { bool equal = true; for (size_t i=1; inumTimeSteps(); i++) equal &= mesh->positions[0] == mesh->positions[i]; if (equal) mesh->positions.resize(1); } else if (Ref mesh = node.dynamicCast()) { bool equal = true; for (size_t i=1; inumTimeSteps(); i++) equal &= mesh->positions[0] == mesh->positions[i]; if (equal) mesh->positions.resize(1); } else if (Ref mesh = node.dynamicCast()) { bool equal = true; for (size_t i=1; inumTimeSteps(); i++) equal &= mesh->positions[0] == mesh->positions[i]; if (equal) mesh->positions.resize(1); } else if (Ref mesh = node.dynamicCast()) { bool equal = true; for (size_t i=1; inumTimeSteps(); i++) equal &= mesh->positions[0] == mesh->positions[i]; if (equal) mesh->positions.resize(1); } else if (Ref mesh = node.dynamicCast()) { bool equal = true; for (size_t i=1; inumTimeSteps(); i++) equal &= mesh->positions[0] == mesh->positions[i]; if (equal) mesh->positions.resize(1); } } void SceneGraph::set_motion_vector(Ref node, const Vec3fa& dP) { if (Ref xfmNode = node.dynamicCast()) { set_motion_vector(xfmNode->child, dP); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) set_motion_vector(groupNode->children[i],dP); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+dP); mesh->positions.push_back(std::move(positions1)); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+dP); mesh->positions.push_back(std::move(positions1)); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+dP); mesh->positions.push_back(std::move(positions1)); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+Vec3ff(dP,0.0f)); mesh->positions.push_back(std::move(positions1)); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+Vec3ff(dP,0.0f)); mesh->positions.push_back(std::move(positions1)); if (mesh->normals.size()) mesh->normals.push_back(mesh->normals[0]); } else if (Ref mesh = node.dynamicCast()) { avector positions1; for (auto& P : mesh->positions.back()) positions1.push_back(P+dP); mesh->positions.push_back(std::move(positions1)); } } void SceneGraph::set_motion_vector(Ref node, const avector& motion_vector) { if (Ref xfmNode = node.dynamicCast()) { set_motion_vector(xfmNode->child,motion_vector); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) set_motion_vector(groupNode->children[i],motion_vector); } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } if (mesh->normals.size()) { for (size_t t=1; tnormals.push_back(mesh->normals[0]); } } else if (Ref mesh = node.dynamicCast()) { avector positions = std::move(mesh->positions[0]); mesh->positions.clear(); for (size_t t=0; t tpositions(positions.size()); for (size_t i=0; ipositions.push_back(std::move(tpositions)); } } } void SceneGraph::resize_randomly(RandomSampler& sampler, Ref node, const size_t N) { if (Ref xfmNode = node.dynamicCast()) { resize_randomly(sampler,xfmNode->child, N); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) resize_randomly(sampler,groupNode->children[i],N); } else if (Ref mesh = node.dynamicCast()) { if (!mesh->triangles.size()) return; for (size_t i=0; itriangles.size(),N)); if (i < mesh->triangles.size()) std::swap(mesh->triangles[i],mesh->triangles[j]); else mesh->triangles.push_back(mesh->triangles[j]); } } else if (Ref mesh = node.dynamicCast()) { if (!mesh->quads.size()) return; for (size_t i=0; iquads.size(),N)); if (i < mesh->quads.size()) std::swap(mesh->quads[i],mesh->quads[j]); else mesh->quads.push_back(mesh->quads[j]); } } else if (Ref mesh = node.dynamicCast()) { if (!mesh->hairs.size()) return; for (size_t i=0; ihairs.size(),N)); if (i < mesh->hairs.size()) std::swap(mesh->hairs[i],mesh->hairs[j]); else mesh->hairs.push_back(mesh->hairs[j]); } } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size() <= N) return; mesh->positions.resize(N); } else if (Ref mesh = node.dynamicCast()) { if (mesh->verticesPerFace.size() <= N) return; mesh->verticesPerFace.resize(N); } } void SceneGraph::set_time_range(Ref node, const BBox1f& time_range) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->spaces.time_range = time_range; } else if (Ref xfmNode = node.dynamicCast()) { for (size_t i = 0; i < xfmNode->spaces.size(); ++i) xfmNode->spaces[i].time_range = time_range; } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) set_time_range(groupNode->children[i],time_range); } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } else if (Ref mesh = node.dynamicCast()) { mesh->time_range = time_range; } } std::pair quad_index2(int p, int a0, int a1, int b0, int b1) { if (b0 == a0) return std::make_pair(p-1,b1); else if (b0 == a1) return std::make_pair(p+0,b1); else if (b1 == a0) return std::make_pair(p-1,b0); else if (b1 == a1) return std::make_pair(p+0,b0); else return std::make_pair(0,-1); } std::pair quad_index3(int a0, int a1, int a2, int b0, int b1, int b2) { if (b0 == a0) return quad_index2(0,a2,a1,b1,b2); else if (b0 == a1) return quad_index2(1,a0,a2,b1,b2); else if (b0 == a2) return quad_index2(2,a1,a0,b1,b2); else if (b1 == a0) return quad_index2(0,a2,a1,b0,b2); else if (b1 == a1) return quad_index2(1,a0,a2,b0,b2); else if (b1 == a2) return quad_index2(2,a1,a0,b0,b2); else if (b2 == a0) return quad_index2(0,a2,a1,b0,b1); else if (b2 == a1) return quad_index2(1,a0,a2,b0,b1); else if (b2 == a2) return quad_index2(2,a1,a0,b0,b1); else return std::make_pair(0,-1); } Ref SceneGraph::convert_triangles_to_quads ( Ref tmesh ) { Ref qmesh = new SceneGraph::QuadMeshNode(tmesh->material,tmesh->time_range,0); for (auto& p : tmesh->positions) qmesh->positions.push_back(p); qmesh->normals = tmesh->normals; qmesh->texcoords = tmesh->texcoords; for (size_t i=0; itriangles.size(); i++) { const int a0 = tmesh->triangles[i+0].v0; const int a1 = tmesh->triangles[i+0].v1; const int a2 = tmesh->triangles[i+0].v2; if (i+1 == tmesh->triangles.size()) { qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a0,a1,a2,a2)); continue; } const int b0 = tmesh->triangles[i+1].v0; const int b1 = tmesh->triangles[i+1].v1; const int b2 = tmesh->triangles[i+1].v2; const std::pair q = quad_index3(a0,a1,a2,b0,b1,b2); const int a3 = q.second; if (a3 == -1) { qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a0,a1,a2,a2)); continue; } if (q.first == -1) qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a1,a2,a3,a0)); else if (q.first == 0) qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a3,a1,a2,a0)); else if (q.first == 1) qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a0,a1,a3,a2)); else if (q.first == 2) qmesh->quads.push_back(SceneGraph::QuadMeshNode::Quad(a1,a2,a3,a0)); i++; } return qmesh.dynamicCast(); } Ref SceneGraph::convert_triangles_to_quads(Ref node, float prop) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_triangles_to_quads(xfmNode->child,prop); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_triangles_to_quads(xfmNode->child,prop); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_triangles_to_quads(groupNode->children[i],prop); } else if (Ref tmesh = node.dynamicCast()) { if (random() <= prop) return convert_triangles_to_quads(tmesh); else return node; } return node; } Ref SceneGraph::convert_quads_to_grids ( Ref qmesh , const unsigned int resX, const unsigned int resY ) { const size_t timeSteps = qmesh->positions.size(); Ref gmesh = new SceneGraph::GridMeshNode(qmesh->material,qmesh->time_range,timeSteps); std::vector& quads = qmesh->quads; for (size_t i=0;ipositions[0].size(); const unsigned int lineStride = resX; for (size_t t=0;tpositions[t][quads[i].v0]; const SceneGraph::GridMeshNode::Vertex v01 = qmesh->positions[t][quads[i].v1]; const SceneGraph::GridMeshNode::Vertex v10 = qmesh->positions[t][quads[i].v3]; const SceneGraph::GridMeshNode::Vertex v11 = qmesh->positions[t][quads[i].v2]; for (unsigned int y=0; ypositions[t].push_back( vtx ); } } } assert(startVtx + resX * resY == gmesh->positions[0].size()); gmesh->grids.push_back(SceneGraph::GridMeshNode::Grid(startVtx,lineStride,resX,resY)); } return gmesh.dynamicCast(); } Ref SceneGraph::convert_quads_to_grids(Ref node, const unsigned int resX, const unsigned int resY ) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_quads_to_grids(xfmNode->child, resX, resY); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_quads_to_grids(xfmNode->child, resX, resY); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_quads_to_grids(groupNode->children[i], resX, resY); } else if (Ref qmesh = node.dynamicCast()) { return convert_quads_to_grids(qmesh, resX, resY); } return node; } Ref SceneGraph::convert_grids_to_quads ( Ref gmesh ) { Ref qmesh = new SceneGraph::QuadMeshNode(gmesh->material,gmesh->time_range,0); for (size_t i=0; inumPrimitives(); i++) { const unsigned int startVtx = gmesh->grids[i].startVtx; const unsigned int lineStride = gmesh->grids[i].lineStride; const unsigned int resX = gmesh->grids[i].resX; const unsigned int resY = gmesh->grids[i].resY; for (unsigned int y=0; yquads.push_back(SceneGraph::QuadMeshNode::Quad(a0,a1,a2,a3)); } } } const size_t timeSteps = gmesh->positions.size(); for (size_t t=0;tpositions.push_back(gmesh->positions[t]); return qmesh.dynamicCast(); } Ref SceneGraph::convert_grids_to_quads(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_grids_to_quads(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_grids_to_quads(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_grids_to_quads(groupNode->children[i]); } else if (Ref gmesh = node.dynamicCast()) { return convert_grids_to_quads(gmesh); } return node; } bool extend_grid(RTCGeometry geom, std::vector& visited, std::deque& left, std::deque& top, std::deque& right) { // top // | <---------- // | /\ . // | left | right // | | // \/ | /* test if all neighboring faces of top exist and are properly connected */ unsigned int prev_opposite_edge = -1; for (size_t i=0; i 0) { const unsigned int border0 = rtcGetGeometryOppositeHalfEdge(geom,0,rtcGetGeometryPreviousHalfEdge(geom,prev_opposite_edge)); const unsigned int border1 = rtcGetGeometryNextHalfEdge(geom,opposite_edge); if (border0 != border1) return false; } prev_opposite_edge = opposite_edge; } /* extend border edges */ for (size_t i=0; i& positions, size_t width, size_t height, unsigned int* indices, avector& vertices, unsigned int edgey) { // // | <---------- <---------- // | /\ | /\ . // | edgey | | | // | | | | // \/ | \/ | /* gather all rows */ size_t y=0; for (; y prev -> opposite moves to the next column (unless we reach the right end) */ edgex = rtcGetGeometryPreviousHalfEdge(geom,edgex); if (x+1 < width) { edgex = rtcGetGeometryPreviousHalfEdge(geom,edgex); edgex = rtcGetGeometryOppositeHalfEdge(geom,0,edgex); } } /* load rightmost vertex */ positions[y*(width+1)+x] = vertices[indices[edgex]]; /* next -> opposite -> next moves to next row (unless we reach the bottom) */ edgey = rtcGetGeometryNextHalfEdge(geom,edgey); if (y+1 < height) { edgey = rtcGetGeometryOppositeHalfEdge(geom,0,edgey); edgey = rtcGetGeometryNextHalfEdge(geom,edgey); } } /* special treatment for last row, edgy points from the bottom/left vertex to the right */ unsigned int edgex = edgey; for (size_t x=0; x opposite -> next moves to the next column (unless we reach the right end) */ edgex = rtcGetGeometryNextHalfEdge(geom,edgex); if (x+1 < width) { edgex = rtcGetGeometryOppositeHalfEdge(geom,0,edgex); edgex = rtcGetGeometryNextHalfEdge(geom,edgex); } } /* load rightmost vertex */ positions[height*(width+1)+width] = vertices[indices[edgex]]; } Ref SceneGraph::my_merge_quads_to_grids(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = my_merge_quads_to_grids(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = my_merge_quads_to_grids(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = my_merge_quads_to_grids(groupNode->children[i]); } else if (Ref qmesh = node.dynamicCast()) { Ref gmesh = new SceneGraph::GridMeshNode(qmesh->material,qmesh->time_range,qmesh->numTimeSteps()); std::vector visited; visited.resize(qmesh->numPrimitives()); for (size_t i=0; i faces(qmesh->numPrimitives()); for (size_t i=0; inumPrimitives()); rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, qmesh->quads.data(), 0, sizeof(unsigned int), 4*qmesh->numPrimitives()); rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, qmesh->positions[0].data(), 0, sizeof(Vec3fa), qmesh->numVertices()); rtcCommitGeometry(geom); /* iterate over mesh and collect all grids */ for (unsigned int i=0; inumPrimitives(); i++) { /* skip face if already added to some grid */ if (visited[i]) continue; visited[i] = true; /* initialize grid with start quad */ unsigned int edge = rtcGetGeometryFirstHalfEdge(geom,i); std::deque left, right, top, bottom; left.push_back(edge); edge = rtcGetGeometryNextHalfEdge(geom,edge); bottom.push_back(edge); edge = rtcGetGeometryNextHalfEdge(geom,edge); right.push_back(edge); edge = rtcGetGeometryNextHalfEdge(geom,edge); top.push_back(edge); edge = rtcGetGeometryNextHalfEdge(geom,edge); assert(edge == rtcGetGeometryFirstHalfEdge(geom,i)); /* extend grid unless no longer possible */ unsigned int width = 1; unsigned int height = 1; while (true) { const bool extended_top = extend_grid(geom,visited,left,top,right); const bool extended_right = extend_grid(geom,visited,top,right,bottom); const bool extended_bottom = extend_grid(geom,visited,right,bottom,left); const bool extended_left = extend_grid(geom,visited,bottom,left,top); width += extended_left + extended_right; height += extended_top + extended_bottom; if (!extended_top && !extended_right && !extended_bottom && !extended_left) break; if (width+2 > SceneGraph::GridMeshNode::GRID_RES_MAX) break; if (height+2 > SceneGraph::GridMeshNode::GRID_RES_MAX) break; } /* add new grid to grid mesh */ unsigned int startVertex = (unsigned int) gmesh->positions[0].size(); gmesh->grids.push_back(SceneGraph::GridMeshNode::Grid(startVertex,width+1,width+1,height+1)); /* gather all vertices of grid */ for (size_t t=0; tnumTimeSteps(); t++) { avector positions; positions.resize((width+1)*(height+1)); gather_grid(geom,positions,width,height,(unsigned int*)qmesh->quads.data(), qmesh->positions[t], left.front()); for (size_t i=0; ipositions[t].push_back(positions[i]); } } rtcReleaseGeometry(geom); return gmesh.dynamicCast(); } return node; } Ref SceneGraph::convert_quads_to_subdivs(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_quads_to_subdivs(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_quads_to_subdivs(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_quads_to_subdivs(groupNode->children[i]); } else if (Ref tmesh = node.dynamicCast()) { Ref smesh = new SceneGraph::SubdivMeshNode(tmesh->material,tmesh->time_range,0); for (auto& p : tmesh->positions) smesh->positions.push_back(p); for (size_t i=0; iquads.size(); i++) { smesh->position_indices.push_back(tmesh->quads[i].v0); smesh->position_indices.push_back(tmesh->quads[i].v1); smesh->position_indices.push_back(tmesh->quads[i].v2); if (tmesh->quads[i].v2 != tmesh->quads[i].v3) smesh->position_indices.push_back(tmesh->quads[i].v3); } smesh->normals = tmesh->normals; if (smesh->normals.size()) smesh->normal_indices = smesh->position_indices; smesh->texcoords = tmesh->texcoords; if (smesh->texcoords.size()) smesh->texcoord_indices = smesh->position_indices; for (size_t i=0; iquads.size(); i++) smesh->verticesPerFace.push_back(3 + (int)(tmesh->quads[i].v2 != tmesh->quads[i].v3)); return smesh.dynamicCast(); } return node; } Ref SceneGraph::convert_bezier_to_lines(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_bezier_to_lines(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_bezier_to_lines(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_bezier_to_lines(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { Ref lmesh = new SceneGraph::HairSetNode(RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, hmesh->material, hmesh->time_range, 0); for (auto& p : hmesh->positions) lmesh->positions.push_back(p); for (auto& hair : hmesh->hairs) { lmesh->hairs.push_back(SceneGraph::HairSetNode::Hair(hair.vertex+0,hair.id)); lmesh->hairs.push_back(SceneGraph::HairSetNode::Hair(hair.vertex+1,hair.id)); lmesh->hairs.push_back(SceneGraph::HairSetNode::Hair(hair.vertex+2,hair.id)); } return lmesh.dynamicCast(); } return node; } Ref SceneGraph::convert_flat_to_round_curves(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_flat_to_round_curves(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_flat_to_round_curves(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_flat_to_round_curves(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { if (hmesh->type == RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE; else if (hmesh->type == RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE; else if (hmesh->type == RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE; return hmesh.dynamicCast(); } return node; } Ref SceneGraph::convert_round_to_flat_curves(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_round_to_flat_curves(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { xfmNode->child = convert_round_to_flat_curves(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = convert_round_to_flat_curves(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { if (hmesh->type == RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE; else if (hmesh->type == RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE; else if (hmesh->type == RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE) hmesh->type = RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE; return hmesh.dynamicCast(); } return node; } Ref SceneGraph::convert_bezier_to_bspline(Ref node) { if (Ref xfmNode = node.dynamicCast()) { convert_bezier_to_bspline(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { convert_bezier_to_bspline(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) convert_bezier_to_bspline(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { hmesh->convert_bezier_to_bspline(); //hmesh->compact_vertices(); } return node; } Ref SceneGraph::convert_bspline_to_bezier(Ref node) { if (Ref xfmNode = node.dynamicCast()) { convert_bspline_to_bezier(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { convert_bspline_to_bezier(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) convert_bspline_to_bezier(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { hmesh->convert_bspline_to_bezier(); } return node; } Ref SceneGraph::convert_bezier_to_hermite(Ref node) { if (Ref xfmNode = node.dynamicCast()) { convert_bezier_to_hermite(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { convert_bezier_to_hermite(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) convert_bezier_to_hermite(groupNode->children[i]); } else if (Ref hmesh = node.dynamicCast()) { hmesh->convert_bezier_to_hermite(); //hmesh->compact_vertices(); } return node; } Ref SceneGraph::remove_mblur(Ref node, bool mblur) { if (Ref xfmNode = node.dynamicCast()) { if (mblur) { if (xfmNode->spaces.size() > 1) return nullptr; } else { if (xfmNode->spaces.size() > 1) return node; } xfmNode->child = remove_mblur(xfmNode->child, mblur); } else if (Ref xfmNode = node.dynamicCast()) { if (mblur) { if (xfmNode->spaces.size() == 0 || xfmNode->spaces[0].size() > 1) return nullptr; } else { if (xfmNode->spaces.size() > 0 && xfmNode->spaces[0].size() > 1) return node; } xfmNode->child = remove_mblur(xfmNode->child, mblur); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) groupNode->children[i] = remove_mblur(groupNode->children[i], mblur); } else if (Ref mesh = node.dynamicCast()) { if ((mesh->numTimeSteps() > 1) == mblur) return nullptr; } else if (Ref mesh = node.dynamicCast()) { if ((mesh->numTimeSteps() > 1) == mblur) return nullptr; } else if (Ref mesh = node.dynamicCast()) { if ((mesh->numTimeSteps() > 1) == mblur) return nullptr; } else if (Ref mesh = node.dynamicCast()) { if ((mesh->numTimeSteps() > 1) == mblur) return nullptr; } else if (Ref mesh = node.dynamicCast()) { if ((mesh->numTimeSteps() > 1) == mblur) return nullptr; } return node; } void SceneGraph::convert_mblur_to_nonmblur(Ref node) { if (Ref xfmNode = node.dynamicCast()) { xfmNode->spaces.spaces.resize(1); convert_mblur_to_nonmblur(xfmNode->child); } else if (Ref xfmNode = node.dynamicCast()) { for (size_t i = 0; i < xfmNode->spaces.size(); ++i) xfmNode->spaces[i].spaces.resize(1); convert_mblur_to_nonmblur(xfmNode->child); } else if (Ref groupNode = node.dynamicCast()) { for (size_t i=0; ichildren.size(); i++) convert_mblur_to_nonmblur(groupNode->children[i]); } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size()) mesh->positions.resize(1); if (mesh->normals.size()) mesh->normals.resize(1); } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size()) mesh->positions.resize(1); if (mesh->normals.size()) mesh->normals.resize(1); } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size()) mesh->positions.resize(1); if (mesh->normals.size()) mesh->normals.resize(1); if (mesh->tangents.size()) mesh->tangents.resize(1); if (mesh->dnormals.size()) mesh->dnormals.resize(1); } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size()) mesh->positions.resize(1); if (mesh->normals.size()) mesh->normals.resize(1); } else if (Ref mesh = node.dynamicCast()) { if (mesh->positions.size()) mesh->positions.resize(1); if (mesh->normals .size()) mesh->normals .resize(1); } else if (Ref mesh = node.dynamicCast()) { mesh->positions.resize(1); } } struct SceneGraphFlattener { Ref node; std::map,Ref> object_mapping; std::map unique_id; SceneGraphFlattener (Ref in, SceneGraph::InstancingMode instancing) { in->calculateInDegree(); in->calculateClosed(instancing == SceneGraph::INSTANCING_GROUP); std::vector> geometries; if (instancing != SceneGraph::INSTANCING_NONE) { if (instancing == SceneGraph::INSTANCING_FLATTENED ) convertFlattenedInstances(geometries,in); else if (instancing == SceneGraph::INSTANCING_MULTI_LEVEL) convertMultiLevelInstances(geometries,in); else convertInstances(geometries,in,one); convertLightsAndCameras(geometries,in,one); } else { convertGeometries(geometries,in,one); convertLightsAndCameras(geometries,in,one); } in->resetInDegree(); node = new SceneGraph::GroupNode(geometries); } std::string makeUniqueID(std::string id) { if (id == "") id = "camera"; std::map::iterator i = unique_id.find(id); if (i == unique_id.end()) { unique_id[id] = 0; return id; } else { int n = ++unique_id[id]; return id + "_" + toString(n); } } void convertLightsAndCameras(std::vector>& group, const Ref& node, const SceneGraph::Transformations& spaces) { if (!node->hasLightOrCamera) return; if (Ref xfmNode = node.dynamicCast()) { convertLightsAndCameras(group,xfmNode->child, spaces*xfmNode->spaces); } else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertLightsAndCameras(group,child,spaces); } else if (Ref lightNode = node.dynamicCast()) { if (spaces.size() != 1) throw std::runtime_error("animated lights cannot get instantiated with a transform animation"); group.push_back(lightNode->transform(spaces[0]).dynamicCast()); } else if (Ref lightNode = node.dynamicCast()) { if (spaces.size() == 1) group.push_back(lightNode->transform(spaces[0]).dynamicCast()); else { std::vector> lights(spaces.size()); for (size_t i=0; itransform(spaces[i]); group.push_back(new SceneGraph::AnimatedLightNode(std::move(lights),spaces.time_range)); } } else if (Ref cameraNode = node.dynamicCast()) { if (spaces.size() != 1) throw std::runtime_error("animated cameras cannot get instantiated with a transform animation"); group.push_back(new SceneGraph::AnimatedPerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name))); } else if (Ref cameraNode = node.dynamicCast()) { if (spaces.size() == 1) group.push_back(new SceneGraph::PerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name))); else { std::vector> cameras(spaces.size()); for (size_t i=0; iname))); } } } void convertGeometries(std::vector>& group, const Ref& node, const SceneGraph::Transformations& spaces) { if (Ref xfmNode = node.dynamicCast()) { convertGeometries(group,xfmNode->child, spaces*xfmNode->spaces); } else if (Ref xfmNode = node.dynamicCast()) { for (size_t i = 0; i < xfmNode->spaces.size(); ++i) convertGeometries(group,xfmNode->child, spaces*xfmNode->spaces[i]); } else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertGeometries(group,child,spaces); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::TriangleMeshNode(mesh,spaces)); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::QuadMeshNode(mesh,spaces)); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::GridMeshNode(mesh,spaces)); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::SubdivMeshNode(mesh,spaces)); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::HairSetNode(mesh,spaces)); } else if (Ref mesh = node.dynamicCast()) { group.push_back(new SceneGraph::PointSetNode(mesh,spaces)); } } Ref lookupGeometries(Ref node) { if (object_mapping.find(node) == object_mapping.end()) { std::vector> geometries; convertGeometries(geometries,node,one); object_mapping[node] = new SceneGraph::GroupNode(geometries); } return object_mapping[node]; } void convertInstances(std::vector>& group, const Ref& node, const std::vector& spaces) { if (node->isClosed()) { //if (group.size() % 10000 == 0) std::cout << "." << std::flush; group.push_back(new SceneGraph::MultiTransformNode(spaces,lookupGeometries(node))); } else if (Ref xfmNode = node.dynamicCast()) { for (size_t i = 0; i < spaces.size(); ++i) convertInstances(group,xfmNode->child, spaces[i]*xfmNode->spaces); } else if (Ref xfmNode = node.dynamicCast()) { convertInstances(group,xfmNode->child, spaces*xfmNode->spaces); } else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertInstances(group,child,spaces); } } void convertInstances(std::vector>& group, const Ref& node, const SceneGraph::Transformations& spaces) { if (node->isClosed()) { //if (group.size() % 10000 == 0) std::cout << "." << std::flush; group.push_back(new SceneGraph::TransformNode(spaces,lookupGeometries(node))); } else if (Ref xfmNode = node.dynamicCast()) { convertInstances(group,xfmNode->child, spaces*xfmNode->spaces); } else if (Ref xfmNode = node.dynamicCast()) { convertInstances(group,xfmNode->child, spaces*xfmNode->spaces); } else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertInstances(group,child,spaces); } } void convertMultiLevelInstances(std::vector>& group, const Ref& node) { if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertMultiLevelInstances(group,child); } else if (node.dynamicCast()) { group.push_back(node); } else if (node.dynamicCast()) { group.push_back(node); } else if (node.dynamicCast()) { group.push_back(node); } else if (node.dynamicCast()) { group.push_back(node); } else if (node.dynamicCast()) { group.push_back(node); } else if (node.dynamicCast()) { group.push_back(node); } else if (object_mapping.find(node) != object_mapping.end()) { group.push_back(object_mapping[node]); } else if (Ref xfmNode = node.dynamicCast()) { auto new_node = new SceneGraph::TransformNode(xfmNode->spaces,convertMultiLevelInstances(xfmNode->child)); object_mapping[node] = new_node; group.push_back(new_node); } else if (Ref xfmNode = node.dynamicCast()) { auto new_node = new SceneGraph::MultiTransformNode(xfmNode->spaces,convertMultiLevelInstances(xfmNode->child)); object_mapping[node] = new_node; group.push_back(new_node); } } Ref convertMultiLevelInstances(const Ref& node) { if (object_mapping.find(node) != object_mapping.end()) { return object_mapping[node]; } std::vector> group; convertMultiLevelInstances(group,node); auto new_node = new SceneGraph::GroupNode(group); object_mapping[node] = new_node; return new_node; } void convertFlattenedInstances(std::vector>& group, const Ref& node) { if (Ref xfmNode = node.dynamicCast()) { group.push_back(node); } else if (Ref groupNode = node.dynamicCast()) { for (const auto& child : groupNode->children) convertFlattenedInstances(group,child); } } }; Ref SceneGraph::flatten(Ref node, InstancingMode mode) { return SceneGraphFlattener(node,mode).node; } Ref SceneGraph::flatten(Ref node, SceneGraph::InstancingMode mode) { return flatten(node.dynamicCast(),mode).dynamicCast(); } }