diff options
-rw-r--r-- | libdimension/dimension/object.h | 1 | ||||
-rw-r--r-- | libdimension/object.c | 18 | ||||
-rw-r--r-- | libdimension/objects.c | 20 | ||||
-rw-r--r-- | libdimension/raytrace.c | 3 | ||||
-rw-r--r-- | libdimensionxx/Makefile.am | 6 | ||||
-rw-r--r-- | libdimensionxx/dimensionxx.hpp | 1 | ||||
-rw-r--r-- | libdimensionxx/dimensionxx/object.hpp | 43 | ||||
-rw-r--r-- | libdimensionxx/dimensionxx/texture.hpp | 115 | ||||
-rw-r--r-- | libdimensionxx/object.cpp | 94 | ||||
-rw-r--r-- | libdimensionxx/texture.cpp | 106 |
10 files changed, 374 insertions, 33 deletions
diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index fefb061..c70452d 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -35,6 +35,7 @@ typedef struct { const dmnsn_texture *texture; } dmnsn_intersection; +/* Intersection allocation cannot fail */ dmnsn_intersection *dmnsn_new_intersection(); void dmnsn_delete_intersection(dmnsn_intersection *intersection); diff --git a/libdimension/object.c b/libdimension/object.c index 6b248ff..f10d53d 100644 --- a/libdimension/object.c +++ b/libdimension/object.c @@ -21,6 +21,24 @@ #include "dimension.h" #include <stdlib.h> /* For malloc */ +/* Allocate an intersection - cannot fail */ +dmnsn_intersection * +dmnsn_new_intersection() +{ + dmnsn_intersection *intersection = malloc(sizeof(dmnsn_intersection)); + if (!intersection) { + dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate an intersection object."); + } + return intersection; +} + +/* Free an intersection */ +void +dmnsn_delete_intersection(dmnsn_intersection *intersection) +{ + free(intersection); +} + /* Allocate a dummy object */ dmnsn_object * dmnsn_new_object() diff --git a/libdimension/objects.c b/libdimension/objects.c index 780c06b..3c772d1 100644 --- a/libdimension/objects.c +++ b/libdimension/objects.c @@ -100,7 +100,7 @@ dmnsn_new_cube() dmnsn_object *cube = dmnsn_new_object(); if (cube) { cube->intersection_fn = &dmnsn_cube_intersection_fn; - cube->inside_fn = &dmnsn_cube_inside_fn; + cube->inside_fn = &dmnsn_cube_inside_fn; } return cube; } @@ -126,7 +126,7 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line) /* x = 1.0 */ t_temp = (1.0 - line.x0.x)/line.n.x; - p = dmnsn_line_point(line, t); + p = dmnsn_line_point(line, t_temp); if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { t = t_temp; @@ -136,16 +136,16 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line) if (line.n.y != 0.0) { /* y = -1.0 */ t_temp = (-1.0 - line.x0.y)/line.n.y; - p = dmnsn_line_point(line, t); - if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 + p = dmnsn_line_point(line, t_temp); + if (p.x >= -1.0 && p.x <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { t = t_temp; } /* y = 1.0 */ t_temp = (1.0 - line.x0.y)/line.n.y; - p = dmnsn_line_point(line, t); - if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 + p = dmnsn_line_point(line, t_temp); + if (p.x >= -1.0 && p.x <= 1.0 && p.z >= -1.0 && p.z <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { t = t_temp; } @@ -154,16 +154,16 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line) if (line.n.z != 0.0) { /* z = -1.0 */ t_temp = (-1.0 - line.x0.z)/line.n.z; - p = dmnsn_line_point(line, t); - if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 + p = dmnsn_line_point(line, t_temp); + if (p.x >= -1.0 && p.x <= 1.0 && p.y >= -1.0 && p.y <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { t = t_temp; } /* z = 1.0 */ t_temp = (1.0 - line.x0.z)/line.n.z; - p = dmnsn_line_point(line, t); - if (p.y >= -1.0 && p.y <= 1.0 && p.z >= -1.0 && p.z <= 1.0 + p = dmnsn_line_point(line, t_temp); + if (p.x >= -1.0 && p.x <= 1.0 && p.y >= -1.0 && p.y <= 1.0 && t_temp >= 0.0 && (t < 0.0 || t_temp < t)) { t = t_temp; } diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 75e857c..10f400d 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -248,6 +248,9 @@ dmnsn_raytrace_shoot(dmnsn_scene *scene, dmnsn_color color, if (intersection) { color = dmnsn_color_from_XYZ(dmnsn_whitepoint); } + + /* Delete the intersection */ + dmnsn_delete_intersection(intersection); } return color; diff --git a/libdimensionxx/Makefile.am b/libdimensionxx/Makefile.am index c31a643..0f8d3a4 100644 --- a/libdimensionxx/Makefile.am +++ b/libdimensionxx/Makefile.am @@ -31,7 +31,8 @@ nobase_include_HEADERS = dimensionxx.hpp \ dimensionxx/png.hpp \ dimensionxx/progress.hpp \ dimensionxx/raytrace.hpp \ - dimensionxx/scene.hpp + dimensionxx/scene.hpp \ + dimensionxx/texture.hpp INCLUDES = -I../libdimension @@ -49,7 +50,8 @@ libdimensionxx_la_SOURCES = $(nobase_include_HEADERS) \ png.cpp \ progress.cpp \ raytrace.cpp \ - scene.cpp + scene.cpp \ + texture.cpp if FOPENCOOKIE libdimensionxx_la_SOURCES += cookie-fopencookie.cpp diff --git a/libdimensionxx/dimensionxx.hpp b/libdimensionxx/dimensionxx.hpp index f063760..99b9a97 100644 --- a/libdimensionxx/dimensionxx.hpp +++ b/libdimensionxx/dimensionxx.hpp @@ -33,6 +33,7 @@ #include <dimensionxx/canvas.hpp> #include <dimensionxx/gl.hpp> #include <dimensionxx/png.hpp> +#include <dimensionxx/texture.hpp> #include <dimensionxx/object.hpp> #include <dimensionxx/objects.hpp> #include <dimensionxx/camera.hpp> diff --git a/libdimensionxx/dimensionxx/object.hpp b/libdimensionxx/dimensionxx/object.hpp index c661fa8..4c9dbff 100644 --- a/libdimensionxx/dimensionxx/object.hpp +++ b/libdimensionxx/dimensionxx/object.hpp @@ -25,10 +25,43 @@ namespace Dimension { - // Abstract base object class. Wraps a dmnsn_object*. + // Type to represent a ray-object intersection + class Intersection + { + public: + Intersection(const Line& ray, double t, const Texture& texture); + explicit Intersection(dmnsn_intersection *intersection); + // Intersection(const Intersection& intersection); + ~Intersection(); + + Line& ray() { return m_ray; } + const Line& ray() const { return m_ray; } + + double t() const { return dmnsn()->t; } + void t(double t) { dmnsn()->t = t; } + + const Texture& texture() const { return m_texture; } + + dmnsn_intersection* dmnsn(); + const dmnsn_intersection* dmnsn() const; + + dmnsn_intersection* release(); + + private: + // Copy-assignment prohibited + Intersection& operator=(const Intersection& intersection); + + std::tr1::shared_ptr<dmnsn_intersection*> m_intersection; + Line m_ray; + const Texture m_texture; + }; + + // Base object class. Wraps a dmnsn_object*. class Object { public: + // Wrap an existing object. + explicit Object(dmnsn_object* object); // Delete the object virtual ~Object(); @@ -37,11 +70,11 @@ namespace Dimension void trans(const Matrix& trans); // Object callbacks - virtual Array<double> intersections(const Line& l); + virtual Intersection intersection(const Line& l); virtual bool inside(const Vector& point); // Shallow-copy a derived object - virtual Object* copy() const = 0; + virtual Object* copy() const; // Access the wrapped C object dmnsn_object* dmnsn(); @@ -52,8 +85,6 @@ namespace Dimension Object(); // Shallow copy Object(const Object& object); - // Wrap an existing object. - explicit Object(dmnsn_object* object); // Is m_object unique? bool unique() const; @@ -75,7 +106,7 @@ namespace Dimension Custom_Object(); virtual ~Custom_Object(); - virtual Array<double> intersections(const Line& l) = 0; + virtual Intersection intersection(const Line& l) = 0; virtual bool inside(const Vector& point) = 0; }; diff --git a/libdimensionxx/dimensionxx/texture.hpp b/libdimensionxx/dimensionxx/texture.hpp new file mode 100644 index 0000000..7f42206 --- /dev/null +++ b/libdimensionxx/dimensionxx/texture.hpp @@ -0,0 +1,115 @@ +/************************************************************************* + * Copyright (C) 2009 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +// dmnsn_texture* wrapper. + +#ifndef DIMENSIONXX_TEXTURE_HPP +#define DIMENSIONXX_TEXTURE_HPP + +namespace Dimension +{ + // Pigment base class. Wraps a dmnsn_pigment*. + class Pigment + { + public: + explicit Pigment(dmnsn_pigment* pigment); + ~Pigment(); + + Pigment* copy() const; + + dmnsn_pigment* dmnsn(); + const dmnsn_pigment* dmnsn() const; + + protected: + // No-op + Pigment(); + // Shallow copy + Pigment(const Pigment& pigment); + + // Is m_pigment unique? + bool unique() const; + + private: + // Copy-assignment prohibited + Pigment& operator=(const Pigment&); + + std::tr1::shared_ptr<dmnsn_pigment*> m_pigment; + }; + + // Texture class. Wraps a dmnsn_texture*. + class Texture + { + public: + Texture(const Pigment& pigment); + explicit Texture(dmnsn_texture* texture); + // Texture(const Texture& texture); + ~Texture(); + + dmnsn_texture* dmnsn(); + const dmnsn_texture* dmnsn() const; + + private: + // Copy-assignment prohibited + Texture& operator=(const Texture&); + + std::tr1::shared_ptr<dmnsn_texture*> m_texture; + std::tr1::shared_ptr<Pigment> m_pigment; + }; + + // Array_Element specializations + + template <> + class Array_Element<Pigment> + : public Polymorphic_Array_Element<Pigment, dmnsn_pigment*> + { + public: + typedef dmnsn_pigment* C_Type; + + Array_Element() { } + Array_Element(Pigment& pigment) + : Polymorphic_Array_Element<Pigment, dmnsn_pigment*>(pigment) { } + Array_Element(C_Type c) + : Polymorphic_Array_Element<Pigment, dmnsn_pigment*>(c) { } + // Array_Element(const Array_Element& ae); + // ~Array_Element(); + + // Array_Element& operator=(const Array_Element& ae); + }; + + template <> + class Array_Element<Texture> + : public DMNSN_Array_Element<Texture, dmnsn_texture*> + { + public: + typedef dmnsn_texture* C_Type; + + Array_Element() { } + Array_Element(Texture& texture) + : DMNSN_Array_Element<Texture, dmnsn_texture*>(texture) { } + Array_Element(C_Type c) + : DMNSN_Array_Element<Texture, dmnsn_texture*>(c) { } + // Array_Element(const Array_Element& ae); + // ~Array_Element(); + + // Array_Element& operator=(const Array_Element& ae); + }; +} + +#endif /* DIMENSIONXX_TEXTURE_HPP */ diff --git a/libdimensionxx/object.cpp b/libdimensionxx/object.cpp index 407935a..c36a37f 100644 --- a/libdimensionxx/object.cpp +++ b/libdimensionxx/object.cpp @@ -22,7 +22,69 @@ namespace Dimension { - // Virtual destructor + // Construct an intersection object + Intersection::Intersection(const Line& ray, double t, const Texture& texture) + : m_intersection(new dmnsn_intersection*(dmnsn_new_intersection())), + m_ray(ray), m_texture(texture) + { + dmnsn()->t = t; + } + + // Wrap an existing intersection - don't release() one of these + Intersection::Intersection(dmnsn_intersection *intersection) + : m_intersection(new dmnsn_intersection*(intersection)), + m_ray(intersection->ray), + m_texture(const_cast<dmnsn_texture*>(intersection->texture)) + { } + + // Delete an intersection + Intersection::~Intersection() { + if (m_intersection && m_intersection.unique()) { + dmnsn_delete_intersection(dmnsn()); + } + } + + dmnsn_intersection* + Intersection::dmnsn() + { + if (!m_intersection) { + throw Dimension_Error("Attempt to access released intersection."); + } + return *m_intersection; + } + + const dmnsn_intersection* + Intersection::dmnsn() const + { + if (!m_intersection) { + throw Dimension_Error("Attempt to access released intersection."); + } + return *m_intersection; + } + + dmnsn_intersection* + Intersection::release() + { + if (!m_intersection) { + throw Dimension_Error("Attempt to release previously released" + " intersection."); + } + + if (!m_intersection.unique()) { + throw Dimension_Error("Attempt to release non-unique intersection."); + } + + dmnsn_intersection* intersection = dmnsn(); + m_intersection.reset(); + return intersection; + } + + // Manual constructor + Object::Object(dmnsn_object* object) + : m_object(new dmnsn_object*(object)) + { } + + // Virtual Object destructor Object::~Object() { if (unique()) { @@ -45,10 +107,10 @@ namespace Dimension } // Intersection list for the line l - Array<double> - Object::intersections(const Line& l) + Intersection + Object::intersection(const Line& l) { - return Array<double>((*dmnsn()->intersections_fn)(dmnsn(), l.dmnsn())); + return Intersection((*dmnsn()->intersection_fn)(dmnsn(), l.dmnsn())); } // Whether the point `point' is inside the object @@ -69,6 +131,12 @@ namespace Dimension return *m_object; } + Object* + Object::copy() const + { + return new Object(*this); + } + // Return a const version of the wrapped canvas const dmnsn_object* Object::dmnsn() const @@ -90,11 +158,6 @@ namespace Dimension : m_object(object.m_object) { } - // Protected manual constructor - Object::Object(dmnsn_object* object) - : m_object(new dmnsn_object*(object)) - { } - // Is m_object unique? bool Object::unique() const @@ -110,12 +173,13 @@ namespace Dimension } // Custom object callbacks - namespace { - dmnsn_array * - intersections_fn(const dmnsn_object *object, dmnsn_line line) + namespace + { + dmnsn_intersection * + intersection_fn(const dmnsn_object *object, dmnsn_line line) { Custom_Object* cobject = reinterpret_cast<Custom_Object*>(object->ptr); - return cobject->intersections(Line(line)).release(); + return cobject->intersection(Line(line)).release(); } int @@ -131,8 +195,8 @@ namespace Dimension : Object(dmnsn_new_object()) { dmnsn()->ptr = this; - dmnsn()->intersections_fn = &intersections_fn; - dmnsn()->inside_fn = &inside_fn; + dmnsn()->intersection_fn = &intersection_fn; + dmnsn()->inside_fn = &inside_fn; } // Delete the object diff --git a/libdimensionxx/texture.cpp b/libdimensionxx/texture.cpp new file mode 100644 index 0000000..cd9c2a8 --- /dev/null +++ b/libdimensionxx/texture.cpp @@ -0,0 +1,106 @@ +/************************************************************************* + * Copyright (C) 2009 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +#include "dimensionxx.hpp" + +namespace Dimension +{ + Pigment::Pigment(dmnsn_pigment* pigment) + : m_pigment(new dmnsn_pigment*(pigment)) + { } + + Pigment::~Pigment() + { + if (unique()) { + dmnsn_delete_pigment(dmnsn()); + } + } + + Pigment* + Pigment::copy() const + { + return new Pigment(*this); + } + + dmnsn_pigment* + Pigment::dmnsn() + { + if (!m_pigment) { + throw Dimension_Error("Attempt to access NULL pigment."); + } + return *m_pigment; + } + + const dmnsn_pigment* + Pigment::dmnsn() const + { + if (!m_pigment) { + throw Dimension_Error("Attempt to access NULL pigment."); + } + return *m_pigment; + } + + // Protected no-op constructor + Pigment::Pigment() { } + + // Shallow copy + Pigment::Pigment(const Pigment& pigment) + : m_pigment(pigment.m_pigment) + { + } + + bool + Pigment::unique() const + { + return m_pigment && m_pigment.unique(); + } + + Texture::Texture(const Pigment& pigment) + : m_texture(new dmnsn_texture*(dmnsn_new_texture())), + m_pigment(pigment.copy()) + { + dmnsn()->pigment = m_pigment->dmnsn(); + } + + Texture::Texture(dmnsn_texture* texture) + : m_texture(new dmnsn_texture*(texture)), + m_pigment(new Pigment(texture->pigment)) + { + } + + Texture::~Texture() + { + if (m_texture.unique()) { + dmnsn_delete_texture(dmnsn()); + } + } + + dmnsn_texture* + Texture::dmnsn() + { + return *m_texture; + } + + const dmnsn_texture* + Texture::dmnsn() const + { + return *m_texture; + } +} |