From 4e2a6e40a77068492e3b63b84a18d0cc7f003fb7 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 6 Jan 2010 13:43:14 -0500 Subject: Split up objects, finishes, pigments, lights, cameras, etc. --- libdimension/Makefile.am | 14 ++- libdimension/ambient.c | 53 +++++++++ libdimension/cameras.c | 86 --------------- libdimension/cube.c | 143 ++++++++++++++++++++++++ libdimension/diffuse.c | 58 ++++++++++ libdimension/finish_combination.c | 112 +++++++++++++++++++ libdimension/finishes.c | 221 -------------------------------------- libdimension/lights.c | 52 --------- libdimension/objects.c | 211 ------------------------------------ libdimension/perspective.c | 86 +++++++++++++++ libdimension/phong.c | 67 ++++++++++++ libdimension/pigments.c | 56 ---------- libdimension/point_light.c | 52 +++++++++ libdimension/solid_pigment.c | 56 ++++++++++ libdimension/sphere.c | 91 ++++++++++++++++ 15 files changed, 727 insertions(+), 631 deletions(-) create mode 100644 libdimension/ambient.c delete mode 100644 libdimension/cameras.c create mode 100644 libdimension/cube.c create mode 100644 libdimension/diffuse.c create mode 100644 libdimension/finish_combination.c delete mode 100644 libdimension/finishes.c delete mode 100644 libdimension/lights.c delete mode 100644 libdimension/objects.c create mode 100644 libdimension/perspective.c create mode 100644 libdimension/phong.c delete mode 100644 libdimension/pigments.c create mode 100644 libdimension/point_light.c create mode 100644 libdimension/solid_pigment.c create mode 100644 libdimension/sphere.c diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am index e67f09e..49685c7 100644 --- a/libdimension/Makefile.am +++ b/libdimension/Makefile.am @@ -41,27 +41,31 @@ nobase_include_HEADERS = dimension.h \ lib_LTLIBRARIES = libdimension.la libdimension_la_SOURCES = $(nobase_include_HEADERS) \ + ambient.c \ camera.c \ - cameras.c \ canvas.c \ color.c \ + cube.c \ + diffuse.c \ dimension_impl.h \ error.c \ - finishes.c \ + finish_combination.c \ geometry.c \ gl.c \ inlines.c \ kD_splay_tree.c \ kD_splay_tree.h \ light.c \ - lights.c \ object.c \ - objects.c \ - pigments.c \ + perspective.c \ + phong.c \ png.c \ + point_light.c \ progress.c \ raytrace.c \ scene.c \ + solid_pigment.c \ + sphere.c \ texture.c libdimension_la_LDFLAGS = -version-info 0:0:0 libdimension_la_LIBADD = -lm -lpthread -lpng -lGL diff --git a/libdimension/ambient.c b/libdimension/ambient.c new file mode 100644 index 0000000..916ba67 --- /dev/null +++ b/libdimension/ambient.c @@ -0,0 +1,53 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include + +/* + * Ambient finish + */ + +static dmnsn_color +dmnsn_ambient_finish_fn(const dmnsn_finish *finish, dmnsn_color pigment) +{ + dmnsn_color *ambient = finish->ptr; + return dmnsn_color_illuminate(*ambient, pigment); +} + +dmnsn_finish * +dmnsn_new_ambient_finish(dmnsn_color ambient) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + dmnsn_color *param = malloc(sizeof(dmnsn_color)); + if (!param) { + dmnsn_delete_finish(finish); + return NULL; + } + + *param = ambient; + finish->ptr = param; + finish->ambient_fn = &dmnsn_ambient_finish_fn; + finish->free_fn = &free; + } + return finish; +} diff --git a/libdimension/cameras.c b/libdimension/cameras.c deleted file mode 100644 index 3389cc7..0000000 --- a/libdimension/cameras.c +++ /dev/null @@ -1,86 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009 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 * - * . * - *************************************************************************/ - -#include "dimension.h" - -/* - * Perspective camera - */ - -/* Perspective camera ray callback */ -static dmnsn_line dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera, - double x, double y); - -/* Create a new perspective camera. Rays are aimed from the origin to a screen - located on the z = 1 frame, from (-0.5, -0.5) to (0.5, 0.5). Rays are then - transformed by the camera's transformation matrix. */ -dmnsn_camera * -dmnsn_new_perspective_camera() -{ - dmnsn_matrix *ptr; - dmnsn_camera *camera = dmnsn_new_camera(); - if (camera) { - /* Allocate room for the transformation matrix */ - ptr = malloc(sizeof(dmnsn_matrix)); - if (!ptr) { - dmnsn_delete_camera(camera); - return NULL; - } - *ptr = dmnsn_identity_matrix(); - - camera->ray_fn = &dmnsn_perspective_camera_ray_fn; - camera->free_fn = &free; - camera->ptr = ptr; - } - return camera; -} - -/* Get the transformation matrix */ -dmnsn_matrix -dmnsn_get_perspective_camera_trans(const dmnsn_camera *camera) -{ - dmnsn_matrix *trans = camera->ptr; - return *trans; -} - -/* Set the transformation matrix */ -void -dmnsn_set_perspective_camera_trans(dmnsn_camera *camera, dmnsn_matrix T) -{ - dmnsn_matrix *trans = camera->ptr; - *trans = T; -} - -/* Perspective camera ray callback */ -static dmnsn_line -dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera, - double x, double y) -{ - dmnsn_matrix *trans = camera->ptr; - dmnsn_line l; - - /* Rays originate at the origin, oddly enough */ - l.x0 = dmnsn_new_vector(0.0, 0.0, 0.0); - - /* Aim at the z = 1 plane */ - l.n = dmnsn_new_vector(x - 0.5, y - 0.5, 1.0); - - return dmnsn_matrix_line_mul(*trans, l); -} diff --git a/libdimension/cube.c b/libdimension/cube.c new file mode 100644 index 0000000..57dd12b --- /dev/null +++ b/libdimension/cube.c @@ -0,0 +1,143 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include /* For sqrt */ + +/* + * Cube + */ + +/* Cube callbacks */ +static dmnsn_intersection *dmnsn_cube_intersection_fn(const dmnsn_object *cube, + dmnsn_line line); +static int dmnsn_cube_inside_fn(const dmnsn_object *cube, + dmnsn_vector point); + +/* Allocate a new cube object */ +dmnsn_object * +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->min = dmnsn_new_vector(-1.0, -1.0, -1.0); + cube->max = dmnsn_new_vector(1.0, 1.0, 1.0); + } + return cube; +} + +/* Intersections callback for a cube */ +static dmnsn_intersection * +dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line) +{ + double t = -1.0, t_temp; + dmnsn_vector p, normal; + dmnsn_intersection *intersection = NULL; + + /* Six ray-plane intersection tests (x, y, z) = +/- 1.0 */ + + if (line.n.x != 0.0) { + /* x = -1.0 */ + t_temp = (-1.0 - line.x0.x)/line.n.x; + 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; + normal = dmnsn_new_vector(-copysign(1.0, line.n.x), 0.0, 0.0); + } + + /* x = 1.0 */ + t_temp = (1.0 - line.x0.x)/line.n.x; + 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; + normal = dmnsn_new_vector(-copysign(1.0, line.n.x), 0.0, 0.0); + } + } + + 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_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; + normal = dmnsn_new_vector(0.0, -copysign(1.0, line.n.y), 0.0); + } + + /* y = 1.0 */ + t_temp = (1.0 - line.x0.y)/line.n.y; + 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; + normal = dmnsn_new_vector(0.0, -copysign(1.0, line.n.y), 0.0); + } + } + + 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_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; + normal = dmnsn_new_vector(0.0, 0.0, -copysign(1.0, line.n.z)); + } + + /* z = 1.0 */ + t_temp = (1.0 - line.x0.z)/line.n.z; + 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; + normal = dmnsn_new_vector(0.0, 0.0, -copysign(1.0, line.n.z)); + } + } + + if (t >= 0.0) { + intersection = dmnsn_new_intersection(); + intersection->ray = line; + intersection->t = t; + intersection->normal = normal; + intersection->texture = cube->texture; + } + + return intersection; +} + +/* Inside callback for a cube */ +static int +dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point) +{ + return point.x > -1.0 && point.x < 1.0 + && point.y > -1.0 && point.y < 1.0 + && point.z > -1.0 && point.z < 1.0; +} diff --git a/libdimension/diffuse.c b/libdimension/diffuse.c new file mode 100644 index 0000000..4da51ee --- /dev/null +++ b/libdimension/diffuse.c @@ -0,0 +1,58 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include + +/* + * Diffuse finish + */ + +static dmnsn_color +dmnsn_diffuse_finish_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) +{ + double *diffuse = finish->ptr; + double diffuse_factor = (*diffuse)*dmnsn_vector_dot(ray, normal); + return dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); +} + +dmnsn_finish * +dmnsn_new_diffuse_finish(double diffuse) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + double *param = malloc(sizeof(double)); + if (!param) { + dmnsn_delete_finish(finish); + return NULL; + } + + *param = diffuse; + + finish->ptr = param; + finish->finish_fn = &dmnsn_diffuse_finish_fn; + finish->free_fn = &free; + } + return finish; +} diff --git a/libdimension/finish_combination.c b/libdimension/finish_combination.c new file mode 100644 index 0000000..045db96 --- /dev/null +++ b/libdimension/finish_combination.c @@ -0,0 +1,112 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include + +/* + * Finish combinations + */ + +static dmnsn_color +dmnsn_finish_combination_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) +{ + dmnsn_finish **params = finish->ptr; + if (params[0]->finish_fn && params[1]->finish_fn) { + return dmnsn_color_add((*params[0]->finish_fn)(params[0], light, color, ray, + normal, viewer), + (*params[1]->finish_fn)(params[1], light, color, ray, + normal, viewer)); + } else if (params[0]->finish_fn) { + return (*params[0]->finish_fn)(params[0], light, color, ray, + normal, viewer); + } else if (params[1]->finish_fn) { + return (*params[1]->finish_fn)(params[1], light, color, ray, + normal, viewer); + } else { + return dmnsn_black; + } +} + +static dmnsn_color +dmnsn_finish_combination_ambient_fn(const dmnsn_finish *finish, + dmnsn_color pigment) +{ + dmnsn_finish **params = finish->ptr; + if (params[0]->ambient_fn && params[1]->ambient_fn) { + return dmnsn_color_add((*params[0]->ambient_fn)(params[0], pigment), + (*params[1]->ambient_fn)(params[1], pigment)); + } else if (params[0]->ambient_fn) { + return (*params[0]->ambient_fn)(params[0], pigment); + } else if (params[1]->ambient_fn) { + return (*params[1]->ambient_fn)(params[1], pigment); + } else { + return dmnsn_black; + } +} + +static void +dmnsn_finish_combination_free_fn(void *ptr) +{ + dmnsn_finish **params = ptr; + dmnsn_delete_finish(params[0]); + dmnsn_delete_finish(params[1]); + free(ptr); +} + +dmnsn_finish * +dmnsn_new_finish_combination(dmnsn_finish *f1, dmnsn_finish *f2) +{ + if (f1 && f2) { + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + dmnsn_finish **params = malloc(2*sizeof(dmnsn_finish *)); + if (!params) { + dmnsn_delete_finish(finish); + dmnsn_delete_finish(f2); + dmnsn_delete_finish(f1); + return NULL; + } + + params[0] = f1; + params[1] = f2; + + finish->ptr = params; + finish->finish_fn = &dmnsn_finish_combination_fn; + finish->ambient_fn = &dmnsn_finish_combination_ambient_fn; + finish->free_fn = &dmnsn_finish_combination_free_fn; + + return finish; + } else { + dmnsn_delete_finish(f2); + dmnsn_delete_finish(f1); + } + } else if (f1) { + dmnsn_delete_finish(f1); + } else if (f2) { + dmnsn_delete_finish(f2); + } + + return NULL; +} diff --git a/libdimension/finishes.c b/libdimension/finishes.c deleted file mode 100644 index a1b10e7..0000000 --- a/libdimension/finishes.c +++ /dev/null @@ -1,221 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009 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 * - * . * - *************************************************************************/ - -#include "dimension.h" -#include /* For malloc */ -#include - -/* - * Finish combinations - */ - -static dmnsn_color -dmnsn_finish_combination_fn(const dmnsn_finish *finish, - dmnsn_color light, dmnsn_color color, - dmnsn_vector ray, dmnsn_vector normal, - dmnsn_vector viewer) -{ - dmnsn_finish **params = finish->ptr; - if (params[0]->finish_fn && params[1]->finish_fn) { - return dmnsn_color_add((*params[0]->finish_fn)(params[0], light, color, ray, - normal, viewer), - (*params[1]->finish_fn)(params[1], light, color, ray, - normal, viewer)); - } else if (params[0]->finish_fn) { - return (*params[0]->finish_fn)(params[0], light, color, ray, - normal, viewer); - } else if (params[1]->finish_fn) { - return (*params[1]->finish_fn)(params[1], light, color, ray, - normal, viewer); - } else { - return dmnsn_black; - } -} - -static dmnsn_color -dmnsn_finish_combination_ambient_fn(const dmnsn_finish *finish, - dmnsn_color pigment) -{ - dmnsn_finish **params = finish->ptr; - if (params[0]->ambient_fn && params[1]->ambient_fn) { - return dmnsn_color_add((*params[0]->ambient_fn)(params[0], pigment), - (*params[1]->ambient_fn)(params[1], pigment)); - } else if (params[0]->ambient_fn) { - return (*params[0]->ambient_fn)(params[0], pigment); - } else if (params[1]->ambient_fn) { - return (*params[1]->ambient_fn)(params[1], pigment); - } else { - return dmnsn_black; - } -} - -static void -dmnsn_finish_combination_free_fn(void *ptr) -{ - dmnsn_finish **params = ptr; - dmnsn_delete_finish(params[0]); - dmnsn_delete_finish(params[1]); - free(ptr); -} - -dmnsn_finish * -dmnsn_new_finish_combination(dmnsn_finish *f1, dmnsn_finish *f2) -{ - if (f1 && f2) { - dmnsn_finish *finish = dmnsn_new_finish(); - if (finish) { - dmnsn_finish **params = malloc(2*sizeof(dmnsn_finish *)); - if (!params) { - dmnsn_delete_finish(finish); - dmnsn_delete_finish(f2); - dmnsn_delete_finish(f1); - return NULL; - } - - params[0] = f1; - params[1] = f2; - - finish->ptr = params; - finish->finish_fn = &dmnsn_finish_combination_fn; - finish->ambient_fn = &dmnsn_finish_combination_ambient_fn; - finish->free_fn = &dmnsn_finish_combination_free_fn; - - return finish; - } else { - dmnsn_delete_finish(f2); - dmnsn_delete_finish(f1); - } - } else if (f1) { - dmnsn_delete_finish(f1); - } else if (f2) { - dmnsn_delete_finish(f2); - } - - return NULL; -} - -/* - * Ambient finish - */ - -static dmnsn_color -dmnsn_ambient_finish_fn(const dmnsn_finish *finish, dmnsn_color pigment) -{ - dmnsn_color *ambient = finish->ptr; - return dmnsn_color_illuminate(*ambient, pigment); -} - -dmnsn_finish * -dmnsn_new_ambient_finish(dmnsn_color ambient) -{ - dmnsn_finish *finish = dmnsn_new_finish(); - if (finish) { - dmnsn_color *param = malloc(sizeof(dmnsn_color)); - if (!param) { - dmnsn_delete_finish(finish); - return NULL; - } - - *param = ambient; - finish->ptr = param; - finish->ambient_fn = &dmnsn_ambient_finish_fn; - finish->free_fn = &free; - } - return finish; -} - -/* - * Diffuse finish - */ - -static dmnsn_color -dmnsn_diffuse_finish_fn(const dmnsn_finish *finish, - dmnsn_color light, dmnsn_color color, - dmnsn_vector ray, dmnsn_vector normal, - dmnsn_vector viewer) -{ - double *diffuse = finish->ptr; - double diffuse_factor = (*diffuse)*dmnsn_vector_dot(ray, normal); - return dmnsn_color_mul(diffuse_factor, dmnsn_color_illuminate(light, color)); -} - -dmnsn_finish * -dmnsn_new_diffuse_finish(double diffuse) -{ - dmnsn_finish *finish = dmnsn_new_finish(); - if (finish) { - double *param = malloc(sizeof(double)); - if (!param) { - dmnsn_delete_finish(finish); - return NULL; - } - - *param = diffuse; - - finish->ptr = param; - finish->finish_fn = &dmnsn_diffuse_finish_fn; - finish->free_fn = &free; - } - return finish; -} - -/* - * Phong finish - */ - -static dmnsn_color -dmnsn_phong_finish_fn(const dmnsn_finish *finish, - dmnsn_color light, dmnsn_color color, - dmnsn_vector ray, dmnsn_vector normal, - dmnsn_vector viewer) -{ - double *params = finish->ptr; - - double specular = params[0]; - double exp = params[1]; - - dmnsn_vector proj = dmnsn_vector_mul(2*dmnsn_vector_dot(ray, normal), normal); - dmnsn_vector reflected = dmnsn_vector_sub(proj, ray); - - double specular_factor = pow(dmnsn_vector_dot(reflected, viewer), exp); - return dmnsn_color_mul(specular*specular_factor, light); -} - -/* A phong finish */ -dmnsn_finish * -dmnsn_new_phong_finish(double specular, double exp) -{ - dmnsn_finish *finish = dmnsn_new_finish(); - if (finish) { - double *params = malloc(2*sizeof(double)); - if (!params) { - dmnsn_delete_finish(finish); - return NULL; - } - - params[0] = specular; - params[1] = exp; - - finish->ptr = params; - finish->finish_fn = &dmnsn_phong_finish_fn; - finish->free_fn = &free; - } - return finish; -} diff --git a/libdimension/lights.c b/libdimension/lights.c deleted file mode 100644 index 9862506..0000000 --- a/libdimension/lights.c +++ /dev/null @@ -1,52 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009 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 * - * . * - *************************************************************************/ - -#include "dimension.h" - -/* - * Point light source - */ - -static dmnsn_color -dmnsn_point_light_fn(const dmnsn_light *light, dmnsn_vector v) -{ - return *(dmnsn_color *)light->ptr; -} - -dmnsn_light * -dmnsn_new_point_light(dmnsn_vector x0, dmnsn_color color) -{ - dmnsn_light *light = dmnsn_new_light(); - if (light) { - /* Allocate room for the transformation matrix */ - dmnsn_color *ptr = malloc(sizeof(dmnsn_color)); - if (!ptr) { - dmnsn_delete_light(light); - return NULL; - } - *ptr = color; - - light->x0 = x0; - light->light_fn = &dmnsn_point_light_fn; - light->free_fn = &free; - light->ptr = ptr; - } - return light; -} diff --git a/libdimension/objects.c b/libdimension/objects.c deleted file mode 100644 index 3470506..0000000 --- a/libdimension/objects.c +++ /dev/null @@ -1,211 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009 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 * - * . * - *************************************************************************/ - -#include "dimension.h" -#include /* For malloc */ -#include /* For sqrt */ - -/* - * Sphere - */ - -/* Sphere object callbacks */ - -static dmnsn_intersection * -dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line); - -static int dmnsn_sphere_inside_fn(const dmnsn_object *sphere, - dmnsn_vector point); - -/* Allocate a new sphere */ -dmnsn_object * -dmnsn_new_sphere() -{ - dmnsn_object *sphere = dmnsn_new_object(); - if (sphere) { - sphere->intersection_fn = &dmnsn_sphere_intersection_fn; - sphere->inside_fn = &dmnsn_sphere_inside_fn; - sphere->min = dmnsn_new_vector(-1.0, -1.0, -1.0); - sphere->max = dmnsn_new_vector(1.0, 1.0, 1.0); - } - return sphere; -} - -/* Returns the closest intersection of `line' with `sphere' */ -static dmnsn_intersection * -dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line) -{ - double a, b, c, t; - dmnsn_intersection *intersection = NULL; - - /* Solve (x0 + nx*t)^2 + (y0 + ny*t)^2 + (z0 + nz*t)^2 == 1 */ - - a = line.n.x*line.n.x + line.n.y*line.n.y + line.n.z*line.n.z; - b = 2.0*(line.n.x*line.x0.x + line.n.y*line.x0.y + line.n.z*line.x0.z); - c = line.x0.x*line.x0.x + line.x0.y*line.x0.y + line.x0.z*line.x0.z - 1.0; - - if (b*b - 4.0*a*c >= 0) { - t = (-b - sqrt(b*b - 4.0*a*c))/(2*a); - if (t < 0.0) { - t = (-b + sqrt(b*b - 4.0*a*c))/(2*a); - } - - if (t >= 0.0) { - intersection = dmnsn_new_intersection(); - intersection->ray = line; - intersection->t = t; - intersection->normal = dmnsn_line_point(line, t); - intersection->texture = sphere->texture; - - /* Flip the normal if we're inside the sphere */ - if (dmnsn_vector_dot(line.n, intersection->normal) > 0.0) - intersection->normal = dmnsn_vector_negate(intersection->normal); - } - } - - return intersection; -} - -/* Return whether a point is inside a sphere (x**2 + y**2 + z**2 < 1.0) */ -static int -dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point) -{ - return point.x*point.x + point.y*point.y + point.z*point.z < 1.0; -} - -/* - * Cube - */ - -/* Cube callbacks */ -static dmnsn_intersection *dmnsn_cube_intersection_fn(const dmnsn_object *cube, - dmnsn_line line); -static int dmnsn_cube_inside_fn(const dmnsn_object *cube, - dmnsn_vector point); - -/* Allocate a new cube object */ -dmnsn_object * -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->min = dmnsn_new_vector(-1.0, -1.0, -1.0); - cube->max = dmnsn_new_vector(1.0, 1.0, 1.0); - } - return cube; -} - -/* Intersections callback for a cube */ -static dmnsn_intersection * -dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line) -{ - double t = -1.0, t_temp; - dmnsn_vector p, normal; - dmnsn_intersection *intersection = NULL; - - /* Six ray-plane intersection tests (x, y, z) = +/- 1.0 */ - - if (line.n.x != 0.0) { - /* x = -1.0 */ - t_temp = (-1.0 - line.x0.x)/line.n.x; - 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; - normal = dmnsn_new_vector(-copysign(1.0, line.n.x), 0.0, 0.0); - } - - /* x = 1.0 */ - t_temp = (1.0 - line.x0.x)/line.n.x; - 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; - normal = dmnsn_new_vector(-copysign(1.0, line.n.x), 0.0, 0.0); - } - } - - 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_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; - normal = dmnsn_new_vector(0.0, -copysign(1.0, line.n.y), 0.0); - } - - /* y = 1.0 */ - t_temp = (1.0 - line.x0.y)/line.n.y; - 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; - normal = dmnsn_new_vector(0.0, -copysign(1.0, line.n.y), 0.0); - } - } - - 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_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; - normal = dmnsn_new_vector(0.0, 0.0, -copysign(1.0, line.n.z)); - } - - /* z = 1.0 */ - t_temp = (1.0 - line.x0.z)/line.n.z; - 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; - normal = dmnsn_new_vector(0.0, 0.0, -copysign(1.0, line.n.z)); - } - } - - if (t >= 0.0) { - intersection = dmnsn_new_intersection(); - intersection->ray = line; - intersection->t = t; - intersection->normal = normal; - intersection->texture = cube->texture; - } - - return intersection; -} - -/* Inside callback for a cube */ -static int -dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point) -{ - return point.x > -1.0 && point.x < 1.0 - && point.y > -1.0 && point.y < 1.0 - && point.z > -1.0 && point.z < 1.0; -} diff --git a/libdimension/perspective.c b/libdimension/perspective.c new file mode 100644 index 0000000..3389cc7 --- /dev/null +++ b/libdimension/perspective.c @@ -0,0 +1,86 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" + +/* + * Perspective camera + */ + +/* Perspective camera ray callback */ +static dmnsn_line dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera, + double x, double y); + +/* Create a new perspective camera. Rays are aimed from the origin to a screen + located on the z = 1 frame, from (-0.5, -0.5) to (0.5, 0.5). Rays are then + transformed by the camera's transformation matrix. */ +dmnsn_camera * +dmnsn_new_perspective_camera() +{ + dmnsn_matrix *ptr; + dmnsn_camera *camera = dmnsn_new_camera(); + if (camera) { + /* Allocate room for the transformation matrix */ + ptr = malloc(sizeof(dmnsn_matrix)); + if (!ptr) { + dmnsn_delete_camera(camera); + return NULL; + } + *ptr = dmnsn_identity_matrix(); + + camera->ray_fn = &dmnsn_perspective_camera_ray_fn; + camera->free_fn = &free; + camera->ptr = ptr; + } + return camera; +} + +/* Get the transformation matrix */ +dmnsn_matrix +dmnsn_get_perspective_camera_trans(const dmnsn_camera *camera) +{ + dmnsn_matrix *trans = camera->ptr; + return *trans; +} + +/* Set the transformation matrix */ +void +dmnsn_set_perspective_camera_trans(dmnsn_camera *camera, dmnsn_matrix T) +{ + dmnsn_matrix *trans = camera->ptr; + *trans = T; +} + +/* Perspective camera ray callback */ +static dmnsn_line +dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera, + double x, double y) +{ + dmnsn_matrix *trans = camera->ptr; + dmnsn_line l; + + /* Rays originate at the origin, oddly enough */ + l.x0 = dmnsn_new_vector(0.0, 0.0, 0.0); + + /* Aim at the z = 1 plane */ + l.n = dmnsn_new_vector(x - 0.5, y - 0.5, 1.0); + + return dmnsn_matrix_line_mul(*trans, l); +} diff --git a/libdimension/phong.c b/libdimension/phong.c new file mode 100644 index 0000000..815885f --- /dev/null +++ b/libdimension/phong.c @@ -0,0 +1,67 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include + +/* + * Phong finish + */ + +static dmnsn_color +dmnsn_phong_finish_fn(const dmnsn_finish *finish, + dmnsn_color light, dmnsn_color color, + dmnsn_vector ray, dmnsn_vector normal, + dmnsn_vector viewer) +{ + double *params = finish->ptr; + + double specular = params[0]; + double exp = params[1]; + + dmnsn_vector proj = dmnsn_vector_mul(2*dmnsn_vector_dot(ray, normal), normal); + dmnsn_vector reflected = dmnsn_vector_sub(proj, ray); + + double specular_factor = pow(dmnsn_vector_dot(reflected, viewer), exp); + return dmnsn_color_mul(specular*specular_factor, light); +} + +/* A phong finish */ +dmnsn_finish * +dmnsn_new_phong_finish(double specular, double exp) +{ + dmnsn_finish *finish = dmnsn_new_finish(); + if (finish) { + double *params = malloc(2*sizeof(double)); + if (!params) { + dmnsn_delete_finish(finish); + return NULL; + } + + params[0] = specular; + params[1] = exp; + + finish->ptr = params; + finish->finish_fn = &dmnsn_phong_finish_fn; + finish->free_fn = &free; + } + return finish; +} diff --git a/libdimension/pigments.c b/libdimension/pigments.c deleted file mode 100644 index adf44c4..0000000 --- a/libdimension/pigments.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009 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 * - * . * - *************************************************************************/ - -#include "dimension.h" -#include /* For malloc */ - -/* Solid color pigment callback */ -static dmnsn_color dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, - dmnsn_vector v); - -/* Create a solid color */ -dmnsn_pigment * -dmnsn_new_solid_pigment(dmnsn_color color) -{ - dmnsn_color *solid; - dmnsn_pigment *pigment = dmnsn_new_pigment(); - if (pigment) { - solid = malloc(sizeof(dmnsn_color)); - if (!solid) { - dmnsn_delete_pigment(pigment); - return NULL; - } - *solid = color; - - pigment->pigment_fn = &dmnsn_solid_pigment_fn; - pigment->free_fn = &free; - pigment->ptr = solid; - } - - return pigment; -} - -/* Solid color callback */ -static dmnsn_color -dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v) -{ - dmnsn_color *color = pigment->ptr; - return *color; -} diff --git a/libdimension/point_light.c b/libdimension/point_light.c new file mode 100644 index 0000000..9862506 --- /dev/null +++ b/libdimension/point_light.c @@ -0,0 +1,52 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" + +/* + * Point light source + */ + +static dmnsn_color +dmnsn_point_light_fn(const dmnsn_light *light, dmnsn_vector v) +{ + return *(dmnsn_color *)light->ptr; +} + +dmnsn_light * +dmnsn_new_point_light(dmnsn_vector x0, dmnsn_color color) +{ + dmnsn_light *light = dmnsn_new_light(); + if (light) { + /* Allocate room for the transformation matrix */ + dmnsn_color *ptr = malloc(sizeof(dmnsn_color)); + if (!ptr) { + dmnsn_delete_light(light); + return NULL; + } + *ptr = color; + + light->x0 = x0; + light->light_fn = &dmnsn_point_light_fn; + light->free_fn = &free; + light->ptr = ptr; + } + return light; +} diff --git a/libdimension/solid_pigment.c b/libdimension/solid_pigment.c new file mode 100644 index 0000000..adf44c4 --- /dev/null +++ b/libdimension/solid_pigment.c @@ -0,0 +1,56 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ + +/* Solid color pigment callback */ +static dmnsn_color dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, + dmnsn_vector v); + +/* Create a solid color */ +dmnsn_pigment * +dmnsn_new_solid_pigment(dmnsn_color color) +{ + dmnsn_color *solid; + dmnsn_pigment *pigment = dmnsn_new_pigment(); + if (pigment) { + solid = malloc(sizeof(dmnsn_color)); + if (!solid) { + dmnsn_delete_pigment(pigment); + return NULL; + } + *solid = color; + + pigment->pigment_fn = &dmnsn_solid_pigment_fn; + pigment->free_fn = &free; + pigment->ptr = solid; + } + + return pigment; +} + +/* Solid color callback */ +static dmnsn_color +dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v) +{ + dmnsn_color *color = pigment->ptr; + return *color; +} diff --git a/libdimension/sphere.c b/libdimension/sphere.c new file mode 100644 index 0000000..c61a46f --- /dev/null +++ b/libdimension/sphere.c @@ -0,0 +1,91 @@ +/************************************************************************* + * Copyright (C) 2009 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 * + * . * + *************************************************************************/ + +#include "dimension.h" +#include /* For malloc */ +#include /* For sqrt */ + +/* + * Sphere + */ + +/* Sphere object callbacks */ + +static dmnsn_intersection * +dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line); + +static int dmnsn_sphere_inside_fn(const dmnsn_object *sphere, + dmnsn_vector point); + +/* Allocate a new sphere */ +dmnsn_object * +dmnsn_new_sphere() +{ + dmnsn_object *sphere = dmnsn_new_object(); + if (sphere) { + sphere->intersection_fn = &dmnsn_sphere_intersection_fn; + sphere->inside_fn = &dmnsn_sphere_inside_fn; + sphere->min = dmnsn_new_vector(-1.0, -1.0, -1.0); + sphere->max = dmnsn_new_vector(1.0, 1.0, 1.0); + } + return sphere; +} + +/* Returns the closest intersection of `line' with `sphere' */ +static dmnsn_intersection * +dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line line) +{ + double a, b, c, t; + dmnsn_intersection *intersection = NULL; + + /* Solve (x0 + nx*t)^2 + (y0 + ny*t)^2 + (z0 + nz*t)^2 == 1 */ + + a = line.n.x*line.n.x + line.n.y*line.n.y + line.n.z*line.n.z; + b = 2.0*(line.n.x*line.x0.x + line.n.y*line.x0.y + line.n.z*line.x0.z); + c = line.x0.x*line.x0.x + line.x0.y*line.x0.y + line.x0.z*line.x0.z - 1.0; + + if (b*b - 4.0*a*c >= 0) { + t = (-b - sqrt(b*b - 4.0*a*c))/(2*a); + if (t < 0.0) { + t = (-b + sqrt(b*b - 4.0*a*c))/(2*a); + } + + if (t >= 0.0) { + intersection = dmnsn_new_intersection(); + intersection->ray = line; + intersection->t = t; + intersection->normal = dmnsn_line_point(line, t); + intersection->texture = sphere->texture; + + /* Flip the normal if we're inside the sphere */ + if (dmnsn_vector_dot(line.n, intersection->normal) > 0.0) + intersection->normal = dmnsn_vector_negate(intersection->normal); + } + } + + return intersection; +} + +/* Return whether a point is inside a sphere (x**2 + y**2 + z**2 < 1.0) */ +static int +dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point) +{ + return point.x*point.x + point.y*point.y + point.z*point.z < 1.0; +} -- cgit v1.2.3