rendering-in-cgi/Framework/scenegraph/scenegraph.cpp
2024-04-23 10:14:24 +02:00

411 lines
19 KiB
C++

// 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::Node> 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::LightNode::calculateStatistics(Statistics& stat)
{
indegree++;
if (indegree == 1) stat.numLights++;
}
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; i < children.size(); i++) {
tab(cout, depth + 1);
cout << "child" << i << " = ";
children[i]->print(cout, depth + 1);
}
tab(cout, depth);
cout << "}" << std::endl;
}
void SceneGraph::MaterialNode::print(std::ostream &cout, int depth) {
cout << "MaterialNode @ " << this << " { closed = " << closed << " }" << std::endl;
}
void SceneGraph::TriangleMeshNode::print(std::ostream &cout, int depth) {
cout << "TriangleMeshNode @ " << this << " { closed = " << closed << " }" << std::endl;
}
void SceneGraph::LightNode::print(std::ostream& cout, int depth) {
cout << "LightNode @ " << this << " { closed = " << closed << " }" << std::endl;
}
void SceneGraph::Node::calculateInDegree() {
indegree++;
}
void SceneGraph::TriangleMeshNode::calculateInDegree() {
indegree++;
if (indegree == 1)
material->calculateInDegree();
}
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::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);
}
bool SceneGraph::LightNode::calculateClosed(bool group_instancing)
{
assert(indegree);
closed = true;
hasLightOrCamera = true;
return indegree == 1;
}
void SceneGraph::Node::resetInDegree() {
closed = false;
indegree--;
}
void SceneGraph::TriangleMeshNode::resetInDegree() {
closed = false;
if (indegree == 1)
material->resetInDegree();
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");
}
}
bool test_location(const std::vector<avector<Vec3ff>> &in, ssize_t ipos, std::vector<avector<Vec3ff>> &out,
ssize_t opos) {
if (opos < 0)
return false;
for (ssize_t i = ipos, j = opos; i < ipos + 4 && j < (ssize_t) out[0].size(); i++, j++) {
for (size_t k = 0; k < in.size(); k++) {
if (any(abs((vfloat4) in[k][i].m128 - (vfloat4) out[k][j].m128) > 0.01f * (vfloat4) max(
abs(in[k][i]), abs(out[k][j])).m128))
return false;
}
}
return true;
}
std::pair<int, int> 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<int, int> 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);
}
struct SceneGraphFlattener {
Ref<SceneGraph::Node> node;
std::map<Ref<SceneGraph::Node>, Ref<SceneGraph::Node>> object_mapping;
std::map<std::string, int> unique_id;
SceneGraphFlattener(Ref<SceneGraph::Node> in, SceneGraph::InstancingMode instancing) {
in->calculateInDegree();
in->calculateClosed(instancing == SceneGraph::INSTANCING_GROUP);
std::vector<Ref<SceneGraph::Node>> 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<std::string, int>::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<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &node,
const SceneGraph::Transformations &spaces) {
if (!node->hasLightOrCamera)
return;
/*if (Ref<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
convertLightsAndCameras(group,xfmNode->child, spaces*xfmNode->spaces);
}
else */
if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertLightsAndCameras(group, child, spaces);
}
// else if (Ref<SceneGraph::AnimatedLightNode> lightNode = node.dynamicCast<SceneGraph::AnimatedLightNode>()) {
// 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<SceneGraph::Node>());
// }
else if (Ref<SceneGraph::LightNode> lightNode = node.dynamicCast<SceneGraph::LightNode>()) {
if (spaces.size() == 1)
group.push_back(lightNode->transform(spaces[0]).dynamicCast<SceneGraph::Node>());
else {
// std::vector<Ref<SceneGraph::LightNode>> lights(spaces.size());
// for (size_t i=0; i<spaces.size(); i++)
// lights[i] = lightNode->transform(spaces[i]);
//
// group.push_back(new SceneGraph::AnimatedLightNode(std::move(lights),spaces.time_range));
}
}
// else if (Ref<SceneGraph::AnimatedPerspectiveCameraNode> cameraNode = node.dynamicCast<SceneGraph::AnimatedPerspectiveCameraNode>())
// {
// 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<SceneGraph::PerspectiveCameraNode> cameraNode = node.dynamicCast<SceneGraph::PerspectiveCameraNode>())
// {
// if (spaces.size() == 1)
// group.push_back(new SceneGraph::PerspectiveCameraNode(cameraNode,spaces[0],makeUniqueID(cameraNode->name)));
// else
// {
// std::vector<Ref<SceneGraph::PerspectiveCameraNode>> cameras(spaces.size());
// for (size_t i=0; i<spaces.size(); i++)
// cameras[i] = new SceneGraph::PerspectiveCameraNode(cameraNode,spaces[i]);
//
// group.push_back(new SceneGraph::AnimatedPerspectiveCameraNode(std::move(cameras),spaces.time_range,makeUniqueID(cameraNode->name)));
// }
// }
}
void convertGeometries(std::vector<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &node,
const SceneGraph::Transformations &spaces) {
/*if (Ref<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
convertGeometries(group, xfmNode->child, spaces * xfmNode->spaces);
} else if (Ref<SceneGraph::MultiTransformNode> xfmNode = node.dynamicCast<
SceneGraph::MultiTransformNode>()) {
for (size_t i = 0; i < xfmNode->spaces.size(); ++i)
convertGeometries(group, xfmNode->child, spaces * xfmNode->spaces[i]);
} else */if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertGeometries(group, child, spaces);
} else if (Ref<SceneGraph::TriangleMeshNode> mesh = node.dynamicCast<SceneGraph::TriangleMeshNode>()) {
group.push_back(new SceneGraph::TriangleMeshNode(mesh, spaces));
} /*else if (Ref<SceneGraph::QuadMeshNode> mesh = node.dynamicCast<SceneGraph::QuadMeshNode>()) {
group.push_back(new SceneGraph::QuadMeshNode(mesh, spaces));
} else if (Ref<SceneGraph::GridMeshNode> mesh = node.dynamicCast<SceneGraph::GridMeshNode>()) {
group.push_back(new SceneGraph::GridMeshNode(mesh, spaces));
} else if (Ref<SceneGraph::SubdivMeshNode> mesh = node.dynamicCast<SceneGraph::SubdivMeshNode>()) {
group.push_back(new SceneGraph::SubdivMeshNode(mesh, spaces));
} else if (Ref<SceneGraph::HairSetNode> mesh = node.dynamicCast<SceneGraph::HairSetNode>()) {
group.push_back(new SceneGraph::HairSetNode(mesh, spaces));
} else if (Ref<SceneGraph::PointSetNode> mesh = node.dynamicCast<SceneGraph::PointSetNode>()) {
group.push_back(new SceneGraph::PointSetNode(mesh, spaces));
}*/
}
Ref<SceneGraph::Node> lookupGeometries(Ref<SceneGraph::Node> node) {
if (object_mapping.find(node) == object_mapping.end()) {
std::vector<Ref<SceneGraph::Node>> geometries;
convertGeometries(geometries, node, one);
object_mapping[node] = new SceneGraph::GroupNode(geometries);
}
return object_mapping[node];
}
void convertInstances(std::vector<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &node,
const std::vector<SceneGraph::Transformations> &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<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
for (size_t i = 0; i < spaces.size(); ++i)
convertInstances(group, xfmNode->child, spaces[i] * xfmNode->spaces);
} else if (Ref<SceneGraph::MultiTransformNode> xfmNode = node.dynamicCast<
SceneGraph::MultiTransformNode>()) {
convertInstances(group, xfmNode->child, spaces * xfmNode->spaces);
} else */if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertInstances(group, child, spaces);
}
}
void convertInstances(std::vector<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &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<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
convertInstances(group, xfmNode->child, spaces * xfmNode->spaces);
} else if (Ref<SceneGraph::MultiTransformNode> xfmNode = node.dynamicCast<
SceneGraph::MultiTransformNode>()) {
convertInstances(group, xfmNode->child, spaces * xfmNode->spaces);
} else */if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertInstances(group, child, spaces);
}
}
void convertMultiLevelInstances(std::vector<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &node) {
if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertMultiLevelInstances(group, child);
} else if (node.dynamicCast<SceneGraph::TriangleMeshNode>()) {
group.push_back(node);
} /*else if (node.dynamicCast<SceneGraph::QuadMeshNode>()) {
group.push_back(node);
} else if (node.dynamicCast<SceneGraph::GridMeshNode>()) {
group.push_back(node);
} else if (node.dynamicCast<SceneGraph::SubdivMeshNode>()) {
group.push_back(node);
} else if (node.dynamicCast<SceneGraph::HairSetNode>()) {
group.push_back(node);
} else if (node.dynamicCast<SceneGraph::PointSetNode>()) {
group.push_back(node);
}*/ else if (object_mapping.find(node) != object_mapping.end()) {
group.push_back(object_mapping[node]);
} /*else if (Ref<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
auto new_node = new SceneGraph::TransformNode(xfmNode->spaces,
convertMultiLevelInstances(xfmNode->child));
object_mapping[node] = new_node;
group.push_back(new_node);
} else if (Ref<SceneGraph::MultiTransformNode> xfmNode = node.dynamicCast<
SceneGraph::MultiTransformNode>()) {
auto new_node = new SceneGraph::MultiTransformNode(xfmNode->spaces,
convertMultiLevelInstances(xfmNode->child));
object_mapping[node] = new_node;
group.push_back(new_node);
}*/
}
Ref<SceneGraph::Node> convertMultiLevelInstances(const Ref<SceneGraph::Node> &node) {
if (object_mapping.find(node) != object_mapping.end()) {
return object_mapping[node];
}
std::vector<Ref<SceneGraph::Node>> group;
convertMultiLevelInstances(group, node);
auto new_node = new SceneGraph::GroupNode(group);
object_mapping[node] = new_node;
return new_node;
}
void convertFlattenedInstances(std::vector<Ref<SceneGraph::Node>> &group, const Ref<SceneGraph::Node> &node) {
/*if (Ref<SceneGraph::TransformNode> xfmNode = node.dynamicCast<SceneGraph::TransformNode>()) {
group.push_back(node);
} else */if (Ref<SceneGraph::GroupNode> groupNode = node.dynamicCast<SceneGraph::GroupNode>()) {
for (const auto &child: groupNode->children)
convertFlattenedInstances(group, child);
}
}
};
Ref<SceneGraph::Node> SceneGraph::flatten(Ref<Node> node, InstancingMode mode) {
return SceneGraphFlattener(node, mode).node;
}
Ref<SceneGraph::GroupNode> SceneGraph::flatten(Ref<SceneGraph::GroupNode> node, SceneGraph::InstancingMode mode) {
return flatten(node.dynamicCast<SceneGraph::Node>(), mode).dynamicCast<SceneGraph::GroupNode>();
}
}