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/include/.directory | 4 + hw3/include/boundedCompound.h | 55 + hw3/include/boundedPrimitive.h | 67 + hw3/include/boundedTriangle.h | 46 + hw3/include/boundingBox.h | 77 ++ hw3/include/brdf_base.h | 47 + hw3/include/camera.h | 80 ++ hw3/include/color.h | 105 ++ hw3/include/compoundShader.h | 51 + hw3/include/constants.h | 16 + hw3/include/coordinateTransform.h | 31 + hw3/include/diffuseBrdf.h | 59 + hw3/include/diffuseReflectanceShader.h | 45 + hw3/include/directionalLightsource.h | 55 + hw3/include/errorMessage.h | 17 + hw3/include/image.h | 89 ++ hw3/include/imageIO.h | 19 + hw3/include/imageIO.pfm.h | 18 + hw3/include/imageIO.ppm.h | 18 + hw3/include/importOBJ.h | 18 + hw3/include/intersectionPoint.h | 110 ++ hw3/include/intersector_base.h | 34 + hw3/include/intersector_factory_base.h | 29 + hw3/include/interval.h | 77 ++ hw3/include/lightSample.h | 75 ++ hw3/include/lightsource_base.h | 51 + hw3/include/linear_intersector.h | 62 + hw3/include/mat3d.h | 112 ++ hw3/include/phongBrdf.h | 60 + hw3/include/phongReflectanceShader.h | 46 + hw3/include/random_number.h | 50 + hw3/include/ray.h | 69 + hw3/include/reflectanceParameter.h | 106 ++ hw3/include/reflectanceShader_base.h | 45 + hw3/include/scene.h | 59 + hw3/include/sceneGraphNode.h | 45 + hw3/include/sceneIO.h | 17 + hw3/include/sceneIO_basis.h | 22 + hw3/include/sceneIO_cache.h | 52 + hw3/include/sceneIO_cache.inline.h | 66 + hw3/include/sceneIO_core.h | 24 + hw3/include/sceneIO_geometry.h | 23 + hw3/include/sceneIO_light.h | 25 + hw3/include/sceneIO_material.h | 22 + hw3/include/sceneIO_xml.h | 51 + hw3/include/shaderProperties.h | 38 + hw3/include/shader_base.h | 59 + hw3/include/shadingFrameTransformation.h | 57 + hw3/include/texture_base.h | 67 + hw3/include/tinyxml2.h | 2102 ++++++++++++++++++++++++++++++ hw3/include/transformation3d.h | 77 ++ hw3/include/triangle.h | 115 ++ hw3/include/triangleMesh.h | 51 + hw3/include/util.h | 19 + hw3/include/vec2d.h | 117 ++ hw3/include/vec3d.h | 120 ++ 56 files changed, 5071 insertions(+) create mode 100644 hw3/include/.directory create mode 100644 hw3/include/boundedCompound.h create mode 100644 hw3/include/boundedPrimitive.h create mode 100644 hw3/include/boundedTriangle.h create mode 100644 hw3/include/boundingBox.h create mode 100644 hw3/include/brdf_base.h create mode 100644 hw3/include/camera.h create mode 100644 hw3/include/color.h create mode 100644 hw3/include/compoundShader.h create mode 100644 hw3/include/constants.h create mode 100644 hw3/include/coordinateTransform.h create mode 100644 hw3/include/diffuseBrdf.h create mode 100644 hw3/include/diffuseReflectanceShader.h create mode 100644 hw3/include/directionalLightsource.h create mode 100644 hw3/include/errorMessage.h create mode 100644 hw3/include/image.h create mode 100644 hw3/include/imageIO.h create mode 100644 hw3/include/imageIO.pfm.h create mode 100644 hw3/include/imageIO.ppm.h create mode 100644 hw3/include/importOBJ.h create mode 100644 hw3/include/intersectionPoint.h create mode 100644 hw3/include/intersector_base.h create mode 100644 hw3/include/intersector_factory_base.h create mode 100644 hw3/include/interval.h create mode 100644 hw3/include/lightSample.h create mode 100644 hw3/include/lightsource_base.h create mode 100644 hw3/include/linear_intersector.h create mode 100644 hw3/include/mat3d.h create mode 100644 hw3/include/phongBrdf.h create mode 100644 hw3/include/phongReflectanceShader.h create mode 100644 hw3/include/random_number.h create mode 100644 hw3/include/ray.h create mode 100644 hw3/include/reflectanceParameter.h create mode 100644 hw3/include/reflectanceShader_base.h create mode 100644 hw3/include/scene.h create mode 100644 hw3/include/sceneGraphNode.h create mode 100644 hw3/include/sceneIO.h create mode 100644 hw3/include/sceneIO_basis.h create mode 100644 hw3/include/sceneIO_cache.h create mode 100644 hw3/include/sceneIO_cache.inline.h create mode 100644 hw3/include/sceneIO_core.h create mode 100644 hw3/include/sceneIO_geometry.h create mode 100644 hw3/include/sceneIO_light.h create mode 100644 hw3/include/sceneIO_material.h create mode 100644 hw3/include/sceneIO_xml.h create mode 100644 hw3/include/shaderProperties.h create mode 100644 hw3/include/shader_base.h create mode 100644 hw3/include/shadingFrameTransformation.h create mode 100644 hw3/include/texture_base.h create mode 100644 hw3/include/tinyxml2.h create mode 100644 hw3/include/transformation3d.h create mode 100644 hw3/include/triangle.h create mode 100644 hw3/include/triangleMesh.h create mode 100644 hw3/include/util.h create mode 100644 hw3/include/vec2d.h create mode 100644 hw3/include/vec3d.h (limited to 'hw3/include') diff --git a/hw3/include/.directory b/hw3/include/.directory new file mode 100644 index 0000000..f009e80 --- /dev/null +++ b/hw3/include/.directory @@ -0,0 +1,4 @@ +[Dolphin] +Timestamp=2016,2,3,13,45,20 +Version=3 +ViewMode=1 diff --git a/hw3/include/boundedCompound.h b/hw3/include/boundedCompound.h new file mode 100644 index 0000000..ab396f3 --- /dev/null +++ b/hw3/include/boundedCompound.h @@ -0,0 +1,55 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _BOUNDED_COMPOUND_H_ +#define _BOUNDED_COMPOUND_H_ + +#include "intersector_base.h" +#include "transformation3d.h" +#include "boundedPrimitive.h" + +class boundedCompound : public boundedPrimitive { + public: + ///////////////// + // Constructor // + ///////////////// + boundedCompound(void); + boundedCompound(const transformation3d& transform, const std::shared_ptr& shader=nullptr); + boundedCompound(const boundedCompound&) = delete; + + /////////////// + // Operators // + /////////////// + boundedCompound& operator=(const boundedCompound&) = delete; + + ///////////// + // Methods // + ///////////// + void initialize(const class intersector_factory_base& ifb); + + virtual bool hasShader(void) const override; + + virtual intersectionPoint intersect(const ray& r) const final override; + + virtual const std::vector>& compounds(void) const = 0; + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + void initializeBoundingBox(void); + virtual void _print(std::ostream& s) const override; + + ////////////////// + // Data Members // + ////////////////// + transformation3d _transform; + std::unique_ptr _intersector; +}; + +#endif /* _BOUNDED_COMPOUND_H_ */ diff --git a/hw3/include/boundedPrimitive.h b/hw3/include/boundedPrimitive.h new file mode 100644 index 0000000..ef467a2 --- /dev/null +++ b/hw3/include/boundedPrimitive.h @@ -0,0 +1,67 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _BOUNDED_PRIMITIVE_H_ +#define _BOUNDED_PRIMITIVE_H_ + +#include +#include +#include + +#include "ray.h" +#include "shader_base.h" +#include "boundingBox.h" +#include "intersectionPoint.h" + +class boundedPrimitive { + public: + ///////////////// + // Constructor // + ///////////////// + boundedPrimitive(void); + boundedPrimitive(const boundingBox& bb, const std::shared_ptr& shader); + boundedPrimitive(const boundedPrimitive&) = delete; + + /////////////// + // Operators // + /////////////// + boundedPrimitive& operator=(const boundedPrimitive& ) = delete; + + ///////////// + // Methods // + ///////////// + const boundingBox& boundingbox(void) const; + bool hitBoundingBox(const ray& r) const; + virtual bool hasShader(void) const; + + virtual intersectionPoint intersect(const ray& r) const = 0; + + ///////////// + // Friends // + ///////////// + friend std::ostream& operator<<(std::ostream& s, const boundedPrimitive& bp) + { + bp._print(s); + return s; + } + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const; + + ////////////////// + // Data Members // + ////////////////// + boundingBox _bb; + std::shared_ptr _shader; +}; + +#endif /* _BOUNDED_PRIMITIVE_H_ */ + diff --git a/hw3/include/boundedTriangle.h b/hw3/include/boundedTriangle.h new file mode 100644 index 0000000..965c0ff --- /dev/null +++ b/hw3/include/boundedTriangle.h @@ -0,0 +1,46 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _BOUNDEDTRIANGLE_H_ +#define _BOUNDEDTRIANGLE_H_ + +#include "triangle.h" +#include "boundedPrimitive.h" + +class boundedTriangle : public boundedPrimitive { + public: + ////////////////// + // Constructors // + ////////////////// + boundedTriangle(void); + boundedTriangle(const triangle& tri, const std::shared_ptr& shader); + boundedTriangle(const boundedTriangle&) = delete; + + /////////////// + // Operators // + /////////////// + boundedTriangle& operator=(const boundedTriangle&) = delete; + + ///////////// + // Methods // + ///////////// + virtual intersectionPoint intersect(const ray& r) const final override; + + private: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const override; + + ////////////////// + // Data Members // + ////////////////// + triangle _triangle; +}; + +#endif /* _BOUNDEDTRIANGLE_H_ */ diff --git a/hw3/include/boundingBox.h b/hw3/include/boundingBox.h new file mode 100644 index 0000000..522672e --- /dev/null +++ b/hw3/include/boundingBox.h @@ -0,0 +1,77 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _BOUNDINGBOX_H_ +#define _BOUNDINGBOX_H_ + +#include + +#include "ray.h" +#include "vec3d.h" +#include "transformation3d.h" + +class boundingBox { + public: + ///////////////// + // Constructor // + ///////////////// + boundingBox(void); + boundingBox(const vec3d& lfb, const vec3d& rbt); + boundingBox(const boundingBox& bb); + + ////////////// + // Operator // + ////////////// + boundingBox& operator=(const boundingBox& src); + + boundingBox& operator+=(const boundingBox& bb); + boundingBox& operator+=(const vec3d& point); + + boundingBox operator+(const boundingBox& bb) const; + + ///////////// + // Methods // + ///////////// + bool isHit(const ray& r) const; + + vec3d center(void) const; + vec3d corner(bool left, bool front, bool bottom) const; + + ////////////// + // Mutators // + ////////////// + boundingBox& transform(const transformation3d& t); + boundingBox& inverseTransform(const transformation3d& t); + + ///////////// + // Friends // + ///////////// + friend void swap(boundingBox& a, boundingBox& b) { a._swap(b); } + friend boundingBox transform(const boundingBox& bb, const transformation3d& t) { return boundingBox(bb).transform(t); } + friend boundingBox inverseTransform(const boundingBox& bb, const transformation3d& t) { return boundingBox(bb).inverseTransform(t); } + friend std::ostream& operator<<(std::ostream& s, const boundingBox& bb) + { + s << bb._lfb << " - " << bb._rbt; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _swap(boundingBox& bb); + void _assign(const boundingBox& bb); + + ////////////////// + // Data Members // + ////////////////// + vec3d _lfb, _rbt; +}; + + +#endif /* _BOUNDINGBOX_H_ */ diff --git a/hw3/include/brdf_base.h b/hw3/include/brdf_base.h new file mode 100644 index 0000000..e0d8009 --- /dev/null +++ b/hw3/include/brdf_base.h @@ -0,0 +1,47 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _BRDF_BASE_H_ +#define _BRDF_BASE_H_ + +#include +#include "vec3d.h" +#include "color.h" + +class brdf_base { + public: + ///////////// + // Methods // + ///////////// + + // Note: 'in' and 'out' point away from the surface point + // Note: 'in' and 'out' are specified in the local shading frame, + // where the normal=(0.0, 0.0, 1.0). + virtual color shade(const vec3d& in, const vec3d& out) const = 0; + + // returns true if BRDF has a specular/diffuse component + virtual bool isSpecular(void) const = 0; + virtual bool isDiffuse(void) const = 0; + + ///////////// + // Friends // + ///////////// + friend std::ostream& operator<<(std::ostream& s, const brdf_base& b) + { + b._print(s); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + virtual void _print(std::ostream& s) const = 0; +}; + +#endif /* _BRDF_BASE_H_ */ diff --git a/hw3/include/camera.h b/hw3/include/camera.h new file mode 100644 index 0000000..9e3be04 --- /dev/null +++ b/hw3/include/camera.h @@ -0,0 +1,80 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _CAMERA_H_ +#define _CAMERA_H_ + +#include + +#include "ray.h" +#include "vec2d.h" +#include "boundingBox.h" + +/**************************************************************/ +/* Note: Field of View (fov) is expressed in degrees, and */ +/* represents the angular spread in the horizontal direction. */ +/**************************************************************/ +class camera { + public: + ///////////////// + // Constructor // + ///////////////// + camera(void); + camera(const vec3d& eye, const vec3d& viewDirection, const vec3d& up, float fov, size_t xres, size_t yres); + camera(const camera& cam); + + /////////////// + // Operators // + /////////////// + camera& operator=(const camera& cam); + + ray operator()(float x, float y) const; + + //////////////// + // Inspectors // + //////////////// + size_t width(void) const { return _width; } + size_t height(void) const { return _height; } + + ////////////// + // Mutators // + ////////////// + void frameBoundingBox(const boundingBox& bb); + + ///////////// + // Friends // + ///////////// + friend void swap(camera& a, camera& b) { a._swap(b); } + friend std::ostream& operator<<(std::ostream& s, const camera& cam) + { + s << "Camera: {"; + s << "eye=" << cam._eye << ", "; + s << "view=" << cam._view << ", "; + s << "up=" << cam._up << "}, "; + s << "fov=" << cam._fov << ", "; + s << "resolution=[" << cam._width << "x" << cam._height << "]"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _swap(camera& cam); + void _assign(const camera& cam); + + ////////////////// + // Data Members // + ////////////////// + vec3d _eye, _view, _up; + float _fov; + size_t _width, _height; +}; + +#endif /* _CAMERA_H_ */ + diff --git a/hw3/include/color.h b/hw3/include/color.h new file mode 100644 index 0000000..b2ca490 --- /dev/null +++ b/hw3/include/color.h @@ -0,0 +1,105 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _COLOR_H_ +#define _COLOR_H_ + +#include + +class color { + public: + ///////////// + // Typedef // + ///////////// + typedef float value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + + ////////////////// + // Data Members // + ////////////////// + union { + struct { value_type r, g, b; }; + struct { value_type red, green, blue; }; + value_type data[3]; + }; + + public: + ///////////////// + // Constructor // + ///////////////// + explicit color(const_reference value=0.0f); + color(const_reference r, const_reference g, const_reference b); + color(const color& col); + + //////////////// + // Inspectors // + //////////////// + const_reference operator[](size_t index) const; + reference operator[](size_t index); + + size_t size(void) const { return 3; } + + iterator begin(void); + const_iterator begin(void) const; + iterator end(void); + const_iterator end(void) const; + + /////////////// + // Operators // + /////////////// + color& operator=(const color& col); + + bool operator==(const color& col) const; + bool operator!=(const color& col) const; + + color operator+(const color& col) const; + color operator-(const color& col) const; + color operator*(const color& col) const; + color operator*(const_reference scale) const; + color operator/(const color& col) const; + color operator/(const_reference scale) const; + + color& operator+=(const color& col); + color& operator-=(const color& col); + color& operator*=(const color& col); + color& operator*=(const_reference scale); + color& operator/=(const color& col); + color& operator/=(const_reference scale); + + /////////////// + // Modifiers // + /////////////// + color& abs(void); + color& clamp(const_reference lowerBound=0.0f, const_reference upperBounds=1.0f); + + ///////////// + // Friends // + ///////////// + friend void swap(color& a, color& b) { return a._swap(b); } + friend color abs(const color& c) { return color(c).abs(); } + friend color clamp(const color& c, const_reference lowerBound=0.0f, const_reference upperBound=1.0f) { return color(c).clamp(lowerBound, upperBound); } + friend color operator*(const_reference scale, const color& col) { return (col*scale); } + + friend std::ostream& operator<<(std::ostream& s, const color& col) + { + s << "(" << col.r << "," << col.g << "," << col.b << ")"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const color& col); + void _swap(color& col); +}; + +#endif /* _COLOR_H_ */ diff --git a/hw3/include/compoundShader.h b/hw3/include/compoundShader.h new file mode 100644 index 0000000..293e7d6 --- /dev/null +++ b/hw3/include/compoundShader.h @@ -0,0 +1,51 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _COMPOUND_SHADER_H_ +#define _COMPOUND_SHADER_H_ + +#include +#include + +#include "shader_base.h" + +class compoundShader : public shader_base { + public: + ////////////////// + // Constructors // + ////////////////// + compoundShader(const std::vector>& shader_list); + compoundShader(const compoundShader&) = delete; + + /////////////// + // Operators // + /////////////// + compoundShader& operator=(const compoundShader&) = delete; + + ///////////// + // Methods // + ///////////// + virtual color shade(const intersectionPoint& ip, const vec3d& light_dir) const override; + + virtual shaderProperties properties(const intersectionPoint& ip) const override; + + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const override; + + private: + ////////////////// + // Data Members // + ////////////////// + std::vector> _compound; +}; + +#endif /* _COMPOUND_SHADER_H_ */ diff --git a/hw3/include/constants.h b/hw3/include/constants.h new file mode 100644 index 0000000..daa1c45 --- /dev/null +++ b/hw3/include/constants.h @@ -0,0 +1,16 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _CONSTANTS_H_ +#define _CONSTANTS_H_ + +static const float EPSILON = 10e-6; +static const float LARGE = 10e10; +static const float PI = 3.14159265359; + +#endif /* _CONSTANTS_H_ */ diff --git a/hw3/include/coordinateTransform.h b/hw3/include/coordinateTransform.h new file mode 100644 index 0000000..008cba7 --- /dev/null +++ b/hw3/include/coordinateTransform.h @@ -0,0 +1,31 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _COORDINATETRANSFORMATION3D_H_ +#define _COORDINATETRANSFORMATION3D_H_ + +#include "transformation3d.h" + +/////////////////////////////////////////////// +// Transformation between coordinate systems // +// forward transform: from local to global // +// inverse transform: from global to local // +/////////////////////////////////////////////// +class coordinateTransformation : public transformation3d { + public: + ////////////////// + // Constructors // + ////////////////// + coordinateTransformation(void); + coordinateTransformation(const vec3d& normal); + coordinateTransformation(const vec3d& normal, const vec3d& other); + coordinateTransformation(const vec3d& X, const vec3d& Y, const vec3d& Z); +}; + +#endif /* _COORDINATETRANSFORMATION3D_H_ */ + diff --git a/hw3/include/diffuseBrdf.h b/hw3/include/diffuseBrdf.h new file mode 100644 index 0000000..e4ab19f --- /dev/null +++ b/hw3/include/diffuseBrdf.h @@ -0,0 +1,59 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _DIFFUSEBRDF_H_ +#define _DIFFUSEBRDF_H_ + +#include "brdf_base.h" + +class diffuseBrdf : public brdf_base { + public: + ////////////////// + // Constructors // + ////////////////// + diffuseBrdf(const color& albedo); + diffuseBrdf(const diffuseBrdf& src); + + /////////////// + // Operators // + /////////////// + diffuseBrdf& operator=(const diffuseBrdf& src); + + ///////////// + // Methods // + ///////////// + virtual color shade(const vec3d& in, const vec3d& out) const final override; + + virtual bool isSpecular(void) const final override; + virtual bool isDiffuse(void) const final override; + + ///////////// + // Friends // + ///////////// + friend void swap(diffuseBrdf& a, diffuseBrdf& b) { a._swap(b); } + friend std::ostream& operator<<(std::ostream& s, const diffuseBrdf& b) + { + b._print(s); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const diffuseBrdf& src); + void _swap(diffuseBrdf& src); + virtual void _print(std::ostream& s) const override; + + ////////////////// + // Data Members // + ////////////////// + color _albedo; +}; + +#endif /* _DIFFUSEBRDF_H_ */ diff --git a/hw3/include/diffuseReflectanceShader.h b/hw3/include/diffuseReflectanceShader.h new file mode 100644 index 0000000..bee9d8d --- /dev/null +++ b/hw3/include/diffuseReflectanceShader.h @@ -0,0 +1,45 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _DIFFUSEREFLECTANCESHADER_H_ +#define _DIFFUSEREFLECTANCESHADER_H_ + +#include "diffuseBrdf.h" +#include "reflectanceParameter.h" +#include "reflectanceShader_base.h" + +class diffuseReflectanceShader : public reflectanceShader_base { + public: + ///////////////// + // Constructor // + ///////////////// + diffuseReflectanceShader(const colorReflectanceParameter& albedo=colorReflectanceParameter(color(1.0f, 1.0f, 1.0f))); + diffuseReflectanceShader(const diffuseReflectanceShader& ) = delete; + + /////////////// + // Operators // + /////////////// + diffuseReflectanceShader& operator=(const diffuseReflectanceShader&) = delete; + +protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual std::unique_ptr make_brdf(const vec2d& textureCoord) const override; + + virtual void _print(std::ostream& s) const override; + +private: + ////////////////// + // Data Members // + ////////////////// + colorReflectanceParameter _albedo; +}; + +#endif /* _DIFFUSEREFLECTANCESHADER_H_ */ + diff --git a/hw3/include/directionalLightsource.h b/hw3/include/directionalLightsource.h new file mode 100644 index 0000000..b33dfaf --- /dev/null +++ b/hw3/include/directionalLightsource.h @@ -0,0 +1,55 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _DIRECTIONALLIGHTSOURCE_H_ +#define _DIRECTIONALLIGHTSOURCE_H_ + +#include "lightsource_base.h" + +class directionalLightsource : public lightsource_base { + public: + ////////////////// + // Constructors // + ////////////////// + directionalLightsource(const vec3d& direction=vec3d(0.0f, 0.0f, 1.0f), const color& power=color(1.0f, 1.0f, 1.0f)); + directionalLightsource(const directionalLightsource&) = delete; + + /////////////// + // Operators // + /////////////// + directionalLightsource& operator=(const directionalLightsource&) = delete; + + ///////////// + // Methods // + ///////////// + virtual lightSample intensityAt(const vec3d& point) const override; + + ///////////// + // Friends // + ///////////// + friend std::ostream& operator<<(std::ostream& s, const directionalLightsource& d) + { + d._print(s); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + virtual void _print(std::ostream& s) const override; + + private: + ////////////////// + // Data Members // + ////////////////// + vec3d _direction; + color _power; +}; + +#endif /* _DIRECTIONALLIGHTSOURCE_H_ */ diff --git a/hw3/include/errorMessage.h b/hw3/include/errorMessage.h new file mode 100644 index 0000000..7ec99d1 --- /dev/null +++ b/hw3/include/errorMessage.h @@ -0,0 +1,17 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _ERROR_MESSAGE_H_ +#define _ERROR_MESSAGE_H_ + +#include + +void errorMessage(const char* msg, ...); +void warningMessage(const char* msg, ...); + +#endif /* _ERROR_MESSAGE_H_ */ diff --git a/hw3/include/image.h b/hw3/include/image.h new file mode 100644 index 0000000..938e6c0 --- /dev/null +++ b/hw3/include/image.h @@ -0,0 +1,89 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +#include +#include +#include + +#include "color.h" + +class image { + public: + ////////////// + // Typedefs // + ////////////// + typedef color value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::unique_ptr::pointer iterator; + typedef std::unique_ptr::pointer const_iterator; + typedef size_t difference_type; + typedef size_t size_type; + + ////////////////// + // Constructors // + ////////////////// + image(size_type width=0, size_type height=0); + image(size_type width, size_type height, const_reference col); + image(const image& src); + image(image&& src); + + virtual ~image(void) { _data.reset(); } + + //////////////// + // Inspectors // + //////////////// + iterator begin(void); + const_iterator begin(void) const; + + iterator end(void); + const_iterator end(void) const; + + size_type size(void) const { return width()*height(); } + size_type width(void) const { return _width; } + size_type height(void) const { return _height; } + + + /////////////// + // Operators // + /////////////// + image& operator=(const image& src); + image& operator=(image&& src); + + reference operator()(size_type x, size_type y); + const_reference operator()(size_type x, size_type y) const; + + ///////////// + // Friends // + ///////////// + friend void swap(image& a, image& b) { a._swap(b); } + friend std::ostream& operator<<(std::ostream& s, const image& img) + { + s << "Image: (" << img.width() << ", " << img.height() << ")"; + return s; + } + +protected: + ///////////////////// + // Private Methods // + ///////////////////// + void _swap(image& img); + void _assign(const image& src); + +private: + ////////////////////////// + // Private Data Members // + ////////////////////////// + size_type _width, _height; + std::unique_ptr _data; +}; + +#endif /* _IMAGE_H_ */ diff --git a/hw3/include/imageIO.h b/hw3/include/imageIO.h new file mode 100644 index 0000000..9e1ecfa --- /dev/null +++ b/hw3/include/imageIO.h @@ -0,0 +1,19 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _IMAGEIO_H_ +#define _IMAGEIO_H_ + +#include +#include "image.h" + +void importImage(const std::string& name, image& img); +void exportImage(const std::string& name, const image& img); + +#endif /* _IMAGEIO_H_ */ + diff --git a/hw3/include/imageIO.pfm.h b/hw3/include/imageIO.pfm.h new file mode 100644 index 0000000..d09531a --- /dev/null +++ b/hw3/include/imageIO.pfm.h @@ -0,0 +1,18 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _IMAGEIO_PFM_H_ +#define _IMAGEIO_PFM_H_ + +#include +#include "image.h" + +void importPFM(const std::string& name, image& img); +void exportPFM(const std::string& name, const image& img); + +#endif /* _IMAGEIO_PFM_H_ */ diff --git a/hw3/include/imageIO.ppm.h b/hw3/include/imageIO.ppm.h new file mode 100644 index 0000000..7a8db42 --- /dev/null +++ b/hw3/include/imageIO.ppm.h @@ -0,0 +1,18 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _IMAGEIO_PPM_H_ +#define _IMAGEIO_PPM_H_ + +#include +#include "image.h" + +void importPPM(const std::string& name, image& img); +void exportPPM(const std::string& name, const image& img); + +#endif /* _IMAGEIO_PPM_H_ */ diff --git a/hw3/include/importOBJ.h b/hw3/include/importOBJ.h new file mode 100644 index 0000000..056a420 --- /dev/null +++ b/hw3/include/importOBJ.h @@ -0,0 +1,18 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _IMPORTOBJ_H_ +#define _IMPORTOBJ_H_ + +#include +#include +#include "triangle.h" + +void importOBJ(const std::string filename, std::vector& triangle_list); + +#endif /* _IMPORTOBJ_H_ */ diff --git a/hw3/include/intersectionPoint.h b/hw3/include/intersectionPoint.h new file mode 100644 index 0000000..a4d8888 --- /dev/null +++ b/hw3/include/intersectionPoint.h @@ -0,0 +1,110 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _INTERSECTIONPOINT_H_ +#define _INTERSECTIONPOINT_H_ + +#include +#include + +#include "ray.h" +#include "vec3d.h" +#include "vec2d.h" +#include "color.h" +#include "constants.h" +#include "lightSample.h" +#include "transformation3d.h" +#include "shaderProperties.h" +#include "coordinateTransform.h" + + +class intersectionPoint +{ + public: + ///////////////// + // Constructor // + ///////////////// + intersectionPoint(void); + intersectionPoint(const ray& r, float rayParameter=+LARGE, const std::shared_ptr& shader=nullptr, const vec3d& normal=vec3d(0.0f, 0.0f, 1.0f), const vec3d& U=vec3d(1.0f, 0.0f, 0.0f), const vec2d& textureCoordinate=vec2d(0.0f, 0.0f)); + intersectionPoint(const intersectionPoint& ip); + + /////////////// + // Operators // + /////////////// + intersectionPoint& operator=(const intersectionPoint& ip); + + bool operator<(const intersectionPoint& ip) const; + bool operator>(const intersectionPoint& ip) const; + bool operator<(const lightSample& ls) const; + bool operator>(const lightSample& ls) const; + + //////////////// + // Inspectors // + //////////////// + bool isHit(void) const; + bool hasShader(void) const; + shaderProperties getShaderProperties(void) const; + float distance(const intersectionPoint& ip) const; + const vec3d& position(void) const; + const vec3d& direction(void) const; + const vec2d& textureCoordinate(void) const; + const vec3d& normal(void) const; + coordinateTransformation shadingFrame(void) const; + + ////////////// + // Mutators // + ////////////// + void transform(const transformation3d& t); + void inverseTransform(const transformation3d& t); + + void transformShadingFrame(const transformation3d& sft); + void inverseTransformShadingFrame(const transformation3d& sft); + + void setShader(const std::shared_ptr& shader); + + ///////////// + // Methods // + ///////////// + color shade(const vec3d& out) const; + color shade(const lightSample& ls) const; + + ///////////// + // Friends // + ///////////// + friend void swap(intersectionPoint& a, intersectionPoint& b) { a._swap(b); } + + friend bool operator<(const lightSample& ls, const intersectionPoint& ip) { return (ip > ls); } + friend bool operator>(const lightSample& ls, const intersectionPoint& ip) { return (ip < ls); } + + friend std::ostream& operator<<(std::ostream& s, const intersectionPoint& ip) + { + if(ip._hit) s << "IntersectionPoint: ray=" << ip._ray << ", position=" << ip._position << " (parameter=" << ip._rayParameter << ", normal=" << ip._normal << ", shading axis=" << ip._U << ", texture coordinate=" << ip._textureCoordinate; + else s << "IntersectionPoint: empty"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const intersectionPoint& ip); + void _swap(intersectionPoint& ip); + + ////////////////// + // Data Members // + ////////////////// + ray _ray; + bool _hit; + float _rayParameter; + vec3d _position; + vec3d _normal, _U; + vec2d _textureCoordinate; + std::shared_ptr _shader; +}; + +#endif /* _INTERSECTIONPOINT_H_ */ diff --git a/hw3/include/intersector_base.h b/hw3/include/intersector_base.h new file mode 100644 index 0000000..64fb05e --- /dev/null +++ b/hw3/include/intersector_base.h @@ -0,0 +1,34 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _INTERSECTOR_BASE_H_ +#define _INTERSECTOR_BASE_H_ + +#include "ray.h" +#include "intersectionPoint.h" + +class intersector_base { + public: + ////////////////// + // Constructors // + ////////////////// + intersector_base(void) {} + intersector_base(const intersector_base&) = delete; + + /////////////// + // Operators // + /////////////// + intersector_base& operator=(const intersector_base&) = delete; + + ///////////// + // Methods // + ///////////// + virtual intersectionPoint intersect(const ray& r) const = 0; +}; + +#endif /* _INTERSECTOR_BASE_H_ */ diff --git a/hw3/include/intersector_factory_base.h b/hw3/include/intersector_factory_base.h new file mode 100644 index 0000000..c6e9e98 --- /dev/null +++ b/hw3/include/intersector_factory_base.h @@ -0,0 +1,29 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _INTERSECTOR_FACTORY_BASE_H_ +#define _INTERSECTOR_FACTORY_BASE_H_ + +#include +#include "boundedCompound.h" +#include "intersector_base.h" + +class intersector_factory_base { +public: + ///////////////// + // Constructor // + ///////////////// + intersector_factory_base(void) {} + + ////////////// + // Operator // + ////////////// + virtual std::unique_ptr operator()(const boundedCompound& bc) const = 0; +}; + +#endif /* _INTERSECTOR_FACTORY_BASE_H_ */ diff --git a/hw3/include/interval.h b/hw3/include/interval.h new file mode 100644 index 0000000..ccb720a --- /dev/null +++ b/hw3/include/interval.h @@ -0,0 +1,77 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _INTERVAL_H_ +#define _INTERVAL_H_ + +#include + +#include "constants.h" + +class interval +{ + public: + ////////////////// + // Constrructor // + ////////////////// + interval(float lower=-LARGE, float upper=+LARGE); + interval(const interval& i); + + /////////////// + // Operators // + /////////////// + interval& operator=(const interval& i); + + interval operator+(float v) const; + interval operator-(float v) const; + interval operator*(float v) const; + interval operator/(float v) const; + + interval& operator+=(float v); + interval& operator-=(float v); + interval& operator*=(float v); + interval& operator/=(float v); + + //////////////// + // Inspectors // + //////////////// + float lower(void) const; + float upper(void) const; + + bool empty(void) const; + + ////////////// + // Mutators // + ////////////// + void intersect(const interval& i); + + ///////////// + // Friends // + ///////////// + friend void swap(interval& a, interval& b) { a._swap(b); } + + friend std::ostream& operator<<(std::ostream& s, const interval& i) + { + s << "[" << i.lower() << ", " << i.upper() << "]"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const interval& i); + void _swap(interval& i); + + ////////////////////////// + // Private Data Members // + ////////////////////////// + float _lower, _upper; +}; + +#endif /* _INTERVAL_H_ */ diff --git a/hw3/include/lightSample.h b/hw3/include/lightSample.h new file mode 100644 index 0000000..3dd76b5 --- /dev/null +++ b/hw3/include/lightSample.h @@ -0,0 +1,75 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _LIGHTSAMPLE_H_ +#define _LIGHTSAMPLE_H_ + +#include "vec3d.h" +#include "color.h" +#include "constants.h" + +class lightSample { + public: + ////////////////// + // Constructors // + ////////////////// + lightSample(const vec3d& direction=vec3d(0.0f, 0.0f, 0.0f), + const color& emittance=color(0.0f, 0.0f, 0.0f), + float distance=+LARGE, + float pdf=1.0f, + float foreshortening=1.0f); + + lightSample(const lightSample& ls); + + /////////////// + // Operators // + /////////////// + lightSample& operator=(const lightSample& ls); + + const color& operator()(void) const; + + //////////////// + // Inspectors // + //////////////// + const vec3d& directionToPoint(void) const; + vec3d directionToLight(void) const; + + const color& emittance(void) const; + float distance(void) const; + + float pdf(void) const; + float foreshortening(void) const; + + ///////////// + // Friends // + ///////////// + friend void swap(lightSample& a, lightSample& b) { a._swap(b); } + friend std::ostream& operator<<(std::ostream& s, const lightSample& ls) + { + s << "LightSample: direction=" << ls.directionToPoint() << ", emittance=" << ls() << ", distance=" << ls.distance() << ", pdf=" << ls.pdf() << ", foreshortening=" << ls.foreshortening(); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const lightSample& ls); + void _swap(lightSample& ls); + + ////////////////// + // Data Members // + ////////////////// + vec3d _direction; + color _emittance; + float _distance; + float _pdf; + float _foreshortening; +}; + +#endif /* _LIGHTSAMPLE_H_ */ diff --git a/hw3/include/lightsource_base.h b/hw3/include/lightsource_base.h new file mode 100644 index 0000000..0a2f0df --- /dev/null +++ b/hw3/include/lightsource_base.h @@ -0,0 +1,51 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _LIGHTSOURCE_BASE_H_ +#define _LIGHTSOURCE_BASE_H_ + +#include + +#include "vec3d.h" +#include "lightSample.h" + +class lightsource_base { + public: + ////////////////// + // Constructors // + ////////////////// + lightsource_base(void) {} + lightsource_base(const lightsource_base&) = delete; + + /////////////// + // Operators // + /////////////// + lightsource_base& operator=(const lightsource_base&) = delete; + + ///////////// + // Methods // + ///////////// + virtual lightSample intensityAt(const vec3d& point) const = 0; + + ///////////// + // Friends // + ///////////// + friend std::ostream& operator<<(std::ostream& s, const lightsource_base& lsb) + { + lsb._print(s); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + virtual void _print(std::ostream& s) const = 0; +}; + +#endif /* _LIGHTSOURCE_BASE_H_ */ diff --git a/hw3/include/linear_intersector.h b/hw3/include/linear_intersector.h new file mode 100644 index 0000000..221e5fe --- /dev/null +++ b/hw3/include/linear_intersector.h @@ -0,0 +1,62 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _LINEAR_INTERSECTOR_H_ +#define _LINEAR_INTERSECTOR_H_ + +#include + +#include "boundedPrimitive.h" +#include "intersector_base.h" +#include "intersector_factory_base.h" + +class linear_intersector : public intersector_base { + public: + ////////////////// + // Constructors // + ////////////////// + linear_intersector(void); + linear_intersector(const std::vector>& compounds); + linear_intersector(const linear_intersector&) = delete; + + /////////////// + // Operators // + /////////////// + linear_intersector& operator=(const linear_intersector&) = delete; + + ///////////// + // Methods // + ///////////// + virtual intersectionPoint intersect(const ray& r) const final override; + + private: + ////////////////// + // Data Members // + ////////////////// + std::vector> _compounds; +}; + + +class linear_intersector_factory : public intersector_factory_base { + public: + ///////////////// + // Constructor // + ///////////////// + linear_intersector_factory(void) {} + + /////////////// + // Operators // + /////////////// + std::unique_ptr operator()(const boundedCompound& boundedCompound) const final override + { + return std::unique_ptr(new linear_intersector(boundedCompound.compounds())); + } +}; + +#endif /* _LINEAR_INTERSECTOR_H_ */ + diff --git a/hw3/include/mat3d.h b/hw3/include/mat3d.h new file mode 100644 index 0000000..e70ece4 --- /dev/null +++ b/hw3/include/mat3d.h @@ -0,0 +1,112 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _MAT3D_H_ +#define _MAT3D_H_ + +#include +#include + +#include "vec3d.h" + +class mat3d { + public: + ///////////// + // Typedef // + ///////////// + typedef float value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::array::iterator iterator; + typedef std::array::const_iterator const_iterator; + typedef std::size_t difference; + typedef std::size_t size_type; + + ///////////////// + // Constructor // + ///////////////// + mat3d(void); // all elements are set to 0 + explicit mat3d(value_type diag); // all elements are set to 0, the diagonal elements are set to 'diag' + mat3d(const vec3d& X, const vec3d& Y, const vec3d& Z); // set columns to X, Y, and Z + mat3d(const mat3d& m); // copy constructor + + //////////////// + // Inspectors // + //////////////// + static size_type width(void) { return 3; } + static size_type height(void) { return 3; } + static size_type size(void) { return 9; } + + iterator begin(void); + const_iterator begin(void) const; + iterator end(void); + const_iterator end(void) const; + + ////////////// + // Mutators // + ////////////// + void clear(value_type value=0.0f); + void setDiagonal(value_type value=1.0f); + + mat3d& transpose(void); + + /////////////// + // Operators // + /////////////// + mat3d& operator=(const mat3d& m); + + reference operator()(size_type row, size_type col); + const_reference operator()(size_type row, size_type col) const; + + mat3d operator+(const mat3d& m) const; + mat3d operator-(const mat3d& m) const; + mat3d operator*(const mat3d& m) const; + vec3d operator*(const vec3d& v) const; + mat3d operator*(value_type scale) const; + mat3d operator/(value_type scale) const; + + mat3d& operator+=(const mat3d& m); + mat3d& operator-=(const mat3d& m); + mat3d& operator*=(const mat3d& m); + mat3d& operator*=(value_type scale); + mat3d& operator/=(value_type scale); + + ///////////// + // Friends // + ///////////// + friend void swap(mat3d& a, mat3d& b) { a._swap(b); } + + friend vec3d operator*(const vec3d& v, const mat3d& m) { return m._premultiply(v); } + friend mat3d operator*(value_type scale, const mat3d& m) { return (m * scale); } + + friend mat3d transpose(mat3d& m) { mat3d n(m); return n.transpose(); } + + friend std::ostream& operator<<(std::ostream& s, const mat3d& m) + { + s << "[[" << m(0,0) << ", " << m(0,1) << ", " << m(0,2) << "],["; + s << m(1,0) << ", " << m(1,1) << ", " << m(1,2) << "],["; + s << m(2,0) << ", " << m(2,1) << ", " << m(2,2) << "]]"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _swap(mat3d& m); + void _assign(const mat3d& m); + + vec3d _premultiply(const vec3d& v) const; + + ////////////////////////// + // Private Data Members // + ////////////////////////// + std::array _data; +}; + +#endif /* _MAT3D_H_ */ diff --git a/hw3/include/phongBrdf.h b/hw3/include/phongBrdf.h new file mode 100644 index 0000000..588efa2 --- /dev/null +++ b/hw3/include/phongBrdf.h @@ -0,0 +1,60 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _PHONGBRDF_H_ +#define _PHONGBRDF_H_ + +#include "brdf_base.h" + +class phongBrdf : public brdf_base { + public: + ////////////////// + // Constructors // + ////////////////// + phongBrdf(const color& albedo, float sharpness); + phongBrdf(const phongBrdf& src); + + /////////////// + // Operators // + /////////////// + phongBrdf& operator=(const phongBrdf& src); + + ///////////// + // Methods // + ///////////// + virtual color shade(const vec3d& in, const vec3d& out) const override; + + virtual bool isSpecular(void) const final override; + virtual bool isDiffuse(void) const final override; + + ///////////// + // Friends // + ///////////// + friend void swap(phongBrdf& a, phongBrdf& b) { a._swap(b); } + friend std::ostream& operator<<(std::ostream& s, const phongBrdf& b) + { + b._print(s); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const phongBrdf& src); + void _swap(phongBrdf& src); + virtual void _print(std::ostream& s) const override; + + ////////////////// + // Data Members // + ////////////////// + color _albedo; + float _sharpness; +}; + +#endif /* _PHONGBRDF_H_ */ diff --git a/hw3/include/phongReflectanceShader.h b/hw3/include/phongReflectanceShader.h new file mode 100644 index 0000000..13291f2 --- /dev/null +++ b/hw3/include/phongReflectanceShader.h @@ -0,0 +1,46 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _PHONGREFLECTANCESHADER_H_ +#define _PHONGREFLECTANCESHADER_H_ + +#include "phongBrdf.h" +#include "reflectanceParameter.h" +#include "reflectanceShader_base.h" + +class phongReflectanceShader : public reflectanceShader_base { + public: + ///////////////// + // Constructor // + ///////////////// + phongReflectanceShader(const colorReflectanceParameter& albedo=colorReflectanceParameter(color(1.0f, 1.0f, 1.0f)), const scalarReflectanceParameter& sharpness=20.0f); + phongReflectanceShader(const phongReflectanceShader& ) = delete; + + /////////////// + // Operators // + /////////////// + phongReflectanceShader& operator=(const phongReflectanceShader&) = delete; + +protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const override; + + virtual std::unique_ptr make_brdf(const vec2d& textureCoord) const override; + +private: + ////////////////// + // Data Members // + ////////////////// + colorReflectanceParameter _albedo; + scalarReflectanceParameter _sharpness; +}; + +#endif /* _PHONGREFLECTANCESHADER_H_ */ + diff --git a/hw3/include/random_number.h b/hw3/include/random_number.h new file mode 100644 index 0000000..328de25 --- /dev/null +++ b/hw3/include/random_number.h @@ -0,0 +1,50 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _RANDOM_NUMBER_H_ +#define _RANDOM_NUMBER_H_ + +#include +#include "vec3d.h" +#include "constants.h" +#include "coordinateTransform.h" + +static std::random_device rd; +static std::mt19937 rnd; + +static unsigned int random_int(unsigned int up=std::numeric_limits::max()) +{ + std::uniform_int_distribution dist(0, up); + return dist(rnd); +} + + +static float random_float(float up=1.0f) +{ + std::uniform_real_distribution dist(0, up); + return dist(rnd); +} + + +static vec3d random_direction(const vec3d& normal, float r1=random_float(), float r2=random_float()) +{ + // generate in standard coordinate system (i.e., Z=(0,0,1)) + vec3d out(cos(2.0f*PI*r1) * sqrt(std::max(1.0f-r2*r2, 0.0f)), + sin(2.0f*PI*r1) * sqrt(std::max(1.0f-r2*r2, 0.0f)), + r2); + + // transform to global coordinates + coordinateTransformation trans(normal); + out = trans.transformDirection(out); + + // Done (PDF = 1/(2.0f*PI)) + return out; +} + + +#endif /* _RANDOM_NUMBER_H_ */ diff --git a/hw3/include/ray.h b/hw3/include/ray.h new file mode 100644 index 0000000..743375f --- /dev/null +++ b/hw3/include/ray.h @@ -0,0 +1,69 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _RAY_H_ +#define _RAY_H_ + +#include +#include "vec3d.h" +#include "transformation3d.h" + +class ray { + public: + ////////////////// + // Constructors // + ////////////////// + ray(const vec3d& origin = vec3d(), const vec3d& direction = vec3d()); + ray(const ray& src); + + //////////////// + // Inspectors // + //////////////// + const vec3d& origin(void) const { return _origin; } + const vec3d& direction(void) const { return _direction; } + + /////////////// + // Operators // + /////////////// + ray& operator=(const ray& r); + vec3d operator()(float t) const; + float operator()(const vec3d& point) const; + + ////////////// + // Mutators // + ////////////// + ray& transform(const transformation3d& t); + ray& inverseTransform(const transformation3d& t); + + ///////////// + // Friends // + ///////////// + friend void swap(ray& a, ray& b) { a._swap(b); } + friend ray transform(const ray& r, const transformation3d& t) { return ray(r).transform(t); } + friend ray inverseTransform(const ray& r, const transformation3d& t) { return ray(r).inverseTransform(t); } + friend std::ostream& operator<<(std::ostream& s, const ray& r) + { + s << r.origin() << "->" << r.direction(); + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _swap(ray& r); + void _assign(const ray& r); + + ////////////////// + // Data Members // + ////////////////// + vec3d _origin; + vec3d _direction; +}; + +#endif /* _RAY_H_ */ diff --git a/hw3/include/reflectanceParameter.h b/hw3/include/reflectanceParameter.h new file mode 100644 index 0000000..c924653 --- /dev/null +++ b/hw3/include/reflectanceParameter.h @@ -0,0 +1,106 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _REFLECTANCEPARAMETER_H_ +#define _REFLECTANCEPARAMETER_H_ + +#include +#include + +#include "vec2d.h" +#include "vec3d.h" +#include "color.h" +#include "texture_base.h" + +class scalarReflectanceParameter { + public: + ///////////////// + // Constructor // + ///////////////// + scalarReflectanceParameter(float value=0.0f); + scalarReflectanceParameter(const std::shared_ptr& texture, unsigned int channel=0); + scalarReflectanceParameter(const scalarReflectanceParameter& src); + + ////////////// + // Operator // + ////////////// + scalarReflectanceParameter& operator=(const scalarReflectanceParameter& src); + + float operator()(const vec2d& textureCoord) const; + + ///////////// + // Friends // + ///////////// + friend void swap(scalarReflectanceParameter& a, scalarReflectanceParameter& b) { a._swap(b); } + + friend std::ostream& operator<<(std::ostream& s, const scalarReflectanceParameter& param) + { + if(param._texture) s << param._texture << "(channel=" << param._channel << ")"; + else s << param._value; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const scalarReflectanceParameter& src); + void _swap(scalarReflectanceParameter& swp); + + ////////////////// + // Data Members // + ////////////////// + float _value; + unsigned int _channel; + std::shared_ptr _texture; +}; + + +class colorReflectanceParameter { + public: + ///////////////// + // Constructor // + ///////////////// + colorReflectanceParameter(color value=color(0.0f)); + colorReflectanceParameter(const std::shared_ptr& texture); + colorReflectanceParameter(const colorReflectanceParameter& src); + + ////////////// + // Operator // + ////////////// + colorReflectanceParameter& operator=(const colorReflectanceParameter& src); + + color operator()(const vec2d& textureCoord) const; + + ///////////// + // Friends // + ///////////// + friend void swap(colorReflectanceParameter& a, colorReflectanceParameter& b) { a._swap(b); } + + friend std::ostream& operator<<(std::ostream& s, const colorReflectanceParameter& param) + { + if(param._texture) s << param._texture; + else s << param._value; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const colorReflectanceParameter& src); + void _swap(colorReflectanceParameter& swp); + + ////////////////// + // Data Members // + ////////////////// + color _value; + std::shared_ptr _texture; +}; + +#endif /* _REFLECTANCEPARAMETER_BASE_H_ */ diff --git a/hw3/include/reflectanceShader_base.h b/hw3/include/reflectanceShader_base.h new file mode 100644 index 0000000..ad91137 --- /dev/null +++ b/hw3/include/reflectanceShader_base.h @@ -0,0 +1,45 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _REFLECTANCESHADER_BASE_H_ +#define _REFLECTANCESHADER_BASE_H_ + +#include +#include "brdf_base.h" +#include "shader_base.h" + +class reflectanceShader_base : public shader_base { + public: + ////////////////// + // Constructors // + ////////////////// + reflectanceShader_base(void) {} + reflectanceShader_base(const reflectanceShader_base&) = delete; + + /////////////// + // Operators // + /////////////// + reflectanceShader_base& operator=(const reflectanceShader_base&) = delete; + + ///////////// + // Methods // + ///////////// + virtual color shade(const intersectionPoint& ip, const vec3d& light_dir) const final override; + + virtual shaderProperties properties(const intersectionPoint& ip) const final override; + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const = 0; + + virtual std::unique_ptr make_brdf(const vec2d& textureCoord) const = 0; +}; + +#endif /* _REFLECTANCE_SHADER_BASE_H_ */ diff --git a/hw3/include/scene.h b/hw3/include/scene.h new file mode 100644 index 0000000..ee3e416 --- /dev/null +++ b/hw3/include/scene.h @@ -0,0 +1,59 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENE_H_ +#define _SCENE_H_ + +#include +#include +#include + +#include "ray.h" +#include "image.h" +#include "camera.h" +#include "boundedCompound.h" +#include "lightsource_base.h" +#include "intersectionPoint.h" + +class scene { + friend void importScene(const std::string&, scene&); + public: + ////////////////// + // Constructors // + ////////////////// + scene(void) {} + scene(const scene&) = delete; + + /////////////// + // Operators // + /////////////// + camera& operator=(const camera&) = delete; + + //////////////// + // Inspectors // + //////////////// + const camera& getCamera(void) const; + + const lightsource_base& getLightsource(size_t idx) const; + size_t numberOfLightsources(void) const; + + ///////////// + // Methods // + ///////////// + intersectionPoint intersect(const ray& r) const; + + private: + ////////////////// + // Data Members // + ////////////////// + camera _camera; + std::unique_ptr _sceneGraphRoot; + std::vector> _lightsources; +}; + +#endif /* _SCENE_H_ */ diff --git a/hw3/include/sceneGraphNode.h b/hw3/include/sceneGraphNode.h new file mode 100644 index 0000000..38e7de1 --- /dev/null +++ b/hw3/include/sceneGraphNode.h @@ -0,0 +1,45 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEGRAPHNODE_H_ +#define _SCENEGRAPHNODE_H_ + +#include +#include + +#include "shader_base.h" +#include "boundedCompound.h" +#include "transformation3d.h" + +class sceneGraphNode : public boundedCompound { + public: + ////////////////// + // Constructors // + ////////////////// + sceneGraphNode(void); + sceneGraphNode(const std::vector>& nodes, const transformation3d& transform=transformation3d(), const std::shared_ptr& shader=nullptr); + sceneGraphNode(const sceneGraphNode&) = delete; + + /////////////// + // Operators // + /////////////// + sceneGraphNode& operator=(sceneGraphNode&) = delete; + + ///////////// + // Methods // + ///////////// + virtual const std::vector>& compounds(void) const final override; + + private: + ////////////////// + // Data Members // + ////////////////// + std::vector> _nodes; +}; + +#endif /* _SCENEGRAPHNODE_H_ */ diff --git a/hw3/include/sceneIO.h b/hw3/include/sceneIO.h new file mode 100644 index 0000000..59fc6cd --- /dev/null +++ b/hw3/include/sceneIO.h @@ -0,0 +1,17 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENE_IO_H_ +#define _SCENE_IO_H_ + +#include +#include "scene.h" + +void importScene(const std::string& filename, scene& s); + +#endif /* _SCENE_IO_H_ */ diff --git a/hw3/include/sceneIO_basis.h b/hw3/include/sceneIO_basis.h new file mode 100644 index 0000000..5f67172 --- /dev/null +++ b/hw3/include/sceneIO_basis.h @@ -0,0 +1,22 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_BASIS_H_ +#define _SCENEIO_BASIS_H_ + +#include +#include +#include + +#include "camera.h" +#include "intersector_factory_base.h" + +bool importCamera(const XMLNode& node, camera& cam); +void importIntersector(const XMLNode& node, std::unique_ptr& intersector); + +#endif /* _SCENEIO_BASIS_H_ */ diff --git a/hw3/include/sceneIO_cache.h b/hw3/include/sceneIO_cache.h new file mode 100644 index 0000000..3807c86 --- /dev/null +++ b/hw3/include/sceneIO_cache.h @@ -0,0 +1,52 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_CACHE_H_ +#define _SCENEIO_CACHE_H_ + +#include +#include +#include +#include + +template +class nodeCache { + public: + ////////////////// + // Constructors // + ////////////////// + nodeCache(void) {} + nodeCache(const nodeCache&) = delete; + + /////////////// + // Operators // + /////////////// + nodeCache& operator=(const nodeCache& ) = delete; + + ///////////// + // Methods // + ///////////// + std::shared_ptr get(const std::string& name) const; + bool add(const std::string& name, const std::shared_ptr& node); + + std::vector> unusedNodes(unsigned int maxCount=1) const; + std::vector> allNodes(void) const; + + private: + ////////////////////////// + // Private Data Members // + ////////////////////////// + std::map> _cache; +}; + +//////////////////// +// Inline Methods // +//////////////////// +#include "sceneIO_cache.inline.h" + +#endif /* _SCENEIO_CACHE_H_ */ diff --git a/hw3/include/sceneIO_cache.inline.h b/hw3/include/sceneIO_cache.inline.h new file mode 100644 index 0000000..27d9cf0 --- /dev/null +++ b/hw3/include/sceneIO_cache.inline.h @@ -0,0 +1,66 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#if defined(_SCENEIO_CACHE_H_) && !defined(_SCENEIO_CACHE_INLINE_H_) +#define _SCENEIO_CACHE_INLINE_H_ + +#include +#include +#include + +#include "errorMessage.h" + +template +std::shared_ptr nodeCache::get(const std::string& name) const +{ + // see if node exists + auto ref_node = _cache.find(name); + + // return nullptr if not. + if(ref_node == _cache.end()) return nullptr; + + // return node. + else return ref_node->second; +} + + +template +bool nodeCache::add(const std::string& name, const std::shared_ptr& node) +{ + _cache[name] = node; +} + +template +std::vector> nodeCache::unusedNodes(unsigned int maxCount) const +{ + std::vector> result; + + // check each node if unique + for(auto itr=_cache.begin(); itr != _cache.end(); itr++) + if(itr->second.use_count() <= maxCount) + result.push_back(itr->second); + + // done. + return result; +} + + +template +std::vector> nodeCache::allNodes(void) const +{ + std::vector> result; + + // check each node if unique + for(auto itr=_cache.begin(); itr != _cache.end(); itr++) + result.push_back(itr->second); + + // done. + return result; +} + +#endif /* _SCENEIO_CACHE_INLINE_H_ */ diff --git a/hw3/include/sceneIO_core.h b/hw3/include/sceneIO_core.h new file mode 100644 index 0000000..8aa726a --- /dev/null +++ b/hw3/include/sceneIO_core.h @@ -0,0 +1,24 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_CORE_H_ +#define _SCENEIO_CORE_H_ + +#include "sceneIO_xml.h" +#include "color.h" +#include "vec2d.h" +#include "vec3d.h" + +color getColor(const XMLNode& node, const std::string& name, const color& default_value=color()); +vec3d getVec3d(const XMLNode& node, const std::string& name, const vec3d& default_value=vec3d()); +vec2d getVec2d(const XMLNode& node, const std::string& name, const vec2d& default_value=vec2d()); +std::string getString(const XMLNode& node, const std::string& name, const std::string& default_value=std::string("")); +float getFloat(const XMLNode& node, const std::string& name, float default_value=0.0f); +unsigned int getInteger(const XMLNode& node, const std::string& name, unsigned int default_value=0); + +#endif /* _SCENEIO_CORE_H_ */ diff --git a/hw3/include/sceneIO_geometry.h b/hw3/include/sceneIO_geometry.h new file mode 100644 index 0000000..fc4d80b --- /dev/null +++ b/hw3/include/sceneIO_geometry.h @@ -0,0 +1,23 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_GEOMETRY_H_ +#define _SCENEIO_GEOMETRY_H_ + +#include + +#include "sceneIO_xml.h" +#include "sceneIO_cache.h" + +#include "shader_base.h" +#include "texture_base.h" +#include "boundedPrimitive.h" + +std::shared_ptr importGeometry(const XMLNode& node, nodeCache& shape_cache, nodeCache& shader_cache, nodeCache& texture_cache, const std::string& rootDir); + +#endif /* _SCENEIO_GEOMETRY_H_ */ diff --git a/hw3/include/sceneIO_light.h b/hw3/include/sceneIO_light.h new file mode 100644 index 0000000..e2745a2 --- /dev/null +++ b/hw3/include/sceneIO_light.h @@ -0,0 +1,25 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_LIGHT_H_ +#define _SCENEIO_LIGHT_H_ + +#include + +#include "sceneIO_xml.h" +#include "sceneIO_cache.h" + +#include "shader_base.h" +#include "texture_base.h" +#include "boundedPrimitive.h" + +#include "lightsource_base.h" + +std::shared_ptr importLight(const XMLNode& node, nodeCache& shape_cache, nodeCache& shader_cache, nodeCache& texture_cache, const std::string& rootDir); + +#endif /* _SCENEIO_LIGHT_H_ */ diff --git a/hw3/include/sceneIO_material.h b/hw3/include/sceneIO_material.h new file mode 100644 index 0000000..9c0852b --- /dev/null +++ b/hw3/include/sceneIO_material.h @@ -0,0 +1,22 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_MATERIAL_H_ +#define _SCENEIO_MATERIAL_H_ + +#include + +#include "sceneIO_xml.h" +#include "sceneIO_cache.h" + +#include "shader_base.h" +#include "texture_base.h" + +std::shared_ptr importMaterial(const XMLNode& node, nodeCache& shader_cache, nodeCache& texture_cache, const std::string& rootDir); + +#endif /* _SCENEIO_MATERIAL_H_ */ diff --git a/hw3/include/sceneIO_xml.h b/hw3/include/sceneIO_xml.h new file mode 100644 index 0000000..5df35a2 --- /dev/null +++ b/hw3/include/sceneIO_xml.h @@ -0,0 +1,51 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SCENEIO_XML_H_ +#define _SCENEIO_XML_H_ + +#include +#include +#include "tinyxml2.h" + +class XMLNode { + public: + ///////////////// + // Constructor // + ///////////////// + XMLNode(const std::string& filename); + XMLNode(const tinyxml2::XMLElement* element, const std::shared_ptr& xml); + XMLNode(const XMLNode& node); + + ///////////// + // Methods // + ///////////// + XMLNode firstChild(void) const; + XMLNode findChild(const std::string& name) const; + + bool isValid(void) const; + std::string name(void) const; + std::string attribute(const std::string& attribute) const; + + /////////////// + // Operators // + /////////////// + XMLNode& operator++(void); + XMLNode& operator++(int); + XMLNode& operator=(const XMLNode& src); + + protected: + ////////////////// + // Data Members // + ////////////////// + const tinyxml2::XMLElement* _element; + std::shared_ptr _xml; +}; + + +#endif /* _SCENEIO_XML_H_ */ diff --git a/hw3/include/shaderProperties.h b/hw3/include/shaderProperties.h new file mode 100644 index 0000000..859aaac --- /dev/null +++ b/hw3/include/shaderProperties.h @@ -0,0 +1,38 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SHADERPROPERTIES_H_ +#define _SHADERPROPERTIES_H_ + +class shaderProperties { + public: + ///////////////// + // Constructor // + ///////////////// + shaderProperties(bool diff=true, bool spec=true) : diffuse(diff), specular(spec) {} + + ////////////// + // Operator // + ////////////// + bool operator==(const shaderProperties& sp) const; + bool operator!=(const shaderProperties& sp) const; + + shaderProperties& operator&=(const shaderProperties& sp); + shaderProperties& operator|=(const shaderProperties& sp); + shaderProperties& operator~(void); + + shaderProperties operator&(const shaderProperties& sp) const; + shaderProperties operator|(const shaderProperties& sp) const; + + ///////////////////////// + // Public data members // + ///////////////////////// + bool diffuse, specular; +}; + +#endif /* _SHADERPROPERTIES_H_ */ diff --git a/hw3/include/shader_base.h b/hw3/include/shader_base.h new file mode 100644 index 0000000..b96cc33 --- /dev/null +++ b/hw3/include/shader_base.h @@ -0,0 +1,59 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SHADER_BASE_H_ +#define _SHADER_BASE_H_ + +#include +#include + +#include "vec2d.h" +#include "vec3d.h" +#include "color.h" +#include "shaderProperties.h" +#include "intersectionPoint.h" + + +class shader_base +{ + public: + ////////////////// + // Constructors // + ////////////////// + shader_base(void) {} + shader_base(const shader_base&) = delete; + + /////////////// + // Operators // + /////////////// + shader_base& operator=(const shader_base&) = delete; + + ///////////// + // Methods // + ///////////// + virtual color shade(const intersectionPoint& ip, const vec3d& light_dir) const = 0; + + virtual shaderProperties properties(const intersectionPoint& ip) const = 0; + + ///////////// + // Friends // + ///////////// + friend std::ostream& operator<<(std::ostream& s, const shader_base& shader) + { + shader._print(s); + return s; + } + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _print(std::ostream& s) const = 0; +}; + +#endif /* _SHADER_BASE_H_ */ diff --git a/hw3/include/shadingFrameTransformation.h b/hw3/include/shadingFrameTransformation.h new file mode 100644 index 0000000..2d8bd34 --- /dev/null +++ b/hw3/include/shadingFrameTransformation.h @@ -0,0 +1,57 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _SHADINGFRAMETRANSFORMATION_H_ +#define _SHADINGFRAMETRANSFORMATION_H_ + +#include + +#include "vec2d.h" +#include "shader_base.h" +#include "transformation3d.h" + +class shadingFrameTransformation : public shader_base { + public: + ////////////////// + // Constructors // + ////////////////// + shadingFrameTransformation(const std::shared_ptr& shader); + shadingFrameTransformation(const shadingFrameTransformation&) = delete; + + /////////////// + // Operators // + /////////////// + shadingFrameTransformation& operator=(const shadingFrameTransformation&) = delete; + + ///////////// + // Methods // + ///////////// + virtual color shade(const intersectionPoint& ip, const vec3d& light_dir) const final override; + + virtual color reflectance(const intersectionPoint& ip, const vec3d& light_dir, const shaderProperties& properties=shaderProperties()) const final override; + virtual brdfSample sample(const intersectionPoint& ip, float r1, float r2, const shaderProperties& properties=shaderProperties()) const final override; + virtual float reflectivity(const intersectionPoint& ip, const shaderProperties& properties=shaderProperties()) const final override; + virtual color emittance(const intersectionPoint& ip) const final override; + + virtual shaderProperties properties(const intersectionPoint& ip) const final override; + + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual transformation3d _transformation(const vec2d& textureCoord) const = 0; + virtual void _print(std::ostream& s) const = 0; + + ////////////////// + // Data Members // + ////////////////// + std::shared_ptr _shader; +}; + +#endif /* _SHADINGFRAMETRANSFORMATION_H_ */ diff --git a/hw3/include/texture_base.h b/hw3/include/texture_base.h new file mode 100644 index 0000000..919ab53 --- /dev/null +++ b/hw3/include/texture_base.h @@ -0,0 +1,67 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _TEXTURE_BASE_H_ +#define _TEXTURE_BASE_H_ + +#include "vec2d.h" +#include "image.h" + +class texture_base : public image { + public: + ////////////////// + // Constructors // + ////////////////// + texture_base(bool repeat=true); + texture_base(const texture_base& src); + + /////////////// + // Operators // + /////////////// + texture_base& operator=(const texture_base& src); + + virtual image::value_type operator()(const vec2d& textureCoord) const = 0; + + //////////////// + // Inspectors // + //////////////// + bool repeatEdge(void) const { return _repeat; } + bool wrapEdge(void) const { return !_repeat; } + + ///////////// + // Friends // + ///////////// + friend void swap(texture_base& a, texture_base& b) { a._swap(b); } + + friend std::ostream& operator<<(std::ostream& s, const texture_base& t) + { + t._print(s); + return s; + } + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + virtual void _assign(const texture_base& src); + color& _at(signed int x, signed int y); + const color& _at(signed int x, signed int y) const; + + private: + ///////////////////// + // Private Methods // + ///////////////////// + virtual void _print(std::ostream& s) const=0; + + ////////////////// + // Data Members // + ////////////////// + bool _repeat; +}; + +#endif /* _TEXTURE_BASE_H_ */ diff --git a/hw3/include/tinyxml2.h b/hw3/include/tinyxml2.h new file mode 100644 index 0000000..fb7464a --- /dev/null +++ b/hw3/include/tinyxml2.h @@ -0,0 +1,2102 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +#endif + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#else +# define TINYXML2_LIB +#endif + + +#if defined(DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } +# else +# include +# define TIXMLASSERT assert +# endif +#else +# define TIXMLASSERT( x ) {} +#endif + + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 3; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] +*/ +class StrPair +{ +public: + enum { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + NEEDS_WHITESPACE_COLLAPSING = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + +private: + void Reset(); + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() { + _mem = _pool; + _allocated = INITIAL_SIZE; + _size = 0; + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size++] = t; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + return _mem[--_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + TIXMLASSERT( _allocated >= INITIAL_SIZE ); + return _allocated; + } + + const T* Mem() const { + TIXMLASSERT( _mem ); + return _mem; + } + + T* Mem() { + TIXMLASSERT( _mem ); + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INITIAL_SIZE]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; + virtual void Clear() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + for( int i=0; ichunk[i].next = &block->chunk[i+1]; + } + block->chunk[COUNT-1].next = 0; + _root = block->chunk; + } + void* result = _root; + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + _nAllocs++; + _nUntracked++; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Chunk* chunk = static_cast( mem ); +#ifdef DEBUG + memset( chunk, 0xfe, sizeof(Chunk) ); +#endif + chunk->next = _root; + _root = chunk; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + _nUntracked--; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Chunk { + Chunk* next; + char mem[SIZE]; + }; + struct Block { + Chunk chunk[COUNT]; + }; + DynArray< Block*, 10 > _blockPtrs; + Chunk* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ERROR = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_ELEMENT_MISMATCH, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_IDENTIFYING_TAG, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p ) { + TIXMLASSERT( p ); + while( IsWhiteSpace(*p) ) { + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* p ) { + return const_cast( SkipWhiteSpace( const_cast(p) ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + return strncmp( p, q, nChar ) == 0; + } + + inline static bool IsUTF8Continuation( char p ) { + return ( p & 0x80 ) != 0; + } + + static const char* ReadBOM( const char* p, bool* hasBOM ); + // p is the starting location, + // the UTF-8 value of the entity will be placed in value, and length filled in. + static const char* GetCharacterRef( const char* p, char* value, int* length ); + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + + // converts primitive types to strings + static void ToStr( int v, char* buffer, int bufferSize ); + static void ToStr( unsigned v, char* buffer, int bufferSize ); + static void ToStr( bool v, char* buffer, int bufferSize ); + static void ToStr( float v, char* buffer, int bufferSize ); + static void ToStr( double v, char* buffer, int bufferSize ); + + // converts strings to primitive types + static bool ToInt( const char* str, int* value ); + static bool ToUnsigned( const char* str, unsigned* value ); + static bool ToBool( const char* str, bool* value ); + static bool ToFloat( const char* str, float* value ); + static bool ToDouble( const char* str, double* value ); +}; + + +/** XMLNode is a base class for every object that is in the + XML Document Object Model (DOM), except XMLAttributes. + Nodes have siblings, a parent, and children which can + be navigated. A node is always in a XMLDocument. + The type of a XMLNode can be queried, and it can + be cast to its more defined type. + + A XMLDocument allocates memory for all its Nodes. + When the XMLDocument gets deleted, all its Nodes + will also be deleted. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + @endverbatim +*/ +class TINYXML2_LIB XMLNode +{ + friend class XMLDocument; + friend class XMLElement; +public: + + /// Get the XMLDocument that owns this XMLNode. + const XMLDocument* GetDocument() const { + TIXMLASSERT( _document ); + return _document; + } + /// Get the XMLDocument that owns this XMLNode. + XMLDocument* GetDocument() { + TIXMLASSERT( _document ); + return _document; + } + + /// Safely cast to an Element, or null. + virtual XMLElement* ToElement() { + return 0; + } + /// Safely cast to Text, or null. + virtual XMLText* ToText() { + return 0; + } + /// Safely cast to a Comment, or null. + virtual XMLComment* ToComment() { + return 0; + } + /// Safely cast to a Document, or null. + virtual XMLDocument* ToDocument() { + return 0; + } + /// Safely cast to a Declaration, or null. + virtual XMLDeclaration* ToDeclaration() { + return 0; + } + /// Safely cast to an Unknown, or null. + virtual XMLUnknown* ToUnknown() { + return 0; + } + + virtual const XMLElement* ToElement() const { + return 0; + } + virtual const XMLText* ToText() const { + return 0; + } + virtual const XMLComment* ToComment() const { + return 0; + } + virtual const XMLDocument* ToDocument() const { + return 0; + } + virtual const XMLDeclaration* ToDeclaration() const { + return 0; + } + virtual const XMLUnknown* ToUnknown() const { + return 0; + } + + /** The meaning of 'value' changes for the specific type. + @verbatim + Document: empty (NULL is returned, not an empty string) + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + const char* Value() const; + + /** Set the Value of an XML node. + @sa Value() + */ + void SetValue( const char* val, bool staticMem=false ); + + /// Get the parent of this node on the DOM. + const XMLNode* Parent() const { + return _parent; + } + + XMLNode* Parent() { + return _parent; + } + + /// Returns true if this node has no children. + bool NoChildren() const { + return !_firstChild; + } + + /// Get the first child node, or null if none exists. + const XMLNode* FirstChild() const { + return _firstChild; + } + + XMLNode* FirstChild() { + return _firstChild; + } + + /** Get the first child element, or optionally the first child + element with the specified name. + */ + const XMLElement* FirstChildElement( const char* name = 0 ) const; + + XMLElement* FirstChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->FirstChildElement( name )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return _lastChild; + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* name = 0 ) const; + + XMLElement* LastChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->LastChildElement(name) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; + + XMLElement* PreviousSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* name = 0 ) const; + + XMLElement* NextSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->NextSiblingElement( name ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + +protected: + XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + virtual char* ParseDeep( char*, StrPair* ); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + + char* ParseDeep( char*, StrPair* endTag ); + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i=0; + QueryIntValue( &i ); + return i; + } + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_NO_ERROR on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities ); + + mutable StrPair _name; + mutable StrPair _value; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. 0 will be + returned if there is an error. For a method with error + checking, see QueryIntAttribute() + */ + int IntAttribute( const char* name ) const { + int i=0; + QueryIntAttribute( name, &i ); + return i; + } + /// See IntAttribute() + unsigned UnsignedAttribute( const char* name ) const { + unsigned i=0; + QueryUnsignedAttribute( name, &i ); + return i; + } + /// See IntAttribute() + bool BoolAttribute( const char* name ) const { + bool b=false; + QueryBoolAttribute( name, &b ); + return b; + } + /// See IntAttribute() + double DoubleAttribute( const char* name ) const { + double d=0; + QueryDoubleAttribute( name, &d ); + return d; + } + /// See IntAttribute() + float FloatAttribute( const char* name ) const { + float f=0; + QueryFloatAttribute( name, &f ); + return f; + } + + /** Given an attribute name, QueryIntAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + + /** Given an attribute name, QueryAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + int QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + int QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + int QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + int QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + int QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + // internal: + enum { + OPEN, // + CLOSED, // + CLOSING // + }; + int ClosingType() const { + return _closingType; + } + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + char* ParseDeep( char* p, StrPair* endTag ); + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } + XMLAttribute* FindOrCreateAttribute( const char* name ); + //void LinkAttribute( XMLAttribute* attrib ); + char* ParseAttributes( char* p ); + static void DeleteAttribute( XMLAttribute* attribute ); + + enum { BUF_SIZE = 200 }; + int _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + TIXMLASSERT( this == _document ); + return this; + } + virtual const XMLDocument* ToDocument() const { + TIXMLASSERT( this == _document ); + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_NO_ERROR (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); + + /** + Load an XML file from disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespace; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + void SetError( XMLError error, const char* str1, const char* str2 ); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_NO_ERROR; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + + /// Return a possibly helpful diagnostic location or string. + const char* GetErrorStr1() const { + return _errorStr1; + } + /// Return a possibly helpful secondary diagnostic location or string. + const char* GetErrorStr2() const { + return _errorStr2; + } + /// If there is an error, print it to stdout. + void PrintError() const; + + /// Clear the document, resetting it to the initial state. + void Clear(); + + // internal + char* Identify( char* p, XMLNode** node ); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespace; + const char* _errorStr1; + const char* _errorStr2; + char* _charBuffer; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); +}; + + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* node ) { + _node = node; + } + /// Create a handle from a node. + XMLHandle( XMLNode& node ) { + _node = &node; + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { + _node = ref._node; + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* node ) { + _node = node; + } + XMLConstHandle( const XMLNode& node ) { + _node = &node; + } + XMLConstHandle( const XMLConstHandle& ref ) { + _node = ref._node; + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + const XMLText* ToText() const { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + const XMLUnknown* ToUnknown() const { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + const XMLDeclaration* ToDeclaration() const { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a XMLDocument + + When loading, an XML parser is very useful. However, sometimes + when saving, it just gets in the way. The code is often set up + for streaming, and constructing the DOM is just overhead. + + The Printer supports the streaming case. The following code + prints out a trivially simple XML file without ever creating + an XML document. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer() { + _buffer.Clear(); + _buffer.Push(0); + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + void Print( const char* format, ... ); + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/hw3/include/transformation3d.h b/hw3/include/transformation3d.h new file mode 100644 index 0000000..7b61ecc --- /dev/null +++ b/hw3/include/transformation3d.h @@ -0,0 +1,77 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _TRANSFORMATION3D_H_ +#define _TRANSFORMATION3D_H_ + +#include "vec3d.h" +#include "mat3d.h" + +class transformation3d { + public: + ////////////////// + // Constructors // + ////////////////// + transformation3d(void); + transformation3d(const vec3d& translation, const mat3d& transformation, const mat3d& inverseTransform); + transformation3d(const transformation3d& t); + + ////////////// + // Operator // + ////////////// + transformation3d& operator=(const transformation3d& t); + + transformation3d operator*(const transformation3d& t) const; + transformation3d& operator*=(const transformation3d& t); + + ////////////// + // Mutators // + ////////////// + transformation3d& invert(void); + + ///////////// + // Methods // + ///////////// + vec3d transformPoint(const vec3d& p) const; + vec3d transformDirection(const vec3d& d) const; + vec3d transformNormal(const vec3d& n) const; + + vec3d inverseTransformPoint(const vec3d& p) const; + vec3d inverseTransformDirection(const vec3d& d) const; + vec3d inverseTransformNormal(const vec3d& n) const; + + ///////////// + // Friends // + ///////////// + friend void swap(transformation3d& a, transformation3d& b) { a._swap(b); } + + friend transformation3d inverse(const transformation3d& t) { transformation3d i(t); return i.invert(); } + + friend std::ostream& operator<<(std::ostream& s, const transformation3d& t) + { + t._print(s); + return s; + } + + protected: + /////////////////////// + // Protected Methods // + /////////////////////// + void _swap(transformation3d& t); + void _assign(const transformation3d& t); + virtual void _print(std::ostream& s) const; + + //////////////////////////// + // Protected Data Members // + //////////////////////////// + vec3d _translation; + mat3d _transformation; + mat3d _inverseTransformation; +}; + +#endif /* _TRANSFORMATION3D_H_ */ diff --git a/hw3/include/triangle.h b/hw3/include/triangle.h new file mode 100644 index 0000000..f7d85bf --- /dev/null +++ b/hw3/include/triangle.h @@ -0,0 +1,115 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _TRIANGLE_H_ +#define _TRIANGLE_H_ + +#include +#include +#include +#include + +#include "ray.h" +#include "vec2d.h" +#include "vec3d.h" +#include "boundingBox.h" + +class triangle { + public: + ////////////////// + // Constructors // + ////////////////// + triangle(void); + triangle(const triangle& t); + triangle(triangle&& t); + + triangle(const vec3d& v1, const vec3d& v2, const vec3d& v3); + triangle(size_t v1_idx, size_t v2_idx, size_t v3_idx, const std::shared_ptr>& vertex_list); + + triangle(const vec3d& v1, const vec3d& v2, const vec3d& v3, + const vec3d& n1, const vec3d& n2, const vec3d& n3); + triangle(size_t v1_idx, size_t v2_idx, size_t v3_idx, const std::shared_ptr>& vertex_list, + size_t n1_idx, size_t n2_idx, size_t n3_idx, const std::shared_ptr>& normal_list); + + triangle(const vec3d& v1, const vec3d& v2, const vec3d& v3, + const vec2d& t1, const vec2d& t2, const vec2d& t3); + triangle(size_t v1_idx, size_t v2_idx, size_t v3_idx, const std::shared_ptr>& vertex_list, + size_t t1_idx, size_t t2_idx, size_t t3_idx, const std::shared_ptr>& texcoord_list); + + triangle(const vec3d& v1, const vec3d& v2, const vec3d& v3, + const vec3d& n1, const vec3d& n2, const vec3d& n3, + const vec2d& t1, const vec2d& t2, const vec2d& t3); + triangle(size_t v1_idx, size_t v2_idx, size_t v3_idx, const std::shared_ptr>& vertex_list, + size_t n1_idx, size_t n2_idx, size_t n3_idx, const std::shared_ptr>& normal_list, + size_t t1_idx, size_t t2_idx, size_t t3_idx, const std::shared_ptr>& texcoord_list); + + //////////////// + // Inspectors // + //////////////// + const vec3d& vertex(size_t index) const; + const vec3d& normal(size_t index) const; + const vec2d& textureCoordinate(size_t index) const; + + bool hasPerVertexNormals(void) const; + bool hasPerVertexTextureCoordinates(void) const; + + /////////////// + // Operators // + /////////////// + triangle& operator=(const triangle& t); + triangle& operator=(triangle&& t); + + ///////////// + // Methods // + ///////////// + bool intersect(const ray& r, vec3d& barycentricCoord, float& t) const; + + boundingBox boundingbox(void) const; + vec3d vertex(const vec3d& barycentricCoord) const; + vec3d normal(void) const; + vec3d shadingAxis(void) const; + vec3d normal(const vec3d& barycentricCoord) const; + vec2d textureCoordinate(const vec3d& barycentricCoord) const; + + vec3d sample(float r1, float r2, vec3d& barycentricCoord, float& pdf) const; + float area(void) const; + + ///////////// + // Friends // + ///////////// + friend void swap(triangle& a, triangle& b) { a._swap(b); } + + friend std::ostream& operator<<(std::ostream& s, const triangle& t) + { + s << "Triangle: v=(" << t.vertex(0) << "," << t.vertex(1) << "," << t.vertex(2) << ")"; + if(t._normal_list) + s << ", n=(" << t.normal(0) << "," << t.normal(1) << "," << t.normal(2) << ")"; + if(t._textureCoord_list) + s << ", t=(" << t.textureCoordinate(0) << "," << t.textureCoordinate(1) << "," << t.textureCoordinate(2) << ")"; + return s; + } + +private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const triangle& t); + void _swap(triangle& t); + + ////////////////// + // Data Members // + ////////////////// + std::array _vertex_idx; + std::array _normal_idx; + std::array _textureCoord_idx; + std::shared_ptr> _vertex_list; + std::shared_ptr> _normal_list; + std::shared_ptr> _textureCoord_list; +}; + +#endif /* _TRIANGLE_H_ */ diff --git a/hw3/include/triangleMesh.h b/hw3/include/triangleMesh.h new file mode 100644 index 0000000..9558602 --- /dev/null +++ b/hw3/include/triangleMesh.h @@ -0,0 +1,51 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _TRIANGLEMESH_H_ +#define _TRIANGLEMESH_H_ + +#include "vec2d.h" +#include "vec3d.h" +#include "shader_base.h" +#include "boundedTriangle.h" +#include "boundedCompound.h" + +class triangleMesh : public boundedCompound { + public: + ////////////////// + // Constructors // + ////////////////// + triangleMesh(void); + triangleMesh(const std::vector& triangle_list, const std::shared_ptr& shader, const transformation3d& transform=transformation3d()); + triangleMesh(const triangleMesh&) = delete; + + /////////////// + // Operators // + /////////////// + triangleMesh& operator=(const triangleMesh&) = delete; + + ///////////// + // Methods // + ///////////// + virtual const std::vector>& compounds(void) const final override; + + virtual bool hasShader(void) const override; + + private: + ///////////////////// + // Private Methods // + ///////////////////// + virtual void _print(std::ostream& s) const override; + + ////////////////// + // Data Members // + ////////////////// + std::vector> _triangles; +}; + +#endif /* _TRIANGLEMESH_H_ */ diff --git a/hw3/include/util.h b/hw3/include/util.h new file mode 100644 index 0000000..2146464 --- /dev/null +++ b/hw3/include/util.h @@ -0,0 +1,19 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include + +std::string getFilename(const std::string& path); +std::string getExtension(const std::string& path); +std::string getDirectory(const std::string& path); + +#endif /* _UTIL_H_ */ diff --git a/hw3/include/vec2d.h b/hw3/include/vec2d.h new file mode 100644 index 0000000..36e0e5c --- /dev/null +++ b/hw3/include/vec2d.h @@ -0,0 +1,117 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _VEC2D_H_ +#define _VEC2D_H_ + +#include +#include + +class vec2d { + public: + ///////////// + // Typedef // + ///////////// + typedef float value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + + ////////////////// + // Data Members // + ////////////////// + union { + struct { value_type x, y; }; + struct { value_type u, v; }; + value_type data[2]; + }; + + public: + ///////////////// + // Constructor // + ///////////////// + explicit vec2d(const_reference value=0.0f); + vec2d(const_reference x, const_reference y); + vec2d(const vec2d& v); + + //////////////// + // Inspectors // + //////////////// + static size_t size(void) { return 2; } + + iterator begin(void); + const_iterator begin(void) const; + iterator end(void); + const_iterator end(void) const; + + const_reference operator[](size_t index) const; + reference operator[](size_t index); + + /////////////// + // Operators // + /////////////// + vec2d& operator=(const vec2d& v); + + bool operator==(const vec2d& v) const; + bool operator!=(const vec2d& v) const; + + vec2d operator-(void) const; + + vec2d operator+(const vec2d& v) const; + vec2d operator-(const vec2d& v) const; + vec2d operator*(const vec2d& v) const; + vec2d operator*(const_reference scale) const; + vec2d operator/(const vec2d& v) const; + vec2d operator/(const_reference scale) const; + + vec2d& operator+=(const vec2d& v); + vec2d& operator-=(const vec2d& v); + vec2d& operator*=(const vec2d& v); + vec2d& operator*=(const_reference scale); + vec2d& operator/=(const vec2d& v); + vec2d& operator/=(const_reference scale); + + ///////////// + // Methods // + ///////////// + value_type dot(const vec2d& v) const; + value_type squared_length(void) const; + value_type length(void) const; + value_type squared_distance(const vec2d& v) const; + value_type distance(const vec2d& v) const; + + /////////////// + // Modifiers // + /////////////// + vec2d& abs(void); + vec2d& normalize(void); + + ///////////// + // Friends // + ///////////// + friend void swap(vec2d& a, vec2d& b) { return a._swap(b); } + friend vec2d normalize(const vec2d& v) { return vec2d(v).normalize(); } + friend vec2d abs(const vec2d& v) { return vec2d(v).abs(); } + friend vec2d operator*(const_reference scale, const vec2d& v) { return (v*scale); } + + friend std::ostream& operator<<(std::ostream& s, const vec2d& v) + { + s << "[" << v.x << "," << v.y << "]"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const vec2d& v); + void _swap(vec2d& v); +}; + +#endif /* _VEC2D_H_ */ diff --git a/hw3/include/vec3d.h b/hw3/include/vec3d.h new file mode 100644 index 0000000..50d918f --- /dev/null +++ b/hw3/include/vec3d.h @@ -0,0 +1,120 @@ +/******************************************************************/ +/* 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. */ +/******************************************************************/ +#ifndef _VEC3D_H_ +#define _VEC3D_H_ + +#include +#include + +class vec3d { + public: + ///////////// + // Typedef // + ///////////// + typedef float value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + + ////////////////// + // Data Members // + ////////////////// + union { + struct { value_type x, y, z; }; + value_type data[3]; + }; + + public: + ///////////////// + // Constructor // + ///////////////// + explicit vec3d(const_reference value=0.0f); + vec3d(const_reference x, const_reference y, const_reference z); + vec3d(const vec3d& v); + + //////////////// + // Inspectors // + //////////////// + static size_t size(void) { return 3; } + + iterator begin(void); + const_iterator begin(void) const; + iterator end(void); + const_iterator end(void) const; + + const_reference operator[](size_t index) const; + reference operator[](size_t index); + + /////////////// + // Operators // + /////////////// + vec3d& operator=(const vec3d& v); + + bool operator==(const vec3d& v) const; + bool operator!=(const vec3d& v) const; + + vec3d operator-(void) const; + + vec3d operator+(const vec3d& v) const; + vec3d operator-(const vec3d& v) const; + vec3d operator*(const vec3d& v) const; + vec3d operator*(const_reference scale) const; + vec3d operator/(const vec3d& v) const; + vec3d operator/(const_reference scale) const; + + vec3d& operator+=(const vec3d& v); + vec3d& operator-=(const vec3d& v); + vec3d& operator*=(const vec3d& v); + vec3d& operator*=(const_reference scale); + vec3d& operator/=(const vec3d& v); + vec3d& operator/=(const_reference scale); + + ///////////// + // Methods // + ///////////// + value_type dot(const vec3d& v) const; + value_type squared_length(void) const; + value_type length(void) const; + value_type squared_distance(const vec3d& v) const; + value_type distance(const vec3d& v) const; + + vec3d cross(const vec3d& v) const; + + /////////////// + // Modifiers // + /////////////// + vec3d& abs(void); + vec3d& clamp(value_type lower=0.0f, value_type upper=1.0f); + vec3d& normalize(void); + + ///////////// + // Friends // + ///////////// + friend void swap(vec3d& a, vec3d& b) { return a._swap(b); } + friend vec3d normalize(const vec3d& v) { return vec3d(v).normalize(); } + friend vec3d abs(const vec3d& v) { return vec3d(v).abs(); } + friend vec3d clamp(const vec3d& v, value_type lower=0.0f, value_type upper=1.0f) { return vec3d(v).clamp(lower, upper); } + friend vec3d operator*(const_reference scale, const vec3d& v) { return (v*scale); } + + friend std::ostream& operator<<(std::ostream& s, const vec3d& v) + { + s << "[" << v.x << "," << v.y << "," << v.z << "]"; + return s; + } + + private: + ///////////////////// + // Private Methods // + ///////////////////// + void _assign(const vec3d& v); + void _swap(vec3d& v); +}; + +#endif /* _VEC3D_H_ */ -- cgit v1.2.3