diff options
author | Martin Poirier <theeth@yahoo.com> | 2007-11-07 01:29:20 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2007-11-07 01:29:20 +0300 |
commit | 0de103c1cdf1e4c40cfad4e233a42a6d1165953d (patch) | |
tree | a57039fa592cf0f5af3738a9624d0b0ccbf20ec0 /source/blender/blenlib |
Filling in branch from trunk
Diffstat (limited to 'source/blender/blenlib')
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,§orspc, &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 |