From db072ad4dc181eca5a1458656b130beb43f475bf Mon Sep 17 00:00:00 2001 From: 53hornet <53hornet@gmail.com> Date: Sat, 2 Feb 2019 23:33:15 -0500 Subject: Init. --- hw3/src/sceneIO_geometry.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 hw3/src/sceneIO_geometry.cpp (limited to 'hw3/src/sceneIO_geometry.cpp') diff --git a/hw3/src/sceneIO_geometry.cpp b/hw3/src/sceneIO_geometry.cpp new file mode 100644 index 0000000..dd15ddb --- /dev/null +++ b/hw3/src/sceneIO_geometry.cpp @@ -0,0 +1,153 @@ +/******************************************************************/ +/* 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 +#include +#include +#include +#include + +#include "sceneIO_xml.h" +#include "sceneIO_core.h" +#include "sceneIO_cache.h" +#include "sceneIO_geometry.h" +#include "sceneIO_material.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_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[1], n[2], n[3])); + 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[1], n[2], n[3], t[0], t[1], t[2])); + + // cycle (to support polygons) + v[1] = v[2]; + n[1] = v[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 importTriangleMesh(const XMLNode& node, nodeCache& shape_cache, nodeCache& shader_cache, nodeCache& texture_cache, const std::string& rootDir) +{ + // sanity check + assert(node.name() == "triangleMesh"); + + // allocate node properties + transformation3d transform; + std::shared_ptr material; + std::vector 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 == "triangle" || name == "polygon") importTriangle(child, triangle_list); + else errorMessage("Unknown child-node in triangleMesh (%s).", name.c_str()); + } + + // Done. + return std::shared_ptr(new triangleMesh(triangle_list, material, transform)); +} + +///////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////// +std::shared_ptr importGeometry(const XMLNode& node, nodeCache& shape_cache, nodeCache& shader_cache, nodeCache& texture_cache, const std::string& rootDir) +{ + // check if geometry type + if(node.name() != "sceneGraphNode" && node.name() != "triangleMesh") return std::shared_ptr(nullptr); + + // check if reference + std::string ref = getString(node, "ref"); + std::shared_ptr 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 + 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; +} -- cgit v1.2.3