Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2007-11-07 01:29:20 +0300
committerMartin Poirier <theeth@yahoo.com>2007-11-07 01:29:20 +0300
commit0de103c1cdf1e4c40cfad4e233a42a6d1165953d (patch)
treea57039fa592cf0f5af3738a9624d0b0ccbf20ec0 /source/blender/blenlib
Filling in branch from trunk
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_arithb.h385
-rw-r--r--source/blender/blenlib/BLI_blenlib.h406
-rw-r--r--source/blender/blenlib/BLI_boxpack2d.h69
-rw-r--r--source/blender/blenlib/BLI_dynamiclist.h58
-rw-r--r--source/blender/blenlib/BLI_dynstr.h90
-rw-r--r--source/blender/blenlib/BLI_edgehash.h99
-rw-r--r--source/blender/blenlib/BLI_editVert.h190
-rw-r--r--source/blender/blenlib/BLI_ghash.h118
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h96
-rw-r--r--source/blender/blenlib/BLI_heap.h74
-rw-r--r--source/blender/blenlib/BLI_jitter.h40
-rw-r--r--source/blender/blenlib/BLI_linklist.h62
-rw-r--r--source/blender/blenlib/BLI_memarena.h61
-rw-r--r--source/blender/blenlib/BLI_rand.h99
-rw-r--r--source/blender/blenlib/BLI_storage_types.h83
-rw-r--r--source/blender/blenlib/BLI_threads.h54
-rw-r--r--source/blender/blenlib/BLI_vfontdata.h103
-rw-r--r--source/blender/blenlib/BLI_winstuff.h119
-rw-r--r--source/blender/blenlib/CMakeLists.txt56
-rw-r--r--source/blender/blenlib/MTC_matrixops.h165
-rw-r--r--source/blender/blenlib/MTC_vectorops.h61
-rw-r--r--source/blender/blenlib/Makefile37
-rw-r--r--source/blender/blenlib/PIL_dynlib.h55
-rw-r--r--source/blender/blenlib/PIL_time.h62
-rw-r--r--source/blender/blenlib/SConscript26
-rw-r--r--source/blender/blenlib/intern/BLI_callbacks.h44
-rw-r--r--source/blender/blenlib/intern/BLI_dynstr.c118
-rw-r--r--source/blender/blenlib/intern/BLI_fileops.h50
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c295
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c220
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c119
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c96
-rw-r--r--source/blender/blenlib/intern/BLI_scanfill.h41
-rw-r--r--source/blender/blenlib/intern/BLI_storage.h41
-rw-r--r--source/blender/blenlib/intern/BLI_util.h45
-rw-r--r--source/blender/blenlib/intern/Makefile61
-rw-r--r--source/blender/blenlib/intern/arithb.c3672
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c416
-rw-r--r--source/blender/blenlib/intern/dynlib.c343
-rw-r--r--source/blender/blenlib/intern/edgehash.c220
-rw-r--r--source/blender/blenlib/intern/fileops.c364
-rw-r--r--source/blender/blenlib/intern/freetypefont.c634
-rw-r--r--source/blender/blenlib/intern/gsqueue.c122
-rw-r--r--source/blender/blenlib/intern/jitter.c178
-rw-r--r--source/blender/blenlib/intern/matrixops.c441
-rw-r--r--source/blender/blenlib/intern/noise.c1392
-rw-r--r--source/blender/blenlib/intern/psfont.c2126
-rw-r--r--source/blender/blenlib/intern/rand.c192
-rw-r--r--source/blender/blenlib/intern/rct.c171
-rw-r--r--source/blender/blenlib/intern/scanfill.c1056
-rw-r--r--source/blender/blenlib/intern/storage.c540
-rw-r--r--source/blender/blenlib/intern/threads.c221
-rw-r--r--source/blender/blenlib/intern/time.c105
-rw-r--r--source/blender/blenlib/intern/util.c1691
-rw-r--r--source/blender/blenlib/intern/vectorops.c169
-rw-r--r--source/blender/blenlib/intern/winstuff.c209
56 files changed, 18060 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
new file mode 100644
index 00000000000..d5e7447ff66
--- /dev/null
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -0,0 +1,385 @@
+#undef TEST_ACTIVE
+//#define ACTIVE 1
+/**
+ * blenlib/BLI_arithb.h mar 2001 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * */
+
+#ifndef BLI_ARITHB_H
+#define BLI_ARITHB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.70710678118654752440
+#endif
+
+#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0},\
+ { 0.0, 1.0, 0.0, 0.0},\
+ { 0.0, 0.0, 1.0, 0.0},\
+ { 0.0, 0.0, 0.0, 1.0}}
+
+#define MAT3_UNITY {{ 1.0, 0.0, 0.0},\
+ { 0.0, 1.0, 0.0},\
+ { 0.0, 0.0, 1.0}}
+
+
+void CalcCent3f(float *cent, float *v1, float *v2, float *v3);
+void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4);
+
+void Crossf(float *c, float *a, float *b);
+void Projf(float *c, float *v1, float *v2);
+
+float Inpf(float *v1, float *v2);
+float Inp2f(float *v1, float *v2);
+
+float Normalize(float *n);
+float Normalize2(float *n);
+
+float Sqrt3f(float f);
+double Sqrt3d(double d);
+
+float saacos(float fac);
+float saasin(float fac);
+float sasqrt(float fac);
+
+int FloatCompare(float *v1, float *v2, float limit);
+float FloatLerpf(float target, float origin, float fac);
+
+float CalcNormFloat(float *v1, float *v2, float *v3, float *n);
+float CalcNormFloat4(float *v1, float *v2, float *v3, float *v4, float *n);
+
+void CalcNormLong(int *v1, int *v2, int *v3, float *n);
+/* CalcNormShort: is ook uitprodukt - (translates as 'is also out/cross product') */
+void CalcNormShort(short *v1, short *v2, short *v3, float *n);
+
+
+/**
+ * @section Euler conversion routines
+ */
+
+void EulToMat3(float *eul, float mat[][3]);
+void EulToMat4(float *eul, float mat[][4]);
+
+void Mat3ToEul(float tmat[][3], float *eul);
+void Mat4ToEul(float tmat[][4],float *eul);
+
+void EulToQuat(float *eul, float *quat);
+
+void compatible_eul(float *eul, float *oldrot);
+
+void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot);
+
+
+/**
+ * @section Quaternion arithmetic routines
+ */
+
+void QuatToEul(float *quat, float *eul);
+void QuatOne(float *);
+void QuatMul(float *, float *, float *);
+void QuatMulVecf(float *q, float *v);
+
+void NormalQuat(float *);
+void VecRotToQuat(float *vec, float phi, float *quat);
+
+void QuatSub(float *q, float *q1, float *q2);
+void QuatConj(float *q);
+void QuatInv(float *q);
+void QuatMulf(float *q, float f);
+float QuatDot(float *q1, float *q2);
+void QuatCopy(float *q1, float *q2);
+
+void printquat(char *str, float q[4]);
+
+void QuatInterpol(float *result, float *quat1, float *quat2, float t);
+void QuatAdd(float *result, float *quat1, float *quat2, float t);
+
+
+/**
+ * @section matrix multiplication and copying routines
+ */
+
+void Mat3MulFloat(float *m, float f);
+void Mat4MulFloat(float *m, float f);
+void Mat4MulFloat3(float *m, float f);
+
+void Mat3Transp(float mat[][3]);
+void Mat4Transp(float mat[][4]);
+
+int Mat4Invert(float inverse[][4], float mat[][4]);
+void Mat4InvertSimp(float inverse[][4], float mat[][4]);
+void Mat4Inv(float *m1, float *m2);
+void Mat4InvGG(float out[][4], float in[][4]);
+void Mat3Inv(float m1[][3], float m2[][3]);
+
+void Mat3CpyMat4(float m1[][3],float m2[][4]);
+void Mat4CpyMat3(float m1[][4], float m2[][3]);
+
+void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight);
+
+float Det2x2(float a,float b,float c, float d);
+
+float Det3x3(
+ float a1, float a2, float a3,
+ float b1, float b2, float b3,
+ float c1, float c2, float c3
+);
+
+float Det4x4(float m[][4]);
+
+void Mat3Adj(float m1[][3], float m[][3]);
+void Mat4Adj(float out[][4], float in[][4]);
+
+void Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4]);
+void subMat4MulMat4(float *m1, float *m2, float *m3);
+#ifndef TEST_ACTIVE
+void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]);
+#else
+void Mat3MulMat3(float *m1, float *m3, float *m2);
+#endif
+void Mat4MulMat34(float (*m1)[4], float (*m3)[3], float (*m2)[4]);
+void Mat4CpyMat4(float m1[][4], float m2[][4]);
+void Mat4SwapMat4(float *m1, float *m2);
+void Mat3CpyMat3(float m1[][3], float m2[][3]);
+
+void Mat3MulSerie(float answ[][3],
+ float m1[][3], float m2[][3], float m3[][3],
+ float m4[][3], float m5[][3], float m6[][3],
+ float m7[][3], float m8[][3]
+);
+
+void Mat4MulSerie(float answ[][4], float m1[][4],
+ float m2[][4], float m3[][4], float m4[][4],
+ float m5[][4], float m6[][4], float m7[][4],
+ float m8[][4]
+);
+
+void Mat4Clr(float *m);
+void Mat3Clr(float *m);
+
+void Mat3One(float m[][3]);
+void Mat4One(float m[][4]);
+
+void Mat3Ortho(float mat[][3]);
+void Mat4Ortho(float mat[][4]);
+
+void VecMat4MulVecfl(float *in, float mat[][4], float *vec);
+void Mat4MulMat43(float (*m1)[4], float (*m3)[4], float (*m2)[3]);
+void Mat3IsMat3MulMat4(float m1[][3], float m2[][3], float m3[][4]);
+
+void Mat4MulVec(float mat[][4],int *vec);
+void Mat4MulVecfl(float mat[][4], float *vec);
+void Mat4Mul3Vecfl(float mat[][4], float *vec);
+void Mat4MulVec3Project(float mat[][4],float *vec);
+void Mat4MulVec4fl(float mat[][4], float *vec);
+void Mat3MulVec(float mat[][3],int *vec);
+void Mat3MulVecfl(float mat[][3], float *vec);
+void Mat3MulVecd(float mat[][3], double *vec);
+void Mat3TransMulVecfl(float mat[][3], float *vec);
+
+void Mat3AddMat3(float m1[][3], float m2[][3], float m3[][3]);
+void Mat4AddMat4(float m1[][4], float m2[][4], float m3[][4]);
+
+void VecUpMat3old(float *vec, float mat[][3], short axis);
+void VecUpMat3(float *vec, float mat[][3], short axis);
+void VecRotToMat3(float *vec, float phi, float mat[][3]);
+void VecRotToMat4(float *vec, float phi, float mat[][4]);
+
+void VecCopyf(float *v1, float *v2);
+int VecLen(int *v1, int *v2);
+float VecLenf(float *v1, float *v2);
+float VecLength(float *v);
+void VecMulf(float *v1, float f);
+
+int VecLenCompare(float *v1, float *v2, float limit);
+int VecCompare(float *v1, float *v2, float limit);
+int VecEqual(float *v1, float *v2);
+
+void printvecf(char *str,float v[3]);
+void printvec4f(char *str, float v[4]);
+
+void VecAddf(float *v, float *v1, float *v2);
+void VecSubf(float *v, float *v1, float *v2);
+void VecLerpf(float *target, float *a, float *b, float t);
+void VecMidf(float *v, float *v1, float *v2);
+
+void VecOrthoBasisf(float *v, float *v1, float *v2);
+
+float Vec2Lenf(float *v1, float *v2);
+void Vec2Mulf(float *v1, float f);
+void Vec2Addf(float *v, float *v1, float *v2);
+void Vec2Subf(float *v, float *v1, float *v2);
+void Vec2Copyf(float *v1, float *v2);
+
+float *vectoquat(float *vec, short axis, short upflag);
+
+float VecAngle2(float *v1, float *v2);
+float VecAngle3(float *v1, float *v2, float *v3);
+float NormalizedVecAngle2(float *v1, float *v2);
+
+void euler_rot(float *beul, float ang, char axis);
+
+
+float DistVL2Dfl(float *v1, float *v2, float *v3);
+float PdistVL2Dfl(float *v1, float *v2, float *v3);
+float PdistVL3Dfl(float *v1, float *v2, float *v3);
+void PclosestVL3Dfl(float *closest, float *v1, float *v2, float *v3);
+float AreaF2Dfl(float *v1, float *v2, float *v3);
+float AreaQ3Dfl(float *v1, float *v2, float *v3, float *v4);
+float AreaT3Dfl(float *v1, float *v2, float *v3);
+float AreaPoly3Dfl(int nr, float *verts, float *normal);
+
+/* intersect Line-Line
+ return:
+ -1: colliniar
+ 0: no intersection of segments
+ 1: exact intersection of segments
+ 2: cross-intersection of segments
+*/
+extern short IsectLL2Df(float *v1, float *v2, float *v3, float *v4);
+extern short IsectLL2Ds(short *v1, short *v2, short *v3, short *v4);
+
+/* interpolation weights of point in a triangle or quad, v4 may be NULL */
+void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, float *w);
+/* interpolation weights of point in a polygon with >= 3 vertices */
+void MeanValueWeights(float v[][3], int n, float *co, float *w);
+
+void i_lookat(
+ float vx, float vy,
+ float vz, float px,
+ float py, float pz,
+ float twist, float mat[][4]
+);
+
+void i_window(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float mat[][4]
+);
+
+void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
+void hex_to_rgb(char *hexcol, float *r, float *g, float *b);
+void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv);
+void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb);
+void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb);
+void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr);
+void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv);
+unsigned int hsv_to_cpack(float h, float s, float v);
+unsigned int rgb_to_cpack(float r, float g, float b);
+void cpack_to_rgb(unsigned int col, float *r, float *g, float *b);
+void MinMaxRGB(short c[]);
+
+
+
+void VecStar(float mat[][3],float *vec);
+
+short EenheidsMat(float mat[][3]);
+
+void QuatToMat3(float *q, float m[][3]);
+void QuatToMat4(float *q, float m[][4]);
+
+void Mat3ToQuat_is_ok(float wmat[][3], float *q);
+
+void i_ortho(float left, float right, float bottom, float top, float nearClip, float farClip, float matrix[][4]);
+void i_polarview(float dist, float azimuth, float incidence, float twist, float Vm[][4]);
+void i_translate(float Tx, float Ty, float Tz, float mat[][4]);
+void i_multmatrix(float icand[][4], float Vm[][4]);
+void i_rotate(float angle, char axis, float mat[][4]);
+
+
+
+
+
+void MinMax3(float *min, float *max, float *vec);
+void SizeToMat3(float *size, float mat[][3]);
+void SizeToMat4(float *size, float mat[][4]);
+
+float Mat3ToScalef(float mat[][3]);
+float Mat4ToScalef(float mat[][4]);
+
+void printmatrix3(char *str, float m[][3]);
+void printmatrix4(char *str, float m[][4]);
+
+/* uit Sig.Proc.85 pag 253 */
+void Mat3ToQuat(float wmat[][3], float *q);
+void Mat4ToQuat(float m[][4], float *q);
+
+void Mat3ToSize(float mat[][3], float *size);
+void Mat4ToSize(float mat[][4], float *size);
+
+void triatoquat(float *v1, float *v2, float *v3, float *quat);
+
+void LocEulSizeToMat4(float mat[][4], float loc[3], float eul[3], float size[3]);
+void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3]);
+
+void tubemap(float x, float y, float z, float *u, float *v);
+void spheremap(float x, float y, float z, float *u, float *v);
+
+int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda);
+int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3]);
+
+float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3]);
+
+typedef struct DualQuat {
+ float quat[4];
+ float trans[4];
+
+ float scale[4][4];
+ float scale_weight;
+} DualQuat;
+
+void Mat4ToDQuat(float basemat[][4], float mat[][4], DualQuat *dq);
+void DQuatToMat4(DualQuat *dq, float mat[][4]);
+void DQuatAddWeighted(DualQuat *dqsum, DualQuat *dq, float weight);
+void DQuatNormalize(DualQuat *dq, float totweight, float factor);
+void DQuatMulVecfl(DualQuat *dq, float *co, float mat[][3]);
+void DQuatCpyDQuat(DualQuat *dq1, DualQuat *dq2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h
new file mode 100644
index 00000000000..57248fb1d68
--- /dev/null
+++ b/source/blender/blenlib/BLI_blenlib.h
@@ -0,0 +1,406 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * @mainpage BLI - Blender LIbrary external interface
+ *
+ * @section about About the BLI module
+ *
+ * This is the external interface of the Blender Library. If you find
+ * a call to a BLI function that is not prototyped here, please add a
+ * prototype here. The library offers mathematical operations (mainly
+ * vector and matrix calculus), an abstraction layer for file i/o,
+ * functions for calculating Perlin noise, scanfilling services for
+ * triangles, and a system for guarded memory
+ * allocation/deallocation. There is also a patch to make MS Windows
+ * behave more or less Posix-compliant.
+ *
+ * @section issues Known issues with BLI
+ *
+ * - blenlib is written in C.
+ * - The posix-compliancy may move to a separate lib that deals with
+ * platform dependencies. (There are other platform-dependent
+ * fixes as well.)
+ * - The file i/o has some redundant code. It should be cleaned.
+ * - arithb.c is a very messy matrix library. We need a better
+ * solution.
+ * - vectorops.c is close to superfluous. It may disappear in the
+ * near future.
+ *
+ * @section dependencies Dependencies
+ *
+ * - The blenlib uses type defines from makesdna/, and functions from
+ * standard libraries.
+ *
+ * $Id$
+*/
+
+#ifndef BLI_BLENLIB_H
+#define BLI_BLENLIB_H
+
+/* braindamage for the masses... needed
+ because fillfacebase and fillvertbase are used outside */
+#include "DNA_listBase.h"
+
+#include <stdlib.h>
+
+extern ListBase fillfacebase;
+extern ListBase fillvertbase;
+/**
+ * @attention Defined in scanfill.c
+ */
+extern ListBase filledgebase;
+extern int totblock;
+
+struct chardesc;
+struct direntry;
+struct rctf;
+struct rcti;
+struct EditVert;
+struct PackedFile;
+struct LinkNode;
+struct DynamicList;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BLI_util.h */
+char *BLI_gethome(void);
+void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
+void BLI_make_exist(char *dir);
+void BLI_make_existing_file(char *name);
+void BLI_split_dirfile(const char *string, char *dir, char *file);
+void BLI_join_dirfile(char *string, const char *dir, const char *file);
+int BLI_testextensie(const char *str, const char *ext);
+void addlisttolist(ListBase *list1, ListBase *list2);
+void BLI_insertlink(struct ListBase *listbase, void *vprevlink, void *vnewlink);
+void *BLI_findlink(struct ListBase *listbase, int number);
+int BLI_findindex(struct ListBase *listbase, void *vlink);
+void BLI_freelistN(struct ListBase *listbase);
+void BLI_addtail(struct ListBase *listbase, void *vlink);
+void BLI_remlink(struct ListBase *listbase, void *vlink);
+void BLI_newname(char * name, int add);
+int BLI_stringdec(char *string, char *kop, char *start, unsigned short *numlen);
+void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic);
+void BLI_addhead(struct ListBase *listbase, void *vlink);
+void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink);
+void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink);
+void BLI_sortlist(struct ListBase *listbase, int (*cmp)(void *, void *));
+void BLI_freelist(struct ListBase *listbase);
+int BLI_countlist(struct ListBase *listbase);
+void BLI_freelinkN(ListBase *listbase, void *vlink);
+void BLI_splitdirstring(char *di,char *fi);
+
+struct DynamicList *BLI_dlist_from_listbase(struct ListBase *lb);
+struct ListBase *BLI_listbase_from_dlist(struct DynamicList *dlist, struct ListBase *lb);
+void * BLI_dlist_find_link(struct DynamicList *dlist, unsigned int index);
+unsigned int BLI_count_items(struct DynamicList *dlist);
+void BLI_dlist_free_item(struct DynamicList *dlist, unsigned int index);
+void BLI_dlist_rem_item(struct DynamicList *dlist, unsigned int index);
+void * BLI_dlist_add_item_index(struct DynamicList *dlist, void *item, unsigned int index);
+void BLI_dlist_destroy(struct DynamicList *dlist);
+void BLI_dlist_init(struct DynamicList *dlist);
+void BLI_dlist_reinit(struct DynamicList *dlist);
+
+ /**
+ * dir can be any input, like from buttons, and this function
+ * converts it to a regular full path.
+ * Also removes garbage from directory paths, like /../ or double slashes etc
+ */
+void BLI_cleanup_dir(const char *relabase, char *dir);
+
+ /**
+ * Blender's path code replacement function.
+ * Bases @a path strings leading with "//" by the
+ * directory @a basepath, and replaces instances of
+ * '#' with the @a framenum. Results are written
+ * back into @a path.
+ *
+ * @a path The path to convert
+ * @a basepath The directory to base relative paths with.
+ * @a framenum The framenumber to replace the frame code with.
+ * @retval Returns true if the path was relative (started with "//").
+ */
+int BLI_convertstringcode(char *path, const char *basepath, int framenum);
+
+void BLI_makestringcode(const char *relfile, char *file);
+
+ /**
+ * Change every @a from in @a string into @a to. The
+ * result will be in @a string
+ *
+ * @a string The string to work on
+ * @a from The character to replace
+ * @a to The character to replace with
+ */
+void BLI_char_switch(char *string, char from, char to);
+
+ /**
+ * Makes sure @a path has platform-specific slashes.
+ *
+ * @a path The path to 'clean'
+ */
+void BLI_clean(char *path);
+ /**
+ * Duplicates the cstring @a str into a newly mallocN'd
+ * string and returns it.
+ *
+ * @param str The string to be duplicated
+ * @retval Returns the duplicated string
+ */
+char *BLI_strdup(const char *str);
+
+ /**
+ * Duplicates the first @a len bytes of cstring @a str
+ * into a newly mallocN'd string and returns it. @a str
+ * is assumed to be at least len bytes long.
+ *
+ * @param str The string to be duplicated
+ * @param len The number of bytes to duplicate
+ * @retval Returns the duplicated string
+ */
+char *BLI_strdupn(const char *str, int len);
+
+ /**
+ * Like strncpy but ensures dst is always
+ * '\0' terminated.
+ *
+ * @param dst Destination for copy
+ * @param src Source string to copy
+ * @param maxncpy Maximum number of characters to copy (generally
+ * the size of dst)
+ * @retval Returns dst
+ */
+char *BLI_strncpy(char *dst, const char *src, int maxncpy);
+
+ /*
+ * Replacement for snprintf
+ */
+int BLI_snprintf(char *buffer, size_t count, const char *format, ...);
+
+ /**
+ * Compare two strings
+ *
+ * @retval True if the strings are equal, false otherwise.
+ */
+int BLI_streq(char *a, char *b);
+
+ /**
+ * Compare two strings without regard to case.
+ *
+ * @retval True if the strings are equal, false otherwise.
+ */
+int BLI_strcaseeq(char *a, char *b);
+
+/* in util.c */
+#ifdef WITH_ICONV
+void BLI_string_to_utf8(char *original, char *utf_8, char *code);
+#endif
+
+ /**
+ * Read a file as ASCII lines. An empty list is
+ * returned if the file cannot be opened or read.
+ *
+ * @attention The returned list should be free'd with
+ * BLI_free_file_lines.
+ *
+ * @param name The name of the file to read.
+ * @retval A list of strings representing the file lines.
+ */
+struct LinkNode *BLI_read_file_as_lines(char *name);
+
+ /**
+ * Free the list returned by BLI_read_file_as_lines.
+ */
+void BLI_free_file_lines(struct LinkNode *lines);
+
+ /**
+ * Checks if name is a fully qualified filename to an executable.
+ * If not it searches $PATH for the file. On Windows it also
+ * adds the correct extension (.com .exe etc) from
+ * $PATHEXT if necessary. Also on Windows it translates
+ * the name to its 8.3 version to prevent problems with
+ * spaces and stuff. Final result is returned in fullname.
+ *
+ * @param fullname The full path and full name of the executable
+ * @param name The name of the executable (usually argv[0]) to be checked
+ */
+void BLI_where_am_i(char *fullname, char *name);
+
+ /**
+ * determines the full path to the application bundle on OS X
+ *
+ * @return path to application bundle
+ */
+#ifdef __APPLE__
+char* BLI_getbundle(void);
+#endif
+
+#ifdef WIN32
+int BLI_getInstallationDir(char *str);
+#endif
+
+/* BLI_storage.h */
+int BLI_filesize(int file);
+double BLI_diskfree(char *dir);
+char *BLI_getwdN(char *dir);
+void BLI_hide_dot_files(int set);
+unsigned int BLI_getdir(char *dirname, struct direntry **filelist);
+
+/**
+ * @attention Do not confuse with BLI_exists
+ */
+int BLI_exist(char *name);
+
+/* BLI_fileops.h */
+void BLI_recurdir_fileops(char *dirname);
+int BLI_link(char *file, char *to);
+int BLI_backup(char *file, char *from, char *to);
+int BLI_is_writable(char *filename);
+
+/**
+ * @attention Do not confuse with BLI_exist
+ */
+int BLI_exists(char *file);
+int BLI_copy_fileops(char *file, char *to);
+int BLI_rename(char *from, char *to);
+int BLI_gzip(char *from, char *to);
+int BLI_delete(char *file, int dir, int recursive);
+int BLI_move(char *file, char *to);
+int BLI_touch(char *file);
+char *BLI_last_slash(char *string);
+
+/* BLI_rct.c */
+/**
+ * Determine if a rect is empty. An empty
+ * rect is one with a zero (or negative)
+ * width or height.
+ *
+ * @return True if @a rect is empty.
+ */
+int BLI_rcti_is_empty(struct rcti *rect);
+void BLI_init_rctf(struct rctf *rect, float xmin, float xmax, float ymin, float ymax);
+void BLI_init_rcti(struct rcti *rect, int xmin, int xmax, int ymin, int ymax);
+void BLI_translate_rctf(struct rctf *rect, float x, float y);
+void BLI_translate_rcti(struct rcti *rect, int x, int y);
+int BLI_in_rcti(struct rcti *rect, int x, int y);
+int BLI_in_rctf(struct rctf *rect, float x, float y);
+int BLI_isect_rctf(struct rctf *src1, struct rctf *src2, struct rctf *dest);
+int BLI_isect_rcti(struct rcti *src1, struct rcti *src2, struct rcti *dest);
+void BLI_union_rctf(struct rctf *rcta, struct rctf *rctb);
+
+/* scanfill.c: used in displist only... */
+struct EditVert *BLI_addfillvert(float *vec);
+struct EditEdge *BLI_addfilledge(struct EditVert *v1, struct EditVert *v2);
+int BLI_edgefill(int mode, int mat_nr);
+void BLI_end_edgefill(void);
+
+/* noise.h: */
+float BLI_hnoise(float noisesize, float x, float y, float z);
+float BLI_hnoisep(float noisesize, float x, float y, float z);
+float BLI_turbulence(float noisesize, float x, float y, float z, int nr);
+float BLI_turbulence1(float noisesize, float x, float y, float z, int nr);
+/* newnoise: generic noise & turbulence functions to replace the above BLI_hnoise/p & BLI_turbulence/1.
+ * This is done so different noise basis functions can be used */
+float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noisebasis);
+float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int hard, int noisebasis);
+/* newnoise: musgrave functions */
+float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis);
+float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis);
+float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nbas2);
+float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, float octaves, float offset, int noisebasis);
+float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis);
+float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis);
+/* newnoise: voronoi */
+void voronoi(float x, float y, float z, float* da, float* pa, float me, int dtype);
+/* newnoise: cellNoise & cellNoiseV (for vector/point/color) */
+float cellNoise(float x, float y, float z);
+void cellNoiseV(float x, float y, float z, float *ca);
+
+/* These callbacks are needed to make the lib finction properly */
+
+/**
+ * Set a function taking a char* as argument to flag errors. If the
+ * callback is not set, the error is discarded.
+ * @param f The function to use as callback
+ * @attention used in creator.c
+ */
+void BLI_setErrorCallBack(void (*f)(char*));
+
+/**
+ * Set a function to be able to interrupt the execution of processing
+ * in this module. If the function returns true, the execution will
+ * terminate gracefully. If the callback is not set, interruption is
+ * not possible.
+ * @param f The function to use as callback
+ * @attention used in creator.c
+ */
+void BLI_setInterruptCallBack(int (*f)(void));
+
+char *BLI_strcasestr(const char *s, const char *find);
+int BLI_strcasecmp(const char *s1, const char *s2);
+int BLI_strncasecmp(const char *s1, const char *s2, int n);
+void BLI_timestr(double time, char *str);
+
+/**
+ * Trick to address 32 GB with an int (only for malloced pointers)
+ */
+int BLI_int_from_pointer(void *poin);
+void *BLI_pointer_from_int(int val);
+
+
+#define PRNTSUB(type,arg) printf(#arg ": %" #type " ", arg)
+
+#ifndef PRINT
+#define PRINT(t,v) {PRNTSUB(t,v); printf("\n");}
+#define PRINT2(t1,v1,t2,v2) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); printf("\n");}
+#define PRINT3(t1,v1,t2,v2,t3,v3) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); PRNTSUB(t3,v3); printf("\n");}
+#define PRINT4(t1,v1,t2,v2,t3,v3,t4,v4) {PRNTSUB(t1,v1); PRNTSUB(t2,v2); PRNTSUB(t3,v3); PRNTSUB(t4,v4); printf("\n");}
+#endif
+
+/**
+ * @param array The array in question
+ * @retval The number of elements in the array.
+ */
+#define BLI_ARRAY_NELEMS(array) (sizeof((array))/sizeof((array)[0]))
+
+/**
+ * @param strct The structure of interest
+ * @param member The name of a member field of @a strct
+ * @retval The offset in bytes of @a member within @a strct
+ */
+#define BLI_STRUCT_OFFSET(strct, member) ((int) &((strct*) 0)->member)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h
new file mode 100644
index 00000000000..b5cf9cd81e9
--- /dev/null
+++ b/source/blender/blenlib/BLI_boxpack2d.h
@@ -0,0 +1,69 @@
+/**
+ *
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * The old math stuff from Ton. These will slowly phase out in favour
+ * of MTC calls. (or even MoTO :) )
+ * */
+
+/* Box Packer */
+
+/* verts, internal use only */
+typedef struct boxVert {
+ float x;
+ float y;
+ short free;
+
+ struct boxPack *trb; /* top right box */
+ struct boxPack *blb; /* bottom left box */
+ struct boxPack *brb; /* bottom right box */
+ struct boxPack *tlb; /* top left box */
+
+ /* Store last intersecting boxes here
+ * speedup intersection testing */
+ struct boxPack *isect_cache[4];
+
+ int index;
+} boxVert;
+
+typedef struct boxPack {
+ float x;
+ float y;
+ float w;
+ float h;
+ int index;
+
+ /* Verts this box uses
+ * (BL,TR,TL,BR) / 0,1,2,3 */
+ boxVert *v[4];
+} boxPack;
+
+void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height);
+
diff --git a/source/blender/blenlib/BLI_dynamiclist.h b/source/blender/blenlib/BLI_dynamiclist.h
new file mode 100644
index 00000000000..89e27743054
--- /dev/null
+++ b/source/blender/blenlib/BLI_dynamiclist.h
@@ -0,0 +1,58 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * Documentation of Two way dynamic list with access array can be found at:
+ *
+ * http://wiki.blender.org/bin/view.pl/Blenderwiki/DynamicListWithAccessArray
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef B_DYNAMIC_LIST_H
+#define B_DYNAMIC_LIST_H
+
+#define PAGE_SIZE 4
+
+struct ListBase;
+
+/*
+ * Access array using realloc
+ */
+typedef struct DynamicArray{
+ unsigned int count; /* count of items in list */
+ unsigned int max_item_index; /* max available index */
+ unsigned int last_item_index; /* max used index */
+ void **items; /* dynamicaly allocated array of pointers
+ pointing at items in list */
+} DynamicArray;
+
+/*
+ * Two way dynamic list with access array
+ */
+typedef struct DynamicList {
+ struct DynamicArray da; /* access array */
+ struct ListBase lb; /* two way linked dynamic list */
+} DynamicList;
+
+#endif
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
new file mode 100644
index 00000000000..7e8cc140964
--- /dev/null
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -0,0 +1,90 @@
+/**
+ * @file BLI_dynstr.h
+ *
+ * A dynamically sized string ADT.
+ * This ADT is designed purely for dynamic string creation
+ * through appending, not for general usage, the intent is
+ * to build up dynamic strings using a DynStr object, then
+ * convert it to a c-string and work with that.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_DYNSTR_H
+#define BLI_DYNSTR_H
+
+struct DynStr;
+
+ /** The abstract DynStr type */
+typedef struct DynStr DynStr;
+
+ /**
+ * Create a new DynStr.
+ *
+ * @return Pointer to a new DynStr.
+ */
+DynStr* BLI_dynstr_new (void);
+
+ /**
+ * Append a c-string to a DynStr.
+ *
+ * @param ds The DynStr to append to.
+ * @param cstr The c-string to append.
+ */
+void BLI_dynstr_append (DynStr *ds, char *cstr);
+
+ /**
+ * Find the length of a DynStr.
+ *
+ * @param ds The DynStr of interest.
+ * @return The length of @a ds.
+ */
+int BLI_dynstr_get_len (DynStr *ds);
+
+ /**
+ * Get a DynStr's contents as a c-string.
+ * <i> The returned c-string should be free'd
+ * using BLI_freeN. </i>
+ *
+ * @param ds The DynStr of interest.
+ * @return The contents of @a ds as a c-string.
+ */
+char* BLI_dynstr_get_cstring (DynStr *ds);
+
+ /**
+ * Free the DynStr
+ *
+ * @param ds The DynStr to free.
+ */
+void BLI_dynstr_free (DynStr *ds);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
new file mode 100644
index 00000000000..6b7eaedea2f
--- /dev/null
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -0,0 +1,99 @@
+/**
+ * A general unordered 2-int pair hash table ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Daniel Dunbar
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_EDGEHASH_H
+#define BLI_EDGEHASH_H
+
+struct EdgeHash;
+struct EdgeHashIterator;
+typedef struct EdgeHash EdgeHash;
+typedef struct EdgeHashIterator EdgeHashIterator;
+
+typedef void (*EdgeHashFreeFP)(void *key);
+
+EdgeHash* BLI_edgehash_new (void);
+void BLI_edgehash_free (EdgeHash *eh, EdgeHashFreeFP valfreefp);
+
+ /* Insert edge (v0,v1) into hash with given value, does
+ * not check for duplicates.
+ */
+void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val);
+
+ /* Return value for given edge (v0,v1), or NULL if
+ * if key does not exist in hash. (If need exists
+ * to differentiate between key-value being NULL and
+ * lack of key then see BLI_edgehash_lookup_p().
+ */
+void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1);
+
+ /* Return pointer to value for given edge (v0,v1),
+ * or NULL if key does not exist in hash.
+ */
+void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1);
+
+ /* Return boolean true/false if edge (v0,v1) in hash. */
+int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1);
+
+ /* Return number of keys in hash. */
+int BLI_edgehash_size (EdgeHash *eh);
+
+ /* Remove all edges from hash. */
+void BLI_edgehash_clear (EdgeHash *eh, EdgeHashFreeFP valfreefp);
+
+/***/
+
+ /**
+ * Create a new EdgeHashIterator. The hash table must not be mutated
+ * while the iterator is in use, and the iterator will step exactly
+ * BLI_edgehash_size(gh) times before becoming done.
+ */
+EdgeHashIterator* BLI_edgehashIterator_new (EdgeHash *eh);
+
+ /* Free an EdgeHashIterator. */
+void BLI_edgehashIterator_free (EdgeHashIterator *ehi);
+
+ /* Retrieve the key from an iterator. */
+void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, int *v0_r, int *v1_r);
+
+ /* Retrieve the value from an iterator. */
+void* BLI_edgehashIterator_getValue (EdgeHashIterator *ehi);
+
+ /* Steps the iterator to the next index. */
+void BLI_edgehashIterator_step (EdgeHashIterator *ehi);
+
+ /* Determine if an iterator is done. */
+int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
new file mode 100644
index 00000000000..795f6781894
--- /dev/null
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -0,0 +1,190 @@
+/**
+ * blenlib/BLI_editVert.h mar 2001 Nzc
+ *
+ * Some editing types needed in the lib (unfortunately) for
+ * scanfill.c
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_EDITVERT_H
+#define BLI_EDITVERT_H
+
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+
+struct DerivedMesh;
+struct RetopoPaintData;
+
+/* note; changing this also might affect the undo copy in editmesh.c */
+typedef struct EditVert
+{
+ struct EditVert *next, *prev;
+ union {
+ /* some lean storage for temporary usage
+ * in editmesh routines
+ */
+ struct EditVert *v;
+ struct EditEdge *e;
+ struct EditFace *f;
+ void *p;
+ long l;
+ float fp;
+ } tmp;
+ float no[3]; /*vertex normal */
+ float co[3]; /*vertex location */
+ short xs, ys; /* used to store a screenspace 2d projection of the verts */
+
+ /* f stores selection eg. if (eve->f & SELECT) {...
+ h for hidden. if (!eve->h) {...
+ f1 and f2 can be used for temp data, clear them first*/
+ unsigned char f, h, f1, f2;
+ short fast; /* only 0 or 1, for editmesh_fastmalloc, do not store temp data here! */
+ int hash;
+ int keyindex; /* original index #, for restoring key information */
+/*#ifdef WITH_VERSE*/
+ void *vvert;
+/*#endif*/
+
+ void *data; /* custom vertex data */
+} EditVert;
+
+struct EditEdge;
+
+typedef struct HashEdge {
+ struct EditEdge *eed;
+ struct HashEdge *next;
+} HashEdge;
+
+/* note; changing this also might affect the undo copy in editmesh.c */
+typedef struct EditEdge
+{
+ struct EditEdge *next, *prev;
+ struct EditVert *v1, *v2;
+ union {
+ /* some lean storage for temporary usage
+ * in editmesh routines
+ */
+ struct EditVert *v;
+ struct EditEdge *e;
+ struct EditFace *f;
+ void *p;
+ long l;
+ float fp;
+ } tmp;
+ short f1, f2; /* short, f1 is (ab)used in subdiv */
+ unsigned char f, h, dir, seam, sharp;
+ float crease;
+ short fast; /* only 0 or 1, for editmesh_fastmalloc */
+ short fgoni; /* index for fgon, for search */
+ HashEdge hash;
+ void *data; /*custom edge data*/
+} EditEdge;
+
+/* note; changing this also might affect the undo copy in editmesh.c */
+typedef struct EditFace
+{
+ struct EditFace *next, *prev;
+ struct EditVert *v1, *v2, *v3, *v4;
+ struct EditEdge *e1, *e2, *e3, *e4;
+ union {
+ /* some lean storage for temporary usage
+ * in editmesh routines
+ */
+ struct EditVert *v;
+ struct EditEdge *e;
+ struct EditFace *f;
+ void *p;
+ long l;
+ float fp;
+ } tmp;
+ float n[3], cent[3];
+ unsigned char mat_nr, flag;
+ unsigned char f, f1, h;
+ unsigned char fast; /* only 0 or 1, for editmesh_fastmalloc */
+ unsigned char fgonf; /* flag for fgon options */
+/*#ifdef WITH_VERSE*/
+ void *vface;
+/*#endif*/
+ void *data; /* custom face data */
+} EditFace;
+
+
+/*selection types*/
+#define EDITVERT 0
+#define EDITEDGE 1
+#define EDITFACE 2
+
+typedef struct EditSelection
+{
+ struct EditSelection *next, *prev;
+ short type;
+ void *data;
+} EditSelection;
+
+
+typedef struct EditMesh
+{
+ ListBase verts, edges, faces;
+ ListBase selected; /*EditSelections. Used to store the order in which things are selected.*/
+ HashEdge *hashedgetab;
+
+ /* this is for the editmesh_fastmalloc */
+ EditVert *allverts, *curvert;
+ EditEdge *alledges, *curedge;
+ EditFace *allfaces, *curface;
+ /* DerivedMesh caches... note that derived cage can be equivalent
+ * to derived final, care should be taken on release.
+ */
+
+ /* used for keeping track of the last clicked on face - so the space image
+ * when using the last selected face - (EditSelection) the space image flickered too much
+ *
+ * never access this directly, use EM_set_actFace and EM_get_actFace */
+ EditFace *act_face;
+
+ struct DerivedMesh *derivedCage, *derivedFinal;
+ /* the custom data layer mask that was last used to calculate
+ * derivedCage and derivedFinal
+ */
+ int lastDataMask;
+
+ struct RetopoPaintData *retopo_paint_data;
+
+ CustomData vdata, edata, fdata;
+
+#ifdef WITH_VERSE
+ void *vnode;
+#endif
+} EditMesh;
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
new file mode 100644
index 00000000000..ce5be5fc311
--- /dev/null
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -0,0 +1,118 @@
+/**
+ * A general (pointer -> pointer) hash table ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_GHASH_H
+#define BLI_GHASH_H
+
+struct GHash;
+typedef struct GHash GHash;
+typedef struct GHashIterator GHashIterator;
+
+typedef unsigned int (*GHashHashFP) (void *key);
+typedef int (*GHashCmpFP) (void *a, void *b);
+typedef void (*GHashKeyFreeFP) (void *key);
+typedef void (*GHashValFreeFP) (void *val);
+
+GHash* BLI_ghash_new (GHashHashFP hashfp, GHashCmpFP cmpfp);
+void BLI_ghash_free (GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+
+void BLI_ghash_insert (GHash *gh, void *key, void *val);
+int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void* BLI_ghash_lookup (GHash *gh, void *key);
+int BLI_ghash_haskey (GHash *gh, void *key);
+
+int BLI_ghash_size (GHash *gh);
+
+/* *** */
+
+ /**
+ * Create a new GHashIterator. The hash table must not be mutated
+ * while the iterator is in use, and the iterator will step exactly
+ * BLI_ghash_size(gh) times before becoming done.
+ *
+ * @param gh The GHash to iterate over.
+ * @return Pointer to a new DynStr.
+ */
+GHashIterator* BLI_ghashIterator_new (GHash *gh);
+ /**
+ * Free a GHashIterator.
+ *
+ * @param ghi The iterator to free.
+ */
+void BLI_ghashIterator_free (GHashIterator *ghi);
+
+ /**
+ * Retrieve the key from an iterator.
+ *
+ * @param ghi The iterator.
+ * @return The key at the current index, or NULL if the
+ * iterator is done.
+ */
+void* BLI_ghashIterator_getKey (GHashIterator *ghi);
+ /**
+ * Retrieve the value from an iterator.
+ *
+ * @param ghi The iterator.
+ * @return The value at the current index, or NULL if the
+ * iterator is done.
+ */
+void* BLI_ghashIterator_getValue (GHashIterator *ghi);
+ /**
+ * Steps the iterator to the next index.
+ *
+ * @param ghi The iterator.
+ */
+void BLI_ghashIterator_step (GHashIterator *ghi);
+ /**
+ * Determine if an iterator is done (has reached the end of
+ * the hash table).
+ *
+ * @param ghi The iterator.
+ * @return True if done, False otherwise.
+ */
+int BLI_ghashIterator_isDone (GHashIterator *ghi);
+
+/* *** */
+
+unsigned int BLI_ghashutil_ptrhash (void *key);
+int BLI_ghashutil_ptrcmp (void *a, void *b);
+
+unsigned int BLI_ghashutil_strhash (void *key);
+int BLI_ghashutil_strcmp (void *a, void *b);
+
+unsigned int BLI_ghashutil_inthash (void *ptr);
+int BLI_ghashutil_intcmp(void *a, void *b);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
new file mode 100644
index 00000000000..5180d3d8bbc
--- /dev/null
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -0,0 +1,96 @@
+/*
+ * A generic structure queue (a queue for fixed length
+ * (generally small) structures.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_GSQUEUE_H
+#define BLI_GSQUEUE_H
+
+typedef struct _GSQueue GSQueue;
+
+ /**
+ * Create a new GSQueue.
+ *
+ * @param elem_size The size of the structures in the queue.
+ * @retval The new queue
+ */
+GSQueue* BLI_gsqueue_new (int elem_size);
+
+ /**
+ * Query if the queue is empty
+ */
+int BLI_gsqueue_is_empty(GSQueue *gq);
+
+ /**
+ * Access the item at the head of the queue
+ * without removing it.
+ *
+ * @param item_r A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new)
+ */
+void BLI_gsqueue_peek (GSQueue *gq, void *item_r);
+
+ /**
+ * Access the item at the head of the queue
+ * and remove it.
+ *
+ * @param item_r A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ * Can be NULL if desired.
+ */
+void BLI_gsqueue_pop (GSQueue *gq, void *item_r);
+
+ /**
+ * Push an element onto the tail of the queue.
+ *
+ * @param item A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
+void BLI_gsqueue_push (GSQueue *gq, void *item);
+
+ /**
+ * Push an element back onto the head of the queue (so
+ * it would be returned from the next call to BLI_gsqueue_pop).
+ *
+ * @param item A pointer to an appropriatly
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
+void BLI_gsqueue_pushback (GSQueue *gq, void *item);
+
+ /**
+ * Free the queue
+ */
+void BLI_gsqueue_free (GSQueue *gq);
+
+#endif /* BLI_GSQUEUE_H */
+
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
new file mode 100644
index 00000000000..8ebb6ad269f
--- /dev/null
+++ b/source/blender/blenlib/BLI_heap.h
@@ -0,0 +1,74 @@
+/**
+ * A heap / priority queue ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Brecht Van Lommel
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_HEAP_H
+#define BLI_HEAP_H
+
+struct Heap;
+struct HeapNode;
+typedef struct Heap Heap;
+typedef struct HeapNode HeapNode;
+
+typedef void (*HeapFreeFP)(void *ptr);
+
+/* Creates a new heap. BLI_memarena is used for allocating nodes. Removed nodes
+ are recycled, so memory usage will not shrink. */
+Heap* BLI_heap_new (void);
+void BLI_heap_free (Heap *heap, HeapFreeFP ptrfreefp);
+
+/* Insert heap node with a value (often a 'cost') and pointer into the heap,
+ duplicate values are allowed. */
+HeapNode* BLI_heap_insert (Heap *heap, float value, void *ptr);
+
+/* Remove a heap node. */
+void BLI_heap_remove (Heap *heap, HeapNode *node);
+
+/* Return 0 if the heap is empty, 1 otherwise. */
+int BLI_heap_empty (Heap *heap);
+
+/* Return the size of the heap. */
+int BLI_heap_size (Heap *heap);
+
+/* Return the top node of the heap. This is the node with the lowest value. */
+HeapNode* BLI_heap_top (Heap *heap);
+
+/* Pop the top node off the heap and return it's pointer. */
+void* BLI_heap_popmin (Heap *heap);
+
+/* Return the value or pointer of a heap node. */
+float BLI_heap_node_value (HeapNode *heap);
+void* BLI_heap_node_ptr (HeapNode *heap);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_jitter.h b/source/blender/blenlib/BLI_jitter.h
new file mode 100644
index 00000000000..1cd4880d0b7
--- /dev/null
+++ b/source/blender/blenlib/BLI_jitter.h
@@ -0,0 +1,40 @@
+/*
+ * jitter.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_JITTER_H
+#define BLI_JITTER_H
+
+extern void BLI_initjit(float *jitarr, int num);
+extern void BLI_jitterate1(float *jit1, float *jit2, int num, float rad1);
+extern void BLI_jitterate2(float *jit1, float *jit2, int num, float rad2);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
new file mode 100644
index 00000000000..9982047ec9e
--- /dev/null
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -0,0 +1,62 @@
+/*
+ * Routines for working with singly linked lists
+ * of 'links' - pointers to other data.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_LINKLIST_H
+#define BLI_LINKLIST_H
+
+struct MemArena;
+
+typedef void (*LinkNodeFreeFP)(void *link);
+typedef void (*LinkNodeApplyFP)(void *link, void *userdata);
+
+struct LinkNode;
+typedef struct LinkNode {
+ struct LinkNode *next;
+ void *link;
+} LinkNode;
+
+int BLI_linklist_length (struct LinkNode *list);
+
+void BLI_linklist_reverse (struct LinkNode **listp);
+
+void BLI_linklist_prepend (struct LinkNode **listp, void *ptr);
+void BLI_linklist_append (struct LinkNode **listp, void *ptr);
+void BLI_linklist_prepend_arena (struct LinkNode **listp, void *ptr, struct MemArena *ma);
+
+void BLI_linklist_free (struct LinkNode *list, LinkNodeFreeFP freefunc);
+void BLI_linklist_apply (struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
new file mode 100644
index 00000000000..420995e3b11
--- /dev/null
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -0,0 +1,61 @@
+/*
+ * Memory arena ADT
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * Memory arena's are commonly used when the program
+ * needs to quickly allocate lots of little bits of
+ * data, which are all freed at the same moment.
+ *
+ */
+
+#ifndef BLI_MEMARENA_H
+#define BLI_MEMARENA_H
+
+ /* A reasonable standard buffer size, big
+ * enough to not cause much internal fragmentation,
+ * small enough not to waste resources
+ */
+#define BLI_MEMARENA_STD_BUFSIZE (1<<14)
+
+struct MemArena;
+typedef struct MemArena MemArena;
+
+
+struct MemArena* BLI_memarena_new (int bufsize);
+void BLI_memarena_free (struct MemArena *ma);
+
+void BLI_memarena_use_calloc (struct MemArena *ma);
+
+void* BLI_memarena_alloc (struct MemArena *ma, int size);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
new file mode 100644
index 00000000000..da2ecb79651
--- /dev/null
+++ b/source/blender/blenlib/BLI_rand.h
@@ -0,0 +1,99 @@
+/**
+ * @file BLI_rand.h
+ *
+ * Random number functions.
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_RAND_H
+#define BLI_RAND_H
+
+ /* RNG is just an abstract random number generator
+ * type that avoids using globals, otherwise identical
+ * to BLI_rand functions below.
+ */
+struct RNG;
+typedef struct RNG RNG;
+
+struct RNG* rng_new (unsigned int seed);
+void rng_free (struct RNG* rng);
+
+void rng_seed (struct RNG* rng, unsigned int seed);
+int rng_getInt (struct RNG* rng);
+double rng_getDouble (struct RNG* rng);
+float rng_getFloat (struct RNG* rng);
+void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems);
+
+ /** Seed the random number generator */
+void BLI_srand (unsigned int seed);
+
+ /** Better seed for the random number generator, using noise.c hash[] */
+void BLI_srandom (unsigned int seed);
+
+ /** Return a pseudo-random number N where 0<=N<(2^31) */
+int BLI_rand (void);
+
+ /** Return a pseudo-random number N where 0.0<=N<1.0 */
+double BLI_drand (void);
+
+ /** Return a pseudo-random number N where 0.0f<=N<1.0f */
+float BLI_frand (void);
+
+ /** Fills a block of memory starting at @a addr
+ * and extending @a len bytes with pseudo-random
+ * contents. This routine does not use nor modify
+ * the state of the BLI random number generator.
+ */
+void BLI_fillrand (void *addr, int len);
+
+ /** Shuffle an array randomly using the given seed.
+ * contents. This routine does not use nor modify
+ * the state of the BLI random number generator.
+ */
+void BLI_array_randomize (void *data, int elemSize, int numElems, unsigned int seed);
+
+
+ /** Better seed for the random number generator, using noise.c hash[] */
+ /** Allows up to 16 threads to address */
+void BLI_thread_srandom (int thread, unsigned int seed);
+
+ /** Return a pseudo-random number N where 0<=N<(2^31) */
+ /** Allows up to 16 threads to address */
+int BLI_thread_rand (int thread);
+
+ /** Return a pseudo-random number N where 0.0f<=N<1.0f */
+ /** Allows up to 16 threads to address */
+float BLI_thread_frand (int thread);
+
+
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_storage_types.h b/source/blender/blenlib/BLI_storage_types.h
new file mode 100644
index 00000000000..ebce33852a1
--- /dev/null
+++ b/source/blender/blenlib/BLI_storage_types.h
@@ -0,0 +1,83 @@
+/**
+ * blenlib/BLI_storage_types.h
+ *
+ * Some types for dealing with directories
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BLI_STORAGE_TYPES_H
+#define BLI_STORAGE_TYPES_H
+
+#include <sys/stat.h>
+
+#define HDRSIZE 512
+#define NAMSIZE 200
+
+struct header{
+ char name[NAMSIZE];
+ unsigned int size;
+ unsigned int chksum;
+ char fill[HDRSIZE-NAMSIZE-2*sizeof(unsigned int)];
+};
+
+#if defined(WIN32) && !defined(FREE_WINDOWS)
+typedef unsigned int mode_t;
+#endif
+
+struct ImBuf;
+
+struct direntry{
+ char *string;
+ mode_t type;
+ char *relname;
+ struct stat s;
+ unsigned int flags;
+ char size[16];
+ char mode1[4];
+ char mode2[4];
+ char mode3[4];
+ char owner[16];
+ char time[8];
+ char date[16];
+ char extra[16];
+ void *poin;
+ int nr;
+ struct ImBuf *image;
+};
+
+struct dirlink
+{
+ struct dirlink *next,*prev;
+ char *name;
+};
+
+#endif /* BLI_STORAGE_TYPES_H */
+
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
new file mode 100644
index 00000000000..60ecce3f9d8
--- /dev/null
+++ b/source/blender/blenlib/BLI_threads.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_THREADS_H
+#define BLI_THREADS_H
+
+/* one custom lock available now. can be extended */
+#define LOCK_IMAGE 0
+#define LOCK_CUSTOM1 1
+
+/* for tables, button in UI, etc */
+#define BLENDER_MAX_THREADS 8
+
+struct ListBase;
+
+void BLI_init_threads (struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
+int BLI_available_threads(struct ListBase *threadbase);
+int BLI_available_thread_index(struct ListBase *threadbase);
+void BLI_insert_thread (struct ListBase *threadbase, void *callerdata);
+void BLI_remove_thread (struct ListBase *threadbase, void *callerdata);
+void BLI_end_threads (struct ListBase *threadbase);
+
+void BLI_lock_thread (int type);
+void BLI_unlock_thread (int type);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
new file mode 100644
index 00000000000..ce800111afb
--- /dev/null
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -0,0 +1,103 @@
+/**
+ * @file BLI_vfontdata.h
+ *
+ * A structure to represent vector fonts,
+ * and to load them from PostScript fonts.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_VFONTDATA_H
+#define BLI_VFONTDATA_H
+
+#include "DNA_listBase.h"
+
+struct PackedFile;
+struct VFont;
+
+#define MAX_VF_CHARS 256
+
+typedef struct VFontData {
+ ListBase characters;
+ // ListBase nurbsbase[MAX_VF_CHARS];
+ // float resol[MAX_VF_CHARS];
+ // float width[MAX_VF_CHARS];
+ // float *points[MAX_VF_CHARS];
+ char name[128];
+} VFontData;
+
+typedef struct VChar {
+ struct VChar *next, *prev;
+ ListBase nurbsbase;
+ unsigned long index;
+ float resol;
+ float width;
+ float *points;
+} VChar;
+
+struct TmpFont
+{
+ struct TmpFont *next, *prev;
+ struct PackedFile *pf;
+ struct VFont *vfont;
+};
+
+
+/**
+ * Construct a new VFontData structure from
+ * PostScript font data in a PackedFile.
+ *
+ * @param pf The font data.
+ * @retval A new VFontData structure, or NULL
+ * if unable to load.
+ */
+ VFontData*
+BLI_vfontdata_from_psfont(
+ struct PackedFile *pf);
+
+/**
+ * Construct a new VFontData structure from
+ * Freetype font data in a PackedFile.
+ *
+ * @param pf The font data.
+ * @retval A new VFontData structure, or NULL
+ * if unable to load.
+ */
+ VFontData*
+BLI_vfontdata_from_freetypefont(
+ struct PackedFile *pf);
+
+ int
+BLI_vfontchar_from_freetypefont(
+ struct VFont *vfont, unsigned long character);
+
+#endif
+
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
new file mode 100644
index 00000000000..0f39d37c31f
--- /dev/null
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -0,0 +1,119 @@
+/**
+ * Compatibility-like things for windows.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#pragma warning(once: 4761 4305 4244 4018)
+
+#define WIN32_LEAN_AND_MEAN
+
+#ifndef WIN32_SKIP_HKEY_PROTECTION
+#define HKEY WIN32_HKEY // prevent competing definitions
+#include <windows.h>
+#undef HKEY
+#else
+#include <windows.h>
+#endif
+
+#undef near
+#undef far
+#undef rad
+#undef rad1
+#undef rad2
+#undef rad3
+#undef vec
+#undef rect
+#undef rct1
+#undef rct2
+
+#define near clipsta
+#define far clipend
+
+#undef small
+
+#ifndef __WINSTUFF_H__
+#define __WINSTUFF_H__
+
+ // These definitions are also in arithb for simplicity
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.70710678118654752440
+#endif
+
+#define MAXPATHLEN MAX_PATH
+
+#ifndef S_ISREG
+#define S_ISREG(x) ((x&S_IFMT) == S_IFREG)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(x) ((x&S_IFMT) == S_IFDIR)
+#endif
+
+#ifndef FREE_WINDOWS
+typedef unsigned int mode_t;
+#endif
+
+struct dirent {
+ int d_ino;
+ int d_off;
+ unsigned short d_reclen;
+ char *d_name;
+};
+
+typedef struct _DIR {
+ HANDLE handle;
+ WIN32_FIND_DATA data;
+ char path[MAX_PATH];
+ long dd_loc;
+ long dd_size;
+ char dd_buf[4096];
+ void *dd_direct;
+
+ struct dirent direntry;
+} DIR;
+
+void RegisterBlendExtension(char * str);
+DIR *opendir (const char *path);
+struct dirent *readdir(DIR *dp);
+int closedir (DIR *dp);
+void get_default_root(char* root);
+
+#endif /* __WINSTUFF_H__ */
+
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
new file mode 100644
index 00000000000..4812cad033d
--- /dev/null
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -0,0 +1,56 @@
+# $Id$
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program 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 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+
+FILE(GLOB SRC intern/*.c)
+
+SET(INC
+ . ../makesdna ../blenkernel ../../../intern/guardedalloc ../include
+ ${FREETYPE_INC}
+ ${SDL_INC}
+ ${ZLIB_INC}
+)
+
+IF(WITH_VERSE)
+ ADD_DEFINITIONS(-DWITH_VERSE)
+ SET(INC ${INC} ${VERSE_INC})
+ENDIF(WITH_VERSE)
+
+IF(WITH_INTERNATIONAL)
+ ADD_DEFINITIONS(-DWITH_FREETYPE2)
+ENDIF(WITH_INTERNATIONAL)
+
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
+BLENDERLIB(bf_blenlib "${SRC}" "${INC}")
+#if env['OURPLATFORM'] == 'linux2':
+# cflags='-pthread'
+#
+#env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags )
diff --git a/source/blender/blenlib/MTC_matrixops.h b/source/blender/blenlib/MTC_matrixops.h
new file mode 100644
index 00000000000..27b5bb1ca95
--- /dev/null
+++ b/source/blender/blenlib/MTC_matrixops.h
@@ -0,0 +1,165 @@
+/*
+ * matrixops.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef MATRIXOPS_H
+#define MATRIXOPS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* need rewriting: */
+/**
+ * copy the left upp3 3 by 3 of m2 to m1
+ */
+void MTC_Mat3CpyMat4(float m1[][3], float m2[][4]);
+
+/* ------------------------------------------------------------------------- */
+/* operations based on 4 by 4 matrices */
+
+/**
+ * Copy m1 to m2
+ */
+void MTC_Mat4CpyMat4(float m1[][4], float m2[][4]);
+
+/**
+ * Multiply all matrices after the first, leave the result in the
+ * first argument
+ */
+void MTC_Mat4MulSerie(float answ[][4],
+ float m1[][4], float m2[][4], float m3[][4],
+ float m4[][4], float m5[][4], float m6[][4],
+ float m7[][4], float m8[][4]);
+
+/**
+ * m1 = m2 matprod m3
+ */
+void MTC_Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4]);
+
+/**
+ * Do vec^t prod mat, result in vec. Ignore vec[3] (vec is a
+ * float[3])
+ */
+void MTC_Mat4MulVecfl(float mat[][4], float *vec);
+
+/**
+ * Invert mat, result in inverse. Always returns 1
+ */
+int MTC_Mat4Invert(float inverse[][4], float mat[][4]);
+
+/**
+ * Make the set of mat orthonormal (mat should already be orthogonal)?
+ * (doesn't appear to normalize properly?)
+ */
+void MTC_Mat4Ortho(float mat[][4]);
+
+/**
+ * vec = mat prod vec, result in vec, ignore fourth component entirely
+ * (4th component is _not_ accessed!!! vec is 3d)
+ */
+void MTC_Mat4Mul3Vecfl(float mat[][4], float *vec);
+
+/**
+ * vec = mat prod vec, result in vec
+ */
+void MTC_Mat4MulVec4fl(float mat[][4], float *vec);
+
+/**
+ * Set <m> to the 4-D unity matrix
+ */
+void MTC_Mat4One(float m[][4]);
+
+/**
+ * Swap matrices m1 and m2
+ */
+void MTC_Mat4SwapMat4(float m1[][4], float m2[][4]);
+
+/**
+ * Copy m2 to the top-left 3x3 of m1, don't touch the remaining elements.
+ */
+void MTC_Mat4CpyMat3nc(float m1[][4], float m2[][3]);
+
+/**
+ * m1 = m2 * m3, but only the top-left 3x3
+ */
+void MTC_Mat4MulMat33(float m1[][3], float m2[][4], float m3[][3]);
+
+/* ------------------------------------------------------------------------- */
+/* Operations based on 3 by 3 matrices */
+/**
+ * Do vec^t prod mat, result in vec.(vex is 3d)
+ */
+void MTC_Mat3MulVecfl(float mat[][3], float *vec);
+
+/**
+ * Copy m1 to m2
+ */
+void MTC_Mat3CpyMat3(float m1[][3], float m2[][3]);
+
+/**
+ * m1 = m2 prod m3
+ */
+void MTC_Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]);
+
+/**
+ * vec = vec prod mat
+ */
+void MTC_Mat3MulVecd(float mat[][3], double *vec);
+
+/**
+ * Guess: invert matrix
+ * result goes to m1
+ */
+void MTC_Mat3Inv(float m1[][3], float m2[][3]);
+
+/**
+ * Sort of a determinant matrix? Doesn't seem very adjoint to me...
+ * result goes to m1
+ */
+void MTC_Mat3Adj(float m1[][3], float m[][3]);
+
+/**
+ * Set <m> to the 3D unity matrix
+ */
+void MTC_Mat3One(float m[][3]);
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MATRIXOPS_H */
+
diff --git a/source/blender/blenlib/MTC_vectorops.h b/source/blender/blenlib/MTC_vectorops.h
new file mode 100644
index 00000000000..64b2c312eb4
--- /dev/null
+++ b/source/blender/blenlib/MTC_vectorops.h
@@ -0,0 +1,61 @@
+/*
+ * vectorops.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef VECTOROPS_H
+#define VECTOROPS_H
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_diff3Int(int v1[3], int v2[3], int v3[3]);
+void MTC_cross3Int(int v1[3], int v2[3], int v3[3]);
+int MTC_dot3Int(int v1[3], int v2[3]);
+
+void MTC_diff3Float(float v1[3], float v2[3], float v3[3]);
+void MTC_cross3Float(float v1[3], float v2[3], float v3[3]);
+float MTC_dot3Float(float v1[3], float v2[3]);
+void MTC_cp3Float(float v1[3], float v2[3]);
+/**
+ * Copy vector with a minus sign (so a = -b)
+ */
+void MTC_cp3FloatInv(float v1[3], float v2[3]);
+
+void MTC_swapInt(int *i1, int *i2);
+
+void MTC_diff3DFF(double v1[3], float v2[3], float v3[3]);
+void MTC_cross3Double(double v1[3], double v2[3], double v3[3]);
+float MTC_normalize3DF(float n[3]);
+
+/* ------------------------------------------------------------------------- */
+#endif /* VECTOROPS_H */
+
diff --git a/source/blender/blenlib/Makefile b/source/blender/blenlib/Makefile
new file mode 100644
index 00000000000..12ee8c5ad8c
--- /dev/null
+++ b/source/blender/blenlib/Makefile
@@ -0,0 +1,37 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program 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 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+# Bounces make to subdirectories.
+
+SOURCEDIR = source/blender/blenlib
+DIRS = intern
+
+include nan_subdirs.mk
diff --git a/source/blender/blenlib/PIL_dynlib.h b/source/blender/blenlib/PIL_dynlib.h
new file mode 100644
index 00000000000..26e1b2f9ac4
--- /dev/null
+++ b/source/blender/blenlib/PIL_dynlib.h
@@ -0,0 +1,55 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef __PIL_DYNLIB_H__
+#define __PIL_DYNLIB_H__
+
+typedef struct PILdynlib PILdynlib;
+
+ PILdynlib*
+PIL_dynlib_open(
+ char *name);
+
+ void*
+PIL_dynlib_find_symbol(
+ PILdynlib* lib,
+ char *symname);
+
+ char*
+PIL_dynlib_get_error_as_string(
+ PILdynlib* lib);
+
+ void
+PIL_dynlib_close(
+ PILdynlib* lib);
+
+#endif /* __PIL_DYNLIB_H__ */
+
diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h
new file mode 100644
index 00000000000..190a116d658
--- /dev/null
+++ b/source/blender/blenlib/PIL_time.h
@@ -0,0 +1,62 @@
+/**
+ * @file PIL_time.h
+ *
+ * Platform independant time functions.
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef PIL_TIME_H
+#define PIL_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern
+ /** Return an indication of time, expressed as
+ * seconds since some fixed point. Successive calls
+ * are guarenteed to generate values greator than or
+ * equal to the last call.
+ */
+double PIL_check_seconds_timer (void);
+
+ /**
+ * Platform-independant sleep function.
+ * @param ms Number of milliseconds to sleep
+ */
+void PIL_sleep_ms (int ms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
new file mode 100644
index 00000000000..e11934d968e
--- /dev/null
+++ b/source/blender/blenlib/SConscript
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+cflags=''
+incs = '. ../makesdna ../blenkernel #/intern/guardedalloc ../include'
+incs += ' ' + env['BF_FREETYPE_INC']
+incs += ' ' + env['BF_ZLIB_INC']
+incs += ' ' + env['BF_SDL_INC']
+defs = ''
+
+if env['WITH_BF_INTERNATIONAL'] == 1:
+ defs = 'WITH_FREETYPE2'
+
+if env['WITH_BF_VERSE']:
+ defs += ' WITH_VERSE'
+ incs += ' ' + env['BF_VERSE_INCLUDE']
+
+if env['OURPLATFORM'] == 'linux2':
+ cflags='-pthread'
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
+env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags )
diff --git a/source/blender/blenlib/intern/BLI_callbacks.h b/source/blender/blenlib/intern/BLI_callbacks.h
new file mode 100644
index 00000000000..1f854764a59
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_callbacks.h
@@ -0,0 +1,44 @@
+/**
+ * blenlib/BLI_editVert.h mar 2001 Nzc
+ *
+ * These callbacks are needed in the lib
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_CALLBACKS_H
+#define BLI_CALLBACKS_H
+
+// This is blenlib internal only
+void callLocalErrorCallBack(char* msg);
+
+#endif
+
diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c
new file mode 100644
index 00000000000..8bde670eef5
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_dynstr.c
@@ -0,0 +1,118 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Dynamically sized string ADT
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/***/
+
+typedef struct DynStrElem DynStrElem;
+struct DynStrElem {
+ DynStrElem *next;
+
+ char *str;
+};
+
+struct DynStr {
+ DynStrElem *elems, *last;
+ int curlen;
+};
+
+/***/
+
+DynStr *BLI_dynstr_new(void) {
+ DynStr *ds= MEM_mallocN(sizeof(*ds), "DynStr");
+ ds->elems= ds->last= NULL;
+ ds->curlen= 0;
+
+ return ds;
+}
+
+void BLI_dynstr_append(DynStr *ds, char *cstr) {
+ DynStrElem *dse= malloc(sizeof(*dse));
+ int cstrlen= strlen(cstr);
+
+ dse->str= malloc(cstrlen+1);
+ memcpy(dse->str, cstr, cstrlen+1);
+ dse->next= NULL;
+
+ if (!ds->last)
+ ds->last= ds->elems= dse;
+ else
+ ds->last= ds->last->next= dse;
+
+ ds->curlen+= cstrlen;
+}
+
+int BLI_dynstr_get_len(DynStr *ds) {
+ return ds->curlen;
+}
+
+char *BLI_dynstr_get_cstring(DynStr *ds) {
+ char *s, *rets= MEM_mallocN(ds->curlen+1, "dynstr_cstring");
+ DynStrElem *dse;
+
+ for (s= rets, dse= ds->elems; dse; dse= dse->next) {
+ int slen= strlen(dse->str);
+
+ memcpy(s, dse->str, slen);
+
+ s+= slen;
+ }
+ rets[ds->curlen]= '\0';
+
+ return rets;
+}
+
+void BLI_dynstr_free(DynStr *ds) {
+ DynStrElem *dse;
+
+ for (dse= ds->elems; dse; ) {
+ DynStrElem *n= dse->next;
+
+ free(dse->str);
+ free(dse);
+
+ dse= n;
+ }
+
+ MEM_freeN(ds);
+}
diff --git a/source/blender/blenlib/intern/BLI_fileops.h b/source/blender/blenlib/intern/BLI_fileops.h
new file mode 100644
index 00000000000..622706a32e9
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_fileops.h
@@ -0,0 +1,50 @@
+/**
+ * blenlib/BLI_listBase.h mar 2001 Nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * More low-level fileops from Daniel Dunbar. Two functions were also
+ * defined in storage.c. These are the old fop_ prefixes. There is
+ * definitely some redundancy here!
+ * */
+
+#ifndef BLI_FILEOPS_H
+#define BLI_FILEOPS_H
+
+char *first_slash(char *string);
+
+/* only for the sane unix world: direct calls to system functions :( */
+#ifndef WIN32
+void BLI_setCmdCallBack(int (*f)(char*));
+#endif
+
+#endif
+
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
new file mode 100644
index 00000000000..5846bbda40e
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -0,0 +1,295 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * A general (pointer -> pointer) hash table ADT
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_ghash.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/***/
+
+static unsigned int hashsizes[]= {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
+ 268435459
+};
+
+/***/
+
+typedef struct Entry Entry;
+struct Entry {
+ Entry *next;
+
+ void *key, *val;
+};
+
+struct GHash {
+ GHashHashFP hashfp;
+ GHashCmpFP cmpfp;
+
+ Entry **buckets;
+ int nbuckets, nentries, cursize;
+};
+
+/***/
+
+GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp) {
+ GHash *gh= MEM_mallocN(sizeof(*gh), "GHash");
+ gh->hashfp= hashfp;
+ gh->cmpfp= cmpfp;
+
+ gh->cursize= 0;
+ gh->nentries= 0;
+ gh->nbuckets= hashsizes[gh->cursize];
+
+ gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
+ memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
+
+ return gh;
+}
+
+void BLI_ghash_insert(GHash *gh, void *key, void *val) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e= malloc(sizeof(*e));
+
+ e->key= key;
+ e->val= val;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ if (++gh->nentries>gh->nbuckets*3) {
+ Entry *e, **old= gh->buckets;
+ int i, nold= gh->nbuckets;
+
+ gh->nbuckets= hashsizes[++gh->cursize];
+ gh->buckets= malloc(gh->nbuckets*sizeof(*gh->buckets));
+ memset(gh->buckets, 0, gh->nbuckets*sizeof(*gh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ Entry *n= e->next;
+
+ hash= gh->hashfp(e->key)%gh->nbuckets;
+ e->next= gh->buckets[hash];
+ gh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ free(old);
+ }
+}
+
+void* BLI_ghash_lookup(GHash *gh, void *key) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return e->val;
+
+ return NULL;
+}
+
+int BLI_ghash_remove (GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+ Entry *p = 0;
+
+ for (e= gh->buckets[hash]; e; e= e->next) {
+ if (gh->cmpfp(key, e->key)==0) {
+ Entry *n= e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+ free(e);
+
+
+ e= n;
+ if (p)
+ p->next = n;
+ else
+ gh->buckets[hash] = n;
+
+ --gh->nentries;
+ return 1;
+ }
+ p = e;
+ }
+
+ return 0;
+}
+
+int BLI_ghash_haskey(GHash *gh, void *key) {
+ unsigned int hash= gh->hashfp(key)%gh->nbuckets;
+ Entry *e;
+
+ for (e= gh->buckets[hash]; e; e= e->next)
+ if (gh->cmpfp(key, e->key)==0)
+ return 1;
+
+ return 0;
+}
+
+int BLI_ghash_size(GHash *gh) {
+ return gh->nentries;
+}
+
+void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) {
+ int i;
+
+ for (i=0; i<gh->nbuckets; i++) {
+ Entry *e;
+
+ for (e= gh->buckets[i]; e; ) {
+ Entry *n= e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+ free(e);
+
+ e= n;
+ }
+ }
+
+ free(gh->buckets);
+ gh->buckets = 0;
+ gh->nentries = 0;
+ gh->nbuckets = 0;
+ MEM_freeN(gh);
+}
+
+/***/
+
+struct GHashIterator {
+ GHash *gh;
+ int curBucket;
+ Entry *curEntry;
+};
+
+GHashIterator *BLI_ghashIterator_new(GHash *gh) {
+ GHashIterator *ghi= malloc(sizeof(*ghi));
+ ghi->gh= gh;
+ ghi->curEntry= NULL;
+ ghi->curBucket= -1;
+ while (!ghi->curEntry) {
+ ghi->curBucket++;
+ if (ghi->curBucket==ghi->gh->nbuckets)
+ break;
+ ghi->curEntry= ghi->gh->buckets[ghi->curBucket];
+ }
+ return ghi;
+}
+void BLI_ghashIterator_free(GHashIterator *ghi) {
+ free(ghi);
+}
+
+void *BLI_ghashIterator_getKey(GHashIterator *ghi) {
+ return ghi->curEntry?ghi->curEntry->key:NULL;
+}
+void *BLI_ghashIterator_getValue(GHashIterator *ghi) {
+ return ghi->curEntry?ghi->curEntry->val:NULL;
+}
+
+void BLI_ghashIterator_step(GHashIterator *ghi) {
+ if (ghi->curEntry) {
+ ghi->curEntry= ghi->curEntry->next;
+ while (!ghi->curEntry) {
+ ghi->curBucket++;
+ if (ghi->curBucket==ghi->gh->nbuckets)
+ break;
+ ghi->curEntry= ghi->gh->buckets[ghi->curBucket];
+ }
+ }
+}
+int BLI_ghashIterator_isDone(GHashIterator *ghi) {
+ return !ghi->curEntry;
+}
+
+/***/
+
+unsigned int BLI_ghashutil_ptrhash(void *key) {
+ return (unsigned int) key;
+}
+int BLI_ghashutil_ptrcmp(void *a, void *b) {
+ if (a==b)
+ return 0;
+ else
+ return (a<b)?-1:1;
+}
+
+unsigned int BLI_ghashutil_inthash(void *ptr) {
+#if defined(_WIN64)
+ unsigned __int64 key = (unsigned __int64)ptr;
+#else
+ unsigned long key = (unsigned long)ptr;
+#endif
+
+ key += ~(key << 16);
+ key ^= (key >> 5);
+ key += (key << 3);
+ key ^= (key >> 13);
+ key += ~(key << 9);
+ key ^= (key >> 17);
+
+ return (unsigned int)(key & 0xffffffff);
+}
+
+int BLI_ghashutil_intcmp(void *a, void *b) {
+ if (a==b)
+ return 0;
+ else
+ return (a<b)?-1:1;
+}
+
+unsigned int BLI_ghashutil_strhash(void *ptr) {
+ char *s= ptr;
+ unsigned int i= 0;
+ unsigned char c;
+
+ while ( (c= *s++) )
+ i= i*37 + c;
+
+ return i;
+}
+int BLI_ghashutil_strcmp(void *a, void *b) {
+ return strcmp(a, b);
+}
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
new file mode 100644
index 00000000000..4d8a5179645
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -0,0 +1,220 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Brecht Van Lommel
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * A heap / priority queue ADT.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_memarena.h"
+#include "BLI_heap.h"
+
+/***/
+
+struct HeapNode {
+ void *ptr;
+ float value;
+ int index;
+};
+
+struct Heap {
+ unsigned int size;
+ unsigned int bufsize;
+ MemArena *arena;
+ HeapNode *freenodes;
+ HeapNode *nodes;
+ HeapNode **tree;
+};
+
+#define SWAP(type, a, b) \
+ { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+#define HEAP_PARENT(i) ((i-1)>>1)
+#define HEAP_LEFT(i) ((i<<1)+1)
+#define HEAP_RIGHT(i) ((i<<1)+2)
+#define HEAP_COMPARE(a, b) (a->value < b->value)
+#define HEAP_EQUALS(a, b) (a->value == b->value)
+#define HEAP_SWAP(heap, i, j) \
+ { SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \
+ SWAP(HeapNode*, heap->tree[i], heap->tree[j]); }
+
+/***/
+
+Heap *BLI_heap_new()
+{
+ Heap *heap = (Heap*)MEM_callocN(sizeof(Heap), "BLIHeap");
+ heap->bufsize = 1;
+ heap->tree = (HeapNode**)MEM_mallocN(sizeof(HeapNode*), "BLIHeapTree");
+ heap->arena = BLI_memarena_new(1<<16);
+
+ return heap;
+}
+
+void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
+{
+ int i;
+
+ if (ptrfreefp)
+ for (i = 0; i < heap->size; i++)
+ ptrfreefp(heap->tree[i]->ptr);
+
+ MEM_freeN(heap->tree);
+ BLI_memarena_free(heap->arena);
+ MEM_freeN(heap);
+}
+
+static void BLI_heap_down(Heap *heap, int i)
+{
+ while (1) {
+ int size = heap->size, smallest;
+ int l = HEAP_LEFT(i);
+ int r = HEAP_RIGHT(i);
+
+ smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i]))? l: i;
+
+ if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest]))
+ smallest = r;
+
+ if (smallest == i)
+ break;
+
+ HEAP_SWAP(heap, i, smallest);
+ i = smallest;
+ }
+}
+
+static void BLI_heap_up(Heap *heap, int i)
+{
+ while (i > 0) {
+ int p = HEAP_PARENT(i);
+
+ if (HEAP_COMPARE(heap->tree[p], heap->tree[i]))
+ break;
+
+ HEAP_SWAP(heap, p, i);
+ i = p;
+ }
+}
+
+HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
+{
+ HeapNode *node;
+
+ if ((heap->size + 1) > heap->bufsize) {
+ int newsize = heap->bufsize*2;
+ HeapNode **newtree;
+
+ newtree = (HeapNode**)MEM_mallocN(newsize*sizeof(*newtree), "BLIHeapTree");
+ memcpy(newtree, heap->tree, sizeof(HeapNode*)*heap->size);
+ MEM_freeN(heap->tree);
+
+ heap->tree = newtree;
+ heap->bufsize = newsize;
+ }
+
+ if (heap->freenodes) {
+ node = heap->freenodes;
+ heap->freenodes = (HeapNode*)(((HeapNode*)heap->freenodes)->ptr);
+ }
+ else
+ node = (HeapNode*)BLI_memarena_alloc(heap->arena, sizeof *node);
+
+ node->value = value;
+ node->ptr = ptr;
+ node->index = heap->size;
+
+ heap->tree[node->index] = node;
+
+ heap->size++;
+
+ BLI_heap_up(heap, heap->size-1);
+
+ return node;
+}
+
+int BLI_heap_empty(Heap *heap)
+{
+ return (heap->size == 0);
+}
+
+int BLI_heap_size(Heap *heap)
+{
+ return heap->size;
+}
+
+HeapNode *BLI_heap_top(Heap *heap)
+{
+ return heap->tree[0];
+}
+
+void *BLI_heap_popmin(Heap *heap)
+{
+ void *ptr = heap->tree[0]->ptr;
+
+ heap->tree[0]->ptr = heap->freenodes;
+ heap->freenodes = heap->tree[0];
+
+ if (heap->size == 1)
+ heap->size--;
+ else {
+ HEAP_SWAP(heap, 0, heap->size-1);
+ heap->size--;
+
+ BLI_heap_down(heap, 0);
+ }
+
+ return ptr;
+}
+
+void BLI_heap_remove(Heap *heap, HeapNode *node)
+{
+ int i = node->index;
+
+ while (i > 0) {
+ int p = HEAP_PARENT(i);
+
+ HEAP_SWAP(heap, p, i);
+ i = p;
+ }
+
+ BLI_heap_popmin(heap);
+}
+
+float BLI_heap_node_value(HeapNode *node)
+{
+ return node->value;
+}
+
+void *BLI_heap_node_ptr(HeapNode *node)
+{
+ return node->ptr;
+}
+
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
new file mode 100644
index 00000000000..6bb828a44bf
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -0,0 +1,119 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Support for linked lists.
+ */
+
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int BLI_linklist_length(LinkNode *list) {
+ if (0) {
+ return list?(1+BLI_linklist_length(list->next)):0;
+ } else {
+ int len;
+
+ for (len=0; list; list= list->next)
+ len++;
+
+ return len;
+ }
+}
+
+void BLI_linklist_reverse(LinkNode **listp) {
+ LinkNode *rhead= NULL, *cur= *listp;
+
+ while (cur) {
+ LinkNode *next= cur->next;
+
+ cur->next= rhead;
+ rhead= cur;
+
+ cur= next;
+ }
+
+ *listp= rhead;
+}
+
+void BLI_linklist_prepend(LinkNode **listp, void *ptr) {
+ LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+ nlink->link= ptr;
+
+ nlink->next= *listp;
+ *listp= nlink;
+}
+
+void BLI_linklist_append(LinkNode **listp, void *ptr) {
+ LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *node = *listp;
+
+ nlink->link = ptr;
+ nlink->next = NULL;
+
+ if(node == NULL){
+ *listp = nlink;
+ } else {
+ while(node->next != NULL){
+ node = node->next;
+ }
+ node->next = nlink;
+ }
+}
+
+void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) {
+ LinkNode *nlink= BLI_memarena_alloc(ma, sizeof(*nlink));
+ nlink->link= ptr;
+
+ nlink->next= *listp;
+ *listp= nlink;
+}
+
+void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc) {
+ while (list) {
+ LinkNode *next= list->next;
+
+ if (freefunc)
+ freefunc(list->link);
+ MEM_freeN(list);
+
+ list= next;
+ }
+}
+
+void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata) {
+ for (; list; list= list->next)
+ applyfunc(list->link, userdata);
+}
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
new file mode 100644
index 00000000000..c42ff3610fd
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -0,0 +1,96 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Efficient memory allocation for lots of similar small chunks.
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_memarena.h"
+#include "BLI_linklist.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+struct MemArena {
+ unsigned char *curbuf;
+ int bufsize, cursize;
+
+ int use_calloc;
+
+ LinkNode *bufs;
+};
+
+MemArena *BLI_memarena_new(int bufsize) {
+ MemArena *ma= MEM_callocN(sizeof(*ma), "memarena");
+ ma->bufsize= bufsize;
+
+ return ma;
+}
+
+void BLI_memarena_use_calloc(MemArena *ma) {
+ ma->use_calloc= 1;
+}
+
+void BLI_memarena_free(MemArena *ma) {
+ BLI_linklist_free(ma->bufs, (void(*)(void*)) MEM_freeN);
+ MEM_freeN(ma);
+}
+
+ /* amt must be power of two */
+#define PADUP(num, amt) ((num+(amt-1))&~(amt-1))
+
+void *BLI_memarena_alloc(MemArena *ma, int size) {
+ void *ptr;
+
+ /* ensure proper alignment by rounding
+ * size up to multiple of 8 */
+ size= PADUP(size, 8);
+
+ if (size>ma->cursize) {
+ ma->cursize= (size>ma->bufsize)?size:ma->bufsize;
+ if(ma->use_calloc)
+ ma->curbuf= MEM_callocN(ma->cursize, "memarena calloc");
+ else
+ ma->curbuf= MEM_mallocN(ma->cursize, "memarena malloc");
+
+ BLI_linklist_prepend(&ma->bufs, ma->curbuf);
+ }
+
+ ptr= ma->curbuf;
+ ma->curbuf+= size;
+ ma->cursize-= size;
+
+ return ptr;
+}
diff --git a/source/blender/blenlib/intern/BLI_scanfill.h b/source/blender/blenlib/intern/BLI_scanfill.h
new file mode 100644
index 00000000000..cc02d76ad69
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_scanfill.h
@@ -0,0 +1,41 @@
+/**
+ * blenlib/BLI_scanfill.h mar 2001 Nzc
+ *
+ * Filling meshes.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_SCANFILL_H
+#define BLI_SCANFILL_H
+
+#endif
+
diff --git a/source/blender/blenlib/intern/BLI_storage.h b/source/blender/blenlib/intern/BLI_storage.h
new file mode 100644
index 00000000000..5e9c377c410
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_storage.h
@@ -0,0 +1,41 @@
+/* $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BLI_STORAGE_H
+#define BLI_STORAGE_H
+
+#include "BLI_storage_types.h"
+
+void BLI_adddirstrings(void);
+void BLI_builddir(char *dirname, char *relname);
+int BLI_compare(struct direntry *entry1, struct direntry *entry2);
+
+#endif /* BLI_STORAGE_H */
+
diff --git a/source/blender/blenlib/intern/BLI_util.h b/source/blender/blenlib/intern/BLI_util.h
new file mode 100644
index 00000000000..b033c89a0c9
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_util.h
@@ -0,0 +1,45 @@
+/**
+ * blenlib/BLI_storage_types.h
+ *
+ * Some types for dealing with directories
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BLI_UTIL_H
+#define BLI_UTIL_H
+
+#define mallocstructN(x,y,name) (x*)MEM_mallocN((y)* sizeof(x),name)
+#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name)
+
+struct ListBase;
+
+#endif
+
diff --git a/source/blender/blenlib/intern/Makefile b/source/blender/blenlib/intern/Makefile
new file mode 100644
index 00000000000..68148a1eb37
--- /dev/null
+++ b/source/blender/blenlib/intern/Makefile
@@ -0,0 +1,61 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program 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 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program 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, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = blenlib
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+# CPPFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+# path to SDNA types
+CPPFLAGS += -I../../makesdna
+# path to our own external headerfiles
+CPPFLAGS += -I..
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+# path to freetype font stuff
+CPPFLAGS += -I$(NAN_FREETYPE)/include
+CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2
+# path to blenkernel
+CPPFLAGS += -I$(SRCHOME)/blender/blenkernel
+CPPFLAGS += -I../../include/
+# path to zlib
+CPPFLAGS += -I$(NAN_ZLIB)/include
+
+ifdef NAN_PTHREADS
+ CPPFLAGS += -I$(NAN_PTHREADS)/include
+endif
+ifeq ($(WITH_FREETYPE2), true)
+ CPPFLAGS += -DWITH_FREETYPE2
+endif
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
new file mode 100644
index 00000000000..721df3a1a0c
--- /dev/null
+++ b/source/blender/blenlib/intern/arithb.c
@@ -0,0 +1,3672 @@
+/* arithb.c
+ *
+ * simple math for blender code
+ *
+ * sort of cleaned up mar-01 nzc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* ************************ FUNKTIES **************************** */
+
+#include <math.h>
+#include <sys/types.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__)
+#include <strings.h>
+#endif
+
+#if !defined(__sgi) && !defined(WIN32)
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include "BLI_arithb.h"
+
+/* A few small defines. Keep'em local! */
+#define SMALL_NUMBER 1.e-8
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+
+#if defined(WIN32) || defined(__APPLE__)
+#include <stdlib.h>
+#define M_PI 3.14159265358979323846
+#define M_SQRT2 1.41421356237309504880
+
+#endif /* defined(WIN32) || defined(__APPLE__) */
+
+
+float saacos(float fac)
+{
+ if(fac<= -1.0f) return (float)M_PI;
+ else if(fac>=1.0f) return 0.0;
+ else return (float)acos(fac);
+}
+
+float saasin(float fac)
+{
+ if(fac<= -1.0f) return (float)-M_PI/2.0f;
+ else if(fac>=1.0f) return (float)M_PI/2.0f;
+ else return (float)asin(fac);
+}
+
+float sasqrt(float fac)
+{
+ if(fac<=0.0) return 0.0;
+ return (float)sqrt(fac);
+}
+
+float Normalize(float *n)
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ /* A larger value causes normalize errors in a scaled down models with camera xtreme close */
+ if(d>1.0e-35F) {
+ d= (float)sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+void Crossf(float *c, float *a, float *b)
+{
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+/* Inpf returns the dot product, also called the scalar product and inner product */
+float Inpf( float *v1, float *v2)
+{
+ return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
+}
+
+/* Project v1 on v2 */
+void Projf(float *c, float *v1, float *v2)
+{
+ float mul;
+ mul = Inpf(v1, v2) / Inpf(v2, v2);
+
+ c[0] = mul * v2[0];
+ c[1] = mul * v2[1];
+ c[2] = mul * v2[2];
+}
+
+void Mat3Transp(float mat[][3])
+{
+ float t;
+
+ t = mat[0][1] ;
+ mat[0][1] = mat[1][0] ;
+ mat[1][0] = t;
+ t = mat[0][2] ;
+ mat[0][2] = mat[2][0] ;
+ mat[2][0] = t;
+ t = mat[1][2] ;
+ mat[1][2] = mat[2][1] ;
+ mat[2][1] = t;
+}
+
+void Mat4Transp(float mat[][4])
+{
+ float t;
+
+ t = mat[0][1] ;
+ mat[0][1] = mat[1][0] ;
+ mat[1][0] = t;
+ t = mat[0][2] ;
+ mat[0][2] = mat[2][0] ;
+ mat[2][0] = t;
+ t = mat[0][3] ;
+ mat[0][3] = mat[3][0] ;
+ mat[3][0] = t;
+
+ t = mat[1][2] ;
+ mat[1][2] = mat[2][1] ;
+ mat[2][1] = t;
+ t = mat[1][3] ;
+ mat[1][3] = mat[3][1] ;
+ mat[3][1] = t;
+
+ t = mat[2][3] ;
+ mat[2][3] = mat[3][2] ;
+ mat[3][2] = t;
+}
+
+
+/*
+ * invertmat -
+ * computes the inverse of mat and puts it in inverse. Returns
+ * TRUE on success (i.e. can always find a pivot) and FALSE on failure.
+ * Uses Gaussian Elimination with partial (maximal column) pivoting.
+ *
+ * Mark Segal - 1992
+ */
+
+int Mat4Invert(float inverse[][4], float mat[][4])
+{
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ /* Set inverse to identity */
+ for (i=0; i<4; i++)
+ for (j=0; j<4; j++)
+ inverse[i][j] = 0;
+ for (i=0; i<4; i++)
+ inverse[i][i] = 1;
+
+ /* Copy original matrix so we don't mess it up */
+ for(i = 0; i < 4; i++)
+ for(j = 0; j <4; j++)
+ tempmat[i][j] = mat[i][j];
+
+ for(i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = ABS(tempmat[i][i]);
+ maxj = i;
+ for(j = i + 1; j < 4; j++) {
+ if(ABS(tempmat[j][i]) > max) {
+ max = ABS(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for( k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ temp = tempmat[i][i];
+ if (temp == 0)
+ return 0; /* No non-zero pivot */
+ for(k = 0; k < 4; k++) {
+ tempmat[i][k] = (float)(tempmat[i][k]/temp);
+ inverse[i][k] = (float)(inverse[i][k]/temp);
+ }
+ for(j = 0; j < 4; j++) {
+ if(j != i) {
+ temp = tempmat[j][i];
+ for(k = 0; k < 4; k++) {
+ tempmat[j][k] -= (float)(tempmat[i][k]*temp);
+ inverse[j][k] -= (float)(inverse[i][k]*temp);
+ }
+ }
+ }
+ }
+ return 1;
+}
+#ifdef TEST_ACTIVE
+void Mat4InvertSimp(float inverse[][4], float mat[][4])
+{
+ /* only for Matrices that have a rotation */
+ /* based at GG IV pag 205 */
+ float scale;
+
+ scale= mat[0][0]*mat[0][0] + mat[1][0]*mat[1][0] + mat[2][0]*mat[2][0];
+ if(scale==0.0) return;
+
+ scale= 1.0/scale;
+
+ /* transpose and scale */
+ inverse[0][0]= scale*mat[0][0];
+ inverse[1][0]= scale*mat[0][1];
+ inverse[2][0]= scale*mat[0][2];
+ inverse[0][1]= scale*mat[1][0];
+ inverse[1][1]= scale*mat[1][1];
+ inverse[2][1]= scale*mat[1][2];
+ inverse[0][2]= scale*mat[2][0];
+ inverse[1][2]= scale*mat[2][1];
+ inverse[2][2]= scale*mat[2][2];
+
+ inverse[3][0]= -(inverse[0][0]*mat[3][0] + inverse[1][0]*mat[3][1] + inverse[2][0]*mat[3][2]);
+ inverse[3][1]= -(inverse[0][1]*mat[3][0] + inverse[1][1]*mat[3][1] + inverse[2][1]*mat[3][2]);
+ inverse[3][2]= -(inverse[0][2]*mat[3][0] + inverse[1][2]*mat[3][1] + inverse[2][2]*mat[3][2]);
+
+ inverse[0][3]= inverse[1][3]= inverse[2][3]= 0.0;
+ inverse[3][3]= 1.0;
+}
+#endif
+/* struct Matrix4; */
+
+#ifdef TEST_ACTIVE
+/* this seems to be unused.. */
+
+void Mat4Inv(float *m1, float *m2)
+{
+
+/* This gets me into trouble: */
+ float mat1[3][3], mat2[3][3];
+
+/* void Mat3Inv(); */
+/* void Mat3CpyMat4(); */
+/* void Mat4CpyMat3(); */
+
+ Mat3CpyMat4((float*)mat2,m2);
+ Mat3Inv((float*)mat1, (float*) mat2);
+ Mat4CpyMat3(m1, mat1);
+
+}
+#endif
+
+
+float Det2x2(float a,float b,float c,float d)
+{
+
+ return a*d - b*c;
+}
+
+
+
+float Det3x3(float a1, float a2, float a3,
+ float b1, float b2, float b3,
+ float c1, float c2, float c3 )
+{
+ float ans;
+
+ ans = a1 * Det2x2( b2, b3, c2, c3 )
+ - b1 * Det2x2( a2, a3, c2, c3 )
+ + c1 * Det2x2( a2, a3, b2, b3 );
+
+ return ans;
+}
+
+float Det4x4(float m[][4])
+{
+ float ans;
+ float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
+
+ a1= m[0][0];
+ b1= m[0][1];
+ c1= m[0][2];
+ d1= m[0][3];
+
+ a2= m[1][0];
+ b2= m[1][1];
+ c2= m[1][2];
+ d2= m[1][3];
+
+ a3= m[2][0];
+ b3= m[2][1];
+ c3= m[2][2];
+ d3= m[2][3];
+
+ a4= m[3][0];
+ b4= m[3][1];
+ c4= m[3][2];
+ d4= m[3][3];
+
+ ans = a1 * Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
+ - b1 * Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
+ + c1 * Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
+ - d1 * Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ return ans;
+}
+
+
+void Mat4Adj(float out[][4], float in[][4]) /* out = ADJ(in) */
+{
+ float a1, a2, a3, a4, b1, b2, b3, b4;
+ float c1, c2, c3, c4, d1, d2, d3, d4;
+
+ a1= in[0][0];
+ b1= in[0][1];
+ c1= in[0][2];
+ d1= in[0][3];
+
+ a2= in[1][0];
+ b2= in[1][1];
+ c2= in[1][2];
+ d2= in[1][3];
+
+ a3= in[2][0];
+ b3= in[2][1];
+ c3= in[2][2];
+ d3= in[2][3];
+
+ a4= in[3][0];
+ b4= in[3][1];
+ c4= in[3][2];
+ d4= in[3][3];
+
+
+ out[0][0] = Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
+ out[1][0] = - Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
+ out[2][0] = Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
+ out[3][0] = - Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
+
+ out[0][1] = - Det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
+ out[1][1] = Det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
+ out[2][1] = - Det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
+ out[3][1] = Det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
+
+ out[0][2] = Det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
+ out[1][2] = - Det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
+ out[2][2] = Det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
+ out[3][2] = - Det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
+
+ out[0][3] = - Det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
+ out[1][3] = Det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
+ out[2][3] = - Det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
+ out[3][3] = Det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
+}
+
+void Mat4InvGG(float out[][4], float in[][4]) /* from Graphic Gems I, out= INV(in) */
+{
+ int i, j;
+ float det;
+
+ /* calculate the adjoint matrix */
+
+ Mat4Adj(out,in);
+
+ det = Det4x4(out);
+
+ if ( fabs( det ) < SMALL_NUMBER) {
+ return;
+ }
+
+ /* scale the adjoint matrix to get the inverse */
+
+ for (i=0; i<4; i++)
+ for(j=0; j<4; j++)
+ out[i][j] = out[i][j] / det;
+
+ /* the last factor is not always 1. For that reason an extra division should be implemented? */
+}
+
+
+void Mat3Inv(float m1[][3], float m2[][3])
+{
+ short a,b;
+ float det;
+
+ /* calc adjoint */
+ Mat3Adj(m1,m2);
+
+ /* then determinant old matrix! */
+ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
+ -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
+ +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
+
+ if(det==0) det=1;
+ det= 1/det;
+ for(a=0;a<3;a++) {
+ for(b=0;b<3;b++) {
+ m1[a][b]*=det;
+ }
+ }
+}
+
+void Mat3Adj(float m1[][3], float m[][3])
+{
+ m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1];
+ m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1];
+ m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1];
+
+ m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0];
+ m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0];
+ m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0];
+
+ m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
+ m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0];
+ m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
+}
+
+void Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4])
+{
+ /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2];
+ m1[0][3] = m2[0][0]*m3[0][3] + m2[0][1]*m3[1][3] + m2[0][2]*m3[2][3] + m2[0][3]*m3[3][3];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0] + m2[1][3]*m3[3][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1] + m2[1][3]*m3[3][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2] + m2[1][3]*m3[3][2];
+ m1[1][3] = m2[1][0]*m3[0][3] + m2[1][1]*m3[1][3] + m2[1][2]*m3[2][3] + m2[1][3]*m3[3][3];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0] + m2[2][3]*m3[3][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1] + m2[2][3]*m3[3][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2] + m2[2][3]*m3[3][2];
+ m1[2][3] = m2[2][0]*m3[0][3] + m2[2][1]*m3[1][3] + m2[2][2]*m3[2][3] + m2[2][3]*m3[3][3];
+
+ m1[3][0] = m2[3][0]*m3[0][0] + m2[3][1]*m3[1][0] + m2[3][2]*m3[2][0] + m2[3][3]*m3[3][0];
+ m1[3][1] = m2[3][0]*m3[0][1] + m2[3][1]*m3[1][1] + m2[3][2]*m3[2][1] + m2[3][3]*m3[3][1];
+ m1[3][2] = m2[3][0]*m3[0][2] + m2[3][1]*m3[1][2] + m2[3][2]*m3[2][2] + m2[3][3]*m3[3][2];
+ m1[3][3] = m2[3][0]*m3[0][3] + m2[3][1]*m3[1][3] + m2[3][2]*m3[2][3] + m2[3][3]*m3[3][3];
+
+}
+#ifdef TEST_ACTIVE
+void subMat4MulMat4(float *m1, float *m2, float *m3)
+{
+
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+ m1+=4;
+ m2+=4;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+ m1+=4;
+ m2+=4;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
+ m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
+}
+#endif
+
+#ifndef TEST_ACTIVE
+void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3])
+#else
+void Mat3MulMat3(float *m1, float *m3, float *m2)
+#endif
+{
+ /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */
+#ifndef TEST_ACTIVE
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+#else
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+ m1+=3;
+ m2+=3;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+ m1+=3;
+ m2+=3;
+ m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
+ m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
+ m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
+#endif
+} /* end of void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+
+void Mat4MulMat43(float (*m1)[4], float (*m3)[4], float (*m2)[3])
+{
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+}
+/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3*/
+void Mat3IsMat3MulMat4(float m1[][3], float m2[][3], float m3[][4])
+{
+ /* m1[i][j] = m2[i][k] * m3[k][j] */
+ m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] +m2[0][2] * m3[2][0];
+ m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] +m2[0][2] * m3[2][1];
+ m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] +m2[0][2] * m3[2][2];
+
+ m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] +m2[1][2] * m3[2][0];
+ m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] +m2[1][2] * m3[2][1];
+ m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] +m2[1][2] * m3[2][2];
+
+ m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] +m2[2][2] * m3[2][0];
+ m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] +m2[2][2] * m3[2][1];
+ m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] +m2[2][2] * m3[2][2];
+}
+
+
+
+void Mat4MulMat34(float (*m1)[4], float (*m3)[3], float (*m2)[4])
+{
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+}
+
+void Mat4CpyMat4(float m1[][4], float m2[][4])
+{
+ memcpy(m1, m2, 4*4*sizeof(float));
+}
+
+void Mat4SwapMat4(float *m1, float *m2)
+{
+ float t;
+ int i;
+
+ for(i=0;i<16;i++) {
+ t= *m1;
+ *m1= *m2;
+ *m2= t;
+ m1++;
+ m2++;
+ }
+}
+
+typedef float Mat3Row[3];
+typedef float Mat4Row[4];
+
+#ifdef TEST_ACTIVE
+void Mat3CpyMat4(float *m1p, float *m2p)
+#else
+void Mat3CpyMat4(float m1[][3], float m2[][4])
+#endif
+{
+#ifdef TEST_ACTIVE
+ int i, j;
+ Mat3Row *m1= (Mat3Row *)m1p;
+ Mat4Row *m2= (Mat4Row *)m2p;
+ for ( i = 0; i++; i < 3) {
+ for (j = 0; j++; j < 3) {
+ m1p[3*i + j] = m2p[4*i + j];
+ }
+ }
+#endif
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* Butched. See .h for comment */
+/* void Mat4CpyMat3(float m1[][4], float m2[][3]) */
+#ifdef TEST_ACTIVE
+void Mat4CpyMat3(float* m1, float *m2)
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ m1[(4*i)] = m2[(3*i)];
+ m1[(4*i) + 1]= m2[(3*i) + 1];
+ m1[(4*i) + 2]= m2[(3*i) + 2];
+ m1[(4*i) + 3]= 0.0;
+ i++;
+ }
+
+ m1[12]=m1[13]= m1[14]= 0.0;
+ m1[15]= 1.0;
+}
+#else
+
+void Mat4CpyMat3(float m1[][4], float m2[][3]) /* no clear */
+{
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+
+ /* Reevan's Bugfix */
+ m1[0][3]=0.0F;
+ m1[1][3]=0.0F;
+ m1[2][3]=0.0F;
+
+ m1[3][0]=0.0F;
+ m1[3][1]=0.0F;
+ m1[3][2]=0.0F;
+ m1[3][3]=1.0F;
+
+
+}
+#endif
+
+void Mat3CpyMat3(float m1[][3], float m2[][3])
+{
+ /* destination comes first: */
+ memcpy(&m1[0], &m2[0], 9*sizeof(float));
+}
+
+void Mat3MulSerie(float answ[][3],
+ float m1[][3], float m2[][3], float m3[][3],
+ float m4[][3], float m5[][3], float m6[][3],
+ float m7[][3], float m8[][3])
+{
+ float temp[3][3];
+
+ if(m1==0 || m2==0) return;
+
+
+ Mat3MulMat3(answ, m2, m1);
+ if(m3) {
+ Mat3MulMat3(temp, m3, answ);
+ if(m4) {
+ Mat3MulMat3(answ, m4, temp);
+ if(m5) {
+ Mat3MulMat3(temp, m5, answ);
+ if(m6) {
+ Mat3MulMat3(answ, m6, temp);
+ if(m7) {
+ Mat3MulMat3(temp, m7, answ);
+ if(m8) {
+ Mat3MulMat3(answ, m8, temp);
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+ }
+ else Mat3CpyMat3(answ, temp);
+ }
+}
+
+void Mat4MulSerie(float answ[][4], float m1[][4],
+ float m2[][4], float m3[][4], float m4[][4],
+ float m5[][4], float m6[][4], float m7[][4],
+ float m8[][4])
+{
+ float temp[4][4];
+
+ if(m1==0 || m2==0) return;
+
+ Mat4MulMat4(answ, m2, m1);
+ if(m3) {
+ Mat4MulMat4(temp, m3, answ);
+ if(m4) {
+ Mat4MulMat4(answ, m4, temp);
+ if(m5) {
+ Mat4MulMat4(temp, m5, answ);
+ if(m6) {
+ Mat4MulMat4(answ, m6, temp);
+ if(m7) {
+ Mat4MulMat4(temp, m7, answ);
+ if(m8) {
+ Mat4MulMat4(answ, m8, temp);
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+ }
+ else Mat4CpyMat4(answ, temp);
+ }
+}
+
+void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight)
+{
+ float squat[4], dquat[4], fquat[4];
+ float ssize[3], dsize[3], fsize[4];
+ float sloc[3], dloc[3], floc[3];
+
+ Mat4ToQuat(dst, dquat);
+ Mat4ToSize(dst, dsize);
+ VecCopyf(dloc, dst[3]);
+
+ Mat4ToQuat(src, squat);
+ Mat4ToSize(src, ssize);
+ VecCopyf(sloc, src[3]);
+
+ /* do blending */
+ VecLerpf(floc, dloc, sloc, srcweight);
+ QuatInterpol(fquat, dquat, squat, srcweight);
+ VecLerpf(fsize, dsize, ssize, srcweight);
+
+ /* compose new matrix */
+ LocQuatSizeToMat4(out, floc, fquat, fsize);
+}
+
+void Mat4Clr(float *m)
+{
+ memset(m, 0, 4*4*sizeof(float));
+}
+
+void Mat3Clr(float *m)
+{
+ memset(m, 0, 3*3*sizeof(float));
+}
+
+void Mat4One(float m[][4])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
+ m[0][1]= m[0][2]= m[0][3]= 0.0;
+ m[1][0]= m[1][2]= m[1][3]= 0.0;
+ m[2][0]= m[2][1]= m[2][3]= 0.0;
+ m[3][0]= m[3][1]= m[3][2]= 0.0;
+}
+
+void Mat3One(float m[][3])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= 1.0;
+ m[0][1]= m[0][2]= 0.0;
+ m[1][0]= m[1][2]= 0.0;
+ m[2][0]= m[2][1]= 0.0;
+}
+
+void Mat4MulVec( float mat[][4], int *vec)
+{
+ int x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=(int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0]);
+ vec[1]=(int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1]);
+ vec[2]=(int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]);
+}
+
+void Mat4MulVecfl( float mat[][4], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+void VecMat4MulVecfl(float *in, float mat[][4], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ in[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ in[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ in[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+void Mat4Mul3Vecfl( float mat[][4], float *vec)
+{
+ float x,y;
+
+ x= vec[0];
+ y= vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat4MulVec3Project(float mat[][4], float *vec)
+{
+ float w;
+
+ w = vec[0]*mat[0][3] + vec[1]*mat[1][3] + vec[2]*mat[2][3] + mat[3][3];
+ Mat4MulVecfl(mat, vec);
+
+ vec[0] /= w;
+ vec[1] /= w;
+ vec[2] /= w;
+}
+
+void Mat4MulVec4fl( float mat[][4], float *vec)
+{
+ float x,y,z;
+
+ x=vec[0];
+ y=vec[1];
+ z= vec[2];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3];
+ vec[3]=x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3];
+}
+
+void Mat3MulVec( float mat[][3], int *vec)
+{
+ int x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= (int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]);
+ vec[1]= (int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]);
+ vec[2]= (int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]);
+}
+
+void Mat3MulVecfl( float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat3MulVecd( float mat[][3], double *vec)
+{
+ double x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+void Mat3TransMulVecfl( float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[0][1] + mat[0][2]*vec[2];
+ vec[1]= x*mat[1][0] + y*mat[1][1] + mat[1][2]*vec[2];
+ vec[2]= x*mat[2][0] + y*mat[2][1] + mat[2][2]*vec[2];
+}
+
+void Mat3MulFloat(float *m, float f)
+{
+ int i;
+
+ for(i=0;i<9;i++) m[i]*=f;
+}
+
+void Mat4MulFloat(float *m, float f)
+{
+ int i;
+
+ for(i=0;i<16;i++) m[i]*=f; /* count to 12: without vector component */
+}
+
+
+void Mat4MulFloat3(float *m, float f) /* only scale component */
+{
+ int i,j;
+
+ for(i=0; i<3; i++) {
+ for(j=0; j<3; j++) {
+
+ m[4*i+j] *= f;
+ }
+ }
+}
+
+void Mat3AddMat3(float m1[][3], float m2[][3], float m3[][3])
+{
+ int i, j;
+
+ for(i=0;i<3;i++)
+ for(j=0;j<3;j++)
+ m1[i][j]= m2[i][j] + m3[i][j];
+}
+
+void Mat4AddMat4(float m1[][4], float m2[][4], float m3[][4])
+{
+ int i, j;
+
+ for(i=0;i<4;i++)
+ for(j=0;j<4;j++)
+ m1[i][j]= m2[i][j] + m3[i][j];
+}
+
+void VecStar(float mat[][3], float *vec)
+{
+
+ mat[0][0]= mat[1][1]= mat[2][2]= 0.0;
+ mat[0][1]= -vec[2];
+ mat[0][2]= vec[1];
+ mat[1][0]= vec[2];
+ mat[1][2]= -vec[0];
+ mat[2][0]= -vec[1];
+ mat[2][1]= vec[0];
+
+}
+#ifdef TEST_ACTIVE
+short EenheidsMat(float mat[][3])
+{
+
+ if(mat[0][0]==1.0 && mat[0][1]==0.0 && mat[0][2]==0.0)
+ if(mat[1][0]==0.0 && mat[1][1]==1.0 && mat[1][2]==0.0)
+ if(mat[2][0]==0.0 && mat[2][1]==0.0 && mat[2][2]==1.0)
+ return 1;
+ return 0;
+}
+#endif
+
+int FloatCompare( float *v1, float *v2, float limit)
+{
+
+ if( fabs(v1[0]-v2[0])<limit ) {
+ if( fabs(v1[1]-v2[1])<limit ) {
+ if( fabs(v1[2]-v2[2])<limit ) return 1;
+ }
+ }
+ return 0;
+}
+
+float FloatLerpf( float target, float origin, float fac)
+{
+ return (fac*target) + (1.0f-fac)*origin;
+}
+
+void printvecf( char *str, float v[3])
+{
+ printf("%s: %.3f %.3f %.3f\n", str, v[0], v[1], v[2]);
+
+}
+
+void printquat( char *str, float q[4])
+{
+ printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]);
+
+}
+
+void printvec4f( char *str, float v[4])
+{
+ printf("%s\n", str);
+ printf("%f %f %f %f\n",v[0],v[1],v[2], v[3]);
+ printf("\n");
+
+}
+
+void printmatrix4( char *str, float m[][4])
+{
+ printf("%s\n", str);
+ printf("%f %f %f %f\n",m[0][0],m[1][0],m[2][0],m[3][0]);
+ printf("%f %f %f %f\n",m[0][1],m[1][1],m[2][1],m[3][1]);
+ printf("%f %f %f %f\n",m[0][2],m[1][2],m[2][2],m[3][2]);
+ printf("%f %f %f %f\n",m[0][3],m[1][3],m[2][3],m[3][3]);
+ printf("\n");
+
+}
+
+void printmatrix3( char *str, float m[][3])
+{
+ printf("%s\n", str);
+ printf("%f %f %f\n",m[0][0],m[1][0],m[2][0]);
+ printf("%f %f %f\n",m[0][1],m[1][1],m[2][1]);
+ printf("%f %f %f\n",m[0][2],m[1][2],m[2][2]);
+ printf("\n");
+
+}
+
+/* **************** QUATERNIONS ********** */
+
+
+void QuatMul(float *q, float *q1, float *q2)
+{
+ float t0,t1,t2;
+
+ t0= q1[0]*q2[0]-q1[1]*q2[1]-q1[2]*q2[2]-q1[3]*q2[3];
+ t1= q1[0]*q2[1]+q1[1]*q2[0]+q1[2]*q2[3]-q1[3]*q2[2];
+ t2= q1[0]*q2[2]+q1[2]*q2[0]+q1[3]*q2[1]-q1[1]*q2[3];
+ q[3]= q1[0]*q2[3]+q1[3]*q2[0]+q1[1]*q2[2]-q1[2]*q2[1];
+ q[0]=t0;
+ q[1]=t1;
+ q[2]=t2;
+}
+
+/* Assumes a unit quaternion */
+void QuatMulVecf(float *q, float *v)
+{
+ float t0, t1, t2;
+
+ t0= -q[1]*v[0]-q[2]*v[1]-q[3]*v[2];
+ t1= q[0]*v[0]+q[2]*v[2]-q[3]*v[1];
+ t2= q[0]*v[1]+q[3]*v[0]-q[1]*v[2];
+ v[2]= q[0]*v[2]+q[1]*v[1]-q[2]*v[0];
+ v[0]=t1;
+ v[1]=t2;
+
+ t1= t0*-q[1]+v[0]*q[0]-v[1]*q[3]+v[2]*q[2];
+ t2= t0*-q[2]+v[1]*q[0]-v[2]*q[1]+v[0]*q[3];
+ v[2]= t0*-q[3]+v[2]*q[0]-v[0]*q[2]+v[1]*q[1];
+ v[0]=t1;
+ v[1]=t2;
+}
+
+void QuatConj(float *q)
+{
+ q[1] = -q[1];
+ q[2] = -q[2];
+ q[3] = -q[3];
+}
+
+float QuatDot(float *q1, float *q2)
+{
+ return q1[0]*q2[0] + q1[1]*q2[1] + q1[2]*q2[2] + q1[3]*q2[3];
+}
+
+void QuatInv(float *q)
+{
+ float f = QuatDot(q, q);
+
+ if (f == 0.0f)
+ return;
+
+ QuatConj(q);
+ QuatMulf(q, 1.0f/f);
+}
+
+void QuatMulf(float *q, float f)
+{
+ q[0] *= f;
+ q[1] *= f;
+ q[2] *= f;
+ q[3] *= f;
+}
+
+void QuatSub(float *q, float *q1, float *q2)
+{
+ q2[0]= -q2[0];
+ QuatMul(q, q1, q2);
+ q2[0]= -q2[0];
+}
+
+
+void QuatToMat3( float *q, float m[][3])
+{
+ double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
+
+ q0= M_SQRT2 * q[0];
+ q1= M_SQRT2 * q[1];
+ q2= M_SQRT2 * q[2];
+ q3= M_SQRT2 * q[3];
+
+ qda= q0*q1;
+ qdb= q0*q2;
+ qdc= q0*q3;
+ qaa= q1*q1;
+ qab= q1*q2;
+ qac= q1*q3;
+ qbb= q2*q2;
+ qbc= q2*q3;
+ qcc= q3*q3;
+
+ m[0][0]= (float)(1.0-qbb-qcc);
+ m[0][1]= (float)(qdc+qab);
+ m[0][2]= (float)(-qdb+qac);
+
+ m[1][0]= (float)(-qdc+qab);
+ m[1][1]= (float)(1.0-qaa-qcc);
+ m[1][2]= (float)(qda+qbc);
+
+ m[2][0]= (float)(qdb+qac);
+ m[2][1]= (float)(-qda+qbc);
+ m[2][2]= (float)(1.0-qaa-qbb);
+}
+
+
+void QuatToMat4( float *q, float m[][4])
+{
+ double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
+
+ q0= M_SQRT2 * q[0];
+ q1= M_SQRT2 * q[1];
+ q2= M_SQRT2 * q[2];
+ q3= M_SQRT2 * q[3];
+
+ qda= q0*q1;
+ qdb= q0*q2;
+ qdc= q0*q3;
+ qaa= q1*q1;
+ qab= q1*q2;
+ qac= q1*q3;
+ qbb= q2*q2;
+ qbc= q2*q3;
+ qcc= q3*q3;
+
+ m[0][0]= (float)(1.0-qbb-qcc);
+ m[0][1]= (float)(qdc+qab);
+ m[0][2]= (float)(-qdb+qac);
+ m[0][3]= 0.0f;
+
+ m[1][0]= (float)(-qdc+qab);
+ m[1][1]= (float)(1.0-qaa-qcc);
+ m[1][2]= (float)(qda+qbc);
+ m[1][3]= 0.0f;
+
+ m[2][0]= (float)(qdb+qac);
+ m[2][1]= (float)(-qda+qbc);
+ m[2][2]= (float)(1.0-qaa-qbb);
+ m[2][3]= 0.0f;
+
+ m[3][0]= m[3][1]= m[3][2]= 0.0f;
+ m[3][3]= 1.0f;
+}
+
+void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */
+{
+ double tr, s;
+ float mat[3][3];
+
+ /* work on a copy */
+ Mat3CpyMat3(mat, wmat);
+ Mat3Ortho(mat); /* this is needed AND a NormalQuat in the end */
+
+ tr= 0.25*(1.0+mat[0][0]+mat[1][1]+mat[2][2]);
+
+ if(tr>FLT_EPSILON) {
+ s= sqrt( tr);
+ q[0]= (float)s;
+ s*= 4.0;
+ q[1]= (float)((mat[1][2]-mat[2][1])/s);
+ q[2]= (float)((mat[2][0]-mat[0][2])/s);
+ q[3]= (float)((mat[0][1]-mat[1][0])/s);
+ }
+ else {
+ q[0]= 0.0f;
+ s= -0.5*(mat[1][1]+mat[2][2]);
+
+ if(s>FLT_EPSILON) {
+ s= sqrt(s);
+ q[1]= (float)s;
+ q[2]= (float)(mat[0][1]/(2*s));
+ q[3]= (float)(mat[0][2]/(2*s));
+ }
+ else {
+ q[1]= 0.0f;
+ s= 0.5*(1.0-mat[2][2]);
+
+ if(s>FLT_EPSILON) {
+ s= sqrt(s);
+ q[2]= (float)s;
+ q[3]= (float)(mat[1][2]/(2*s));
+ }
+ else {
+ q[2]= 0.0f;
+ q[3]= 1.0f;
+ }
+ }
+ }
+ NormalQuat(q);
+}
+
+void Mat3ToQuat_is_ok( float wmat[][3], float *q)
+{
+ float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3];
+
+ /* work on a copy */
+ Mat3CpyMat3(mat, wmat);
+ Mat3Ortho(mat);
+
+ /* rotate z-axis of matrix to z-axis */
+
+ nor[0] = mat[2][1]; /* cross product with (0,0,1) */
+ nor[1] = -mat[2][0];
+ nor[2] = 0.0;
+ Normalize(nor);
+
+ co= mat[2][2];
+ angle= 0.5f*saacos(co);
+
+ co= (float)cos(angle);
+ si= (float)sin(angle);
+ q1[0]= co;
+ q1[1]= -nor[0]*si; /* negative here, but why? */
+ q1[2]= -nor[1]*si;
+ q1[3]= -nor[2]*si;
+
+ /* rotate back x-axis from mat, using inverse q1 */
+ QuatToMat3(q1, matr);
+ Mat3Inv(matn, matr);
+ Mat3MulVecfl(matn, mat[0]);
+
+ /* and align x-axes */
+ angle= (float)(0.5*atan2(mat[0][1], mat[0][0]));
+
+ co= (float)cos(angle);
+ si= (float)sin(angle);
+ q2[0]= co;
+ q2[1]= 0.0f;
+ q2[2]= 0.0f;
+ q2[3]= si;
+
+ QuatMul(q, q1, q2);
+}
+
+
+void Mat4ToQuat( float m[][4], float *q)
+{
+ float mat[3][3];
+
+ Mat3CpyMat4(mat, m);
+ Mat3ToQuat(mat, q);
+
+}
+
+void QuatOne(float *q)
+{
+ q[0]= q[2]= q[3]= 0.0;
+ q[1]= 1.0;
+}
+
+void NormalQuat(float *q)
+{
+ float len;
+
+ len= (float)sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
+ if(len!=0.0) {
+ q[0]/= len;
+ q[1]/= len;
+ q[2]/= len;
+ q[3]/= len;
+ } else {
+ q[1]= 1.0f;
+ q[0]= q[2]= q[3]= 0.0f;
+ }
+}
+
+float *vectoquat( float *vec, short axis, short upflag)
+{
+ static float q1[4];
+ float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;
+
+ /* first rotate to axis */
+ if(axis>2) {
+ x2= vec[0] ; y2= vec[1] ; z2= vec[2];
+ axis-= 3;
+ }
+ else {
+ x2= -vec[0] ; y2= -vec[1] ; z2= -vec[2];
+ }
+
+ q1[0]=1.0;
+ q1[1]=q1[2]=q1[3]= 0.0;
+
+ len1= (float)sqrt(x2*x2+y2*y2+z2*z2);
+ if(len1 == 0.0) return(q1);
+
+ /* nasty! I need a good routine for this...
+ * problem is a rotation of an Y axis to the negative Y-axis for example.
+ */
+
+ if(axis==0) { /* x-axis */
+ nor[0]= 0.0;
+ nor[1]= -z2;
+ nor[2]= y2;
+
+ if( fabs(y2)+fabs(z2)<0.0001 ) {
+ nor[1]= 1.0;
+ }
+
+ co= x2;
+ }
+ else if(axis==1) { /* y-axis */
+ nor[0]= z2;
+ nor[1]= 0.0;
+ nor[2]= -x2;
+
+ if( fabs(x2)+fabs(z2)<0.0001 ) {
+ nor[2]= 1.0;
+ }
+
+ co= y2;
+ }
+ else { /* z-axis */
+ nor[0]= -y2;
+ nor[1]= x2;
+ nor[2]= 0.0;
+
+ if( fabs(x2)+fabs(y2)<0.0001 ) {
+ nor[0]= 1.0;
+ }
+
+ co= z2;
+ }
+ co/= len1;
+
+ Normalize(nor);
+
+ angle= 0.5f*saacos(co);
+ si= (float)sin(angle);
+ q1[0]= (float)cos(angle);
+ q1[1]= nor[0]*si;
+ q1[2]= nor[1]*si;
+ q1[3]= nor[2]*si;
+
+ if(axis!=upflag) {
+ QuatToMat3(q1, mat);
+
+ fp= mat[2];
+ if(axis==0) {
+ if(upflag==1) angle= (float)(0.5*atan2(fp[2], fp[1]));
+ else angle= (float)(-0.5*atan2(fp[1], fp[2]));
+ }
+ else if(axis==1) {
+ if(upflag==0) angle= (float)(-0.5*atan2(fp[2], fp[0]));
+ else angle= (float)(0.5*atan2(fp[0], fp[2]));
+ }
+ else {
+ if(upflag==0) angle= (float)(0.5*atan2(-fp[1], -fp[0]));
+ else angle= (float)(-0.5*atan2(-fp[0], -fp[1]));
+ }
+
+ co= (float)cos(angle);
+ si= (float)(sin(angle)/len1);
+ q2[0]= co;
+ q2[1]= x2*si;
+ q2[2]= y2*si;
+ q2[3]= z2*si;
+
+ QuatMul(q1,q2,q1);
+ }
+
+ return(q1);
+}
+
+void VecUpMat3old( float *vec, float mat[][3], short axis)
+{
+ float inp, up[3];
+ short cox = 0, coy = 0, coz = 0;
+
+ /* using different up's is not useful, infact there is no real 'up'!
+ */
+
+ up[0]= 0.0;
+ up[1]= 0.0;
+ up[2]= 1.0;
+
+ if(axis==0) {
+ cox= 0; coy= 1; coz= 2; /* Y up Z tr */
+ }
+ if(axis==1) {
+ cox= 1; coy= 2; coz= 0; /* Z up X tr */
+ }
+ if(axis==2) {
+ cox= 2; coy= 0; coz= 1; /* X up Y tr */
+ }
+ if(axis==3) {
+ cox= 0; coy= 2; coz= 1; /* */
+ }
+ if(axis==4) {
+ cox= 1; coy= 0; coz= 2; /* */
+ }
+ if(axis==5) {
+ cox= 2; coy= 1; coz= 0; /* Y up X tr */
+ }
+
+ mat[coz][0]= vec[0];
+ mat[coz][1]= vec[1];
+ mat[coz][2]= vec[2];
+ Normalize((float *)mat[coz]);
+
+ inp= mat[coz][0]*up[0] + mat[coz][1]*up[1] + mat[coz][2]*up[2];
+ mat[coy][0]= up[0] - inp*mat[coz][0];
+ mat[coy][1]= up[1] - inp*mat[coz][1];
+ mat[coy][2]= up[2] - inp*mat[coz][2];
+
+ Normalize((float *)mat[coy]);
+
+ Crossf(mat[cox], mat[coy], mat[coz]);
+
+}
+
+void VecUpMat3(float *vec, float mat[][3], short axis)
+{
+ float inp;
+ short cox = 0, coy = 0, coz = 0;
+
+ /* using different up's is not useful, infact there is no real 'up'!
+ */
+
+ if(axis==0) {
+ cox= 0; coy= 1; coz= 2; /* Y up Z tr */
+ }
+ if(axis==1) {
+ cox= 1; coy= 2; coz= 0; /* Z up X tr */
+ }
+ if(axis==2) {
+ cox= 2; coy= 0; coz= 1; /* X up Y tr */
+ }
+ if(axis==3) {
+ cox= 0; coy= 1; coz= 2; /* Y op -Z tr */
+ vec[0]= -vec[0];
+ vec[1]= -vec[1];
+ vec[2]= -vec[2];
+ }
+ if(axis==4) {
+ cox= 1; coy= 0; coz= 2; /* */
+ }
+ if(axis==5) {
+ cox= 2; coy= 1; coz= 0; /* Y up X tr */
+ }
+
+ mat[coz][0]= vec[0];
+ mat[coz][1]= vec[1];
+ mat[coz][2]= vec[2];
+ Normalize((float *)mat[coz]);
+
+ inp= mat[coz][2];
+ mat[coy][0]= - inp*mat[coz][0];
+ mat[coy][1]= - inp*mat[coz][1];
+ mat[coy][2]= 1.0f - inp*mat[coz][2];
+
+ Normalize((float *)mat[coy]);
+
+ Crossf(mat[cox], mat[coy], mat[coz]);
+
+}
+
+/* A & M Watt, Advanced animation and rendering techniques, 1992 ACM press */
+void QuatInterpolW(float *, float *, float *, float );
+
+void QuatInterpolW(float *result, float *quat1, float *quat2, float t)
+{
+ float omega, cosom, sinom, sc1, sc2;
+
+ cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ;
+
+ /* rotate around shortest angle */
+ if ((1.0 + cosom) > 0.0001) {
+
+ if ((1.0 - cosom) > 0.0001) {
+ omega = acos(cosom);
+ sinom = sin(omega);
+ sc1 = sin((1.0 - t) * omega) / sinom;
+ sc2 = sin(t * omega) / sinom;
+ }
+ else {
+ sc1 = 1.0 - t;
+ sc2 = t;
+ }
+ result[0] = sc1*quat1[0] + sc2*quat2[0];
+ result[1] = sc1*quat1[1] + sc2*quat2[1];
+ result[2] = sc1*quat1[2] + sc2*quat2[2];
+ result[3] = sc1*quat1[3] + sc2*quat2[3];
+ }
+ else {
+ result[0] = quat2[3];
+ result[1] = -quat2[2];
+ result[2] = quat2[1];
+ result[3] = -quat2[0];
+
+ sc1 = sin((1.0 - t)*M_PI_2);
+ sc2 = sin(t*M_PI_2);
+
+ result[0] = sc1*quat1[0] + sc2*result[0];
+ result[1] = sc1*quat1[1] + sc2*result[1];
+ result[2] = sc1*quat1[2] + sc2*result[2];
+ result[3] = sc1*quat1[3] + sc2*result[3];
+ }
+}
+
+void QuatInterpol(float *result, float *quat1, float *quat2, float t)
+{
+ float quat[4], omega, cosom, sinom, sc1, sc2;
+
+ cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ;
+
+ /* rotate around shortest angle */
+ if (cosom < 0.0) {
+ cosom = -cosom;
+ quat[0]= -quat1[0];
+ quat[1]= -quat1[1];
+ quat[2]= -quat1[2];
+ quat[3]= -quat1[3];
+ }
+ else {
+ quat[0]= quat1[0];
+ quat[1]= quat1[1];
+ quat[2]= quat1[2];
+ quat[3]= quat1[3];
+ }
+
+ if ((1.0 - cosom) > 0.0001) {
+ omega = acos(cosom);
+ sinom = sin(omega);
+ sc1 = sin((1 - t) * omega) / sinom;
+ sc2 = sin(t * omega) / sinom;
+ } else {
+ sc1= 1.0 - t;
+ sc2= t;
+ }
+
+ result[0] = sc1 * quat[0] + sc2 * quat2[0];
+ result[1] = sc1 * quat[1] + sc2 * quat2[1];
+ result[2] = sc1 * quat[2] + sc2 * quat2[2];
+ result[3] = sc1 * quat[3] + sc2 * quat2[3];
+}
+
+void QuatAdd(float *result, float *quat1, float *quat2, float t)
+{
+ result[0]= quat1[0] + t*quat2[0];
+ result[1]= quat1[1] + t*quat2[1];
+ result[2]= quat1[2] + t*quat2[2];
+ result[3]= quat1[3] + t*quat2[3];
+}
+
+void QuatCopy(float *q1, float *q2)
+{
+ q1[0]= q2[0];
+ q1[1]= q2[1];
+ q1[2]= q2[2];
+ q1[3]= q2[3];
+}
+
+/* **************** DUAL QUATERNIONS ************** */
+
+/*
+ Conversion routines between (regular quaternion, translation) and
+ dual quaternion.
+
+ Version 1.0.0, February 7th, 2007
+
+ Copyright (C) 2006-2007 University of Dublin, Trinity College, All Rights
+ Reserved
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the author(s) be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Author: Ladislav Kavan, kavanl@cs.tcd.ie
+
+ Changes for Blender:
+ - renaming, style changes and optimizations
+ - added support for scaling
+*/
+
+void Mat4ToDQuat(float basemat[][4], float mat[][4], DualQuat *dq)
+{
+ float *t, *q, dscale[3], scale[3], basequat[4];
+ float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4];
+ float R[4][4], S[4][4];
+
+ /* split scaling and rotation, there is probably a faster way to do
+ this, it's done like this now to correctly get negative scaling */
+ Mat4MulMat4(baseRS, basemat, mat);
+ Mat4ToSize(baseRS, scale);
+
+ VecCopyf(dscale, scale);
+ dscale[0] -= 1.0f; dscale[1] -= 1.0f; dscale[2] -= 1.0f;
+
+ if((Det4x4(mat) < 0.0f) || VecLength(dscale) > 1e-4) {
+ /* extract R and S */
+ Mat4ToQuat(baseRS, basequat);
+ QuatToMat4(basequat, baseR);
+ VecCopyf(baseR[3], baseRS[3]);
+
+ Mat4Invert(baseinv, basemat);
+ Mat4MulMat4(R, baseinv, baseR);
+
+ Mat4Invert(baseRinv, baseR);
+ Mat4MulMat4(S, baseRS, baseRinv);
+
+ /* set scaling part */
+ Mat4MulSerie(dq->scale, basemat, S, baseinv, 0, 0, 0, 0, 0);
+ dq->scale_weight= 1.0f;
+ }
+ else {
+ /* matrix does not contain scaling */
+ Mat4CpyMat4(R, mat);
+ dq->scale_weight= 0.0f;
+ }
+
+ /* non-dual part */
+ Mat4ToQuat(R, dq->quat);
+
+ /* dual part */
+ t= R[3];
+ q= dq->quat;
+ dq->trans[0]= -0.5f*( t[0]*q[1] + t[1]*q[2] + t[2]*q[3]);
+ dq->trans[1]= 0.5f*( t[0]*q[0] + t[1]*q[3] - t[2]*q[2]);
+ dq->trans[2]= 0.5f*(-t[0]*q[3] + t[1]*q[0] + t[2]*q[1]);
+ dq->trans[3]= 0.5f*( t[0]*q[2] - t[1]*q[1] + t[2]*q[0]);
+}
+
+void DQuatToMat4(DualQuat *dq, float mat[][4])
+{
+ float len, *t, q0[4];
+
+ /* regular quaternion */
+ QuatCopy(q0, dq->quat);
+
+ /* normalize */
+ len= sqrt(QuatDot(q0, q0));
+ if(len != 0.0f)
+ QuatMulf(q0, 1.0f/len);
+
+ /* rotation */
+ QuatToMat4(q0, mat);
+
+ /* translation */
+ t= dq->trans;
+ mat[3][0]= 2.0*(-t[0]*q0[1] + t[1]*q0[0] - t[2]*q0[3] + t[3]*q0[2]);
+ mat[3][1]= 2.0*(-t[0]*q0[2] + t[1]*q0[3] + t[2]*q0[0] - t[3]*q0[1]);
+ mat[3][2]= 2.0*(-t[0]*q0[3] - t[1]*q0[2] + t[2]*q0[1] + t[3]*q0[0]);
+
+ /* note: this does not handle scaling */
+}
+
+void DQuatAddWeighted(DualQuat *dqsum, DualQuat *dq, float weight)
+{
+ /* make sure we interpolate quats in the right direction */
+ if (QuatDot(dq->quat, dqsum->quat) < 0)
+ weight = -weight;
+
+ /* interpolate rotation and translation */
+ dqsum->quat[0] += weight*dq->quat[0];
+ dqsum->quat[1] += weight*dq->quat[1];
+ dqsum->quat[2] += weight*dq->quat[2];
+ dqsum->quat[3] += weight*dq->quat[3];
+
+ dqsum->trans[0] += weight*dq->trans[0];
+ dqsum->trans[1] += weight*dq->trans[1];
+ dqsum->trans[2] += weight*dq->trans[2];
+ dqsum->trans[3] += weight*dq->trans[3];
+
+ /* interpolate scale - but only if needed */
+ if (dq->scale_weight) {
+ float wmat[4][4];
+
+ Mat4CpyMat4(wmat, dq->scale);
+ Mat4MulFloat((float*)wmat, weight);
+ Mat4AddMat4(dqsum->scale, dqsum->scale, wmat);
+ dqsum->scale_weight += weight;
+ }
+}
+
+void DQuatNormalize(DualQuat *dq, float totweight, float factor)
+{
+ float scale= factor/totweight;
+
+ QuatMulf(dq->quat, scale);
+ QuatMulf(dq->trans, scale);
+
+ if(dq->scale_weight) {
+ float addweight= totweight - dq->scale_weight;
+
+ if(addweight) {
+ dq->scale[0][0] += addweight;
+ dq->scale[1][1] += addweight;
+ dq->scale[2][2] += addweight;
+ dq->scale[3][3] += addweight;
+ }
+
+ Mat4MulFloat((float*)dq->scale, scale);
+ dq->scale_weight= 1.0f;
+ }
+}
+
+void DQuatMulVecfl(DualQuat *dq, float *co, float mat[][3])
+{
+ float M[3][3], t[3], scalemat[3][3], len2;
+ float w= dq->quat[0], x= dq->quat[1], y= dq->quat[2], z= dq->quat[3];
+ float t0= dq->trans[0], t1= dq->trans[1], t2= dq->trans[2], t3= dq->trans[3];
+
+ /* rotation matrix */
+ M[0][0]= w*w + x*x - y*y - z*z;
+ M[1][0]= 2*(x*y - w*z);
+ M[2][0]= 2*(x*z + w*y);
+
+ M[0][1]= 2*(x*y + w*z);
+ M[1][1]= w*w + y*y - x*x - z*z;
+ M[2][1]= 2*(y*z - w*x);
+
+ M[0][2]= 2*(x*z - w*y);
+ M[1][2]= 2*(y*z + w*x);
+ M[2][2]= w*w + z*z - x*x - y*y;
+
+ len2= QuatDot(dq->quat, dq->quat);
+ if(len2 > 0.0f)
+ len2= 1.0f/len2;
+
+ /* translation */
+ t[0]= 2*(-t0*x + w*t1 - t2*z + y*t3);
+ t[1]= 2*(-t0*y + t1*z - x*t3 + w*t2);
+ t[2]= 2*(-t0*z + x*t2 + w*t3 - t1*y);
+
+ /* apply scaling */
+ if(dq->scale_weight)
+ Mat4MulVecfl(dq->scale, co);
+
+ /* apply rotation and translation */
+ Mat3MulVecfl(M, co);
+ co[0]= (co[0] + t[0])*len2;
+ co[1]= (co[1] + t[1])*len2;
+ co[2]= (co[2] + t[2])*len2;
+
+ /* compute crazyspace correction mat */
+ if(mat) {
+ if(dq->scale_weight) {
+ Mat3CpyMat4(scalemat, dq->scale);
+ Mat3MulMat3(mat, M, scalemat);
+ }
+ else
+ Mat3CpyMat3(mat, M);
+ Mat3MulFloat((float*)mat, len2);
+ }
+}
+
+void DQuatCpyDQuat(DualQuat *dq1, DualQuat *dq2)
+{
+ memcpy(dq1, dq2, sizeof(DualQuat));
+}
+
+/* **************** VIEW / PROJECTION ******************************** */
+
+
+void i_ortho(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float matrix[][4]
+){
+ float Xdelta, Ydelta, Zdelta;
+
+ Xdelta = right - left;
+ Ydelta = top - bottom;
+ Zdelta = farClip - nearClip;
+ if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
+ return;
+ }
+ Mat4One(matrix);
+ matrix[0][0] = 2.0f/Xdelta;
+ matrix[3][0] = -(right + left)/Xdelta;
+ matrix[1][1] = 2.0f/Ydelta;
+ matrix[3][1] = -(top + bottom)/Ydelta;
+ matrix[2][2] = -2.0f/Zdelta; /* note: negate Z */
+ matrix[3][2] = -(farClip + nearClip)/Zdelta;
+}
+
+void i_window(
+ float left, float right,
+ float bottom, float top,
+ float nearClip, float farClip,
+ float mat[][4]
+){
+ float Xdelta, Ydelta, Zdelta;
+
+ Xdelta = right - left;
+ Ydelta = top - bottom;
+ Zdelta = farClip - nearClip;
+
+ if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
+ return;
+ }
+ mat[0][0] = nearClip * 2.0f/Xdelta;
+ mat[1][1] = nearClip * 2.0f/Ydelta;
+ mat[2][0] = (right + left)/Xdelta; /* note: negate Z */
+ mat[2][1] = (top + bottom)/Ydelta;
+ mat[2][2] = -(farClip + nearClip)/Zdelta;
+ mat[2][3] = -1.0f;
+ mat[3][2] = (-2.0f * nearClip * farClip)/Zdelta;
+ mat[0][1] = mat[0][2] = mat[0][3] =
+ mat[1][0] = mat[1][2] = mat[1][3] =
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
+
+}
+
+void i_translate(float Tx, float Ty, float Tz, float mat[][4])
+{
+ mat[3][0] += (Tx*mat[0][0] + Ty*mat[1][0] + Tz*mat[2][0]);
+ mat[3][1] += (Tx*mat[0][1] + Ty*mat[1][1] + Tz*mat[2][1]);
+ mat[3][2] += (Tx*mat[0][2] + Ty*mat[1][2] + Tz*mat[2][2]);
+}
+
+void i_multmatrix( float icand[][4], float Vm[][4])
+{
+ int row, col;
+ float temp[4][4];
+
+ for(row=0 ; row<4 ; row++)
+ for(col=0 ; col<4 ; col++)
+ temp[row][col] = icand[row][0] * Vm[0][col]
+ + icand[row][1] * Vm[1][col]
+ + icand[row][2] * Vm[2][col]
+ + icand[row][3] * Vm[3][col];
+ Mat4CpyMat4(Vm, temp);
+}
+
+void i_rotate(float angle, char axis, float mat[][4])
+{
+ int col;
+ float temp[4];
+ float cosine, sine;
+
+ for(col=0; col<4 ; col++) /* init temp to zero matrix */
+ temp[col] = 0;
+
+ angle = (float)(angle*(3.1415926535/180.0));
+ cosine = (float)cos(angle);
+ sine = (float)sin(angle);
+ switch(axis){
+ case 'x':
+ case 'X':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[1][col] + sine*mat[2][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col];
+ mat[1][col] = temp[col];
+ }
+ break;
+
+ case 'y':
+ case 'Y':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[0][col] - sine*mat[2][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[2][col] = sine*mat[0][col] + cosine*mat[2][col];
+ mat[0][col] = temp[col];
+ }
+ break;
+
+ case 'z':
+ case 'Z':
+ for(col=0 ; col<4 ; col++)
+ temp[col] = cosine*mat[0][col] + sine*mat[1][col];
+ for(col=0 ; col<4 ; col++) {
+ mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col];
+ mat[0][col] = temp[col];
+ }
+ break;
+ }
+}
+
+void i_polarview(float dist, float azimuth, float incidence, float twist, float Vm[][4])
+{
+
+ Mat4One(Vm);
+
+ i_translate(0.0, 0.0, -dist, Vm);
+ i_rotate(-twist,'z', Vm);
+ i_rotate(-incidence,'x', Vm);
+ i_rotate(-azimuth,'z', Vm);
+}
+
+void i_lookat(float vx, float vy, float vz, float px, float py, float pz, float twist, float mat[][4])
+{
+ float sine, cosine, hyp, hyp1, dx, dy, dz;
+ float mat1[4][4];
+
+ Mat4One(mat);
+ Mat4One(mat1);
+
+ i_rotate(-twist,'z', mat);
+
+ dx = px - vx;
+ dy = py - vy;
+ dz = pz - vz;
+ hyp = dx * dx + dz * dz; /* hyp squared */
+ hyp1 = (float)sqrt(dy*dy + hyp);
+ hyp = (float)sqrt(hyp); /* the real hyp */
+
+ if (hyp1 != 0.0) { /* rotate X */
+ sine = -dy / hyp1;
+ cosine = hyp /hyp1;
+ } else {
+ sine = 0;
+ cosine = 1.0f;
+ }
+ mat1[1][1] = cosine;
+ mat1[1][2] = sine;
+ mat1[2][1] = -sine;
+ mat1[2][2] = cosine;
+
+ i_multmatrix(mat1, mat);
+
+ mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
+ mat1[1][2] = mat1[2][1] = 0.0; /* those modified by the last */
+
+ /* paragraph */
+ if (hyp != 0.0f) { /* rotate Y */
+ sine = dx / hyp;
+ cosine = -dz / hyp;
+ } else {
+ sine = 0;
+ cosine = 1.0f;
+ }
+ mat1[0][0] = cosine;
+ mat1[0][2] = -sine;
+ mat1[2][0] = sine;
+ mat1[2][2] = cosine;
+
+ i_multmatrix(mat1, mat);
+ i_translate(-vx,-vy,-vz, mat); /* translate viewpoint to origin */
+}
+
+
+
+
+
+/* ************************************************ */
+
+void Mat3Ortho(float mat[][3])
+{
+ Normalize(mat[0]);
+ Normalize(mat[1]);
+ Normalize(mat[2]);
+}
+
+void Mat4Ortho(float mat[][4])
+{
+ float len;
+
+ len= Normalize(mat[0]);
+ if(len!=0.0) mat[0][3]/= len;
+ len= Normalize(mat[1]);
+ if(len!=0.0) mat[1][3]/= len;
+ len= Normalize(mat[2]);
+ if(len!=0.0) mat[2][3]/= len;
+}
+
+void VecCopyf(float *v1, float *v2)
+{
+ v1[0]= v2[0];
+ v1[1]= v2[1];
+ v1[2]= v2[2];
+}
+
+int VecLen( int *v1, int *v2)
+{
+ float x,y,z;
+
+ x=(float)(v1[0]-v2[0]);
+ y=(float)(v1[1]-v2[1]);
+ z=(float)(v1[2]-v2[2]);
+ return (int)floor(sqrt(x*x+y*y+z*z));
+}
+
+float VecLenf( float *v1, float *v2)
+{
+ float x,y,z;
+
+ x=v1[0]-v2[0];
+ y=v1[1]-v2[1];
+ z=v1[2]-v2[2];
+ return (float)sqrt(x*x+y*y+z*z);
+}
+
+float VecLength(float *v)
+{
+ return (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+}
+
+void VecAddf(float *v, float *v1, float *v2)
+{
+ v[0]= v1[0]+ v2[0];
+ v[1]= v1[1]+ v2[1];
+ v[2]= v1[2]+ v2[2];
+}
+
+void VecSubf(float *v, float *v1, float *v2)
+{
+ v[0]= v1[0]- v2[0];
+ v[1]= v1[1]- v2[1];
+ v[2]= v1[2]- v2[2];
+}
+
+void VecLerpf(float *target, float *a, float *b, float t)
+{
+ float s = 1.0f-t;
+
+ target[0]= s*a[0] + t*b[0];
+ target[1]= s*a[1] + t*b[1];
+ target[2]= s*a[2] + t*b[2];
+}
+
+void VecMidf(float *v, float *v1, float *v2)
+{
+ v[0]= 0.5f*(v1[0]+ v2[0]);
+ v[1]= 0.5f*(v1[1]+ v2[1]);
+ v[2]= 0.5f*(v1[2]+ v2[2]);
+}
+
+void VecMulf(float *v1, float f)
+{
+
+ v1[0]*= f;
+ v1[1]*= f;
+ v1[2]*= f;
+}
+
+void VecOrthoBasisf(float *v, float *v1, float *v2)
+{
+ if (v[0] == 0.0f && v[1] == 0.0f)
+ {
+ // degenerate case
+ v1[0] = 0.0f; v1[1] = 1.0f; v1[2] = 0.0f;
+ if (v[2] > 0.0f) {
+ v2[0] = 1.0f; v2[1] = v2[2] = 0.0f;
+ }
+ else {
+ v2[0] = -1.0f; v2[1] = v2[2] = 0.0f;
+ }
+ }
+ else
+ {
+ float f = 1.0f/sqrt(v[0]*v[0] + v[1]*v[1]);
+ v1[0] = v[1]*f;
+ v1[1] = -v[0]*f;
+ v1[2] = 0.0f;
+
+ Crossf(v2, v, v1);
+ }
+}
+
+int VecLenCompare(float *v1, float *v2, float limit)
+{
+ float x,y,z;
+
+ x=v1[0]-v2[0];
+ y=v1[1]-v2[1];
+ z=v1[2]-v2[2];
+
+ return ((x*x + y*y + z*z) < (limit*limit));
+}
+
+int VecCompare( float *v1, float *v2, float limit)
+{
+ if( fabs(v1[0]-v2[0])<limit )
+ if( fabs(v1[1]-v2[1])<limit )
+ if( fabs(v1[2]-v2[2])<limit ) return 1;
+ return 0;
+}
+
+int VecEqual(float *v1, float *v2)
+{
+ return ((v1[0]==v2[0]) && (v1[1]==v2[1]) && (v1[2]==v2[2]));
+}
+
+void CalcNormShort( short *v1, short *v2, short *v3, float *n) /* is also cross product */
+{
+ float n1[3],n2[3];
+
+ n1[0]= (float)(v1[0]-v2[0]);
+ n2[0]= (float)(v2[0]-v3[0]);
+ n1[1]= (float)(v1[1]-v2[1]);
+ n2[1]= (float)(v2[1]-v3[1]);
+ n1[2]= (float)(v1[2]-v2[2]);
+ n2[2]= (float)(v2[2]-v3[2]);
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ Normalize(n);
+}
+
+void CalcNormLong( int* v1, int*v2, int*v3, float *n)
+{
+ float n1[3],n2[3];
+
+ n1[0]= (float)(v1[0]-v2[0]);
+ n2[0]= (float)(v2[0]-v3[0]);
+ n1[1]= (float)(v1[1]-v2[1]);
+ n2[1]= (float)(v2[1]-v3[1]);
+ n1[2]= (float)(v1[2]-v2[2]);
+ n2[2]= (float)(v2[2]-v3[2]);
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ Normalize(n);
+}
+
+float CalcNormFloat( float *v1, float *v2, float *v3, float *n)
+{
+ float n1[3],n2[3];
+
+ n1[0]= v1[0]-v2[0];
+ n2[0]= v2[0]-v3[0];
+ n1[1]= v1[1]-v2[1];
+ n2[1]= v2[1]-v3[1];
+ n1[2]= v1[2]-v2[2];
+ n2[2]= v2[2]-v3[2];
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+ return Normalize(n);
+}
+
+float CalcNormFloat4( float *v1, float *v2, float *v3, float *v4, float *n)
+{
+ /* real cross! */
+ float n1[3],n2[3];
+
+ n1[0]= v1[0]-v3[0];
+ n1[1]= v1[1]-v3[1];
+ n1[2]= v1[2]-v3[2];
+
+ n2[0]= v2[0]-v4[0];
+ n2[1]= v2[1]-v4[1];
+ n2[2]= v2[2]-v4[2];
+
+ n[0]= n1[1]*n2[2]-n1[2]*n2[1];
+ n[1]= n1[2]*n2[0]-n1[0]*n2[2];
+ n[2]= n1[0]*n2[1]-n1[1]*n2[0];
+
+ return Normalize(n);
+}
+
+
+void CalcCent3f(float *cent, float *v1, float *v2, float *v3)
+{
+
+ cent[0]= 0.33333f*(v1[0]+v2[0]+v3[0]);
+ cent[1]= 0.33333f*(v1[1]+v2[1]+v3[1]);
+ cent[2]= 0.33333f*(v1[2]+v2[2]+v3[2]);
+}
+
+void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4)
+{
+
+ cent[0]= 0.25f*(v1[0]+v2[0]+v3[0]+v4[0]);
+ cent[1]= 0.25f*(v1[1]+v2[1]+v3[1]+v4[1]);
+ cent[2]= 0.25f*(v1[2]+v2[2]+v3[2]+v4[2]);
+}
+
+float Sqrt3f(float f)
+{
+ if(f==0.0) return 0;
+ if(f<0) return (float)(-exp(log(-f)/3));
+ else return (float)(exp(log(f)/3));
+}
+
+double Sqrt3d(double d)
+{
+ if(d==0.0) return 0;
+ if(d<0) return -exp(log(-d)/3);
+ else return exp(log(d)/3);
+}
+
+/* distance v1 to line v2-v3 */
+/* using Hesse formula, NO LINE PIECE! */
+float DistVL2Dfl( float *v1, float *v2, float *v3) {
+ float a[2],deler;
+
+ a[0]= v2[1]-v3[1];
+ a[1]= v3[0]-v2[0];
+ deler= (float)sqrt(a[0]*a[0]+a[1]*a[1]);
+ if(deler== 0.0f) return 0;
+
+ return (float)(fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler);
+
+}
+
+/* distance v1 to line-piece v2-v3 */
+float PdistVL2Dfl( float *v1, float *v2, float *v3)
+{
+ float labda, rc[2], pt[2], len;
+
+ rc[0]= v3[0]-v2[0];
+ rc[1]= v3[1]-v2[1];
+ len= rc[0]*rc[0]+ rc[1]*rc[1];
+ if(len==0.0) {
+ rc[0]= v1[0]-v2[0];
+ rc[1]= v1[1]-v2[1];
+ return (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1]));
+ }
+
+ labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
+ if(labda<=0.0) {
+ pt[0]= v2[0];
+ pt[1]= v2[1];
+ }
+ else if(labda>=1.0) {
+ pt[0]= v3[0];
+ pt[1]= v3[1];
+ }
+ else {
+ pt[0]= labda*rc[0]+v2[0];
+ pt[1]= labda*rc[1]+v2[1];
+ }
+
+ rc[0]= pt[0]-v1[0];
+ rc[1]= pt[1]-v1[1];
+ return (float)sqrt(rc[0]*rc[0]+ rc[1]*rc[1]);
+}
+
+float AreaF2Dfl( float *v1, float *v2, float *v3)
+{
+ return (float)(0.5*fabs( (v1[0]-v2[0])*(v2[1]-v3[1]) + (v1[1]-v2[1])*(v3[0]-v2[0]) ));
+}
+
+
+float AreaQ3Dfl( float *v1, float *v2, float *v3, float *v4) /* only convex Quadrilaterals */
+{
+ float len, vec1[3], vec2[3], n[3];
+
+ VecSubf(vec1, v2, v1);
+ VecSubf(vec2, v4, v1);
+ Crossf(n, vec1, vec2);
+ len= Normalize(n);
+
+ VecSubf(vec1, v4, v3);
+ VecSubf(vec2, v2, v3);
+ Crossf(n, vec1, vec2);
+ len+= Normalize(n);
+
+ return (len/2.0f);
+}
+
+float AreaT3Dfl( float *v1, float *v2, float *v3) /* Triangles */
+{
+ float len, vec1[3], vec2[3], n[3];
+
+ VecSubf(vec1, v3, v2);
+ VecSubf(vec2, v1, v2);
+ Crossf(n, vec1, vec2);
+ len= Normalize(n);
+
+ return (len/2.0f);
+}
+
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
+#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
+
+
+float AreaPoly3Dfl(int nr, float *verts, float *normal)
+{
+ float x, y, z, area, max;
+ float *cur, *prev;
+ int a, px=0, py=1;
+
+ /* first: find dominant axis: 0==X, 1==Y, 2==Z */
+ x= (float)fabs(normal[0]);
+ y= (float)fabs(normal[1]);
+ z= (float)fabs(normal[2]);
+ max = MAX3(x, y, z);
+ if(max==y) py=2;
+ else if(max==x) {
+ px=1;
+ py= 2;
+ }
+
+ /* The Trapezium Area Rule */
+ prev= verts+3*(nr-1);
+ cur= verts;
+ area= 0;
+ for(a=0; a<nr; a++) {
+ area+= (cur[px]-prev[px])*(cur[py]+prev[py]);
+ prev= cur;
+ cur+=3;
+ }
+
+ return (float)fabs(0.5*area/max);
+}
+
+/* intersect Line-Line, shorts */
+short IsectLL2Ds(short *v1, short *v2, short *v3, short *v4)
+{
+ /* return:
+ -1: colliniar
+ 0: no intersection of segments
+ 1: exact intersection of segments
+ 2: cross-intersection of segments
+ */
+ float div, labda, mu;
+
+ div= (v2[0]-v1[0])*(v4[1]-v3[1])-(v2[1]-v1[1])*(v4[0]-v3[0]);
+ if(div==0.0) return -1;
+
+ labda= ((float)(v1[1]-v3[1])*(v4[0]-v3[0])-(v1[0]-v3[0])*(v4[1]-v3[1]))/div;
+
+ mu= ((float)(v1[1]-v3[1])*(v2[0]-v1[0])-(v1[0]-v3[0])*(v2[1]-v1[1]))/div;
+
+ if(labda>=0.0 && labda<=1.0 && mu>=0.0 && mu<=1.0) {
+ if(labda==0.0 || labda==1.0 || mu==0.0 || mu==1.0) return 1;
+ return 2;
+ }
+ return 0;
+}
+
+/* intersect Line-Line, floats */
+short IsectLL2Df(float *v1, float *v2, float *v3, float *v4)
+{
+ /* return:
+ -1: colliniar
+0: no intersection of segments
+1: exact intersection of segments
+2: cross-intersection of segments
+ */
+ float div, labda, mu;
+
+ div= (v2[0]-v1[0])*(v4[1]-v3[1])-(v2[1]-v1[1])*(v4[0]-v3[0]);
+ if(div==0.0) return -1;
+
+ labda= ((float)(v1[1]-v3[1])*(v4[0]-v3[0])-(v1[0]-v3[0])*(v4[1]-v3[1]))/div;
+
+ mu= ((float)(v1[1]-v3[1])*(v2[0]-v1[0])-(v1[0]-v3[0])*(v2[1]-v1[1]))/div;
+
+ if(labda>=0.0 && labda<=1.0 && mu>=0.0 && mu<=1.0) {
+ if(labda==0.0 || labda==1.0 || mu==0.0 || mu==1.0) return 1;
+ return 2;
+ }
+ return 0;
+}
+
+void MinMax3(float *min, float *max, float *vec)
+{
+ if(min[0]>vec[0]) min[0]= vec[0];
+ if(min[1]>vec[1]) min[1]= vec[1];
+ if(min[2]>vec[2]) min[2]= vec[2];
+
+ if(max[0]<vec[0]) max[0]= vec[0];
+ if(max[1]<vec[1]) max[1]= vec[1];
+ if(max[2]<vec[2]) max[2]= vec[2];
+}
+
+static float TriSignedArea(float *v1, float *v2, float *v3, int i, int j)
+{
+ return 0.5f*((v1[i]-v2[i])*(v2[j]-v3[j]) + (v1[j]-v2[j])*(v3[i]-v2[i]));
+}
+
+static int BarycentricWeights(float *v1, float *v2, float *v3, float *co, float *n, float *w)
+{
+ float xn, yn, zn, a1, a2, a3, asum;
+ short i, j;
+
+ /* find best projection of face XY, XZ or YZ: barycentric weights of
+ the 2d projected coords are the same and faster to compute */
+ xn= fabs(n[0]);
+ yn= fabs(n[1]);
+ zn= fabs(n[2]);
+ if(zn>=xn && zn>=yn) {i= 0; j= 1;}
+ else if(yn>=xn && yn>=zn) {i= 0; j= 2;}
+ else {i= 1; j= 2;}
+
+ a1= TriSignedArea(v2, v3, co, i, j);
+ a2= TriSignedArea(v3, v1, co, i, j);
+ a3= TriSignedArea(v1, v2, co, i, j);
+
+ asum= a1 + a2 + a3;
+
+ if (fabs(asum) < FLT_EPSILON) {
+ /* zero area triangle */
+ w[0]= w[1]= w[2]= 1.0f/3.0f;
+ return 1;
+ }
+
+ asum= 1.0f/asum;
+ w[0]= a1*asum;
+ w[1]= a2*asum;
+ w[2]= a3*asum;
+
+ return 0;
+}
+
+void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, float *w)
+{
+ float w2[3];
+
+ w[0]= w[1]= w[2]= w[3]= 0.0f;
+
+ /* first check for exact match */
+ if(VecEqual(co, v1))
+ w[0]= 1.0f;
+ else if(VecEqual(co, v2))
+ w[1]= 1.0f;
+ else if(VecEqual(co, v3))
+ w[2]= 1.0f;
+ else if(v4 && VecEqual(co, v4))
+ w[3]= 1.0f;
+ else {
+ /* otherwise compute barycentric interpolation weights */
+ float n1[3], n2[3], n[3];
+ int degenerate;
+
+ VecSubf(n1, v1, v3);
+ if (v4) {
+ VecSubf(n2, v2, v4);
+ }
+ else {
+ VecSubf(n2, v2, v3);
+ }
+ Crossf(n, n1, n2);
+
+ /* OpenGL seems to split this way, so we do too */
+ if (v4) {
+ degenerate= BarycentricWeights(v1, v2, v4, co, n, w);
+ SWAP(float, w[2], w[3]);
+
+ if(degenerate || (w[0] < 0.0f)) {
+ /* if w[1] is negative, co is on the other side of the v1-v3 edge,
+ so we interpolate using the other triangle */
+ degenerate= BarycentricWeights(v2, v3, v4, co, n, w2);
+
+ if(!degenerate) {
+ w[0]= 0.0f;
+ w[1]= w2[0];
+ w[2]= w2[1];
+ w[3]= w2[2];
+ }
+ }
+ }
+ else
+ BarycentricWeights(v1, v2, v3, co, n, w);
+ }
+}
+
+/* Mean value weights - smooth interpolation weights for polygons with
+ * more than 3 vertices */
+static float MeanValueHalfTan(float *v1, float *v2, float *v3)
+{
+ float d2[3], d3[3], cross[3], area, dot, len;
+
+ VecSubf(d2, v2, v1);
+ VecSubf(d3, v3, v1);
+ Crossf(cross, d2, d3);
+
+ area= VecLength(cross);
+ dot= Inpf(d2, d3);
+ len= VecLength(d2)*VecLength(d3);
+
+ if(area == 0.0f)
+ return 0.0f;
+ else
+ return (len - dot)/area;
+}
+
+void MeanValueWeights(float v[][3], int n, float *co, float *w)
+{
+ float totweight, t1, t2, len, *vmid, *vprev, *vnext;
+ int i;
+
+ totweight= 0.0f;
+
+ for(i=0; i<n; i++) {
+ vmid= v[i];
+ vprev= (i == 0)? v[n-1]: v[i-1];
+ vnext= (i == n-1)? v[0]: v[i+1];
+
+ t1= MeanValueHalfTan(co, vprev, vmid);
+ t2= MeanValueHalfTan(co, vmid, vnext);
+
+ len= VecLenf(co, vmid);
+ w[i]= (t1+t2)/len;
+ totweight += w[i];
+ }
+
+ if(totweight != 0.0f)
+ for(i=0; i<n; i++)
+ w[i] /= totweight;
+}
+
+
+/* ************ EULER *************** */
+
+void EulToMat3( float *eul, float mat[][3])
+{
+ double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ci = cos(eul[0]);
+ cj = cos(eul[1]);
+ ch = cos(eul[2]);
+ si = sin(eul[0]);
+ sj = sin(eul[1]);
+ sh = sin(eul[2]);
+ cc = ci*ch;
+ cs = ci*sh;
+ sc = si*ch;
+ ss = si*sh;
+
+ mat[0][0] = (float)(cj*ch);
+ mat[1][0] = (float)(sj*sc-cs);
+ mat[2][0] = (float)(sj*cc+ss);
+ mat[0][1] = (float)(cj*sh);
+ mat[1][1] = (float)(sj*ss+cc);
+ mat[2][1] = (float)(sj*cs-sc);
+ mat[0][2] = (float)-sj;
+ mat[1][2] = (float)(cj*si);
+ mat[2][2] = (float)(cj*ci);
+
+}
+
+void EulToMat4( float *eul,float mat[][4])
+{
+ double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ci = cos(eul[0]);
+ cj = cos(eul[1]);
+ ch = cos(eul[2]);
+ si = sin(eul[0]);
+ sj = sin(eul[1]);
+ sh = sin(eul[2]);
+ cc = ci*ch;
+ cs = ci*sh;
+ sc = si*ch;
+ ss = si*sh;
+
+ mat[0][0] = (float)(cj*ch);
+ mat[1][0] = (float)(sj*sc-cs);
+ mat[2][0] = (float)(sj*cc+ss);
+ mat[0][1] = (float)(cj*sh);
+ mat[1][1] = (float)(sj*ss+cc);
+ mat[2][1] = (float)(sj*cs-sc);
+ mat[0][2] = (float)-sj;
+ mat[1][2] = (float)(cj*si);
+ mat[2][2] = (float)(cj*ci);
+
+
+ mat[3][0]= mat[3][1]= mat[3][2]= mat[0][3]= mat[1][3]= mat[2][3]= 0.0f;
+ mat[3][3]= 1.0f;
+}
+
+/* returns two euler calculation methods, so we can pick the best */
+static void mat3_to_eul2(float tmat[][3], float *eul1, float *eul2)
+{
+ float cy, quat[4], mat[3][3];
+
+ Mat3ToQuat(tmat, quat);
+ QuatToMat3(quat, mat);
+ Mat3CpyMat3(mat, tmat);
+ Mat3Ortho(mat);
+
+ cy = (float)sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]);
+
+ if (cy > 16.0*FLT_EPSILON) {
+
+ eul1[0] = (float)atan2(mat[1][2], mat[2][2]);
+ eul1[1] = (float)atan2(-mat[0][2], cy);
+ eul1[2] = (float)atan2(mat[0][1], mat[0][0]);
+
+ eul2[0] = (float)atan2(-mat[1][2], -mat[2][2]);
+ eul2[1] = (float)atan2(-mat[0][2], -cy);
+ eul2[2] = (float)atan2(-mat[0][1], -mat[0][0]);
+
+ } else {
+ eul1[0] = (float)atan2(-mat[2][1], mat[1][1]);
+ eul1[1] = (float)atan2(-mat[0][2], cy);
+ eul1[2] = 0.0f;
+
+ VecCopyf(eul2, eul1);
+ }
+}
+
+void Mat3ToEul(float tmat[][3], float *eul)
+{
+ float eul1[3], eul2[3];
+
+ mat3_to_eul2(tmat, eul1, eul2);
+
+ /* return best, which is just the one with lowest values it in */
+ if( fabs(eul1[0])+fabs(eul1[1])+fabs(eul1[2]) > fabs(eul2[0])+fabs(eul2[1])+fabs(eul2[2])) {
+ VecCopyf(eul, eul2);
+ }
+ else {
+ VecCopyf(eul, eul1);
+ }
+}
+
+void Mat4ToEul(float tmat[][4], float *eul)
+{
+ float tempMat[3][3];
+
+ Mat3CpyMat4 (tempMat, tmat);
+ Mat3Ortho(tempMat);
+ Mat3ToEul(tempMat, eul);
+}
+
+void QuatToEul( float *quat, float *eul)
+{
+ float mat[3][3];
+
+ QuatToMat3(quat, mat);
+ Mat3ToEul(mat, eul);
+}
+
+
+void EulToQuat( float *eul, float *quat)
+{
+ float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+
+ ti = eul[0]*0.5f; tj = eul[1]*0.5f; th = eul[2]*0.5f;
+ ci = (float)cos(ti); cj = (float)cos(tj); ch = (float)cos(th);
+ si = (float)sin(ti); sj = (float)sin(tj); sh = (float)sin(th);
+ cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
+
+ quat[0] = cj*cc + sj*ss;
+ quat[1] = cj*sc - sj*cs;
+ quat[2] = cj*ss + sj*cc;
+ quat[3] = cj*cs - sj*sc;
+}
+
+void VecRotToMat3( float *vec, float phi, float mat[][3])
+{
+ /* rotation of phi radials around vec */
+ float vx, vx2, vy, vy2, vz, vz2, co, si;
+
+ vx= vec[0];
+ vy= vec[1];
+ vz= vec[2];
+ vx2= vx*vx;
+ vy2= vy*vy;
+ vz2= vz*vz;
+ co= (float)cos(phi);
+ si= (float)sin(phi);
+
+ mat[0][0]= vx2+co*(1.0f-vx2);
+ mat[0][1]= vx*vy*(1.0f-co)+vz*si;
+ mat[0][2]= vz*vx*(1.0f-co)-vy*si;
+ mat[1][0]= vx*vy*(1.0f-co)-vz*si;
+ mat[1][1]= vy2+co*(1.0f-vy2);
+ mat[1][2]= vy*vz*(1.0f-co)+vx*si;
+ mat[2][0]= vz*vx*(1.0f-co)+vy*si;
+ mat[2][1]= vy*vz*(1.0f-co)-vx*si;
+ mat[2][2]= vz2+co*(1.0f-vz2);
+
+}
+
+void VecRotToMat4( float *vec, float phi, float mat[][4])
+{
+ float tmat[3][3];
+
+ VecRotToMat3(vec, phi, tmat);
+ Mat4One(mat);
+ Mat4CpyMat3(mat, tmat);
+}
+
+void VecRotToQuat( float *vec, float phi, float *quat)
+{
+ /* rotation of phi radials around vec */
+ float si;
+
+ quat[1]= vec[0];
+ quat[2]= vec[1];
+ quat[3]= vec[2];
+
+ if( Normalize(quat+1) == 0.0) {
+ QuatOne(quat);
+ }
+ else {
+ quat[0]= (float)cos( phi/2.0 );
+ si= (float)sin( phi/2.0 );
+ quat[1] *= si;
+ quat[2] *= si;
+ quat[3] *= si;
+ }
+}
+
+/* Return the angle in degrees between vecs 1-2 and 2-3 in degrees
+ If v1 is a shoulder, v2 is the elbow and v3 is the hand,
+ this would return the angle at the elbow */
+float VecAngle3(float *v1, float *v2, float *v3)
+{
+ float vec1[3], vec2[3];
+
+ VecSubf(vec1, v2, v1);
+ VecSubf(vec2, v2, v3);
+ Normalize(vec1);
+ Normalize(vec2);
+
+ return NormalizedVecAngle2(vec1, vec2) * 180.0/M_PI;
+}
+
+/* Return the shortest angle in degrees between the 2 vectors */
+float VecAngle2(float *v1, float *v2)
+{
+ float vec1[3], vec2[3];
+
+ VecCopyf(vec1, v1);
+ VecCopyf(vec2, v2);
+ Normalize(vec1);
+ Normalize(vec2);
+
+ return NormalizedVecAngle2(vec1, vec2)* 180.0/M_PI;
+}
+
+float NormalizedVecAngle2(float *v1, float *v2)
+{
+ /* this is the same as acos(Inpf(v1, v2)), but more accurate */
+ if (Inpf(v1, v2) < 0.0f) {
+ float vec[3];
+
+ vec[0]= -v2[0];
+ vec[1]= -v2[1];
+ vec[2]= -v2[2];
+
+ return (float)M_PI - 2.0f*saasin(VecLenf(vec, v1)/2.0f);
+ }
+ else
+ return 2.0f*saasin(VecLenf(v2, v1)/2.0);
+}
+
+void euler_rot(float *beul, float ang, char axis)
+{
+ float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
+
+ eul[0]= eul[1]= eul[2]= 0.0;
+ if(axis=='x') eul[0]= ang;
+ else if(axis=='y') eul[1]= ang;
+ else eul[2]= ang;
+
+ EulToMat3(eul, mat1);
+ EulToMat3(beul, mat2);
+
+ Mat3MulMat3(totmat, mat2, mat1);
+
+ Mat3ToEul(totmat, beul);
+
+}
+
+/* exported to transform.c */
+void compatible_eul(float *eul, float *oldrot)
+{
+ float dx, dy, dz;
+
+ /* correct differences of about 360 degrees first */
+
+ dx= eul[0] - oldrot[0];
+ dy= eul[1] - oldrot[1];
+ dz= eul[2] - oldrot[2];
+
+ while( fabs(dx) > 5.1) {
+ if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
+ dx= eul[0] - oldrot[0];
+ }
+ while( fabs(dy) > 5.1) {
+ if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
+ dy= eul[1] - oldrot[1];
+ }
+ while( fabs(dz) > 5.1 ) {
+ if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
+ dz= eul[2] - oldrot[2];
+ }
+
+ /* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */
+ if( fabs(dx) > 3.2 && fabs(dy)<1.6 && fabs(dz)<1.6 ) {
+ if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
+ }
+ if( fabs(dy) > 3.2 && fabs(dz)<1.6 && fabs(dx)<1.6 ) {
+ if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
+ }
+ if( fabs(dz) > 3.2 && fabs(dx)<1.6 && fabs(dy)<1.6 ) {
+ if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
+ }
+
+ /* the method below was there from ancient days... but why! probably because the code sucks :)
+ */
+#if 0
+ /* calc again */
+ dx= eul[0] - oldrot[0];
+ dy= eul[1] - oldrot[1];
+ dz= eul[2] - oldrot[2];
+
+ /* special case, tested for x-z */
+
+ if( (fabs(dx) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dz) > 3.1 ) ) {
+ if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
+ if(eul[1] > 0.0) eul[1]= M_PI - eul[1]; else eul[1]= -M_PI - eul[1];
+ if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
+
+ }
+ else if( (fabs(dx) > 3.1 && fabs(dy) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dy) > 3.1 ) ) {
+ if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
+ if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
+ if(eul[2] > 0.0) eul[2]= M_PI - eul[2]; else eul[2]= -M_PI - eul[2];
+ }
+ else if( (fabs(dy) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dy) > 1.5 && fabs(dz) > 3.1 ) ) {
+ if(eul[0] > 0.0) eul[0]= M_PI - eul[0]; else eul[0]= -M_PI - eul[0];
+ if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
+ if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
+ }
+#endif
+}
+
+/* uses 2 methods to retrieve eulers, and picks the closest */
+void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot)
+{
+ float eul1[3], eul2[3];
+ float d1, d2;
+
+ mat3_to_eul2(mat, eul1, eul2);
+
+ compatible_eul(eul1, oldrot);
+ compatible_eul(eul2, oldrot);
+
+ d1= fabs(eul1[0]-oldrot[0]) + fabs(eul1[1]-oldrot[1]) + fabs(eul1[2]-oldrot[2]);
+ d2= fabs(eul2[0]-oldrot[0]) + fabs(eul2[1]-oldrot[1]) + fabs(eul2[2]-oldrot[2]);
+
+ /* return best, which is just the one with lowest difference */
+ if( d1 > d2) {
+ VecCopyf(eul, eul2);
+ }
+ else {
+ VecCopyf(eul, eul1);
+ }
+
+}
+
+/* ******************************************** */
+
+void SizeToMat3( float *size, float mat[][3])
+{
+ mat[0][0]= size[0];
+ mat[0][1]= 0.0;
+ mat[0][2]= 0.0;
+ mat[1][1]= size[1];
+ mat[1][0]= 0.0;
+ mat[1][2]= 0.0;
+ mat[2][2]= size[2];
+ mat[2][1]= 0.0;
+ mat[2][0]= 0.0;
+}
+
+void SizeToMat4( float *size, float mat[][4])
+{
+ float tmat[3][3];
+
+ SizeToMat3(size, tmat);
+ Mat4One(mat);
+ Mat4CpyMat3(mat, tmat);
+}
+
+void Mat3ToSize( float mat[][3], float *size)
+{
+ size[0]= VecLength(mat[0]);
+ size[1]= VecLength(mat[1]);
+ size[2]= VecLength(mat[2]);
+}
+
+void Mat4ToSize( float mat[][4], float *size)
+{
+ size[0]= VecLength(mat[0]);
+ size[1]= VecLength(mat[1]);
+ size[2]= VecLength(mat[2]);
+}
+
+/* this gets the average scale of a matrix, only use when your scaling
+ * data that has no idea of scale axis, examples are bone-envelope-radius
+ * and curve radius */
+float Mat3ToScalef(float mat[][3])
+{
+ /* unit length vector */
+ float unit_vec[3] = {0.577350269189626, 0.577350269189626, 0.577350269189626};
+ Mat3MulVecfl(mat, unit_vec);
+ return VecLength(unit_vec);
+}
+
+float Mat4ToScalef(float mat[][4])
+{
+ float tmat[3][3];
+ Mat3CpyMat4(tmat, mat);
+ return Mat3ToScalef(tmat);
+}
+
+
+/* ************* SPECIALS ******************* */
+
+void triatoquat( float *v1, float *v2, float *v3, float *quat)
+{
+ /* imaginary x-axis, y-axis triangle is being rotated */
+ float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3];
+
+ /* move z-axis to face-normal */
+ CalcNormFloat(v1, v2, v3, vec);
+
+ n[0]= vec[1];
+ n[1]= -vec[0];
+ n[2]= 0.0;
+ Normalize(n);
+
+ if(n[0]==0.0 && n[1]==0.0) n[0]= 1.0;
+
+ angle= -0.5f*saacos(vec[2]);
+ co= (float)cos(angle);
+ si= (float)sin(angle);
+ q1[0]= co;
+ q1[1]= n[0]*si;
+ q1[2]= n[1]*si;
+ q1[3]= 0.0f;
+
+ /* rotate back line v1-v2 */
+ QuatToMat3(q1, mat);
+ Mat3Inv(imat, mat);
+ VecSubf(vec, v2, v1);
+ Mat3MulVecfl(imat, vec);
+
+ /* what angle has this line with x-axis? */
+ vec[2]= 0.0;
+ Normalize(vec);
+
+ angle= (float)(0.5*atan2(vec[1], vec[0]));
+ co= (float)cos(angle);
+ si= (float)sin(angle);
+ q2[0]= co;
+ q2[1]= 0.0f;
+ q2[2]= 0.0f;
+ q2[3]= si;
+
+ QuatMul(quat, q1, q2);
+}
+
+void MinMaxRGB(short c[])
+{
+ if(c[0]>255) c[0]=255;
+ else if(c[0]<0) c[0]=0;
+ if(c[1]>255) c[1]=255;
+ else if(c[1]<0) c[1]=0;
+ if(c[2]>255) c[2]=255;
+ else if(c[2]<0) c[2]=0;
+}
+
+float Vec2Lenf(float *v1, float *v2)
+{
+ float x, y;
+
+ x = v1[0]-v2[0];
+ y = v1[1]-v2[1];
+ return (float)sqrt(x*x+y*y);
+}
+
+void Vec2Mulf(float *v1, float f)
+{
+ v1[0]*= f;
+ v1[1]*= f;
+}
+
+void Vec2Addf(float *v, float *v1, float *v2)
+{
+ v[0]= v1[0]+ v2[0];
+ v[1]= v1[1]+ v2[1];
+}
+
+void Vec2Subf(float *v, float *v1, float *v2)
+{
+ v[0]= v1[0]- v2[0];
+ v[1]= v1[1]- v2[1];
+}
+
+void Vec2Copyf(float *v1, float *v2)
+{
+ v1[0]= v2[0];
+ v1[1]= v2[1];
+}
+
+float Inp2f(float *v1, float *v2)
+{
+ return v1[0]*v2[0]+v1[1]*v2[1];
+}
+
+float Normalize2(float *n)
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1];
+
+ if(d>1.0e-35F) {
+ d= (float)sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ } else {
+ n[0]=n[1]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
+{
+ int i;
+ float f, p, q, t;
+
+ h *= 360.0f;
+
+ if(s==0.0) {
+ *r = v;
+ *g = v;
+ *b = v;
+ }
+ else {
+ if(h==360) h = 0;
+
+ h /= 60;
+ i = (int)floor(h);
+ f = h - i;
+ p = v*(1.0f-s);
+ q = v*(1.0f-(s*f));
+ t = v*(1.0f-(s*(1.0f-f)));
+
+ switch (i) {
+ case 0 :
+ *r = v;
+ *g = t;
+ *b = p;
+ break;
+ case 1 :
+ *r = q;
+ *g = v;
+ *b = p;
+ break;
+ case 2 :
+ *r = p;
+ *g = v;
+ *b = t;
+ break;
+ case 3 :
+ *r = p;
+ *g = q;
+ *b = v;
+ break;
+ case 4 :
+ *r = t;
+ *g = p;
+ *b = v;
+ break;
+ case 5 :
+ *r = v;
+ *g = p;
+ *b = q;
+ break;
+ }
+ }
+}
+
+void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
+{
+ float y, u, v;
+ y= 0.299*r + 0.587*g + 0.114*b;
+ u=-0.147*r - 0.289*g + 0.436*b;
+ v= 0.615*r - 0.515*g - 0.100*b;
+
+ *ly=y;
+ *lu=u;
+ *lv=v;
+}
+
+void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
+{
+ float r, g, b;
+ r=y+1.140*v;
+ g=y-0.394*u - 0.581*v;
+ b=y+2.032*u;
+
+ *lr=r;
+ *lg=g;
+ *lb=b;
+}
+
+void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr)
+{
+ float sr,sg, sb;
+ float y, cr, cb;
+
+ sr=255.0*r;
+ sg=255.0*g;
+ sb=255.0*b;
+
+
+ y=(0.257*sr)+(0.504*sg)+(0.098*sb)+16.0;
+ cb=(-0.148*sr)-(0.291*sg)+(0.439*sb)+128.0;
+ cr=(0.439*sr)-(0.368*sg)-(0.071*sb)+128.0;
+
+ *ly=y;
+ *lcb=cb;
+ *lcr=cr;
+}
+
+void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb)
+{
+ float r,g,b;
+
+ r=1.164*(y-16)+1.596*(cr-128);
+ g=1.164*(y-16)-0.813*(cr-128)-0.392*(cb-128);
+ b=1.164*(y-16)+2.017*(cb-128);
+
+ *lr=r/255.0;
+ *lg=g/255.0;
+ *lb=b/255.0;
+}
+
+void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
+{
+ unsigned int ri, gi, bi;
+
+ if (hexcol[0] == '#') hexcol++;
+
+ if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi)) {
+ *r = ri / 255.0;
+ *g = gi / 255.0;
+ *b = bi / 255.0;
+ }
+}
+
+void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
+{
+ float h, s, v;
+ float cmax, cmin, cdelta;
+ float rc, gc, bc;
+
+ cmax = r;
+ cmin = r;
+ cmax = (g>cmax ? g:cmax);
+ cmin = (g<cmin ? g:cmin);
+ cmax = (b>cmax ? b:cmax);
+ cmin = (b<cmin ? b:cmin);
+
+ v = cmax; /* value */
+ if (cmax!=0.0)
+ s = (cmax - cmin)/cmax;
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+ if (s == 0.0)
+ h = -1.0;
+ else {
+ cdelta = cmax-cmin;
+ rc = (cmax-r)/cdelta;
+ gc = (cmax-g)/cdelta;
+ bc = (cmax-b)/cdelta;
+ if (r==cmax)
+ h = bc-gc;
+ else
+ if (g==cmax)
+ h = 2.0f+rc-bc;
+ else
+ h = 4.0f+gc-rc;
+ h = h*60.0f;
+ if (h<0.0f)
+ h += 360.0f;
+ }
+
+ *ls = s;
+ *lh = h/360.0f;
+ if( *lh < 0.0) *lh= 0.0;
+ *lv = v;
+}
+
+
+/* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
+ for that reason it is sensitive for endianness... with this function it works correctly
+*/
+
+unsigned int hsv_to_cpack(float h, float s, float v)
+{
+ short r, g, b;
+ float rf, gf, bf;
+ unsigned int col;
+
+ hsv_to_rgb(h, s, v, &rf, &gf, &bf);
+
+ r= (short)(rf*255.0f);
+ g= (short)(gf*255.0f);
+ b= (short)(bf*255.0f);
+
+ col= ( r + (g*256) + (b*256*256) );
+ return col;
+}
+
+
+unsigned int rgb_to_cpack(float r, float g, float b)
+{
+ int ir, ig, ib;
+
+ ir= (int)floor(255.0*r);
+ if(ir<0) ir= 0; else if(ir>255) ir= 255;
+ ig= (int)floor(255.0*g);
+ if(ig<0) ig= 0; else if(ig>255) ig= 255;
+ ib= (int)floor(255.0*b);
+ if(ib<0) ib= 0; else if(ib>255) ib= 255;
+
+ return (ir+ (ig*256) + (ib*256*256));
+}
+
+void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
+{
+
+ *r= (float)((col)&0xFF);
+ *r /= 255.0f;
+
+ *g= (float)(((col)>>8)&0xFF);
+ *g /= 255.0f;
+
+ *b= (float)(((col)>>16)&0xFF);
+ *b /= 255.0f;
+}
+
+
+/* *************** PROJECTIONS ******************* */
+
+void tubemap(float x, float y, float z, float *u, float *v)
+{
+ float len;
+
+ *v = (z + 1.0) / 2.0;
+
+ len= sqrt(x*x+y*y);
+ if(len>0) {
+ *u = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void spheremap(float x, float y, float z, float *u, float *v)
+{
+ float len;
+
+ len= sqrt(x*x+y*y+z*z);
+ if(len>0.0) {
+
+ if(x==0.0 && y==0.0) *u= 0.0; /* othwise domain error */
+ else *u = (1.0 - atan2(x,y)/M_PI )/2.0;
+
+ z/=len;
+ *v = 1.0- saacos(z)/M_PI;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* ***************** m1 = m2 ***************** */
+void cpy_m3_m3(float m1[][3], float m2[][3])
+{
+ memcpy(m1[0], m2[0], 9*sizeof(float));
+}
+
+/* ***************** m1 = m2 ***************** */
+void cpy_m4_m4(float m1[][4], float m2[][4])
+{
+ memcpy(m1[0], m2[0], 16*sizeof(float));
+}
+
+/* ***************** identity matrix ***************** */
+void ident_m4(float m[][4])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
+ m[0][1]= m[0][2]= m[0][3]= 0.0;
+ m[1][0]= m[1][2]= m[1][3]= 0.0;
+ m[2][0]= m[2][1]= m[2][3]= 0.0;
+ m[3][0]= m[3][1]= m[3][2]= 0.0;
+}
+
+
+/* ***************** m1 = m2 (pre) * m3 (post) ***************** */
+void mul_m3_m3m3(float m1[][3], float m2[][3], float m3[][3])
+{
+ float m[3][3];
+
+ m[0][0]= m2[0][0]*m3[0][0] + m2[1][0]*m3[0][1] + m2[2][0]*m3[0][2];
+ m[0][1]= m2[0][1]*m3[0][0] + m2[1][1]*m3[0][1] + m2[2][1]*m3[0][2];
+ m[0][2]= m2[0][2]*m3[0][0] + m2[1][2]*m3[0][1] + m2[2][2]*m3[0][2];
+
+ m[1][0]= m2[0][0]*m3[1][0] + m2[1][0]*m3[1][1] + m2[2][0]*m3[1][2];
+ m[1][1]= m2[0][1]*m3[1][0] + m2[1][1]*m3[1][1] + m2[2][1]*m3[1][2];
+ m[1][2]= m2[0][2]*m3[1][0] + m2[1][2]*m3[1][1] + m2[2][2]*m3[1][2];
+
+ m[2][0]= m2[0][0]*m3[2][0] + m2[1][0]*m3[2][1] + m2[2][0]*m3[2][2];
+ m[2][1]= m2[0][1]*m3[2][0] + m2[1][1]*m3[2][1] + m2[2][1]*m3[2][2];
+ m[2][2]= m2[0][2]*m3[2][0] + m2[1][2]*m3[2][1] + m2[2][2]*m3[2][2];
+
+ cpy_m3_m3(m1, m2);
+}
+
+/* ***************** m1 = m2 (pre) * m3 (post) ***************** */
+void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4])
+{
+ float m[4][4];
+
+ m[0][0]= m2[0][0]*m3[0][0] + m2[1][0]*m3[0][1] + m2[2][0]*m3[0][2] + m2[3][0]*m3[0][3];
+ m[0][1]= m2[0][1]*m3[0][0] + m2[1][1]*m3[0][1] + m2[2][1]*m3[0][2] + m2[3][1]*m3[0][3];
+ m[0][2]= m2[0][2]*m3[0][0] + m2[1][2]*m3[0][1] + m2[2][2]*m3[0][2] + m2[3][2]*m3[0][3];
+ m[0][3]= m2[0][3]*m3[0][0] + m2[1][3]*m3[0][1] + m2[2][3]*m3[0][2] + m2[3][3]*m3[0][3];
+
+ m[1][0]= m2[0][0]*m3[1][0] + m2[1][0]*m3[1][1] + m2[2][0]*m3[1][2] + m2[3][0]*m3[1][3];
+ m[1][1]= m2[0][1]*m3[1][0] + m2[1][1]*m3[1][1] + m2[2][1]*m3[1][2] + m2[3][1]*m3[1][3];
+ m[1][2]= m2[0][2]*m3[1][0] + m2[1][2]*m3[1][1] + m2[2][2]*m3[1][2] + m2[3][2]*m3[1][3];
+ m[1][3]= m2[0][3]*m3[1][0] + m2[1][3]*m3[1][1] + m2[2][3]*m3[1][2] + m2[3][3]*m3[1][3];
+
+ m[2][0]= m2[0][0]*m3[2][0] + m2[1][0]*m3[2][1] + m2[2][0]*m3[2][2] + m2[3][0]*m3[2][3];
+ m[2][1]= m2[0][1]*m3[2][0] + m2[1][1]*m3[2][1] + m2[2][1]*m3[2][2] + m2[3][1]*m3[2][3];
+ m[2][2]= m2[0][2]*m3[2][0] + m2[1][2]*m3[2][1] + m2[2][2]*m3[2][2] + m2[3][2]*m3[2][3];
+ m[2][3]= m2[0][3]*m3[2][0] + m2[1][3]*m3[2][1] + m2[2][3]*m3[2][2] + m2[3][3]*m3[2][3];
+
+ m[3][0]= m2[0][0]*m3[3][0] + m2[1][0]*m3[3][1] + m2[2][0]*m3[3][2] + m2[3][0]*m3[3][3];
+ m[3][1]= m2[0][1]*m3[3][0] + m2[1][1]*m3[3][1] + m2[2][1]*m3[3][2] + m2[3][1]*m3[3][3];
+ m[3][2]= m2[0][2]*m3[3][0] + m2[1][2]*m3[3][1] + m2[2][2]*m3[3][2] + m2[3][2]*m3[3][3];
+ m[3][3]= m2[0][3]*m3[3][0] + m2[1][3]*m3[3][1] + m2[2][3]*m3[3][2] + m2[3][3]*m3[3][3];
+
+ cpy_m4_m4(m1, m2);
+}
+
+/* ***************** m1 = inverse(m2) ***************** */
+void inv_m3_m3(float m1[][3], float m2[][3])
+{
+ short a,b;
+ float det;
+
+ /* calc adjoint */
+ Mat3Adj(m1, m2);
+
+ /* then determinant old matrix! */
+ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
+ -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
+ +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
+
+ if(det==0.0f) det=1.0f;
+ det= 1.0f/det;
+ for(a=0;a<3;a++) {
+ for(b=0;b<3;b++) {
+ m1[a][b]*=det;
+ }
+ }
+}
+
+/* ***************** m1 = inverse(m2) ***************** */
+int inv_m4_m4(float inverse[][4], float mat[][4])
+{
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ /* Set inverse to identity */
+ ident_m4(inverse);
+
+ /* Copy original matrix so we don't mess it up */
+ cpy_m4_m4(tempmat, mat);
+
+ for(i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = ABS(tempmat[i][i]);
+ maxj = i;
+ for(j = i + 1; j < 4; j++) {
+ if(ABS(tempmat[j][i]) > max) {
+ max = ABS(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for( k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ temp = tempmat[i][i];
+ if (temp == 0)
+ return 0; /* No non-zero pivot */
+ for(k = 0; k < 4; k++) {
+ tempmat[i][k] = (float)(tempmat[i][k]/temp);
+ inverse[i][k] = (float)(inverse[i][k]/temp);
+ }
+ for(j = 0; j < 4; j++) {
+ if(j != i) {
+ temp = tempmat[j][i];
+ for(k = 0; k < 4; k++) {
+ tempmat[j][k] -= (float)(tempmat[i][k]*temp);
+ inverse[j][k] -= (float)(inverse[i][k]*temp);
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/* ***************** v1 = v2 * mat ***************** */
+void mul_v3_v3m4(float *v1, float *v2, float mat[][4])
+{
+ float x, y;
+
+ x= v2[0]; /* work with a copy, v1 can be same as v2 */
+ y= v2[1];
+ v1[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*v2[2] + mat[3][0];
+ v1[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*v2[2] + mat[3][1];
+ v1[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*v2[2] + mat[3][2];
+
+}
+
+/* moved from effect.c
+ test if the line starting at p1 ending at p2 intersects the triangle v0..v2
+ return non zero if it does
+*/
+int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
+{
+
+ float p[3], s[3], d[3], e1[3], e2[3], q[3];
+ float a, f, u, v;
+
+ VecSubf(e1, v1, v0);
+ VecSubf(e2, v2, v0);
+ VecSubf(d, p2, p1);
+
+ Crossf(p, d, e2);
+ a = Inpf(e1, p);
+ if ((a > -0.000001) && (a < 0.000001)) return 0;
+ f = 1.0f/a;
+
+ VecSubf(s, p1, v0);
+
+ Crossf(q, s, e1);
+ *lambda = f * Inpf(e2, q);
+ if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
+
+ u = f * Inpf(s, p);
+ if ((u < 0.0)||(u > 1.0)) return 0;
+
+ v = f * Inpf(d, q);
+ if ((v < 0.0)||((u + v) > 1.0)) return 0;
+
+ return 1;
+}
+
+
+/*
+find closest point to p on line through l1,l2
+and return lambda, where (0 <= lambda <= 1) when cp is in the line segement l1,l2
+*/
+float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3])
+{
+ float h[3],u[3],lambda;
+ VecSubf(u, l2, l1);
+ VecSubf(h, p, l1);
+ lambda =Inpf(u,h)/Inpf(u,u);
+ cp[0] = l1[0] + u[0] * lambda;
+ cp[1] = l1[1] + u[1] * lambda;
+ cp[2] = l1[2] + u[2] * lambda;
+ return lambda;
+}
+/* little sister we only need to know lambda */
+float lambda_cp_line(float p[3], float l1[3], float l2[3])
+{
+ float h[3],u[3];
+ VecSubf(u, l2, l1);
+ VecSubf(h, p, l1);
+ return(Inpf(u,h)/Inpf(u,u));
+}
+
+
+
+int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3])
+{
+/*
+what is a slice ?
+some maths:
+a line including l1,l2 and a point not on the line
+define a subset of R3 delimeted by planes parallel to the line and orthogonal
+to the (point --> line) distance vector,one plane on the line one on the point,
+the room inside usually is rather small compared to R3 though still infinte
+useful for restricting (speeding up) searches
+e.g. all points of triangular prism are within the intersection of 3 'slices'
+onother trivial case : cube
+but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too
+*/
+ float h,rp[3],cp[3],q[3];
+
+ lambda_cp_line_ex(v1,l1,l2,cp);
+ VecSubf(q,cp,v1);
+
+ VecSubf(rp,p,v1);
+ h=Inpf(q,rp)/Inpf(q,q);
+ if (h < 0.0f || h > 1.0f) return 0;
+ return 1;
+}
+
+/*adult sister defining the slice planes by the origin and the normal
+NOTE |normal| may not be 1 but defining the thickness of the slice*/
+int point_in_slice_as(float p[3],float origin[3],float normal[3])
+{
+ float h,rp[3];
+ VecSubf(rp,p,origin);
+ h=Inpf(normal,rp)/Inpf(normal,normal);
+ if (h < 0.0f || h > 1.0f) return 0;
+ return 1;
+}
+
+/*mama (knowing the squared lenght of the normal)*/
+int point_in_slice_m(float p[3],float origin[3],float normal[3],float lns)
+{
+ float h,rp[3];
+ VecSubf(rp,p,origin);
+ h=Inpf(normal,rp)/lns;
+ if (h < 0.0f || h > 1.0f) return 0;
+ return 1;
+}
+
+
+int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3])
+{
+ if(!point_in_slice(p,v1,v2,v3)) return 0;
+ if(!point_in_slice(p,v2,v3,v1)) return 0;
+ if(!point_in_slice(p,v3,v1,v2)) return 0;
+ return 1;
+}
+
+/* point closest to v1 on line v2-v3 in 3D */
+void PclosestVL3Dfl(float *closest, float *v1, float *v2, float *v3)
+{
+ float lambda, cp[3];
+
+ lambda= lambda_cp_line_ex(v1, v2, v3, cp);
+
+ if(lambda <= 0.0f)
+ VecCopyf(closest, v2);
+ else if(lambda >= 1.0f)
+ VecCopyf(closest, v3);
+ else
+ VecCopyf(closest, cp);
+}
+
+/* distance v1 to line-piece v2-v3 in 3D */
+float PdistVL3Dfl(float *v1, float *v2, float *v3)
+{
+ float closest[3];
+
+ PclosestVL3Dfl(closest, v1, v2, v3);
+
+ return VecLenf(closest, v1);
+}
+
+/********************************************************/
+
+/* make a 4x4 matrix out of 3 transform components */
+/* matrices are made in the order: scale * rot * loc */
+void LocEulSizeToMat4(float mat[][4], float loc[3], float eul[3], float size[3])
+{
+ float rmat[3][3], smat[3][3], tmat[3][3];
+
+ /* initialise new matrix */
+ Mat4One(mat);
+
+ /* make rotation + scaling part */
+ EulToMat3(eul, rmat);
+ SizeToMat3(size, smat);
+ Mat3MulMat3(tmat, rmat, smat);
+
+ /* copy rot/scale part to output matrix*/
+ Mat4CpyMat3(mat, tmat);
+
+ /* copy location to matrix */
+ mat[3][0] = loc[0];
+ mat[3][1] = loc[1];
+ mat[3][2] = loc[2];
+}
+
+/* make a 4x4 matrix out of 3 transform components */
+/* matrices are made in the order: scale * rot * loc */
+void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3])
+{
+ float rmat[3][3], smat[3][3], tmat[3][3];
+
+ /* initialise new matrix */
+ Mat4One(mat);
+
+ /* make rotation + scaling part */
+ QuatToMat3(quat, rmat);
+ SizeToMat3(size, smat);
+ Mat3MulMat3(tmat, rmat, smat);
+
+ /* copy rot/scale part to output matrix*/
+ Mat4CpyMat3(mat, tmat);
+
+ /* copy location to matrix */
+ mat[3][0] = loc[0];
+ mat[3][1] = loc[1];
+ mat[3][2] = loc[2];
+}
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
new file mode 100644
index 00000000000..42092bc54c3
--- /dev/null
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -0,0 +1,416 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell barton
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "BKE_utildefines.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_boxpack2d.h"
+
+/* BoxPacker ported from Python by Campbell Barton
+ *
+ * The defined Below are for internal use only */
+
+/* free vert flags */
+#define eul 0.0000001
+#define BLF 1
+#define TRF 2
+#define TLF 4
+#define BRF 8
+#define BL 0
+#define TR 1
+#define TL 2
+#define BR 3
+
+#define BOXLEFT(b) b->v[BL]->x
+#define BOXRIGHT(b) b->v[TR]->x
+#define BOXBOTTOM(b) b->v[BL]->y
+#define BOXTOP(b) b->v[TR]->y
+#define BOXAREA(b) (b->w * b->h)
+
+#define UPDATE_V34X(b) b->v[TL]->x = b->v[BL]->x;\
+ b->v[BR]->x = b->v[TR]->x
+#define UPDATE_V34Y(b) b->v[TL]->y = b->v[TR]->y;\
+ b->v[BR]->y = b->v[BL]->y
+#define UPDATE_V34(b) UPDATE_V34X(b); UPDATE_V34Y(b)
+
+#define SET_BOXLEFT(b, f) b->v[TR]->x = f + b->w;\
+ b->v[BL]->x = f;\
+ UPDATE_V34X(b)
+#define SET_BOXRIGHT(b, f) b->v[BL]->x = f - b->w;\
+ b->v[TR]->x = f;\
+ UPDATE_V34X(b)
+#define SET_BOXBOTTOM(b, f) b->v[TR]->y = f + b->h;\
+ b->v[BL]->y = f;\
+ UPDATE_V34Y(b)
+#define SET_BOXTOP(b, f) b->v[BL]->y = f - b->h;\
+ b->v[TR]->y = f;\
+ UPDATE_V34Y(b)
+#define BOXINTERSECT(b1, b2)\
+ (!( BOXLEFT(b1)+eul>=BOXRIGHT(b2) ||\
+ BOXBOTTOM(b1)+eul>=BOXTOP(b2) ||\
+ BOXRIGHT(b1)-eul<=BOXLEFT(b2) ||\
+ BOXTOP(b1)-eul<=BOXBOTTOM(b2) ))
+
+/* #define BOXDEBUG(b)\
+ * printf("\tBox Debug i %i, w:%.3f h:%.3f x:%.3f y:%.3f\n",\
+ * b->index, b->w, b->h, b->x, b->y) */
+
+/* qsort function - sort largest to smallest */
+static int box_areasort(const void *p1, const void *p2)
+{
+ const boxPack *b1=p1, *b2=p2;
+ float a1, a2;
+
+ a1 = BOXAREA(b1);
+ a2 = BOXAREA(b2);
+
+ if ( a1 < a2 ) return 1;
+ else if ( a1 > a2 ) return -1;
+ return 0;
+}
+
+/* qsort vertex sorting function
+ * sorts from lower left to top right It uses the current box's width and height
+ * as offsets when sorting, this has the result of not placing boxes outside
+ * the bounds of the existing backed area where possible
+ * */
+static float box_width;
+static float box_height;
+static boxVert *vertarray;
+
+static int vertex_sort(const void *p1, const void *p2)
+{
+ boxVert *v1, *v2;
+ float a1, a2;
+
+ v1 = vertarray + ((int *) p1)[0];
+ v2 = vertarray + ((int *) p2)[0];
+
+ a1 = MAX2(v1->x+box_width, v1->y+box_height);
+ a2 = MAX2(v2->x+box_width, v2->y+box_height);
+
+ /* sort largest to smallest */
+ if ( a1 > a2 ) return 1;
+ else if ( a1 < a2 ) return -1;
+ return 0;
+}
+/* Main boxpacking function accessed from other functions
+ * This sets boxes x,y to positive values, sorting from 0,0 outwards.
+ * There is no limit to the space boxes may take, only that they will be packed
+ * tightly into the lower left hand corner (0,0)
+ *
+ * boxarray - a pre allocated array of boxes.
+ * only the 'box->x' and 'box->y' are set, 'box->w' and 'box->h' are used,
+ * 'box->index' is not used at all, the only reason its there
+ * is that the box array is sorted by area and programs need to be able
+ * to have some way of writing the boxes back to the original data.
+ * len - the number of boxes in teh array.
+ * tot_width and tot_height are set so you can normalize the data.
+ * */
+void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height)
+{
+ boxVert *vert; /* the current vert */
+ int box_index, verts_pack_len, i, j, k, isect;
+ int quad_flags[4]= {BLF,TRF,TLF,BRF}; /* use for looping */
+ boxPack *box, *box_test; /*current box and another for intersection tests*/
+ int *vertex_pack_indicies; /*an array of indicies used for sorting verts*/
+
+ if (!len) {
+ *tot_width = 0.0;
+ *tot_height = 0.0;
+ return;
+ }
+
+ /* Sort boxes, biggest first */
+ qsort(boxarray, len, sizeof(boxPack), box_areasort);
+
+ /* add verts to the boxes, these are only used internally */
+ vert = vertarray = MEM_mallocN( len*4*sizeof(boxVert), "boxPack verts");
+ vertex_pack_indicies = MEM_mallocN( len*3*sizeof(int), "boxPack indicies");
+
+ for (box=boxarray, box_index=0, i=0; box_index < len; box_index++, box++) {
+
+ vert->blb = vert->brb = vert->tlb =\
+ vert->isect_cache[0] = vert->isect_cache[1] =\
+ vert->isect_cache[2] = vert->isect_cache[3] = NULL;
+ vert->free = 15 &~ TRF;
+ vert->trb = box;
+ vert->index = i; i++;
+ box->v[BL] = vert; vert++;
+
+ vert->trb= vert->brb = vert->tlb =\
+ vert->isect_cache[0] = vert->isect_cache[1] =\
+ vert->isect_cache[2] = vert->isect_cache[3] = NULL;
+ vert->free = 15 &~ BLF;
+ vert->blb = box;
+ vert->index = i; i++;
+ box->v[TR] = vert; vert++;
+
+ vert->trb = vert->blb = vert->tlb =\
+ vert->isect_cache[0] = vert->isect_cache[1] =\
+ vert->isect_cache[2] = vert->isect_cache[3] = NULL;
+ vert->free = 15 &~ BRF;
+ vert->brb = box;
+ vert->index = i; i++;
+ box->v[TL] = vert; vert++;
+
+ vert->trb = vert->blb = vert->brb =\
+ vert->isect_cache[0] = vert->isect_cache[1] =\
+ vert->isect_cache[2] = vert->isect_cache[3] = NULL;
+ vert->free = 15 &~ TLF;
+ vert->tlb = box;
+ vert->index = i; i++;
+ box->v[BR] = vert; vert++;
+ }
+ vert = NULL;
+
+
+ /* Pack the First box!
+ * then enter the main boxpacking loop */
+
+ box = boxarray; /* get the first box */
+ /* First time, no boxes packed */
+ box->v[BL]->free = 0; /* Cant use any if these */
+ box->v[BR]->free &= ~(BLF|BRF);
+ box->v[TL]->free &= ~(BLF|TLF);
+
+ *tot_width = box->w;
+ *tot_height = box->h;
+
+ /* This sets all the vertex locations */
+ SET_BOXLEFT(box, 0.0);
+ SET_BOXBOTTOM(box, 0.0);
+ box->x = box->y = 0.0;
+
+ for (i=0; i<3; i++)
+ vertex_pack_indicies[i] = box->v[i+1]->index;
+ verts_pack_len = 3;
+ box++; /* next box, needed for the loop below */
+ /* ...done packing the first box */
+
+ /* Main boxpacking loop */
+ for (box_index=1; box_index < len; box_index++, box++) {
+
+ /* Sort the verts, these constants are used in sorting */
+ box_width = box->w;
+ box_height = box->h;
+
+ qsort(vertex_pack_indicies, verts_pack_len, sizeof(int), vertex_sort);
+
+ /* Pack the box in with the others */
+ /* sort the verts */
+ isect = 1;
+
+ for (i=0; i<verts_pack_len && isect; i++) {
+ vert = vertarray + vertex_pack_indicies[i];
+ /* printf("\ttesting vert %i %i %i %f %f\n", i,
+ * vert->free, verts_pack_len, vert->x, vert->y); */
+
+ /* This vert has a free quaderent
+ * Test if we can place the box here
+ * vert->free & quad_flags[j] - Checks
+ * */
+
+ for (j=0; (j<4) && isect; j++) {
+ if (vert->free & quad_flags[j]) {
+ switch (j) {
+ case BL:
+ SET_BOXRIGHT(box, vert->x);
+ SET_BOXTOP(box, vert->y);
+ break;
+ case TR:
+ SET_BOXLEFT(box, vert->x);
+ SET_BOXBOTTOM(box, vert->y);
+ break;
+ case TL:
+ SET_BOXRIGHT(box, vert->x);
+ SET_BOXBOTTOM(box, vert->y);
+ break;
+ case BR:
+ SET_BOXLEFT(box, vert->x);
+ SET_BOXTOP(box, vert->y);
+ break;
+ }
+
+ /* Now we need to check that the box intersects
+ * with any other boxes
+ * Assume no intersection... */
+ isect = 0;
+
+ if (/* Constrain boxes to positive X/Y values */
+ BOXLEFT(box)<0.0 || BOXBOTTOM(box) < 0.0 ||
+ /* check for last intersected */
+ ( vert->isect_cache[j] &&
+ BOXINTERSECT(box, vert->isect_cache[j]) )
+ ) {
+ /* Here we check that the last intersected
+ * box will intersect with this one using
+ * isect_cache that can store a pointer to a
+ * box for each quaderent
+ * big speedup */
+ isect = 1;
+ } else {
+ /* do a full saech for colliding box
+ * this is realy slow, some spacialy divided
+ * datastructure would be better */
+ for (box_test=boxarray; box_test != box; box_test++) {
+ if BOXINTERSECT(box, box_test) {
+ /* Store the last intersecting here as cache
+ * for faster checking next time around */
+ vert->isect_cache[j] = box_test;
+ isect = 1;
+ break;
+ }
+ }
+ }
+
+ if (!isect) {
+
+ /* maintain the total width and height */
+ (*tot_width) = MAX2(BOXRIGHT(box), (*tot_width));
+ (*tot_height) = MAX2(BOXTOP(box), (*tot_height));
+
+ /* Place the box */
+ vert->free &= ~quad_flags[j];
+
+ switch (j) {
+ case TR:
+ box->v[BL]= vert;
+ vert->trb = box;
+ break;
+ case TL:
+ box->v[BR]= vert;
+ vert->tlb = box;
+ break;
+ case BR:
+ box->v[TL]= vert;
+ vert->brb = box;
+ break;
+ case BL:
+ box->v[TR]= vert;
+ vert->blb = box;
+ break;
+ }
+
+ /* Mask free flags for verts that are
+ * on the bottom or side so we dont get
+ * boxes outside the given rectangle ares
+ *
+ * We can do an else/if here because only the first
+ * box can be at the very bottom left corner */
+ if (BOXLEFT(box) <= 0) {
+ box->v[TL]->free &= ~(TLF|BLF);
+ box->v[BL]->free &= ~(TLF|BLF);
+ } else if (BOXBOTTOM(box) <= 0) {
+ box->v[BL]->free &= ~(BRF|BLF);
+ box->v[BR]->free &= ~(BRF|BLF);
+ }
+
+ /* The following block of code does a logical
+ * check with 2 adjacent boxes, its possible to
+ * flag verts on one or both of the boxes
+ * as being used by checking the width or
+ * height of both boxes */
+ if (vert->tlb && vert->trb &&
+ (box == vert->tlb || box == vert->trb)) {
+ if (vert->tlb->h > vert->trb->h) {
+ vert->trb->v[TL]->free &= ~(TLF|BLF);
+ } else if (vert->tlb->h < vert->trb->h) {
+ vert->tlb->v[TR]->free &= ~(TRF|BRF);
+ } else { /*same*/
+ vert->tlb->v[TR]->free &= ~BLF;
+ vert->trb->v[TL]->free &= ~BRF;
+ }
+ } else if (vert->blb && vert->brb &&
+ (box == vert->blb || box == vert->brb)) {
+ if (vert->blb->h > vert->brb->h) {
+ vert->brb->v[BL]->free &= ~(TLF|BLF);
+ } else if (vert->blb->h < vert->brb->h) {
+ vert->blb->v[BR]->free &= ~(TRF|BRF);
+ } else { /*same*/
+ vert->blb->v[BR]->free &= ~TRF;
+ vert->brb->v[BL]->free &= ~TLF;
+ }
+ }
+ /* Horizontal */
+ if (vert->tlb && vert->blb &&
+ (box == vert->tlb || box == vert->blb) ) {
+ if (vert->tlb->w > vert->blb->w) {
+ vert->blb->v[TL]->free &= ~(TLF|TRF);
+ } else if (vert->tlb->w < vert->blb->w) {
+ vert->tlb->v[BL]->free &= ~(BLF|BRF);
+ } else { /*same*/
+ vert->blb->v[TL]->free &= ~TRF;
+ vert->tlb->v[BL]->free &= ~BRF;
+ }
+ } else if ( vert->trb && vert->brb &&
+ (box == vert->trb || box == vert->brb) ) {
+ if (vert->trb->w > vert->brb->w) {
+ vert->brb->v[TR]->free &= ~(TRF|TRF);
+ } else if (vert->trb->w < vert->brb->w) {
+ vert->trb->v[BR]->free &= ~(BLF|BRF);
+ } else { /*same*/
+ vert->brb->v[TR]->free &= ~TLF;
+ vert->trb->v[BR]->free &= ~BLF;
+ }
+ }
+ /* End logical check */
+
+
+ for (k=0; k<4; k++) {
+ if (box->v[k] != vert) {
+ vertex_pack_indicies[verts_pack_len] =
+ box->v[k]->index;
+ verts_pack_len++;
+ }
+ }
+ /* The Box verts are only used interially
+ * Update the box x and y since thats what external
+ * functions will see */
+ box->x = BOXLEFT(box);
+ box->y = BOXBOTTOM(box);
+ }
+ }
+ }
+ }
+ }
+
+ /* free all the verts, not realy needed because they shouldebt be
+ * touched anymore but accessing the pointers woud crash blender */
+ for (box_index=0; box_index < len; box_index++) {
+ box = boxarray+box_index;
+ box->v[0] = box->v[1] = box->v[2] = box->v[3] = NULL;
+ }
+ MEM_freeN(vertex_pack_indicies);
+ MEM_freeN(vertarray);
+}
+
diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c
new file mode 100644
index 00000000000..c455ba664ce
--- /dev/null
+++ b/source/blender/blenlib/intern/dynlib.c
@@ -0,0 +1,343 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file, with exception of below:
+ *
+ * Contributor(s): Peter O'Gorman
+ * The functions osxdlopen() and osxerror()
+ * are Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net>
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../PIL_dynlib.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined(CHAR_MAX)
+#define CHAR_MAX 255
+#endif
+
+/*
+ * XXX, should use mallocN so we can see
+ * handle's not being released. fixme zr
+ */
+
+#ifdef WIN32
+
+#include <windows.h>
+
+struct PILdynlib {
+ void *handle;
+};
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= LoadLibrary(name);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
+ return GetProcAddress(lib->handle, symname);
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
+ int err;
+
+ /* if lib is NULL reset the last error code */
+ if (!lib) {
+ SetLastError(ERROR_SUCCESS);
+ return NULL;
+ }
+
+ err= GetLastError();
+ if (err) {
+ static char buf[1024];
+
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ buf,
+ sizeof(buf),
+ NULL))
+ return buf;
+ }
+
+ return NULL;
+}
+
+void PIL_dynlib_close(PILdynlib *lib) {
+ FreeLibrary(lib->handle);
+
+ free(lib);
+}
+
+#else
+#ifdef __APPLE__ /* MacOS X */
+
+#include <mach-o/dyld.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+
+#define ERR_STR_LEN 256
+
+struct PILdynlib {
+ void *handle;
+};
+
+static char *osxerror(int setget, const char *str, ...)
+{
+ static char errstr[ERR_STR_LEN];
+ static int err_filled = 0;
+ char *retval;
+ NSLinkEditErrors ler;
+ int lerno;
+ const char *dylderrstr;
+ const char *file;
+ va_list arg;
+ if (setget <= 0)
+ {
+ va_start(arg, str);
+ strncpy(errstr, "dlsimple: ", ERR_STR_LEN);
+ vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg);
+ va_end(arg);
+ /* We prefer to use the dyld error string if setget is 0 */
+ if (setget == 0) {
+ NSLinkEditError(&ler, &lerno, &file, &dylderrstr);
+// printf("dyld: %s\n",dylderrstr);
+ if (dylderrstr && strlen(dylderrstr))
+ strncpy(errstr,dylderrstr,ERR_STR_LEN);
+ }
+ err_filled = 1;
+ retval = NULL;
+ }
+ else
+ {
+ if (!err_filled)
+ retval = NULL;
+ else
+ retval = errstr;
+ err_filled = 0;
+ }
+ return retval;
+}
+
+static void *osxdlopen(const char *path, int mode)
+{
+ void *module = 0;
+ NSObjectFileImage ofi = 0;
+ NSObjectFileImageReturnCode ofirc;
+ static int (*make_private_module_public) (NSModule module) = 0;
+ unsigned int flags = NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE;
+
+ /* If we got no path, the app wants the global namespace, use -1 as the marker
+ in this case */
+ if (!path)
+ return (void *)-1;
+
+ /* Create the object file image, works for things linked with the -bundle arg to ld */
+ ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
+ switch (ofirc)
+ {
+ case NSObjectFileImageSuccess:
+ /* It was okay, so use NSLinkModule to link in the image */
+ if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW;
+ module = NSLinkModule(ofi, path,flags);
+ /* Don't forget to destroy the object file image, unless you like leaks */
+ NSDestroyObjectFileImage(ofi);
+ /* If the mode was global, then change the module, this avoids
+ multiply defined symbol errors to first load private then make
+ global. Silly, isn't it. */
+ if ((mode & RTLD_GLOBAL))
+ {
+ if (!make_private_module_public)
+ {
+ _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",
+ (unsigned long *)&make_private_module_public);
+ }
+ make_private_module_public(module);
+ }
+ break;
+ case NSObjectFileImageInappropriateFile:
+ /* It may have been a dynamic library rather than a bundle, try to load it */
+ module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ break;
+ case NSObjectFileImageFailure:
+ osxerror(0,"Object file setup failure : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageArch:
+ osxerror(0,"No object for this architecture : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageFormat:
+ osxerror(0,"Bad object file format : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageAccess:
+ osxerror(0,"Can't read object file : \"%s\"", path);
+ return 0;
+ }
+ if (!module)
+ osxerror(0, "Can not open \"%s\"", path);
+ return module;
+}
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= osxdlopen(name, RTLD_LAZY);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname)
+{
+ int sym_len = strlen(symname);
+ void *value = NULL;
+ char *malloc_sym = NULL;
+ NSSymbol *nssym = 0;
+ malloc_sym = malloc(sym_len + 2);
+ if (malloc_sym)
+ {
+ sprintf(malloc_sym, "_%s", symname);
+ /* If the lib->handle is -1, if is the app global context */
+ if (lib->handle == (void *)-1)
+ {
+ /* Global context, use NSLookupAndBindSymbol */
+ if (NSIsSymbolNameDefined(malloc_sym))
+ {
+ nssym = NSLookupAndBindSymbol(malloc_sym);
+ }
+ }
+ /* Now see if the lib->handle is a struch mach_header* or not, use NSLookupSymbol in image
+ for libraries, and NSLookupSymbolInModule for bundles */
+ else
+ {
+ /* Check for both possible magic numbers depending on x86/ppc byte order */
+ if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
+ (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
+ {
+ if (NSIsSymbolNameDefinedInImage((struct mach_header *)lib->handle, malloc_sym))
+ {
+ nssym = NSLookupSymbolInImage((struct mach_header *)lib->handle,
+ malloc_sym,
+ NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+ | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ }
+
+ }
+ else
+ {
+ nssym = NSLookupSymbolInModule(lib->handle, malloc_sym);
+ }
+ }
+ if (!nssym)
+ {
+ osxerror(0, "symname \"%s\" Not found", symname);
+ }
+ value = NSAddressOfSymbol(nssym);
+ free(malloc_sym);
+ }
+ else
+ {
+ osxerror(-1, "Unable to allocate memory");
+ }
+ return value;
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib)
+{
+ return osxerror(1, (char *)NULL);
+}
+
+void PIL_dynlib_close(PILdynlib *lib)
+{
+ if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
+ (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
+ {
+ osxerror(-1, "Can't remove dynamic libraries on darwin");
+ }
+ if (!NSUnLinkModule(lib->handle, 0))
+ {
+ osxerror(0, "unable to unlink module %s", NSNameOfModule(lib->handle));
+ }
+
+ free(lib);
+}
+
+#else /* Unix */
+
+#include <dlfcn.h>
+
+struct PILdynlib {
+ void *handle;
+};
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= dlopen(name, RTLD_LAZY);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
+ return dlsym(lib->handle, symname);
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
+ return dlerror();
+}
+
+void PIL_dynlib_close(PILdynlib *lib) {
+ dlclose(lib->handle);
+
+ free(lib);
+}
+
+#endif
+#endif
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
new file mode 100644
index 00000000000..8fae0f63746
--- /dev/null
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -0,0 +1,220 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Daniel Dunbar
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * A general (pointer -> pointer) hash table ADT
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_edgehash.h"
+
+/***/
+
+static unsigned int hashsizes[]= {
+ 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
+ 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169,
+ 4194319, 8388617, 16777259, 33554467, 67108879, 134217757,
+ 268435459
+};
+
+#define EDGEHASH(v0,v1) ((v0*39)^(v1*31))
+
+/***/
+
+typedef struct Entry Entry;
+struct Entry {
+ Entry *next;
+ int v0, v1;
+ void *val;
+};
+
+struct EdgeHash {
+ Entry **buckets;
+ int nbuckets, nentries, cursize;
+};
+
+/***/
+
+EdgeHash *BLI_edgehash_new(void) {
+ EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash");
+ eh->cursize= 0;
+ eh->nentries= 0;
+ eh->nbuckets= hashsizes[eh->cursize];
+
+ eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
+ memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+
+ return eh;
+}
+
+void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
+ unsigned int hash;
+ Entry *e= malloc(sizeof(*e));
+
+ if (v1<v0) v0 ^= v1 ^= v0 ^= v1;
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+
+ e->v0 = v0;
+ e->v1 = v1;
+ e->val = val;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ if (++eh->nentries>eh->nbuckets*3) {
+ Entry *e, **old= eh->buckets;
+ int i, nold= eh->nbuckets;
+
+ eh->nbuckets= hashsizes[++eh->cursize];
+ eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets));
+ memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+
+ for (i=0; i<nold; i++) {
+ for (e= old[i]; e;) {
+ Entry *n= e->next;
+
+ hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
+ e->next= eh->buckets[hash];
+ eh->buckets[hash]= e;
+
+ e= n;
+ }
+ }
+
+ free(old);
+ }
+}
+
+void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
+ unsigned int hash;
+ Entry *e;
+
+ if (v1<v0) v0 ^= v1 ^= v0 ^= v1;
+ hash = EDGEHASH(v0,v1)%eh->nbuckets;
+ for (e= eh->buckets[hash]; e; e= e->next)
+ if (v0==e->v0 && v1==e->v1)
+ return &e->val;
+
+ return NULL;
+}
+
+void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
+ void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
+
+ return value_p?*value_p:NULL;
+}
+
+int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
+ return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+}
+
+int BLI_edgehash_size(EdgeHash *eh) {
+ return eh->nentries;
+}
+
+void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
+ int i;
+
+ for (i=0; i<eh->nbuckets; i++) {
+ Entry *e;
+
+ for (e= eh->buckets[i]; e; ) {
+ Entry *n= e->next;
+
+ if (valfreefp) valfreefp(e->val);
+ free(e);
+
+ e= n;
+ }
+ eh->buckets[i]= NULL;
+ }
+
+ eh->nentries= 0;
+}
+
+void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) {
+ BLI_edgehash_clear(eh, valfreefp);
+
+ free(eh->buckets);
+ MEM_freeN(eh);
+}
+
+
+/***/
+
+struct EdgeHashIterator {
+ EdgeHash *eh;
+ int curBucket;
+ Entry *curEntry;
+};
+
+EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) {
+ EdgeHashIterator *ehi= malloc(sizeof(*ehi));
+ ehi->eh= eh;
+ ehi->curEntry= NULL;
+ ehi->curBucket= -1;
+ while (!ehi->curEntry) {
+ ehi->curBucket++;
+ if (ehi->curBucket==ehi->eh->nbuckets)
+ break;
+ ehi->curEntry= ehi->eh->buckets[ehi->curBucket];
+ }
+ return ehi;
+}
+void BLI_edgehashIterator_free(EdgeHashIterator *ehi) {
+ free(ehi);
+}
+
+void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) {
+ if (ehi->curEntry) {
+ *v0_r = ehi->curEntry->v0;
+ *v1_r = ehi->curEntry->v1;
+ }
+}
+void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) {
+ return ehi->curEntry?ehi->curEntry->val:NULL;
+}
+
+void BLI_edgehashIterator_step(EdgeHashIterator *ehi) {
+ if (ehi->curEntry) {
+ ehi->curEntry= ehi->curEntry->next;
+ while (!ehi->curEntry) {
+ ehi->curBucket++;
+ if (ehi->curBucket==ehi->eh->nbuckets)
+ break;
+ ehi->curEntry= ehi->eh->buckets[ehi->curBucket];
+ }
+ }
+}
+int BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) {
+ return !ehi->curEntry;
+}
+
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
new file mode 100644
index 00000000000..fcea30982bd
--- /dev/null
+++ b/source/blender/blenlib/intern/fileops.c
@@ -0,0 +1,364 @@
+/*
+ * blenlib/fileops.h
+ *
+ * cleaned up (a bit) mar-01 nzc
+ *
+ * More low-level file things.
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "zlib.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#include <io.h>
+#else
+#include <sys/param.h>
+#endif
+
+#include "BLI_blenlib.h"
+#include "BLI_storage.h"
+#include "BLI_fileops.h"
+#include "BLI_callbacks.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "BKE_utildefines.h"
+#include <errno.h>
+
+/* implementations: */
+char *first_slash(char *string) {
+ char *ffslash, *fbslash;
+
+ ffslash= strchr(string, '/');
+ fbslash= strchr(string, '\\');
+
+ if (!ffslash) return fbslash;
+ else if (!fbslash) return ffslash;
+
+ if ((long)ffslash < (long)fbslash) return ffslash;
+ else return fbslash;
+}
+
+char *BLI_last_slash(char *string) {
+ char *lfslash, *lbslash;
+
+ lfslash= strrchr(string, '/');
+ lbslash= strrchr(string, '\\');
+
+ if (!lfslash) return lbslash;
+ else if (!lbslash) return lfslash;
+
+ if ((long)lfslash < (long)lbslash) return lbslash;
+ else return lfslash;
+}
+
+/* gzip the file in from and write it to "to".
+ return -1 if zlib fails, -2 if the originating file does not exist
+ note: will remove the "from" file
+ */
+int BLI_gzip(char *from, char *to) {
+ char buffer[10240];
+ int file;
+ int readsize = 0;
+
+ gzFile gzfile = gzopen(to,"wb");
+ if (NULL == gzfile) return -1;
+
+ file = open(from,O_BINARY|O_RDONLY);
+
+ if ( -1 == file ) return -2;
+
+ while ( 1 )
+ {
+ readsize = read(file, buffer, 10240);
+
+ if (readsize <= 0) break;
+
+ gzwrite(gzfile,buffer,readsize);
+ }
+
+ gzclose(gzfile);
+ close(file);
+
+ remove(from);
+
+ return 0;
+}
+
+/* return 1 when file can be written */
+int BLI_is_writable(char *filename)
+{
+ int file;
+
+ file = open(filename, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666);
+
+ if (file < 0)
+ return 0;
+ else {
+ close(file);
+ return 1;
+ }
+}
+
+#ifdef WIN32
+
+static char str[MAXPATHLEN+12];
+
+int BLI_delete(char *file, int dir, int recursive) {
+ int err;
+
+ if (recursive) {
+ callLocalErrorCallBack("Recursive delete is unsupported on Windows");
+ err= 1;
+ } else if (dir) {
+ err= !RemoveDirectory(file);
+ if (err) printf ("Unable to remove directory");
+ } else {
+ err= !DeleteFile(file);
+ if (err) callLocalErrorCallBack("Unable to delete file");
+ }
+
+ return err;
+}
+
+int BLI_touch(char *file) {
+ callLocalErrorCallBack("Touching files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_move(char *file, char *to) {
+ int err;
+
+ // windows doesn't support moveing to a directory
+ // it has to be 'mv filename filename' and not
+ // 'mv filename destdir'
+
+ strcpy(str, to);
+ // points 'to' to a directory ?
+ if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
+ if (BLI_last_slash(file) != NULL) {
+ strcat(str, BLI_last_slash(file) + 1);
+ }
+ }
+
+ err= !MoveFile(file, str);
+ if (err) {
+ callLocalErrorCallBack("Unable to move file");
+ printf(" Move from '%s' to '%s' failed\n", file, str);
+ }
+
+ return err;
+}
+
+
+int BLI_copy_fileops(char *file, char *to) {
+ int err;
+
+ // windows doesn't support copying to a directory
+ // it has to be 'cp filename filename' and not
+ // 'cp filename destdir'
+
+ strcpy(str, to);
+ // points 'to' to a directory ?
+ if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
+ if (BLI_last_slash(file) != NULL) {
+ strcat(str, BLI_last_slash(file) + 1);
+ }
+ }
+
+ err= !CopyFile(file,str,FALSE);
+
+ if (err) {
+ callLocalErrorCallBack("Unable to copy file!");
+ printf(" Copy from '%s' to '%s' failed\n", file, str);
+ }
+
+ return err;
+}
+
+int BLI_link(char *file, char *to) {
+ callLocalErrorCallBack("Linking files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_backup(char *file, char *from, char *to) {
+ callLocalErrorCallBack("Backing up files is unsupported on Windows");
+
+ return 1;
+}
+
+int BLI_exists(char *file) {
+ return (GetFileAttributes(file) != 0xFFFFFFFF);
+}
+
+void BLI_recurdir_fileops(char *dirname) {
+ char *lslash;
+ char tmp[MAXPATHLEN];
+
+ // First remove possible slash at the end of the dirname.
+ // This routine otherwise tries to create
+ // blah1/blah2/ (with slash) after creating
+ // blah1/blah2 (without slash)
+
+ strcpy(tmp, dirname);
+ lslash= BLI_last_slash(tmp);
+
+ if (lslash == tmp + strlen(tmp) - 1) {
+ *lslash = 0;
+ }
+
+ if (BLI_exists(tmp)) return;
+
+ lslash= BLI_last_slash(tmp);
+ if (lslash) {
+ /* Split about the last slash and recurse */
+ *lslash = 0;
+ BLI_recurdir_fileops(tmp);
+ }
+
+ if(dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
+ if (!CreateDirectory(dirname, NULL))
+ callLocalErrorCallBack("Unable to create directory\n");
+}
+
+int BLI_rename(char *from, char *to) {
+ if (!BLI_exists(from)) return 0;
+
+ if (BLI_exists(to))
+ if(BLI_delete(to, 0, 0)) return 1;
+
+ return rename(from, to);
+}
+
+#else /* The sane UNIX world */
+
+/*
+ * but the sane UNIX world is tied to the interface, and the system
+ * timer, and... We implement a callback mechanism. The system will
+ * have to initialise the callback before the functions will work!
+ * */
+static char str[MAXPATHLEN+12];
+
+int BLI_delete(char *file, int dir, int recursive)
+{
+ if(strchr(file, '"')) {
+ printf("Error: not deleted file %s because of quote!\n", file);
+ }
+ else {
+ if (recursive) sprintf(str, "/bin/rm -rf \"%s\"", file);
+ else if (dir) sprintf(str, "/bin/rmdir \"%s\"", file);
+ else sprintf(str, "/bin/rm -f \"%s\"", file);
+
+ return system(str);
+ }
+ return -1;
+}
+
+int BLI_touch(char *file)
+{
+
+ if( BLI_exists("/bin/touch") )
+ sprintf(str, "/bin/touch %s", file);
+ else
+ sprintf(str, "/usr/bin/touch %s", file);
+
+ return system(str);
+}
+
+int BLI_move(char *file, char *to) {
+ sprintf(str, "/bin/mv -f \"%s\" \"%s\"", file, to);
+
+ return system(str);
+}
+
+int BLI_copy_fileops(char *file, char *to) {
+ sprintf(str, "/bin/cp -rf \"%s\" \"%s\"", file, to);
+
+ return system(str);
+}
+
+int BLI_link(char *file, char *to) {
+ sprintf(str, "/bin/ln -f \"%s\" \"%s\"", file, to);
+
+ return system(str);
+}
+
+int BLI_backup(char *file, char *from, char *to) {
+ sprintf(str, "/bin/su root -c 'cd %s; /bin/tar cf - \"%s\" | (/bin/cd %s; /bin/tar xf -)'", from, file, to);
+
+ return system(str);
+}
+
+int BLI_exists(char *file) {
+ return BLI_exist(file);
+}
+
+void BLI_recurdir_fileops(char *dirname) {
+ char *lslash;
+ char tmp[MAXPATHLEN];
+
+ if (BLI_exists(dirname)) return;
+
+ strcpy(tmp, dirname);
+
+ lslash= BLI_last_slash(tmp);
+ if (lslash) {
+ /* Split about the last slash and recurse */
+ *lslash = 0;
+ BLI_recurdir_fileops(tmp);
+ }
+
+ mkdir(dirname, 0777);
+}
+
+int BLI_rename(char *from, char *to) {
+ if (!BLI_exists(from)) return 0;
+
+ if (BLI_exists(to)) if(BLI_delete(to, 0, 0)) return 1;
+
+ return rename(from, to);
+}
+
+#endif
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
new file mode 100644
index 00000000000..7fbd4bac485
--- /dev/null
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -0,0 +1,634 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is written by Rob Haarsma (phase)
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This code parses the Freetype font outline data to chains of Blender's beziertriples.
+ * Additional information can be found at the bottom of this file.
+ *
+ * Code that uses exotic character maps is present but commented out.
+ */
+
+#ifdef WITH_FREETYPE2
+
+#ifdef WIN32
+#pragma warning (disable:4244)
+#endif
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_BBOX_H
+#include FT_SIZES_H
+#include <freetype/ttnameid.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_vfontdata.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BIF_toolbox.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "DNA_vfont_types.h"
+#include "DNA_packedFile_types.h"
+#include "DNA_curve_types.h"
+
+#define myMIN_ASCII 32
+#define myMAX_ASCII 255
+
+/* local variables */
+static FT_Library library;
+static FT_Error err;
+
+
+void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
+{
+ // Blender
+ struct Nurb *nu;
+ struct VChar *che;
+ struct BezTriple *bezt;
+
+ // Freetype2
+ FT_GlyphSlot glyph;
+ FT_UInt glyph_index;
+ FT_Outline ftoutline;
+ float scale, height;
+ float dx, dy;
+ int j,k,l,m=0;
+
+ // adjust font size
+ height= ((double) face->bbox.yMax - (double) face->bbox.yMin);
+ if(height != 0.0)
+ scale = 1.0 / height;
+ else
+ scale = 1.0 / 1000.0;
+
+ //
+ // Generate the character 3D data
+ //
+ // Get the FT Glyph index and load the Glyph
+ glyph_index= FT_Get_Char_Index(face, charcode);
+ err= FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+
+ // If loading succeeded, convert the FT glyph to the internal format
+ if(!err)
+ {
+ int *npoints;
+ int *onpoints;
+
+ // First we create entry for the new character to the character list
+ che= (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
+ BLI_addtail(&vfd->characters, che);
+
+ // Take some data for modifying purposes
+ glyph= face->glyph;
+ ftoutline= glyph->outline;
+
+ // Set the width and character code
+ che->index= charcode;
+ che->width= glyph->advance.x * scale;
+
+ // Start converting the FT data
+ npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
+ onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
+
+ // calculate total points of each contour
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ if(j == 0)
+ npoints[j] = ftoutline.contours[j] + 1;
+ else
+ npoints[j] = ftoutline.contours[j] - ftoutline.contours[j - 1];
+ }
+
+ // get number of on-curve points for beziertriples (including conic virtual on-points)
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ l = 0;
+ for(k = 0; k < npoints[j]; k++) {
+ if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+ if(ftoutline.tags[l] == FT_Curve_Tag_On)
+ onpoints[j]++;
+
+ if(k < npoints[j] - 1 )
+ if( ftoutline.tags[l] == FT_Curve_Tag_Conic &&
+ ftoutline.tags[l+1] == FT_Curve_Tag_Conic)
+ onpoints[j]++;
+ }
+ }
+
+ //contour loop, bezier & conic styles merged
+ for(j = 0; j < ftoutline.n_contours; j++) {
+ // add new curve
+ nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
+ bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
+ BLI_addtail(&che->nurbsbase, nu);
+
+ nu->type= CU_BEZIER+CU_2D;
+ nu->pntsu = onpoints[j];
+ nu->resolu= 8;
+ nu->flagu= 1;
+ nu->bezt = bezt;
+
+ //individual curve loop, start-end
+ for(k = 0; k < npoints[j]; k++) {
+ if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
+ if(k == 0) m = l;
+
+ //virtual conic on-curve points
+ if(k < npoints[j] - 1 )
+ {
+ if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+ dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
+ dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
+
+ //left handle
+ bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x)* scale) / 3.0;
+ bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y)* scale) / 3.0;
+
+ //midpoint (virtual on-curve point)
+ bezt->vec[1][0] = dx;
+ bezt->vec[1][1] = dy;
+
+ //right handle
+ bezt->vec[2][0] = (dx + (2 * ftoutline.points[l+1].x)* scale) / 3.0;
+ bezt->vec[2][1] = (dy + (2 * ftoutline.points[l+1].y)* scale) / 3.0;
+
+ bezt->h1= bezt->h2= HD_ALIGN;
+ bezt++;
+ }
+ }
+
+ //on-curve points
+ if(ftoutline.tags[l] == FT_Curve_Tag_On) {
+ //left handle
+ if(k > 0) {
+ if(ftoutline.tags[l - 1] == FT_Curve_Tag_Cubic) {
+ bezt->vec[0][0] = ftoutline.points[l-1].x* scale;
+ bezt->vec[0][1] = ftoutline.points[l-1].y* scale;
+ bezt->h1= HD_FREE;
+ } else if(ftoutline.tags[l - 1] == FT_Curve_Tag_Conic) {
+ bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l - 1].x))* scale / 3.0;
+ bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l - 1].y))* scale / 3.0;
+ bezt->h1= HD_FREE;
+ } else {
+ bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l-1].x)* scale / 3.0;
+ bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l-1].y)* scale / 3.0;
+ bezt->h1= HD_VECT;
+ }
+ } else { //first point on curve
+ if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Cubic) {
+ bezt->vec[0][0] = ftoutline.points[ftoutline.contours[j]].x * scale;
+ bezt->vec[0][1] = ftoutline.points[ftoutline.contours[j]].y * scale;
+ bezt->h1= HD_FREE;
+ } else if(ftoutline.tags[ftoutline.contours[j]] == FT_Curve_Tag_Conic) {
+ bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[ftoutline.contours[j]].x))* scale / 3.0 ;
+ bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[ftoutline.contours[j]].y))* scale / 3.0 ;
+ bezt->h1= HD_FREE;
+ } else {
+ bezt->vec[0][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[ftoutline.contours[j]].x)* scale / 3.0;
+ bezt->vec[0][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[ftoutline.contours[j]].y)* scale / 3.0;
+ bezt->h1= HD_VECT;
+ }
+ }
+
+ //midpoint (on-curve point)
+ bezt->vec[1][0] = ftoutline.points[l].x* scale;
+ bezt->vec[1][1] = ftoutline.points[l].y* scale;
+
+ //right handle
+ if(k < (npoints[j] - 1)) {
+ if(ftoutline.tags[l+1] == FT_Curve_Tag_Cubic) {
+ bezt->vec[2][0] = ftoutline.points[l+1].x* scale;
+ bezt->vec[2][1] = ftoutline.points[l+1].y* scale;
+ bezt->h2= HD_FREE;
+ } else if(ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
+ bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l+1].x))* scale / 3.0;
+ bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l+1].y))* scale / 3.0;
+ bezt->h2= HD_FREE;
+ } else {
+ bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[l+1].x)* scale / 3.0;
+ bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[l+1].y)* scale / 3.0;
+ bezt->h2= HD_VECT;
+ }
+ } else { //last point on curve
+ if(ftoutline.tags[m] == FT_Curve_Tag_Cubic) {
+ bezt->vec[2][0] = ftoutline.points[m].x* scale;
+ bezt->vec[2][1] = ftoutline.points[m].y* scale;
+ bezt->h2= HD_FREE;
+ } else if(ftoutline.tags[m] == FT_Curve_Tag_Conic) {
+ bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[m].x))* scale / 3.0 ;
+ bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[m].y))* scale / 3.0 ;
+ bezt->h2= HD_FREE;
+ } else {
+ bezt->vec[2][0] = ftoutline.points[l].x* scale - (ftoutline.points[l].x - ftoutline.points[m].x)* scale / 3.0;
+ bezt->vec[2][1] = ftoutline.points[l].y* scale - (ftoutline.points[l].y - ftoutline.points[m].y)* scale / 3.0;
+ bezt->h2= HD_VECT;
+ }
+ }
+
+ // get the handles that are aligned, tricky...
+ // DistVL2Dfl, check if the three beztriple points are on one line
+ // VecLenf, see if there's a distance between the three points
+ // VecLenf again, to check the angle between the handles
+ // finally, check if one of them is a vector handle
+ if((DistVL2Dfl(bezt->vec[0],bezt->vec[1],bezt->vec[2]) < 0.001) &&
+ (VecLenf(bezt->vec[0], bezt->vec[1]) > 0.0001) &&
+ (VecLenf(bezt->vec[1], bezt->vec[2]) > 0.0001) &&
+ (VecLenf(bezt->vec[0], bezt->vec[2]) > 0.0002) &&
+ (VecLenf(bezt->vec[0], bezt->vec[2]) > MAX2(VecLenf(bezt->vec[0], bezt->vec[1]), VecLenf(bezt->vec[1], bezt->vec[2]))) &&
+ bezt->h1 != HD_VECT && bezt->h2 != HD_VECT)
+ {
+ bezt->h1= bezt->h2= HD_ALIGN;
+ }
+ bezt++;
+ }
+ }
+ }
+ if(npoints) MEM_freeN(npoints);
+ if(onpoints) MEM_freeN(onpoints);
+ }
+}
+
+int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
+{
+ // Freetype2
+ FT_Face face;
+ struct TmpFont *tf;
+
+ // Find the correct FreeType font
+ tf= G.ttfdata.first;
+ while(tf)
+ {
+ if(tf->vfont == vfont)
+ break;
+ tf= tf->next;
+ }
+
+ // What, no font found. Something strange here
+ if(!tf) return FALSE;
+
+ // Load the font to memory
+ if(tf->pf)
+ {
+ err= FT_New_Memory_Face( library,
+ tf->pf->data,
+ tf->pf->size,
+ 0,
+ &face);
+ }
+ else
+ err= TRUE;
+
+ // Read the char
+ freetypechar_to_vchar(face, charcode, vfont->data);
+
+ // And everything went ok
+ return TRUE;
+}
+
+
+static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+{
+ // Variables
+ FT_Face face;
+ FT_ULong charcode = 0, lcode;
+ FT_UInt glyph_index;
+ const char *fontname;
+ VFontData *vfd;
+
+/*
+ FT_CharMap found = 0;
+ FT_CharMap charmap;
+ FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
+ FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
+ int n;
+*/
+
+ // load the freetype font
+ err = FT_New_Memory_Face( library,
+ pf->data,
+ pf->size,
+ 0,
+ &face );
+
+ if(err) return NULL;
+/*
+ for ( n = 0; n < face->num_charmaps; n++ )
+ {
+ charmap = face->charmaps[n];
+ if ( charmap->platform_id == my_platform_id &&
+ charmap->encoding_id == my_encoding_id )
+ {
+ found = charmap;
+ break;
+ }
+ }
+
+ if ( !found ) { return NULL; }
+
+ // now, select the charmap for the face object
+ err = FT_Set_Charmap( face, found );
+ if ( err ) { return NULL; }
+*/
+
+ // allocate blender font
+ vfd= MEM_callocN(sizeof(*vfd), "FTVFontData");
+
+ // get the name
+ fontname = FT_Get_Postscript_Name(face);
+ strcpy(vfd->name, (fontname == NULL) ? "Fontname not available" : fontname);
+
+ // Extract the first 256 character from TTF
+ lcode= charcode= FT_Get_First_Char(face, &glyph_index);
+
+ // No charmap found from the ttf so we need to figure it out
+ if(glyph_index == 0)
+ {
+ FT_CharMap found = 0;
+ FT_CharMap charmap;
+ int n;
+
+ for ( n = 0; n < face->num_charmaps; n++ )
+ {
+ charmap = face->charmaps[n];
+ if (charmap->encoding == FT_ENCODING_APPLE_ROMAN)
+ {
+ found = charmap;
+ break;
+ }
+ }
+
+ err = FT_Set_Charmap( face, found );
+
+ if( err )
+ return NULL;
+
+ lcode= charcode= FT_Get_First_Char(face, &glyph_index);
+ }
+
+ // Load characters
+ while(charcode < 256)
+ {
+ // Generate the font data
+ freetypechar_to_vchar(face, charcode, vfd);
+
+ // Next glyph
+ charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
+
+ // Check that we won't start infinite loop
+ if(charcode <= lcode)
+ break;
+ lcode = charcode;
+ }
+
+ err = FT_Set_Charmap( face, (FT_CharMap) FT_ENCODING_UNICODE );
+
+ return vfd;
+}
+
+
+static int check_freetypefont(PackedFile * pf)
+{
+ FT_Face face;
+ FT_GlyphSlot glyph;
+ FT_UInt glyph_index;
+/*
+ FT_CharMap charmap;
+ FT_CharMap found;
+ FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
+ FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
+ int n;
+*/
+ int success = 0;
+
+ err = FT_New_Memory_Face( library,
+ pf->data,
+ pf->size,
+ 0,
+ &face );
+ if(err) {
+ success = 0;
+ error("This is not a valid font");
+ }
+ else {
+/*
+ for ( n = 0; n < face->num_charmaps; n++ )
+ {
+ charmap = face->charmaps[n];
+ if ( charmap->platform_id == my_platform_id &&
+ charmap->encoding_id == my_encoding_id )
+ {
+ found = charmap;
+ break;
+ }
+ }
+
+ if ( !found ) { return 0; }
+
+ // now, select the charmap for the face object
+ err = FT_Set_Charmap( face, found );
+ if ( err ) { return 0; }
+*/
+ glyph_index = FT_Get_Char_Index( face, 'A' );
+ err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+ if(err) success = 0;
+ else {
+ glyph = face->glyph;
+ if (glyph->format == ft_glyph_format_outline ) {
+ success = 1;
+ } else {
+ error("Selected Font has no outline data");
+ success = 0;
+ }
+ }
+ }
+
+ return success;
+}
+
+
+VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
+{
+ VFontData *vfd= NULL;
+ int success = 0;
+
+ //init Freetype
+ err = FT_Init_FreeType( &library);
+ if(err) {
+ error("Failed to load the Freetype font library");
+ return 0;
+ }
+
+ success = check_freetypefont(pf);
+
+ if (success) {
+ vfd= objfnt_to_ftvfontdata(pf);
+ }
+
+ //free Freetype
+ FT_Done_FreeType( library);
+
+ return vfd;
+}
+
+int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
+{
+ int success = FALSE;
+
+ if(!vfont) return FALSE;
+
+ // Init Freetype
+ err = FT_Init_FreeType(&library);
+ if(err) {
+ error("Failed to load the Freetype font library");
+ return 0;
+ }
+
+ // Load the character
+ success = objchr_to_ftvfontdata(vfont, character);
+ if(success == FALSE) return FALSE;
+
+ // Free Freetype
+ FT_Done_FreeType(library);
+
+ // Ahh everything ok
+ return TRUE;
+}
+
+#endif // WITH_FREETYPE2
+
+
+
+#if 0
+
+// Freetype2 Outline struct
+
+typedef struct FT_Outline_
+ {
+ short n_contours; /* number of contours in glyph */
+ short n_points; /* number of points in the glyph */
+
+ FT_Vector* points; /* the outline's points */
+ char* tags; /* the points flags */
+ short* contours; /* the contour end points */
+
+ int flags; /* outline masks */
+
+ } FT_Outline;
+
+#endif
+
+/***//*
+from: http://www.freetype.org/freetype2/docs/glyphs/glyphs-6.html#section-1
+
+Vectorial representation of Freetype glyphs
+
+The source format of outlines is a collection of closed paths called "contours". Each contour is
+made of a series of line segments and bezier arcs. Depending on the file format, these can be
+second-order or third-order polynomials. The former are also called quadratic or conic arcs, and
+they come from the TrueType format. The latter are called cubic arcs and mostly come from the
+Type1 format.
+
+Each arc is described through a series of start, end and control points. Each point of the outline
+has a specific tag which indicates wether it is used to describe a line segment or an arc.
+
+
+The following rules are applied to decompose the contour's points into segments and arcs :
+
+# two successive "on" points indicate a line segment joining them.
+
+# one conic "off" point amidst two "on" points indicates a conic bezier arc, the "off" point being
+ the control point, and the "on" ones the start and end points.
+
+# Two successive cubic "off" points amidst two "on" points indicate a cubic bezier arc. There must
+ be exactly two cubic control points and two on points for each cubic arc (using a single cubic
+ "off" point between two "on" points is forbidden, for example).
+
+# finally, two successive conic "off" points forces the rasterizer to create (during the scan-line
+ conversion process exclusively) a virtual "on" point amidst them, at their exact middle. This
+ greatly facilitates the definition of successive conic bezier arcs. Moreover, it's the way
+ outlines are described in the TrueType specification.
+
+Note that it is possible to mix conic and cubic arcs in a single contour, even though no current
+font driver produces such outlines.
+
+ * # on
+ * off
+ __---__
+ #-__ _-- -_
+ --__ _- -
+ --__ # \
+ --__ #
+ -#
+ Two "on" points
+ Two "on" points and one "conic" point
+ between them
+
+
+
+ *
+ # __ Two "on" points with two "conic"
+ \ - - points between them. The point
+ \ / \ marked '0' is the middle of the
+ - 0 \ "off" points, and is a 'virtual'
+ -_ _- # "on" point where the curve passes.
+ -- It does not appear in the point
+ list.
+ *
+
+
+
+
+ * # on
+ * * off
+ __---__
+ _-- -_
+ _- -
+ # \
+ #
+
+ Two "on" points
+ and two "cubic" point
+ between them
+
+
+Each glyph's original outline points are located on a grid of indivisible units. The points are stored
+in the font file as 16-bit integer grid coordinates, with the grid origin's being at (0,0); they thus
+range from -16384 to 16383.
+
+Convert conic to bezier arcs:
+Conic P0 P1 P2
+Bezier B0 B1 B2 B3
+B0=P0
+B1=(P0+2*P1)/3
+B2=(P2+2*P1)/3
+B3=P2
+
+*//****/
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
new file mode 100644
index 00000000000..e52c573eec7
--- /dev/null
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -0,0 +1,122 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+#include "BLI_gsqueue.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+typedef struct _GSQueueElem GSQueueElem;
+struct _GSQueueElem {
+ GSQueueElem *next;
+};
+
+struct _GSQueue {
+ GSQueueElem *head;
+ GSQueueElem *tail;
+ int elem_size;
+};
+
+GSQueue *BLI_gsqueue_new(int elem_size)
+{
+ GSQueue *gq= MEM_mallocN(sizeof(*gq), "gqueue_new");
+ gq->head= gq->tail= NULL;
+ gq->elem_size= elem_size;
+
+ return gq;
+}
+
+int BLI_gsqueue_is_empty(GSQueue *gq)
+{
+ return (gq->head==NULL);
+}
+
+void BLI_gsqueue_peek(GSQueue *gq, void *item_r)
+{
+ memcpy(item_r, &gq->head[1], gq->elem_size);
+}
+void BLI_gsqueue_pop(GSQueue *gq, void *item_r)
+{
+ GSQueueElem *elem= gq->head;
+ if (elem==gq->tail) {
+ gq->head= gq->tail= NULL;
+ } else {
+ gq->head= gq->head->next;
+ }
+
+ if (item_r) memcpy(item_r, &elem[1], gq->elem_size);
+ MEM_freeN(elem);
+}
+void BLI_gsqueue_push(GSQueue *gq, void *item)
+{
+ GSQueueElem *elem;
+
+ /* compare: prevent events added double in row */
+ if (!BLI_gsqueue_is_empty(gq)) {
+ if(0==memcmp(item, &gq->head[1], gq->elem_size))
+ return;
+ }
+ elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, gq->elem_size);
+ elem->next= NULL;
+
+ if (BLI_gsqueue_is_empty(gq)) {
+ gq->tail= gq->head= elem;
+ } else {
+ gq->tail= gq->tail->next= elem;
+ }
+}
+void BLI_gsqueue_pushback(GSQueue *gq, void *item)
+{
+ GSQueueElem *elem= MEM_mallocN(sizeof(*elem)+gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, gq->elem_size);
+ elem->next= gq->head;
+
+ if (BLI_gsqueue_is_empty(gq)) {
+ gq->head= gq->tail= elem;
+ } else {
+ gq->head= elem;
+ }
+}
+
+void BLI_gsqueue_free(GSQueue *gq)
+{
+ while (gq->head) {
+ BLI_gsqueue_pop(gq, NULL);
+ }
+ MEM_freeN(gq);
+}
+
+
diff --git a/source/blender/blenlib/intern/jitter.c b/source/blender/blenlib/intern/jitter.c
new file mode 100644
index 00000000000..fd658765802
--- /dev/null
+++ b/source/blender/blenlib/intern/jitter.c
@@ -0,0 +1,178 @@
+/**
+ * Jitter offset table
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_rand.h"
+#include "BLI_jitter.h"
+
+
+void BLI_jitterate1(float *jit1, float *jit2, int num, float rad1)
+{
+ int i , j , k;
+ float vecx, vecy, dvecx, dvecy, x, y, len;
+
+ for (i = 2*num-2; i>=0 ; i-=2) {
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j = 2*num-2; j>=0 ; j-=2) {
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+ for (k = 3; k>0 ; k--){
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx += 1.0;
+
+ if( fabs(vecx)<rad1 && fabs(vecy)<rad1) {
+ len= sqrt(vecx*vecx + vecy*vecy);
+ if(len>0 && len<rad1) {
+ len= len/rad1;
+ dvecx += vecx/len;
+ dvecy += vecy/len;
+ }
+ }
+ vecx -= 2.0;
+ vecy += 1.0;
+ }
+ }
+ }
+
+ x -= dvecx/18.0 ;
+ y -= dvecy/18.0;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+void BLI_jitterate2(float *jit1, float *jit2, int num, float rad2)
+{
+ int i, j;
+ float vecx, vecy, dvecx, dvecy, x, y;
+
+ for (i=2*num -2; i>= 0 ; i-=2){
+ dvecx = dvecy = 0.0;
+ x = jit1[i];
+ y = jit1[i+1];
+ for (j =2*num -2; j>= 0 ; j-=2){
+ if (i != j){
+ vecx = jit1[j] - x - 1.0;
+ vecy = jit1[j+1] - y - 1.0;
+
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+ vecx += 1.0;
+ if( fabs(vecx)<rad2) dvecx+= vecx*rad2;
+
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+ vecy += 1.0;
+ if( fabs(vecy)<rad2) dvecy+= vecy*rad2;
+
+ }
+ }
+
+ x -= dvecx/2 ;
+ y -= dvecy/2;
+ x -= floor(x) ;
+ y -= floor(y);
+ jit2[i] = x;
+ jit2[i+1] = y;
+ }
+ memcpy(jit1,jit2,2 * num * sizeof(float));
+}
+
+
+void BLI_initjit(float *jitarr, int num)
+{
+ float *jit2, x, rad1, rad2, rad3;
+ int i;
+
+ if(num==0) return;
+
+ jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
+ rad1= 1.0/sqrt((float)num);
+ rad2= 1.0/((float)num);
+ rad3= sqrt((float)num)/((float)num);
+
+ BLI_srand(31415926 + num);
+ x= 0;
+ for(i=0; i<2*num; i+=2) {
+ jitarr[i]= x+ rad1*(0.5-BLI_drand());
+ jitarr[i+1]= ((float)i/2)/num +rad1*(0.5-BLI_drand());
+ x+= rad3;
+ x -= floor(x);
+ }
+
+ for (i=0 ; i<24 ; i++) {
+ BLI_jitterate1(jitarr, jit2, num, rad1);
+ BLI_jitterate1(jitarr, jit2, num, rad1);
+ BLI_jitterate2(jitarr, jit2, num, rad2);
+ }
+
+ MEM_freeN(jit2);
+
+ /* finally, move jittertab to be centered around (0,0) */
+ for(i=0; i<2*num; i+=2) {
+ jitarr[i] -= 0.5;
+ jitarr[i+1] -= 0.5;
+ }
+
+}
+
+
+/* eof */
diff --git a/source/blender/blenlib/intern/matrixops.c b/source/blender/blenlib/intern/matrixops.c
new file mode 100644
index 00000000000..62098d5fa90
--- /dev/null
+++ b/source/blender/blenlib/intern/matrixops.c
@@ -0,0 +1,441 @@
+/*
+ *
+ * Some matrix operations.
+ *
+ * Always use
+ * - vector with x components : float x[3], int x[3], etc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* ------------------------------------------------------------------------- */
+#include <string.h>
+#include "MTC_matrixops.h"
+#include "MTC_vectorops.h"
+/* ------------------------------------------------------------------------- */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__)
+#include <strings.h>
+#endif
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+void MTC_Mat4CpyMat4(float m1[][4], float m2[][4])
+{
+ memcpy(m1, m2, 4*4*sizeof(float));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulSerie(float answ[][4],
+ float m1[][4], float m2[][4], float m3[][4],
+ float m4[][4], float m5[][4], float m6[][4],
+ float m7[][4], float m8[][4])
+{
+ float temp[4][4];
+
+ if(m1==0 || m2==0) return;
+
+ MTC_Mat4MulMat4(answ, m2, m1);
+ if(m3) {
+ MTC_Mat4MulMat4(temp, m3, answ);
+ if(m4) {
+ MTC_Mat4MulMat4(answ, m4, temp);
+ if(m5) {
+ MTC_Mat4MulMat4(temp, m5, answ);
+ if(m6) {
+ MTC_Mat4MulMat4(answ, m6, temp);
+ if(m7) {
+ MTC_Mat4MulMat4(temp, m7, answ);
+ if(m8) {
+ MTC_Mat4MulMat4(answ, m8, temp);
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+ }
+ else MTC_Mat4CpyMat4(answ, temp);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4])
+{
+ /* matrix product: c[j][k] = a[j][i].b[i][k] */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2];
+ m1[0][3] = m2[0][0]*m3[0][3] + m2[0][1]*m3[1][3] + m2[0][2]*m3[2][3] + m2[0][3]*m3[3][3];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0] + m2[1][3]*m3[3][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1] + m2[1][3]*m3[3][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2] + m2[1][3]*m3[3][2];
+ m1[1][3] = m2[1][0]*m3[0][3] + m2[1][1]*m3[1][3] + m2[1][2]*m3[2][3] + m2[1][3]*m3[3][3];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0] + m2[2][3]*m3[3][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1] + m2[2][3]*m3[3][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2] + m2[2][3]*m3[3][2];
+ m1[2][3] = m2[2][0]*m3[0][3] + m2[2][1]*m3[1][3] + m2[2][2]*m3[2][3] + m2[2][3]*m3[3][3];
+
+ m1[3][0] = m2[3][0]*m3[0][0] + m2[3][1]*m3[1][0] + m2[3][2]*m3[2][0] + m2[3][3]*m3[3][0];
+ m1[3][1] = m2[3][0]*m3[0][1] + m2[3][1]*m3[1][1] + m2[3][2]*m3[2][1] + m2[3][3]*m3[3][1];
+ m1[3][2] = m2[3][0]*m3[0][2] + m2[3][1]*m3[1][2] + m2[3][2]*m3[2][2] + m2[3][3]*m3[3][2];
+ m1[3][3] = m2[3][0]*m3[0][3] + m2[3][1]*m3[1][3] + m2[3][2]*m3[2][3] + m2[3][3]*m3[3][3];
+
+}
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulVecfl(float mat[][4], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
+ vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
+ vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat3MulVecfl(float mat[][3], float *vec)
+{
+ float x,y;
+
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+int MTC_Mat4Invert(float inverse[][4], float mat[][4])
+{
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ /* Set inverse to identity */
+ for (i=0; i<4; i++)
+ for (j=0; j<4; j++)
+ inverse[i][j] = 0;
+ for (i=0; i<4; i++)
+ inverse[i][i] = 1;
+
+ /* Copy original matrix so we don't mess it up */
+ for(i = 0; i < 4; i++)
+ for(j = 0; j <4; j++)
+ tempmat[i][j] = mat[i][j];
+
+ for(i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = ABS(tempmat[i][i]);
+ maxj = i;
+ for(j = i + 1; j < 4; j++) {
+ if(ABS(tempmat[j][i]) > max) {
+ max = ABS(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for( k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ temp = tempmat[i][i];
+ if (temp == 0)
+ return 0; /* No non-zero pivot */
+ for(k = 0; k < 4; k++) {
+ tempmat[i][k] /= temp;
+ inverse[i][k] /= temp;
+ }
+ for(j = 0; j < 4; j++) {
+ if(j != i) {
+ temp = tempmat[j][i];
+ for(k = 0; k < 4; k++) {
+ tempmat[j][k] -= tempmat[i][k]*temp;
+ inverse[j][k] -= inverse[i][k]*temp;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_Mat3CpyMat4(float m1[][3], float m2[][4])
+{
+
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3CpyMat3(float m1[][3], float m2[][3])
+{
+ memcpy(m1, m2, 3*3*sizeof(float));
+}
+
+/* ------------------------------------------------------------------------- */
+/* void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+void MTC_Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3])
+{
+ /* be careful about this rewrite... */
+ /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */
+ m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+/* m1+=3; */
+/* m2+=3; */
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+/* m1+=3; */
+/* m2+=3; */
+/* m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6]; */
+/* m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7]; */
+/* m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8]; */
+} /* end of void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4Ortho(float mat[][4])
+{
+ float len;
+
+ len= MTC_normalize3DF(mat[0]);
+ if(len!=0.0) mat[0][3]/= len;
+ len= MTC_normalize3DF(mat[1]);
+ if(len!=0.0) mat[1][3]/= len;
+ len= MTC_normalize3DF(mat[2]);
+ if(len!=0.0) mat[2][3]/= len;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4Mul3Vecfl(float mat[][4], float *vec)
+{
+ float x,y;
+ /* vec = mat^T dot vec !!! or vec a row, then vec = vec dot mat*/
+
+ x= vec[0];
+ y= vec[1];
+ vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
+ vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
+ vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4One(float m[][4])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
+ m[0][1]= m[0][2]= m[0][3]= 0.0;
+ m[1][0]= m[1][2]= m[1][3]= 0.0;
+ m[2][0]= m[2][1]= m[2][3]= 0.0;
+ m[3][0]= m[3][1]= m[3][2]= 0.0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* Result is a 3-vector!*/
+void MTC_Mat3MulVecd(float mat[][3], double *vec)
+{
+ double x,y;
+
+ /* vec = mat^T dot vec !!! or vec a row, then vec = vec dot mat*/
+ x=vec[0];
+ y=vec[1];
+ vec[0]= x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
+ vec[1]= x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
+ vec[2]= x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3Inv(float m1[][3], float m2[][3])
+{
+ short a,b;
+ float det;
+
+ /* first adjoint */
+ MTC_Mat3Adj(m1,m2);
+
+ /* then determinant old mat! */
+ det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
+ -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
+ +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
+
+ if(det==0) det=1;
+ det= 1/det;
+ for(a=0;a<3;a++) {
+ for(b=0;b<3;b++) {
+ m1[a][b]*=det;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3Adj(float m1[][3], float m[][3])
+{
+ m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1];
+ m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1];
+ m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1];
+
+ m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0];
+ m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0];
+ m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0];
+
+ m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
+ m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0];
+ m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat3One(float m[][3])
+{
+
+ m[0][0]= m[1][1]= m[2][2]= 1.0;
+ m[0][1]= m[0][2]= 0.0;
+ m[1][0]= m[1][2]= 0.0;
+ m[2][0]= m[2][1]= 0.0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4SwapMat4(float m1[][4], float m2[][4])
+{
+ float t;
+ int i, j;
+
+ for(i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ t = m1[i][j];
+ m1[i][j] = m2[i][j];
+ m2[i][j] = t;
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulVec4fl(float mat[][4], float *vec)
+{
+ float x,y,z;
+
+ x = vec[0];
+ y = vec[1];
+ z = vec[2];
+ vec[0] = x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3];
+ vec[1] = x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3];
+ vec[2] = x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3];
+ vec[3] = x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4CpyMat3nc(float m1[][4], float m2[][3]) /* no clear */
+{
+ m1[0][0]= m2[0][0];
+ m1[0][1]= m2[0][1];
+ m1[0][2]= m2[0][2];
+
+ m1[1][0]= m2[1][0];
+ m1[1][1]= m2[1][1];
+ m1[1][2]= m2[1][2];
+
+ m1[2][0]= m2[2][0];
+ m1[2][1]= m2[2][1];
+ m1[2][2]= m2[2][2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_Mat4MulMat33(float m1[][3], float m2[][4], float m3[][3])
+{
+ /* m1_i_j = m2_i_k * m3_k_j ? */
+
+ m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
+ m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
+ m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
+
+ m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
+ m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
+ m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
+
+ m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
+ m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
+ m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
new file mode 100644
index 00000000000..4fa2d1fdd48
--- /dev/null
+++ b/source/blender/blenlib/intern/noise.c
@@ -0,0 +1,1392 @@
+/*
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#ifdef _WIN32
+#pragma warning (disable : 4244) // "conversion from double to float"
+#pragma warning (disable : 4305) // "truncation from const double to float"
+#endif
+
+#include <math.h>
+#include "BLI_blenlib.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* local */
+float noise3_perlin(float vec[3]);
+float turbulence_perlin(float *point, float lofreq, float hifreq);
+float turbulencep(float noisesize, float x, float y, float z, int nr);
+
+#define HASHVEC(x,y,z) hashvectf+3*hash[ (hash[ (hash[(z) & 255]+(y)) & 255]+(x)) & 255]
+
+/* needed for voronoi */
+#define HASHPNT(x,y,z) hashpntf+3*hash[ (hash[ (hash[(z) & 255]+(y)) & 255]+(x)) & 255]
+static float hashpntf[768] = {0.536902, 0.020915, 0.501445, 0.216316, 0.517036, 0.822466, 0.965315,
+0.377313, 0.678764, 0.744545, 0.097731, 0.396357, 0.247202, 0.520897,
+0.613396, 0.542124, 0.146813, 0.255489, 0.810868, 0.638641, 0.980742,
+0.292316, 0.357948, 0.114382, 0.861377, 0.629634, 0.722530, 0.714103,
+0.048549, 0.075668, 0.564920, 0.162026, 0.054466, 0.411738, 0.156897,
+0.887657, 0.599368, 0.074249, 0.170277, 0.225799, 0.393154, 0.301348,
+0.057434, 0.293849, 0.442745, 0.150002, 0.398732, 0.184582, 0.915200,
+0.630984, 0.974040, 0.117228, 0.795520, 0.763238, 0.158982, 0.616211,
+0.250825, 0.906539, 0.316874, 0.676205, 0.234720, 0.667673, 0.792225,
+0.273671, 0.119363, 0.199131, 0.856716, 0.828554, 0.900718, 0.705960,
+0.635923, 0.989433, 0.027261, 0.283507, 0.113426, 0.388115, 0.900176,
+0.637741, 0.438802, 0.715490, 0.043692, 0.202640, 0.378325, 0.450325,
+0.471832, 0.147803, 0.906899, 0.524178, 0.784981, 0.051483, 0.893369,
+0.596895, 0.275635, 0.391483, 0.844673, 0.103061, 0.257322, 0.708390,
+0.504091, 0.199517, 0.660339, 0.376071, 0.038880, 0.531293, 0.216116,
+0.138672, 0.907737, 0.807994, 0.659582, 0.915264, 0.449075, 0.627128,
+0.480173, 0.380942, 0.018843, 0.211808, 0.569701, 0.082294, 0.689488,
+0.573060, 0.593859, 0.216080, 0.373159, 0.108117, 0.595539, 0.021768,
+0.380297, 0.948125, 0.377833, 0.319699, 0.315249, 0.972805, 0.792270,
+0.445396, 0.845323, 0.372186, 0.096147, 0.689405, 0.423958, 0.055675,
+0.117940, 0.328456, 0.605808, 0.631768, 0.372170, 0.213723, 0.032700,
+0.447257, 0.440661, 0.728488, 0.299853, 0.148599, 0.649212, 0.498381,
+0.049921, 0.496112, 0.607142, 0.562595, 0.990246, 0.739659, 0.108633,
+0.978156, 0.209814, 0.258436, 0.876021, 0.309260, 0.600673, 0.713597,
+0.576967, 0.641402, 0.853930, 0.029173, 0.418111, 0.581593, 0.008394,
+0.589904, 0.661574, 0.979326, 0.275724, 0.111109, 0.440472, 0.120839,
+0.521602, 0.648308, 0.284575, 0.204501, 0.153286, 0.822444, 0.300786,
+0.303906, 0.364717, 0.209038, 0.916831, 0.900245, 0.600685, 0.890002,
+0.581660, 0.431154, 0.705569, 0.551250, 0.417075, 0.403749, 0.696652,
+0.292652, 0.911372, 0.690922, 0.323718, 0.036773, 0.258976, 0.274265,
+0.225076, 0.628965, 0.351644, 0.065158, 0.080340, 0.467271, 0.130643,
+0.385914, 0.919315, 0.253821, 0.966163, 0.017439, 0.392610, 0.478792,
+0.978185, 0.072691, 0.982009, 0.097987, 0.731533, 0.401233, 0.107570,
+0.349587, 0.479122, 0.700598, 0.481751, 0.788429, 0.706864, 0.120086,
+0.562691, 0.981797, 0.001223, 0.192120, 0.451543, 0.173092, 0.108960,
+0.549594, 0.587892, 0.657534, 0.396365, 0.125153, 0.666420, 0.385823,
+0.890916, 0.436729, 0.128114, 0.369598, 0.759096, 0.044677, 0.904752,
+0.088052, 0.621148, 0.005047, 0.452331, 0.162032, 0.494238, 0.523349,
+0.741829, 0.698450, 0.452316, 0.563487, 0.819776, 0.492160, 0.004210,
+0.647158, 0.551475, 0.362995, 0.177937, 0.814722, 0.727729, 0.867126,
+0.997157, 0.108149, 0.085726, 0.796024, 0.665075, 0.362462, 0.323124,
+0.043718, 0.042357, 0.315030, 0.328954, 0.870845, 0.683186, 0.467922,
+0.514894, 0.809971, 0.631979, 0.176571, 0.366320, 0.850621, 0.505555,
+0.749551, 0.750830, 0.401714, 0.481216, 0.438393, 0.508832, 0.867971,
+0.654581, 0.058204, 0.566454, 0.084124, 0.548539, 0.902690, 0.779571,
+0.562058, 0.048082, 0.863109, 0.079290, 0.713559, 0.783496, 0.265266,
+0.672089, 0.786939, 0.143048, 0.086196, 0.876129, 0.408708, 0.229312,
+0.629995, 0.206665, 0.207308, 0.710079, 0.341704, 0.264921, 0.028748,
+0.629222, 0.470173, 0.726228, 0.125243, 0.328249, 0.794187, 0.741340,
+0.489895, 0.189396, 0.724654, 0.092841, 0.039809, 0.860126, 0.247701,
+0.655331, 0.964121, 0.672536, 0.044522, 0.690567, 0.837238, 0.631520,
+0.953734, 0.352484, 0.289026, 0.034152, 0.852575, 0.098454, 0.795529,
+0.452181, 0.826159, 0.186993, 0.820725, 0.440328, 0.922137, 0.704592,
+0.915437, 0.738183, 0.733461, 0.193798, 0.929213, 0.161390, 0.318547,
+0.888751, 0.430968, 0.740837, 0.193544, 0.872253, 0.563074, 0.274598,
+0.347805, 0.666176, 0.449831, 0.800991, 0.588727, 0.052296, 0.714761,
+0.420620, 0.570325, 0.057550, 0.210888, 0.407312, 0.662848, 0.924382,
+0.895958, 0.775198, 0.688605, 0.025721, 0.301913, 0.791408, 0.500602,
+0.831984, 0.828509, 0.642093, 0.494174, 0.525880, 0.446365, 0.440063,
+0.763114, 0.630358, 0.223943, 0.333806, 0.906033, 0.498306, 0.241278,
+0.427640, 0.772683, 0.198082, 0.225379, 0.503894, 0.436599, 0.016503,
+0.803725, 0.189878, 0.291095, 0.499114, 0.151573, 0.079031, 0.904618,
+0.708535, 0.273900, 0.067419, 0.317124, 0.936499, 0.716511, 0.543845,
+0.939909, 0.826574, 0.715090, 0.154864, 0.750150, 0.845808, 0.648108,
+0.556564, 0.644757, 0.140873, 0.799167, 0.632989, 0.444245, 0.471978,
+0.435910, 0.359793, 0.216241, 0.007633, 0.337236, 0.857863, 0.380247,
+0.092517, 0.799973, 0.919000, 0.296798, 0.096989, 0.854831, 0.165369,
+0.568475, 0.216855, 0.020457, 0.835511, 0.538039, 0.999742, 0.620226,
+0.244053, 0.060399, 0.323007, 0.294874, 0.988899, 0.384919, 0.735655,
+0.773428, 0.549776, 0.292882, 0.660611, 0.593507, 0.621118, 0.175269,
+0.682119, 0.794493, 0.868197, 0.632150, 0.807823, 0.509656, 0.482035,
+0.001780, 0.259126, 0.358002, 0.280263, 0.192985, 0.290367, 0.208111,
+0.917633, 0.114422, 0.925491, 0.981110, 0.255570, 0.974862, 0.016629,
+0.552599, 0.575741, 0.612978, 0.615965, 0.803615, 0.772334, 0.089745,
+0.838812, 0.634542, 0.113709, 0.755832, 0.577589, 0.667489, 0.529834,
+0.325660, 0.817597, 0.316557, 0.335093, 0.737363, 0.260951, 0.737073,
+0.049540, 0.735541, 0.988891, 0.299116, 0.147695, 0.417271, 0.940811,
+0.524160, 0.857968, 0.176403, 0.244835, 0.485759, 0.033353, 0.280319,
+0.750688, 0.755809, 0.924208, 0.095956, 0.962504, 0.275584, 0.173715,
+0.942716, 0.706721, 0.078464, 0.576716, 0.804667, 0.559249, 0.900611,
+0.646904, 0.432111, 0.927885, 0.383277, 0.269973, 0.114244, 0.574867,
+0.150703, 0.241855, 0.272871, 0.199950, 0.079719, 0.868566, 0.962833,
+0.789122, 0.320025, 0.905554, 0.234876, 0.991356, 0.061913, 0.732911,
+0.785960, 0.874074, 0.069035, 0.658632, 0.309901, 0.023676, 0.791603,
+0.764661, 0.661278, 0.319583, 0.829650, 0.117091, 0.903124, 0.982098,
+0.161631, 0.193576, 0.670428, 0.857390, 0.003760, 0.572578, 0.222162,
+0.114551, 0.420118, 0.530404, 0.470682, 0.525527, 0.764281, 0.040596,
+0.443275, 0.501124, 0.816161, 0.417467, 0.332172, 0.447565, 0.614591,
+0.559246, 0.805295, 0.226342, 0.155065, 0.714630, 0.160925, 0.760001,
+0.453456, 0.093869, 0.406092, 0.264801, 0.720370, 0.743388, 0.373269,
+0.403098, 0.911923, 0.897249, 0.147038, 0.753037, 0.516093, 0.739257,
+0.175018, 0.045768, 0.735857, 0.801330, 0.927708, 0.240977, 0.591870,
+0.921831, 0.540733, 0.149100, 0.423152, 0.806876, 0.397081, 0.061100,
+0.811630, 0.044899, 0.460915, 0.961202, 0.822098, 0.971524, 0.867608,
+0.773604, 0.226616, 0.686286, 0.926972, 0.411613, 0.267873, 0.081937,
+0.226124, 0.295664, 0.374594, 0.533240, 0.237876, 0.669629, 0.599083,
+0.513081, 0.878719, 0.201577, 0.721296, 0.495038, 0.079760, 0.965959,
+0.233090, 0.052496, 0.714748, 0.887844, 0.308724, 0.972885, 0.723337,
+0.453089, 0.914474, 0.704063, 0.823198, 0.834769, 0.906561, 0.919600,
+0.100601, 0.307564, 0.901977, 0.468879, 0.265376, 0.885188, 0.683875,
+0.868623, 0.081032, 0.466835, 0.199087, 0.663437, 0.812241, 0.311337,
+0.821361, 0.356628, 0.898054, 0.160781, 0.222539, 0.714889, 0.490287,
+0.984915, 0.951755, 0.964097, 0.641795, 0.815472, 0.852732, 0.862074,
+0.051108, 0.440139, 0.323207, 0.517171, 0.562984, 0.115295, 0.743103,
+0.977914, 0.337596, 0.440694, 0.535879, 0.959427, 0.351427, 0.704361,
+0.010826, 0.131162, 0.577080, 0.349572, 0.774892, 0.425796, 0.072697,
+0.500001, 0.267322, 0.909654, 0.206176, 0.223987, 0.937698, 0.323423,
+0.117501, 0.490308, 0.474372, 0.689943, 0.168671, 0.719417, 0.188928,
+0.330464, 0.265273, 0.446271, 0.171933, 0.176133, 0.474616, 0.140182,
+0.114246, 0.905043, 0.713870, 0.555261, 0.951333};
+
+unsigned char hash[512]= {
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+};
+
+
+float hashvectf[768]= {
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+};
+
+/**************************/
+/* IMPROVED PERLIN NOISE */
+/**************************/
+
+#define lerp(t, a, b) ((a)+(t)*((b)-(a)))
+#define npfade(t) ((t)*(t)*(t)*((t)*((t)*6-15)+10))
+
+static float grad(int hash, float x, float y, float z)
+{
+ int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
+ float u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
+ v = h<4 ? y : h==12||h==14 ? x : z;
+ return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+}
+
+/* instead of adding another permutation array, just use hash table defined above */
+static float newPerlin(float x, float y, float z)
+{
+ int A, AA, AB, B, BA, BB;
+ float u=floor(x), v=floor(y), w=floor(z);
+ int X=((int)u) & 255, Y=((int)v) & 255, Z=((int)w) & 255; // FIND UNIT CUBE THAT CONTAINS POINT
+ x -= u; // FIND RELATIVE X,Y,Z
+ y -= v; // OF POINT IN CUBE.
+ z -= w;
+ u = npfade(x); // COMPUTE FADE CURVES
+ v = npfade(y); // FOR EACH OF X,Y,Z.
+ w = npfade(z);
+ A = hash[X ]+Y; AA = hash[A]+Z; AB = hash[A+1]+Z; // HASH COORDINATES OF
+ B = hash[X+1]+Y; BA = hash[B]+Z; BB = hash[B+1]+Z; // THE 8 CUBE CORNERS,
+ return lerp(w, lerp(v, lerp(u, grad(hash[AA ], x , y , z ), // AND ADD
+ grad(hash[BA ], x-1, y , z )), // BLENDED
+ lerp(u, grad(hash[AB ], x , y-1, z ), // RESULTS
+ grad(hash[BB ], x-1, y-1, z ))),// FROM 8
+ lerp(v, lerp(u, grad(hash[AA+1], x , y , z-1 ), // CORNERS
+ grad(hash[BA+1], x-1, y , z-1 )), // OF CUBE
+ lerp(u, grad(hash[AB+1], x , y-1, z-1 ),
+ grad(hash[BB+1], x-1, y-1, z-1 ))));
+}
+
+/* for use with BLI_gNoise()/BLI_gTurbulence(), returns unsigned improved perlin noise */
+static float newPerlinU(float x, float y, float z)
+{
+ return (0.5+0.5*newPerlin(x, y, z));
+}
+
+
+/**************************/
+/* END OF IMPROVED PERLIN */
+/**************************/
+
+/* Was BLI_hnoise(), removed noisesize, so other functions can call it without scaling. */
+static float orgBlenderNoise(float x, float y, float z)
+{
+ register float cn1, cn2, cn3, cn4, cn5, cn6, i, *h;
+ float ox, oy, oz, jx, jy, jz;
+ float n= 0.5;
+ int ix, iy, iz, b00, b01, b10, b11, b20, b21;
+
+ ox= (x- (ix= (int)floor(x)) );
+ oy= (y- (iy= (int)floor(y)) );
+ oz= (z- (iz= (int)floor(z)) );
+
+ jx= ox-1;
+ jy= oy-1;
+ jz= oz-1;
+
+ cn1=ox*ox; cn2=oy*oy; cn3=oz*oz;
+ cn4=jx*jx; cn5=jy*jy; cn6=jz*jz;
+
+ cn1= 1.0-3.0*cn1+2.0*cn1*ox;
+ cn2= 1.0-3.0*cn2+2.0*cn2*oy;
+ cn3= 1.0-3.0*cn3+2.0*cn3*oz;
+ cn4= 1.0-3.0*cn4-2.0*cn4*jx;
+ cn5= 1.0-3.0*cn5-2.0*cn5*jy;
+ cn6= 1.0-3.0*cn6-2.0*cn6*jz;
+
+ b00= hash[ hash[ix & 255]+(iy & 255)];
+ b10= hash[ hash[(ix+1) & 255]+(iy & 255)];
+ b01= hash[ hash[ix & 255]+((iy+1) & 255)];
+ b11= hash[ hash[(ix+1) & 255]+((iy+1) & 255)];
+
+ b20=iz & 255; b21= (iz+1) & 255;
+
+ /* 0 */
+ i= (cn1*cn2*cn3);
+ h=hashvectf+ 3*hash[b20+b00];
+ n+= i*(h[0]*ox+h[1]*oy+h[2]*oz);
+ /* 1 */
+ i= (cn1*cn2*cn6);
+ h=hashvectf+ 3*hash[b21+b00];
+ n+= i*(h[0]*ox+h[1]*oy+h[2]*jz);
+ /* 2 */
+ i= (cn1*cn5*cn3);
+ h=hashvectf+ 3*hash[b20+b01];
+ n+= i*(h[0]*ox+h[1]*jy+h[2]*oz);
+ /* 3 */
+ i= (cn1*cn5*cn6);
+ h=hashvectf+ 3*hash[b21+b01];
+ n+= i*(h[0]*ox+h[1]*jy+h[2]*jz);
+ /* 4 */
+ i= cn4*cn2*cn3;
+ h=hashvectf+ 3*hash[b20+b10];
+ n+= i*(h[0]*jx+h[1]*oy+h[2]*oz);
+ /* 5 */
+ i= cn4*cn2*cn6;
+ h=hashvectf+ 3*hash[b21+b10];
+ n+= i*(h[0]*jx+h[1]*oy+h[2]*jz);
+ /* 6 */
+ i= cn4*cn5*cn3;
+ h=hashvectf+ 3*hash[b20+b11];
+ n+= i*(h[0]*jx+h[1]*jy+h[2]*oz);
+ /* 7 */
+ i= (cn4*cn5*cn6);
+ h=hashvectf+ 3*hash[b21+b11];
+ n+= i*(h[0]*jx+h[1]*jy+h[2]*jz);
+
+ if(n<0.0) n=0.0; else if(n>1.0) n=1.0;
+ return n;
+}
+
+/* as orgBlenderNoise(), returning signed noise */
+static float orgBlenderNoiseS(float x, float y, float z)
+{
+ return (2.0*orgBlenderNoise(x, y, z)-1.0);
+}
+
+/* separated from orgBlenderNoise above, with scaling */
+float BLI_hnoise(float noisesize, float x, float y, float z)
+{
+ if(noisesize==0.0) return 0.0;
+ x= (1.0+x)/noisesize;
+ y= (1.0+y)/noisesize;
+ z= (1.0+z)/noisesize;
+ return orgBlenderNoise(x, y, z);
+}
+
+
+/* original turbulence functions */
+float BLI_turbulence(float noisesize, float x, float y, float z, int nr)
+{
+ float s, d= 0.5, div=1.0;
+
+ s= BLI_hnoise(noisesize, x, y, z);
+
+ while(nr>0) {
+
+ s+= d*BLI_hnoise(noisesize*d, x, y, z);
+ div+= d;
+ d*= 0.5;
+
+ nr--;
+ }
+ return s/div;
+}
+
+float BLI_turbulence1(float noisesize, float x, float y, float z, int nr)
+{
+ float s, d= 0.5, div=1.0;
+
+ s= fabs( (-1.0+2.0*BLI_hnoise(noisesize, x, y, z)));
+
+ while(nr>0) {
+
+ s+= fabs(d* (-1.0+2.0*BLI_hnoise(noisesize*d, x, y, z)));
+ div+= d;
+ d*= 0.5;
+
+ nr--;
+ }
+ return s/div;
+}
+
+/* ********************* FROM PERLIN HIMSELF: ******************** */
+
+static char p[512+2]= {
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0,0x19,0x3B,0xF8,0xEB,0xAA,0xEE,0xF3,0x1C,0x67,0x28,0x1D,0xED,0x0,0xDE,0x95,0x2E,0xDC,0x3F,0x3A,0x82,0x35,0x4D,0x6C,0xBA,0x36,0xD0,0xF6,0xC,0x79,0x32,0xD1,0x59,0xF4,0x8,0x8B,0x63,0x89,0x2F,0xB8,0xB4,0x97,0x83,0xF2,0x8F,0x18,0xC7,0x51,0x14,0x65,0x87,0x48,0x20,0x42,0xA8,0x80,0xB5,0x40,0x13,0xB2,0x22,0x7E,0x57,
+0xBC,0x7F,0x6B,0x9D,0x86,0x4C,0xC8,0xDB,0x7C,0xD5,0x25,0x4E,0x5A,0x55,0x74,0x50,0xCD,0xB3,0x7A,0xBB,0xC3,0xCB,0xB6,0xE2,0xE4,0xEC,0xFD,0x98,0xB,0x96,0xD3,0x9E,0x5C,0xA1,0x64,0xF1,0x81,0x61,0xE1,0xC4,0x24,0x72,0x49,0x8C,0x90,0x4B,0x84,0x34,0x38,0xAB,0x78,0xCA,0x1F,0x1,0xD7,0x93,0x11,0xC1,0x58,0xA9,0x31,0xF9,0x44,0x6D,
+0xBF,0x33,0x9C,0x5F,0x9,0x94,0xA3,0x85,0x6,0xC6,0x9A,0x1E,0x7B,0x46,0x15,0x30,0x27,0x2B,0x1B,0x71,0x3C,0x5B,0xD6,0x6F,0x62,0xAC,0x4F,0xC2,0xC0,0xE,0xB1,0x23,0xA7,0xDF,0x47,0xB0,0x77,0x69,0x5,0xE9,0xE6,0xE7,0x76,0x73,0xF,0xFE,0x6E,0x9B,0x56,0xEF,0x12,0xA5,0x37,0xFC,0xAE,0xD9,0x3,0x8E,0xDD,0x10,0xB9,0xCE,0xC9,0x8D,
+0xDA,0x2A,0xBD,0x68,0x17,0x9F,0xBE,0xD4,0xA,0xCC,0xD2,0xE8,0x43,0x3D,0x70,0xB7,0x2,0x7D,0x99,0xD8,0xD,0x60,0x8A,0x4,0x2C,0x3E,0x92,0xE5,0xAF,0x53,0x7,0xE0,0x29,0xA6,0xC5,0xE3,0xF5,0xF7,0x4A,0x41,0x26,0x6A,0x16,0x5E,0x52,0x2D,0x21,0xAD,0xF0,0x91,0xFF,0xEA,0x54,0xFA,0x66,0x1A,0x45,0x39,0xCF,0x75,0xA4,0x88,0xFB,0x5D,
+0xA2,0xA0};
+
+
+float g[512+2][3]= {
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624,-0.101074,-0.416443,-0.903503,0.799286,0.49411,-0.341949,-0.854645,0.518036,0.033936,0.42514,-0.437866,-0.792114,-0.358948,0.597046,0.717377,-0.985413,0.144714,0.089294,-0.601776,-0.33728,-0.723907,-0.449921,0.594513,0.666382,0.208313,-0.10791,
+0.972076,0.575317,0.060425,0.815643,0.293365,-0.875702,-0.383453,0.293762,0.465759,0.834686,-0.846008,-0.233398,-0.47934,-0.115814,0.143036,-0.98291,0.204681,-0.949036,-0.239532,0.946716,-0.263947,0.184326,-0.235596,0.573822,0.784332,0.203705,-0.372253,-0.905487,0.756989,-0.651031,0.055298,0.497803,
+0.814697,-0.297363,-0.16214,0.063995,-0.98468,-0.329254,0.834381,0.441925,0.703827,-0.527039,-0.476227,0.956421,0.266113,0.119781,0.480133,0.482849,0.7323,-0.18631,0.961212,-0.203125,-0.748474,-0.656921,-0.090393,-0.085052,-0.165253,0.982544,-0.76947,0.628174,-0.115234,0.383148,0.537659,0.751068,
+0.616486,-0.668488,-0.415924,-0.259979,-0.630005,0.73175,0.570953,-0.087952,0.816223,-0.458008,0.023254,0.888611,-0.196167,0.976563,-0.088287,-0.263885,-0.69812,-0.665527,0.437134,-0.892273,-0.112793,-0.621674,-0.230438,0.748566,0.232422,0.900574,-0.367249,0.22229,-0.796143,0.562744,-0.665497,-0.73764,
+0.11377,0.670135,0.704803,0.232605,0.895599,0.429749,-0.114655,-0.11557,-0.474243,0.872742,0.621826,0.604004,-0.498444,-0.832214,0.012756,0.55426,-0.702484,0.705994,-0.089661,-0.692017,0.649292,0.315399,-0.175995,-0.977997,0.111877,0.096954,-0.04953,0.994019,0.635284,-0.606689,-0.477783,-0.261261,
+-0.607422,-0.750153,0.983276,0.165436,0.075958,-0.29837,0.404083,-0.864655,-0.638672,0.507721,0.578156,0.388214,0.412079,0.824249,0.556183,-0.208832,0.804352,0.778442,0.562012,0.27951,-0.616577,0.781921,-0.091522,0.196289,0.051056,0.979187,-0.121216,0.207153,-0.970734,-0.173401,-0.384735,0.906555,
+0.161499,-0.723236,-0.671387,0.178497,-0.006226,-0.983887,-0.126038,0.15799,0.97934,0.830475,-0.024811,0.556458,-0.510132,-0.76944,0.384247,0.81424,0.200104,-0.544891,-0.112549,-0.393311,-0.912445,0.56189,0.152222,-0.813049,0.198914,-0.254517,-0.946381,-0.41217,0.690979,-0.593811,-0.407257,0.324524,
+0.853668,-0.690186,0.366119,-0.624115,-0.428345,0.844147,-0.322296,-0.21228,-0.297546,-0.930756,-0.273071,0.516113,0.811798,0.928314,0.371643,0.007233,0.785828,-0.479218,-0.390778,-0.704895,0.058929,0.706818,0.173248,0.203583,0.963562,0.422211,-0.904297,-0.062469,-0.363312,-0.182465,0.913605,0.254028,
+-0.552307,-0.793945,-0.28891,-0.765747,-0.574554,0.058319,0.291382,0.954803,0.946136,-0.303925,0.111267,-0.078156,0.443695,-0.892731,0.182098,0.89389,0.409515,-0.680298,-0.213318,0.701141,0.062469,0.848389,-0.525635,-0.72879,-0.641846,0.238342,-0.88089,0.427673,0.202637,-0.532501,-0.21405,0.818878,
+0.948975,-0.305084,0.07962,0.925446,0.374664,0.055817,0.820923,0.565491,0.079102,0.25882,0.099792,-0.960724,-0.294617,0.910522,0.289978,0.137115,0.320038,-0.937408,-0.908386,0.345276,-0.235718,-0.936218,0.138763,0.322754,0.366577,0.925934,-0.090637,0.309296,-0.686829,-0.657684,0.66983,0.024445,
+0.742065,-0.917999,-0.059113,-0.392059,0.365509,0.462158,-0.807922,0.083374,0.996399,-0.014801,0.593842,0.253143,-0.763672,0.974976,-0.165466,0.148285,0.918976,0.137299,0.369537,0.294952,0.694977,0.655731,0.943085,0.152618,-0.295319,0.58783,-0.598236,0.544495,0.203796,0.678223,0.705994,-0.478821,
+-0.661011,0.577667,0.719055,-0.1698,-0.673828,-0.132172,-0.965332,0.225006,-0.981873,-0.14502,0.121979,0.763458,0.579742,0.284546,-0.893188,0.079681,0.442474,-0.795776,-0.523804,0.303802,0.734955,0.67804,-0.007446,0.15506,0.986267,-0.056183,0.258026,0.571503,-0.778931,-0.681549,-0.702087,-0.206116,
+-0.96286,-0.177185,0.203613,-0.470978,-0.515106,0.716095,-0.740326,0.57135,0.354095,-0.56012,-0.824982,-0.074982,-0.507874,0.753204,0.417969,-0.503113,0.038147,0.863342,0.594025,0.673553,-0.439758,-0.119873,-0.005524,-0.992737,0.098267,-0.213776,0.971893,-0.615631,0.643951,0.454163,0.896851,-0.441071,
+0.032166,-0.555023,0.750763,-0.358093,0.398773,0.304688,0.864929,-0.722961,0.303589,0.620544,-0.63559,-0.621948,-0.457306,-0.293243,0.072327,0.953278,-0.491638,0.661041,-0.566772,-0.304199,-0.572083,-0.761688,0.908081,-0.398956,0.127014,-0.523621,-0.549683,-0.650848,-0.932922,-0.19986,0.299408,0.099426,
+0.140869,0.984985,-0.020325,-0.999756,-0.002319,0.952667,0.280853,-0.11615,-0.971893,0.082581,0.220337,0.65921,0.705292,-0.260651,0.733063,-0.175537,0.657043,-0.555206,0.429504,-0.712189,0.400421,-0.89859,0.179352,0.750885,-0.19696,0.630341,0.785675,-0.569336,0.241821,-0.058899,-0.464111,0.883789,
+0.129608,-0.94519,0.299622,-0.357819,0.907654,0.219238,-0.842133,-0.439117,-0.312927,-0.313477,0.84433,0.434479,-0.241211,0.053253,0.968994,0.063873,0.823273,0.563965,0.476288,0.862152,-0.172516,0.620941,-0.298126,0.724915,0.25238,-0.749359,-0.612122,-0.577545,0.386566,0.718994,-0.406342,-0.737976,
+0.538696,0.04718,0.556305,0.82959,-0.802856,0.587463,0.101166,-0.707733,-0.705963,0.026428,0.374908,0.68457,0.625092,0.472137,0.208405,-0.856506,-0.703064,-0.581085,-0.409821,-0.417206,-0.736328,0.532623,-0.447876,-0.20285,-0.870728,0.086945,-0.990417,0.107086,0.183685,0.018341,-0.982788,0.560638,
+-0.428864,0.708282,0.296722,-0.952576,-0.0672,0.135773,0.990265,0.030243,-0.068787,0.654724,0.752686,0.762604,-0.551758,0.337585,-0.819611,-0.407684,0.402466,-0.727844,-0.55072,-0.408539,-0.855774,-0.480011,0.19281,0.693176,-0.079285,0.716339,0.226013,0.650116,-0.725433,0.246704,0.953369,-0.173553,
+-0.970398,-0.239227,-0.03244,0.136383,-0.394318,0.908752,0.813232,0.558167,0.164368,0.40451,0.549042,-0.731323,-0.380249,-0.566711,0.730865,0.022156,0.932739,0.359741,0.00824,0.996552,-0.082306,0.956635,-0.065338,-0.283722,-0.743561,0.008209,0.668579,-0.859589,-0.509674,0.035767,-0.852234,0.363678,
+-0.375977,-0.201965,-0.970795,-0.12915,0.313477,0.947327,0.06546,-0.254028,-0.528259,0.81015,0.628052,0.601105,0.49411,-0.494385,0.868378,0.037933,0.275635,-0.086426,0.957336,-0.197937,0.468903,-0.860748,0.895599,0.399384,0.195801,0.560791,0.825012,-0.069214,0.304199,-0.849487,0.43103,0.096375,
+0.93576,0.339111,-0.051422,0.408966,-0.911072,0.330444,0.942841,-0.042389,-0.452362,-0.786407,0.420563,0.134308,-0.933472,-0.332489,0.80191,-0.566711,-0.188934,-0.987946,-0.105988,0.112518,-0.24408,0.892242,-0.379791,-0.920502,0.229095,-0.316376,0.7789,0.325958,0.535706,-0.912872,0.185211,-0.36377,
+-0.184784,0.565369,-0.803833,-0.018463,0.119537,0.992615,-0.259247,-0.935608,0.239532,-0.82373,-0.449127,-0.345947,-0.433105,0.659515,0.614349,-0.822754,0.378845,-0.423676,0.687195,-0.674835,-0.26889,-0.246582,-0.800842,0.545715,-0.729187,-0.207794,0.651978,0.653534,-0.610443,-0.447388,0.492584,-0.023346,
+0.869934,0.609039,0.009094,-0.79306,0.962494,-0.271088,-0.00885,0.2659,-0.004913,0.963959,0.651245,0.553619,-0.518951,0.280548,-0.84314,0.458618,-0.175293,-0.983215,0.049805,0.035339,-0.979919,0.196045,-0.982941,0.164307,-0.082245,0.233734,-0.97226,-0.005005,-0.747253,-0.611328,0.260437,0.645599,
+0.592773,0.481384,0.117706,-0.949524,-0.29068,-0.535004,-0.791901,-0.294312,-0.627167,-0.214447,0.748718,-0.047974,-0.813477,-0.57959,-0.175537,0.477264,-0.860992,0.738556,-0.414246,-0.53183,0.562561,-0.704071,0.433289,-0.754944,0.64801,-0.100586,0.114716,0.044525,-0.992371,0.966003,0.244873,-0.082764,
+0.33783,0.715698,-0.611206,-0.944031,-0.326599,-0.045624};
+
+
+
+#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
+
+#define setup(i,b0,b1,r0,r1) \
+ t = vec[i] + 10000.; \
+ b0 = ((int)t) & 255; \
+ b1 = (b0+1) & 255; \
+ r0 = t - (int)t; \
+ r1 = r0 - 1.;
+
+
+float noise3_perlin(float vec[3])
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+
+ setup(0, bx0,bx1, rx0,rx1);
+ setup(1, by0,by1, ry0,ry1);
+ setup(2, bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+#define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+#define surve(t) ( t * t * (3. - 2. * t) )
+
+/* lerp moved to improved perlin above */
+
+ sx = surve(rx0);
+ sy = surve(ry0);
+ sz = surve(rz0);
+
+
+ q = g[ b00 + bz0 ] ;
+ u = at(rx0,ry0,rz0);
+ q = g[ b10 + bz0 ] ;
+ v = at(rx1,ry0,rz0);
+ a = lerp(sx, u, v);
+
+ q = g[ b01 + bz0 ] ;
+ u = at(rx0,ry1,rz0);
+ q = g[ b11 + bz0 ] ;
+ v = at(rx1,ry1,rz0);
+ b = lerp(sx, u, v);
+
+ c = lerp(sy, a, b); /* interpolate in y at lo x */
+
+ q = g[ b00 + bz1 ] ;
+ u = at(rx0,ry0,rz1);
+ q = g[ b10 + bz1 ] ;
+ v = at(rx1,ry0,rz1);
+ a = lerp(sx, u, v);
+
+ q = g[ b01 + bz1 ] ;
+ u = at(rx0,ry1,rz1);
+ q = g[ b11 + bz1 ] ;
+ v = at(rx1,ry1,rz1);
+ b = lerp(sx, u, v);
+
+ d = lerp(sy, a, b); /* interpolate in y at hi x */
+
+ return 1.5 * lerp(sz, c, d); /* interpolate in z */
+}
+
+float turbulence_perlin(float *point, float lofreq, float hifreq)
+{
+ float freq, t, p[3];
+
+ p[0] = point[0] + 123.456;
+ p[1] = point[1];
+ p[2] = point[2];
+
+ t = 0;
+ for (freq = lofreq ; freq < hifreq ; freq *= 2.) {
+ t += fabs(noise3_perlin(p)) / freq;
+ p[0] *= 2.;
+ p[1] *= 2.;
+ p[2] *= 2.;
+ }
+ return t - 0.3; /* readjust to make mean value = 0.0 */
+}
+
+/* for use with BLI_gNoise/gTurbulence, returns signed noise */
+static float orgPerlinNoise(float x, float y, float z)
+{
+ float v[3];
+
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ return noise3_perlin(v);
+}
+
+/* for use with BLI_gNoise/gTurbulence, returns unsigned noise */
+static float orgPerlinNoiseU(float x, float y, float z)
+{
+ float v[3];
+
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ return (0.5+0.5*noise3_perlin(v));
+}
+
+/* *************** CALL AS: *************** */
+
+float BLI_hnoisep(float noisesize, float x, float y, float z)
+{
+ float vec[3];
+
+ vec[0]= x/noisesize;
+ vec[1]= y/noisesize;
+ vec[2]= z/noisesize;
+
+ return noise3_perlin(vec);
+}
+
+float turbulencep(float noisesize, float x, float y, float z, int nr)
+{
+ float vec[3];
+
+ vec[0]= x/noisesize;
+ vec[1]= y/noisesize;
+ vec[2]= z/noisesize;
+ nr++;
+ return turbulence_perlin(vec, 1.0, (float)(1<<nr));
+}
+
+/******************/
+/* VORONOI/WORLEY */
+/******************/
+
+/* distance metrics for voronoi, e parameter only used in Minkovsky */
+/* Camberra omitted, didn't seem useful */
+
+/* distance squared */
+static float dist_Squared(float x, float y, float z, float e) { return (x*x + y*y + z*z); }
+/* real distance */
+static float dist_Real(float x, float y, float z, float e) { return sqrt(x*x + y*y + z*z); }
+/* manhattan/taxicab/cityblock distance */
+static float dist_Manhattan(float x, float y, float z, float e) { return (fabs(x) + fabs(y) + fabs(z)); }
+/* Chebychev */
+static float dist_Chebychev(float x, float y, float z, float e)
+{
+ float t;
+ x = fabs(x);
+ y = fabs(y);
+ z = fabs(z);
+ t = (x>y)?x:y;
+ return ((z>t)?z:t);
+}
+
+/* minkovsky preset exponent 0.5 */
+static float dist_MinkovskyH(float x, float y, float z, float e)
+{
+ float d = sqrt(fabs(x)) + sqrt(fabs(y)) + sqrt(fabs(z));
+ return (d*d);
+}
+
+/* minkovsky preset exponent 4 */
+static float dist_Minkovsky4(float x, float y, float z, float e)
+{
+ x *= x;
+ y *= y;
+ z *= z;
+ return sqrt(sqrt(x*x + y*y + z*z));
+}
+
+/* Minkovsky, general case, slow, maybe too slow to be useful */
+static float dist_Minkovsky(float x, float y, float z, float e)
+{
+ return pow(pow(fabs(x), e) + pow(fabs(y), e) + pow(fabs(z), e), 1.0/e);
+}
+
+
+/* Not 'pure' Worley, but the results are virtually the same.
+ Returns distances in da and point coords in pa */
+void voronoi(float x, float y, float z, float* da, float* pa, float me, int dtype)
+{
+ int xx, yy, zz, xi, yi, zi;
+ float xd, yd, zd, d, *p;
+
+ float (*distfunc)(float, float, float, float);
+ switch (dtype) {
+ case 1:
+ distfunc = dist_Squared;
+ break;
+ case 2:
+ distfunc = dist_Manhattan;
+ break;
+ case 3:
+ distfunc = dist_Chebychev;
+ break;
+ case 4:
+ distfunc = dist_MinkovskyH;
+ break;
+ case 5:
+ distfunc = dist_Minkovsky4;
+ break;
+ case 6:
+ distfunc = dist_Minkovsky;
+ break;
+ case 0:
+ default:
+ distfunc = dist_Real;
+ }
+
+ xi = (int)(floor(x));
+ yi = (int)(floor(y));
+ zi = (int)(floor(z));
+ da[0] = da[1] = da[2] = da[3] = 1e10f;
+ for (xx=xi-1;xx<=xi+1;xx++) {
+ for (yy=yi-1;yy<=yi+1;yy++) {
+ for (zz=zi-1;zz<=zi+1;zz++) {
+ p = HASHPNT(xx, yy, zz);
+ xd = x - (p[0] + xx);
+ yd = y - (p[1] + yy);
+ zd = z - (p[2] + zz);
+ d = distfunc(xd, yd, zd, me);
+ if (d<da[0]) {
+ da[3]=da[2]; da[2]=da[1]; da[1]=da[0]; da[0]=d;
+ pa[9]=pa[6]; pa[10]=pa[7]; pa[11]=pa[8];
+ pa[6]=pa[3]; pa[7]=pa[4]; pa[8]=pa[5];
+ pa[3]=pa[0]; pa[4]=pa[1]; pa[5]=pa[2];
+ pa[0]=p[0]+xx; pa[1]=p[1]+yy; pa[2]=p[2]+zz;
+ }
+ else if (d<da[1]) {
+ da[3]=da[2]; da[2]=da[1]; da[1]=d;
+ pa[9]=pa[6]; pa[10]=pa[7]; pa[11]=pa[8];
+ pa[6]=pa[3]; pa[7]=pa[4]; pa[8]=pa[5];
+ pa[3]=p[0]+xx; pa[4]=p[1]+yy; pa[5]=p[2]+zz;
+ }
+ else if (d<da[2]) {
+ da[3]=da[2]; da[2]=d;
+ pa[9]=pa[6]; pa[10]=pa[7]; pa[11]=pa[8];
+ pa[6]=p[0]+xx; pa[7]=p[1]+yy; pa[8]=p[2]+zz;
+ }
+ else if (d<da[3]) {
+ da[3]=d;
+ pa[9]=p[0]+xx; pa[10]=p[1]+yy; pa[11]=p[2]+zz;
+ }
+ }
+ }
+ }
+}
+
+/* returns different feature points for use in BLI_gNoise() */
+static float voronoi_F1(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return da[0];
+}
+
+static float voronoi_F2(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return da[1];
+}
+
+static float voronoi_F3(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return da[2];
+}
+
+static float voronoi_F4(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return da[3];
+}
+
+static float voronoi_F1F2(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (da[1]-da[0]);
+}
+
+/* Crackle type pattern, just a scale/clamp of F2-F1 */
+static float voronoi_Cr(float x, float y, float z)
+{
+ float t = 10*voronoi_F1F2(x, y, z);
+ if (t>1.f) return 1.f;
+ return t;
+}
+
+
+/* Signed version of all 6 of the above, just 2x-1, not really correct though (range is potentially (0, sqrt(6)).
+ Used in the musgrave functions */
+static float voronoi_F1S(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (2.0*da[0]-1.0);
+}
+
+static float voronoi_F2S(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (2.0*da[1]-1.0);
+}
+
+static float voronoi_F3S(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (2.0*da[2]-1.0);
+}
+
+static float voronoi_F4S(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (2.0*da[3]-1.0);
+}
+
+static float voronoi_F1F2S(float x, float y, float z)
+{
+ float da[4], pa[12];
+ voronoi(x, y, z, da, pa, 1, 0);
+ return (2.0*(da[1]-da[0])-1.0);
+}
+
+/* Crackle type pattern, just a scale/clamp of F2-F1 */
+static float voronoi_CrS(float x, float y, float z)
+{
+ float t = 10*voronoi_F1F2(x, y, z);
+ if (t>1.f) return 1.f;
+ return (2.0*t-1.0);
+}
+
+
+/***************/
+/* voronoi end */
+/***************/
+
+/*************/
+/* CELLNOISE */
+/*************/
+
+/* returns unsigned cellnoise */
+static float cellNoiseU(float x, float y, float z)
+{
+ int xi = (int)(floor(x));
+ int yi = (int)(floor(y));
+ int zi = (int)(floor(z));
+ unsigned int n = xi + yi*1301 + zi*314159;
+ n ^= (n<<13);
+ return ((float)(n*(n*n*15731 + 789221) + 1376312589) / 4294967296.0);
+}
+
+/* idem, signed */
+float cellNoise(float x, float y, float z)
+{
+ return (2.0*cellNoiseU(x, y, z)-1.0);
+}
+
+/* returns a vector/point/color in ca, using point hasharray directly */
+void cellNoiseV(float x, float y, float z, float *ca)
+{
+ int xi = (int)(floor(x));
+ int yi = (int)(floor(y));
+ int zi = (int)(floor(z));
+ float *p = HASHPNT(xi, yi, zi);
+ ca[0] = p[0];
+ ca[1] = p[1];
+ ca[2] = p[2];
+}
+
+
+/*****************/
+/* end cellnoise */
+/*****************/
+
+/* newnoise: generic noise function for use with different noisebases */
+float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noisebasis)
+{
+ float (*noisefunc)(float, float, float);
+
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoiseU;
+ break;
+ case 2:
+ noisefunc = newPerlinU;
+ break;
+ case 3:
+ noisefunc = voronoi_F1;
+ break;
+ case 4:
+ noisefunc = voronoi_F2;
+ break;
+ case 5:
+ noisefunc = voronoi_F3;
+ break;
+ case 6:
+ noisefunc = voronoi_F4;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2;
+ break;
+ case 8:
+ noisefunc = voronoi_Cr;
+ break;
+ case 14:
+ noisefunc = cellNoiseU;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoise;
+ /* add one to make return value same as BLI_hnoise */
+ x += 1;
+ y += 1;
+ z += 1;
+ }
+ }
+
+ if (noisesize!=0.0) {
+ noisesize = 1.0/noisesize;
+ x *= noisesize;
+ y *= noisesize;
+ z *= noisesize;
+ }
+
+ if (hard) return fabs(2.0*noisefunc(x, y, z)-1.0);
+ return noisefunc(x, y, z);
+}
+
+/* newnoise: generic turbulence function for use with different noisebasis */
+float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int hard, int noisebasis)
+{
+ float (*noisefunc)(float, float, float);
+ float sum, t, amp=1, fscale=1;
+ int i;
+
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoiseU;
+ break;
+ case 2:
+ noisefunc = newPerlinU;
+ break;
+ case 3:
+ noisefunc = voronoi_F1;
+ break;
+ case 4:
+ noisefunc = voronoi_F2;
+ break;
+ case 5:
+ noisefunc = voronoi_F3;
+ break;
+ case 6:
+ noisefunc = voronoi_F4;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2;
+ break;
+ case 8:
+ noisefunc = voronoi_Cr;
+ break;
+ case 14:
+ noisefunc = cellNoiseU;
+ break;
+ case 0:
+ default:
+ noisefunc = orgBlenderNoise;
+ x += 1;
+ y += 1;
+ z += 1;
+ }
+
+ if (noisesize!=0.0) {
+ noisesize = 1.0/noisesize;
+ x *= noisesize;
+ y *= noisesize;
+ z *= noisesize;
+ }
+
+ sum = 0;
+ for (i=0;i<=oct;i++, amp*=0.5, fscale*=2) {
+ t = noisefunc(fscale*x, fscale*y, fscale*z);
+ if (hard) t = fabs(2.0*t-1.0);
+ sum += t * amp;
+ }
+
+ sum *= ((float)(1<<oct)/(float)((1<<(oct+1))-1));
+
+ return sum;
+
+}
+
+
+/*
+ * The following code is based on Ken Musgrave's explanations and sample
+ * source code in the book "Texturing and Modelling: A procedural approach"
+ */
+
+/*
+ * Procedural fBm evaluated at "point"; returns value stored in "value".
+ *
+ * Parameters:
+ * ``H'' is the fractal increment parameter
+ * ``lacunarity'' is the gap between successive frequencies
+ * ``octaves'' is the number of frequencies in the fBm
+ */
+float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis)
+{
+ float rmd, value=0.0, pwr=1.0, pwHL=pow(lacunarity, -H);
+ int i;
+
+ float (*noisefunc)(float, float, float);
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc = newPerlin;
+ break;
+ case 3:
+ noisefunc = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoiseS;
+ }
+ }
+
+ for (i=0; i<(int)octaves; i++) {
+ value += noisefunc(x, y, z) * pwr;
+ pwr *= pwHL;
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd!=0.f) value += rmd * noisefunc(x, y, z) * pwr;
+
+ return value;
+
+} /* fBm() */
+
+
+/*
+ * Procedural multifractal evaluated at "point";
+ * returns value stored in "value".
+ *
+ * Parameters:
+ * ``H'' determines the highest fractal dimension
+ * ``lacunarity'' is gap between successive frequencies
+ * ``octaves'' is the number of frequencies in the fBm
+ * ``offset'' is the zero offset, which determines multifractality (NOT USED??)
+ */
+ /* this one is in fact rather confusing,
+ * there seem to be errors in the original source code (in all three versions of proc.text&mod),
+ * I modified it to something that made sense to me, so it might be wrong... */
+float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis)
+{
+ float rmd, value=1.0, pwr=1.0, pwHL=pow(lacunarity, -H);
+ int i;
+
+ float (*noisefunc)(float, float, float);
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc = newPerlin;
+ break;
+ case 3:
+ noisefunc = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoiseS;
+ }
+ }
+
+ for (i=0; i<(int)octaves; i++) {
+ value *= (pwr * noisefunc(x, y, z) + 1.0);
+ pwr *= pwHL;
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ }
+ rmd = octaves - floor(octaves);
+ if (rmd!=0.0) value *= (rmd * noisefunc(x, y, z) * pwr + 1.0);
+
+ return value;
+
+} /* multifractal() */
+
+/*
+ * Heterogeneous procedural terrain function: stats by altitude method.
+ * Evaluated at "point"; returns value stored in "value".
+ *
+ * Parameters:
+ * ``H'' determines the fractal dimension of the roughest areas
+ * ``lacunarity'' is the gap between successive frequencies
+ * ``octaves'' is the number of frequencies in the fBm
+ * ``offset'' raises the terrain from `sea level'
+ */
+float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, float octaves, float offset, int noisebasis)
+{
+ float value, increment, rmd;
+ int i;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL; /* starts with i=1 instead of 0 */
+
+ float (*noisefunc)(float, float, float);
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc = newPerlin;
+ break;
+ case 3:
+ noisefunc = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoiseS;
+ }
+ }
+
+ /* first unscaled octave of function; later octaves are scaled */
+ value = offset + noisefunc(x, y, z);
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+
+ for (i=1; i<(int)octaves; i++) {
+ increment = (noisefunc(x, y, z) + offset) * pwr * value;
+ value += increment;
+ pwr *= pwHL;
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd!=0.0) {
+ increment = (noisefunc(x, y, z) + offset) * pwr * value;
+ value += rmd * increment;
+ }
+ return value;
+}
+
+
+/* Hybrid additive/multiplicative multifractal terrain model.
+ *
+ * Some good parameter values to start with:
+ *
+ * H: 0.25
+ * offset: 0.7
+ */
+float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis)
+{
+ float result, signal, weight, rmd;
+ int i;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL; /* starts with i=1 instead of 0 */
+ float (*noisefunc)(float, float, float);
+
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc = newPerlin;
+ break;
+ case 3:
+ noisefunc = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoiseS;
+ }
+ }
+
+ result = noisefunc(x, y, z) + offset;
+ weight = gain * result;
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+
+ for (i=1; (weight>0.001) && (i<(int)octaves); i++) {
+ if (weight>1.0) weight=1.0;
+ signal = (noisefunc(x, y, z) + offset) * pwr;
+ pwr *= pwHL;
+ result += weight * signal;
+ weight *= gain * signal;
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd!=0.f) result += rmd * ((noisefunc(x, y, z) + offset) * pwr);
+
+ return result;
+
+} /* HybridMultifractal() */
+
+
+/* Ridged multifractal terrain model.
+ *
+ * Some good parameter values to start with:
+ *
+ * H: 1.0
+ * offset: 1.0
+ * gain: 2.0
+ */
+float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity, float octaves, float offset, float gain, int noisebasis)
+{
+ float result, signal, weight;
+ int i;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL; /* starts with i=1 instead of 0 */
+
+ float (*noisefunc)(float, float, float);
+ switch (noisebasis) {
+ case 1:
+ noisefunc = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc = newPerlin;
+ break;
+ case 3:
+ noisefunc = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc = orgBlenderNoiseS;
+ }
+ }
+
+ signal = offset - fabs(noisefunc(x, y, z));
+ signal *= signal;
+ result = signal;
+ weight = 1.f;
+
+ for( i=1; i<(int)octaves; i++ ) {
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ weight = signal * gain;
+ if (weight>1.0) weight=1.0; else if (weight<0.0) weight=0.0;
+ signal = offset - fabs(noisefunc(x, y, z));
+ signal *= signal;
+ signal *= weight;
+ result += signal * pwr;
+ pwr *= pwHL;
+ }
+
+ return result;
+} /* RidgedMultifractal() */
+
+/* "Variable Lacunarity Noise"
+ * A distorted variety of Perlin noise.
+ */
+float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nbas2)
+{
+ float rv[3];
+ float (*noisefunc1)(float, float, float);
+ float (*noisefunc2)(float, float, float);
+
+ switch (nbas1) {
+ case 1:
+ noisefunc1 = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc1 = newPerlin;
+ break;
+ case 3:
+ noisefunc1 = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc1 = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc1 = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc1 = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc1 = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc1 = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc1 = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc1 = orgBlenderNoiseS;
+ }
+ }
+
+ switch (nbas2) {
+ case 1:
+ noisefunc2 = orgPerlinNoise;
+ break;
+ case 2:
+ noisefunc2 = newPerlin;
+ break;
+ case 3:
+ noisefunc2 = voronoi_F1S;
+ break;
+ case 4:
+ noisefunc2 = voronoi_F2S;
+ break;
+ case 5:
+ noisefunc2 = voronoi_F3S;
+ break;
+ case 6:
+ noisefunc2 = voronoi_F4S;
+ break;
+ case 7:
+ noisefunc2 = voronoi_F1F2S;
+ break;
+ case 8:
+ noisefunc2 = voronoi_CrS;
+ break;
+ case 14:
+ noisefunc2 = cellNoise;
+ break;
+ case 0:
+ default: {
+ noisefunc2 = orgBlenderNoiseS;
+ }
+ }
+
+ /* get a random vector and scale the randomization */
+ rv[0] = noisefunc1(x+13.5, y+13.5, z+13.5) * distortion;
+ rv[1] = noisefunc1(x, y, z) * distortion;
+ rv[2] = noisefunc1(x-13.5, y-13.5, z-13.5) * distortion;
+ return noisefunc2(x+rv[0], y+rv[1], z+rv[2]); /* distorted-domain noise */
+}
+
+/****************/
+/* musgrave end */
+/****************/
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
new file mode 100644
index 00000000000..941bf4204a8
--- /dev/null
+++ b/source/blender/blenlib/intern/psfont.c
@@ -0,0 +1,2126 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * fromtype1 - Convert an Adobe type 1 font into .of or .sf format.
+ * Paul Haeberli - 1990
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_vfontdata.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_packedFile_types.h"
+#include "DNA_curve_types.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+ /* ObjFnt types */
+
+typedef struct chardesc {
+ short movex, movey; /* advance */
+ short llx, lly; /* bounding box */
+ short urx, ury;
+ short *data; /* char data */
+ long datalen;
+} chardesc;
+
+typedef struct objfnt {
+ struct objfnt *freeaddr; /* if freeaddr != 0, objfnt is one chunck */
+ short type;
+ short charmin, charmax;
+ short my_nchars;
+ short scale;
+ chardesc *my_chars;
+} objfnt;
+
+#define OFMAGIC 0x93339333
+
+#define TM_TYPE 1
+#define PO_TYPE 2
+#define SP_TYPE 3
+
+/* ops for tmesh characters */
+
+#define TM_BGNTMESH (1)
+#define TM_SWAPTMESH (2)
+#define TM_ENDBGNTMESH (3)
+#define TM_RETENDTMESH (4)
+#define TM_RET (5)
+
+/* ops for poly characters */
+
+#define PO_BGNLOOP (1)
+#define PO_ENDBGNLOOP (2)
+#define PO_RETENDLOOP (3)
+#define PO_RET (4)
+
+/* ops for spline characters */
+
+#define SP_MOVETO (1)
+#define SP_LINETO (2)
+#define SP_CURVETO (3)
+#define SP_CLOSEPATH (4)
+#define SP_RETCLOSEPATH (5)
+#define SP_RET (6)
+
+
+#define MIN_ASCII ' '
+#define MAX_ASCII '~'
+#define NASCII (256 - 32)
+
+#define NOBBOX (30000)
+
+typedef struct pschar {
+ char *name;
+ int code;
+ int prog;
+} pschar;
+
+ /***/
+
+#define SKIP 4
+#define LINELEN 2048
+#define NOTHEX (100)
+#define MC1 52845
+#define MC2 22719
+#define MAXSUBRS 4000
+#define MAXCHARS 4000
+#define MAXTRIES 30
+
+/* some local thingies */
+static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
+static void makeobjfont(int savesplines);
+static void drawchar(int c);
+static void runprog(void);
+static int chartoindex(objfnt *fnt, int c);
+static short STDtoISO(short c);
+static char * newfgets(char * s, int n, PackedFile * pf);
+static int readfontmatrix(PackedFile * pf, float mat[2][2]);
+static char mdecrypt(char cipher);
+static void decryptall(void);
+static int decodetype1(PackedFile * pf, char *outname);
+static void fakefopen(void);
+static char *fakefread(int n);
+static void setcharlist(void);
+static void initpcstack(void);
+static char *poppc(void);
+static void initstack(void);
+static void push(int val);
+static int pop(void);
+static void initretstack(void);
+static void retpush(int val);
+static int retpop(void);
+static void subr1(void);
+static void subr2(void);
+static void subr0(void);
+static void append_poly_offset(short ofsx, short ofsy, short * data);
+static void append_spline_offset(short ofsx, short ofsy, short * data);
+static void setwidth(int w, int x);
+static void poly_beginchar(void);
+static void poly_endchar(void);
+static void poly_close(void);
+static void poly_pnt(float x, float y);
+static void spline_beginchar(void);
+static void spline_endchar(void);
+static void spline_close(void);
+static void spline_line(float x0, float y0, float x1, float y1);
+static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+static void savestart(int x, int y);
+static void sbpoint( int x, int y);
+static void rmoveto( int x, int y);
+static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1);
+static void rlineto( int x, int y);
+static void closepath(void);
+static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol);
+static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+static int docommand(int cmd);
+
+/* some local vars */
+static int startx, starty;
+static int curx, cury;
+static int nextx, nexty;
+static int delx, dely;
+static int started;
+
+
+/* postscript commands */
+#define HSTEM (1)
+#define VSTEM (3)
+#define VMOVETO (4)
+#define RLINETO (5)
+#define HLINETO (6)
+#define VLINETO (7)
+#define RRCURVETO (8)
+#define CLOSEPATH (9)
+#define CALLSUBR (10)
+#define RETURN (11)
+#define HSBW (13)
+#define ENDCHAR (14)
+#define RMOVETO (21)
+#define HMOVETO (22)
+#define VHCURVETO (30)
+#define HVCURVETO (31)
+#define DOTSECTION (256+0)
+#define VSTEM3 (256+1)
+#define HSTEM3 (256+2)
+#define SEAC (256+6)
+#define SBW (256+7)
+#define DIV (256+12)
+#define CALLOTHERSUBR (256+16)
+#define POP (256+17)
+#define SETCURRENTPOINT (256+33)
+#define WHAT0 (0)
+
+static char oneline[LINELEN];
+static objfnt *fnt;
+
+static unsigned short int mr;
+
+static char *bindat;
+static int datbytes;
+static int firsted;
+static short chardata[20000];
+static int nshorts;
+
+static int thecharwidth, thesidebearing;
+static int npnts, nloops;
+static int nvertpos;
+
+static int fakepos;
+static int fakemax;
+
+static float beztol = 100.0;
+
+/* extern: from libfm */
+
+static char *my_subrs[MAXSUBRS];
+static unsigned int my_sublen[MAXSUBRS];
+static char *my_chars[MAXCHARS];
+static unsigned int my_charlen[MAXCHARS];
+static char *my_charname[MAXCHARS];
+static int my_nsubrs, my_nchars;
+
+static short sidebearing[MAXCHARS];
+static char tok[LINELEN];
+static int sp_npnts, sp_nloops;
+
+/*
+ * interpreter globals
+ */
+
+
+static float mat[2][2];
+static char *pcstack[100];
+static char *pc;
+static int pcsp;
+static int coordpos;
+static int coordsave[7][2];
+static int incusp;
+static int retstack[1000];
+static int retsp;
+static int stack[1000];
+static int sp;
+static int savesplines = 1;
+
+static pschar ISOcharlist[NASCII] = {
+ "/space", 040, 0,
+ "/exclam", 041, 0,
+ "/quotedbl", 042, 0,
+ "/numbersign", 043, 0,
+ "/dollar", 044, 0,
+ "/percent", 045, 0,
+ "/ampersand", 046, 0,
+ "/quoteright", 047, 0,
+
+ "/parenleft", 050, 0,
+ "/parenright", 051, 0,
+ "/asterisk", 052, 0,
+ "/plus", 053, 0,
+ "/comma", 054, 0,
+ "/hyphen", 055, 0,
+ "/period", 056, 0,
+ "/slash", 057, 0,
+
+ "/zero", 060, 0,
+ "/one", 061, 0,
+ "/two", 062, 0,
+ "/three", 063, 0,
+ "/four", 064, 0,
+ "/five", 065, 0,
+ "/six", 066, 0,
+ "/seven", 067, 0,
+
+ "/eight", 070, 0,
+ "/nine", 071, 0,
+ "/colon", 072, 0,
+ "/semicolon", 073, 0,
+ "/less", 074, 0,
+ "/equal", 075, 0,
+ "/greater", 076, 0,
+ "/question", 077, 0,
+
+ "/at", 0100, 0,
+ "/A", 0101, 0,
+ "/B", 0102, 0,
+ "/C", 0103, 0,
+ "/D", 0104, 0,
+ "/E", 0105, 0,
+ "/F", 0106, 0,
+ "/G", 0107, 0,
+
+ "/H", 0110, 0,
+ "/I", 0111, 0,
+ "/J", 0112, 0,
+ "/K", 0113, 0,
+ "/L", 0114, 0,
+ "/M", 0115, 0,
+ "/N", 0116, 0,
+ "/O", 0117, 0,
+
+ "/P", 0120, 0,
+ "/Q", 0121, 0,
+ "/R", 0122, 0,
+ "/S", 0123, 0,
+ "/T", 0124, 0,
+ "/U", 0125, 0,
+ "/V", 0126, 0,
+ "/W", 0127, 0,
+
+ "/X", 0130, 0,
+ "/Y", 0131, 0,
+ "/Z", 0132, 0,
+ "/bracketleft", 0133, 0,
+ "/backslash", 0134, 0,
+ "/bracketright", 0135, 0,
+ "/asciicircum", 0136, 0,
+ "/underscore", 0137, 0,
+
+ "/quoteleft", 0140, 0,
+ "/a", 0141, 0,
+ "/b", 0142, 0,
+ "/c", 0143, 0,
+ "/d", 0144, 0,
+ "/e", 0145, 0,
+ "/f", 0146, 0,
+ "/g", 0147, 0,
+
+ "/h", 0150, 0,
+ "/i", 0151, 0,
+ "/j", 0152, 0,
+ "/k", 0153, 0,
+ "/l", 0154, 0,
+ "/m", 0155, 0,
+ "/n", 0156, 0,
+ "/o", 0157, 0,
+
+ "/p", 0160, 0,
+ "/q", 0161, 0,
+ "/r", 0162, 0,
+ "/s", 0163, 0,
+ "/t", 0164, 0,
+ "/u", 0165, 0,
+ "/v", 0166, 0,
+ "/w", 0167, 0,
+
+ "/x", 0170, 0,
+ "/y", 0171, 0,
+ "/z", 0172, 0,
+ "/braceleft", 0173, 0,
+ "/bar", 0174, 0,
+ "/braceright", 0175, 0,
+ "/asciitilde", 0176, 0,
+ "/", 0177, 0,
+
+
+ /* nonstandard defs */
+
+ "/quotedblleft", 0200, 0,
+ "/quotedblright", 0201, 0,
+ "/quotedblbase", 0202, 0,
+ "/quotesinglbase", 0203, 0,
+ "/guilsinglleft", 0204, 0,
+ "/guilsinglright", 0205, 0,
+ "/endash", 0206, 0,
+ "/dagger", 0207, 0,
+
+ "/daggerdbl", 0210, 0,
+ "/trademark", 0211, 0,
+ "/bullet", 0212, 0,
+ "/perthousand", 0213, 0,
+ "/Lslash", 0214, 0,
+ "/OE", 0215, 0,
+ "/lslash", 0216, 0,
+ "/oe", 0217, 0,
+
+ /* endnonstandard defs */
+
+ "/dotlessi", 0220, 0,
+ "/grave", 0221, 0,
+ "/acute", 0222, 0,
+ "/circumflex", 0223, 0,
+ "/tilde", 0224, 0,
+ "/", 0225, 0,
+ "/breve", 0226, 0,
+ "/dotaccent", 0227, 0,
+
+ "/", 0230, 0,
+ "/", 0231, 0,
+ "/ring", 0232, 0,
+ "/", 0233, 0,
+ "/", 0234, 0,
+ "/hungarumlaut", 0235, 0,
+ "/ogonek", 0236, 0,
+ "/caron", 0237, 0,
+
+ "/", 0240, 0,
+ "/exclamdown", 0241, 0,
+ "/cent", 0242, 0,
+ "/sterling", 0243, 0,
+ "/florin", 0244, 0,
+ "/yen", 0245, 0,
+ "/brokenbar", 0246, 0,
+ "/section", 0247, 0,
+
+ "/dieresis", 0250, 0,
+ "/copyright", 0251, 0,
+ "/ordfeminine", 0252, 0,
+ "/guillemotleft", 0253, 0,
+ "/logicalnot", 0254, 0,
+ "/hyphen", 0255, 0,
+ "/registered", 0256, 0,
+ "/macron", 0257, 0,
+
+ "/degree", 0260, 0,
+ "/plusminus", 0261, 0,
+ "/twosuperior", 0262, 0,
+ "/threesuperior", 0263, 0,
+ "/acute", 0264, 0,
+ "/mu", 0265, 0,
+ "/paragraph", 0266, 0,
+ "/periodcentered", 0267, 0,
+
+ "/cedilla", 0270, 0,
+ "/onesuperior", 0271, 0,
+ "/ordmasculine", 0272, 0,
+ "/guillemotright", 0273, 0,
+ "/onequarter", 0274, 0,
+ "/onehalf", 0275, 0,
+ "/threequarters", 0276, 0,
+ "/questiondown", 0277, 0,
+
+ "/Agrave", 0300, 0,
+ "/Aacute", 0301, 0,
+ "/Acircumflex", 0302, 0,
+ "/Atilde", 0303, 0,
+ "/Adieresis", 0304, 0,
+ "/Aring", 0305, 0,
+ "/AE", 0306, 0,
+ "/Ccedilla", 0307, 0,
+
+ "/Egrave", 0310, 0,
+ "/Eacute", 0311, 0,
+ "/Ecircumflex", 0312, 0,
+ "/Edieresis", 0313, 0,
+ "/Igrave", 0314, 0,
+ "/Iacute", 0315, 0,
+ "/Icircumflex", 0316, 0,
+ "/Idieresis", 0317, 0,
+
+ "/Eth", 0320, 0,
+ "/Ntilde", 0321, 0,
+ "/Ograve", 0322, 0,
+ "/Oacute", 0323, 0,
+ "/Ocircumflex", 0324, 0,
+ "/Otilde", 0325, 0,
+ "/Odieresis", 0326, 0,
+ "/multiply", 0327, 0,
+
+ "/Oslash", 0330, 0,
+ "/Ugrave", 0331, 0,
+ "/Uacute", 0332, 0,
+ "/Ucircumflex", 0333, 0,
+ "/Udieresis", 0334, 0,
+ "/Yacute", 0335, 0,
+ "/Thorn", 0336, 0,
+ "/germandbls", 0337, 0,
+
+ "/agrave", 0340, 0,
+ "/aacute", 0341, 0,
+ "/acircumflex", 0342, 0,
+ "/atilde", 0343, 0,
+ "/adieresis", 0344, 0,
+ "/aring", 0345, 0,
+ "/ae", 0346, 0,
+ "/ccedilla", 0347, 0,
+
+ "/egrave", 0350, 0,
+ "/eacute", 0351, 0,
+ "/ecircumflex", 0352, 0,
+ "/edieresis", 0353, 0,
+ "/igrave", 0354, 0,
+ "/iacute", 0355, 0,
+ "/icircumflex", 0356, 0,
+ "/idieresis", 0357, 0,
+
+ "/eth", 0360, 0,
+ "/ntilde", 0361, 0,
+ "/ograve", 0362, 0,
+ "/oacute", 0363, 0,
+ "/ocircumflex", 0364, 0,
+ "/otilde", 0365, 0,
+ "/odieresis", 0366, 0,
+ "/divide", 0367, 0,
+
+ "/oslash", 0370, 0,
+ "/ugrave", 0371, 0,
+ "/uacute", 0372, 0,
+ "/ucircumflex", 0373, 0,
+ "/udieresis", 0374, 0,
+ "/yacute", 0375, 0,
+ "/thorn", 0376, 0,
+ "/ydieresis", 0377, 0,
+};
+
+
+static short STDvsISO [][2] = {
+ 0341, 0306, /* AE */
+ 0351, 0330, /* Oslash */
+ 0302, 0222, /* acute */
+ 0361, 0346, /* ae */
+ 0306, 0226, /* breve */
+ 0317, 0237, /* caron */
+ 0313, 0270, /* cedilla */
+ 0303, 0223, /* circumflex */
+ 0250, 0244, /* currency */
+ 0310, 0250, /* dieresis */
+ 0307, 0227, /* dotaccent */
+ 0365, 0220, /* dotlessi */
+ 0373, 0337, /* germandbls */
+ 0301, 0221, /* grave */
+ 0315, 0235, /* hungarumlaut */
+ 0055, 0255, /* hyphen */
+ 0305, 0257, /* macron */
+ 0316, 0236, /* ogenek */
+ 0343, 0252, /* ordfeminine */
+ 0353, 0272, /* ordmasculine */
+ 0371, 0370, /* oslash */
+ 0264, 0267, /* periodcentered */
+ 0312, 0232, /* ring */
+ 0304, 0224, /* tilde */
+};
+
+/* from objfont.c, rest is in lfm_s !!*/
+
+/* START 5.2 */
+
+static int chartoindex(objfnt *fnt, int c)
+{
+ if(c<fnt->charmin)
+ return -1;
+ if(c>fnt->charmax)
+ return -1;
+ return c-fnt->charmin;
+}
+
+
+static chardesc *getchardesc(objfnt *fnt, int c)
+{
+ int index;
+
+ index = chartoindex(fnt,c);
+ if(index<0)
+ return 0;
+ return fnt->my_chars+index;
+}
+
+static objfnt *newobjfnt(int type, int charmin, int charmax, int fscale)
+{
+ objfnt *fnt;
+
+ fnt = (objfnt *)MEM_mallocN(sizeof(objfnt), "newobjfnt");
+ fnt->freeaddr = 0;
+ fnt->type = type;
+ fnt->charmin = charmin;
+ fnt->charmax = charmax;
+ fnt->my_nchars = fnt->charmax-fnt->charmin+1;
+ fnt->scale = fscale;
+ fnt->my_chars = (chardesc *)MEM_mallocN(fnt->my_nchars*sizeof(chardesc), "newobjfnt2");
+ memset(fnt->my_chars, 0, fnt->my_nchars*sizeof(chardesc));
+ return fnt;
+}
+
+
+static void addchardata (objfnt * fnt, int c, short * data, int nshorts)
+{
+ int index;
+ chardesc *cd;
+
+ index = chartoindex(fnt,c);
+ if(index<0) {
+ fprintf(stderr,"Addchardata bad poop\n");
+ return;
+ }
+ cd = fnt->my_chars+index;
+ fnt->freeaddr = 0;
+ cd->datalen = nshorts*sizeof(short);
+ cd->data = (short *)MEM_mallocN(cd->datalen, "addchardata");
+ memcpy(cd->data, data, cd->datalen);
+}
+
+static void addcharmetrics(objfnt *fnt, int c, int movex, int movey)
+{
+ int index;
+ chardesc *cd;
+
+ index = chartoindex(fnt,c);
+ if(index<0) {
+ fprintf(stderr,"Addcharmetrics bad poop\n");
+ return;
+ }
+ cd = fnt->my_chars+index;
+ cd->movex = movex;
+ cd->movey = movey;
+}
+
+
+static void fakechar(objfnt *fnt, int c, int width)
+{
+ short chardata[1];
+
+ chardata[0] = PO_RET;
+ addchardata(fnt,c,chardata,1);
+ addcharmetrics(fnt,c,width,0);
+}
+
+
+static void freeobjfnt(objfnt * fnt)
+{
+ int i;
+ chardesc *cd;
+
+ cd = fnt->my_chars;
+ for(i=0; i<fnt->my_nchars; i++) {
+ if(cd->data)
+ MEM_freeN(cd->data);
+ cd++;
+ }
+ MEM_freeN(fnt->my_chars);
+ MEM_freeN(fnt);
+}
+
+
+/* END 5.2 */
+
+static short STDtoISO(short c)
+{
+ short i = (sizeof(STDvsISO) / (2 * sizeof(short))) - 1;
+
+ for (;i >= 0; i--){
+ if (STDvsISO[i][0] == c) return (STDvsISO[i][1]);
+ }
+ return(c);
+}
+
+
+/*
+ * read the font matrix out of the font file
+ *
+ */
+
+static char * newfgets(char * s, int n, PackedFile * pf){
+ int c;
+ char * p;
+
+ p = s;
+ while (n > 0){
+ c = ((char *) pf->data)[pf->seek];
+ pf->seek++;
+ if (pf->seek > pf->size){
+ return (0);
+ }
+ if (c == 10 || c == 13){
+ *p = 0;
+ return(s);
+ }
+ *p++ = c;
+ n--;
+ }
+ *p = 0;
+ return(s);
+}
+
+static int readfontmatrix(PackedFile * pf, float mat[2][2])
+{
+ char *cptr;
+ float a, b, c, d, e, f;
+
+ pf->seek = 0;
+
+ /* look for the FontMatrix def */
+ while(1) {
+ if(!newfgets(oneline, LINELEN, pf)) {
+ fprintf(stderr,"fromtype1: no FontMatrix found\n");
+ return(-1);
+ }
+ cptr = strchr(oneline,'/');
+ if(cptr) {
+ if(strncmp(cptr,"/FontMatrix",11) == 0) {
+ cptr = strchr(cptr,'[');
+ if(!cptr) {
+ fprintf(stderr,"fromtype1: bad FontMatrix line\n");
+ return(-1);
+ }
+ sscanf(cptr+1,"%f %f %f %f %f %f\n",&a,&b,&c,&d,&e,&f);
+ break;
+ }
+ }
+ }
+
+ mat[0][0] = 1000.0*a;
+ mat[1][0] = 1000.0*b;
+ mat[0][1] = 1000.0*c;
+ mat[1][1] = 1000.0*d;
+
+ return(0);
+}
+
+/*
+ * Decryption support
+ *
+ *
+ */
+static void resetdecrypt(int n)
+{
+ mr = n;
+}
+
+
+
+/*
+ * decryption subroutines
+ *
+ */
+
+static char mdecrypt(char cipher)
+{
+ char plain;
+
+ plain = (cipher^(mr>>8));
+ mr = (cipher+mr)*MC1 + MC2;
+ return plain;
+}
+
+static void decryptdata(char * cptr, int n)
+{
+ while(n--) {
+ *cptr = mdecrypt(*cptr);
+ cptr++;
+ }
+}
+
+static int decryptprogram(char *buf, int len)
+{
+ int i;
+
+ resetdecrypt(4330);
+ for(i=0; i<len; i++) {
+ if(i<SKIP) {
+ mdecrypt(buf[i]);
+ }
+ else {
+ buf[i-SKIP] = mdecrypt(buf[i]);
+ }
+ }
+ return len-SKIP;
+}
+
+static void decryptall(void)
+{
+ int i;
+
+ for(i=0; i<my_nsubrs; i++)
+ my_sublen[i] = decryptprogram(my_subrs[i],my_sublen[i]);
+ for(i=0; i<my_nchars; i++)
+ my_charlen[i] = decryptprogram(my_chars[i],my_charlen[i]);
+}
+
+
+/*
+ * decode the eexec part of the file
+ *
+ */
+
+static int decodetype1(PackedFile * pf, char *outname)
+{
+ char *hptr, *bptr;
+ int i, totlen, hexbytes, c;
+ char *hexdat;
+ char hextab[256];
+
+ /* make hex table */
+ if(!firsted) {
+ for(i=0; i<256; i++) {
+ if(i>='0' && i<='9')
+ hextab[i] = i-'0';
+ else if(i>='a' && i<='f')
+ hextab[i] = 10+i-'a';
+ else if(i>='A' && i<='F')
+ hextab[i] = 10+i-'A';
+ else
+ hextab[i] = NOTHEX;
+ }
+ }
+
+ pf->seek = 0;
+
+ /* allocate buffers */
+ totlen = pf->size;
+ hexdat = (char *)MEM_mallocN(totlen, "hexdat");
+ bindat = (char *)MEM_mallocN(totlen, "bindat");
+
+ /* look for eexec part of file */
+ while(1) {
+ if(!newfgets(oneline, LINELEN, pf)) {
+ fprintf(stderr,"fromtype1: no currentfile eexec found\n");
+ return(-1);
+ }
+ oneline[16] = 0;
+ if(strcmp(oneline,"currentfile eexe") == 0)
+ break;
+ }
+
+ /* initialize decryption variables */
+ mr = 55665;
+
+ /* first byte == 0 for binary data (???) */
+
+ c = ((char *) pf->data)[pf->seek];
+
+ if (hextab[c] != NOTHEX){
+ /* read all the hex bytes into the hex buffer */
+ hexbytes = 0;
+ while(newfgets(oneline, LINELEN, pf)) {
+ hptr = (char *)oneline;
+ while(*hptr) {
+ if(hextab[*hptr] != NOTHEX)
+ hexdat[hexbytes++] = *hptr;
+ hptr++;
+ }
+ }
+
+ /* check number of hex bytes */
+ if(hexbytes & 1)
+ hexbytes--;
+ datbytes = hexbytes/2;
+
+ /* translate hex data to binary */
+ hptr = hexdat;
+ bptr = bindat;
+ c = datbytes;
+ while(c--) {
+ *bptr++ = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
+ hptr += 2;
+ }
+
+ /* decrypt the data */
+ decryptdata(bindat,datbytes);
+
+ } else {
+ datbytes = pf->size - pf->seek;
+ memcpy(bindat, ((char *) pf->data) + pf->seek, datbytes);
+
+ if ((bindat[2] << (8 + bindat[3])) == 0x800){
+ /* order data (remove 6 bytes headers) */
+ i = datbytes;
+ hptr = bptr = bindat + 4;
+ hptr += 2;
+
+ while (i > 0){
+ if (i > 2046) c = 2046;
+ else c = i;
+
+ memcpy(bptr, hptr, c);
+ bptr += 2046;
+ hptr += 2046 + 6;
+ i -= 2046 + 6;
+ datbytes -= 6;
+ }
+
+ /* decrypt the data */
+ decryptdata(bindat+4,datbytes);
+ } else{
+ decryptdata(bindat+6,datbytes-6);
+ }
+ }
+
+#ifdef DEBUG
+ outf = fopen(outname,"wb");
+ fwrite(bindat,datbytes,1,outf);
+ fclose(outf);
+#endif
+
+ MEM_freeN(hexdat);
+
+ return 1;
+}
+
+/*
+ * fake file reading funcs
+ *
+ *
+ */
+
+static void fakefopen(void)
+{
+ fakepos = 0;
+ fakemax = datbytes;
+}
+
+
+static void fakegettoken(char *str)
+{
+ int c;
+ char *cptr;
+ char *start;
+
+ start = (char *) str;
+ cptr = bindat+fakepos;
+ c = *cptr++;
+ fakepos++;
+ if(c != '\n') {
+ while(isspace(c)) {
+ c = *cptr++;
+ fakepos++;
+ }
+ while (fakepos<fakemax && !isspace(c)) {
+ *str++ = c;
+ c = *cptr++;
+ fakepos++;
+ }
+ if(c == '\n')
+ fakepos--;
+ }
+ *str = 0;
+ if(fakepos>fakemax) {
+ fprintf(stderr,"fromtype1: unexpected eof\n");
+ strcpy(start, "end");
+ }
+}
+
+static int fakefgets(char *buf,int max)
+{
+ char *cptr;
+
+ cptr = (char *)(bindat+fakepos);
+ while(max--) {
+ *buf++ = *cptr;
+ fakepos++;
+ if(*cptr == 10 || *cptr == 13)
+ return 1;
+ cptr++;
+ if(fakepos>fakemax)
+ return 0;
+ }
+ return 0;
+}
+
+static char *fakefread(int n)
+{
+ fakepos += n;
+ return bindat+fakepos-n;
+}
+
+static void applymat(float mat[][2], float *x, float *y)
+{
+ float tx, ty;
+
+ tx = ((*x)*mat[0][0])+((*y)*mat[0][1]);
+ ty = ((*x)*mat[1][0])+((*y)*mat[1][1]);
+ *x = tx;
+ *y = ty;
+}
+
+static void setcharlist(void)
+{
+ char *name, found;
+ int i, j;
+
+ for(i=0; i<NASCII; i++) ISOcharlist[i].prog = -1;
+
+ for(j=0; j<my_nchars; j++) {
+ name = my_charname[j];
+ if(name) {
+ found = 0;
+ for(i=0; i<NASCII; i++) {
+ if(ISOcharlist[i].name && (strcmp(name,ISOcharlist[i].name) == 0)){
+ ISOcharlist[i].prog = j;
+ found = 1;
+ }
+ }
+ /*if (found == 0) printf("no match found for: %s\n", name);*/
+ MEM_freeN(name);
+ my_charname[j] = 0;
+ }
+ }
+}
+
+
+static objfnt * objfnt_from_psfont(PackedFile * pf)
+{
+ int i, k, index;
+ int nread, namelen;
+ char *cptr;
+
+ fnt = 0;
+ bindat = 0;
+
+ /* read the font matrix from the font */
+ if (readfontmatrix(pf,mat)) return(0);
+
+ /* decode the font data */
+ decodetype1(pf, "/usr/tmp/type1.dec");
+
+ /* open the input file */
+ fakefopen();
+
+ /* look for the /Subrs def and get my_nsubrs */
+ while(1) {
+ if(!fakefgets(oneline,LINELEN)) {
+ fprintf(stderr,"fromtype1: no /Subrs found\n");
+ my_nsubrs = 0;
+ fakefopen();
+ break;
+ }
+ cptr = strchr(oneline,'/');
+ if(cptr) {
+ if(strncmp(cptr,"/Subrs",6) == 0) {
+ my_nsubrs = atoi(cptr+6);
+ break;
+ }
+ }
+ }
+
+ /* read the Subrs in one by one */
+ for(i=0; i<my_nsubrs; i++)
+ my_sublen[i] = 0;
+ for(i=0; i<my_nsubrs; i++) {
+ for(k=0; k<MAXTRIES; k++) {
+ fakegettoken(tok);
+ if(strcmp(tok,"dup") == 0)
+ break;
+ }
+ if(k == MAXTRIES) {
+ fprintf(stderr,"dup for subr %d not found in range\n", i);
+ /*exit(1);*/
+ }
+
+ /* get the Subr index here */
+ fakegettoken(tok);
+ index = atoi(tok);
+
+ /* check to make sure it is in range */
+ if(index<0 || index>my_nsubrs) {
+ fprintf(stderr,"bad Subr index %d\n",index);
+ /*exit(1);*/
+ }
+
+ /* get the number of bytes to read */
+ fakegettoken(tok);
+ nread = atoi(tok);
+ fakegettoken(tok);
+
+ /* read in the subroutine */
+ my_sublen[index] = nread;
+ my_subrs[index] = fakefread(nread);
+ fakegettoken(tok);
+ }
+
+ /* look for the CharStrings */
+ while(1) {
+ fakegettoken(tok);
+ cptr = strchr(tok,'/');
+ if(cptr && strcmp(cptr,"/CharStrings") == 0)
+ break;
+ }
+
+ fakegettoken(tok); /* skip my_ncharscrings */
+ fakegettoken(tok); /* skip dict */
+ fakegettoken(tok); /* skip dup */
+ fakegettoken(tok); /* skip begin */
+ fakegettoken(tok); /* skip newline */
+
+ /* read the CharStrings one by one */
+ my_nchars = 0;
+ for(i=0; i<MAXCHARS; i++) {
+
+ /* check for end */
+ fakegettoken(tok);
+ if(strcmp(tok,"end") == 0)
+ break;
+
+ /* get the char name and allocate space for it */
+ namelen = strlen(tok);
+ my_charname[i] = (char *)MEM_mallocN(namelen+1, "my_charname");
+ strcpy(my_charname[i],tok);
+
+ /* get the number of bytes to read */
+ fakegettoken(tok);
+ nread = atoi(tok);
+ fakegettoken(tok);
+
+ /* read in the char description */
+ my_charlen[i] = nread;
+ my_chars[i] = fakefread(nread);
+
+ /* skip the end of line */
+ fakegettoken(tok);
+ fakegettoken(tok);
+ my_nchars++;
+ }
+
+ /* decrypt the character descriptions */
+ decryptall();
+ setcharlist();
+
+ /* make the obj font */
+ makeobjfont(savesplines);
+
+ if (bindat) MEM_freeN(bindat);
+ /* system("rm /usr/tmp/type1.dec"); */
+
+ return (fnt);
+}
+
+
+
+
+/*
+ * pc stack support
+ *
+ */
+
+static void initpcstack(void)
+{
+ pcsp = 0;
+}
+
+static void pushpc(char *pc)
+{
+ pcstack[pcsp] = pc;
+ pcsp++;
+}
+
+static char *poppc(void)
+{
+ pcsp--;
+ if(pcsp<0) {
+ fprintf(stderr,"\nYUCK: pc stack under flow\n");
+ pcsp = 0;
+ return 0;
+ }
+ return pcstack[pcsp];
+}
+
+/*
+ * Data stack support
+ *
+ */
+
+static void initstack(void)
+{
+ sp = 0;
+}
+
+static void push(int val)
+/* int val; */
+{
+ stack[sp] = val;
+ sp++;
+}
+
+static int pop(void)
+{
+ sp--;
+ if(sp<0) {
+ fprintf(stderr,"\nYUCK: stack under flow\n");
+ sp = 0;
+ return 0;
+ }
+ return stack[sp];
+}
+
+/*
+ * call/return data stack
+ *
+ */
+
+static void initretstack(void)
+{
+ retsp = 0;
+}
+
+static void retpush(int val)
+/* int val; */
+{
+ retstack[retsp] = val;
+ retsp++;
+}
+
+static int retpop(void)
+{
+ retsp--;
+ if(retsp<0) {
+ fprintf(stderr,"\nYUCK: ret stack under flow\n");
+ retsp = 0;
+ return 0;
+ }
+ return retstack[retsp];
+}
+
+
+/*
+ * execute the program:
+ *
+ *
+ */
+
+static void getmove(int *x, int *y)
+{
+ *x = delx;
+ *y = dely;
+ /* printf("ingetmove\n"); */
+}
+
+static void getpos(int *x, int *y)
+{
+ *x = curx;
+ *y = cury;
+}
+
+static void subr1(void)
+{
+ coordpos = 0;
+ incusp = 1;
+}
+
+static void subr2(void)
+{
+ int x, y;
+
+ getmove(&x,&y);
+ if(coordpos>=7) {
+ fprintf(stderr,"subr2: bad poop\n");
+ /*exit(1);*/
+ }
+ coordsave[coordpos][0] = x;
+ coordsave[coordpos][1] = y;
+ coordpos++;
+}
+
+static void subr0(void)
+{
+ int x0, y0;
+ int x1, y1;
+ int x2, y2;
+ int x3, y3;
+ int xpos, ypos, noise;
+
+ ypos = pop();
+ xpos = pop();
+ noise = pop();
+ if(coordpos!=7) {
+ fprintf(stderr,"subr0: bad poop\n");
+ /*exit(1);*/
+ }
+ x0 = coordsave[0][0];
+ y0 = coordsave[0][1];
+
+ x1 = coordsave[1][0]+x0;
+ y1 = coordsave[1][1]+y0;
+ x2 = coordsave[2][0];
+ y2 = coordsave[2][1];
+ x3 = coordsave[3][0];
+ y3 = coordsave[3][1];
+ rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
+ x1 = coordsave[4][0];
+ y1 = coordsave[4][1];
+ x2 = coordsave[5][0];
+ y2 = coordsave[5][1];
+ x3 = coordsave[6][0];
+ y3 = coordsave[6][1];
+ rcurveto(x1,y1,x1+x2,y1+y2,x1+x2+x3,y1+y2+y3);
+ getpos(&x0,&y0);
+ retpush(y0);
+ retpush(x0);
+ incusp = 0;
+}
+
+static void append_poly_offset(short ofsx, short ofsy, short * data)
+{
+ int nverts;
+
+ if (data == 0) return;
+
+ while(1) {
+ switch(chardata[nshorts++] = *data++) {
+ case PO_BGNLOOP:
+ nshorts --; /* for the first time */
+ break;
+ case PO_RETENDLOOP:
+ case PO_RET:
+ return;
+ }
+ nverts = chardata[nshorts++] = *data++;
+ while(nverts--) {
+ chardata[nshorts++] = (*data++) + ofsx;
+ chardata[nshorts++] = (*data++) + ofsy;
+ }
+ }
+}
+
+
+static void append_spline_offset(short ofsx, short ofsy, short * data)
+{
+ int nverts = 0;
+
+ if (data == 0) return;
+
+ while(1) {
+ switch(chardata[nshorts++] = *data++) {
+ case SP_MOVETO:
+ case SP_LINETO:
+ nverts = 1;
+ break;
+ case SP_CURVETO:
+ nverts = 3;
+ break;
+ case SP_RETCLOSEPATH:
+ case SP_RET:
+ return;
+ }
+
+ for (; nverts > 0; nverts--) {
+ chardata[nshorts++] = (*data++) + ofsx;
+ chardata[nshorts++] = (*data++) + ofsy;
+ }
+ }
+}
+
+
+
+/*
+ * graphics follows
+ *
+ *
+ */
+
+
+/* poly output stuff */
+
+static void setwidth(int w, int x)
+{
+ thecharwidth = w;
+ thesidebearing = x;
+}
+
+static void poly_beginchar(void)
+{
+ npnts = 0;
+ nloops = 0;
+}
+
+static void poly_endchar(void)
+{
+ if(nloops == 0)
+ chardata[nshorts++] = PO_RET;
+ else
+ chardata[nshorts++] = PO_RETENDLOOP;
+}
+
+static void poly_close(void)
+{
+ chardata[nvertpos] = npnts;
+ npnts = 0;
+}
+
+static void poly_pnt(float x, float y)
+{
+ int ix, iy;
+
+ applymat(mat,&x,&y);
+ ix = floor(x);
+ iy = floor(y);
+ if(npnts == 0) {
+ if(nloops == 0) {
+ chardata[nshorts++] = PO_BGNLOOP;
+ nvertpos = nshorts++;
+ } else {
+ chardata[nshorts++] = PO_ENDBGNLOOP;
+ nvertpos = nshorts++;
+ }
+ nloops++;
+ }
+ chardata[nshorts++] = ix;
+ chardata[nshorts++] = iy;
+ npnts++;
+
+}
+
+/* spline output stuff */
+
+static void spline_beginchar(void)
+{
+ sp_npnts = 0;
+ sp_nloops = 0;
+}
+
+static void spline_endchar(void)
+{
+ if(sp_nloops == 0)
+ chardata[nshorts++] = SP_RET;
+ else
+ chardata[nshorts++] = SP_RETCLOSEPATH;
+}
+
+static void spline_close(void)
+{
+ chardata[nshorts++] = SP_CLOSEPATH;
+ sp_npnts = 0;
+ sp_nloops = 0;
+}
+
+static void spline_line(float x0, float y0, float x1, float y1)
+{
+ applymat(mat,&x0,&y0);
+ applymat(mat,&x1,&y1);
+
+ if(sp_npnts == 0) {
+ chardata[nshorts++] = SP_MOVETO;
+ chardata[nshorts++] = floor(x0);
+ chardata[nshorts++] = floor(y0);
+ sp_npnts++;
+ sp_nloops++;
+ }
+ chardata[nshorts++] = SP_LINETO;
+ chardata[nshorts++] = floor(x1);
+ chardata[nshorts++] = floor(y1);
+ sp_npnts++;
+}
+
+static void spline_curveto(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ applymat(mat,&x0,&y0);
+
+ applymat(mat,&x1,&y1);
+ applymat(mat,&x2,&y2);
+ applymat(mat,&x3,&y3);
+ if(sp_npnts == 0) {
+ chardata[nshorts++] = SP_MOVETO;
+ chardata[nshorts++] = floor(x0);
+ chardata[nshorts++] = floor(y0);
+ sp_npnts++;
+ sp_nloops++;
+ }
+ chardata[nshorts++] = SP_CURVETO;
+ chardata[nshorts++] = floor(x1);
+ chardata[nshorts++] = floor(y1);
+ chardata[nshorts++] = floor(x2);
+ chardata[nshorts++] = floor(y2);
+ chardata[nshorts++] = floor(x3);
+ chardata[nshorts++] = floor(y3);
+}
+
+static void savestart(int x, int y)
+{
+ startx = x;
+ starty = y;
+ started = 1;
+}
+
+static void sbpoint( int x, int y)
+{
+ curx = x;
+ cury = y;
+}
+
+static void rmoveto( int x, int y)
+{
+ if(incusp) {
+ delx = x;
+ dely = y;
+ } else {
+ curx += x;
+ cury += y;
+ savestart(curx,cury);
+ }
+}
+
+static void drawline(float x0, float y0, float x1, float y1, float dx0, float dy0, float dx1, float dy1)
+{
+ if(x0!=x1 || y0!=y1)
+ poly_pnt(x1,y1);
+}
+
+
+static void rlineto( int x, int y)
+{
+ float dx, dy;
+
+ nextx = curx + x;
+ nexty = cury + y;
+ dx = nextx-curx;
+ dy = nexty-cury;
+ if (savesplines) spline_line( curx, cury, nextx, nexty);
+ else drawline( curx, cury, nextx, nexty,dx,dy,dx,dy);
+ curx = nextx;
+ cury = nexty;
+}
+
+static void closepath(void)
+{
+ float dx, dy;
+
+ if(started) {
+ dx = startx-curx;
+ dy = starty-cury;
+ if (savesplines) {
+ spline_close();
+ } else {
+ drawline( curx, cury, startx, starty,dx,dy,dx,dy);
+ poly_close();
+ }
+ started = 0;
+ }
+}
+
+static void bezadapt( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float beztol)
+{
+ float ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3;
+ float bx0,by0,bx1,by1,bx2,by2,bx3,by3;
+ float midx, midy;
+ float linx, liny, dx, dy, mag;
+
+ midx = (x0+3*x1+3*x2+x3)/8.0;
+ midy = (y0+3*y1+3*y2+y3)/8.0;
+ linx = (x0+x3)/2.0;
+ liny = (y0+y3)/2.0;
+ dx = midx-linx;
+ dy = midy-liny;
+ mag = dx*dx+dy*dy;
+ if(mag<(beztol*beztol))
+ drawline(x0,y0,x3,y3,x1-x0,y1-y0,x3-x2,y3-y2);
+ else {
+ ax0 = x0;
+ ay0 = y0;
+ ax1 = (x0+x1)/2;
+ ay1 = (y0+y1)/2;
+ ax2 = (x0+2*x1+x2)/4;
+ ay2 = (y0+2*y1+y2)/4;
+ ax3 = midx;
+ ay3 = midy;
+ bezadapt(ax0,ay0,ax1,ay1,ax2,ay2,ax3,ay3,beztol);
+
+ bx0 = midx;
+ by0 = midy;
+ bx1 = (x1+2*x2+x3)/4;
+ by1 = (y1+2*y2+y3)/4;
+ bx2 = (x2+x3)/2;
+ by2 = (y2+y3)/2;
+ bx3 = x3;
+ by3 = y3;
+ bezadapt(bx0,by0,bx1,by1,bx2,by2,bx3,by3,beztol);
+ }
+}
+
+static void drawbez( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ bezadapt(x0,y0,x1,y1,x2,y2,x3,y3,beztol);
+}
+
+
+static void rcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
+{
+ int x0, y0;
+ int x1, y1;
+ int x2, y2;
+ int x3, y3;
+
+ x0 = curx;
+ y0 = cury;
+ x1 = curx+dx1;
+ y1 = cury+dy1;
+ x2 = curx+dx2;
+ y2 = cury+dy2;
+ x3 = curx+dx3;
+ y3 = cury+dy3;
+
+ if (savesplines) {
+ spline_curveto( x0, y0, x1, y1, x2, y2, x3, y3);
+ } else{
+ drawbez( x0, y0, x1, y1, x2, y2, x3, y3);
+ }
+ curx = x3;
+ cury = y3;
+}
+
+/*
+ * saveobjfont -
+ * save an object font.
+ *
+ */
+
+/* generic routines */
+
+static void makeobjfont(int savesplines)
+{
+ int i, c;
+
+ if(savesplines)
+ fnt = newobjfnt(SP_TYPE, 32, 32+NASCII-1, 9840);
+ else
+ fnt = newobjfnt(PO_TYPE, 32, 32+NASCII-1, 9840);
+
+ for(i=0; i<NASCII; i++) {
+ c = i+32;
+ if(ISOcharlist[i].prog>=0) {
+ /*printf("decoding %s\n", ISOcharlist[i].name);*/
+
+ nshorts = 0;
+ drawchar(ISOcharlist[i].prog);
+ addchardata(fnt,c,chardata,nshorts);
+ addcharmetrics(fnt,c,thecharwidth,0);
+ sidebearing[c] = thesidebearing;
+ } else if(c == ' ') {
+ printf("faking space %d\n",i);
+ fakechar(fnt,' ',400);
+ }
+ }
+}
+
+/*
+ * run the character program
+ *
+ *
+ */
+
+static void drawchar(int c)
+{
+ if (savesplines) {
+ spline_beginchar();
+ } else {
+ poly_beginchar();
+ }
+ initstack();
+ initpcstack();
+ initretstack();
+ pc = my_chars[c];
+ runprog();
+ if (savesplines){
+ spline_endchar();
+ } else {
+ poly_endchar();
+ }
+}
+
+static int docommand(int cmd)
+{
+ int x, y, w, c1, c2;
+ int dx1, dy1;
+ int dx2, dy2;
+ int dx3, dy3;
+ float fdx1, fdy1;
+ int i, sub, n;
+ char *subpc;
+ chardesc *cd;
+ short *ndata;
+
+ switch(cmd) {
+ case WHAT0:
+ fprintf(stderr,"\nYUCK: WHAT0\n");
+ break;
+ case HSTEM:
+ pop();
+ pop();
+ /*printf("hstem: %d %d\n", pop(), pop());*/
+ break;
+ case VSTEM:
+ pop();
+ pop();
+ /*printf("vstem: %d %d\n", pop(), pop());*/
+ break;
+ case VMOVETO:
+ y = pop();
+ rmoveto(0,y);
+ break;
+ case RLINETO:
+ y = pop();
+ x = pop();
+ rlineto(x,y);
+ break;
+ case HLINETO:
+ x = pop();
+ rlineto(x,0);
+ break;
+ case VLINETO:
+ y = pop();
+ rlineto(0,y);
+ break;
+ case RRCURVETO:
+ dy3 = pop();
+ dx3 = pop();
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = pop();
+ dx1 = pop();
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case CLOSEPATH:
+ closepath();
+ break;
+ case CALLSUBR:
+ sub = pop();
+ subpc = my_subrs[sub];
+ if(!subpc) {
+ fprintf(stderr,"\nYUCK no sub addr\n");
+ }
+ pushpc(pc);
+ pc = subpc;
+ break;
+ case RETURN:
+ pc = poppc();
+ break;
+ case HSBW:
+ w = pop();
+ x = pop();
+ setwidth(w, x);
+ sbpoint(x,0);
+ break;
+ case ENDCHAR:
+ closepath();
+ break;
+ case RMOVETO:
+ y = pop();
+ x = pop();
+ rmoveto(x,y);
+ break;
+ case HMOVETO:
+ x = pop();
+ rmoveto(x,0);
+ break;
+ case VHCURVETO:
+ dy3 = 0;
+ dx3 = pop();
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = pop();
+ dx1 = 0;
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case HVCURVETO:
+ dy3 = pop();
+ dx3 = 0;
+ dy2 = pop();
+ dx2 = pop();
+ dy1 = 0;
+ dx1 = pop();
+ rcurveto(dx1,dy1,dx1+dx2,dy1+dy2,dx1+dx2+dx3,dy1+dy2+dy3);
+ break;
+ case DOTSECTION:
+ break;
+ case VSTEM3:
+ /*printf("vstem3\n");*/
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ break;
+ case HSTEM3:
+ /*printf("hstem3\n");*/
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ pop();
+ break;
+ case SEAC:
+ if (0) {
+ printf("seac: %3d %3d %3d %3d %3d\n", pop(), pop(), pop(), pop(), pop());
+ } else{
+ c2 = STDtoISO(pop()); /* accent */
+ c1 = STDtoISO(pop()); /* letter */
+
+ cd = getchardesc(fnt, c1);
+ if (cd) {
+ memcpy(chardata, cd->data, cd->datalen);
+ nshorts = cd->datalen / sizeof(short);
+ }
+
+ cd = getchardesc(fnt, c2);
+ if (cd && cd->data && cd->datalen) {
+ ndata = cd->data;
+
+ if (nshorts) {
+ if (savesplines) {
+ switch (chardata[nshorts - 1]){
+ case SP_RET:
+ nshorts--;
+ break;
+ case SP_RETCLOSEPATH:
+ chardata[nshorts - 1] = SP_CLOSEPATH;
+ break;
+ }
+ } else {
+ switch (chardata[nshorts - 1]){
+ case PO_RET:
+ printf("PO_RET in character disription ?\n");
+ nshorts--;
+ break;
+ case PO_RETENDLOOP:
+ if (ndata[0] == PO_BGNLOOP) {
+ chardata[nshorts - 1] = PO_ENDBGNLOOP;
+ } else {
+ printf("new character doesn't start with PO_BGNLOOP ?\n");
+ }
+ break;
+ }
+ }
+ }
+
+ /* instead of the sidebearing[c1] maybe thesidebearing should be used */
+
+ dy1 = pop();
+ dx1 = pop() + sidebearing[c1] - sidebearing[c2];
+ pop();
+
+ fdx1 = dx1;
+ fdy1 = dy1;
+ applymat(mat, &fdx1, &fdy1);
+ dx1 = floor(fdx1);
+ dy1 = floor(fdy1);
+
+ if (savesplines) {
+ append_spline_offset(dx1, dy1, ndata);
+ } else{
+ append_poly_offset(dx1, dy1, ndata);
+ }
+
+ /*printf("first: %d %d\n", cd->data[0], cd->data[1]);*/
+ }
+ fflush(stdout);
+ }
+ break;
+ case SBW:
+ w = pop();
+ y = pop();
+ fprintf(stderr,"sbw: width: %d %d\n",w,y);
+ y = pop();
+ x = pop();
+ fprintf(stderr,"sbw: side: %d %d\n",x,y);
+ setwidth(w, x);
+ sbpoint(x,y);
+ break;
+ case DIV:
+ x = pop();
+ y = pop();
+ push(x/y);
+ break;
+ case CALLOTHERSUBR:
+ sub = pop();
+ n = pop();
+ if(sub == 0)
+ subr0();
+ else if(sub == 1)
+ subr1();
+ else if(sub == 2)
+ subr2();
+ else {
+ for(i=0; i<n; i++) {
+ retpush(pop());
+ }
+ }
+ break;
+ case POP:
+ push(retpop());
+ break;
+ case SETCURRENTPOINT:
+ y = pop();
+ x = pop();
+ sbpoint(x,y);
+ break;
+ default:
+ /*fprintf(stderr,"\nYUCK bad instruction %d\n",cmd);*/
+ break;
+ }
+ if(pc == 0 || cmd == ENDCHAR || cmd == WHAT0 || cmd == SEAC)
+ return 0;
+ else
+ return 1;
+}
+
+
+/*
+ * Character interpreter
+ *
+ */
+
+static void runprog(void)
+{
+ int v, w, num, cmd;
+
+ while(1) {
+ v = *pc++;
+ if(v>=0 && v<=31) {
+ if(v == 12) {
+ w = *pc++;
+ cmd = 256+w;
+ } else
+ cmd = v;
+ if(!docommand(cmd)) {
+ return;
+ }
+ } else if(v>=32 && v<=246) {
+ num = v-139;
+ push(num);
+ } else if(v>=247 && v<=250) {
+ w = *pc++;
+ num = (v-247)*256+w+108;
+ push(num);
+ } else if(v>=251 && v<=254) {
+ w = *pc++;
+ num = -(v-251)*256-w-108;
+ push(num);
+ } else if(v == 255) {
+ num = *pc++;
+ num <<= 8;
+ num |= *pc++;
+ num <<= 8;
+ num |= *pc++;
+ num <<= 8;
+ num |= *pc++;
+ push(num);
+ }
+ }
+}
+
+/***/
+
+static VFontData *objfnt_to_vfontdata(objfnt *fnt)
+{
+ VFontData *vfd;
+ chardesc *cd;
+ short *_data, *data;
+ int a, i, count, stop, ready, meet;
+ short first[2], last[2];
+ struct Nurb *nu;
+ struct BezTriple *bezt, *bez2;
+ float scale, dx, dy;
+ struct VChar *che;
+
+ if (!fnt || (fnt->type!=SP_TYPE)) {
+ return NULL;
+ }
+
+ vfd= MEM_callocN(sizeof(*vfd), "VFontData");
+ scale = 10.0/(float)fnt->scale; /* after IRIX 6.2, scaling went wrong */
+
+ for (i = 0; i < MAX_VF_CHARS; i++) {
+ cd = getchardesc(fnt, i);
+ if (cd && cd->data && cd->datalen) {
+ che = (VChar *) MEM_callocN(sizeof(VChar), "objfnt_char");
+ BLI_addtail(&vfd->characters, che);
+ che->index = i;
+ che->width = scale * cd->movex;
+
+ _data = data = cd->data;
+
+ do{
+ /* count first */
+ _data = data;
+ count = 0;
+ ready = stop = 0;
+
+ do{
+ switch(*data++){
+ case SP_MOVETO:
+ first[0] = data[0];
+ first[1] = data[1];
+ case SP_LINETO:
+ count++;
+ last[0] = data[0];
+ last[1] = data[1];
+ data += 2;
+ break;
+ case SP_CURVETO:
+ count++;
+ last[0] = data[4];
+ last[1] = data[5];
+ data += 6;
+ break;
+ case SP_RET:
+ case SP_RETCLOSEPATH:
+ stop = 1;
+ ready = 1;
+ break;
+ case SP_CLOSEPATH:
+ stop = 1;
+ break;
+ }
+ } while (!stop);
+
+ if ((count>0) && last[0] == first[0] && last[1] == first[1]) meet = 1;
+ else meet = 0;
+
+ /* is there more than 1 unique point ?*/
+
+ if (count - meet > 0) {
+ data = _data;
+ nu = (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
+ bezt = (BezTriple*)MEM_callocN((count)* sizeof(BezTriple),"objfnt_bezt") ;
+ if (nu != 0 && bezt != 0) {
+ BLI_addtail(&che->nurbsbase, nu);
+ nu->type= CU_BEZIER+CU_2D;
+ nu->pntsu = count;
+ nu->resolu= 8;
+ nu->flagu= 1;
+ nu->bezt = bezt;
+ stop = 0;
+
+ /* read points */
+ do {
+ switch(*data++){
+ case SP_MOVETO:
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+
+ break;
+ case SP_LINETO:
+ bez2 = bezt++;
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+ /* vector handles */
+ bezt->h1= HD_VECT;
+ bez2->h2= HD_VECT;
+ dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
+ dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
+ bezt->vec[0][0] = bezt->vec[1][0] - dx;
+ bezt->vec[0][1] = bezt->vec[1][1] - dy;
+ bez2->vec[2][0] = bez2->vec[1][0] + dx;
+ bez2->vec[2][1] = bez2->vec[1][1] + dy;
+ break;
+
+ case SP_CURVETO:
+ bezt->vec[2][0] = scale * *data++;
+ bezt->vec[2][1] = scale * *data++;
+ bezt->h2= HD_ALIGN;
+ bezt++;
+ bezt->vec[0][0] = scale * *data++;
+ bezt->vec[0][1] = scale * *data++;
+ bezt->vec[1][0] = scale * *data++;
+ bezt->vec[1][1] = scale * *data++;
+ bezt->h1= HD_ALIGN;
+ break;
+
+ case SP_RET:
+ case SP_RETCLOSEPATH:
+ stop = 1;
+ ready = 1;
+ break;
+ case SP_CLOSEPATH:
+ stop = 1;
+ break;
+ }
+ } while (stop == 0);
+
+ if (meet) {
+ /* copy handles */
+ nu->bezt->vec[0][0] = bezt->vec[0][0];
+ nu->bezt->vec[0][1] = bezt->vec[0][1];
+ /* and forget last point */
+ nu->pntsu--;
+ }
+ else {
+ /* vector handles */
+ bez2 = nu->bezt;
+ dx = (bezt->vec[1][0] - bez2->vec[1][0]) / 3.0;
+ dy = (bezt->vec[1][1] - bez2->vec[1][1]) / 3.0;
+ bezt->vec[2][0] = bezt->vec[1][0] - dx;
+ bezt->vec[2][1] = bezt->vec[1][1] - dy;
+ bez2->vec[0][0] = bez2->vec[1][0] + dx;
+ bez2->vec[0][1] = bez2->vec[1][1] + dy;
+ bezt->h2= bez2->h1= HD_VECT;
+ }
+
+ /* forbidden handle combinations */
+ a= nu->pntsu;
+ bezt= nu->bezt;
+ while(a--) {
+ if(bezt->h1!=HD_ALIGN && bezt->h2==HD_ALIGN) bezt->h2= 0;
+ else if(bezt->h2!=HD_ALIGN && bezt->h1==HD_ALIGN) bezt->h1= 0;
+ bezt++;
+ }
+
+ }
+ else {
+ if (nu) MEM_freeN(nu);
+ if (bezt) MEM_freeN(bezt);
+ }
+ }
+ _data = data;
+ } while (ready == 0);
+ }
+ }
+
+ return vfd;
+}
+
+VFontData *BLI_vfontdata_from_psfont(PackedFile *pf)
+{
+ objfnt *fnt= objfnt_from_psfont(pf);
+ VFontData *vfd= NULL;
+
+ if (fnt) {
+ vfd= objfnt_to_vfontdata(fnt);
+ freeobjfnt(fnt);
+ }
+
+ return vfd;
+}
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
new file mode 100644
index 00000000000..df01288aab8
--- /dev/null
+++ b/source/blender/blenlib/intern/rand.c
@@ -0,0 +1,192 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "PIL_time.h"
+
+#include "BLI_threads.h"
+#include "BLI_rand.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(WIN32) && !defined(FREE_WINDOWS)
+typedef unsigned __int64 r_uint64;
+
+#define MULTIPLIER 0x5DEECE66Di64
+#define MASK 0x0000FFFFFFFFFFFFi64
+#else
+typedef unsigned long long r_uint64;
+
+#define MULTIPLIER 0x5DEECE66Dll
+#define MASK 0x0000FFFFFFFFFFFFll
+#endif
+
+#define ADDEND 0xB
+
+#define LOWSEED 0x330E
+
+/***/
+
+struct RNG {
+ r_uint64 X;
+};
+
+RNG *rng_new(unsigned int seed)
+{
+ RNG *rng = MEM_mallocN(sizeof(*rng), "rng");
+
+ rng_seed(rng, seed);
+
+ return rng;
+}
+
+void rng_free(RNG* rng)
+{
+ MEM_freeN(rng);
+}
+
+void rng_seed(RNG *rng, unsigned int seed) {
+ rng->X= (((r_uint64) seed)<<16) | LOWSEED;
+}
+
+int rng_getInt(RNG *rng) {
+ rng->X= (MULTIPLIER*rng->X + ADDEND)&MASK;
+ return (int) (rng->X>>17);
+}
+
+double rng_getDouble(RNG *rng) {
+ return (double) rng_getInt(rng)/0x80000000;
+}
+
+float rng_getFloat(RNG *rng) {
+ return (float) rng_getInt(rng)/0x80000000;
+}
+
+void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems)
+{
+ int i = numElems;
+ void *temp = malloc(elemSize);
+
+ while (--i) {
+ int j = rng_getInt(rng)%numElems;
+ if(i!=j) {
+ void *iElem = (unsigned char*)data + i*elemSize;
+ void *jElem = (unsigned char*)data + j*elemSize;
+ memcpy(temp, iElem, elemSize);
+ memcpy(iElem, jElem, elemSize);
+ memcpy(jElem, temp, elemSize);
+ }
+ }
+
+ free(temp);
+}
+
+/***/
+
+static RNG theBLI_rng = {0};
+
+/* note, this one creates periodical patterns */
+void BLI_srand(unsigned int seed) {
+ rng_seed(&theBLI_rng, seed);
+}
+
+/* using hash table to create better seed */
+void BLI_srandom(unsigned int seed) {
+ extern unsigned char hash[]; // noise.c
+
+ rng_seed(&theBLI_rng, seed + hash[seed & 255]);
+ seed= rng_getInt(&theBLI_rng);
+ rng_seed(&theBLI_rng, seed + hash[seed & 255]);
+ seed= rng_getInt(&theBLI_rng);
+ rng_seed(&theBLI_rng, seed + hash[seed & 255]);
+}
+
+int BLI_rand(void) {
+ return rng_getInt(&theBLI_rng);
+}
+
+double BLI_drand(void) {
+ return rng_getDouble(&theBLI_rng);
+}
+
+float BLI_frand(void) {
+ return rng_getFloat(&theBLI_rng);
+}
+
+void BLI_fillrand(void *addr, int len) {
+ RNG rng;
+ unsigned char *p= addr;
+
+ rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
+ while (len--) *p++= rng_getInt(&rng)&0xFF;
+}
+
+void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed)
+{
+ RNG rng;
+
+ rng_seed(&rng, seed);
+ rng_shuffleArray(&rng, data, elemSize, numElems);
+}
+
+/* ********* for threaded random ************** */
+
+static RNG rng_tab[BLENDER_MAX_THREADS];
+
+void BLI_thread_srandom(int thread, unsigned int seed)
+{
+ extern unsigned char hash[]; // noise.c
+
+ if(thread >= BLENDER_MAX_THREADS)
+ thread= 0;
+
+ rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
+ seed= rng_getInt(&rng_tab[thread]);
+ rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
+ seed= rng_getInt(&rng_tab[thread]);
+ rng_seed(&rng_tab[thread], seed + hash[seed & 255]);
+}
+
+int BLI_thread_rand(int thread) {
+ return rng_getInt(&rng_tab[thread]);
+}
+
+float BLI_thread_frand(int thread) {
+ return rng_getFloat(&rng_tab[thread]);
+}
+
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
new file mode 100644
index 00000000000..60d96922544
--- /dev/null
+++ b/source/blender/blenlib/intern/rct.c
@@ -0,0 +1,171 @@
+/*
+ *
+ * rct.c
+ *
+ * april 95
+ *
+ * $Id$
+ *
+ * A minimalist lib for functions doing stuff with rectangle structs.
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#include "DNA_vec_types.h"
+#include "BLI_blenlib.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int BLI_rcti_is_empty(rcti * rect)
+{
+ return ((rect->xmax<=rect->xmin) ||
+ (rect->ymax<=rect->ymin));
+}
+
+int BLI_in_rcti(rcti * rect, int x, int y)
+{
+
+ if(x<rect->xmin) return 0;
+ if(x>rect->xmax) return 0;
+ if(y<rect->ymin) return 0;
+ if(y>rect->ymax) return 0;
+ return 1;
+}
+
+int BLI_in_rctf(rctf *rect, float x, float y)
+{
+
+ if(x<rect->xmin) return 0;
+ if(x>rect->xmax) return 0;
+ if(y<rect->ymin) return 0;
+ if(y>rect->ymax) return 0;
+ return 1;
+}
+
+void BLI_union_rctf(rctf *rct1, rctf *rct2)
+{
+
+ if(rct1->xmin>rct2->xmin) rct1->xmin= rct2->xmin;
+ if(rct1->xmax<rct2->xmax) rct1->xmax= rct2->xmax;
+ if(rct1->ymin>rct2->ymin) rct1->ymin= rct2->ymin;
+ if(rct1->ymax<rct2->ymax) rct1->ymax= rct2->ymax;
+}
+
+void BLI_init_rctf(rctf *rect, float xmin, float xmax, float ymin, float ymax)
+{
+ rect->xmin= xmin;
+ rect->xmax= xmax;
+ rect->ymin= ymin;
+ rect->ymax= ymax;
+}
+void BLI_init_rcti(rcti *rect, int xmin, int xmax, int ymin, int ymax)
+{
+ rect->xmin= xmin;
+ rect->xmax= xmax;
+ rect->ymin= ymin;
+ rect->ymax= ymax;
+}
+
+void BLI_translate_rcti(rcti *rect, int x, int y)
+{
+ rect->xmin += x;
+ rect->ymin += y;
+ rect->xmax += x;
+ rect->ymax += y;
+}
+void BLI_translate_rctf(rctf *rect, float x, float y)
+{
+ rect->xmin += x;
+ rect->ymin += y;
+ rect->xmax += x;
+ rect->ymax += y;
+}
+
+int BLI_isect_rctf(rctf *src1, rctf *src2, rctf *dest)
+{
+ float xmin, xmax;
+ float ymin, ymax;
+
+ xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin);
+ xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax);
+ ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin);
+ ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax);
+
+ if(xmax>=xmin && ymax>=ymin) {
+ if(dest) {
+ dest->xmin = xmin;
+ dest->xmax = xmax;
+ dest->ymin = ymin;
+ dest->ymax = ymax;
+ }
+ return 1;
+ }
+ else {
+ if(dest) {
+ dest->xmin = 0;
+ dest->xmax = 0;
+ dest->ymin = 0;
+ dest->ymax = 0;
+ }
+ return 0;
+ }
+}
+
+int BLI_isect_rcti(rcti *src1, rcti *src2, rcti *dest)
+{
+ int xmin, xmax;
+ int ymin, ymax;
+
+ xmin = (src1->xmin) > (src2->xmin) ? (src1->xmin) : (src2->xmin);
+ xmax = (src1->xmax) < (src2->xmax) ? (src1->xmax) : (src2->xmax);
+ ymin = (src1->ymin) > (src2->ymin) ? (src1->ymin) : (src2->ymin);
+ ymax = (src1->ymax) < (src2->ymax) ? (src1->ymax) : (src2->ymax);
+
+ if(xmax>=xmin && ymax>=ymin) {
+ if(dest) {
+ dest->xmin = xmin;
+ dest->xmax = xmax;
+ dest->ymin = ymin;
+ dest->ymax = ymax;
+ }
+ return 1;
+ }
+ else {
+ if(dest) {
+ dest->xmin = 0;
+ dest->xmax = 0;
+ dest->ymin = 0;
+ dest->ymax = 0;
+ }
+ return 0;
+ }
+}
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
new file mode 100644
index 00000000000..3c0770e5e07
--- /dev/null
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -0,0 +1,1056 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * (uit traces) maart 95
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BLI_util.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+#include "BLI_scanfill.h"
+#include "BLI_callbacks.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* callbacks for errors and interrupts and some goo */
+static void (*BLI_localErrorCallBack)(char*) = NULL;
+static int (*BLI_localInterruptCallBack)(void) = NULL;
+
+void BLI_setErrorCallBack(void (*f)(char*))
+{
+ BLI_localErrorCallBack = f;
+}
+
+void BLI_setInterruptCallBack(int (*f)(void))
+{
+ BLI_localInterruptCallBack = f;
+}
+
+/* just flush the error to /dev/null if the error handler is missing */
+void callLocalErrorCallBack(char* msg)
+{
+ if (BLI_localErrorCallBack) {
+ BLI_localErrorCallBack(msg);
+ }
+}
+
+#if 0
+/* ignore if the interrupt wasn't set */
+static int callLocalInterruptCallBack(void)
+{
+ if (BLI_localInterruptCallBack) {
+ return BLI_localInterruptCallBack();
+ } else {
+ return 0;
+ }
+}
+#endif
+
+/* local types */
+typedef struct PolyFill {
+ int edges,verts;
+ float min[3],max[3];
+ short f,nr;
+} PolyFill;
+
+typedef struct ScFillVert {
+ EditVert *v1;
+ EditEdge *first,*last;
+ short f,f1;
+} ScFillVert;
+
+
+/* local funcs */
+
+#define COMPLIMIT 0.00003
+
+static ScFillVert *scdata;
+
+ListBase fillvertbase = {0,0};
+ListBase filledgebase = {0,0};
+ListBase fillfacebase = {0,0};
+
+static short cox, coy;
+
+/* **** FUBCTIONS FOR QSORT *************************** */
+
+
+static int vergscdata(const void *a1, const void *a2)
+{
+ const ScFillVert *x1=a1,*x2=a2;
+
+ if( x1->v1->co[coy] < x2->v1->co[coy] ) return 1;
+ else if( x1->v1->co[coy] > x2->v1->co[coy]) return -1;
+ else if( x1->v1->co[cox] > x2->v1->co[cox] ) return 1;
+ else if( x1->v1->co[cox] < x2->v1->co[cox]) return -1;
+
+ return 0;
+}
+
+static int vergpoly(const void *a1, const void *a2)
+{
+ const PolyFill *x1=a1, *x2=a2;
+
+ if( x1->min[cox] > x2->min[cox] ) return 1;
+ else if( x1->min[cox] < x2->min[cox] ) return -1;
+ else if( x1->min[coy] > x2->min[coy] ) return 1;
+ else if( x1->min[coy] < x2->min[coy] ) return -1;
+
+ return 0;
+}
+
+/* ************* MEMORY MANAGEMENT ************* */
+
+struct mem_elements {
+ struct mem_elements *next, *prev;
+ char *data;
+};
+
+
+/* simple optimization for allocating thousands of small memory blocks
+ only to be used within loops, and not by one function at a time
+ free in the end, with argument '-1'
+*/
+
+static void *new_mem_element(int size)
+{
+ int blocksize= 16384;
+ static int offs= 0; /* the current free adress */
+ static struct mem_elements *cur= 0;
+ static ListBase lb= {0, 0};
+ void *adr;
+
+ if(size>10000 || size==0) {
+ printf("incorrect use of new_mem_element\n");
+ }
+ else if(size== -1) {
+ cur= lb.first;
+ while(cur) {
+ MEM_freeN(cur->data);
+ cur= cur->next;
+ }
+ BLI_freelistN(&lb);
+
+ return NULL;
+ }
+
+ size= 4*( (size+3)/4 );
+
+ if(cur) {
+ if(size+offs < blocksize) {
+ adr= (void *) (cur->data+offs);
+ offs+= size;
+ return adr;
+ }
+ }
+
+ cur= MEM_callocN( sizeof(struct mem_elements), "newmem");
+ cur->data= MEM_callocN(blocksize, "newmem");
+ BLI_addtail(&lb, cur);
+
+ offs= size;
+ return cur->data;
+}
+
+void BLI_end_edgefill(void)
+{
+ new_mem_element(-1);
+
+ fillvertbase.first= fillvertbase.last= 0;
+ filledgebase.first= filledgebase.last= 0;
+ fillfacebase.first= fillfacebase.last= 0;
+}
+
+/* **** FILL ROUTINES *************************** */
+
+EditVert *BLI_addfillvert(float *vec)
+{
+ EditVert *eve;
+
+ eve= new_mem_element(sizeof(EditVert));
+ BLI_addtail(&fillvertbase, eve);
+
+ eve->co[0] = vec[0];
+ eve->co[1] = vec[1];
+ eve->co[2] = vec[2];
+
+ return eve;
+}
+
+EditEdge *BLI_addfilledge(EditVert *v1, EditVert *v2)
+{
+ EditEdge *newed;
+
+ newed= new_mem_element(sizeof(EditEdge));
+ BLI_addtail(&filledgebase, newed);
+
+ newed->v1= v1;
+ newed->v2= v2;
+
+ return newed;
+}
+
+static void addfillface(EditVert *v1, EditVert *v2, EditVert *v3, int mat_nr)
+{
+ /* does not make edges */
+ EditFace *evl;
+
+ evl= new_mem_element(sizeof(EditFace));
+ BLI_addtail(&fillfacebase, evl);
+
+ evl->v1= v1;
+ evl->v2= v2;
+ evl->v3= v3;
+ evl->f= 2;
+ evl->mat_nr= mat_nr;
+}
+
+static int boundisect(PolyFill *pf2, PolyFill *pf1)
+{
+ /* has pf2 been touched (intersected) by pf1 ? with bounding box */
+ /* test first if polys exist */
+
+ if(pf1->edges==0 || pf2->edges==0) return 0;
+
+ if(pf2->max[cox] < pf1->min[cox] ) return 0;
+ if(pf2->max[coy] < pf1->min[coy] ) return 0;
+
+ if(pf2->min[cox] > pf1->max[cox] ) return 0;
+ if(pf2->min[coy] > pf1->max[coy] ) return 0;
+
+ /* join */
+ if(pf2->max[cox]<pf1->max[cox]) pf2->max[cox]= pf1->max[cox];
+ if(pf2->max[coy]<pf1->max[coy]) pf2->max[coy]= pf1->max[coy];
+
+ if(pf2->min[cox]>pf1->min[cox]) pf2->min[cox]= pf1->min[cox];
+ if(pf2->min[coy]>pf1->min[coy]) pf2->min[coy]= pf1->min[coy];
+
+ return 1;
+}
+
+
+static void mergepolysSimp(PolyFill *pf1, PolyFill *pf2) /* add pf2 to pf1 */
+{
+ EditVert *eve;
+ EditEdge *eed;
+
+ /* replace old poly numbers */
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->xs== pf2->nr) eve->xs= pf1->nr;
+ eve= eve->next;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->f1== pf2->nr) eed->f1= pf1->nr;
+ eed= eed->next;
+ }
+
+ pf1->verts+= pf2->verts;
+ pf1->edges+= pf2->edges;
+ pf2->verts= pf2->edges= 0;
+ pf1->f= (pf1->f | pf2->f);
+}
+
+static short testedgeside(float *v1, float *v2, float *v3)
+/* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */
+{
+ float inp;
+
+ inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy])
+ +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]);
+
+ if(inp<0.0) return 0;
+ else if(inp==0) {
+ if(v1[cox]==v3[cox] && v1[coy]==v3[coy]) return 0;
+ if(v2[cox]==v3[cox] && v2[coy]==v3[coy]) return 0;
+ }
+ return 1;
+}
+
+static short addedgetoscanvert(ScFillVert *sc, EditEdge *eed)
+{
+ /* find first edge to the right of eed, and insert eed before that */
+ EditEdge *ed;
+ float fac,fac1,x,y;
+
+ if(sc->first==0) {
+ sc->first= sc->last= eed;
+ eed->prev= eed->next=0;
+ return 1;
+ }
+
+ x= eed->v1->co[cox];
+ y= eed->v1->co[coy];
+
+ fac1= eed->v2->co[coy]-y;
+ if(fac1==0.0) {
+ fac1= 1.0e10*(eed->v2->co[cox]-x);
+
+ }
+ else fac1= (x-eed->v2->co[cox])/fac1;
+
+ ed= sc->first;
+ while(ed) {
+
+ if(ed->v2==eed->v2) return 0;
+
+ fac= ed->v2->co[coy]-y;
+ if(fac==0.0) {
+ fac= 1.0e10*(ed->v2->co[cox]-x);
+
+ }
+ else fac= (x-ed->v2->co[cox])/fac;
+ if(fac>fac1) break;
+
+ ed= ed->next;
+ }
+ if(ed) BLI_insertlinkbefore((ListBase *)&(sc->first), ed, eed);
+ else BLI_addtail((ListBase *)&(sc->first),eed);
+
+ return 1;
+}
+
+
+static ScFillVert *addedgetoscanlist(EditEdge *eed, int len)
+{
+ /* inserts edge at correct location in ScFillVert list */
+ /* returns sc when edge already exists */
+ ScFillVert *sc,scsearch;
+ EditVert *eve;
+
+ /* which vert is left-top? */
+ if(eed->v1->co[coy] == eed->v2->co[coy]) {
+ if(eed->v1->co[cox] > eed->v2->co[cox]) {
+ eve= eed->v1;
+ eed->v1= eed->v2;
+ eed->v2= eve;
+ }
+ }
+ else if(eed->v1->co[coy] < eed->v2->co[coy]) {
+ eve= eed->v1;
+ eed->v1= eed->v2;
+ eed->v2= eve;
+ }
+ /* find location in list */
+ scsearch.v1= eed->v1;
+ sc= (ScFillVert *)bsearch(&scsearch,scdata,len,
+ sizeof(ScFillVert), vergscdata);
+
+ if(sc==0) printf("Error in search edge: %p\n",eed);
+ else if(addedgetoscanvert(sc,eed)==0) return sc;
+
+ return 0;
+}
+
+static short boundinsideEV(EditEdge *eed, EditVert *eve)
+/* is eve inside boundbox eed */
+{
+ float minx,maxx,miny,maxy;
+
+ if(eed->v1->co[cox]<eed->v2->co[cox]) {
+ minx= eed->v1->co[cox];
+ maxx= eed->v2->co[cox];
+ } else {
+ minx= eed->v2->co[cox];
+ maxx= eed->v1->co[cox];
+ }
+ if(eve->co[cox]>=minx && eve->co[cox]<=maxx) {
+ if(eed->v1->co[coy]<eed->v2->co[coy]) {
+ miny= eed->v1->co[coy];
+ maxy= eed->v2->co[coy];
+ } else {
+ miny= eed->v2->co[coy];
+ maxy= eed->v1->co[coy];
+ }
+ if(eve->co[coy]>=miny && eve->co[coy]<=maxy) return 1;
+ }
+ return 0;
+}
+
+
+static void testvertexnearedge(void)
+{
+ /* only vertices with ->h==1 are being tested for
+ being close to an edge, if true insert */
+
+ EditVert *eve;
+ EditEdge *eed,*ed1;
+ float dist,vec1[2],vec2[2],vec3[2];
+
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->h==1) {
+ vec3[0]= eve->co[cox];
+ vec3[1]= eve->co[coy];
+ /* find the edge which has vertex eve */
+ ed1= filledgebase.first;
+ while(ed1) {
+ if(ed1->v1==eve || ed1->v2==eve) break;
+ ed1= ed1->next;
+ }
+ if(ed1->v1==eve) {
+ ed1->v1= ed1->v2;
+ ed1->v2= eve;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ if(eve!=eed->v1 && eve!=eed->v2 && eve->xs==eed->f1) {
+ if(FloatCompare(eve->co,eed->v1->co, COMPLIMIT)) {
+ ed1->v2= eed->v1;
+ eed->v1->h++;
+ eve->h= 0;
+ break;
+ }
+ else if(FloatCompare(eve->co,eed->v2->co, COMPLIMIT)) {
+ ed1->v2= eed->v2;
+ eed->v2->h++;
+ eve->h= 0;
+ break;
+ }
+ else {
+ vec1[0]= eed->v1->co[cox];
+ vec1[1]= eed->v1->co[coy];
+ vec2[0]= eed->v2->co[cox];
+ vec2[1]= eed->v2->co[coy];
+ if(boundinsideEV(eed,eve)) {
+ dist= DistVL2Dfl(vec1,vec2,vec3);
+ if(dist<COMPLIMIT) {
+ /* new edge */
+ ed1= BLI_addfilledge(eed->v1, eve);
+
+ /* printf("fill: vertex near edge %x\n",eve); */
+ ed1->f= ed1->h= 0;
+ ed1->f1= eed->f1;
+ eed->v1= eve;
+ eve->h= 3;
+ break;
+ }
+ }
+ }
+ }
+ eed= eed->next;
+ }
+ }
+ eve= eve->next;
+ }
+}
+
+static void splitlist(ListBase *tempve, ListBase *temped, short nr)
+{
+ /* everything is in templist, write only poly nr to fillist */
+ EditVert *eve,*nextve;
+ EditEdge *eed,*nexted;
+
+ addlisttolist(tempve,&fillvertbase);
+ addlisttolist(temped,&filledgebase);
+
+ eve= tempve->first;
+ while(eve) {
+ nextve= eve->next;
+ if(eve->xs==nr) {
+ BLI_remlink(tempve,eve);
+ BLI_addtail(&fillvertbase,eve);
+ }
+ eve= nextve;
+ }
+ eed= temped->first;
+ while(eed) {
+ nexted= eed->next;
+ if(eed->f1==nr) {
+ BLI_remlink(temped,eed);
+ BLI_addtail(&filledgebase,eed);
+ }
+ eed= nexted;
+ }
+}
+
+
+static void scanfill(PolyFill *pf, int mat_nr)
+{
+ ScFillVert *sc = NULL, *sc1;
+ EditVert *eve,*v1,*v2,*v3;
+ EditEdge *eed,*nexted,*ed1,*ed2,*ed3;
+ float miny = 0.0;
+ int a,b,verts, maxface, totface;
+ short nr, test, twoconnected=0;
+
+ nr= pf->nr;
+ verts= pf->verts;
+
+ /* PRINTS
+ eve= fillvertbase.first;
+ while(eve) {
+ printf("vert: %x co: %f %f\n",eve,eve->co[cox],eve->co[coy]);
+ eve= eve->next;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ printf("edge: %x verts: %x %x\n",eed,eed->v1,eed->v2);
+ eed= eed->next;
+ } */
+
+ /* STEP 0: remove zero sized edges */
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->v1->co[cox]==eed->v2->co[cox]) {
+ if(eed->v1->co[coy]==eed->v2->co[coy]) {
+ if(eed->v1->f==255 && eed->v2->f!=255) {
+ eed->v2->f= 255;
+ eed->v2->tmp.v= eed->v1->tmp.v;
+ }
+ else if(eed->v2->f==255 && eed->v1->f!=255) {
+ eed->v1->f= 255;
+ eed->v1->tmp.v= eed->v2->tmp.v;
+ }
+ else if(eed->v2->f==255 && eed->v1->f==255) {
+ eed->v1->tmp.v= eed->v2->tmp.v;
+ }
+ else {
+ eed->v2->f= 255;
+ eed->v2->tmp.v = eed->v1->tmp.v;
+ }
+ }
+ }
+ eed= eed->next;
+ }
+
+ /* STEP 1: make using FillVert and FillEdge lists a sorted
+ ScFillVert list
+ */
+ sc= scdata= (ScFillVert *)MEM_callocN(pf->verts*sizeof(ScFillVert),"Scanfill1");
+ eve= fillvertbase.first;
+ verts= 0;
+ while(eve) {
+ if(eve->xs==nr) {
+ if(eve->f!= 255) {
+ verts++;
+ eve->f= 0; /* flag for connectedges later on */
+ sc->v1= eve;
+ sc++;
+ }
+ }
+ eve= eve->next;
+ }
+
+ qsort(scdata, verts, sizeof(ScFillVert), vergscdata);
+
+ sc= scdata;
+ eed= filledgebase.first;
+ while(eed) {
+ nexted= eed->next;
+ eed->f= 0;
+ BLI_remlink(&filledgebase,eed);
+/* commented all of this out, this I have no idea for what it is for, probably from ancient past */
+/* it does crash blender, since it uses mixed original and new vertices (ton) */
+// if(eed->v1->f==255) {
+// v1= eed->v1;
+// while((eed->v1->f == 255) && (eed->v1->tmp.v != v1))
+// eed->v1 = eed->v1->tmp.v;
+// }
+// if(eed->v2->f==255) {
+// v2= eed->v2;
+// while((eed->v2->f == 255) && (eed->v2->tmp.v != v2))
+// eed->v2 = eed->v2->tmp.v;
+// }
+ if(eed->v1!=eed->v2) addedgetoscanlist(eed,verts);
+
+ eed= nexted;
+ }
+ /*
+ sc= scdata;
+ for(a=0;a<verts;a++) {
+ printf("\nscvert: %x\n",sc->v1);
+ eed= sc->first;
+ while(eed) {
+ printf(" ed %x %x %x\n",eed,eed->v1,eed->v2);
+ eed= eed->next;
+ }
+ sc++;
+ }*/
+
+
+ /* STEP 2: FILL LOOP */
+
+ if(pf->f==0) twoconnected= 1;
+
+ /* (temporal) security: never much more faces than vertices */
+ totface= 0;
+ maxface= 2*verts; /* 2*verts: based at a filled circle within a triangle */
+
+ sc= scdata;
+ for(a=0;a<verts;a++) {
+ /* printf("VERTEX %d %x\n",a,sc->v1); */
+ ed1= sc->first;
+ while(ed1) { /* set connectflags */
+ nexted= ed1->next;
+ if(ed1->v1->h==1 || ed1->v2->h==1) {
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ if(ed1->v1->h>1) ed1->v1->h--;
+ if(ed1->v2->h>1) ed1->v2->h--;
+ }
+ else ed1->v2->f= 1;
+
+ ed1= nexted;
+ }
+ while(sc->first) { /* for as long there are edges */
+ ed1= sc->first;
+ ed2= ed1->next;
+
+ /* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */
+ /* if(callLocalInterruptCallBack()) break; */
+ if(totface>maxface) {
+ /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */
+ a= verts;
+ break;
+ }
+ if(ed2==0) {
+ sc->first=sc->last= 0;
+ /* printf("just 1 edge to vert\n"); */
+ BLI_addtail(&filledgebase,ed1);
+ ed1->v2->f= 0;
+ ed1->v1->h--;
+ ed1->v2->h--;
+ } else {
+ /* test rest of vertices */
+ v1= ed1->v2;
+ v2= ed1->v1;
+ v3= ed2->v2;
+ /* this happens with a serial of overlapping edges */
+ if(v1==v2 || v2==v3) break;
+ /* printf("test verts %x %x %x\n",v1,v2,v3); */
+ miny = ( (v1->co[coy])<(v3->co[coy]) ? (v1->co[coy]) : (v3->co[coy]) );
+ /* miny= MIN2(v1->co[coy],v3->co[coy]); */
+ sc1= sc+1;
+ test= 0;
+
+ for(b=a+1;b<verts;b++) {
+ if(sc1->v1->f==0) {
+ if(sc1->v1->co[coy] <= miny) break;
+
+ if(testedgeside(v1->co,v2->co,sc1->v1->co))
+ if(testedgeside(v2->co,v3->co,sc1->v1->co))
+ if(testedgeside(v3->co,v1->co,sc1->v1->co)) {
+ /* point in triangle */
+
+ test= 1;
+ break;
+ }
+ }
+ sc1++;
+ }
+ if(test) {
+ /* make new edge, and start over */
+ /* printf("add new edge %x %x and start again\n",v2,sc1->v1); */
+
+ ed3= BLI_addfilledge(v2, sc1->v1);
+ BLI_remlink(&filledgebase, ed3);
+ BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3);
+ ed3->v2->f= 1;
+ ed3->f= 2;
+ ed3->v1->h++;
+ ed3->v2->h++;
+ }
+ else {
+ /* new triangle */
+ /* printf("add face %x %x %x\n",v1,v2,v3); */
+ addfillface(v1, v2, v3, mat_nr);
+ totface++;
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ ed1->v2->f= 0;
+ ed1->v1->h--;
+ ed1->v2->h--;
+ /* ed2 can be removed when it's an old one */
+ if(ed2->f==0 && twoconnected) {
+ BLI_remlink((ListBase *)&(sc->first),ed2);
+ BLI_addtail(&filledgebase,ed2);
+ ed2->v2->f= 0;
+ ed2->v1->h--;
+ ed2->v2->h--;
+ }
+
+ /* new edge */
+ ed3= BLI_addfilledge(v1, v3);
+ BLI_remlink(&filledgebase, ed3);
+ ed3->f= 2;
+ ed3->v1->h++;
+ ed3->v2->h++;
+
+ /* printf("add new edge %x %x\n",v1,v3); */
+ sc1= addedgetoscanlist(ed3, verts);
+
+ if(sc1) { /* ed3 already exists: remove */
+ /* printf("Edge exists\n"); */
+ ed3->v1->h--;
+ ed3->v2->h--;
+
+ if(twoconnected) ed3= sc1->first;
+ else ed3= 0;
+ while(ed3) {
+ if( (ed3->v1==v1 && ed3->v2==v3) || (ed3->v1==v3 && ed3->v2==v1) ) {
+ BLI_remlink((ListBase *)&(sc1->first),ed3);
+ BLI_addtail(&filledgebase,ed3);
+ ed3->v1->h--;
+ ed3->v2->h--;
+ break;
+ }
+ ed3= ed3->next;
+ }
+ }
+
+ }
+ }
+ /* test for loose edges */
+ ed1= sc->first;
+ while(ed1) {
+ nexted= ed1->next;
+ if(ed1->v1->h<2 || ed1->v2->h<2) {
+ BLI_remlink((ListBase *)&(sc->first),ed1);
+ BLI_addtail(&filledgebase,ed1);
+ if(ed1->v1->h>1) ed1->v1->h--;
+ if(ed1->v2->h>1) ed1->v2->h--;
+ }
+
+ ed1= nexted;
+ }
+ }
+ sc++;
+ }
+
+ MEM_freeN(scdata);
+}
+
+
+
+int BLI_edgefill(int mode, int mat_nr)
+{
+ /*
+ - fill works with its own lists, so create that first (no faces!)
+ - for vertices, put in ->tmp.v the old pointer
+ - struct elements xs en ys are not used here: don't hide stuff in it
+ - edge flag ->f becomes 2 when it's a new edge
+ - mode: & 1 is check for crossings, then create edges (TO DO )
+ */
+ ListBase tempve, temped;
+ EditVert *eve;
+ EditEdge *eed,*nexted;
+ PolyFill *pflist,*pf;
+ float *minp, *maxp, *v1, *v2, norm[3], len;
+ short a,c,poly=0,ok=0,toggle=0;
+
+ /* reset variables */
+ eve= fillvertbase.first;
+ while(eve) {
+ eve->f= 0;
+ eve->xs= 0;
+ eve->h= 0;
+ eve= eve->next;
+ }
+
+ /* first test vertices if they are in edges */
+ /* including resetting of flags */
+ eed= filledgebase.first;
+ while(eed) {
+ eed->f= eed->f1= eed->h= 0;
+ eed->v1->f= 1;
+ eed->v2->f= 1;
+
+ eed= eed->next;
+ }
+
+ eve= fillvertbase.first;
+ while(eve) {
+ if(eve->f & 1) {
+ ok=1;
+ break;
+ }
+ eve= eve->next;
+ }
+
+ if(ok==0) return 0;
+
+ /* NEW NEW! define projection: with 'best' normal */
+ /* just use the first three different vertices */
+
+ /* THIS PART STILL IS PRETTY WEAK! (ton) */
+
+ eve= fillvertbase.last;
+ len= 0.0;
+ v1= eve->co;
+ v2= 0;
+ eve= fillvertbase.first;
+ while(eve) {
+ if(v2) {
+ if( FloatCompare(v2, eve->co, COMPLIMIT)==0) {
+ len= CalcNormFloat(v1, v2, eve->co, norm);
+ if(len != 0.0) break;
+ }
+ }
+ else if(FloatCompare(v1, eve->co, COMPLIMIT)==0) {
+ v2= eve->co;
+ }
+ eve= eve->next;
+ }
+
+ if(len==0.0) return 0; /* no fill possible */
+
+ norm[0]= fabs(norm[0]);
+ norm[1]= fabs(norm[1]);
+ norm[2]= fabs(norm[2]);
+
+ if(norm[2]>=norm[0] && norm[2]>=norm[1]) {
+ cox= 0; coy= 1;
+ }
+ else if(norm[1]>=norm[0] && norm[1]>=norm[2]) {
+ cox= 0; coy= 2;
+ }
+ else {
+ cox= 1; coy= 2;
+ }
+
+ /* STEP 1: COUNT POLYS */
+ eve= fillvertbase.first;
+ while(eve) {
+ /* get first vertex with no poly number */
+ if(eve->xs==0) {
+ poly++;
+ /* now a sortof select connected */
+ ok= 1;
+ eve->xs= poly;
+
+ while(ok) {
+
+ ok= 0;
+ toggle++;
+ if(toggle & 1) eed= filledgebase.first;
+ else eed= filledgebase.last;
+
+ while(eed) {
+ if(eed->v1->xs==0 && eed->v2->xs==poly) {
+ eed->v1->xs= poly;
+ eed->f1= poly;
+ ok= 1;
+ }
+ else if(eed->v2->xs==0 && eed->v1->xs==poly) {
+ eed->v2->xs= poly;
+ eed->f1= poly;
+ ok= 1;
+ }
+ else if(eed->f1==0) {
+ if(eed->v1->xs==poly && eed->v2->xs==poly) {
+ eed->f1= poly;
+ ok= 1;
+ }
+ }
+ if(toggle & 1) eed= eed->next;
+ else eed= eed->prev;
+ }
+ }
+ }
+ eve= eve->next;
+ }
+ /* printf("amount of poly's: %d\n",poly); */
+
+ /* STEP 2: remove loose edges and strings of edges */
+ eed= filledgebase.first;
+ while(eed) {
+ if(eed->v1->h++ >250) break;
+ if(eed->v2->h++ >250) break;
+ eed= eed->next;
+ }
+ if(eed) {
+ /* otherwise it's impossible to be sure you can clear vertices */
+ callLocalErrorCallBack("No vertices with 250 edges allowed!");
+ return 0;
+ }
+
+ /* does it only for vertices with ->h==1 */
+ testvertexnearedge();
+
+ ok= 1;
+ while(ok) {
+ ok= 0;
+ toggle++;
+ if(toggle & 1) eed= filledgebase.first;
+ else eed= filledgebase.last;
+ while(eed) {
+ if(toggle & 1) nexted= eed->next;
+ else nexted= eed->prev;
+ if(eed->v1->h==1) {
+ eed->v2->h--;
+ BLI_remlink(&fillvertbase,eed->v1);
+ BLI_remlink(&filledgebase,eed);
+ ok= 1;
+ }
+ else if(eed->v2->h==1) {
+ eed->v1->h--;
+ BLI_remlink(&fillvertbase,eed->v2);
+ BLI_remlink(&filledgebase,eed);
+ ok= 1;
+ }
+ eed= nexted;
+ }
+ }
+ if(filledgebase.first==0) {
+ /* printf("All edges removed\n"); */
+ return 0;
+ }
+
+
+ /* CURRENT STATUS:
+ - eve->f :1= availalble in edges
+ - eve->xs :polynumber
+ - eve->h :amount of edges connected to vertex
+ - eve->tmp.v :store! original vertex number
+
+ - eed->f :
+ - eed->f1 :poly number
+ */
+
+
+ /* STEP 3: MAKE POLYFILL STRUCT */
+ pflist= (PolyFill *)MEM_callocN(poly*sizeof(PolyFill),"edgefill");
+ pf= pflist;
+ for(a=1;a<=poly;a++) {
+ pf->nr= a;
+ pf->min[0]=pf->min[1]=pf->min[2]= 1.0e20;
+ pf->max[0]=pf->max[1]=pf->max[2]= -1.0e20;
+ pf++;
+ }
+ eed= filledgebase.first;
+ while(eed) {
+ pflist[eed->f1-1].edges++;
+ eed= eed->next;
+ }
+
+ eve= fillvertbase.first;
+ while(eve) {
+ pflist[eve->xs-1].verts++;
+ minp= pflist[eve->xs-1].min;
+ maxp= pflist[eve->xs-1].max;
+
+ minp[cox]= (minp[cox])<(eve->co[cox]) ? (minp[cox]) : (eve->co[cox]);
+ minp[coy]= (minp[coy])<(eve->co[coy]) ? (minp[coy]) : (eve->co[coy]);
+ maxp[cox]= (maxp[cox])>(eve->co[cox]) ? (maxp[cox]) : (eve->co[cox]);
+ maxp[coy]= (maxp[coy])>(eve->co[coy]) ? (maxp[coy]) : (eve->co[coy]);
+ if(eve->h>2) pflist[eve->xs-1].f= 1;
+
+ eve= eve->next;
+ }
+
+ /* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM
+ * ( bounds just to divide it in pieces for optimization,
+ * the edgefill itself has good auto-hole detection)
+ * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */
+
+ if(poly>1) {
+ short *polycache, *pc;
+
+ /* so, sort first */
+ qsort(pflist, poly, sizeof(PolyFill), vergpoly);
+
+ /*pf= pflist;
+ for(a=1;a<=poly;a++) {
+ printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
+ PRINT2(f, f, pf->min[0], pf->min[1]);
+ pf++;
+ }*/
+
+ polycache= pc= MEM_callocN(sizeof(short)*poly, "polycache");
+ pf= pflist;
+ for(a=0; a<poly; a++, pf++) {
+ for(c=a+1;c<poly;c++) {
+
+ /* if 'a' inside 'c': join (bbox too)
+ * Careful: 'a' can also be inside another poly.
+ */
+ if(boundisect(pf, pflist+c)) {
+ *pc= c;
+ pc++;
+ }
+ /* only for optimize! */
+ /* else if(pf->max[cox] < (pflist+c)->min[cox]) break; */
+
+ }
+ while(pc!=polycache) {
+ pc--;
+ mergepolysSimp(pf, pflist+ *pc);
+ }
+ }
+ MEM_freeN(polycache);
+ }
+
+ pf= pflist;
+ /* printf("after merge\n");
+ for(a=1;a<=poly;a++) {
+ printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
+ pf++;
+ } */
+
+ /* STEP 5: MAKE TRIANGLES */
+
+ tempve.first= fillvertbase.first;
+ tempve.last= fillvertbase.last;
+ temped.first= filledgebase.first;
+ temped.last= filledgebase.last;
+ fillvertbase.first=fillvertbase.last= 0;
+ filledgebase.first=filledgebase.last= 0;
+
+ pf= pflist;
+ for(a=0;a<poly;a++) {
+ if(pf->edges>1) {
+ splitlist(&tempve,&temped,pf->nr);
+ scanfill(pf, mat_nr);
+ }
+ pf++;
+ }
+ addlisttolist(&fillvertbase,&tempve);
+ addlisttolist(&filledgebase,&temped);
+
+ /* FREE */
+
+ MEM_freeN(pflist);
+ return 1;
+
+}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
new file mode 100644
index 00000000000..1d46679cbf2
--- /dev/null
+++ b/source/blender/blenlib/intern/storage.c
@@ -0,0 +1,540 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Reorganised mar-01 nzc
+ * Some really low-level file thingies.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#include <sys/types.h>
+#include <io.h>
+#include <direct.h>
+#endif
+
+#ifndef WIN32
+#include <dirent.h>
+#endif
+
+#include <time.h>
+#include <sys/stat.h>
+
+#if !defined(linux) && (defined(__sgi) || defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__))
+#include <sys/statfs.h>
+#endif
+
+#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+
+#if defined(linux) || defined(__CYGWIN32__) || defined(__hpux)
+#include <sys/vfs.h>
+#endif
+
+#ifdef __BeOS
+struct statfs {
+ int f_bsize;
+ int f_bfree;
+};
+#endif
+
+#ifdef __APPLE__
+/* For statfs */
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif /* __APPLE__ */
+
+
+#include <fcntl.h>
+#if !defined(__BeOS) && !defined(WIN32)
+#include <sys/mtio.h> /* tape comando's */
+#endif
+#include <string.h> /* strcpy etc.. */
+
+#ifndef WIN32
+#include <sys/ioctl.h>
+#include <unistd.h> /* */
+#include <pwd.h>
+#endif
+
+#if !defined(__FreeBSD__) && !defined(__APPLE__)
+#include <malloc.h>
+#endif
+
+/* lib includes */
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "BLI_blenlib.h"
+#include "BLI_storage.h"
+#include "BLI_storage_types.h"
+
+#include "BLI_util.h"
+#include "BLI_linklist.h"
+
+#include "BKE_utildefines.h"
+
+/* vars: */
+static int totnum,actnum;
+static struct direntry *files;
+
+static struct ListBase dirbase_={
+ 0,0};
+static struct ListBase *dirbase = &dirbase_;
+
+
+char *BLI_getwdN(char *dir)
+{
+ char *pwd;
+
+ if (dir) {
+ pwd = getenv("PWD");
+ if (pwd){
+ strcpy(dir, pwd);
+ return(dir);
+ }
+ /* 160 is FILE_MAXDIR in filesel.c */
+ return( getcwd(dir, 160) );
+ }
+ return(0);
+}
+
+
+int BLI_compare(struct direntry *entry1, struct direntry *entry2)
+{
+ /* type is equal to stat.st_mode */
+
+ if (S_ISDIR(entry1->type)){
+ if (S_ISDIR(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISDIR(entry2->type)) return (1);
+ }
+ if (S_ISREG(entry1->type)){
+ if (S_ISREG(entry2->type)==0) return (-1);
+ } else{
+ if (S_ISREG(entry2->type)) return (1);
+ }
+ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+ if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+ /* make sure "." and ".." are always first */
+ if( strcmp(entry1->relname, ".")==0 ) return (-1);
+ if( strcmp(entry2->relname, ".")==0 ) return (1);
+ if( strcmp(entry1->relname, "..")==0 ) return (-1);
+
+ return (BLI_strcasecmp(entry1->relname,entry2->relname));
+}
+
+
+double BLI_diskfree(char *dir)
+{
+#ifdef WIN32
+ DWORD sectorspc, bytesps, freec, clusters;
+ char tmp[4];
+
+ tmp[0]='\\'; tmp[1]=0; /* Just a failsafe */
+ if (dir[0]=='/' || dir[0]=='\\') {
+ tmp[0]='\\';
+ tmp[1]=0;
+ } else if (dir[1]==':') {
+ tmp[0]=dir[0];
+ tmp[1]=':';
+ tmp[2]='\\';
+ tmp[3]=0;
+ }
+
+ GetDiskFreeSpace(tmp,&sectorspc, &bytesps, &freec, &clusters);
+
+ return (double) (freec*bytesps*sectorspc);
+#else
+ struct statfs disk;
+ char name[FILE_MAXDIR],*slash;
+ int len = strlen(dir);
+
+ if (len >= FILE_MAXDIR) /* path too long */
+ return -1;
+
+ strcpy(name,dir);
+
+ if(len){
+ slash = strrchr(name,'/');
+ if (slash) slash[1] = 0;
+ } else strcpy(name,"/");
+
+#if defined (__FreeBSD__) || defined (linux) || defined (__OpenBSD__) || defined (__APPLE__)
+ if (statfs(name, &disk)) return(-1);
+#endif
+#ifdef __BeOS
+ return -1;
+#endif
+#if !defined(linux) && (defined (__sgi) || defined (__sun__) || defined (__sun) || defined(__sparc) || defined(__sparc__))
+
+ if (statfs(name, &disk, sizeof(struct statfs), 0)){
+ /* printf("diskfree: Couldn't get information about %s.\n",dir); */
+ return(-1);
+ }
+#endif
+
+ return ( ((double) disk.f_bsize) * ((double) disk.f_bfree));
+#endif
+}
+
+static int hide_dot= 0;
+
+void BLI_hide_dot_files(int set)
+{
+ if(set) hide_dot= 1;
+ else hide_dot= 0;
+}
+
+void BLI_builddir(char *dirname, char *relname)
+{
+ struct dirent *fname;
+ struct dirlink *dlink;
+ int rellen, newnum = 0, seen_ = 0, seen__ = 0;
+ char buf[256];
+ DIR *dir;
+
+ strcpy(buf,relname);
+ rellen=strlen(relname);
+
+ if (rellen){
+ buf[rellen]='/';
+ rellen++;
+ }
+
+ if (chdir(dirname) == -1){
+ perror(dirname);
+ return;
+ }
+
+ if ( (dir = (DIR *)opendir(".")) ){
+ while ((fname = (struct dirent*) readdir(dir)) != NULL) {
+
+ if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0);
+ else {
+
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ if (dlink){
+ strcpy(buf+rellen,fname->d_name);
+
+ dlink->name = BLI_strdup(buf);
+
+ if (dlink->name[0] == '.') {
+ if (dlink->name[1] == 0) seen_ = 1;
+ else if (dlink->name[1] == '.') {
+ if (dlink->name[2] == 0) seen__ = 1;
+ }
+ }
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+ }
+ }
+
+ if (newnum){
+#ifndef WIN32
+ if (seen_ == 0) { /* Cachefs PATCH */
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ strcpy(buf+rellen,"./.");
+ dlink->name = BLI_strdup(buf);
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+ if (seen__ == 0) { /* MAC PATCH */
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ strcpy(buf+rellen,"./..");
+ dlink->name = BLI_strdup(buf);
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+#else // WIN32
+ if (seen_ == 0) { /* should only happen for root paths like "C:\" */
+ dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
+ strcpy(buf+rellen,".");
+ dlink->name = BLI_strdup(buf);
+ BLI_addhead(dirbase,dlink);
+ newnum++;
+ }
+#endif
+
+ if (files) files=(struct direntry *)realloc(files,(totnum+newnum) * sizeof(struct direntry));
+ else files=(struct direntry *)malloc(newnum * sizeof(struct direntry));
+
+ if (files){
+ dlink = (struct dirlink *) dirbase->first;
+ while(dlink){
+ memset(&files[actnum], 0 , sizeof(struct direntry));
+ files[actnum].relname = dlink->name;
+ stat(dlink->name,&files[actnum].s);
+ files[actnum].type=files[actnum].s.st_mode;
+ files[actnum].flags = 0;
+ totnum++;
+ actnum++;
+ dlink = dlink->next;
+ }
+ } else{
+ printf("Couldn't get memory for dir\n");
+ exit(1);
+ }
+
+ BLI_freelist(dirbase);
+ if (files) qsort(files, actnum, sizeof(struct direntry), (int (*)(const void *,const void*))BLI_compare);
+ } else {
+ printf("%s empty directory\n",dirname);
+ }
+
+ closedir(dir);
+ } else {
+ printf("%s non-existant directory\n",dirname);
+ }
+}
+
+void BLI_adddirstrings()
+{
+ char datum[100];
+ char buf[250];
+ char size[250];
+ static char * types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+ int num, mode;
+ int num1, num2, num3, num4;
+#ifdef WIN32
+ __int64 st_size;
+#else
+ long long st_size;
+#endif
+
+ struct direntry * file;
+ struct tm *tm;
+ time_t zero= 0;
+
+ file = &files[0];
+
+ for(num=0;num<actnum;num++){
+#ifdef WIN32
+ mode = 0;
+ strcpy(file->mode1, types[0]);
+ strcpy(file->mode2, types[0]);
+ strcpy(file->mode3, types[0]);
+#else
+ mode = file->s.st_mode;
+
+ strcpy(file->mode1, types[(mode & 0700) >> 6]);
+ strcpy(file->mode2, types[(mode & 0070) >> 3]);
+ strcpy(file->mode3, types[(mode & 0007)]);
+
+ if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2]=='-'))file->mode2[2]='l';
+
+ if (mode & (S_ISUID | S_ISGID)){
+ if (file->mode1[2]=='x') file->mode1[2]='s';
+ else file->mode1[2]='S';
+
+ if (file->mode2[2]=='x')file->mode2[2]='s';
+ }
+
+ if (mode & S_ISVTX){
+ if (file->mode3[2] == 'x') file->mode3[2] = 't';
+ else file->mode3[2] = 'T';
+ }
+#endif
+
+#ifdef WIN32
+ strcpy(files[num].owner,"user");
+#else
+ {
+ struct passwd *pwuser;
+ pwuser = getpwuid(files[num].s.st_uid);
+ if ( pwuser ) {
+ strcpy(files[num].owner, pwuser->pw_name);
+ } else {
+ sprintf(files[num].owner, "%d", files[num].s.st_uid);
+ }
+ }
+#endif
+
+ tm= localtime(&files[num].s.st_mtime);
+ // prevent impossible dates in windows
+ if(tm==NULL) tm= localtime(&zero);
+ strftime(files[num].time, 8, "%H:%M", tm);
+ strftime(files[num].date, 16, "%d-%b-%y", tm);
+
+ /*
+ * Seems st_size is signed 32-bit value in *nix and Windows. This
+ * will buy us some time until files get bigger than 4GB or until
+ * everyone starts using __USE_FILE_OFFSET64 or equivalent.
+ */
+ st_size= (unsigned int)files[num].s.st_size;
+
+ num1= st_size % 1000;
+ num2= st_size/1000;
+ num2= num2 % 1000;
+ num3= st_size/(1000*1000);
+ num3= num3 % 1000;
+ num4= st_size/(1000*1000*1000);
+ num4= num4 % 1000;
+
+ if(num4) sprintf(files[num].size, "%3d %03d %03d %03d", num4, num3, num2, num1);
+ else if(num3) sprintf(files[num].size, "%7d %03d %03d", num3, num2, num1);
+ else if(num2) sprintf(files[num].size, "%11d %03d", num2, num1);
+ else if(num1) sprintf(files[num].size, "%15d", num1);
+ else sprintf(files[num].size, "0");
+
+ strftime(datum, 32, "%d-%b-%y %H:%M", tm);
+
+ if (st_size < 1000) {
+ sprintf(size, "%10d", (int) st_size);
+ } else if (st_size < 1000 * 1000) {
+ sprintf(size, "%6d %03d", (int) (st_size / 1000), (int) (st_size % 1000));
+ } else if (st_size < 100 * 1000 * 1000) {
+ sprintf(size, "%2d %03d %03d", (int) (st_size / (1000 * 1000)), (int) ((st_size / 1000) % 1000), (int) ( st_size % 1000));
+ } else {
+ sprintf(size, "> %4.1f M", (double) (st_size / (1024.0 * 1024.0)));
+ sprintf(size, "%10d", (int) st_size);
+ }
+
+ sprintf(buf,"%s %s %10s %s", files[num].date, files[num].time, size,
+ files[num].relname);
+
+ sprintf(buf,"%s %s %s %7s %s %s %10s %s", file->mode1, file->mode2, file->mode3, files[num].owner, files[num].date, files[num].time, size,
+ files[num].relname);
+
+ files[num].string=MEM_mallocN(strlen(buf)+1, "filestring");
+ if (files[num].string){
+ strcpy(files[num].string,buf);
+ }
+
+ file++;
+ }
+}
+
+unsigned int BLI_getdir(char *dirname, struct direntry **filelist)
+{
+ // reset global variables
+ // memory stored in files is free()'d in
+ // filesel.c:freefilelist()
+
+ actnum = totnum = 0;
+ files = 0;
+
+ BLI_builddir(dirname,"");
+ BLI_adddirstrings();
+
+ if (files) {
+ *(filelist) = files;
+ } else {
+ // keep blender happy. Blender stores this in a variable
+ // where 0 has special meaning.....
+ *(filelist) = files = malloc(sizeof(struct direntry));
+ }
+
+ return(actnum);
+}
+
+
+int BLI_filesize(int file)
+{
+ struct stat buf;
+
+ if (file <= 0) return (-1);
+ fstat(file, &buf);
+ return (buf.st_size);
+}
+
+
+
+int BLI_exist(char *name)
+{
+ struct stat st;
+#ifdef WIN32
+ /* in Windows stat doesn't recognize dir ending on a slash
+ To not break code where the ending slash is expected we
+ don't mess with the argument name directly here - elubie */
+ char tmp[FILE_MAXDIR+FILE_MAXFILE];
+ int len;
+ BLI_strncpy(tmp, name, FILE_MAXDIR+FILE_MAXFILE);
+ len = strlen(tmp);
+ if (len > 3 && ( tmp[len-1]=='\\' || tmp[len-1]=='/') ) tmp[len-1] = '\0';
+ if (stat(tmp,&st)) return(0);
+#else
+ if (stat(name,&st)) return(0);
+#endif
+ return(st.st_mode);
+}
+
+LinkNode *BLI_read_file_as_lines(char *name)
+{
+ FILE *fp= fopen(name, "r");
+ LinkNode *lines= NULL;
+ char *buf;
+ int size;
+
+ if (!fp) return NULL;
+
+ fseek(fp, 0, SEEK_END);
+ size= ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ buf= malloc(size);
+ if (buf) {
+ int i, last= 0;
+
+ /*
+ * size = because on win32 reading
+ * all the bytes in the file will return
+ * less bytes because of crnl changes.
+ */
+ size= fread(buf, 1, size, fp);
+ for (i=0; i<=size; i++) {
+ if (i==size || buf[i]=='\n') {
+ char *line= BLI_strdupn(&buf[last], i-last);
+
+ BLI_linklist_prepend(&lines, line);
+ last= i+1;
+ }
+ }
+
+ free(buf);
+ }
+
+ fclose(fp);
+
+ BLI_linklist_reverse(&lines);
+ return lines;
+}
+
+void BLI_free_file_lines(LinkNode *lines)
+{
+ BLI_linklist_free(lines, (void(*)(void*)) MEM_freeN);
+}
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
new file mode 100644
index 00000000000..cb10185386a
--- /dev/null
+++ b/source/blender/blenlib/intern/threads.c
@@ -0,0 +1,221 @@
+/**
+ *
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+
+
+/* ********** basic thread control API ************
+
+Many thread cases have an X amount of jobs, and only an Y amount of
+threads are useful (typically amount of cpus)
+
+This code can be used to start a maximum amount of 'thread slots', which
+then can be filled in a loop with an idle timer.
+
+A sample loop can look like this (pseudo c);
+
+ ListBase lb;
+ int maxthreads= 2;
+ int cont= 1;
+
+ BLI_init_threads(&lb, do_something_func, maxthreads);
+
+ while(cont) {
+ if(BLI_available_threads(&lb) && !(escape loop event)) {
+ // get new job (data pointer)
+ // tag job 'processed
+ BLI_insert_thread(&lb, job);
+ }
+ else PIL_sleep_ms(50);
+
+ // find if a job is ready, this the do_something_func() should write in job somewhere
+ cont= 0;
+ for(go over all jobs)
+ if(job is ready) {
+ if(job was not removed) {
+ BLI_remove_thread(&lb, job);
+ }
+ }
+ else cont= 1;
+ }
+ // conditions to exit loop
+ if(if escape loop event) {
+ if(BLI_available_threadslots(&lb)==maxthreads)
+ break;
+ }
+ }
+
+ BLI_end_threads(&lb);
+
+ ************************************************ */
+static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER;
+static int thread_levels= 0; /* threads can be invoked inside threads */
+
+/* just a max for security reasons */
+#define RE_MAX_THREAD 8
+
+typedef struct ThreadSlot {
+ struct ThreadSlot *next, *prev;
+ void *(*do_thread)(void *);
+ void *callerdata;
+ pthread_t pthread;
+ int avail;
+} ThreadSlot;
+
+static void BLI_lock_malloc_thread(void)
+{
+ pthread_mutex_lock(&_malloc_lock);
+}
+
+static void BLI_unlock_malloc_thread(void)
+{
+ pthread_mutex_unlock(&_malloc_lock);
+}
+
+void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
+{
+ int a;
+
+ if(threadbase==NULL)
+ return;
+ threadbase->first= threadbase->last= NULL;
+
+ if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD;
+ else if(tot<1) tot= 1;
+
+ for(a=0; a<tot; a++) {
+ ThreadSlot *tslot= MEM_callocN(sizeof(ThreadSlot), "threadslot");
+ BLI_addtail(threadbase, tslot);
+ tslot->do_thread= do_thread;
+ tslot->avail= 1;
+ }
+
+ MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
+ thread_levels++;
+}
+
+/* amount of available threads */
+int BLI_available_threads(ListBase *threadbase)
+{
+ ThreadSlot *tslot;
+ int counter=0;
+
+ for(tslot= threadbase->first; tslot; tslot= tslot->next) {
+ if(tslot->avail)
+ counter++;
+ }
+ return counter;
+}
+
+/* returns thread number, for sample patterns or threadsafe tables */
+int BLI_available_thread_index(ListBase *threadbase)
+{
+ ThreadSlot *tslot;
+ int counter=0;
+
+ for(tslot= threadbase->first; tslot; tslot= tslot->next, counter++) {
+ if(tslot->avail)
+ return counter;
+ }
+ return 0;
+}
+
+
+void BLI_insert_thread(ListBase *threadbase, void *callerdata)
+{
+ ThreadSlot *tslot;
+
+ for(tslot= threadbase->first; tslot; tslot= tslot->next) {
+ if(tslot->avail) {
+ tslot->avail= 0;
+ tslot->callerdata= callerdata;
+ pthread_create(&tslot->pthread, NULL, tslot->do_thread, tslot->callerdata);
+ return;
+ }
+ }
+ printf("ERROR: could not insert thread slot\n");
+}
+
+void BLI_remove_thread(ListBase *threadbase, void *callerdata)
+{
+ ThreadSlot *tslot;
+
+ for(tslot= threadbase->first; tslot; tslot= tslot->next) {
+ if(tslot->callerdata==callerdata) {
+ tslot->callerdata= NULL;
+ pthread_join(tslot->pthread, NULL);
+ tslot->avail= 1;
+ }
+ }
+}
+
+void BLI_end_threads(ListBase *threadbase)
+{
+ ThreadSlot *tslot;
+
+ for(tslot= threadbase->first; tslot; tslot= tslot->next) {
+ if(tslot->avail==0) {
+ pthread_join(tslot->pthread, NULL);
+ }
+ }
+ BLI_freelistN(threadbase);
+
+ thread_levels--;
+ if(thread_levels==0)
+ MEM_set_lock_callback(NULL, NULL);
+}
+
+void BLI_lock_thread(int type)
+{
+ if (type==LOCK_IMAGE)
+ pthread_mutex_lock(&_image_lock);
+ else if (type==LOCK_CUSTOM1)
+ pthread_mutex_lock(&_custom1_lock);
+}
+
+void BLI_unlock_thread(int type)
+{
+ if (type==LOCK_IMAGE)
+ pthread_mutex_unlock(&_image_lock);
+ else if(type==LOCK_CUSTOM1)
+ pthread_mutex_unlock(&_custom1_lock);
+}
+
+/* eof */
diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c
new file mode 100644
index 00000000000..47abca10b36
--- /dev/null
+++ b/source/blender/blenlib/intern/time.c
@@ -0,0 +1,105 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#include "PIL_time.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+
+#include <windows.h>
+
+double PIL_check_seconds_timer(void)
+{
+ static int hasperfcounter= -1; /* -1==unknown */
+ static double perffreq;
+
+ if (hasperfcounter==-1) {
+ __int64 ifreq;
+ hasperfcounter= QueryPerformanceFrequency((LARGE_INTEGER*) &ifreq);
+ perffreq= (double) ifreq;
+ }
+
+ if (hasperfcounter) {
+ __int64 count;
+
+ QueryPerformanceCounter((LARGE_INTEGER*) &count);
+
+ return count/perffreq;
+ } else {
+ static double accum= 0.0;
+ static int ltick= 0;
+ int ntick= GetTickCount();
+
+ if (ntick<ltick) {
+ accum+= (0xFFFFFFFF-ltick+ntick)/1000.0;
+ } else {
+ accum+= (ntick-ltick)/1000.0;
+ }
+
+ ltick= ntick;
+ return accum;
+ }
+}
+
+void PIL_sleep_ms(int ms)
+{
+ Sleep(ms);
+}
+
+#else
+
+#include <unistd.h>
+#include <sys/time.h>
+
+double PIL_check_seconds_timer(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+
+ return ((double) tv.tv_sec + tv.tv_usec/1000000.0);
+}
+
+void PIL_sleep_ms(int ms)
+{
+ if (ms>=1000) {
+ sleep(ms/1000);
+ ms= (ms%1000);
+ }
+
+ usleep(ms*1000);
+}
+
+#endif
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
new file mode 100644
index 00000000000..8e396eec09d
--- /dev/null
+++ b/source/blender/blenlib/intern/util.c
@@ -0,0 +1,1691 @@
+/* util.c
+ *
+ * various string, file, list operations.
+ *
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "DNA_listBase.h"
+#include "BLI_storage.h"
+#include "BLI_storage_types.h"
+#include "BLI_dynamiclist.h"
+
+#include "BLI_util.h"
+#include "BKE_utildefines.h"
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+
+/* for duplicate_defgroup */
+#if !(defined vsnprintf)
+#define vsnprintf _vsnprintf
+#endif
+
+#endif
+
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+#ifdef __APPLE__
+#include <sys/param.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+/* local */
+
+static int add_win32_extension(char *name);
+
+/* implementation */
+
+/* Ripped this from blender.c */
+void addlisttolist(ListBase *list1, ListBase *list2)
+{
+ if (list2->first==0) return;
+
+ if (list1->first==0) {
+ list1->first= list2->first;
+ list1->last= list2->last;
+ }
+ else {
+ ((Link *)list1->last)->next= list2->first;
+ ((Link *)list2->first)->prev= list1->last;
+ list1->last= list2->last;
+ }
+ list2->first= list2->last= 0;
+}
+
+int BLI_stringdec(char *string, char *kop, char *start, unsigned short *numlen)
+{
+ unsigned short len, len2, nums = 0, nume = 0;
+ short i, found = 0;
+
+ len2 = len = strlen(string);
+
+ if (len > 6) {
+ if (BLI_strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6;
+ else if (BLI_strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
+ }
+
+ if (len > 9) {
+ if (BLI_strncasecmp(string + len - 9, ".blend.gz", 9) == 0) len -= 9;
+ }
+
+ if (len == len2) {
+ if (len > 4) {
+ /* handle .jf0 en .jf1 for jstreams */
+ if (BLI_strncasecmp(string + len - 4, ".jf", 3) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".tga", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".jpg", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".png", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".txt", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".cyc", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".enh", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".rgb", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".psx", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".ble", 4) == 0) len -= 4;
+ else if (BLI_strncasecmp(string + len - 4, ".exr", 4) == 0) len -= 4;
+ }
+ }
+
+ for (i = len - 1; i >= 0; i--) {
+ if (string[i] == '/') break;
+ if (isdigit(string[i])) {
+ if (found){
+ nums = i;
+ }
+ else{
+ nume = i;
+ nums = i;
+ found = 1;
+ }
+ }
+ else {
+ if (found) break;
+ }
+ }
+ if (found){
+ if (start) strcpy(start,&string[nume+1]);
+ if (kop) {
+ strcpy(kop,string);
+ kop[nums]=0;
+ }
+ if (numlen) *numlen = nume-nums+1;
+ return ((int)atoi(&(string[nums])));
+ }
+ if (start) strcpy(start, string + len);
+ if (kop) {
+ strncpy(kop, string, len);
+ kop[len] = 0;
+ }
+ if (numlen) *numlen=0;
+ return 0;
+}
+
+
+void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic)
+{
+ char numstr[10]="";
+ unsigned short len,i;
+
+ strcpy(string,kop);
+
+ if (pic>0 || numlen==4) {
+ len= sprintf(numstr,"%d",pic);
+
+ for(i=len;i<numlen;i++){
+ strcat(string,"0");
+ }
+ strcat(string,numstr);
+ }
+ strcat(string, start);
+}
+
+
+void BLI_newname(char *name, int add)
+{
+ char head[128], tail[128];
+ int pic;
+ unsigned short digits;
+
+ pic = BLI_stringdec(name, head, tail, &digits);
+
+ /* are we going from 100 -> 99 or from 10 -> 9 */
+ if (add < 0 && digits < 4 && digits > 0) {
+ int i, exp;
+ exp = 1;
+ for (i = digits; i > 1; i--) exp *= 10;
+ if (pic >= exp && (pic + add) < exp) digits--;
+ }
+
+ pic += add;
+
+ if (digits==4 && pic<0) pic= 0;
+ BLI_stringenc(name, head, tail, digits, pic);
+}
+
+
+void BLI_addhead(ListBase *listbase, void *vlink)
+{
+ Link *link= vlink;
+
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+
+ link->next = listbase->first;
+ link->prev = NULL;
+
+ if (listbase->first) ((Link *)listbase->first)->prev = link;
+ if (listbase->last == NULL) listbase->last = link;
+ listbase->first = link;
+}
+
+
+void BLI_addtail(ListBase *listbase, void *vlink)
+{
+ Link *link= vlink;
+
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+
+ link->next = NULL;
+ link->prev = listbase->last;
+
+ if (listbase->last) ((Link *)listbase->last)->next = link;
+ if (listbase->first == 0) listbase->first = link;
+ listbase->last = link;
+}
+
+
+void BLI_remlink(ListBase *listbase, void *vlink)
+{
+ Link *link= vlink;
+
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+
+ if (link->next) link->next->prev = link->prev;
+ if (link->prev) link->prev->next = link->next;
+
+ if (listbase->last == link) listbase->last = link->prev;
+ if (listbase->first == link) listbase->first = link->next;
+}
+
+
+void BLI_freelinkN(ListBase *listbase, void *vlink)
+{
+ Link *link= vlink;
+
+ if (link == NULL) return;
+ if (listbase == NULL) return;
+
+ BLI_remlink(listbase,link);
+ MEM_freeN(link);
+}
+
+
+void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
+{
+ Link *prevlink= vprevlink;
+ Link *newlink= vnewlink;
+
+ /* newlink comes after prevlink */
+ if (newlink == NULL) return;
+ if (listbase == NULL) return;
+
+ /* empty list */
+ if (listbase->first == NULL) {
+
+ listbase->first= newlink;
+ listbase->last= newlink;
+ return;
+ }
+
+ /* insert before first element */
+ if (prevlink == NULL) {
+ newlink->next= listbase->first;
+ newlink->prev= 0;
+ newlink->next->prev= newlink;
+ listbase->first= newlink;
+ return;
+ }
+
+ /* at end of list */
+ if (listbase->last== prevlink)
+ listbase->last = newlink;
+
+ newlink->next= prevlink->next;
+ prevlink->next= newlink;
+ if (newlink->next) newlink->next->prev= newlink;
+ newlink->prev= prevlink;
+}
+
+/* This uses insertion sort, so NOT ok for large list */
+void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
+{
+ Link *current = NULL;
+ Link *previous = NULL;
+ Link *next = NULL;
+
+ if (cmp == NULL) return;
+ if (listbase == NULL) return;
+
+ if (listbase->first != listbase->last)
+ {
+ for( previous = listbase->first, current = previous->next; current; previous = current, current = next )
+ {
+ next = current->next;
+
+ BLI_remlink(listbase, current);
+
+ while(previous && cmp(previous, current) == 1)
+ {
+ previous = previous->prev;
+ }
+
+ if (previous == NULL)
+ {
+ BLI_addhead(listbase, current);
+ }
+ else
+ {
+ BLI_insertlinkafter(listbase, previous, current);
+ }
+ }
+ }
+}
+
+void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
+{
+ Link *prevlink= vprevlink;
+ Link *newlink= vnewlink;
+
+ /* newlink before nextlink */
+ if (newlink == NULL) return;
+ if (listbase == NULL) return;
+
+ /* empty list */
+ if (listbase->first == NULL) {
+ listbase->first= newlink;
+ listbase->last= newlink;
+ return;
+ }
+
+ /* insert at head of list */
+ if (prevlink == NULL) {
+ newlink->prev = NULL;
+ newlink->next = listbase->first;
+ ((Link *)listbase->first)->prev = newlink;
+ listbase->first = newlink;
+ return;
+ }
+
+ /* at end of list */
+ if (listbase->last == prevlink)
+ listbase->last = newlink;
+
+ newlink->next = prevlink->next;
+ newlink->prev = prevlink;
+ prevlink->next = newlink;
+ if (newlink->next) newlink->next->prev = newlink;
+}
+
+void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
+{
+ Link *nextlink= vnextlink;
+ Link *newlink= vnewlink;
+
+ /* newlink before nextlink */
+ if (newlink == NULL) return;
+ if (listbase == NULL) return;
+
+ /* empty list */
+ if (listbase->first == NULL) {
+ listbase->first= newlink;
+ listbase->last= newlink;
+ return;
+ }
+
+ /* insert at end of list */
+ if (nextlink == NULL) {
+ newlink->prev= listbase->last;
+ newlink->next= 0;
+ ((Link *)listbase->last)->next= newlink;
+ listbase->last= newlink;
+ return;
+ }
+
+ /* at beginning of list */
+ if (listbase->first== nextlink)
+ listbase->first = newlink;
+
+ newlink->next= nextlink;
+ newlink->prev= nextlink->prev;
+ nextlink->prev= newlink;
+ if (newlink->prev) newlink->prev->next= newlink;
+}
+
+
+void BLI_freelist(ListBase *listbase)
+{
+ Link *link, *next;
+
+ if (listbase == NULL)
+ return;
+
+ link= listbase->first;
+ while (link) {
+ next= link->next;
+ free(link);
+ link= next;
+ }
+
+ listbase->first= NULL;
+ listbase->last= NULL;
+}
+
+void BLI_freelistN(ListBase *listbase)
+{
+ Link *link, *next;
+
+ if (listbase == NULL) return;
+
+ link= listbase->first;
+ while (link) {
+ next= link->next;
+ MEM_freeN(link);
+ link= next;
+ }
+
+ listbase->first= NULL;
+ listbase->last= NULL;
+}
+
+
+int BLI_countlist(ListBase *listbase)
+{
+ Link *link;
+ int count = 0;
+
+ if (listbase) {
+ link = listbase->first;
+ while (link) {
+ count++;
+ link= link->next;
+ }
+ }
+ return count;
+}
+
+void *BLI_findlink(ListBase *listbase, int number)
+{
+ Link *link = NULL;
+
+ if (number >= 0) {
+ link = listbase->first;
+ while (link != NULL && number != 0) {
+ number--;
+ link = link->next;
+ }
+ }
+
+ return link;
+}
+
+int BLI_findindex(ListBase *listbase, void *vlink)
+{
+ Link *link= NULL;
+ int number= 0;
+
+ if (listbase == NULL) return -1;
+ if (vlink == NULL) return -1;
+
+ link= listbase->first;
+ while (link) {
+ if (link == vlink)
+ return number;
+
+ number++;
+ link= link->next;
+ }
+
+ return -1;
+}
+
+/*=====================================================================================*/
+/* Methods for access array (realloc) */
+/*=====================================================================================*/
+
+/* remove item with index */
+static void rem_array_item(struct DynamicArray *da, unsigned int index)
+{
+ da->items[index]=NULL;
+ da->count--;
+ if(index==da->last_item_index){
+ while((!da->items[da->last_item_index]) && (da->last_item_index>0)){
+ da->last_item_index--;
+ }
+ }
+}
+
+/* add array (if needed, then realloc) */
+static void add_array_item(struct DynamicArray *da, void *item, unsigned int index)
+{
+ /* realloc of access array */
+ if(da->max_item_index < index){
+ unsigned int i, max = da->max_item_index;
+ void **nitems;
+
+ do {
+ da->max_item_index += PAGE_SIZE; /* OS can allocate only PAGE_SIZE Bytes */
+ } while(da->max_item_index<=index);
+
+ nitems = (void**)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
+ for(i=0;i<=max;i++)
+ nitems[i] = da->items[i];
+
+ /* set rest pointers to the NULL */
+ for(i=max+1; i<=da->max_item_index; i++)
+ nitems[i]=NULL;
+
+ MEM_freeN(da->items); /* free old access array */
+ da->items = nitems;
+ }
+
+ da->items[index] = item;
+ da->count++;
+ if(index > da->last_item_index) da->last_item_index = index;
+}
+
+/* free access array */
+static void destroy_array(DynamicArray *da)
+{
+ da->count=0;
+ da->last_item_index=0;
+ da->max_item_index=0;
+ MEM_freeN(da->items);
+ da->items = NULL;
+}
+
+/* initialize dynamic array */
+static void init_array(DynamicArray *da)
+{
+ unsigned int i;
+
+ da->count=0;
+ da->last_item_index=0;
+ da->max_item_index = PAGE_SIZE-1;
+ da->items = (void*)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
+ for(i=0; i<=da->max_item_index; i++) da->items[i]=NULL;
+}
+
+/* reinitialize dynamic array */
+static void reinit_array(DynamicArray *da)
+{
+ destroy_array(da);
+ init_array(da);
+}
+
+/*=====================================================================================*/
+/* Methods for two way dynamic list with access array */
+/*=====================================================================================*/
+
+/* create new two way dynamic list with access array from two way dynamic list
+ * it doesn't copy any items to new array or something like this It is strongly
+ * recomended to use BLI_dlist_ methods for adding/removing items from dynamic list
+ * unless you can end with inconsistence system !!! */
+DynamicList *BLI_dlist_from_listbase(ListBase *lb)
+{
+ DynamicList *dlist;
+ Link *item;
+ int i=0, count;
+
+ if(!lb) return NULL;
+
+ count = BLI_countlist(lb);
+
+ dlist = MEM_mallocN(sizeof(DynamicList), "temp dynamic list");
+ /* ListBase stuff */
+ dlist->lb.first = lb->first;
+ dlist->lb.last = lb->last;
+ /* access array stuff */
+ dlist->da.count=count;
+ dlist->da.max_item_index = count-1;
+ dlist->da.last_item_index = count -1;
+ dlist->da.items = (void*)MEM_mallocN(sizeof(void*)*count, "temp dlist access array");
+
+ item = (Link*)lb->first;
+ while(item){
+ dlist->da.items[i] = (void*)item;
+ item = item->next;
+ i++;
+ }
+
+ /* to prevent you of using original ListBase :-) */
+ lb->first = lb->last = NULL;
+
+ return dlist;
+}
+
+/* take out ListBase from DynamicList and destroy all temporary structures of DynamicList */
+ListBase *BLI_listbase_from_dlist(DynamicList *dlist, ListBase *lb)
+{
+ if(!dlist) return NULL;
+
+ if(!lb) lb = (ListBase*)MEM_mallocN(sizeof(ListBase), "ListBase");
+
+ lb->first = dlist->lb.first;
+ lb->last = dlist->lb.last;
+
+ /* free all items of access array */
+ MEM_freeN(dlist->da.items);
+ /* free DynamicList*/
+ MEM_freeN(dlist);
+
+ return lb;
+}
+
+/* return pointer at item from th dynamic list with access array */
+void *BLI_dlist_find_link(DynamicList *dlist, unsigned int index)
+{
+ if(!dlist || !dlist->da.items) return NULL;
+
+ if((index <= dlist->da.last_item_index) && (index >= 0) && (dlist->da.count>0)){
+ return dlist->da.items[index];
+ }
+ else {
+ return NULL;
+ }
+}
+
+/* return count of items in the dynamic list with access array */
+unsigned int BLI_count_items(DynamicList *dlist)
+{
+ if(!dlist) return 0;
+
+ return dlist->da.count;
+}
+
+/* free item from the dynamic list with access array */
+void BLI_dlist_free_item(DynamicList *dlist, unsigned int index)
+{
+ if(!dlist || !dlist->da.items) return;
+
+ if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
+ BLI_freelinkN(&(dlist->lb), dlist->da.items[index]);
+ rem_array_item(&(dlist->da), index);
+ }
+}
+
+/* remove item from the dynamic list with access array */
+void BLI_dlist_rem_item(DynamicList *dlist, unsigned int index)
+{
+ if(!dlist || !dlist->da.items) return;
+
+ if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
+ BLI_remlink(&(dlist->lb), dlist->da.items[index]);
+ rem_array_item(&(dlist->da), index);
+ }
+}
+
+/* add item to the dynamic list with access array (index) */
+void* BLI_dlist_add_item_index(DynamicList *dlist, void *item, unsigned int index)
+{
+ if(!dlist || !dlist->da.items) return NULL;
+
+ if((index <= dlist->da.max_item_index) && (dlist->da.items[index])) {
+ /* you can't place item at used index */
+ return NULL;
+ }
+ else {
+ add_array_item(&(dlist->da), item, index);
+ BLI_addtail(&(dlist->lb), item);
+ return item;
+ }
+}
+
+/* destroy dynamic list with access array */
+void BLI_dlist_destroy(DynamicList *dlist)
+{
+ if(!dlist) return;
+
+ BLI_freelistN(&(dlist->lb));
+ destroy_array(&(dlist->da));
+}
+
+/* initialize dynamic list with access array */
+void BLI_dlist_init(DynamicList *dlist)
+{
+ if(!dlist) return;
+
+ dlist->lb.first = NULL;
+ dlist->lb.last = NULL;
+
+ init_array(&(dlist->da));
+}
+
+/* reinitialize dynamic list with acces array */
+void BLI_dlist_reinit(DynamicList *dlist)
+{
+ if(!dlist) return;
+
+ BLI_freelistN(&(dlist->lb));
+ reinit_array(&(dlist->da));
+}
+
+/*=====================================================================================*/
+
+char *BLI_strdupn(const char *str, int len) {
+ char *n= MEM_mallocN(len+1, "strdup");
+ memcpy(n, str, len);
+ n[len]= '\0';
+
+ return n;
+}
+char *BLI_strdup(const char *str) {
+ return BLI_strdupn(str, strlen(str));
+}
+
+char *BLI_strncpy(char *dst, const char *src, int maxncpy) {
+ int srclen= strlen(src);
+ int cpylen= (srclen>(maxncpy-1))?(maxncpy-1):srclen;
+
+ memcpy(dst, src, cpylen);
+ dst[cpylen]= '\0';
+
+ return dst;
+}
+
+int BLI_snprintf(char *buffer, size_t count, const char *format, ...)
+{
+ int n;
+ va_list arg;
+
+ va_start(arg, format);
+ n = vsnprintf(buffer, count, format, arg);
+
+ if (n != -1 && n < count) {
+ buffer[n] = '\0';
+ } else {
+ buffer[count-1] = '\0';
+ }
+
+ va_end(arg);
+ return n;
+}
+
+int BLI_streq(char *a, char *b) {
+ return (strcmp(a, b)==0);
+}
+int BLI_strcaseeq(char *a, char *b) {
+ return (BLI_strcasecmp(a, b)==0);
+}
+
+/* ******************** string encoding ***************** */
+
+/* This is quite an ugly function... its purpose is to
+ * take the dir name, make it absolute, and clean it up, replacing
+ * excess file entry stuff (like /tmp/../tmp/../)
+ * note that dir isn't protected for max string names...
+ */
+
+void BLI_cleanup_dir(const char *relabase, char *dir)
+{
+ short a;
+ char *start, *eind;
+
+ BLI_convertstringcode(dir, relabase, 0);
+
+#ifdef WIN32
+ if(dir[0]=='.') { /* happens for example in FILE_MAIN */
+ get_default_root(dir);
+ return;
+ }
+
+ while ( (start = strstr(dir, "\\..\\")) ) {
+ eind = start + strlen("\\..\\") - 1;
+ a = start-dir-1;
+ while (a>0) {
+ if (dir[a] == '\\') break;
+ a--;
+ }
+ strcpy(dir+a,eind);
+ }
+
+ while ( (start = strstr(dir,"\\.\\")) ){
+ eind = start + strlen("\\.\\") - 1;
+ strcpy(start,eind);
+ }
+
+ while ( (start = strstr(dir,"\\\\" )) ){
+ eind = start + strlen("\\\\") - 1;
+ strcpy(start,eind);
+ }
+
+ if((a = strlen(dir))){ /* remove the '\\' at the end */
+ while(a>0 && dir[a-1] == '\\'){
+ a--;
+ dir[a] = 0;
+ }
+ }
+
+ strcat(dir, "\\");
+#else
+ if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
+ dir[0]= '/';
+ dir[1]= 0;
+ return;
+ }
+
+ while ( (start = strstr(dir, "/../")) ) {
+ eind = start + strlen("/../") - 1;
+ a = start-dir-1;
+ while (a>0) {
+ if (dir[a] == '/') break;
+ a--;
+ }
+ strcpy(dir+a,eind);
+ }
+
+ while ( (start = strstr(dir,"/./")) ){
+ eind = start + strlen("/./") - 1;
+ strcpy(start,eind);
+ }
+
+ while ( (start = strstr(dir,"//" )) ){
+ eind = start + strlen("//") - 1;
+ strcpy(start,eind);
+ }
+
+ if( (a = strlen(dir)) ){ /* remove all '/' at the end */
+ while(dir[a-1] == '/'){
+ a--;
+ dir[a] = 0;
+ if (a<=0) break;
+ }
+ }
+
+ strcat(dir, "/");
+#endif
+}
+
+
+void BLI_makestringcode(const char *relfile, char *file)
+{
+ char * p;
+ char * q;
+ char * lslash;
+ char temp[FILE_MAXDIR+FILE_MAXFILE];
+ char res[FILE_MAXDIR+FILE_MAXFILE];
+
+ /* if file is already relative, bail out */
+ if(file[0]=='/' && file[1]=='/') return;
+
+ /* also bail out if relative path is not set */
+ if (relfile[0] == 0) return;
+
+#ifdef WIN32
+ if (strlen(relfile) > 2 && relfile[1] != ':') {
+ char* ptemp;
+ /* fix missing volume name in relative base,
+ can happen with old .Blog files */
+ get_default_root(temp);
+ ptemp = &temp[2];
+ if (relfile[0] != '\\' && relfile[0] != '/') {
+ ptemp++;
+ }
+ BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
+ } else {
+ BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
+ }
+
+ if (strlen(file) > 2) {
+ if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
+ return;
+ }
+#else
+ BLI_strncpy(temp, relfile, FILE_MAX);
+#endif
+
+ BLI_char_switch(temp, '\\', '/');
+ BLI_char_switch(file, '\\', '/');
+
+ /* the last slash in the file indicates where the path part ends */
+ lslash = BLI_last_slash(temp);
+
+ if (lslash)
+ {
+ /* find the prefix of the filename that is equal for both filenames.
+ This is replaced by the two slashes at the beginning */
+ p = temp;
+ q = file;
+ while (*p == *q) {
+ ++p; ++q;
+ }
+ /* we might have passed the slash when the beginning of a dir matches
+ so we rewind. Only check on the actual filename
+ */
+ if (*q != '/') {
+ while ( (q >= file) && (*q != '/') ) { --q; --p; }
+ }
+ else if (*p != '/') {
+ while ( (p >= temp) && (*p != '/') ) { --p; --q; }
+ }
+
+ strcpy(res, "//");
+
+ /* p now points to the slash that is at the beginning of the part
+ where the path is different from the relative path.
+ We count the number of directories we need to go up in the
+ hierarchy to arrive at the common 'prefix' of the path
+ */
+ while (p && p < lslash) {
+ if (*p == '/')
+ strcat(res, "../");
+ ++p;
+ }
+
+ strcat(res, q+1); /* don't copy the slash at the beginning */
+
+#ifdef WIN32
+ BLI_char_switch(res+2, '/', '\\');
+#endif
+ strcpy(file, res);
+ }
+}
+
+int BLI_convertstringcode(char *path, const char *basepath, int framenum)
+{
+ int len, wasrelative;
+ char tmp[FILE_MAXDIR+FILE_MAXFILE];
+ char base[FILE_MAXDIR];
+ char vol[3] = {'\0', '\0', '\0'};
+
+ BLI_strncpy(vol, path, 3);
+ wasrelative= (strncmp(vol, "//", 2)==0);
+
+#ifdef WIN32
+ /* we are checking here if we have an absolute path that is not in the current
+ blend file as a lib main - we are basically checking for the case that a
+ UNIX root '/' is passed.
+ */
+ if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
+ char *p = path;
+ get_default_root(tmp);
+ // get rid of the slashes at the beginning of the path
+ while (*p == '\\' || *p == '/') {
+ p++;
+ }
+ strcat(tmp, p);
+ }
+ else {
+ strcpy(tmp, path);
+ }
+#else
+ strcpy(tmp, path);
+#endif
+
+ strcpy(base, basepath);
+
+ /* push slashes into unix mode - strings entering this part are
+ potentially messed up: having both back- and forward slashes.
+ Here we push into one conform direction, and at the end we
+ push them into the system specific dir. This ensures uniformity
+ of paths and solving some problems (and prevent potential future
+ ones) -jesterKing. */
+ BLI_char_switch(tmp, '\\', '/');
+ BLI_char_switch(base, '\\', '/');
+
+ if (tmp[0] == '/' && tmp[1] == '/') {
+ char *filepart= BLI_strdup(tmp+2); /* skip code */
+ char *lslash= BLI_last_slash(base);
+
+ if (lslash) {
+ int baselen= (int) (lslash-base) + 1;
+
+ memcpy(tmp, base, baselen);
+ strcpy(tmp+baselen, filepart);
+ } else {
+ strcpy(tmp, filepart);
+ }
+
+ MEM_freeN(filepart);
+ }
+
+ len= strlen(tmp);
+ if(len && tmp[len-1]=='#') {
+ sprintf(tmp+len-1, "%04d", framenum);
+ }
+
+ strcpy(path, tmp);
+#ifdef WIN32
+ /* skip first two chars, which in case of
+ absolute path will be drive:/blabla and
+ in case of relpath //blabla/. So relpath
+ // will be retained, rest will be nice and
+ shiny win32 backward slashes :) -jesterKing
+ */
+ BLI_char_switch(path+2, '/', '\\');
+#endif
+
+ return wasrelative;
+}
+
+void BLI_splitdirstring(char *di, char *fi)
+{
+ char *lslash= BLI_last_slash(di);
+
+ if (lslash) {
+ BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
+ *(lslash+1)=0;
+ } else {
+ BLI_strncpy(fi, di, FILE_MAXFILE);
+ di[0]= 0;
+ }
+}
+
+char *BLI_gethome(void) {
+ #ifdef __BeOS
+ return "/boot/home/"; /* BeOS 4.5: doubleclick at icon doesnt give home env */
+
+ #elif !defined(WIN32)
+ return getenv("HOME");
+
+ #else /* Windows */
+ char * ret;
+ static char dir[512];
+
+ /* Check for %HOME% env var */
+
+ ret = getenv("HOME");
+ if(ret) {
+ sprintf(dir, "%s\\.blender", ret);
+ if (BLI_exists(dir)) return dir;
+ }
+
+ /* else, check install dir (path containing blender.exe) */
+
+ BLI_getInstallationDir(dir);
+
+ if (BLI_exists(dir))
+ {
+ strcat(dir,"\\.blender");
+ if (BLI_exists(dir)) return(dir);
+ }
+
+
+ /* add user profile support for WIN 2K / NT */
+ ret = getenv("USERPROFILE");
+ if (ret) {
+ if (BLI_exists(ret)) { /* from fop, also below... */
+ sprintf(dir, "%s\\Application Data\\Blender Foundation\\Blender", ret);
+ BLI_recurdir_fileops(dir);
+ if (BLI_exists(dir)) {
+ strcat(dir,"\\.blender");
+ if(BLI_exists(dir)) return(dir);
+ }
+ }
+ }
+
+ /*
+ Saving in the Windows dir is less than desirable.
+ Use as a last resort ONLY! (aphex)
+ */
+
+ ret = getenv("WINDOWS");
+ if (ret) {
+ if(BLI_exists(ret)) return ret;
+ }
+
+ ret = getenv("WINDIR");
+ if (ret) {
+ if(BLI_exists(ret)) return ret;
+ }
+
+ return "C:\\Temp"; /* sheesh! bad, bad, bad! (aphex) */
+ #endif
+}
+
+void BLI_clean(char *path)
+{
+ if(path==0) return;
+#ifdef WIN32
+ if(path && strlen(path)>2) {
+ BLI_char_switch(path+2, '/', '\\');
+ }
+#else
+ BLI_char_switch(path, '\\', '/');
+#endif
+}
+
+void BLI_char_switch(char *string, char from, char to)
+{
+ if(string==0) return;
+ while (*string != 0) {
+ if (*string == from) *string = to;
+ string++;
+ }
+}
+
+void BLI_make_exist(char *dir) {
+ int a;
+
+ #ifdef WIN32
+ BLI_char_switch(dir, '/', '\\');
+ #else
+ BLI_char_switch(dir, '\\', '/');
+ #endif
+
+ a = strlen(dir);
+
+#ifdef WIN32
+ while(BLI_exists(dir) == 0){
+ a --;
+ while(dir[a] != '\\'){
+ a--;
+ if (a <= 0) break;
+ }
+ if (a >= 0) dir[a+1] = 0;
+ else {
+ /* defaulting to drive (usually 'C:') of Windows installation */
+ get_default_root(dir);
+ break;
+ }
+ }
+#else
+ while(BLI_exist(dir) == 0){
+ a --;
+ while(dir[a] != '/'){
+ a--;
+ if (a <= 0) break;
+ }
+ if (a >= 0) dir[a+1] = 0;
+ else {
+ strcpy(dir,"/");
+ break;
+ }
+ }
+#endif
+}
+
+void BLI_make_existing_file(char *name)
+{
+ char di[FILE_MAXDIR], fi[FILE_MAXFILE];
+
+ strcpy(di, name);
+ BLI_splitdirstring(di, fi);
+
+ /* test exist */
+ if (BLI_exists(di) == 0) {
+ BLI_recurdir_fileops(di);
+ }
+}
+
+
+void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
+{
+ int sl;
+
+ if (!string || !dir || !file) return; /* We don't want any NULLs */
+
+ string[0]= 0; /* ton */
+
+ /* we first push all slashes into unix mode, just to make sure we don't get
+ any mess with slashes later on. -jesterKing */
+ /* constant strings can be passed for those parameters - don't change them - elubie */
+ /*
+ BLI_char_switch(relabase, '\\', '/');
+ BLI_char_switch(dir, '\\', '/');
+ BLI_char_switch(file, '\\', '/');
+ */
+
+ /* Resolve relative references */
+ if (relabase && dir[0] == '/' && dir[1] == '/') {
+ char *lslash;
+
+ /* Get the file name, chop everything past the last slash (ie. the filename) */
+ strcpy(string, relabase);
+
+ lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\');
+
+ if(lslash) *(lslash+1)= 0;
+
+ dir+=2; /* Skip over the relative reference */
+ }
+#ifdef WIN32
+ else {
+ if (strlen(dir) >= 2 && dir[1] == ':' ) {
+ BLI_strncpy(string, dir, 3);
+ dir += 2;
+ }
+ else { /* no drive specified */
+ /* first option: get the drive from the relabase if it has one */
+ if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
+ BLI_strncpy(string, relabase, 3);
+ string[2] = '\\';
+ string[3] = '\0';
+ }
+ else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
+ get_default_root(string);
+ }
+
+ /* ignore leading slashes */
+ while (*dir == '/' || *dir == '\\') dir++;
+ }
+ }
+#endif
+
+ strcat(string, dir);
+
+ /* Make sure string ends in one (and only one) slash */
+ /* first trim all slashes from the end of the string */
+ sl = strlen(string);
+ while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
+ string[sl-1] = '\0';
+ sl--;
+ }
+ /* since we've now removed all slashes, put back one slash at the end. */
+ strcat(string, "/");
+
+ while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
+ file++;
+
+ strcat (string, file);
+
+ /* Push all slashes to the system preferred direction */
+ BLI_clean(string);
+}
+
+int BLI_testextensie(const char *str, const char *ext)
+{
+ short a, b;
+ int retval;
+
+ a= strlen(str);
+ b= strlen(ext);
+
+ if(a==0 || b==0 || b>=a) {
+ retval = 0;
+ } else if (BLI_strcasecmp(ext, str + a - b)) {
+ retval = 0;
+ } else {
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+
+
+void BLI_split_dirfile(const char *string, char *dir, char *file)
+{
+ int a;
+#ifdef WIN32
+ int sl;
+ short is_relative = 0;
+#endif
+
+ dir[0]= 0;
+ file[0]= 0;
+
+#ifdef WIN32
+ BLI_char_switch(string, '/', '\\'); /* make sure we have a valid path format */
+ sl = strlen(string);
+ if (sl) {
+ int len;
+ if (string[0] == '/' || string[0] == '\\') {
+ BLI_strncpy(dir, string, FILE_MAXDIR);
+ if (sl > 1 && string[0] == '\\' && string[1] == '\\') is_relative = 1;
+ } else if (sl > 2 && string[1] == ':' && string[2] == '\\') {
+ BLI_strncpy(dir, string, FILE_MAXDIR);
+ } else {
+ BLI_getwdN(dir);
+ strcat(dir,"\\");
+ strcat(dir,string);
+ BLI_strncpy(string,dir,FILE_MAXDIR+FILE_MAXFILE);
+ }
+
+ // BLI_exist doesn't recognize a slashed dirname as a dir
+ // check if a trailing slash exists, and remove it. Do not do this
+ // when we are already at root. -jesterKing
+ a = strlen(dir);
+ if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0;
+
+ if (is_relative) {
+ printf("WARNING: BLI_split_dirfile needs absolute dir\n");
+ }
+ else {
+ BLI_make_exist(dir);
+ }
+
+ if (S_ISDIR(BLI_exist(dir))) {
+
+ /* copy from end of string into file, to ensure filename itself isn't truncated
+ if string is too long. (aphex) */
+
+ len = FILE_MAXFILE - strlen(string);
+
+ if (len < 0)
+ BLI_strncpy(file,string + abs(len),FILE_MAXFILE);
+ else
+ BLI_strncpy(file,string,FILE_MAXFILE);
+
+ if (strrchr(string,'\\')) {
+ BLI_strncpy(file,strrchr(string,'\\')+1,FILE_MAXFILE);
+ }
+
+ if ( (a = strlen(dir)) ) {
+ if (dir[a-1] != '\\') strcat(dir,"\\");
+ }
+ }
+ else {
+ a = strlen(dir) - 1;
+ while(a>0 && dir[a] != '\\') a--;
+ dir[a + 1] = 0;
+ BLI_strncpy(file, string + strlen(dir),FILE_MAXFILE);
+ }
+
+ }
+ else {
+ /* defaulting to first valid drive hoping it's not empty CD and DVD drives */
+ get_default_root(dir);
+ file[0]=0;
+ }
+#else
+ if (strlen(string)) {
+ if (string[0] == '/') {
+ strcpy(dir, string);
+ } else if (string[1] == ':' && string[2] == '\\') {
+ string+=2;
+ strcpy(dir, string);
+ } else {
+ BLI_getwdN(dir);
+ strcat(dir,"/");
+ strcat(dir,string);
+ strcpy((char *)string,dir);
+ }
+
+ BLI_make_exist(dir);
+
+ if (S_ISDIR(BLI_exist(dir))) {
+ strcpy(file,string + strlen(dir));
+
+ if (strrchr(file,'/')) strcpy(file,strrchr(file,'/')+1);
+
+ if ( (a = strlen(dir)) ) {
+ if (dir[a-1] != '/') strcat(dir,"/");
+ }
+ }
+ else {
+ a = strlen(dir) - 1;
+ while(dir[a] != '/') a--;
+ dir[a + 1] = 0;
+ strcpy(file, string + strlen(dir));
+ }
+ }
+ else {
+ BLI_getwdN(dir);
+ strcat(dir, "/");
+ file[0] = 0;
+ }
+#endif
+}
+
+/* simple appending of filename to dir, does not check for valid path! */
+void BLI_join_dirfile(char *string, const char *dir, const char *file)
+{
+ int sl_dir = strlen(dir);
+ BLI_strncpy(string, dir, FILE_MAX);
+ if (sl_dir > FILE_MAX-1) sl_dir = FILE_MAX-1;
+#ifdef WIN32
+ string[sl_dir] = '\\';
+#else
+ string[sl_dir] = '/';
+#endif
+ sl_dir++;
+ if (sl_dir <FILE_MAX) {
+ BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir);
+ }
+}
+
+static int add_win32_extension(char *name)
+{
+ int retval = 0;
+ int type;
+
+ type = BLI_exist(name);
+ if ((type == 0) || S_ISDIR(type)) {
+#ifdef _WIN32
+ char filename[FILE_MAXDIR+FILE_MAXFILE];
+ char ext[FILE_MAXDIR+FILE_MAXFILE];
+ char *extensions = getenv("PATHEXT");
+ if (extensions) {
+ char *temp;
+ do {
+ strcpy(filename, name);
+ temp = strstr(extensions, ";");
+ if (temp) {
+ strncpy(ext, extensions, temp - extensions);
+ ext[temp - extensions] = 0;
+ extensions = temp + 1;
+ strcat(filename, ext);
+ } else {
+ strcat(filename, extensions);
+ }
+
+ type = BLI_exist(filename);
+ if (type && (! S_ISDIR(type))) {
+ retval = 1;
+ strcpy(name, filename);
+ break;
+ }
+ } while (temp);
+ }
+#endif
+ } else {
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+void BLI_where_am_i(char *fullname, char *name)
+{
+ char filename[FILE_MAXDIR+FILE_MAXFILE];
+ char *path, *temp;
+ int len;
+#ifdef _WIN32
+ char *seperator = ";";
+ char *slash = "\\";
+#else
+ char *seperator = ":";
+ char *slash = "/";
+#endif
+
+ if (name && fullname && strlen(name)) {
+ strcpy(fullname, name);
+ if (name[0] == '.') {
+ // relative path, prepend cwd
+ BLI_getwdN(fullname);
+ len = strlen(fullname);
+ if (len && fullname[len -1] != slash[0]) {
+ strcat(fullname, slash);
+ }
+ strcat(fullname, name);
+ add_win32_extension(fullname);
+ } else if (BLI_last_slash(name)) {
+ // full path
+ strcpy(fullname, name);
+ add_win32_extension(fullname);
+ } else {
+ // search for binary in $PATH
+ path = getenv("PATH");
+ if (path) {
+ do {
+ temp = strstr(path, seperator);
+ if (temp) {
+ strncpy(filename, path, temp - path);
+ filename[temp - path] = 0;
+ path = temp + 1;
+ } else {
+ strncpy(filename, path, sizeof(filename));
+ }
+ len = strlen(filename);
+ if (len && filename[len - 1] != slash[0]) {
+ strcat(filename, slash);
+ }
+ strcat(filename, name);
+ if (add_win32_extension(filename)) {
+ strcpy(fullname, filename);
+ break;
+ }
+ } while (temp);
+ }
+ }
+#ifndef NDEBUG
+ if (strcmp(name, fullname)) {
+ printf("guessing '%s' == '%s'\n", name, fullname);
+ }
+#endif
+
+#ifdef _WIN32
+ // in windows change long filename to short filename because
+ // win2k doesn't know how to parse a commandline with lots of
+ // spaces and double-quotes. There's another solution to this
+ // with spawnv(P_WAIT, bprogname, argv) instead of system() but
+ // that's even uglier
+ GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE);
+#ifndef NDEBUG
+ printf("Shortname = '%s'\n", fullname);
+#endif
+#endif
+ }
+}
+
+/*
+ * returns absolute path to the app bundle
+ * only useful on OS X
+ */
+#ifdef __APPLE__
+char* BLI_getbundle(void) {
+ CFURLRef bundleURL;
+ CFStringRef pathStr;
+ static char path[MAXPATHLEN];
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+
+ bundleURL = CFBundleCopyBundleURL(mainBundle);
+ pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
+ CFStringGetCString(pathStr, path, MAXPATHLEN, kCFStringEncodingASCII);
+ return path;
+}
+#endif
+
+/* strcasestr not available in MSVC */
+char *BLI_strcasestr(const char *s, const char *find)
+{
+ register char c, sc;
+ register size_t len;
+
+ if ((c = *find++) != 0) {
+ c= tolower(c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ sc= tolower(sc);
+ } while (sc != c);
+ } while (BLI_strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *) s);
+}
+
+
+int BLI_strcasecmp(const char *s1, const char *s2) {
+ int i;
+
+ for (i=0; ; i++) {
+ char c1 = tolower(s1[i]);
+ char c2 = tolower(s2[i]);
+
+ if (c1<c2) {
+ return -1;
+ } else if (c1>c2) {
+ return 1;
+ } else if (c1==0) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int BLI_strncasecmp(const char *s1, const char *s2, int n) {
+ int i;
+
+ for (i=0; i<n; i++) {
+ char c1 = tolower(s1[i]);
+ char c2 = tolower(s2[i]);
+
+ if (c1<c2) {
+ return -1;
+ } else if (c1>c2) {
+ return 1;
+ } else if (c1==0) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+#ifdef WITH_ICONV
+#include "iconv.h"
+#include "localcharset.h"
+
+void BLI_string_to_utf8(char *original, char *utf_8, char *code)
+{
+ size_t inbytesleft=strlen(original);
+ size_t outbytesleft=512;
+ size_t rv=0;
+ iconv_t cd;
+
+ if (NULL == code) {
+ code = locale_charset();
+ }
+ cd=iconv_open("UTF-8", code);
+
+ if (cd == (iconv_t)(-1)) {
+ printf("iconv_open Error");
+ *utf_8='\0';
+ return ;
+ }
+ rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
+ if (rv == (size_t) -1) {
+ printf("iconv Error\n");
+ return ;
+ }
+ *utf_8 = '\0';
+ iconv_close(cd);
+}
+#endif // WITH_ICONV
+
+void BLI_timestr(double time, char *str)
+{
+ /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
+ int hr= ((int) time) / (60*60);
+ int min= ( ((int) time) / 60 ) % 60;
+ int sec= ((int) (time)) % 60;
+ int hun= ((int) (time * 100.0)) % 100;
+
+ if (hr) {
+ sprintf(str, "%.2d:%.2d:%.2d.%.2d",hr,min,sec,hun);
+ } else {
+ sprintf(str, "%.2d:%.2d.%.2d",min,sec,hun);
+ }
+
+ str[11]=0;
+}
+
+/* ************** 64 bits magic, trick to support up to 32 gig of address space *************** */
+/* only works for malloced pointers (8 aligned) */
+
+#ifdef __LP64__
+
+#if defined(WIN32) && !defined(FREE_WINDOWS)
+#define PMASK 0x07FFFFFFFFi64
+#else
+#define PMASK 0x07FFFFFFFFll
+#endif
+
+
+int BLI_int_from_pointer(void *poin)
+{
+ long lval= (long)poin;
+
+ return (int)(lval>>3);
+}
+
+void *BLI_pointer_from_int(int val)
+{
+ static int firsttime= 1;
+ static long basevalue= 0;
+
+ if(firsttime) {
+ void *poin= malloc(10000);
+ basevalue= (long)poin;
+ basevalue &= ~PMASK;
+ printf("base: %d pointer %p\n", basevalue, poin); /* debug */
+ firsttime= 0;
+ free(poin);
+ }
+ return (void *)(basevalue | (((long)val)<<3));
+}
+
+#else
+
+int BLI_int_from_pointer(void *poin)
+{
+ return (int)poin;
+}
+void *BLI_pointer_from_int(int val)
+{
+ return (void *)val;
+}
+
+#endif
+
diff --git a/source/blender/blenlib/intern/vectorops.c b/source/blender/blenlib/intern/vectorops.c
new file mode 100644
index 00000000000..8c4ad5414db
--- /dev/null
+++ b/source/blender/blenlib/intern/vectorops.c
@@ -0,0 +1,169 @@
+/*
+ *
+ * Some vector operations.
+ *
+ * Always use
+ * - vector with x components : float x[3], int x[3], etc
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* ------------------------------------------------------------------------- */
+/* General format: op(a, b, c): a = b op c */
+/* Copying is done cp <from, to> */
+/* ------------------------------------------------------------------------- */
+
+#include "MTC_vectorops.h"
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+void MTC_diff3Int(int v1[3], int v2[3], int v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+void MTC_diff3Float(float v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Int(int v1[3], int v2[3], int v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Float(float v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+/* ------------------------------------------------------------------------- */
+
+void MTC_cross3Double(double v1[3], double v2[3], double v3[3])
+{
+ v1[0] = v2[1]*v3[2] - v2[2]*v3[1];
+ v1[1] = v2[2]*v3[0] - v2[0]*v3[2];
+ v1[2] = v2[0]*v3[1] - v2[1]*v3[0];
+}
+
+/* ------------------------------------------------------------------------- */
+
+int MTC_dot3Int(int v1[3], int v2[3])
+{
+ return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+float MTC_dot3Float(float v1[3], float v2[3])
+{
+ return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cp3Float(float v1[3], float v2[3])
+{
+ v2[0] = v1[0];
+ v2[1] = v1[1];
+ v2[2] = v1[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_cp3FloatInv(float v1[3], float v2[3])
+{
+ v2[0] = -v1[0];
+ v2[1] = -v1[1];
+ v2[2] = -v1[2];
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_swapInt(int *i1, int *i2)
+{
+ int swap;
+ swap = *i1;
+ *i1 = *i2;
+ *i2 = swap;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void MTC_diff3DFF(double v1[3], float v2[3], float v3[3])
+{
+ v1[0] = v2[0] - v3[0];
+ v1[1] = v2[1] - v3[1];
+ v1[2] = v2[2] - v3[2];
+}
+
+/* ------------------------------------------------------------------------- */
+float MTC_normalize3DF(float n[3])
+{
+ float d;
+
+ d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
+ /* FLT_EPSILON is too large! A larger value causes normalize errors in */
+ /* a scaled down utah teapot */
+ if(d>0.0000000000001) {
+
+ /* d= sqrt(d); This _should_ be sqrt, but internally it's a double*/
+ /* anyway. This is safe. */
+ d = sqrt(d);
+
+ n[0]/=d;
+ n[1]/=d;
+ n[2]/=d;
+ } else {
+ n[0]=n[1]=n[2]= 0.0;
+ d= 0.0;
+ }
+ return d;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* eof */
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
new file mode 100644
index 00000000000..1a3dfa79516
--- /dev/null
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -0,0 +1,209 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program 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, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * Windows-posix compatibility layer, windows-specific functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_util.h"
+#define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY
+#include "BLI_winstuff.h"
+
+#include "BKE_utildefines.h" /* FILE_MAXDIR + FILE_MAXFILE */
+
+int BLI_getInstallationDir( char * str ) {
+ char dir[FILE_MAXDIR];
+ char file[FILE_MAXFILE];
+ int a;
+
+ GetModuleFileName(NULL,str,FILE_MAXDIR+FILE_MAXFILE);
+ BLI_split_dirfile(str,dir,file); /* shouldn't be relative */
+ a = strlen(dir);
+ if(dir[a-1] == '\\') dir[a-1]=0;
+
+ strcpy(str,dir);
+
+ return 1;
+}
+
+
+void RegisterBlendExtension(char * str) {
+ LONG lresult;
+ HKEY hkey = 0;
+ DWORD dwd = 0;
+ char buffer[128];
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, "blendfile\\shell\\open\\command", 0,
+ "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "\"%s\" \"%%1\"", str);
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, "blendfile\\DefaultIcon", 0,
+ "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "\"%s\",1", str);
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+
+ lresult = RegCreateKeyEx(HKEY_CLASSES_ROOT, ".blend", 0,
+ "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
+
+ if (lresult == ERROR_SUCCESS) {
+ sprintf(buffer, "%s", "blendfile");
+ lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, buffer, strlen(buffer) + 1);
+ RegCloseKey(hkey);
+ }
+}
+
+DIR *opendir (const char *path) {
+ if (GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY) {
+ DIR *newd= MEM_mallocN(sizeof(DIR), "opendir");
+
+ newd->handle = INVALID_HANDLE_VALUE;
+ sprintf(newd->path, "%s\\*",path);
+
+ newd->direntry.d_ino= 0;
+ newd->direntry.d_off= 0;
+ newd->direntry.d_reclen= 0;
+ newd->direntry.d_name= NULL;
+
+ return newd;
+ } else {
+ return NULL;
+ }
+}
+
+struct dirent *readdir(DIR *dp) {
+ if (dp->direntry.d_name) {
+ MEM_freeN(dp->direntry.d_name);
+ dp->direntry.d_name= NULL;
+ }
+
+ if (dp->handle==INVALID_HANDLE_VALUE) {
+ dp->handle= FindFirstFile(dp->path, &(dp->data));
+ if (dp->handle==INVALID_HANDLE_VALUE)
+ return NULL;
+
+ dp->direntry.d_name= BLI_strdup(dp->data.cFileName);
+
+ return &dp->direntry;
+ } else if (FindNextFile (dp->handle, &(dp->data))) {
+ dp->direntry.d_name= BLI_strdup(dp->data.cFileName);
+
+ return &dp->direntry;
+ } else {
+ return NULL;
+ }
+}
+
+int closedir (DIR *dp) {
+ if (dp->direntry.d_name) MEM_freeN(dp->direntry.d_name);
+ if (dp->handle!=INVALID_HANDLE_VALUE) FindClose(dp->handle);
+
+ MEM_freeN(dp);
+
+ return 0;
+}
+
+void get_default_root(char* root) {
+ char str[MAX_PATH+1];
+
+ /* the default drive to resolve a directory without a specified drive
+ should be the Windows installation drive, since this was what the OS
+ assumes. */
+ if (GetWindowsDirectory(str,MAX_PATH+1)) {
+ root[0] = str[0];
+ root[1] = ':';
+ root[2] = '\\';
+ root[3] = '\0';
+ } else {
+ /* if GetWindowsDirectory fails, something has probably gone wrong,
+ we are trying the blender install dir though */
+ if (GetModuleFileName(NULL,str,MAX_PATH+1)) {
+ printf("Error! Could not get the Windows Directory - Defaulting to Blender installation Dir!");
+ root[0] = str[0];
+ root[1] = ':';
+ root[2] = '\\';
+ root[3] = '\0';
+ } else {
+ DWORD tmp;
+ int i;
+ int rc = 0;
+ /* now something has gone really wrong - still trying our best guess */
+ printf("Error! Could not get the Windows Directory - Defaulting to first valid drive! Path might be invalid!");
+ tmp= GetLogicalDrives();
+ for (i=2; i < 26; i++) {
+ if ((tmp>>i) & 1) {
+ root[0] = 'a'+i;
+ root[1] = ':';
+ root[2] = '\\';
+ root[3] = '\0';
+ if (GetFileAttributes(root) != 0xFFFFFFFF) {
+ rc = i;
+ break;
+ }
+ }
+ }
+ if (0 == rc) {
+ printf("ERROR in 'get_default_root': can't find a valid drive!");
+ root[0] = 'C';
+ root[1] = ':';
+ root[2] = '\\';
+ root[3] = '\0';
+ }
+ }
+ }
+}
+
+#else
+
+static void BLI_WINSTUFF_C_IS_EMPTY_FOR_UNIX(void)
+{
+ /*intentionally empty*/
+}
+
+#endif