From 3ec26ddd28cbcc279a4fa65de8d68c68b3950576 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 13 Jul 2011 13:47:17 -0600 Subject: Implement triangles. --- dimension/tests/demo.dmnsn | 22 +++++++++++ libdimension-python/dimension.pxd | 3 ++ libdimension-python/dimension.pyx | 14 +++++++ libdimension-python/tests/demo.py | 20 ++++++++++ libdimension/Makefile.am | 3 +- libdimension/dimension/objects.h | 10 +++++ libdimension/tests/render.c | 33 ++++++++++++++++ libdimension/triangle.c | 83 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 libdimension/triangle.c diff --git a/dimension/tests/demo.dmnsn b/dimension/tests/demo.dmnsn index a85a96e..550c57a 100644 --- a/dimension/tests/demo.dmnsn +++ b/dimension/tests/demo.dmnsn @@ -17,6 +17,9 @@ # along with this program. If not, see . # ######################################################################### +# Background +background = Clear + # Camera camera = PerspectiveCamera(location = (0, 0.25, -4), look_at = 0) @@ -97,6 +100,24 @@ torii = Union( spike = Union([arrow, torii]).transform(rotate(-45*X)) +strip_textures = [ + Texture(pigment = Red), + Texture(pigment = Orange), + Texture(pigment = Yellow), +] +strip_triangles = [] + +a = 0 +b = Vector(0, sqrt(3)/2, 0.5) +c = Z +for i in range(128): + strip_triangles.append(Triangle(a, b, c, texture = strip_textures[i%3])) + a = b + b = c + c = a + Z + +strip = Union(strip_triangles).transform(translate(5, -2, -4)) + ground = Plane( normal = Y, distance = -2, @@ -112,6 +133,7 @@ ground = Plane( objects = [ hollow_cube, spike, + strip, ground, ] diff --git a/libdimension-python/dimension.pxd b/libdimension-python/dimension.pxd index 6ac6319..f675501 100644 --- a/libdimension-python/dimension.pxd +++ b/libdimension-python/dimension.pxd @@ -307,6 +307,9 @@ cdef extern from "../libdimension/dimension.h": dmnsn_object *dmnsn_new_object() void dmnsn_delete_object(dmnsn_object *object) + dmnsn_object *dmnsn_new_triangle(dmnsn_vector a, + dmnsn_vector b, + dmnsn_vector c) dmnsn_object *dmnsn_new_plane(dmnsn_vector normal) dmnsn_object *dmnsn_new_sphere() dmnsn_object *dmnsn_new_cube() diff --git a/libdimension-python/dimension.pyx b/libdimension-python/dimension.pyx index 8c25538..addba7e 100644 --- a/libdimension-python/dimension.pyx +++ b/libdimension-python/dimension.pyx @@ -939,6 +939,20 @@ cdef class Object: self._object.texture.trans = dmnsn_matrix_mul(self._object.texture.trans, trans.inverse()._m) +cdef class Triangle(Object): + """A triangle.""" + def __init__(self, a, b, c, *args, **kwargs): + """ + Create a Triangle. + + Keyword arguments: + a, b, c -- the corners of the triangle + + Additionally, Triangle() accepts any arguments that Object() accepts. + """ + self._object = dmnsn_new_triangle(Vector(a)._v, Vector(b)._v, Vector(c)._v) + Object.__init__(self, *args, **kwargs) + cdef class Plane(Object): """A plane.""" def __init__(self, normal, double distance, *args, **kwargs): diff --git a/libdimension-python/tests/demo.py b/libdimension-python/tests/demo.py index 96ef22c..e4e1e14 100755 --- a/libdimension-python/tests/demo.py +++ b/libdimension-python/tests/demo.py @@ -19,6 +19,7 @@ # along with this program. If not, see . # ######################################################################### +from math import * from dimension import * # Treat warnings as errors for tests @@ -116,6 +117,24 @@ torii = Union( spike = Union([arrow, torii]).transform(rotate(-45*X)) +strip_textures = [ + Texture(pigment = Red), + Texture(pigment = Orange), + Texture(pigment = Yellow), +] +strip_triangles = [] + +a = 0 +b = Vector(0, sqrt(3)/2, 0.5) +c = Z +for i in range(128): + strip_triangles.append(Triangle(a, b, c, texture = strip_textures[i%3])) + a = b + b = c + c = a + Z + +strip = Union(strip_triangles).transform(translate(5, -2, -4)) + ground = Plane( normal = Y, distance = -2, @@ -131,6 +150,7 @@ ground = Plane( objects = [ hollow_cube, spike, + strip, ground, ] diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am index 0f3dee5..b042fc9 100644 --- a/libdimension/Makefile.am +++ b/libdimension/Makefile.am @@ -111,7 +111,8 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \ threads.c \ threads.h \ timer.c \ - torus.c + torus.c \ + triangle.c libdimension_la_CFLAGS = $(AM_CFLAGS) libdimension_la_LDFLAGS = -version-info 0:0:0 -no-undefined $(AM_LDFLAGS) libdimension_la_LIBADD = -lm -lpthread diff --git a/libdimension/dimension/objects.h b/libdimension/dimension/objects.h index aa53329..ba9547d 100644 --- a/libdimension/dimension/objects.h +++ b/libdimension/dimension/objects.h @@ -25,6 +25,16 @@ #include +/** + * A triangle. + * @param[in] a The first corner of the triangle. + * @param[in] b The second corner of the triangle. + * @param[in] c The third corner of the triangle. + */ +dmnsn_object *dmnsn_new_triangle(dmnsn_vector a, + dmnsn_vector b, + dmnsn_vector c); + /** * A plane. * @param[in] normal The normal vector of the plane. diff --git a/libdimension/tests/render.c b/libdimension/tests/render.c index 04897d6..a9d20d7 100644 --- a/libdimension/tests/render.c +++ b/libdimension/tests/render.c @@ -190,6 +190,39 @@ dmnsn_new_test_scene(void) ); dmnsn_array_push(scene->objects, &spike); + /* Triangle strip */ + + dmnsn_array *strip_array = dmnsn_new_array(sizeof(dmnsn_object *)); + dmnsn_vector a = dmnsn_zero; + dmnsn_vector b = dmnsn_new_vector(0.0, sqrt(3.0)/2.0, 0.5); + dmnsn_vector c = dmnsn_z; + dmnsn_texture *strip_textures[3] = { + dmnsn_new_texture(), + dmnsn_new_texture(), + dmnsn_new_texture(), + }; + strip_textures[0]->pigment = dmnsn_new_solid_pigment(dmnsn_red); + strip_textures[1]->pigment = dmnsn_new_solid_pigment(dmnsn_orange); + strip_textures[2]->pigment = dmnsn_new_solid_pigment(dmnsn_yellow); + for (unsigned int i = 0; i < 128; ++i) { + dmnsn_object *triangle = dmnsn_new_triangle(a, b, c); + triangle->texture = strip_textures[i%3]; + DMNSN_INCREF(triangle->texture); + dmnsn_array_push(strip_array, &triangle); + + a = b; + b = c; + c = dmnsn_vector_add(a, dmnsn_z); + } + for (unsigned int i = 0; i < 3; ++i) { + dmnsn_delete_texture(strip_textures[i]); + } + + dmnsn_object *strip = dmnsn_new_csg_union(strip_array); + dmnsn_delete_array(strip_array); + strip->trans = dmnsn_translation_matrix(dmnsn_new_vector(5.0, -2.0, -4.0)); + dmnsn_array_push(scene->objects, &strip); + dmnsn_object *plane = dmnsn_new_plane(dmnsn_new_vector(0.0, 1.0, 0.0)); plane->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, -2.0, 0.0)); dmnsn_pattern *checker1 = dmnsn_new_checker_pattern(); diff --git a/libdimension/triangle.c b/libdimension/triangle.c new file mode 100644 index 0000000..bd54e1a --- /dev/null +++ b/libdimension/triangle.c @@ -0,0 +1,83 @@ +/************************************************************************* + * Copyright (C) 2009-2010 Tavian Barnes * + * * + * 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 * + * . * + *************************************************************************/ + +/** + * @file + * Triangles. + */ + +#include "dimension.h" + +typedef struct dmnsn_triangle_payload { + dmnsn_vector a, ab, ac, normal; +} dmnsn_triangle_payload; + +/** Triangle intersection callback. */ +static bool +dmnsn_triangle_intersection_fn(const dmnsn_object *triangle, dmnsn_line l, + dmnsn_intersection *intersection) +{ + const dmnsn_triangle_payload *payload = triangle->ptr; + + double den = -dmnsn_vector_dot(l.n, payload->normal); + dmnsn_vector ax0 = dmnsn_vector_sub(l.x0, payload->a); + double t = dmnsn_vector_dot(ax0, payload->normal)/den; + double u = -dmnsn_vector_dot(l.n, dmnsn_vector_cross(ax0, payload->ac))/den; + double v = -dmnsn_vector_dot(l.n, dmnsn_vector_cross(payload->ab, ax0))/den; + if (t >= 0.0 && u >= 0.0 && v >= 0.0 && u + v <= 1.0) { + intersection->ray = l; + intersection->t = t; + intersection->normal = payload->normal; + intersection->texture = triangle->texture; + intersection->interior = triangle->interior; + return true; + } + + return false; +} + +/** Triangle inside callback. */ +static bool +dmnsn_triangle_inside_fn(const dmnsn_object *triangle, dmnsn_vector point) +{ + return false; +} + +/* Allocate a new triangle */ +dmnsn_object * +dmnsn_new_triangle(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c) +{ + dmnsn_object *triangle = dmnsn_new_object(); + + dmnsn_triangle_payload *payload = + dmnsn_malloc(sizeof(dmnsn_triangle_payload)); + payload->a = a; + payload->ab = dmnsn_vector_sub(b, a); + payload->ac = dmnsn_vector_sub(c, a); + payload->normal = dmnsn_vector_cross(payload->ab, payload->ac); + + triangle->ptr = payload; + triangle->intersection_fn = dmnsn_triangle_intersection_fn; + triangle->inside_fn = dmnsn_triangle_inside_fn; + triangle->free_fn = dmnsn_free; + triangle->bounding_box.min = dmnsn_vector_min(dmnsn_vector_min(a, b), c); + triangle->bounding_box.max = dmnsn_vector_max(dmnsn_vector_max(a, b), c); + return triangle; +} -- cgit v1.2.3