rendering-in-cgi/Framework/external/embree/tutorials/common/scenegraph/scenegraph.h
2024-04-23 10:14:24 +02:00

1660 lines
54 KiB
C++

// 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<Node> load(const FileName& fname, bool singleObject = false);
void store(Ref<Node> root, const FileName& fname, bool embedTextures, bool referenceMaterials, bool binaryFormat);
void extend_animation(Ref<Node> node0, Ref<Node> node1);
void optimize_animation(Ref<Node> node0);
void set_motion_vector(Ref<Node> node, const Vec3fa& dP);
void set_motion_vector(Ref<Node> node, const avector<Vec3fa>& motion_vector);
void set_time_range(Ref<SceneGraph::Node> node, const BBox1f& time_range);
void resize_randomly(RandomSampler& sampler, Ref<Node> node, const size_t N);
Ref<Node> convert_triangles_to_quads(Ref<Node> node, float prop);
Ref<Node> convert_triangles_to_quads( Ref<TriangleMeshNode> tmesh);
Ref<Node> convert_quads_to_subdivs(Ref<Node> node);
Ref<Node> my_merge_quads_to_grids(Ref<SceneGraph::Node> node);
Ref<Node> convert_bezier_to_lines(Ref<Node> node);
Ref<Node> convert_bezier_to_bspline(Ref<Node> node);
Ref<Node> convert_bezier_to_hermite(Ref<Node> node);
Ref<Node> convert_bspline_to_bezier(Ref<Node> node);
Ref<Node> convert_flat_to_round_curves(Ref<Node> node);
Ref<Node> convert_round_to_flat_curves(Ref<Node> node);
Ref<Node> convert_quads_to_grids( Ref<QuadMeshNode> qmesh, const unsigned resX, const unsigned resY );
Ref<Node> convert_quads_to_grids( Ref<Node> node, const unsigned resX, const unsigned resY );
Ref<Node> convert_grids_to_quads( Ref<GridMeshNode> gmesh);
Ref<Node> convert_grids_to_quads( Ref<Node> node);
Ref<Node> remove_mblur(Ref<Node> node, bool mblur);
void convert_mblur_to_nonmblur(Ref<Node> 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<MaterialNode> 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<Node> set_motion_vector(const Vec3fa& dP) {
SceneGraph::set_motion_vector(this,dP); return this;
}
Ref<Node> set_motion_vector(const avector<Vec3fa>& 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<AffineSpace3ff>& 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<spaces.size(); i++)
r.extend(xfmBounds(spaces[i],cbounds));
return r;
}
LBBox3fa lbounds ( const LBBox3fa& cbounds ) const
{
assert(spaces.size());
if (spaces.size() == 1)
{
return LBBox3fa(xfmBounds(spaces[0],cbounds.bounds0),
xfmBounds(spaces[0],cbounds.bounds1));
}
else
{
avector<BBox3fa> bounds(spaces.size());
for (size_t i=0; i<spaces.size(); i++) {
const float f = float(i)/float(spaces.size()-1);
bounds[i] = xfmBounds(spaces[i],cbounds.interpolate(f));
}
return LBBox3fa(bounds);
}
}
void add (const Transformations& other) {
for (size_t i=0; i<other.size(); i++) spaces.push_back(other[i]);
}
static __forceinline bool isIdentity(AffineSpace3ff const& M, bool q)
{
if (M.l.vx.x != 1.f) return false;
if (M.l.vx.y != 0.f) return false;
if (M.l.vx.z != 0.f) return false;
if (q && M.l.vx.w != 0.f) return false;
if (M.l.vy.x != 0.f) return false;
if (M.l.vy.y != 1.f) return false;
if (M.l.vy.z != 0.f) return false;
if (q && M.l.vy.w != 0.f) return false;
if (M.l.vz.x != 0.f) return false;
if (M.l.vz.y != 0.f) return false;
if (M.l.vz.z != 1.f) return false;
if (q && M.l.vz.w != 0.f) return false;
if (M.p.x != 0.f) return false;
if (M.p.y != 0.f) return false;
if (M.p.z != 0.f) return false;
if (q && M.p.w != 1.f) return false;
return true;
}
static __forceinline AffineSpace3ff mul(AffineSpace3ff const& M0, AffineSpace3ff const& M1, bool q0, bool q1, bool& q)
{
q = false;
if (isIdentity(M0, q0)) { q = q1; return M1; }
if (isIdentity(M1, q1)) { q = q0; return M0; }
// simple case non of the transformations is a quaternion
if (q0 == false && q1 == false)
{
return M0 * M1;
}
else if (q0 == true && q1 == true)
{
std::cout << "warning: cannot multiply two quaternion decompositions. will convert to regular transforms and multiply" << std::endl;
return quaternionDecompositionToAffineSpace(M0) * quaternionDecompositionToAffineSpace(M1);
}
else if (q0 == true && q1 == false)
{
AffineSpace3fa S; Quaternion3f Q; Vec3fa T;
quaternionDecomposition(M0, T, Q, S);
S = S * AffineSpace3fa(M1);
if (S.l.vx.y != 0.f || S.l.vx.z != 0 || S.l.vy.z != 0)
std::cout << "warning: cannot multiply quaternion and general transformation matrix. will ignore lower diagonal" << std::endl;
q = true;
return quaternionDecomposition(T, Q, S);
}
else {
if (M0.l.vx.y != 0.f || M0.l.vx.z != 0 || M0.l.vy.z != 0 || M0.l.vy.x != 0.f || M0.l.vz.x != 0 || M0.l.vz.y != 0)
std::cout << "warning: cannot multiply general transformation matrix and quaternion. will only consider translation and diagonal as scale factors" << std::endl;
AffineSpace3ff M = M1;
M.l.vx.y += M0.p.x;
M.l.vx.z += M0.p.y;
M.l.vy.z += M0.p.z;
M.l.vx.x *= M0.l.vx.x;
M.l.vy.y *= M0.l.vy.y;
M.l.vz.z *= M0.l.vz.z;
q = true;
return M;
}
}
friend __forceinline Transformations operator* ( const Transformations& a, const Transformations& b )
{
if (a.size() == 1)
{
Transformations c(intersect(a.time_range,b.time_range),b.size());
for (size_t i=0; i<b.size(); i++) c[i] = mul(a[0], b[i], a.quaternion, b.quaternion, c.quaternion);
return c;
}
else if (b.size() == 1)
{
Transformations c(intersect(a.time_range,b.time_range),a.size());
c.quaternion = a.quaternion || b.quaternion;
for (size_t i=0; i<a.size(); i++) c[i] = mul(a[i], b[0], a.quaternion, b.quaternion, c.quaternion);
return c;
}
else if (a.size() == b.size())
{
Transformations c(intersect(a.time_range,b.time_range),a.size());
c.quaternion = a.quaternion || b.quaternion;
for (size_t i=0; i<a.size(); i++) c[i] = mul(a[i], b[i], a.quaternion, b.quaternion, c.quaternion);
return c;
}
else
THROW_RUNTIME_ERROR("number of transformations does not match");
}
friend __forceinline std::vector<Transformations> operator* ( const std::vector<Transformations>& a, const Transformations& b )
{
std::vector<Transformations> result;
for (size_t i = 0; i < a.size(); ++i) {
result.push_back(a[i] * b);
}
return result;
}
friend __forceinline std::vector<Transformations> operator* ( const Transformations& a, const std::vector<Transformations>& b )
{
return b * a;
}
friend __forceinline std::vector<Transformations> operator* ( const std::vector<Transformations>& a, const std::vector<Transformations>& b )
{
if(a.size() != b.size())
THROW_RUNTIME_ERROR("number of transformations does not match");
std::vector<Transformations> 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<AffineSpace3ff> spaces;
bool quaternion = false;
};
template<typename Vertex>
std::vector<avector<Vertex>> transformMSMBlurBuffer(const std::vector<avector<Vertex>>& positions_in, const Transformations& spaces)
{
std::vector<avector<Vertex>> 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<spaces.size(); i++)
{
avector<Vertex> verts(num_vertices);
for (size_t j=0; j<num_vertices; j++) {
verts[j] = xfmPoint(spaces[i],positions_in[0][j]);
verts[j].w = positions_in[0][j].w;
}
positions_out.push_back(std::move(verts));
}
}
/* otherwise transform all vertex sets with interpolated transformation */
else
{
for (size_t t=0; t<num_time_steps; t++)
{
float time = num_time_steps > 1 ? float(t)/float(num_time_steps-1) : 0.0f;
const AffineSpace3ff space = spaces.interpolate(time);
avector<Vertex> verts(num_vertices);
for (size_t i=0; i<num_vertices; i++) {
verts[i] = xfmPoint (space,positions_in[t][i]);
verts[i].w = positions_in[t][i].w;
}
positions_out.push_back(std::move(verts));
}
}
return positions_out;
}
inline std::vector<avector<Vec3fa>> transformMSMBlurVec3faBuffer(const std::vector<avector<Vec3fa>>& positions_in, const Transformations& spaces)
{
std::vector<avector<Vec3fa>> 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<spaces.size(); i++)
{
avector<Vec3fa> verts(num_vertices);
for (size_t j=0; j<num_vertices; j++) {
verts[j] = xfmPoint((AffineSpace3fa)spaces[i],positions_in[0][j]);
}
positions_out.push_back(std::move(verts));
}
}
/* otherwise transform all vertex sets with interpolated transformation */
else
{
for (size_t t=0; t<num_time_steps; t++)
{
float time = num_time_steps > 1 ? float(t)/float(num_time_steps-1) : 0.0f;
const AffineSpace3ff space = spaces.interpolate(time);
avector<Vec3fa> verts(num_vertices);
for (size_t i=0; i<num_vertices; i++) {
verts[i] = xfmPoint ((AffineSpace3fa)space,positions_in[t][i]);
}
positions_out.push_back(std::move(verts));
}
}
return positions_out;
}
template<typename Vertex>
std::vector<avector<Vertex>> transformMSMBlurVectorBuffer(const std::vector<avector<Vertex>>& vectors_in, const Transformations& spaces)
{
if (vectors_in.size() == 0)
return vectors_in;
std::vector<avector<Vertex>> 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<spaces.size(); i++)
{
avector<Vertex> vecs(num_vertices);
for (size_t j=0; j<num_vertices; j++) {
vecs[j] = xfmVector(spaces[i],vectors_in[0][j]);
vecs[j].w = vectors_in[0][j].w;
}
vectors_out.push_back(std::move(vecs));
}
}
/* otherwise transform all vertex sets with interpolated transformation */
else
{
for (size_t t=0; t<num_time_steps; t++)
{
float time = num_time_steps > 1 ? float(t)/float(num_time_steps-1) : 0.0f;
const AffineSpace3ff space = spaces.interpolate(time);
avector<Vertex> vecs(num_vertices);
for (size_t i=0; i<num_vertices; i++) {
vecs[i] = xfmVector (space,vectors_in[t][i]);
vecs[i].w = vectors_in[t][i].w;
}
vectors_out.push_back(std::move(vecs));
}
}
return vectors_out;
}
template<typename Vertex>
std::vector<avector<Vertex>> transformMSMBlurVectorVec3faBuffer(const std::vector<avector<Vertex>>& vectors_in, const Transformations& spaces)
{
if (vectors_in.size() == 0)
return vectors_in;
std::vector<avector<Vertex>> 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<spaces.size(); i++)
{
avector<Vertex> vecs(num_vertices);
for (size_t j=0; j<num_vertices; j++) {
vecs[j] = xfmVector((AffineSpace3fa)spaces[i],vectors_in[0][j]);
}
vectors_out.push_back(std::move(vecs));
}
}
/* otherwise transform all vertex sets with interpolated transformation */
else
{
for (size_t t=0; t<num_time_steps; t++)
{
float time = num_time_steps > 1 ? float(t)/float(num_time_steps-1) : 0.0f;
const AffineSpace3ff space = spaces.interpolate(time);
avector<Vertex> vecs(num_vertices);
for (size_t i=0; i<num_vertices; i++) {
vecs[i] = xfmVector ((AffineSpace3fa)space,vectors_in[t][i]);
}
vectors_out.push_back(std::move(vecs));
}
}
return vectors_out;
}
template<typename Vertex>
std::vector<avector<Vertex>> transformMSMBlurNormalBuffer(const std::vector<avector<Vertex>>& normals_in, const Transformations& spaces)
{
if (normals_in.size() == 0)
return normals_in;
std::vector<avector<Vertex>> 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<spaces.size(); i++)
{
avector<Vertex> norms(num_vertices);
for (size_t j=0; j<num_vertices; j++) {
norms[j] = xfmNormal((AffineSpace3fa)spaces[i],normals_in[0][j]);
}
normals_out.push_back(std::move(norms));
}
}
/* otherwise transform all vertex sets with interpolated transformation */
else
{
for (size_t t=0; t<num_time_steps; t++)
{
float time = num_time_steps > 1 ? float(t)/float(num_time_steps-1) : 0.0f;
const AffineSpace3ff space = spaces.interpolate(time);
avector<Vertex> norms(num_vertices);
for (size_t i=0; i<num_vertices; i++) {
norms[i] = xfmNormal ((AffineSpace3fa)space,normals_in[t][i]);
}
normals_out.push_back(std::move(norms));
}
}
return normals_out;
}
struct PerspectiveCameraData
{
PerspectiveCameraData()
: from(1,0,0), to(0,0,0), up(0,1,0), fov(30) {}
PerspectiveCameraData (const Vec3fa& from, const Vec3fa& to, const Vec3fa& up, const float fov)
: from(from), to(to), up(up), fov(fov) {}
PerspectiveCameraData (const PerspectiveCameraData& other, const AffineSpace3fa& space)
: from(xfmPoint(space,other.from)), to(xfmPoint(space,other.to)), up(xfmVector(space,other.up)), fov(other.fov) {}
friend PerspectiveCameraData lerp(const PerspectiveCameraData& a, const PerspectiveCameraData& b, const float t)
{
const Vec3fa from = embree::lerp(a.from, b.from, t);
const Vec3fa to = embree::lerp(a.to , b.to , t);
const Vec3fa up = embree::lerp(a.up , b.up , t);
const float fov = embree::lerp(a.fov , b.fov , t);
return PerspectiveCameraData(from,to,up,fov);
}
public:
Vec3fa from; //!< position of camera
Vec3fa to; //!< look at point
Vec3fa up; //!< up vector
float fov; //!< vertical field of view
};
struct PerspectiveCameraNode : public Node
{
ALIGNED_STRUCT_(16);
PerspectiveCameraNode (std::string name = "")
: Node(name) {}
PerspectiveCameraNode (const Vec3fa& from, const Vec3fa& to, const Vec3fa& up, const float fov)
: data(from, to, up, fov) {}
PerspectiveCameraNode (const Ref<PerspectiveCameraNode>& 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<Ref<PerspectiveCameraNode>>&& cameras, BBox1f time_range, const std::string& id = "")
: time_range(time_range), cameras(cameras) {}
AnimatedPerspectiveCameraNode (const Ref<AnimatedPerspectiveCameraNode>& other, const AffineSpace3fa& space, const std::string& id)
: PerspectiveCameraNode(id), time_range(other->time_range)
{
cameras.resize(other->size());
for (size_t i=0; i<other->size(); 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<Ref<PerspectiveCameraNode>> cameras;
};
struct TransformNode : public Node
{
ALIGNED_STRUCT_(16);
TransformNode (const AffineSpace3fa& xfm, const Ref<Node>& child)
: spaces((AffineSpace3ff)xfm), child(child) {}
TransformNode (const AffineSpace3fa& xfm0, const AffineSpace3fa& xfm1, const Ref<Node>& child)
: spaces((AffineSpace3ff)xfm0,(AffineSpace3ff)xfm1), child(child) {}
TransformNode (const avector<AffineSpace3ff>& spaces, const Ref<Node>& child)
: spaces(spaces), child(child) {}
TransformNode(const Transformations& spaces, const Ref<Node>& child)
: spaces(spaces), child(child) {}
virtual void setMaterial(Ref<MaterialNode> 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<Node> child;
};
struct MultiTransformNode : public Node
{
ALIGNED_STRUCT_(16);
MultiTransformNode (const avector<AffineSpace3fa>& xfm, const Ref<Node>& child)
: child(child)
{
for (const AffineSpace3fa& space : xfm) {
spaces.push_back(Transformations(space));
}
}
MultiTransformNode (const avector<AffineSpace3fa>& xfm0, const avector<AffineSpace3fa>& xfm1, const Ref<Node>& 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<avector<AffineSpace3ff>>& spaces_in, const Ref<Node>& 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<AffineSpace3ff> 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<Transformations>& spaces, const Ref<Node>& child)
: spaces(spaces), child(child) {}
virtual void setMaterial(Ref<MaterialNode> 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<Transformations> spaces;
Ref<Node> child;
};
struct GroupNode : public Node
{
GroupNode (const size_t N = 0) {
children.resize(N);
}
GroupNode (std::vector<Ref<Node>>& children)
: children(children) {}
size_t size() const {
return children.size();
}
void add(const Ref<Node>& node) {
if (node) children.push_back(node);
}
void set(const size_t i, const Ref<Node>& node) {
children[i] = node;
}
Ref<Node> 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<children.size(); i++)
children[i] = convert_triangles_to_quads(children[i],prop);
}
void quads_to_grids(unsigned int resX, unsigned int resY)
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_quads_to_grids(children[i],resX, resY);
}
void grids_to_quads()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_grids_to_quads(children[i]);
}
void quads_to_subdivs()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_quads_to_subdivs(children[i]);
}
void bezier_to_lines()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_bezier_to_lines(children[i]);
}
void flat_to_round_curves()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_flat_to_round_curves(children[i]);
}
void round_to_flat_curves()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_round_to_flat_curves(children[i]);
}
void bezier_to_bspline()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_bezier_to_bspline(children[i]);
}
void bezier_to_hermite()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_bezier_to_hermite(children[i]);
}
void bspline_to_bezier()
{
for (size_t i=0; i<children.size(); i++)
children[i] = convert_bspline_to_bezier(children[i]);
}
void merge_quads_to_grids()
{
for (size_t i=0; i<children.size(); i++)
children[i] = my_merge_quads_to_grids(children[i]);
}
void remove_mblur(bool mblur)
{
for (size_t i=0; i<children.size(); i++)
SceneGraph::remove_mblur(children[i], mblur);
}
virtual void setMaterial(Ref<MaterialNode> 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<Ref<Node> > 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<LightNode> transform(const AffineSpace3fa& space) const = 0;
virtual Ref<LightNode> lerp(const Ref<LightNode>& light1_in, float f) const = 0;
virtual Ref<LightNode> get(float time) const = 0;
};
template<typename Light>
struct LightNodeImpl : public LightNode
{
ALIGNED_STRUCT_(16);
LightNodeImpl (const Light& light)
: light(light) {}
virtual LightType getType() const {
return light.getType();
}
virtual Ref<LightNode> transform(const AffineSpace3fa& space) const {
return new LightNodeImpl(light.transform(space));
}
virtual Ref<LightNode> get(float time) const {
return (LightNode*) this;
}
virtual Ref<LightNode> lerp(const Ref<LightNode>& light1_in, float f) const
{
const Ref<LightNodeImpl<Light>> light1 = light1_in.dynamicCast<LightNodeImpl<Light>>();
assert(light1);
return new LightNodeImpl(Light::lerp(light,light1->light,f));
}
Light light;
};
struct AnimatedLightNode : public LightNode
{
AnimatedLightNode (const std::vector<Ref<LightNode>>&& lights, BBox1f time_range)
: lights(lights), time_range(time_range) {}
virtual LightType getType() const {
return lights[0]->getType();
}
virtual Ref<LightNode> transform(const AffineSpace3fa& space) const
{
std::vector<Ref<LightNode>> xfm_lights(lights.size());
for (size_t i=0; i<lights.size(); i++)
xfm_lights[i] = lights[i]->transform(space);
return new AnimatedLightNode(std::move(xfm_lights), time_range);
}
virtual Ref<LightNode> 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<LightNode> light0 = lights[itime+0]->get(time);
Ref<LightNode> light1 = lights[itime+1]->get(time);
return light0->lerp(light1,ftime);
}
virtual Ref<LightNode> lerp(const Ref<LightNode>& light1_in, float f) const {
assert(false); return nullptr;
}
public:
std::vector<Ref<LightNode>> 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<Vertex>& positions_in,
const avector<Vertex>& normals_in,
const std::vector<Vec2f>& texcoords,
const std::vector<Triangle>& triangles,
Ref<MaterialNode> 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<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
}
TriangleMeshNode (Ref<SceneGraph::TriangleMeshNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t]) b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return triangles.size();
}
size_t numVertices() const {
assert(positions.size());
return positions[0].size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numPrimitives()*sizeof(Triangle) + numVertices()*numTimeSteps()*sizeof(Vertex);
}
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range;
std::vector<avector<Vertex>> positions;
std::vector<avector<Vertex>> normals;
std::vector<Vec2f> texcoords;
std::vector<Triangle> triangles;
Ref<MaterialNode> 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<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
}
QuadMeshNode (Ref<SceneGraph::QuadMeshNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t]) b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return quads.size();
}
size_t numVertices() const {
assert(positions.size());
return positions[0].size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numPrimitives()*sizeof(Quad) + numVertices()*numTimeSteps()*sizeof(Vertex);
}
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range;
std::vector<avector<Vertex>> positions;
std::vector<avector<Vertex>> normals;
std::vector<Vec2f> texcoords;
std::vector<Quad> quads;
Ref<MaterialNode> material;
};
/*! Subdivision Mesh. */
struct SubdivMeshNode : public Node
{
typedef Vec3fa Vertex;
SubdivMeshNode (Ref<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
zero_pad_arrays();
}
SubdivMeshNode (Ref<SceneGraph::SubdivMeshNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t]) b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return verticesPerFace.size();
}
size_t numPositions() const {
assert(positions.size());
return positions[0].size();
}
size_t numNormals() const {
if (normals.size()) return normals[0].size();
else return 0;
}
size_t numEdges() const {
return position_indices.size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numPrimitives()*sizeof(unsigned) + numEdges()*sizeof(unsigned) + numPositions()*numTimeSteps()*sizeof(Vertex);
}
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range; //!< geometry time range for motion blur
std::vector<avector<Vertex>> positions; //!< vertex positions for multiple timesteps
std::vector<avector<Vertex>> normals; //!< vertex normals
std::vector<Vec2f> texcoords; //!< face texture coordinates
std::vector<unsigned> position_indices; //!< position indices for all faces
std::vector<unsigned> normal_indices; //!< normal indices for all faces
std::vector<unsigned> texcoord_indices; //!< texcoord indices for all faces
RTCSubdivisionMode position_subdiv_mode;
RTCSubdivisionMode normal_subdiv_mode;
RTCSubdivisionMode texcoord_subdiv_mode;
std::vector<unsigned> verticesPerFace; //!< number of indices of each face
std::vector<unsigned> holes; //!< face ID of holes
std::vector<Vec2i> edge_creases; //!< index pairs for edge crease
std::vector<float> edge_crease_weights; //!< weight for each edge crease
std::vector<unsigned> vertex_creases; //!< indices of vertex creases
std::vector<float> vertex_crease_weights; //!< weight for each vertex crease
Ref<MaterialNode> 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<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
}
HairSetNode (const avector<Vertex>& positions_in, const std::vector<Hair>& hairs, Ref<MaterialNode> 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<SceneGraph::HairSetNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t]) b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return hairs.size();
}
size_t numVertices() const {
assert(positions.size());
return positions[0].size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numPrimitives()*sizeof(Hair) + numVertices()*numTimeSteps()*sizeof(Vertex);
}
void convert_bezier_to_bspline();
void convert_bspline_to_bezier();
void convert_bezier_to_hermite();
void compact_vertices();
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range; //!< geometry time range for motion blur
RTCGeometryType type; //!< type of curve
std::vector<avector<Vertex>> positions; //!< hair control points (x,y,z,r) for multiple timesteps
std::vector<avector<Vec3fa>> normals; //!< hair control normals (nx,ny,nz) for multiple timesteps
std::vector<avector<Vertex>> tangents; //!< hair control tangents (tx,ty,tz,tr) for multiple timesteps
std::vector<avector<Vec3fa>> dnormals; //!< hair control normal derivatives (nx,ny,nz) for multiple timesteps
std::vector<Hair> hairs; //!< list of hairs
std::vector<unsigned char> flags; //!< left, right end cap flags
Ref<MaterialNode> material;
unsigned tessellation_rate;
};
/*! Point Set. */
struct PointSetNode : public Node
{
typedef Vec3ff Vertex;
public:
PointSetNode (RTCGeometryType type, Ref<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
}
PointSetNode (const avector<Vertex>& positions_in, Ref<MaterialNode> material, RTCGeometryType type)
: Node(true), time_range(0.0f, 1.0f), type(type), material(material)
{
positions.push_back(positions_in);
}
PointSetNode (Ref<SceneGraph::PointSetNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t])
b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return numVertices();
}
size_t numVertices() const {
assert(positions.size());
return positions[0].size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numVertices()*numTimeSteps()*sizeof(Vertex);
}
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range; //!< geometry time range for motion blur
RTCGeometryType type; //!< type of point
std::vector<avector<Vertex>> positions; //!< point control points (x,y,z,r) for multiple timesteps
std::vector<avector<Vec3fa>> normals; //!< point control normals (nx,ny,nz) for multiple timesteps (oriented only)
Ref<MaterialNode> 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<MaterialNode> 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<numTimeSteps; i++)
positions.push_back(avector<Vertex>());
}
GridMeshNode (Ref<SceneGraph::GridMeshNode> 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<MaterialNode> 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<BBox3fa> bboxes(positions.size());
for (size_t t=0; t<positions.size(); t++) {
BBox3fa b = empty;
for (auto& x : positions[t]) b.extend(x);
bboxes[t] = b;
}
return LBBox3fa(bboxes);
}
virtual size_t numPrimitives() const {
return grids.size();
}
size_t numVertices() const {
assert(positions.size());
return positions[0].size();
}
size_t numTimeSteps() const {
return positions.size();
}
size_t numBytes() const {
return numPrimitives()*sizeof(Grid) + numVertices()*numTimeSteps()*sizeof(Vertex);
}
void verify() const;
virtual void print(std::ostream& cout, int depth);
virtual void calculateStatistics(Statistics& stat);
virtual void calculateInDegree();
virtual void resetInDegree();
public:
BBox1f time_range;
std::vector<avector<Vertex>> positions;
std::vector<Grid> grids;
Ref<MaterialNode> material;
};
enum InstancingMode { INSTANCING_NONE, INSTANCING_GEOMETRY, INSTANCING_GROUP, INSTANCING_FLATTENED, INSTANCING_MULTI_LEVEL };
Ref<Node> flatten(Ref<Node> node, InstancingMode mode);
Ref<GroupNode> flatten(Ref<GroupNode> node, InstancingMode mode);
Statistics calculateStatistics(Ref<Node> node);
enum CurveSubtype
{
ROUND_CURVE,
FLAT_CURVE
};
enum PointSubtype
{
SPHERE,
DISC,
ORIENTED_DISC
};
}
}
#include "materials.h"