// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "lights.h" #include "../../../include/embree4/rtcore.h" RTC_NAMESPACE_USE #include "../math/random_sampler.h" namespace embree { struct Material; namespace SceneGraph { struct Node; struct MaterialNode; struct Transformations; struct TriangleMeshNode; struct QuadMeshNode; struct GridMeshNode; Ref load(const FileName& fname, bool singleObject = false); void store(Ref root, const FileName& fname, bool embedTextures, bool referenceMaterials, bool binaryFormat); void extend_animation(Ref node0, Ref node1); void optimize_animation(Ref node0); void set_motion_vector(Ref node, const Vec3fa& dP); void set_motion_vector(Ref node, const avector& motion_vector); void set_time_range(Ref node, const BBox1f& time_range); void resize_randomly(RandomSampler& sampler, Ref node, const size_t N); Ref convert_triangles_to_quads(Ref node, float prop); Ref convert_triangles_to_quads( Ref tmesh); Ref convert_quads_to_subdivs(Ref node); Ref my_merge_quads_to_grids(Ref node); Ref convert_bezier_to_lines(Ref node); Ref convert_bezier_to_bspline(Ref node); Ref convert_bezier_to_hermite(Ref node); Ref convert_bspline_to_bezier(Ref node); Ref convert_flat_to_round_curves(Ref node); Ref convert_round_to_flat_curves(Ref node); Ref convert_quads_to_grids( Ref qmesh, const unsigned resX, const unsigned resY ); Ref convert_quads_to_grids( Ref node, const unsigned resX, const unsigned resY ); Ref convert_grids_to_quads( Ref gmesh); Ref convert_grids_to_quads( Ref node); Ref remove_mblur(Ref node, bool mblur); void convert_mblur_to_nonmblur(Ref node); extern void (*opaque_geometry_destruction)(void*); struct Statistics { Statistics () : numTriangleMeshes(0), numTriangles(0), numTriangleBytes(0), numQuadMeshes(0), numQuads(0), numQuadBytes(0), numSubdivMeshes(0), numPatches(0), numSubdivBytes(0), numCurveSets(0), numCurves(0), numCurveBytes(0), numGridMeshNodes(0), numGrids(0), numGridBytes(0), numPointSets(0), numPoints(0), numPointBytes(0), numTransformNodes(0), numTransformedObjects(0), numLights(0), numCameras(0), numMaterials(0) {} void print(); size_t numTriangleMeshes; size_t numTriangles; size_t numTriangleBytes; size_t numQuadMeshes; size_t numQuads; size_t numQuadBytes; size_t numSubdivMeshes; size_t numPatches; size_t numSubdivBytes; size_t numCurveSets; size_t numCurves; size_t numCurveBytes; size_t numGridMeshNodes; size_t numGrids; size_t numGridBytes; size_t numPointSets; size_t numPoints; size_t numPointBytes; size_t numTransformNodes; size_t numTransformedObjects; size_t numLights; size_t numCameras; size_t numMaterials; }; struct Node : public RefCount { Node (bool closed = false) : indegree(0), closed(closed), hasLightOrCamera(false), id(-1), geometry(nullptr) {} Node (const std::string& name) : name(name), indegree(0), closed(false), id(-1), geometry(nullptr) {} ~Node() { if (opaque_geometry_destruction) opaque_geometry_destruction(geometry); } /* prints scenegraph */ virtual void print(std::ostream& cout, int depth = 0) = 0; /* sets material */ virtual void setMaterial(Ref material) {}; /* calculates the number of parent nodes pointing to this node */ virtual void calculateInDegree(); /* calculates for each node if its subtree is closed, indegrees have to be calculated first */ virtual bool calculateClosed(bool group_instancing); /* resets the number of parent nodes pointing to this node */ virtual void resetInDegree(); /* calculates statistics */ virtual void calculateStatistics(Statistics& stat); /* checks if the node is closed */ __forceinline bool isClosed() const { return closed; } /* calculates bounding box of node */ virtual BBox3fa bounds() const { return empty; } virtual BBox3fa bounds(size_t i) const { return empty; } /* calculates linear bounding box of node */ virtual LBBox3fa lbounds() const { return empty; } virtual LBBox3fa lbounds(size_t i) const { return empty; } /* calculates number of primitives */ virtual size_t numPrimitives() const { return 0; } Ref set_motion_vector(const Vec3fa& dP) { SceneGraph::set_motion_vector(this,dP); return this; } Ref set_motion_vector(const avector& motion_vector) { SceneGraph::set_motion_vector(this,motion_vector); return this; } public: std::string fileName; // when set to some filename the exporter references this file std::string name; // name of this node size_t indegree; // number of nodes pointing to us bool closed; // determines if the subtree may represent an instance bool hasLightOrCamera; unsigned int id; void* geometry; }; struct Transformations { __forceinline Transformations() {} __forceinline Transformations(OneTy) : time_range(0.0f,1.0f) { spaces.push_back(one); } __forceinline Transformations( const BBox1f& time_range, size_t N ) : time_range(time_range), spaces(N) {} __forceinline Transformations(const AffineSpace3fa& space) : time_range(0.0f,1.0f) { spaces.push_back(space); } __forceinline Transformations(const AffineSpace3fa& space0, const AffineSpace3fa& space1) : time_range(0.0f,1.0f) { spaces.push_back(space0); spaces.push_back(space1); } __forceinline Transformations(const avector& spaces) : time_range(0.0f,1.0f), spaces(spaces) { assert(spaces.size()); } __forceinline size_t size() const { return spaces.size(); } __forceinline AffineSpace3ff& operator[] ( const size_t i ) { return spaces[i]; } __forceinline const AffineSpace3ff& operator[] ( const size_t i ) const { return spaces[i]; } BBox3fa bounds ( const BBox3fa& cbounds ) const { BBox3fa r = empty; for (size_t i=0; i bounds(spaces.size()); for (size_t i=0; i operator* ( const std::vector& a, const Transformations& b ) { std::vector result; for (size_t i = 0; i < a.size(); ++i) { result.push_back(a[i] * b); } return result; } friend __forceinline std::vector operator* ( const Transformations& a, const std::vector& b ) { return b * a; } friend __forceinline std::vector operator* ( const std::vector& a, const std::vector& b ) { if(a.size() != b.size()) THROW_RUNTIME_ERROR("number of transformations does not match"); std::vector result; for (size_t i = 0; i < a.size(); ++i) { result.push_back(a[i] * b[i]); } return result; } AffineSpace3ff interpolate (const float gtime) const { assert(time_range.lower == 0.0f && time_range.upper == 1.0f); if (spaces.size() == 1) return spaces[0]; /* calculate time segment itime and fractional time ftime */ const int time_segments = int(spaces.size()-1); const float time = gtime*float(time_segments); const int itime = clamp(int(floor(time)),0,time_segments-1); const float ftime = time - float(itime); return lerp(spaces[itime+0],spaces[itime+1],ftime); } public: BBox1f time_range; avector spaces; bool quaternion = false; }; template std::vector> transformMSMBlurBuffer(const std::vector>& positions_in, const Transformations& spaces) { std::vector> positions_out; const size_t num_time_steps = positions_in.size(); assert(num_time_steps); const size_t num_vertices = positions_in[0].size(); /* if we have only one set of vertices, use transformation to generate more vertex sets */ if (num_time_steps == 1) { for (size_t i=0; i verts(num_vertices); for (size_t j=0; j 1 ? float(t)/float(num_time_steps-1) : 0.0f; const AffineSpace3ff space = spaces.interpolate(time); avector verts(num_vertices); for (size_t i=0; i> transformMSMBlurVec3faBuffer(const std::vector>& positions_in, const Transformations& spaces) { std::vector> positions_out; const size_t num_time_steps = positions_in.size(); assert(num_time_steps); const size_t num_vertices = positions_in[0].size(); /* if we have only one set of vertices, use transformation to generate more vertex sets */ if (num_time_steps == 1) { for (size_t i=0; i verts(num_vertices); for (size_t j=0; j 1 ? float(t)/float(num_time_steps-1) : 0.0f; const AffineSpace3ff space = spaces.interpolate(time); avector verts(num_vertices); for (size_t i=0; i std::vector> transformMSMBlurVectorBuffer(const std::vector>& vectors_in, const Transformations& spaces) { if (vectors_in.size() == 0) return vectors_in; std::vector> vectors_out; const size_t num_time_steps = vectors_in.size(); const size_t num_vertices = vectors_in[0].size(); /* if we have only one set of vertices, use transformation to generate more vertex sets */ if (num_time_steps == 1) { for (size_t i=0; i vecs(num_vertices); for (size_t j=0; j 1 ? float(t)/float(num_time_steps-1) : 0.0f; const AffineSpace3ff space = spaces.interpolate(time); avector vecs(num_vertices); for (size_t i=0; i std::vector> transformMSMBlurVectorVec3faBuffer(const std::vector>& vectors_in, const Transformations& spaces) { if (vectors_in.size() == 0) return vectors_in; std::vector> vectors_out; const size_t num_time_steps = vectors_in.size(); const size_t num_vertices = vectors_in[0].size(); /* if we have only one set of vertices, use transformation to generate more vertex sets */ if (num_time_steps == 1) { for (size_t i=0; i vecs(num_vertices); for (size_t j=0; j 1 ? float(t)/float(num_time_steps-1) : 0.0f; const AffineSpace3ff space = spaces.interpolate(time); avector vecs(num_vertices); for (size_t i=0; i std::vector> transformMSMBlurNormalBuffer(const std::vector>& normals_in, const Transformations& spaces) { if (normals_in.size() == 0) return normals_in; std::vector> normals_out; const size_t num_time_steps = normals_in.size(); const size_t num_vertices = normals_in[0].size(); /* if we have only one set of vertices, use transformation to generate more vertex sets */ if (num_time_steps == 1) { for (size_t i=0; i norms(num_vertices); for (size_t j=0; j 1 ? float(t)/float(num_time_steps-1) : 0.0f; const AffineSpace3ff space = spaces.interpolate(time); avector norms(num_vertices); for (size_t i=0; i& other, const AffineSpace3fa& space, const std::string& id = "") : Node(id), data(other->data,space) {} virtual bool isAnimated() const { return false; } virtual PerspectiveCameraData get(float time) const { return data; } virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual bool calculateClosed(bool group_instancing); public: PerspectiveCameraData data; }; struct AnimatedPerspectiveCameraNode : public PerspectiveCameraNode { AnimatedPerspectiveCameraNode (std::vector>&& cameras, BBox1f time_range, const std::string& id = "") : time_range(time_range), cameras(cameras) {} AnimatedPerspectiveCameraNode (const Ref& other, const AffineSpace3fa& space, const std::string& id) : PerspectiveCameraNode(id), time_range(other->time_range) { cameras.resize(other->size()); for (size_t i=0; isize(); i++) cameras[i] = new PerspectiveCameraNode(other->cameras[i],space); } virtual bool isAnimated() const { return true; } virtual PerspectiveCameraData get(float time) const { time = frac((time-time_range.lower)/time_range.size()); time = (cameras.size()-1)*time; int itime = (int)floor(time); itime = min(max(itime,0),(int)cameras.size()-2); float ftime = time - (float)itime; return lerp(cameras[itime+0]->get(time), cameras[itime+1]->get(time), ftime); } virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual bool calculateClosed(bool group_instancing); size_t size() const { return cameras.size(); } public: BBox1f time_range; std::vector> cameras; }; struct TransformNode : public Node { ALIGNED_STRUCT_(16); TransformNode (const AffineSpace3fa& xfm, const Ref& child) : spaces((AffineSpace3ff)xfm), child(child) {} TransformNode (const AffineSpace3fa& xfm0, const AffineSpace3fa& xfm1, const Ref& child) : spaces((AffineSpace3ff)xfm0,(AffineSpace3ff)xfm1), child(child) {} TransformNode (const avector& spaces, const Ref& child) : spaces(spaces), child(child) {} TransformNode(const Transformations& spaces, const Ref& child) : spaces(spaces), child(child) {} virtual void setMaterial(Ref material) { child->setMaterial(material); } virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual void calculateInDegree(); virtual bool calculateClosed(bool group_instancing); virtual void resetInDegree(); virtual BBox3fa bounds() const { return spaces.bounds(child->bounds()); } virtual LBBox3fa lbounds() const { return spaces.lbounds(child->lbounds()); } virtual size_t numPrimitives() const { return child->numPrimitives(); } virtual AffineSpace3ff get(float time) const { if (spaces.size() <= 1) return spaces[0]; int numTimeSteps = spaces.size(); BBox1f time_range = spaces.time_range; time = frac((time-time_range.lower)/time_range.size()); time = (numTimeSteps-1)*time; int itime = (int)floor(time); itime = min(max(itime,0),(int)numTimeSteps-2); float ftime = time - (float)itime; const AffineSpace3ff xfm0 = spaces[itime+0]; const AffineSpace3ff xfm1 = spaces[itime+1]; const AffineSpace3ff xfm = lerp(xfm0,xfm1,ftime); return xfm; } public: Transformations spaces; Ref child; }; struct MultiTransformNode : public Node { ALIGNED_STRUCT_(16); MultiTransformNode (const avector& xfm, const Ref& child) : child(child) { for (const AffineSpace3fa& space : xfm) { spaces.push_back(Transformations(space)); } } MultiTransformNode (const avector& xfm0, const avector& xfm1, const Ref& child) : child(child) { assert(xfm0.size() == xfm1.size()); for (size_t i = 0; i < xfm0.size(); ++i) { spaces.push_back(Transformations(xfm0[i], xfm1[i])); } } MultiTransformNode (const avector>& spaces_in, const Ref& child) : child(child) { assert(spaces_in.size() > 0); const size_t time_steps = spaces_in.size(); const size_t array_size = spaces_in[0].size(); for (size_t i = 0; i < array_size; ++i) { avector s; for (size_t j = 0; j < time_steps; ++j) { s.push_back(spaces_in[j][i]); } spaces.push_back(Transformations(s)); } } MultiTransformNode(const std::vector& spaces, const Ref& child) : spaces(spaces), child(child) {} virtual void setMaterial(Ref material) { child->setMaterial(material); } virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual void calculateInDegree(); virtual bool calculateClosed(bool group_instancing); virtual void resetInDegree(); virtual BBox3fa bounds(size_t i) const { return spaces[i].bounds(child->bounds()); } virtual LBBox3fa lbounds(size_t i) const { return spaces[i].lbounds(child->lbounds()); } virtual size_t numPrimitives() const { return child->numPrimitives(); } virtual AffineSpace3ff get(size_t i, float time) const { if (spaces[i].size() <= 1) return spaces[i][0]; int numTimeSteps = spaces[i].size(); BBox1f time_range = spaces[i].time_range; time = frac((time-time_range.lower)/time_range.size()); time = (numTimeSteps-1)*time; int itime = (int)floor(time); itime = min(max(itime,0),(int)numTimeSteps-2); float ftime = time - (float)itime; const AffineSpace3ff xfm0 = spaces[i][itime+0]; const AffineSpace3ff xfm1 = spaces[i][itime+1]; const AffineSpace3ff xfm = lerp(xfm0,xfm1,ftime); return xfm; } public: std::vector spaces; Ref child; }; struct GroupNode : public Node { GroupNode (const size_t N = 0) { children.resize(N); } GroupNode (std::vector>& children) : children(children) {} size_t size() const { return children.size(); } void add(const Ref& node) { if (node) children.push_back(node); } void set(const size_t i, const Ref& node) { children[i] = node; } Ref child ( size_t i ) const { return children[i]; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (auto& c : children) b.extend(c->bounds()); return b; } virtual LBBox3fa lbounds() const { LBBox3fa b = empty; for (auto& c : children) b.extend(c->lbounds()); return b; } virtual size_t numPrimitives() const { size_t n = 0; for (auto& child : children) n += child->numPrimitives(); return n; } void triangles_to_quads(float prop = inf) { for (size_t i=0; i material) { for (auto& child : children) child->setMaterial(material); } virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual void calculateInDegree(); virtual bool calculateClosed(bool group_instancing); virtual void resetInDegree(); public: std::vector > children; }; struct LightNode : public Node { virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); virtual bool calculateClosed(bool group_instancing); virtual LightType getType() const = 0; virtual Ref transform(const AffineSpace3fa& space) const = 0; virtual Ref lerp(const Ref& light1_in, float f) const = 0; virtual Ref get(float time) const = 0; }; template struct LightNodeImpl : public LightNode { ALIGNED_STRUCT_(16); LightNodeImpl (const Light& light) : light(light) {} virtual LightType getType() const { return light.getType(); } virtual Ref transform(const AffineSpace3fa& space) const { return new LightNodeImpl(light.transform(space)); } virtual Ref get(float time) const { return (LightNode*) this; } virtual Ref lerp(const Ref& light1_in, float f) const { const Ref> light1 = light1_in.dynamicCast>(); assert(light1); return new LightNodeImpl(Light::lerp(light,light1->light,f)); } Light light; }; struct AnimatedLightNode : public LightNode { AnimatedLightNode (const std::vector>&& lights, BBox1f time_range) : lights(lights), time_range(time_range) {} virtual LightType getType() const { return lights[0]->getType(); } virtual Ref transform(const AffineSpace3fa& space) const { std::vector> xfm_lights(lights.size()); for (size_t i=0; itransform(space); return new AnimatedLightNode(std::move(xfm_lights), time_range); } virtual Ref get(float time) const { time = frac((time-time_range.lower)/time_range.size()); time = (lights.size()-1)*time; int itime = (int)floor(time); itime = min(max(itime,0),(int)lights.size()-2); float ftime = time - (float)itime; Ref light0 = lights[itime+0]->get(time); Ref light1 = lights[itime+1]->get(time); return light0->lerp(light1,ftime); } virtual Ref lerp(const Ref& light1_in, float f) const { assert(false); return nullptr; } public: std::vector> lights; BBox1f time_range; }; struct MaterialNode : public Node { ALIGNED_STRUCT_USM_(16) MaterialNode(const std::string& name = "") : Node(name) {} virtual Material* material() = 0; virtual void print(std::ostream& cout, int depth); virtual void calculateStatistics(Statistics& stat); }; /*! Mesh. */ struct TriangleMeshNode : public Node { typedef Vec3fa Vertex; struct Triangle { public: Triangle() {} Triangle (unsigned v0, unsigned v1, unsigned v2) : v0(v0), v1(v1), v2(v2) {} public: unsigned v0, v1, v2; }; public: TriangleMeshNode (const avector& positions_in, const avector& normals_in, const std::vector& texcoords, const std::vector& triangles, Ref material) : Node(true), time_range(0.0f,1.0f), texcoords(texcoords), triangles(triangles), material(material) { positions.push_back(positions_in); normals.push_back(normals_in); } TriangleMeshNode (Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0) : Node(true), time_range(time_range), material(material) { for (size_t i=0; i()); } TriangleMeshNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), positions(transformMSMBlurVec3faBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), texcoords(imesh->texcoords), triangles(imesh->triangles), material(imesh->material) {} virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; std::vector> normals; std::vector texcoords; std::vector triangles; Ref material; }; /*! Mesh. */ struct QuadMeshNode : public Node { typedef Vec3fa Vertex; struct Quad { public: Quad() {} Quad (unsigned int v0, unsigned int v1, unsigned int v2, unsigned int v3) : v0(v0), v1(v1), v2(v2), v3(v3) {} public: unsigned int v0, v1, v2, v3; }; public: QuadMeshNode (Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0 ) : Node(true), time_range(time_range), material(material) { for (size_t i=0; i()); } QuadMeshNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), positions(transformMSMBlurVec3faBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), texcoords(imesh->texcoords), quads(imesh->quads), material(imesh->material) {} virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; std::vector> normals; std::vector texcoords; std::vector quads; Ref material; }; /*! Subdivision Mesh. */ struct SubdivMeshNode : public Node { typedef Vec3fa Vertex; SubdivMeshNode (Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0) : Node(true), time_range(time_range), position_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY), normal_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY), texcoord_subdiv_mode(RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY), material(material), tessellationRate(2.0f) { for (size_t i=0; i()); zero_pad_arrays(); } SubdivMeshNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), positions(transformMSMBlurVec3faBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), texcoords(imesh->texcoords), position_indices(imesh->position_indices), normal_indices(imesh->normal_indices), texcoord_indices(imesh->texcoord_indices), position_subdiv_mode(imesh->position_subdiv_mode), normal_subdiv_mode(imesh->normal_subdiv_mode), texcoord_subdiv_mode(imesh->texcoord_subdiv_mode), verticesPerFace(imesh->verticesPerFace), holes(imesh->holes), edge_creases(imesh->edge_creases), edge_crease_weights(imesh->edge_crease_weights), vertex_creases(imesh->vertex_creases), vertex_crease_weights(imesh->vertex_crease_weights), material(imesh->material), tessellationRate(imesh->tessellationRate) { zero_pad_arrays(); } void zero_pad_arrays() { if (texcoords.size()) { // zero pad to 16 bytes texcoords.reserve(texcoords.size()+1); texcoords.data()[texcoords.size()] = zero; } } virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; //!< vertex positions for multiple timesteps std::vector> normals; //!< vertex normals std::vector texcoords; //!< face texture coordinates std::vector position_indices; //!< position indices for all faces std::vector normal_indices; //!< normal indices for all faces std::vector texcoord_indices; //!< texcoord indices for all faces RTCSubdivisionMode position_subdiv_mode; RTCSubdivisionMode normal_subdiv_mode; RTCSubdivisionMode texcoord_subdiv_mode; std::vector verticesPerFace; //!< number of indices of each face std::vector holes; //!< face ID of holes std::vector edge_creases; //!< index pairs for edge crease std::vector edge_crease_weights; //!< weight for each edge crease std::vector vertex_creases; //!< indices of vertex creases std::vector vertex_crease_weights; //!< weight for each vertex crease Ref material; float tessellationRate; }; /*! Hair Set. */ struct HairSetNode : public Node { typedef Vec3ff Vertex; struct Hair { public: Hair () {} Hair (unsigned vertex, unsigned id) : vertex(vertex), id(id) {} public: unsigned vertex, id; //!< index of first control point and hair ID }; public: HairSetNode (RTCGeometryType type, Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0) : Node(true), time_range(time_range), type(type), material(material), tessellation_rate(4) { for (size_t i=0; i()); } HairSetNode (const avector& positions_in, const std::vector& hairs, Ref material, RTCGeometryType type) : Node(true), time_range(0.0f,1.0f), type(type), hairs(hairs), material(material), tessellation_rate(4) { positions.push_back(positions_in); } HairSetNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), type(imesh->type), positions(transformMSMBlurBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), tangents(transformMSMBlurVectorBuffer(imesh->tangents,spaces)), dnormals(transformMSMBlurVectorVec3faBuffer(imesh->dnormals,spaces)), hairs(imesh->hairs), flags(imesh->flags), material(imesh->material), tessellation_rate(imesh->tessellation_rate) {} virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; //!< hair control points (x,y,z,r) for multiple timesteps std::vector> normals; //!< hair control normals (nx,ny,nz) for multiple timesteps std::vector> tangents; //!< hair control tangents (tx,ty,tz,tr) for multiple timesteps std::vector> dnormals; //!< hair control normal derivatives (nx,ny,nz) for multiple timesteps std::vector hairs; //!< list of hairs std::vector flags; //!< left, right end cap flags Ref material; unsigned tessellation_rate; }; /*! Point Set. */ struct PointSetNode : public Node { typedef Vec3ff Vertex; public: PointSetNode (RTCGeometryType type, Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0) : Node(true), time_range(time_range), type(type), material(material) { for (size_t i=0; i()); } PointSetNode (const avector& positions_in, Ref material, RTCGeometryType type) : Node(true), time_range(0.0f, 1.0f), type(type), material(material) { positions.push_back(positions_in); } PointSetNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), type(imesh->type), positions(transformMSMBlurBuffer(imesh->positions,spaces)), normals(transformMSMBlurNormalBuffer(imesh->normals,spaces)), material(imesh->material) {} virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; //!< point control points (x,y,z,r) for multiple timesteps std::vector> normals; //!< point control normals (nx,ny,nz) for multiple timesteps (oriented only) Ref material; }; struct GridMeshNode : public Node { typedef Vec3fa Vertex; static const unsigned int GRID_RES_MAX = 0x7FFF; struct Grid { public: Grid() {} Grid (unsigned int startVtx, unsigned int lineStride, unsigned int resX_in, unsigned int resY_in) : startVtx(startVtx), lineStride(lineStride), resX(resX_in), resY(resY_in) { assert(resX_in <= GRID_RES_MAX); assert(resY_in <= GRID_RES_MAX); } public: unsigned int startVtx; unsigned int lineStride; unsigned short resX,resY; }; public: GridMeshNode (Ref material, const BBox1f time_range = BBox1f(0,1), size_t numTimeSteps = 0) : Node(true), time_range(time_range), material(material) { for (size_t i=0; i()); } GridMeshNode (Ref imesh, const Transformations& spaces) : Node(true), time_range(imesh->time_range), positions(transformMSMBlurVec3faBuffer(imesh->positions,spaces)), grids(imesh->grids), material(imesh->material) {} virtual void setMaterial(Ref material) { this->material = material; } virtual BBox3fa bounds() const { BBox3fa b = empty; for (const auto& p : positions) for (auto& x : p) b.extend(x); return b; } virtual LBBox3fa lbounds() const { avector bboxes(positions.size()); for (size_t t=0; t> positions; std::vector grids; Ref material; }; enum InstancingMode { INSTANCING_NONE, INSTANCING_GEOMETRY, INSTANCING_GROUP, INSTANCING_FLATTENED, INSTANCING_MULTI_LEVEL }; Ref flatten(Ref node, InstancingMode mode); Ref flatten(Ref node, InstancingMode mode); Statistics calculateStatistics(Ref node); enum CurveSubtype { ROUND_CURVE, FLAT_CURVE }; enum PointSubtype { SPHERE, DISC, ORIENTED_DISC }; } } #include "materials.h"