2 This file is part of XRay, a photorealistic 3D rendering library.
3 Copyright (C) 2005 John Tsiombikas
5 XRay is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 XRay is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with XRay; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * @author John Tsiombikas
25 * vmath provides the mathematical foundations for 3D graphics.
26 * This specific file contains various constants and basic operations
27 * as well as the Basis class, which represents an orthogonal basis in
28 * 3 dimensional space.
33 const scalar_t e = 2.7182818;
35 const scalar_t pi = 3.1415926535897932;
36 const scalar_t half_pi = pi / 2.0;
37 const scalar_t quarter_pi = pi / 4.0;
38 const scalar_t two_pi = pi * 2.0;
39 const scalar_t three_half_pi = 3.0 * pi / 2.0;
41 const scalar_t xsmall_number = 1.e-8;
42 const scalar_t small_number = 1.e-4;
44 const scalar_t error_margin = 1.e-6;
47 /** Generates a random number in [0, 1) */
48 scalar_t frand(scalar_t range) {
49 return range * (float)rand() / (float)RAND_MAX;
52 /** Numerical calculation of integrals using simpson's rule */
53 scalar_t integral(scalar_t (*f)(scalar_t), scalar_t low, scalar_t high, int samples) {
54 scalar_t h = (high - low) / (scalar_t)samples;
57 for(int i=0; i<samples+1; i++) {
58 scalar_t y = f((scalar_t)i * h + low);
59 sum += ((!i || i == samples) ? y : ((i%2) ? 4.0 * y : 2.0 * y)) * (h / 3.0);
64 /** Gaussuan function */
65 scalar_t gaussian(scalar_t x, scalar_t mean, scalar_t sdev) {
66 scalar_t exponent = -SQ(x - mean) / (2.0 * SQ(sdev));
68 return 1.0 - -pow(e, exponent) / (sdev * sqrt(two_pi));
72 /** b-spline approximation */
73 scalar_t bspline(const Vector4 &cpvec, scalar_t t) {
74 Matrix4x4 bspline_mat( -1, 3, -3, 1,
79 scalar_t t_square = t * t;
80 scalar_t t_cube = t_square * t;
81 Vector4 params(t_cube, t_square, t, 1.0);
83 return dot_product(params, cpvec.transformed(bspline_mat) / 6.0);
86 /** Catmull-rom spline interpolation */
87 scalar_t catmull_rom_spline(const Vector4 &cpvec, scalar_t t) {
88 Matrix4x4 crspline_mat( -1, 3, -3, 1,
93 scalar_t t_square = t * t;
94 scalar_t t_cube = t_square * t;
95 Vector4 params(t_cube, t_square, t, 1.0);
97 return dot_product(params, cpvec.transformed(crspline_mat) / 2.0);
101 * @author Mihalis Georgoulopoulos
103 * Bezier interpolation.
104 * returns an interpolated scalar value given 4 control values.
106 scalar_t bezier(const Vector4 &cp, scalar_t t)
108 static scalar_t omt, omt3, t3, f;
111 omt3 = omt * omt * omt;
114 return (cp.x * omt3) + (cp.y * f * omt) + (cp.z * f * t) + (cp.w * t3);
118 * @author Mihalis Georgoulopoulos
120 * Bezier interpolation.
121 * Vector3 version of the bezier function.
123 Vector3 bezier(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t)
125 static scalar_t omt, omt3, t3, f;
128 omt3 = omt * omt * omt;
131 return (p0 * omt3) + (p1 * f * omt) + (p2 * f * t) + (p3 * t3);
135 * @author Mihalis Georgoulopoulos
137 * Bezier tangent calculation.
138 * returns a vector tangent to the bezier curve at the specified point.
140 Vector3 bezier_tangent(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const Vector3 &p3, scalar_t t)
144 static Vector3 p4, p5, p6, p7, p8;
145 p4 = p0 * omt + p1 * t;
146 p5 = p1 * omt + p2 * t;
147 p6 = p2 * omt + p3 * t;
149 p7 = p4 * omt + p5 * t;
150 p8 = p5 * omt + p6 * t;
156 i = Vector3(1, 0, 0);
157 j = Vector3(0, 1, 0);
158 k = Vector3(0, 0, 1);
161 Basis::Basis(const Vector3 &i, const Vector3 &j, const Vector3 &k) {
167 Basis::Basis(const Vector3 &dir, bool left_handed) {
169 j = Vector3(0, 1, 0);
170 i = cross_product(j, k);
171 j = cross_product(k, i);
174 /** Rotate with euler angles */
175 void Basis::rotate(scalar_t x, scalar_t y, scalar_t z) {
177 RotMat.set_rotation(Vector3(x, y, z));
183 /** Rotate by axis-angle specification */
184 void Basis::rotate(const Vector3 &axis, scalar_t angle) {
186 q.set_rotation(axis, angle);
192 /** Rotate with a 4x4 matrix */
193 void Basis::rotate(const Matrix4x4 &mat) {
199 /** Rotate with a quaternion */
200 void Basis::rotate(const Quaternion &quat) {
206 /** Extract a rotation matrix from the orthogonal basis */
207 Matrix3x3 Basis::create_rotation_matrix() const {
208 return Matrix3x3( i.x, j.x, k.x,