diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
commit | db072ad4dc181eca5a1458656b130beb43f475bf (patch) | |
tree | a3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/sceneIO_geometry.cpp | |
download | csci427-master.tar.xz csci427-master.zip |
Diffstat (limited to 'hw6/src/sceneIO_geometry.cpp')
-rw-r--r-- | hw6/src/sceneIO_geometry.cpp | 187 |
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; +} |