summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/Makefile.am25
-rw-r--r--libdimension/canvas.c203
-rw-r--r--libdimension/dimension.h39
-rw-r--r--libdimension/dimension/canvas.h50
-rw-r--r--libdimension/dimension/color.h46
-rw-r--r--libdimension/dimension/geometry.h92
6 files changed, 455 insertions, 0 deletions
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am
new file mode 100644
index 0000000..293093c
--- /dev/null
+++ b/libdimension/Makefile.am
@@ -0,0 +1,25 @@
+###########################################################################
+## Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> ##
+## ##
+## This file is part of the Dimension Build Suite. ##
+## ##
+## The Dimension Build Suite is free software; you can redistribute it ##
+## and/or modify it under the terms of the GNU 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 Build Suite 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 ##
+## General Public License for more details. ##
+## ##
+## You should have received a copy of the GNU General Public License ##
+## along with this program. If not, see <http://www.gnu.org/licenses/>. ##
+###########################################################################
+
+nobase_include_HEADERS = dimension.h dimension/geometry.h dimension/color.h dimension/canvas.h
+
+lib_LTLIBRARIES = libdimension.la
+
+libdimension_la_SOURCES = dimension.h dimension/geometry.h dimension/color.h dimension/canvas.h canvas.c
+libdimension_la_LDFLAGS = -version-info 0:0:0
diff --git a/libdimension/canvas.c b/libdimension/canvas.c
new file mode 100644
index 0000000..c730b53
--- /dev/null
+++ b/libdimension/canvas.c
@@ -0,0 +1,203 @@
+/*************************************************************************
+ * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of Dimension. *
+ * *
+ * Dimension 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. *
+ * *
+ * Dimension 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 "dimension.h"
+#include <math.h>
+#include <stdlib.h>
+
+/* Conversions between CIE 1931 XYZ and sRGB color. */
+
+dmnsn_pixel
+dmnsn_pixel_from_color(dmnsn_color color)
+{
+ double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */
+ double R, G, B; /* sRGB values */
+ dmnsn_pixel pixel;
+
+ /*
+ * First, the linear conversion. Expressed as matrix multiplication, it looks
+ * like this:
+ *
+ * [Rlinear] [ 3.2410 -1.5374 -0.4986] [X]
+ * [Glinear] = [-0.9692 1.8760 0.0416]*[Y]
+ * [Blinear] [ 0.0556 -0.2040 1.0570] [Z]
+ */
+ Rlinear = 3.2410*color.X - 1.5374*color.Y - 0.4986*color.Z;
+ Glinear = -0.9692*color.X + 1.8760*color.Y + 0.0416*color.Z;
+ Blinear = 0.0556*color.X - 0.2040*color.Y + 1.0570*color.Z;
+
+ /*
+ * If C represents R, G, and B, then the sRGB values are now found as follows:
+ *
+ * { 12.92*Clinear, Clinear <= 0.0031308
+ * Csrgb = { 1/2.4
+ * { (1.055)*Clinear - 0.055, Clinear > 0.0031308
+ */
+
+ if (Rlinear <= 0.0031308) {
+ R = 12.92*Rlinear;
+ } else {
+ R = 1.055*pow(Rlinear, 1.0/2.4) - 0.055;
+ }
+
+ if (Glinear <= 0.0031308) {
+ G = 12.92*Glinear;
+ } else {
+ G = 1.055*pow(Glinear, 1.0/2.4) - 0.055;
+ }
+
+ if (Blinear <= 0.0031308) {
+ B = 12.92*Blinear;
+ } else {
+ B = 1.055*pow(Blinear, 1.0/2.4) - 0.055;
+ }
+
+ /* Now we go from unlimited to limited light, saturating at UINT16_MAX */
+
+ if (R < 0) {
+ pixel.r = 0;
+ } else if (R > 1) {
+ pixel.r = UINT16_MAX;
+ } else {
+ pixel.r = UINT16_MAX*R;
+ }
+
+ if (G < 0) {
+ pixel.g = 0;
+ } else if (G > 1) {
+ pixel.g = UINT16_MAX;
+ } else {
+ pixel.g = UINT16_MAX*G;
+ }
+
+ if (B < 0) {
+ pixel.b = 0;
+ } else if (B > 1) {
+ pixel.b = UINT16_MAX;
+ } else {
+ pixel.b = UINT16_MAX*B;
+ }
+
+ if (color.alpha < 0) {
+ pixel.a = 0;
+ } else if (color.alpha > 1) {
+ pixel.a = UINT16_MAX;
+ } else {
+ pixel.a = UINT16_MAX*color.alpha;
+ }
+
+ if (color.trans < 0) {
+ pixel.t = 0;
+ } else if (color.trans > 1) {
+ pixel.t = UINT16_MAX;
+ } else {
+ pixel.t = UINT16_MAX*color.trans;
+ }
+
+ return pixel;
+}
+
+dmnsn_color
+dmnsn_color_from_pixel(dmnsn_pixel pixel)
+{
+ double R, G, B; /* sRGB values */
+ double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */
+ dmnsn_color color;
+
+ /* Conversion back to unlimited light */
+ R = ((double)pixel.r)/UINT16_MAX;
+ G = ((double)pixel.g)/UINT16_MAX;
+ B = ((double)pixel.b)/UINT16_MAX;
+
+ /*
+ * If C represents R, G, and B, then the Clinear values are now found as
+ * follows:
+ *
+ * { Csrgb/12.92, Csrgb <= 0.04045
+ * Clinear = { 1/2.4
+ * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045
+ */
+
+ if (R <= 0.04045) {
+ Rlinear = R/19.92;
+ } else {
+ Rlinear = pow((R + 0.055)/1.055, 2.4);
+ }
+
+ if (G <= 0.04045) {
+ Glinear = G/19.92;
+ } else {
+ Glinear = pow((G + 0.055)/1.055, 2.4);
+ }
+
+ if (B <= 0.04045) {
+ Blinear = B/19.92;
+ } else {
+ Blinear = pow((B + 0.055)/1.055, 2.4);
+ }
+
+ /*
+ * Now, the linear conversion. Expressed as matrix multiplication, it looks
+ * like this:
+ *
+ * [X] [0.4124 0.3576 0.1805] [Rlinear]
+ * [Y] = [0.2126 0.7152 0.0722]*[Glinear]
+ * [X] [0.0193 0.1192 0.9505] [Blinear]
+ */
+
+ color.X = 0.4124*Rlinear + 0.3576*Glinear + 0.1805*Blinear;
+ color.Y = 0.2126*Rlinear + 0.7152*Glinear + 0.0722*Blinear;
+ color.Z = 0.0193*Rlinear + 0.1192*Glinear + 0.9505*Blinear;
+
+ color.alpha = ((double)pixel.a)/UINT16_MAX;
+ color.trans = ((double)pixel.t)/UINT16_MAX;
+
+ return color;
+}
+
+dmnsn_canvas *
+dmnsn_new_canvas(unsigned int x, unsigned int y)
+{
+ dmnsn_canvas *canvas = malloc(sizeof(dmnsn_canvas));
+
+ if (canvas) {
+ canvas->x = x;
+ canvas->y = y;
+ canvas->pixels = malloc(sizeof(dmnsn_pixel)*x*y);
+
+ if (canvas->pixels) {
+ return canvas;
+ } else {
+ free(canvas);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+void
+dmnsn_delete_canvas(dmnsn_canvas *canvas)
+{
+ if (canvas) {
+ free(canvas->pixels);
+ free(canvas);
+ }
+}
diff --git a/libdimension/dimension.h b/libdimension/dimension.h
new file mode 100644
index 0000000..558c9ed
--- /dev/null
+++ b/libdimension/dimension.h
@@ -0,0 +1,39 @@
+/*************************************************************************
+ * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of Dimension. *
+ * *
+ * Dimension 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. *
+ * *
+ * Dimension 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/>. *
+ *************************************************************************/
+
+#ifndef DIMENSION_H
+#define DIMENSION_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dimension/geometry.h>
+#include <dimension/color.h>
+#include <dimension/canvas.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DIMENSION_H */
diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h
new file mode 100644
index 0000000..251c64a
--- /dev/null
+++ b/libdimension/dimension/canvas.h
@@ -0,0 +1,50 @@
+/*************************************************************************
+ * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of Dimension. *
+ * *
+ * Dimension 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. *
+ * *
+ * Dimension 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/>. *
+ *************************************************************************/
+
+/*
+ * A canvas which is rendered to.
+ */
+
+#ifndef DIMENSION_CANVAS_H
+#define DIMENSION_CANVAS_H
+
+/* 48-bit sRGB color for pixels. */
+typedef struct {
+ uint16_t r, g, b;
+ uint16_t a, t;
+} dmnsn_pixel;
+
+dmnsn_pixel dmnsn_pixel_from_color(dmnsn_color color);
+dmnsn_color dmnsn_color_from_pixel(dmnsn_pixel pixel);
+
+typedef struct {
+ unsigned int x, y;
+
+ /*
+ * Stored in first-quadrant representation (origin is bottom-left). The pixel
+ * at (a,b) is accessible as pixels[b*x + a].
+ */
+ dmnsn_pixel *pixels;
+} dmnsn_canvas;
+
+dmnsn_canvas *dmnsn_new_canvas(unsigned int x, unsigned int y);
+void dmnsn_delete_canvas(dmnsn_canvas *canvas);
+
+#endif /* DIMENSION_CANVAS_H */
diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h
new file mode 100644
index 0000000..1f4a42e
--- /dev/null
+++ b/libdimension/dimension/color.h
@@ -0,0 +1,46 @@
+/*************************************************************************
+ * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of Dimension. *
+ * *
+ * Dimension 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. *
+ * *
+ * Dimension 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/>. *
+ *************************************************************************/
+
+/*
+ * Types to represent color.
+ */
+
+#ifndef DIMENSION_COLOR_H
+#define DIMENSION_COLOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CIE 1931 XYZ color. */
+typedef struct {
+ double X, Y, Z; /* X, Y, and Z are the tristimulus values of a color in CIE
+ 1931 XYZ color space. We use an unlimited light model
+ here, where the range of X, Y, and Z are unbounded >= 0. */
+ double alpha, trans; /* Alpha transparancy only lets light of this color
+ through; regular transparancy lets all colors
+ through */
+} dmnsn_color;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DIMENSION_COLOR_H */
diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h
new file mode 100644
index 0000000..2c0c204
--- /dev/null
+++ b/libdimension/dimension/geometry.h
@@ -0,0 +1,92 @@
+/*************************************************************************
+ * Copyright (C) 2008 Tavian Barnes <tavianator@gmail.com> *
+ * *
+ * This file is part of Dimension. *
+ * *
+ * Dimension 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. *
+ * *
+ * Dimension 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/>. *
+ *************************************************************************/
+
+/*
+ * Core geometric types like scalars, vectors, and rays.
+ */
+
+#ifndef DIMENSION_GEOMETRY_H
+#define DIMENSION_GEOMETRY_H
+
+/* Scalar and vector types. */
+typedef double dmnsn_scalar;
+typedef struct { dmnsn_scalar x, y, z; } dmnsn_vector;
+
+/* Vector arithmetic */
+
+inline dmnsn_vector
+dmnsn_vector_construct(dmnsn_scalar x, dmnsn_scalar y, dmnsn_scalar z)
+{
+ dmnsn_vector v = { .x = x, .y = y, .z = z };
+ return v;
+}
+
+inline dmnsn_vector
+dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs)
+{
+ return dmnsn_vector_construct(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
+}
+
+inline dmnsn_vector
+dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs)
+{
+ return dmnsn_vector_construct(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
+}
+
+inline dmnsn_vector
+dmnsn_vector_mul(dmnsn_scalar lhs, dmnsn_vector rhs)
+{
+ return dmnsn_vector_construct(lhs*rhs.x, lhs*rhs.y, lhs*rhs.z);
+}
+
+inline dmnsn_vector
+dmnsn_vector_div(dmnsn_vector lhs, dmnsn_scalar rhs)
+{
+ return dmnsn_vector_construct(lhs.x/rhs, lhs.y/rhs, lhs.z/rhs);
+}
+
+inline dmnsn_scalar
+dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs)
+{
+ return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
+}
+
+inline dmnsn_vector
+dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs)
+{
+ return dmnsn_vector_construct(lhs.y*rhs.z - lhs.z*rhs.y,
+ lhs.z*rhs.x - lhs.x*rhs.z,
+ lhs.x*rhs.y - lhs.y*rhs.x);
+}
+
+/* A line, or ray. */
+typedef struct {
+ dmnsn_vector x0; /* A point on the line */
+ dmnsn_vector n; /* A normal vector; the direction of the line */
+} dmnsn_line;
+
+/* A point on a line, defined by x0 + t*n */
+inline dmnsn_vector
+dmnsn_line_point(dmnsn_line l, dmnsn_scalar t)
+{
+ return dmnsn_vector_add(l.x0, dmnsn_vector_mul(t, l.n));
+}
+
+#endif /* DIMENSION_GEOMETRY_H */