summaryrefslogtreecommitdiff
path: root/hw6/src/sceneIO_geometry.cpp
diff options
context:
space:
mode:
author53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
committer53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
commitdb072ad4dc181eca5a1458656b130beb43f475bf (patch)
treea3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/sceneIO_geometry.cpp
downloadcsci427-db072ad4dc181eca5a1458656b130beb43f475bf.tar.xz
csci427-db072ad4dc181eca5a1458656b130beb43f475bf.zip
Diffstat (limited to 'hw6/src/sceneIO_geometry.cpp')
-rw-r--r--hw6/src/sceneIO_geometry.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/hw6/src/sceneIO_geometry.cpp b/hw6/src/sceneIO_geometry.cpp
new file mode 100644
index 0000000..5fa4a5c
--- /dev/null
+++ b/hw6/src/sceneIO_geometry.cpp
@@ -0,0 +1,187 @@
+/******************************************************************/
+/* This file is part of the homework assignments for CSCI-427/527 */
+/* at The College of William & Mary and authored by Pieter Peers. */
+/* No part of this file, whether altered or in original form, can */
+/* be distributed or used outside the context of CSCI-427/527 */
+/* without consent of either the College of William & Mary or */
+/* Pieter Peers. */
+/******************************************************************/
+#include <vector>
+#include <memory>
+#include <string>
+#include <cstdio>
+#include <cassert>
+
+#include "sceneIO_xml.h"
+#include "sceneIO_core.h"
+#include "sceneIO_cache.h"
+#include "sceneIO_geometry.h"
+#include "sceneIO_material.h"
+#include "sceneIO_transformation3d.h"
+
+#include "util.h"
+#include "vec2d.h"
+#include "vec3d.h"
+#include "triangle.h"
+#include "constants.h"
+#include "importOBJ.h"
+#include "errorMessage.h"
+#include "triangleMesh.h"
+#include "random_number.h"
+#include "sceneGraphNode.h"
+
+static void importTriangle(const XMLNode& node, std::vector<triangle>& triangle_list)
+{
+ // sanity check
+ assert(node.name() == "triangle" || node.name() == "polygon");
+
+ // allocate temp data
+ unsigned int idx=0;
+ vec3d v[3], n[3];
+ vec2d t[3];
+
+ // for each child node, parse all vertices
+ for(XMLNode child = node.firstChild(); child.isValid(); child++)
+ {
+ std::string name = child.name();
+ if(name == "vertex")
+ {
+ v[idx] = getVec3d(child, "v", vec3d(+LARGE));
+ n[idx] = getVec3d(child, "n", vec3d(0.0f));
+ t[idx] = getVec2d(child, "t", vec2d(+LARGE));
+
+ // check if valid vertex
+ if(v[idx].x >= +LARGE || v[idx].y >= +LARGE || v[idx].z >= +LARGE)
+ errorMessage("Invalid vertex in %s definition.", node.name().c_str());
+
+ // create triangle
+ if(idx == 2)
+ {
+ // determine which attributes are defined on the triangle
+ bool hasNormals = (n[0].squared_length() > +EPSILON) && (n[0].squared_length() > +EPSILON) && (n[0].squared_length() > +EPSILON);
+ bool hasTextureCoord = (fabs(t[0].x) < +LARGE && fabs(t[0].y) < +LARGE) && (fabs(t[1].x) < +LARGE && fabs(t[1].y) < +LARGE) && (fabs(t[2].x) < +LARGE && fabs(t[2].y) < +LARGE);
+
+ if(!hasNormals && !hasTextureCoord) triangle_list.push_back(triangle(v[0], v[1], v[2]));
+ else if(hasNormals && !hasTextureCoord) triangle_list.push_back(triangle(v[0], v[1], v[2], n[0], n[1], n[2]));
+ else if(!hasNormals && hasTextureCoord) triangle_list.push_back(triangle(v[0], v[1], v[2], t[0], t[1], t[2]));
+ else triangle_list.push_back(triangle(v[0], v[1], v[2], n[0], n[1], n[2], t[0], t[1], t[2]));
+
+ // cycle (to support polygons)
+ v[1] = v[2];
+ n[1] = n[2];
+ t[1] = t[2];
+ }
+ else idx++;
+ }
+ else errorMessage("Unknown child element in %s node (%s).", node.name().c_str(), name.c_str());
+ }
+
+ // check if at least one full triangle was found
+ if(idx != 2)
+ errorMessage("%s requires at least 3 vertices.", node.name().c_str());
+
+ // Done.
+ }
+
+
+/////////////////////////////////////////////////////////////////
+static std::shared_ptr<boundedPrimitive> importTriangleMesh(const XMLNode& node, nodeCache<boundedPrimitive>& shape_cache, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir)
+{
+ // sanity check
+ assert(node.name() == "triangleMesh");
+
+ // allocate node properties
+ transformation3d transform;
+ std::shared_ptr<const shader_base> material;
+ std::vector<triangle> triangle_list;
+
+ // import OBJ triangles
+ std::string objname = getString(node, "filename");
+ if(objname != "")
+ {
+ std::string path = getDirectory(objname);
+ if(path == "") objname = rootDir + objname;
+ importOBJ(objname, triangle_list);
+ }
+
+ // check child nodes
+ for(XMLNode child = node.firstChild(); child.isValid(); child++)
+ {
+ std::string name = child.name();
+
+ // general child nodes
+ auto tempmat = importMaterial(child, shader_cache, texture_cache, rootDir);
+ if(tempmat) material = tempmat;
+
+ // specialized child nodes
+ else if(name == "transformation") importTransformation(child, transform);
+ else if(name == "triangle" || name == "polygon") importTriangle(child, triangle_list);
+ else errorMessage("Unknown child-node in triangleMesh (%s).", name.c_str());
+ }
+
+ // Done.
+ return std::shared_ptr<boundedPrimitive>(new triangleMesh(triangle_list, material, transform));
+}
+
+/////////////////////////////////////////////////////////////////
+
+static std::shared_ptr<boundedPrimitive> importSceneGraphNode(const XMLNode& node, nodeCache<boundedPrimitive>& shape_cache, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir)
+{
+ // sanity check
+ assert(node.name() == "sceneGraphNode");
+
+ // node properties
+ transformation3d transform;
+ std::shared_ptr<const shader_base> material;
+ std::vector<std::shared_ptr<const boundedPrimitive>> child_nodes;
+
+ // check child nodes
+ for(XMLNode child = node.firstChild(); child.isValid(); child++)
+ {
+ std::string name = child.name();
+
+ // general child nodes
+ auto tempmat = importMaterial(child, shader_cache, texture_cache, rootDir);
+ auto shape = importGeometry(child, shape_cache, shader_cache, texture_cache, rootDir);
+
+ if(tempmat) material = tempmat;
+ else if(shape) child_nodes.push_back(shape);
+
+ // node specific children.
+ else if(name == "transformation") importTransformation(child, transform);
+ else errorMessage("Unknown child-node in sceneGraphNode (%s).", name.c_str());
+ }
+
+ // Done.
+ return std::shared_ptr<boundedPrimitive>(new sceneGraphNode(child_nodes, transform, material));
+}
+
+/////////////////////////////////////////////////////////////////
+std::shared_ptr<boundedPrimitive> importGeometry(const XMLNode& node, nodeCache<boundedPrimitive>& shape_cache, nodeCache<shader_base>& shader_cache, nodeCache<texture_base>& texture_cache, const std::string& rootDir)
+{
+ // check if geometry type
+ if(node.name() != "sceneGraphNode" && node.name() != "triangleMesh") return std::shared_ptr<boundedPrimitive>(nullptr);
+
+ // check if reference
+ std::string ref = getString(node, "ref");
+ std::shared_ptr<boundedPrimitive> shape = shape_cache.get(ref);
+ if(shape) return shape;
+ else if(ref != "") errorMessage("Unknown %s name (%s).", node.name().c_str(), ref.c_str());
+
+ // generate default name & get id
+ char defaultname[32]; sprintf(defaultname, "noname-%u", random_int());
+ std::string id = getString(node, "id", defaultname);
+
+ if(shape_cache.get(id))
+ errorMessage("%s-node id is not unique (%s).", node.name().c_str(), id.c_str());
+
+ // process primitive based on type
+ if(node.name() == "sceneGraphNode") shape = importSceneGraphNode(node, shape_cache, shader_cache, texture_cache, rootDir);
+ else if(node.name() == "triangleMesh") shape = importTriangleMesh(node, shape_cache, shader_cache, texture_cache, rootDir);
+
+ // update cache
+ if(id != "") shape_cache.add(id, shape);
+
+ // Done.
+ return shape;
+}