| 1058 | // Scene graph |
| 1059 | |
| 1060 | NodeID SceneBuilder::addNode(const Node& node) |
| 1061 | { |
| 1062 | // Validate node. |
| 1063 | auto validateMatrix = [&](float4x4 m, const char* field) |
| 1064 | { |
| 1065 | if (!isMatrixValid(m)) |
| 1066 | { |
| 1067 | FALCOR_THROW("Node '{}' {} matrix has inf/nan values", node.name, field); |
| 1068 | } |
| 1069 | // Check the assumption that transforms are affine. Note that glm is column-major. |
| 1070 | if (!isMatrixAffine(m)) |
| 1071 | { |
| 1072 | logWarning("SceneBuilder::addNode() - Node '{}' {} matrix is not affine. Setting last row to (0,0,0,1).", node.name, field); |
| 1073 | m[3] = float4(0, 0, 0, 1); |
| 1074 | } |
| 1075 | return m; |
| 1076 | }; |
| 1077 | |
| 1078 | InternalNode internalNode(node); |
| 1079 | internalNode.transform = validateMatrix(node.transform, "transform"); |
| 1080 | internalNode.localToBindPose = validateMatrix(node.localToBindPose, "localToBindPose"); |
| 1081 | |
| 1082 | static_assert(NodeID::kInvalidID >= std::numeric_limits<uint32_t>::max()); |
| 1083 | if (node.parent.isValid() && node.parent.get() >= mSceneGraph.size()) FALCOR_THROW("Node parent is out of range"); |
| 1084 | if (mSceneGraph.size() >= std::numeric_limits<NodeID::IntType>::max()) FALCOR_THROW("Scene graph is too large"); |
| 1085 | |
| 1086 | // Add node to scene graph. |
| 1087 | NodeID newNodeID{ mSceneGraph.size() }; |
| 1088 | mSceneGraph.push_back(internalNode); |
| 1089 | if (node.parent.isValid()) mSceneGraph[node.parent.get()].children.push_back(newNodeID); |
| 1090 | |
| 1091 | return newNodeID; |
| 1092 | } |
| 1093 | |
| 1094 | void SceneBuilder::addMeshInstance(NodeID nodeID, MeshID meshID) |
| 1095 | { |