summaryrefslogtreecommitdiffstats
path: root/libdimensionxx
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-07-07 04:23:05 +0000
committerTavian Barnes <tavianator@gmail.com>2009-07-07 04:23:05 +0000
commit81c84a38992ce8e38106d86ce85ac3e88ed91a31 (patch)
tree08fb5913e141b7e208737b799b45921d477d45cc /libdimensionxx
parentd7b7b4b3391cf99ca63d8311eac3957df7a862ed (diff)
downloaddimension-81c84a38992ce8e38106d86ce85ac3e88ed91a31.tar.xz
Add shallow copy semantics to Camera's, Object's, and Scene's.
Diffstat (limited to 'libdimensionxx')
-rw-r--r--libdimensionxx/camera.cpp51
-rw-r--r--libdimensionxx/cameras.cpp20
-rw-r--r--libdimensionxx/dimensionxx/camera.hpp20
-rw-r--r--libdimensionxx/dimensionxx/cameras.hpp9
-rw-r--r--libdimensionxx/dimensionxx/object.hpp20
-rw-r--r--libdimensionxx/dimensionxx/objects.hpp18
-rw-r--r--libdimensionxx/dimensionxx/scene.hpp53
-rw-r--r--libdimensionxx/object.cpp56
-rw-r--r--libdimensionxx/objects.cpp36
-rw-r--r--libdimensionxx/scene.cpp42
10 files changed, 258 insertions, 67 deletions
diff --git a/libdimensionxx/camera.cpp b/libdimensionxx/camera.cpp
index 2897dac..ba2428a 100644
--- a/libdimensionxx/camera.cpp
+++ b/libdimensionxx/camera.cpp
@@ -22,37 +22,66 @@
namespace Dimension
{
- // Pure virtual no-op destructor
+ // Virtual no-op destructor
Camera::~Camera()
{ }
+ // Return the result of the dmnsn_camera*'s ray callback
+ Line
+ Camera::ray(const Canvas& canvas, unsigned int x, unsigned int y)
+ {
+ return Line(dmnsn()->ray_fn(dmnsn(), canvas.dmnsn(), x, y));
+ }
+
// Return the wrapped camera
dmnsn_camera*
Camera::dmnsn()
{
- return m_camera;
+ if (!m_camera) {
+ throw Dimension_Error("Attempt to access NULL camera.");
+ }
+
+ return *m_camera;
}
// Return a const version of the wrapped canvas
const dmnsn_camera*
Camera::dmnsn() const
{
- return m_camera;
+ if (!m_camera) {
+ throw Dimension_Error("Attempt to access NULL camera.");
+ }
+
+ return *m_camera;
}
// Protected default no-op constructor
Camera::Camera()
+ : m_camera()
+ { }
+
+ // Protected copy constructor
+ Camera::Camera(const Camera& camera)
+ : m_camera(camera.m_camera)
{ }
// Protected manual constructor
Camera::Camera(dmnsn_camera *camera)
- : m_camera(camera)
+ : m_camera(new dmnsn_camera*(camera))
{ }
- Line
- Camera::ray(const Canvas& canvas, unsigned int x, unsigned int y)
+ // Is m_camera unique?
+ bool
+ Camera::unique() const
{
- return Line(m_camera->ray_fn(m_camera, canvas.dmnsn(), x, y));
+ return m_camera.unique();
+ }
+
+ // Set the wrapped dmnsn_camera*
+ void
+ Camera::dmnsn(dmnsn_camera* camera)
+ {
+ m_camera.reset(new dmnsn_camera*(camera));
}
// Custom camera callbacks
@@ -75,13 +104,15 @@ namespace Dimension
Custom_Camera::Custom_Camera()
: Camera(dmnsn_new_camera())
{
- m_camera->ptr = this;
- m_camera->ray_fn = &ray_fn;
+ dmnsn()->ptr = this;
+ dmnsn()->ray_fn = &ray_fn;
}
// Delete the camera
Custom_Camera::~Custom_Camera()
{
- dmnsn_delete_camera(m_camera);
+ if (unique()) {
+ dmnsn_delete_camera(dmnsn());
+ }
}
}
diff --git a/libdimensionxx/cameras.cpp b/libdimensionxx/cameras.cpp
index a7a8255..ea0bca9 100644
--- a/libdimensionxx/cameras.cpp
+++ b/libdimensionxx/cameras.cpp
@@ -26,7 +26,7 @@ namespace Dimension
Perspective_Camera::Perspective_Camera(const Matrix& trans)
: Camera(dmnsn_new_perspective_camera(trans.dmnsn()))
{
- if (!m_camera) {
+ if (!dmnsn()) {
throw Dimension_Error("Failed to allocate perspective camera.");
}
}
@@ -34,18 +34,30 @@ namespace Dimension
// Delete a perspective camera
Perspective_Camera::~Perspective_Camera()
{
- dmnsn_delete_perspective_camera(m_camera);
+ if (unique()) {
+ dmnsn_delete_perspective_camera(dmnsn());
+ }
}
Matrix
Perspective_Camera::trans()
{
- return Matrix(dmnsn_get_perspective_camera_trans(m_camera));
+ return Matrix(dmnsn_get_perspective_camera_trans(dmnsn()));
}
void
Perspective_Camera::trans(const Matrix& trans)
{
- dmnsn_set_perspective_camera_trans(m_camera, trans.dmnsn());
+ dmnsn_set_perspective_camera_trans(dmnsn(), trans.dmnsn());
}
+
+ Camera*
+ Perspective_Camera::copy() const
+ {
+ return new Perspective_Camera(*this);
+ }
+
+ Perspective_Camera::Perspective_Camera(const Perspective_Camera& camera)
+ : Camera(camera)
+ { }
}
diff --git a/libdimensionxx/dimensionxx/camera.hpp b/libdimensionxx/dimensionxx/camera.hpp
index 950e16d..a883969 100644
--- a/libdimensionxx/dimensionxx/camera.hpp
+++ b/libdimensionxx/dimensionxx/camera.hpp
@@ -29,12 +29,15 @@ namespace Dimension
class Camera
{
public:
- // No-op, made pure virtual
- virtual ~Camera() = 0;
+ // No-op
+ virtual ~Camera();
// Camera callback
virtual Line ray(const Canvas& canvas, unsigned int x, unsigned int y);
+ // Shallow-copy a derived camera
+ virtual Camera* copy() const = 0;
+
// Access the wrapped C camera.
dmnsn_camera* dmnsn();
const dmnsn_camera* dmnsn() const;
@@ -42,15 +45,22 @@ namespace Dimension
protected:
// No-op
Camera();
+ // Shallow-copy
+ Camera(const Camera& camera);
// Wrap an existing camera
explicit Camera(dmnsn_camera* camera);
- dmnsn_camera* m_camera;
+ // Is m_camera unique?
+ bool unique() const;
+
+ // Set the wrapped C camera
+ void dmnsn(dmnsn_camera* camera);
private:
- // Copying prohibited
- Camera(const Camera&);
+ // Copy-assignment prohibited
Camera& operator=(const Camera&);
+
+ std::tr1::shared_ptr<dmnsn_camera*> m_camera;
};
// A custom camera abstract base class, for creating your own camera types
diff --git a/libdimensionxx/dimensionxx/cameras.hpp b/libdimensionxx/dimensionxx/cameras.hpp
index 4e67d64..cabae97 100644
--- a/libdimensionxx/dimensionxx/cameras.hpp
+++ b/libdimensionxx/dimensionxx/cameras.hpp
@@ -30,10 +30,17 @@ namespace Dimension
{
public:
Perspective_Camera(const Matrix& trans);
- virtual ~Perspective_Camera();
+ ~Perspective_Camera();
Matrix trans();
void trans(const Matrix& trans);
+
+ Camera* copy() const;
+
+ private:
+ // Copying prohibited, but used internally
+ Perspective_Camera(const Perspective_Camera& camera);
+ Perspective_Camera& operator=(const Perspective_Camera&);
};
}
diff --git a/libdimensionxx/dimensionxx/object.hpp b/libdimensionxx/dimensionxx/object.hpp
index 1b9c848..c56d358 100644
--- a/libdimensionxx/dimensionxx/object.hpp
+++ b/libdimensionxx/dimensionxx/object.hpp
@@ -29,8 +29,8 @@ namespace Dimension
class Object
{
public:
- // No-op, made pure virtual
- virtual ~Object() = 0;
+ // No-op
+ virtual ~Object();
// Get/set the transformation matrix
Matrix trans();
@@ -40,6 +40,9 @@ namespace Dimension
virtual Array<double> intersections(const Line& l);
virtual bool inside(const Vector& point);
+ // Shallow-copy a derived
+ virtual Object* copy() const = 0;
+
// Access the wrapped C object.
dmnsn_object* dmnsn();
const dmnsn_object* dmnsn() const;
@@ -47,15 +50,22 @@ namespace Dimension
protected:
// No-op
Object();
+ // Shallow copy
+ Object(const Object& object);
// Wrap an existing object.
explicit Object(dmnsn_object* object);
- dmnsn_object* m_object;
+ // Is m_object unique?
+ bool unique() const;
+
+ // Set the wrapped object
+ void dmnsn(dmnsn_object* object);
private:
- // Copying prohibited
- Object(const Object&);
+ // Copy-assignment prohibited
Object& operator=(const Object&);
+
+ std::tr1::shared_ptr<dmnsn_object*> m_object;
};
// A custom object abstract base class, for creating your own object types
diff --git a/libdimensionxx/dimensionxx/objects.hpp b/libdimensionxx/dimensionxx/objects.hpp
index 89aab14..5b43dc4 100644
--- a/libdimensionxx/dimensionxx/objects.hpp
+++ b/libdimensionxx/dimensionxx/objects.hpp
@@ -30,7 +30,14 @@ namespace Dimension
{
public:
Sphere();
- virtual ~Sphere();
+ ~Sphere();
+
+ Object* copy() const;
+
+ private:
+ // Copying prohibited, but used internally
+ Sphere(const Sphere& sphere);
+ Sphere& operator=(const Sphere&);
};
// A cube
@@ -38,7 +45,14 @@ namespace Dimension
{
public:
Cube();
- virtual ~Cube();
+ ~Cube();
+
+ Object* copy() const;
+
+ private:
+ // Copying prohibited, but used internally
+ Cube(const Cube& cube);
+ Cube& operator=(const Cube&);
};
}
diff --git a/libdimensionxx/dimensionxx/scene.hpp b/libdimensionxx/dimensionxx/scene.hpp
index 256de29..b5adde0 100644
--- a/libdimensionxx/dimensionxx/scene.hpp
+++ b/libdimensionxx/dimensionxx/scene.hpp
@@ -25,14 +25,20 @@
namespace Dimension
{
+ // Iterator class for scene objects
+ class Scene_Iterator;
+
// Base scene class. Wraps a dmnsn_scene*.
class Scene
{
public:
- // Allocate a dmnsn_scene
+ typedef Scene_Iterator Iterator;
+
+ // Allocate a dmnsn_scene*
Scene(const Color& background, Camera& camera, Canvas& canvas);
- // Wrap an existing scene
- explicit Scene(dmnsn_scene* scene);
+
+ // Scene(const Scene& scene);
+
// Delete the scene
~Scene();
@@ -43,7 +49,11 @@ namespace Dimension
Canvas& canvas();
const Canvas& canvas() const;
- // Add objects
+ // Object access
+
+ Iterator begin();
+ Iterator end();
+
void push_object(Object& object);
// Access the wrapped C object.
@@ -51,13 +61,38 @@ namespace Dimension
const dmnsn_scene* dmnsn() const;
private:
- // Copying prohibited
- Scene(const Scene&);
+ // Copy-assignment prohibited
Scene& operator=(const Scene&);
- dmnsn_scene* m_scene;
- Camera* m_camera;
- Canvas* m_canvas;
+ std::tr1::shared_ptr<dmnsn_scene*> m_scene;
+ std::tr1::shared_ptr<Camera> m_camera;
+ std::tr1::shared_ptr<Canvas> m_canvas;
+ std::list<std::tr1::shared_ptr<Object> > m_objects;
+ };
+
+ class Scene_Iterator
+ {
+ public:
+ Scene_Iterator(std::list<std::tr1::shared_ptr<Object> >::iterator i)
+ : m_i(i) { }
+ // Scene_Iterator(const Scene_Iterator& i);
+ // ~Scene_Iterator();
+
+ // Scene_Iterator& operator=(const Scene_Iterator& i);
+
+ Object& operator*() const { return **m_i; }
+ Object* operator->() const { return &**m_i; }
+
+ bool operator==(Scene_Iterator i) const { return m_i == i.m_i; }
+ bool operator!=(Scene_Iterator i) const { return m_i != i.m_i; }
+
+ Scene_Iterator& operator++() { ++m_i; return *this; }
+ Scene_Iterator operator++(int) { return Scene_Iterator(m_i++); }
+ Scene_Iterator& operator--() { --m_i; return *this; }
+ Scene_Iterator operator--(int) { return Scene_Iterator(m_i--); }
+
+ private:
+ std::list<std::tr1::shared_ptr<Object> >::iterator m_i;
};
}
diff --git a/libdimensionxx/object.cpp b/libdimensionxx/object.cpp
index 7d66206..61b8b7d 100644
--- a/libdimensionxx/object.cpp
+++ b/libdimensionxx/object.cpp
@@ -22,59 +22,87 @@
namespace Dimension
{
- // Pure virtual no-op destructor
+ // Virtual no-op destructor
Object::~Object()
{ }
Matrix
Object::trans()
{
- return Matrix(m_object->trans);
+ return Matrix(dmnsn()->trans);
}
void
Object::trans(const Matrix& trans)
{
- m_object->trans = trans.dmnsn();
+ dmnsn()->trans = trans.dmnsn();
}
// Intersection list for the line l
Array<double>
Object::intersections(const Line& l)
{
- return Array<double>(m_object->intersections_fn(m_object, l.dmnsn()));
+ return Array<double>(dmnsn()->intersections_fn(dmnsn(), l.dmnsn()));
}
// Whether the point `point' is inside the object
bool
Object::inside(const Vector& point)
{
- return m_object->inside_fn(m_object, point.dmnsn());
+ return dmnsn()->inside_fn(dmnsn(), point.dmnsn());
}
// Return the wrapped object
dmnsn_object*
Object::dmnsn()
{
- return m_object;
+ if (!m_object) {
+ throw Dimension_Error("Attempt to access NULL object.");
+ }
+
+ return *m_object;
}
// Return a const version of the wrapped canvas
const dmnsn_object*
Object::dmnsn() const
{
- return m_object;
+ if (!m_object) {
+ throw Dimension_Error("Attempt to access NULL object.");
+ }
+
+ return *m_object;
}
// Protected default no-op constructor
Object::Object()
+ : m_object()
+ { }
+
+ // Protected copy constructor
+ Object::Object(const Object& object)
+ : m_object(object.m_object)
{ }
// Protected manual constructor
- Object::Object(dmnsn_object *object)
- : m_object(object)
+ Object::Object(dmnsn_object* object)
+ : m_object(new dmnsn_object*(object))
{ }
+ // Is m_object unique?
+ bool
+ Object::unique() const
+ {
+ return m_object.unique();
+ }
+
+ // Set the wrapped dmnsn_object*
+ void
+ Object::dmnsn(dmnsn_object* object)
+ {
+ m_object.reset(new dmnsn_object*(object));
+ }
+
// Custom object callbacks
namespace {
dmnsn_array *
@@ -96,14 +124,16 @@ namespace Dimension
Custom_Object::Custom_Object()
: Object(dmnsn_new_object())
{
- m_object->ptr = this;
- m_object->intersections_fn = &intersections_fn;
- m_object->inside_fn = &inside_fn;
+ dmnsn()->ptr = this;
+ dmnsn()->intersections_fn = &intersections_fn;
+ dmnsn()->inside_fn = &inside_fn;
}
// Delete the object
Custom_Object::~Custom_Object()
{
- dmnsn_delete_object(m_object);
+ if (unique()) {
+ dmnsn_delete_object(dmnsn());
+ }
}
}
diff --git a/libdimensionxx/objects.cpp b/libdimensionxx/objects.cpp
index 1b78731..eac642c 100644
--- a/libdimensionxx/objects.cpp
+++ b/libdimensionxx/objects.cpp
@@ -26,7 +26,7 @@ namespace Dimension
Sphere::Sphere()
: Object(dmnsn_new_sphere())
{
- if (!m_object) {
+ if (!dmnsn()) {
throw Dimension_Error("Failed to allocate sphere.");
}
}
@@ -34,14 +34,28 @@ namespace Dimension
// Delete a sphere
Sphere::~Sphere()
{
- dmnsn_delete_sphere(m_object);
+ if (unique()) {
+ dmnsn_delete_sphere(dmnsn());
+ }
}
+ // Shallow copy a sphere
+ Object*
+ Sphere::copy() const
+ {
+ return new Sphere(*this);
+ }
+
+ // Protected copy constructor
+ Sphere::Sphere(const Sphere& sphere)
+ : Object(sphere)
+ { }
+
// Create a cube
Cube::Cube()
: Object(dmnsn_new_cube())
{
- if (!m_object) {
+ if (!dmnsn()) {
throw Dimension_Error("Failed to allocate cube.");
}
}
@@ -49,6 +63,20 @@ namespace Dimension
// Delete a sphere
Cube::~Cube()
{
- dmnsn_delete_cube(m_object);
+ if (unique()) {
+ dmnsn_delete_cube(dmnsn());
+ }
}
+
+ // Shallow copy a cube
+ Object*
+ Cube::copy() const
+ {
+ return new Cube(*this);
+ }
+
+ // Protected copy constructor
+ Cube::Cube(const Cube& sphere)
+ : Object(sphere)
+ { }
}
diff --git a/libdimensionxx/scene.cpp b/libdimensionxx/scene.cpp
index f5e4ea8..2b0fba5 100644
--- a/libdimensionxx/scene.cpp
+++ b/libdimensionxx/scene.cpp
@@ -24,25 +24,24 @@ namespace Dimension
{
// Allocate a dmnsn_scene
Scene::Scene(const Color& background, Camera& camera, Canvas& canvas)
- : m_scene(dmnsn_new_scene()), m_camera(&camera), m_canvas(&canvas)
+ : m_scene(new dmnsn_scene*(dmnsn_new_scene())), m_camera(camera.copy()),
+ m_canvas(new Canvas(canvas))
{
if (!m_scene) {
throw Dimension_Error("Couldn't allocate scene.");
}
- m_scene->background = background.dmnsn();
- m_scene->camera = camera.dmnsn();
- m_scene->canvas = canvas.dmnsn();
+ dmnsn()->background = background.dmnsn();
+ dmnsn()->camera = this->camera().dmnsn();
+ dmnsn()->canvas = this->canvas().dmnsn();
}
- // Wrap an existing scene
- Scene::Scene(dmnsn_scene* scene)
- : m_scene(scene) { }
-
// Delete the scene
Scene::~Scene()
{
- dmnsn_delete_scene(m_scene);
+ if (m_scene.unique()) {
+ dmnsn_delete_scene(dmnsn());
+ }
}
// Element access
@@ -50,7 +49,7 @@ namespace Dimension
Color
Scene::background() const
{
- return Color(m_scene->background);
+ return Color(dmnsn()->background);
}
Camera&
@@ -77,12 +76,27 @@ namespace Dimension
return *m_canvas;
}
- // Add objects
+ // An iterator to the beginning of the object list
+ Scene::Iterator
+ Scene::begin()
+ {
+ return Iterator(m_objects.begin());
+ }
+
+ // An iterator one past the end of the object list
+ Scene::Iterator
+ Scene::end()
+ {
+ return Iterator(m_objects.end());
+ }
+
+ // Add an object
void
Scene::push_object(Object& object)
{
+ m_objects.push_back(std::tr1::shared_ptr<Object>(object.copy()));
dmnsn_object* cobject = object.dmnsn();
- dmnsn_array_push(m_scene->objects, &cobject);
+ dmnsn_array_push(dmnsn()->objects, &cobject);
}
// Access the wrapped C object.
@@ -90,12 +104,12 @@ namespace Dimension
dmnsn_scene*
Scene::dmnsn()
{
- return m_scene;
+ return *m_scene;
}
const dmnsn_scene*
Scene::dmnsn() const
{
- return m_scene;
+ return *m_scene;
}
}