4 * Created by Toshi Nagata on 06/03/11.
5 * Copyright 2006-2008 Toshi Nagata. All rights reserved.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation version 2 of the License.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
23 defaultPanic(const char *fmt, ...)
27 vfprintf(stderr, fmt, ap);
32 defaultWarning(const char *fmt, ...)
36 vfprintf(stderr, fmt, ap);
39 void (*gPanicFunc)(const char *, ...) = defaultPanic;
40 void (*gWarningFunc)(const char *, ...) = defaultWarning;
43 SetPanicFunc(void (*func)(const char *, ...))
46 gPanicFunc = defaultPanic;
47 else gPanicFunc = func;
51 SetWarningFunc(void (*func)(const char *, ...))
54 gWarningFunc = defaultWarning;
55 else gWarningFunc = func;
59 PanicByOutOfMemory(const char *msg)
61 Panic("Out of memory while %s", msg);
65 PanicByInternalError(const char *msg, const char *file, int line)
67 Panic("Internal Error in %s; File %s line %d", msg, file, line);
71 #pragma mark ==== Vector and Matrix ====
74 NormalizeVec(Vector *vdst, const Vector *vsrc)
77 dval = 1.0 / VecLength(*vsrc);
78 VecScale(*vdst, *vsrc, dval);
79 if (!isfinite(vdst->x) || !isfinite(vdst->y) || !isfinite(vdst->z)) {
86 MatrixRotation(Mat33 dst, const Vector *axis, Double angle)
88 /* Taken from "Matrix and Quaternion FAQ"
89 http://www.j3d.org/matrix_faq/matrfaq_latest.html */
90 double rcos = cos((double)angle);
91 double rsin = sin((double)angle);
92 dst[0] = rcos + axis->x*axis->x*(1-rcos);
93 dst[1] = -axis->z * rsin + axis->x*axis->y*(1-rcos);
94 dst[2] = axis->y * rsin + axis->x*axis->z*(1-rcos);
95 dst[3] = axis->z * rsin + axis->y*axis->x*(1-rcos);
96 dst[4] = rcos + axis->y*axis->y*(1-rcos);
97 dst[5] = -axis->x * rsin + axis->y*axis->z*(1-rcos);
98 dst[6] = -axis->y * rsin + axis->z*axis->x*(1-rcos);
99 dst[7] = axis->x * rsin + axis->z*axis->y*(1-rcos);
100 dst[8] = rcos + axis->z*axis->z*(1-rcos);
104 MatrixVec(Vector *dst, const Mat33 mat, const Vector *src)
107 temp.x = mat[0] * src->x + mat[3] * src->y + mat[6] * src->z;
108 temp.y = mat[1] * src->x + mat[4] * src->y + mat[7] * src->z;
109 temp.z = mat[2] * src->x + mat[5] * src->y + mat[8] * src->z;
114 MatrixMul(Mat33 dst, const Mat33 src1, const Mat33 src2)
117 temp[0] = src1[0] * src2[0] + src1[3] * src2[1] + src1[6] * src2[2];
118 temp[1] = src1[1] * src2[0] + src1[4] * src2[1] + src1[7] * src2[2];
119 temp[2] = src1[2] * src2[0] + src1[5] * src2[1] + src1[8] * src2[2];
120 temp[3] = src1[0] * src2[3] + src1[3] * src2[4] + src1[6] * src2[5];
121 temp[4] = src1[1] * src2[3] + src1[4] * src2[4] + src1[7] * src2[5];
122 temp[5] = src1[2] * src2[3] + src1[5] * src2[4] + src1[8] * src2[5];
123 temp[6] = src1[0] * src2[6] + src1[3] * src2[7] + src1[6] * src2[8];
124 temp[7] = src1[1] * src2[6] + src1[4] * src2[7] + src1[7] * src2[8];
125 temp[8] = src1[2] * src2[6] + src1[5] * src2[7] + src1[8] * src2[8];
126 memmove(dst, temp, sizeof(Mat33));
130 MatrixTranspose(Mat33 dst, const Mat33 src)
136 w = src[3]; dst[3] = src[1]; dst[1] = w;
137 w = src[6]; dst[6] = src[2]; dst[2] = w;
138 w = src[7]; dst[7] = src[5]; dst[5] = w;
142 MatrixDeterminant(const Mat33 src)
144 return src[0] * src[4] * src[8] + src[1] * src[5] * src[6] + src[2] * src[3] * src[7]
145 - src[0] * src[5] * src[7] - src[1] * src[3] * src[8] - src[2] * src[4] * src[6];
149 MatrixInvert(Mat33 dst, const Mat33 src)
152 Double d = MatrixDeterminant(src);
156 temp[0] = d * ( src[4] * src[8] - src[5] * src[7]);
157 temp[1] = d * (-src[1] * src[8] + src[2] * src[7]);
158 temp[2] = d * ( src[1] * src[5] - src[2] * src[4]);
159 temp[3] = d * (-src[3] * src[8] + src[5] * src[6]);
160 temp[4] = d * ( src[0] * src[8] - src[2] * src[6]);
161 temp[5] = d * (-src[0] * src[5] + src[2] * src[3]);
162 temp[6] = d * ( src[3] * src[7] - src[4] * src[6]);
163 temp[7] = d * (-src[0] * src[7] + src[1] * src[6]);
164 temp[8] = d * ( src[0] * src[4] - src[1] * src[3]);
165 memmove(dst, temp, sizeof(Mat33));
170 MatrixScale(Mat33 dst, const Mat33 src, Double factor)
172 dst[0] = src[0] * factor;
173 dst[1] = src[1] * factor;
174 dst[2] = src[2] * factor;
175 dst[3] = src[3] * factor;
176 dst[4] = src[4] * factor;
177 dst[5] = src[5] * factor;
178 dst[6] = src[6] * factor;
179 dst[7] = src[7] * factor;
180 dst[8] = src[8] * factor;
183 /* Get the matrix to rotate (1,0,0)->v1, (0,1,0)->v2, (0,0,1)->v3 */
185 MatrixGeneralRotation(Mat33 dst, const Vector *v1, const Vector *v2, const Vector *v3)
187 dst[0] = v1->x; dst[3] = v2->x; dst[6] = v3->x;
188 dst[1] = v1->y; dst[4] = v2->y; dst[7] = v3->y;
189 dst[2] = v1->z; dst[5] = v2->z; dst[8] = v3->z;
193 /* Get the eigenvalue/eigenvector for a real symmetric matrix (3x3) */
194 #if !defined(__WXMAC__) && !defined(__CMDMAC__)
195 typedef integer __CLPK_integer;
196 typedef logical __CLPK_logical;
197 typedef real __CLPK_real;
198 typedef doublereal __CLPK_doublereal;
202 MatrixSymDiagonalize(Mat33 mat, Double *out_values, Vector *out_vectors)
204 __CLPK_integer n, lda, lwork, info;
205 __CLPK_doublereal a[9], w[3], work[9];
207 for (i = 0; i < 3; i++) {
208 for (j = 0; j < 3; j++) {
209 a[i * 3 + j] = mat[i * 3 + j];
214 /* For the meanings of the arguments, consult the LAPACK source;
215 http://www.netlib.org/lapack/double/dsyev.f */
216 dsyev_("V", "U", &n, a, &lda, w, work, &lwork, &info);
218 for (i = 0; i < 3; i++) {
219 out_values[i] = w[i];
220 out_vectors[i].x = a[i * 3];
221 out_vectors[i].y = a[i * 3 + 1];
222 out_vectors[i].z = a[i * 3 + 2];
229 TransformVec(Vector *dst, const Transform tf, const Vector *src)
232 temp.x = tf[0] * src->x + tf[3] * src->y + tf[6] * src->z + tf[9];
233 temp.y = tf[1] * src->x + tf[4] * src->y + tf[7] * src->z + tf[10];
234 temp.z = tf[2] * src->x + tf[5] * src->y + tf[8] * src->z + tf[11];
239 TransformMul(Transform dst, const Transform src1, const Transform src2)
242 temp[0] = src1[0] * src2[0] + src1[3] * src2[1] + src1[6] * src2[2];
243 temp[1] = src1[1] * src2[0] + src1[4] * src2[1] + src1[7] * src2[2];
244 temp[2] = src1[2] * src2[0] + src1[5] * src2[1] + src1[8] * src2[2];
245 temp[3] = src1[0] * src2[3] + src1[3] * src2[4] + src1[6] * src2[5];
246 temp[4] = src1[1] * src2[3] + src1[4] * src2[4] + src1[7] * src2[5];
247 temp[5] = src1[2] * src2[3] + src1[5] * src2[4] + src1[8] * src2[5];
248 temp[6] = src1[0] * src2[6] + src1[3] * src2[7] + src1[6] * src2[8];
249 temp[7] = src1[1] * src2[6] + src1[4] * src2[7] + src1[7] * src2[8];
250 temp[8] = src1[2] * src2[6] + src1[5] * src2[7] + src1[8] * src2[8];
251 temp[9] = src1[0] * src2[9] + src1[3] * src2[10] + src1[6] * src2[11] + src1[9];
252 temp[10] = src1[1] * src2[9] + src1[4] * src2[10] + src1[7] * src2[11] + src1[10];
253 temp[11] = src1[2] * src2[9] + src1[5] * src2[10] + src1[8] * src2[11] + src1[11];
254 memmove(dst, temp, sizeof(Transform));
258 TransformDeterminant(const Transform src)
260 return MatrixDeterminant(src);
264 TransformTranspose(Transform dst, const Transform src)
270 w = src[3]; dst[3] = src[1]; dst[1] = w;
271 w = src[6]; dst[6] = src[2]; dst[2] = w;
272 w = src[7]; dst[7] = src[5]; dst[5] = w;
279 TransformInvert(Transform dst, const Transform src)
282 int n = MatrixInvert(temp, src);
284 temp[9] = -temp[0] * src[9] - temp[3] * src[10] - temp[6] * src[11];
285 temp[10] = -temp[1] * src[9] - temp[4] * src[10] - temp[7] * src[11];
286 temp[11] = -temp[2] * src[9] - temp[5] * src[10] - temp[8] * src[11];
287 memmove(dst, temp, sizeof(Transform));
293 TransformForInversion(Transform dst, const Vector *center)
295 dst[0] = dst[4] = dst[8] = -1.0;
296 dst[1] = dst[2] = dst[3] = dst[5] = dst[6] = dst[7] = 0.0;
297 dst[9] = center->x * 2.0;
298 dst[10] = center->y * 2.0;
299 dst[11] = center->z * 2.0;
303 TransformForReflection(Transform dst, const Vector *axis, const Vector *center)
307 if ((w = VecLength2(av)) < 1e-15)
311 /* r' = r - 2 * VecDot(r-c, a) * a; a should be a unit vector */
312 /* (x',y',z') = (x,y,z) - 2*((x-cx)*ax + (y-cy)*ay + (z-cz)*az)*(ax,ay,az) */
313 /* = (1-2*ax*ax, -2*ax*ay, -2*ax*az)x + (-2*ax*ay, 1-2*ay*ay, -2*ay*az)y
314 + (-2*ax*az, -2*ay*az, 1-2*az*az)z + (ax*C, ay*C, az*C); C = 2*(ax*cx+ay*cy+az*cz) */
315 dst[0] = 1.0 - 2.0 * av.x * av.x;
316 dst[1] = dst[3] = -2.0 * av.x * av.y;
317 dst[2] = dst[6] = -2.0 * av.x * av.z;
318 dst[4] = 1.0 - 2.0 * av.y * av.y;
319 dst[5] = dst[7] = -2.0 * av.y * av.z;
320 dst[8] = 1.0 - 2.0 * av.z * av.z;
321 w = 2.0 * VecDot(av, *center);
329 TransformForRotation(Transform dst, const Vector *axis, Double angle, const Vector *center)
334 if ((w = VecLength2(av)) < 1e-15)
338 memset(tf, 0, sizeof(tf));
339 memset(temp1, 0, sizeof(tf));
340 tf[0] = tf[4] = tf[8] = 1.0;
341 tf[1] = tf[2] = tf[3] = tf[5] = tf[6] = tf[7] = 0.0;
345 MatrixRotation((Double *)temp1, &av, angle);
346 temp1[9] = center->x;
347 temp1[10] = center->y;
348 temp1[11] = center->z;
349 TransformMul(dst, temp1, tf);
353 #pragma mark ==== Array ====
355 /* Assign a value to an array. An array is represented by two fields; count and base,
356 * where base is a pointer to an array and count is the number of items.
357 * The memory block of the array is allocated by 8*item_size. If the index exceeds
358 * that limit, then a new memory block is allocated. */
360 AssignArray(void *base, Int *count, int item_size, int idx, const void *value)
362 void **bp = (void **)base;
363 if (*count == 0 || idx / 8 > (*count - 1) / 8) {
364 int new_size = (idx / 8 + 1) * 8;
366 *bp = calloc(item_size, new_size);
368 *bp = realloc(*bp, new_size * item_size);
371 memset((char *)*bp + *count * item_size, 0, (new_size - *count) * item_size);
376 memcpy((char *)*bp + idx * item_size, value, item_size);
377 return (char *)*bp + idx * item_size;
380 /* Allocate a new array. This works consistently with AssignArray().
381 * Don't mix calloc()/malloc() with AssignArray(); that causes disasters!
382 * (free() is OK though). */
384 NewArray(void *base, Int *count, int item_size, int nitems)
386 void **bp = (void *)base;
389 return AssignArray(base, count, item_size, nitems - 1, NULL);
392 /* Insert items to an array. */
394 InsertArray(void *base, Int *count, int item_size, int idx, int nitems, const void *value)
396 void **bp = (void *)base;
401 /* Allocate storage */
402 p = AssignArray(base, count, item_size, *count + nitems - 1, NULL);
405 /* Move items if necessary */
407 memmove((char *)*bp + (idx + nitems) * item_size, (char *)*bp + idx * item_size, (ocount - idx) * item_size);
410 memmove((char *)*bp + idx * item_size, value, nitems * item_size);
412 memset((char *)*bp + idx * item_size, 0, nitems * item_size);
413 return (char *)*bp + idx * item_size;
417 DeleteArray(void *base, Int *count, int item_size, int idx, int nitems, void *outValue)
419 void **bp = (void *)base;
420 if (nitems <= 0 || idx < 0 || idx >= *count)
422 if (nitems > *count - idx)
423 nitems = *count - idx;
425 if (outValue != NULL)
426 memmove(outValue, (char *)*bp + idx * item_size, nitems * item_size);
428 if (idx + nitems < *count)
429 memmove((char *)*bp + idx * item_size, (char *)*bp + (idx + nitems) * item_size, (*count - idx - nitems) * item_size);
439 ReadLine(char *buf, int size, FILE *stream, int *lineNumber)
444 while (i < size - 1) {
451 else if (c == '\r') {
460 if (c != '\n' && c != EOF) {
461 /* Skip until the end of line */
462 while (c != '\n' && c != '\r' && c != EOF)
470 if (lineNumber != NULL)
476 ReadFormat(const char *str, const char *fmt,...)
480 int c, n, count, len;
487 while (*fmt != 0 && *str != 0) {
494 n = strtol(fmt, (char **)&fmt, 0);
502 strncpy(buf, str, n);
508 ip = va_arg(ap, Int *);
513 fp = va_arg(ap, Double *);
518 sp = va_arg(ap, char *);
519 sscanf(buf, " %s", sp);