diff options
author | Jean-Luc Peurière <jlp@nerim.net> | 2008-03-14 02:54:02 +0300 |
---|---|---|
committer | Jean-Luc Peurière <jlp@nerim.net> | 2008-03-14 02:54:02 +0300 |
commit | a68a7f42b02ad0260220d94f36ab61c772db071a (patch) | |
tree | 620b763cd24fbfc1259f00ccb005217914af0c6f /source/blender/blenlib | |
parent | 526d0bec4722900a86d81ff0f5d71504b2b4ad8c (diff) | |
parent | 15215493bf9d1d08e650109e6eb6189fc76e289e (diff) |
resolved conflict state with HEAD r14096
blenderbuttons still bad
not let this compile
Diffstat (limited to 'source/blender/blenlib')
25 files changed, 3286 insertions, 1083 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index cebeff5c3e1..99e30bc91c0 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -54,6 +54,13 @@ extern "C" { #define M_SQRT1_2 0.70710678118654752440 #endif +#ifdef WIN32 + #ifndef FREE_WINDOWS + #define isnan(n) _isnan(n) + #define finite _finite + #endif +#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},\ @@ -64,577 +71,216 @@ extern "C" { { 0.0, 0.0, 1.0}} -/* matrix operations */ -/* void Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4]); */ -/* void Mat3MulVecfl(float mat[][3], float *vec); */ -/* or **mat, but it's the same */ -/*void Mat3MulVecd(float mat[][3], double *vec); */ - -/* void Mat4MulVecfl(float mat[][4], float *vec); */ -/* 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]); */ -/* int Mat4Invert(float inverse[][4], float mat[][4]); */ - -/* m2 to m1 */ -/* void Mat3CpyMat4(float m1p[][3], float m2p[][4]); */ -/* void Mat3CpyMat4(float *m1p, float *m2p); */ - -/* m1 to m2 */ -/* void Mat3CpyMat3(float m1p[][3], float m2p[][3]); */ -/* void Mat3CpyMat3(float *m1p, float *m2p); */ - -/* m2 to m1 */ -/* void Mat4CpyMat3(float m1p[][4], float m2p[][3]); */ +void CalcCent3f(float *cent, float *v1, float *v2, float *v3); +void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4); -/* M1 = M3*M2 */ -/* void Mat3MulMat3(float m1[][3], float m2[][3], float m3[][3]); */ -/*void Mat3MulMat3(float *m1, float *m3, float *m2); */ +void Crossf(float *c, float *a, float *b); +void Projf(float *c, float *v1, float *v2); -/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */ -/*void Mat3IsMat3MulMat4(float m1[][3], float m2[][3], float m3[][4]); */ +float Inpf(float *v1, float *v2); +float Inp2f(float *v1, float *v2); -/* m1 to m2 */ -/* void Mat4CpyMat4(float m1[][4], float m2[][4]); */ -/* void Mat4CpyMat4(float *m1, float *m2); */ +float Normalize(float *n); +float Normalize2(float *n); +float Sqrt3f(float f); +double Sqrt3d(double d); -/* void Mat4Ortho(float mat[][4]); */ -/* void Mat4Mul3Vecfl(float mat[][4], float *vec); */ -/* void Mat4MulVec4fl(float mat[][4], float *vec); */ -/* void Mat4SwapMat4(float *m1, float *m2); */ +float saacos(float fac); +float saasin(float fac); +float sasqrt(float fac); -/* void Mat3Inv(float m1[][3], float m2[][3]); */ -/* void Mat4One(float m[][4]); */ -/* void Mat3One(float m[][3]); */ +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 -CalcCent3f( - float *cent, float *v1, float *v2, float *v3 -); - - void -CalcCent4f( - float *cent, float *v1, - float *v2, float *v3, - float *v4 -); +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); - void -Crossf( - float *c, float *a, float *b -); - - void -Projf( - float *c, float *v1, float *v2 -); /** - * Euler conversion routines + * @section Euler conversion routines */ - void -EulToMat3( - float *eul, - float mat[][3] -); - void -EulToMat4( - float* eul, - float mat[][4] -); +void EulToMat3(float *eul, float mat[][3]); +void EulToMat4(float *eul, float mat[][4]); - void -Mat3ToEul( - float tmat[][3], - float *eul -); +void Mat3ToEul(float tmat[][3], float *eul); +void Mat4ToEul(float tmat[][4],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 -printquat( - char *str, - float q[4] -); +void QuatToEul(float *quat, float *eul); +void QuatOne(float *); +void QuatMul(float *, float *, float *); +void QuatMulVecf(float *q, float *v); +void QuatMulf(float *q, float f); +void QuatMulFac(float *q, float fac); +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); +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 can copying routines + * @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 -Mat3CpyMat4( - float m1[][3], - float m2[][4] -); +void Mat3MulFloat(float *m, float f); +void Mat4MulFloat(float *m, float f); +void Mat4MulFloat3(float *m, float f); - void -Mat3Inv( - float m1[][3], - float m2[][3] -); +void Mat3Transp(float mat[][3]); +void Mat4Transp(float mat[][4]); - void -Mat4CpyMat3( - float m1[][4], - float m2[][3] -); +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]); - float -Det2x2( - float a,float b,float c,float d -); +void Mat3CpyMat4(float m1[][3],float m2[][4]); +void Mat4CpyMat3(float m1[][4], float m2[][3]); - float -Det3x3( +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] -); +float Det4x4(float m[][4]); - void -Mat4Adj( - float out[][4], - float in[][4] -); - void -Mat3Adj( - float m1[][3], - float m[][3] -); - void -Mat4MulMat4( - float m1[][4], - float m2[][4], - float m3[][4] -); - void -subMat4MulMat4( - float *m1, - float *m2, - float *m3 -); +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] -); +void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]); #else - void -Mat3MulMat3( - float *m1, - float *m3, - float *m2 -); +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], +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], + +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 -Mat4MulVec3Project( - float mat[][4], - float *vec -); - void -Mat4MulVec( - float mat[][4], - int *vec -); - 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 -Mat4One( - float m[][4] -); - void -Mat4Mul3Vecfl( - float mat[][4], - float *vec -); - void -Mat4MulVec4fl( - float mat[][4], - float *vec -); - void -Mat3MulVec( - float mat[][3], - int *vec -); - void -Mat4MulVecfl( - float mat[][4], - float *vec -); - void -Mat4ToQuat( - float m[][4], - float *q -); - void -VecUpMat3old( - float *vec, - float mat[][3], - short axis -); - int -FloatCompare( - float *v1, - float *v2, - float limit -); - float -FloatLerpf( - float target, - float origin, - float fac -); - float -Normalize( - float *n -); - float -CalcNormFloat( - float *v1, - float *v2, - float *v3, - float *n -); - - float -CalcNormFloat4( - float *v1, - float *v2, - float *v3, - float *v4, - float *n -); - 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 -); - float -Sqrt3f( - float f -); - double -Sqrt3d( - double d -); + +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); +float Vec2Length(float *v); +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); + +void vectoquat(float *vec, short axis, short upflag, float *q); + +float VecAngle2(float *v1, float *v2); +float VecAngle3(float *v1, float *v2, float *v3); +float NormalizedVecAngle2(float *v1, float *v2); + +float VecAngle3_2D(float *v1, float *v2, float *v3); +float NormalizedVecAngle2_2D(float *v1, float *v2); + +void euler_rot(float *beul, float ang, char axis); + - void -euler_rot( - float *beul, - float ang, - char axis -); - float -saacos( - float fac -); - float -saasin( - float fac -); - float -sasqrt( - float fac -); - void -printvecf( - char *str, - float v[3] -); - void -printvec4f( - char *str, - float v[4] -); - float -Inpf( - float *v1, - float *v2 -); - void -VecSubf( - float *v, - float *v1, - float *v2 -); - void -VecAddf( - float *v, - float *v1, - float *v2 -); - void -VecLerpf( - float *target, - float *a, - float *b, - float t -); - void -VecUpMat3( - float *vec, - float mat[][3], - short axis -); - float -DistVL2Dfl( - float *v1, - float *v2, - float *v3 -); - float -PdistVL2Dfl( - 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 -); - void -VecRotToMat3( - float *vec, - float phi, - float mat[][3] -); +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: @@ -646,313 +292,113 @@ VecRotToMat3( 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 -); - - float * -vectoquat( - float *vec, - short axis, - short upflag -); +/*point in tri, 0 no intersection, 1 intersect */ +int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2]); +/* point in quad, 0 no intersection, 1 intersect */ +int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]); - float -VecAngle3( - float *v1, - float *v2, - float *v3 -); - - float -VecAngle2( - float *v1, - float *v2 -); - float -NormalizedVecAngle2( - float *v1, - float *v2 -); +/* 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( +void i_lookat( float vx, float vy, float vz, float px, float py, float pz, float twist, float mat[][4] ); - void -i_window( + +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 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 -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 VecStar(float mat[][3],float *vec); - void -ycc_to_rgb( - float y, float cb, float cr, - float *lr, float *lg, float *lb -); +short EenheidsMat(float mat[][3]); - 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 QuatToMat3(float *q, float m[][3]); +void QuatToMat4(float *q, float m[][4]); - void -EulToQuat( - float *eul, - float *quat -); +void Mat3ToQuat_is_ok(float wmat[][3], float *q); - void -Mat3MulVecfl( - float mat[][3], - float *vec -); - void -Mat3MulVecd( - float mat[][3], - double *vec -); - void -Mat3TransMulVecfl( - float mat[][3], - float *vec -); - void -VecStar( - float mat[][3], - float *vec -); - short -EenheidsMat( - float mat[][3] -); - void -printmatrix3( - char *str, float m[][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 -Mat3Ortho( - float mat[][3] -); - void -Mat4Ortho( - float mat[][4] -); - void -VecCopyf( - float *v1, - float *v2 -); - int -VecLen( - int *v1, - int *v2 -); - void -CalcNormShort( - short *v1, - short *v2, - short *v3, - float *n -) /* is ook uitprodukt */; - - void -CalcNormLong( - int* v1, - int*v2, - int*v3, - float *n -); - void -MinMax3( - float *min, - float *max, - float *vec -); +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]); - void -SizeToMat3( - float *size, - float mat[][3] -); - void -printmatrix4( - char *str, - float m[][4] -); /* uit Sig.Proc.85 pag 253 */ - void -Mat3ToQuat( - float wmat[][3], - float *q -); - 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 -VecMidf( - float *v, float *v1, float *v2 -); - 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 -MinMaxRGB( - short c[] -); - 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 -Inp2f( - float *v1, - float *v2 -); - float -Normalize2( - float *n -); +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 LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv); +int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint); +int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda); +int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]); +void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v); +void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv); +void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv); 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); +void DQuatMulVecfl(DualQuat *dq, float *co, float mat[][3]); +void DQuatCpyDQuat(DualQuat *dq1, DualQuat *dq2); #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 75a0e7b49a1..7d401cf2fc3 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -70,7 +70,6 @@ #include "DNA_listBase.h" #include <stdlib.h> - extern ListBase fillfacebase; extern ListBase fillvertbase; /** @@ -79,6 +78,8 @@ extern ListBase fillvertbase; extern ListBase filledgebase; extern int totblock; +extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */ + struct chardesc; struct direntry; struct rctf; @@ -97,20 +98,24 @@ 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_split_dirfile(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); +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_uniquename(struct ListBase *list, void *vlink, char defname[], short name_offs, short len); void BLI_newname(char * name, int add); -int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen); -void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic); +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); @@ -132,7 +137,8 @@ void BLI_dlist_reinit(struct DynamicList *dlist); * 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); +void BLI_cleanup_file(const char *relabase, char *dir); +void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */ /** * Blender's path code replacement function. @@ -173,7 +179,7 @@ void BLI_clean(char *path); * @param str The string to be duplicated * @retval Returns the duplicated string */ -char* BLI_strdup(char *str); +char *BLI_strdup(const char *str); /** * Duplicates the first @a len bytes of cstring @a str @@ -184,7 +190,7 @@ char* BLI_strdup(char *str); * @param len The number of bytes to duplicate * @retval Returns the duplicated string */ -char* BLI_strdupn(char *str, int len); +char *BLI_strdupn(const char *str, int len); /** * Like strncpy but ensures dst is always @@ -196,7 +202,7 @@ char* BLI_strdupn(char *str, int len); * the size of dst) * @retval Returns dst */ -char* BLI_strncpy(char *dst, const char *src, int maxncpy); +char *BLI_strncpy(char *dst, const char *src, int maxncpy); /* * Replacement for snprintf @@ -217,6 +223,11 @@ int BLI_streq(char *a, char *b); */ 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. @@ -245,10 +256,21 @@ void BLI_free_file_lines(struct LinkNode *lines); * @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); +void BLI_where_am_i(char *fullname, const char *name); char *get_install_dir(void); /** + * Gets the temp directory when blender first runs. + * If the default path is not found, use try $TEMP + * + * Also make sure the temp dir has a trailing slash + * + * @param fullname The full path to the temp directory + */ +void BLI_where_is_temp(char *fullname, int usertemp); + + + /** * determines the full path to the application bundle on OS X * * @return path to application bundle @@ -258,15 +280,16 @@ char* BLI_getbundle(void); #endif #ifdef WIN32 -int BLI_getInstallationDir( char * str ); +int BLI_getInstallationDir(char *str); #endif /* BLI_storage.h */ int BLI_filesize(int file); +int BLI_filepathsize(const char *path); double BLI_diskfree(char *dir); -char * BLI_getwdN(char * dir); +char *BLI_getwdN(char *dir); void BLI_hide_dot_files(int set); -unsigned int BLI_getdir(char *dirname, struct direntry **filelist); +unsigned int BLI_getdir(char *dirname, struct direntry **filelist); /** * @attention Do not confuse with BLI_exists @@ -288,8 +311,10 @@ 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); +int BLI_touch(const char *file); +char *BLI_last_slash(const char *string); +void BLI_add_slash(char *string); +void BLI_del_slash(char *string); /* BLI_rct.c */ /** @@ -299,12 +324,12 @@ char *BLI_last_slash(char *string); * * @return True if @a rect is empty. */ -int BLI_rcti_is_empty(struct rcti * rect); +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_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); @@ -361,7 +386,7 @@ 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); +void BLI_timestr(double _time, char *str); /* time var is global */ /** * Trick to address 32 GB with an int (only for malloced pointers) diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h index b5cf9cd81e9..50b864df5f8 100644 --- a/source/blender/blenlib/BLI_boxpack2d.h +++ b/source/blender/blenlib/BLI_boxpack2d.h @@ -28,10 +28,7 @@ * 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 */ diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h new file mode 100644 index 00000000000..e932c39eb06 --- /dev/null +++ b/source/blender/blenlib/BLI_bpath.h @@ -0,0 +1,60 @@ +/** + * + * ***** 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 ***** + */ + +/* Based on ghash, difference is ghash is not a fixed size, + * so for BPath we dont need to malloc */ + +struct BPathIterator { + char* path; + char* lib; + char* name; + void* data; + int len; + int type; +}; + +void BLI_bpathIterator_init (struct BPathIterator *bpi); +char* BLI_bpathIterator_getPath (struct BPathIterator *bpi); +char* BLI_bpathIterator_getLib (struct BPathIterator *bpi); +char* BLI_bpathIterator_getName (struct BPathIterator *bpi); +int BLI_bpathIterator_getType (struct BPathIterator *bpi); +int BLI_bpathIterator_getPathMaxLen(struct BPathIterator *bpi); +void BLI_bpathIterator_step (struct BPathIterator *bpi); +int BLI_bpathIterator_isDone (struct BPathIterator *bpi); +void BLI_bpathIterator_copyPathExpanded( struct BPathIterator *bpi, char *path_expanded); + +/* high level funcs */ + +/* creates a text file with missing files if there are any */ +void checkMissingFiles(char *txtname ); +void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked); +void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked); +void findMissingFiles(char *str); diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index a763ad53f1f..f9b73d521c9 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -55,9 +55,9 @@ typedef struct EditVert struct EditVert *v; struct EditEdge *e; struct EditFace *f; - float *fp; void *p; long l; + float fp; } tmp; float no[3]; /*vertex normal */ float co[3]; /*vertex location */ @@ -67,6 +67,7 @@ typedef struct EditVert h for hidden. if (!eve->h) {... f1 and f2 can be used for temp data, clear them first*/ unsigned char f, h, f1, f2; + float bweight; 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 */ @@ -103,9 +104,11 @@ typedef struct EditEdge short f1, f2; /* short, f1 is (ab)used in subdiv */ unsigned char f, h, dir, seam, sharp; float crease; + float bweight; 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 */ @@ -163,6 +166,13 @@ typedef struct EditMesh /* 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 @@ -171,7 +181,7 @@ typedef struct EditMesh struct RetopoPaintData *retopo_paint_data; - CustomData vdata, fdata; + CustomData vdata, edata, fdata; #ifdef WITH_VERSE void *vnode; diff --git a/source/blender/blenlib/BLI_fnmatch.h b/source/blender/blenlib/BLI_fnmatch.h new file mode 100644 index 00000000000..af1dcf523bf --- /dev/null +++ b/source/blender/blenlib/BLI_fnmatch.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +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, 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. */ + +#ifndef _FNMATCH_H + +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#undef __P +#define __P(protos) protos +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(protos) () +/* We can get away without defining `const' here only because in this file + it is used only inside the prototype for `fnmatch', which is elided in + non-ANSI C where `const' is problematical. */ +#endif /* C++ or ANSI C. */ + + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in <unistd.h>. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE) +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* Match STRING against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch __P ((const char *__pattern, const char *__string, + int __flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h new file mode 100644 index 00000000000..d32e85c150c --- /dev/null +++ b/source/blender/blenlib/BLI_kdtree.h @@ -0,0 +1,63 @@ +/** + * A kd-tree for nearest neighbour search. + * + * $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): Janne Karhu + * Brecht Van Lommel + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BLI_KDTREE_H +#define BLI_KDTREE_H + +struct KDTree; +typedef struct KDTree KDTree; + +typedef struct KDTreeNearest { + int index; + float dist; + float co[3]; +} KDTreeNearest; + +/* Creates or free a kdtree */ +KDTree* BLI_kdtree_new(int maxsize); +void BLI_kdtree_free(KDTree *tree); + +/* Construction: first insert points, then call balance. Normal is optional. */ +void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor); +void BLI_kdtree_balance(KDTree *tree); + +/* Find nearest returns index, and -1 if no node is found. + * Find n nearest returns number of points found, with results in nearest. + * Normal is optional. */ +int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest); +int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest); + +#endif + diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index da2ecb79651..638f36b7414 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -52,6 +52,9 @@ double rng_getDouble (struct RNG* rng); float rng_getFloat (struct RNG* rng); void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems); + /** Note that skipping is as slow as generating n numbers! */ +void rng_skip (struct RNG *rng, int n); + /** Seed the random number generator */ void BLI_srand (unsigned int seed); diff --git a/source/blender/blenlib/BLI_storage_types.h b/source/blender/blenlib/BLI_storage_types.h index 825a8bc9cbd..ebce33852a1 100644 --- a/source/blender/blenlib/BLI_storage_types.h +++ b/source/blender/blenlib/BLI_storage_types.h @@ -52,6 +52,8 @@ struct header{ typedef unsigned int mode_t; #endif +struct ImBuf; + struct direntry{ char *string; mode_t type; @@ -68,6 +70,7 @@ struct direntry{ char extra[16]; void *poin; int nr; + struct ImBuf *image; }; struct dirlink diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 60ecce3f9d8..39162b8bd91 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -50,5 +50,6 @@ void BLI_end_threads (struct ListBase *threadbase); void BLI_lock_thread (int type); void BLI_unlock_thread (int type); +int BLI_system_thread_count( void ); /* gets the number of threads the system can make use of */ #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 4812cad033d..ac2f3235646 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -36,6 +36,13 @@ SET(INC ${ZLIB_INC} ) +IF(CMAKE_SYSTEM_NAME MATCHES "Linux") +SET(INC + ${INC} + ${BINRELOC_INC} +) +ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + IF(WITH_VERSE) ADD_DEFINITIONS(-DWITH_VERSE) SET(INC ${INC} ${VERSE_INC}) diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index e11934d968e..649d3cb5659 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -19,6 +19,7 @@ if env['WITH_BF_VERSE']: if env['OURPLATFORM'] == 'linux2': cflags='-pthread' + incs += ' ../../../extern/binreloc/include' if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 5846bbda40e..6af377edfba 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -117,14 +117,16 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val) { } } -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; - +void* BLI_ghash_lookup(GHash *gh, void *key) +{ + if(gh) { + 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; } diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c new file mode 100644 index 00000000000..80e92cb8809 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -0,0 +1,341 @@ +/** + * $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): Janne Karhu + * Brecht Van Lommel + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_kdtree.h" + +#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } + +typedef struct KDTreeNode { + struct KDTreeNode *left, *right; + float co[3], nor[3]; + int index; + short d; +} KDTreeNode; + +struct KDTree { + KDTreeNode *nodes; + int totnode; + KDTreeNode *root; +}; + +KDTree *BLI_kdtree_new(int maxsize) +{ + KDTree *tree; + + tree= MEM_callocN(sizeof(KDTree), "KDTree"); + tree->nodes= MEM_callocN(sizeof(KDTreeNode)*maxsize, "KDTreeNode"); + tree->totnode= 0; + + return tree; +} + +void BLI_kdtree_free(KDTree *tree) +{ + if(tree) { + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } +} + +void BLI_kdtree_insert(KDTree *tree, int index, float *co, float *nor) +{ + KDTreeNode *node= &tree->nodes[tree->totnode++]; + + node->index= index; + VecCopyf(node->co, co); + if(nor) VecCopyf(node->nor, nor); +} + +static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis) +{ + KDTreeNode *node; + float co; + int left, right, median, i, j; + + if(totnode <= 0) + return NULL; + else if(totnode == 1) + return nodes; + + /* quicksort style sorting around median */ + left= 0; + right= totnode-1; + median= totnode/2; + + while(right > left) { + co= nodes[right].co[axis]; + i= left-1; + j= right; + + while(1) { + while(nodes[++i].co[axis] < co); + while(nodes[--j].co[axis] > co && j>left); + + if(i >= j) break; + SWAP(KDTreeNode, nodes[i], nodes[j]); + } + + SWAP(KDTreeNode, nodes[i], nodes[right]); + if(i >= median) + right= i-1; + if(i <= median) + left= i+1; + } + + /* set node and sort subnodes */ + node= &nodes[median]; + node->d= axis; + node->left= kdtree_balance(nodes, median, (axis+1)%3); + node->right= kdtree_balance(nodes+median+1, (totnode-(median+1)), (axis+1)%3); + + return node; +} + +void BLI_kdtree_balance(KDTree *tree) +{ + tree->root= kdtree_balance(tree->nodes, tree->totnode, 0); +} + +static float squared_distance(float *v1, float *v2, float *n1, float *n2) +{ + float d[3], dist; + + d[0]= v2[0]-v1[0]; + d[1]= v2[1]-v1[1]; + d[2]= v2[2]-v1[2]; + + dist= d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; + + if(n1 && n2 && n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2] < 0.0f) + dist *= 10.0f; + + return dist; +} + +int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest) +{ + KDTreeNode *root, *node, *min_node; + KDTreeNode **stack, *defaultstack[100]; + float min_dist, cur_dist; + int totstack, cur=0; + + if(!tree->root) + return -1; + + stack= defaultstack; + totstack= 100; + + root= tree->root; + min_node= root; + min_dist= squared_distance(root->co,co,root->nor,nor); + + if(co[root->d] < root->co[root->d]) { + if(root->right) + stack[cur++]=root->right; + if(root->left) + stack[cur++]=root->left; + } + else { + if(root->left) + stack[cur++]=root->left; + if(root->right) + stack[cur++]=root->right; + } + + while(cur--){ + node=stack[cur]; + + cur_dist = node->co[node->d] - co[node->d]; + + if(cur_dist<0.0){ + cur_dist= -cur_dist*cur_dist; + + if(-cur_dist<min_dist){ + cur_dist=squared_distance(node->co,co,node->nor,nor); + if(cur_dist<min_dist){ + min_dist=cur_dist; + min_node=node; + } + if(node->left) + stack[cur++]=node->left; + } + if(node->right) + stack[cur++]=node->right; + } + else{ + cur_dist= cur_dist*cur_dist; + + if(cur_dist<min_dist){ + cur_dist=squared_distance(node->co,co,node->nor,nor); + if(cur_dist<min_dist){ + min_dist=cur_dist; + min_node=node; + } + if(node->right) + stack[cur++]=node->right; + } + if(node->left) + stack[cur++]=node->left; + } + if(cur+3 > totstack){ + KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack"); + memcpy(temp,stack,totstack*sizeof(KDTreeNode*)); + if(stack != defaultstack) + MEM_freeN(stack); + stack=temp; + totstack+=100; + } + } + + if(nearest) { + nearest->index= min_node->index; + nearest->dist= sqrt(min_dist); + VecCopyf(nearest->co, min_node->co); + } + + if(stack != defaultstack) + MEM_freeN(stack); + + return min_node->index; +} + +static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co) +{ + int i; + + if(*found<n) (*found)++; + + for(i=*found-1; i>0; i--) { + if(dist >= ptn[i-1].dist) + break; + else + ptn[i]= ptn[i-1]; + } + + ptn[i].index= index; + ptn[i].dist= dist; + VecCopyf(ptn[i].co, co); +} + +/* finds the nearest n entries in tree to specified coordinates */ +int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest) +{ + KDTreeNode *root, *node=0; + KDTreeNode **stack, *defaultstack[100]; + float cur_dist; + int i, totstack, cur=0, found=0; + + if(!tree->root) + return 0; + + stack= defaultstack; + totstack= 100; + + root= tree->root; + + cur_dist= squared_distance(root->co,co,root->nor,nor); + add_nearest(nearest,&found,n,root->index,cur_dist,root->co); + + if(co[root->d] < root->co[root->d]) { + if(root->right) + stack[cur++]=root->right; + if(root->left) + stack[cur++]=root->left; + } + else { + if(root->left) + stack[cur++]=root->left; + if(root->right) + stack[cur++]=root->right; + } + + while(cur--){ + node=stack[cur]; + + cur_dist = node->co[node->d] - co[node->d]; + + if(cur_dist<0.0){ + cur_dist= -cur_dist*cur_dist; + + if(found<n || -cur_dist<nearest[found-1].dist){ + cur_dist=squared_distance(node->co,co,node->nor,nor); + + if(found<n || cur_dist<nearest[found-1].dist) + add_nearest(nearest,&found,n,node->index,cur_dist,node->co); + + if(node->left) + stack[cur++]=node->left; + } + if(node->right) + stack[cur++]=node->right; + } + else{ + cur_dist= cur_dist*cur_dist; + + if(found<n || cur_dist<nearest[found-1].dist){ + cur_dist=squared_distance(node->co,co,node->nor,nor); + if(found<n || cur_dist<nearest[found-1].dist) + add_nearest(nearest,&found,n,node->index,cur_dist,node->co); + + if(node->right) + stack[cur++]=node->right; + } + if(node->left) + stack[cur++]=node->left; + } + if(cur+3 > totstack){ + KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack"); + memcpy(temp,stack,totstack*sizeof(KDTreeNode*)); + if(stack != defaultstack) + MEM_freeN(stack); + stack=temp; + totstack+=100; + } + } + + for(i=0; i<found; i++) + nearest[i].dist= sqrt(nearest[i].dist); + + if(stack != defaultstack) + MEM_freeN(stack); + + return found; +} + diff --git a/source/blender/blenlib/intern/BLI_storage.h b/source/blender/blenlib/intern/BLI_storage.h index 5e9c377c410..9cbdfa327cd 100644 --- a/source/blender/blenlib/intern/BLI_storage.h +++ b/source/blender/blenlib/intern/BLI_storage.h @@ -31,6 +31,11 @@ #ifndef BLI_STORAGE_H #define BLI_STORAGE_H +#ifndef WIN32 +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + #include "BLI_storage_types.h" void BLI_adddirstrings(void); diff --git a/source/blender/blenlib/intern/Makefile b/source/blender/blenlib/intern/Makefile index 0c3f4a486be..9f40710209d 100644 --- a/source/blender/blenlib/intern/Makefile +++ b/source/blender/blenlib/intern/Makefile @@ -36,10 +36,6 @@ DIR = $(OCGDIR)/blender/$(LIBNAME) include nan_compile.mk -ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) - CFLAGS += -funsigned-char -endif - # CPPFLAGS += $(LEVEL_2_CPP_WARNINGS) # path to SDNA types @@ -63,3 +59,6 @@ endif ifeq ($(WITH_FREETYPE2), true) CPPFLAGS += -DWITH_FREETYPE2 endif +ifeq ($(OS),linux) + CPPFLAGS += -I$(OCGDIR)/extern/binreloc/include +endif
\ No newline at end of file diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 182607740a5..cd7de83b9c0 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -760,7 +760,28 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } +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) { @@ -915,7 +936,7 @@ void Mat4MulFloat(float *m, float f) { int i; - for(i=0;i<12;i++) m[i]*=f; /* count to 12: without vector component */ + for(i=0;i<16;i++) m[i]*=f; /* count to 12: without vector component */ } @@ -931,6 +952,24 @@ void Mat4MulFloat3(float *m, float f) /* only scale component */ } } +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) { @@ -1070,6 +1109,7 @@ void QuatInv(float *q) QuatMulf(q, 1.0f/f); } +/* simple mult */ void QuatMulf(float *q, float f) { q[0] *= f; @@ -1085,6 +1125,20 @@ void QuatSub(float *q, float *q1, float *q2) q2[0]= -q2[0]; } +/* angular mult factor */ +void QuatMulFac(float *q, float fac) +{ + float angle= fac*saacos(q[0]); /* quat[0]= cos(0.5*angle), but now the 0.5 and 2.0 rule out */ + + float co= (float)cos(angle); + float si= (float)sin(angle); + q[0]= co; + Normalize(q+1); + q[1]*= si; + q[2]*= si; + q[3]*= si; + +} void QuatToMat3( float *q, float m[][3]) { @@ -1157,7 +1211,7 @@ void QuatToMat4( float *q, float m[][4]) m[3][3]= 1.0f; } -void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */ +void Mat3ToQuat(float wmat[][3], float *q) { double tr, s; float mat[3][3]; @@ -1171,34 +1225,38 @@ void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */ 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); + s= 1.0/(4.0*s); + 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)); + if(mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) { + s= 2.0*sqrtf(1.0 + mat[0][0] - mat[1][1] - mat[2][2]); + q[1]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[2][1] - mat[1][2])*s); + q[2]= (float)((mat[1][0] + mat[0][1])*s); + q[3]= (float)((mat[2][0] + mat[0][2])*s); + } + else if(mat[1][1] > mat[2][2]) { + s= 2.0*sqrtf(1.0 + mat[1][1] - mat[0][0] - mat[2][2]); + q[2]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[2][0] - mat[0][2])*s); + q[1]= (float)((mat[1][0] + mat[0][1])*s); + q[3]= (float)((mat[2][1] + mat[1][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; - } + s= 2.0*sqrtf(1.0 + mat[2][2] - mat[0][0] - mat[1][1]); + q[3]= (float)(0.25*s); + + s= 1.0/s; + q[0]= (float)((mat[1][0] - mat[0][1])*s); + q[1]= (float)((mat[2][0] + mat[0][2])*s); + q[2]= (float)((mat[2][1] + mat[1][2])*s); } } NormalQuat(q); @@ -1279,9 +1337,8 @@ void NormalQuat(float *q) } } -float *vectoquat( float *vec, short axis, short upflag) +void vectoquat(float *vec, short axis, short upflag, float *q) { - static float q1[4]; float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1; /* first rotate to axis */ @@ -1293,11 +1350,11 @@ float *vectoquat( float *vec, short axis, short upflag) x2= -vec[0] ; y2= -vec[1] ; z2= -vec[2]; } - q1[0]=1.0; - q1[1]=q1[2]=q1[3]= 0.0; + q[0]=1.0; + q[1]=q[2]=q[3]= 0.0; len1= (float)sqrt(x2*x2+y2*y2+z2*z2); - if(len1 == 0.0) return(q1); + if(len1 == 0.0) return; /* nasty! I need a good routine for this... * problem is a rotation of an Y axis to the negative Y-axis for example. @@ -1308,9 +1365,8 @@ float *vectoquat( float *vec, short axis, short upflag) nor[1]= -z2; nor[2]= y2; - if( fabs(y2)+fabs(z2)<0.0001 ) { + if(fabs(y2)+fabs(z2)<0.0001) nor[1]= 1.0; - } co= x2; } @@ -1319,9 +1375,8 @@ float *vectoquat( float *vec, short axis, short upflag) nor[1]= 0.0; nor[2]= -x2; - if( fabs(x2)+fabs(z2)<0.0001 ) { + if(fabs(x2)+fabs(z2)<0.0001) nor[2]= 1.0; - } co= y2; } @@ -1330,9 +1385,8 @@ float *vectoquat( float *vec, short axis, short upflag) nor[1]= x2; nor[2]= 0.0; - if( fabs(x2)+fabs(y2)<0.0001 ) { + if(fabs(x2)+fabs(y2)<0.0001) nor[0]= 1.0; - } co= z2; } @@ -1342,13 +1396,13 @@ float *vectoquat( float *vec, short axis, short upflag) 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; + q[0]= (float)cos(angle); + q[1]= nor[0]*si; + q[2]= nor[1]*si; + q[3]= nor[2]*si; if(axis!=upflag) { - QuatToMat3(q1, mat); + QuatToMat3(q, mat); fp= mat[2]; if(axis==0) { @@ -1371,10 +1425,8 @@ float *vectoquat( float *vec, short axis, short upflag) q2[2]= y2*si; q2[3]= z2*si; - QuatMul(q1,q2,q1); + QuatMul(q,q2,q); } - - return(q1); } void VecUpMat3old( float *vec, float mat[][3], short axis) @@ -1558,6 +1610,225 @@ void QuatAdd(float *result, float *quat1, float *quat2, float t) 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 scale= 1.0f/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 ******************************** */ @@ -1767,7 +2038,6 @@ void Mat4Ortho(float mat[][4]) void VecCopyf(float *v1, float *v2) { - v1[0]= v2[0]; v1[1]= v2[1]; v1[2]= v2[2]; @@ -1836,6 +2106,30 @@ void VecMulf(float *v1, float 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; @@ -2125,6 +2419,98 @@ short IsectLL2Df(float *v1, float *v2, float *v3, float *v4) return 0; } +/* +-1: colliniar + 1: intersection + +*/ +short IsectLLPt2Df(float x0,float y0,float x1,float y1, + float x2,float y2,float x3,float y3, float *xi,float *yi) + +{ + /* + this function computes the intersection of the sent lines + and returns the intersection point, note that the function assumes + the lines intersect. the function can handle vertical as well + as horizontal lines. note the function isn't very clever, it simply + applies the math, but we don't need speed since this is a + pre-processing step + */ + float c1,c2, // constants of linear equations + det_inv, // the inverse of the determinant of the coefficient + m1,m2; // the slopes of each line + /* + compute slopes, note the cludge for infinity, however, this will + be close enough + */ + if ( fabs( x1-x0 ) > 0.000001 ) + m1 = ( y1-y0 ) / ( x1-x0 ); + else + return -1; /*m1 = ( float ) 1e+10;*/ // close enough to infinity + + if ( fabs( x3-x2 ) > 0.000001 ) + m2 = ( y3-y2 ) / ( x3-x2 ); + else + return -1; /*m2 = ( float ) 1e+10;*/ // close enough to infinity + + if (fabs(m1-m2) < 0.000001) + return -1; /* paralelle lines */ + +// compute constants + + c1 = ( y0-m1*x0 ); + c2 = ( y2-m2*x2 ); + +// compute the inverse of the determinate + + det_inv = 1.0f / ( -m1 + m2 ); + +// use Kramers rule to compute xi and yi + + *xi= ( ( -c2 + c1 ) *det_inv ); + *yi= ( ( m2*c1 - m1*c2 ) *det_inv ); + + return 1; +} // end Intersect_Lines + +#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) +#define ISECT_EPSILON 1e-6 + +/* point in tri */ +int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2]) +{ + if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) && + (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) && + (SIDE_OF_LINE(v3,v1,pt)>=-ISECT_EPSILON)) + return 1; + else { + return 0; + } +} +/* point in quad - only convex quads */ +int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2]) +{ + if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) && + (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) && + (SIDE_OF_LINE(v3,v4,pt)>=-ISECT_EPSILON) && + (SIDE_OF_LINE(v4,v1,pt)>=-ISECT_EPSILON)) + return 1; + else + return 0; +} + + + + /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */ +#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1])) +#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0)) + +/** + * + * @param min + * @param max + * @param vec + */ void MinMax3(float *min, float *max, float *vec) { if(min[0]>vec[0]) min[0]= vec[0]; @@ -2225,7 +2611,53 @@ void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, f 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 *************** */ @@ -2391,6 +2823,15 @@ void VecRotToMat3( float *vec, float phi, float mat[][3]) } +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 */ @@ -2399,7 +2840,7 @@ void VecRotToQuat( float *vec, float phi, float *quat) quat[1]= vec[0]; quat[2]= vec[1]; quat[3]= vec[2]; - + if( Normalize(quat+1) == 0.0) { QuatOne(quat); } @@ -2427,6 +2868,22 @@ float VecAngle3(float *v1, float *v2, float *v3) return NormalizedVecAngle2(vec1, vec2) * 180.0/M_PI; } +float VecAngle3_2D(float *v1, float *v2, float *v3) +{ + float vec1[2], vec2[2]; + + vec1[0] = v2[0]-v1[0]; + vec1[1] = v2[1]-v1[1]; + + vec2[0] = v2[0]-v3[0]; + vec2[1] = v2[1]-v3[1]; + + Normalize2(vec1); + Normalize2(vec2); + + return NormalizedVecAngle2_2D(vec1, vec2) * 180.0/M_PI; +} + /* Return the shortest angle in degrees between the 2 vectors */ float VecAngle2(float *v1, float *v2) { @@ -2456,6 +2913,21 @@ float NormalizedVecAngle2(float *v1, float *v2) return 2.0f*saasin(VecLenf(v2, v1)/2.0); } +float NormalizedVecAngle2_2D(float *v1, float *v2) +{ + /* this is the same as acos(Inpf(v1, v2)), but more accurate */ + if (Inp2f(v1, v2) < 0.0f) { + float vec[2]; + + vec[0]= -v2[0]; + vec[1]= -v2[1]; + + return (float)M_PI - 2.0f*saasin(Vec2Lenf(vec, v1)/2.0f); + } + else + return 2.0f*saasin(Vec2Lenf(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]; @@ -2577,32 +3049,48 @@ void SizeToMat3( float *size, float mat[][3]) mat[2][0]= 0.0; } -void Mat3ToSize( float mat[][3], float *size) +void SizeToMat4( float *size, float mat[][4]) { - float vec[3]; - - VecCopyf(vec, mat[0]); - size[0]= Normalize(vec); - VecCopyf(vec, mat[1]); - size[1]= Normalize(vec); - VecCopyf(vec, mat[2]); - size[2]= Normalize(vec); + 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) { - float vec[3]; - + 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); +} - VecCopyf(vec, mat[0]); - size[0]= Normalize(vec); - VecCopyf(vec, mat[1]); - size[1]= Normalize(vec); - VecCopyf(vec, mat[2]); - size[2]= Normalize(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) @@ -2668,6 +3156,11 @@ float Vec2Lenf(float *v1, float *v2) return (float)sqrt(x*x+y*y); } +float Vec2Length(float *v) +{ + return (float)sqrt(v[0]*v[0] + v[1]*v[1]); +} + void Vec2Mulf(float *v1, float f) { v1[0]*= f; @@ -2947,6 +3440,8 @@ void tubemap(float x, float y, float z, float *u, float *v) len= sqrt(x*x+y*y); if(len>0) { *u = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0; + } else { + *v = *u = 0.0f; /* to avoid un-initialized variables */ } } @@ -2964,6 +3459,8 @@ void spheremap(float x, float y, float z, float *u, float *v) z/=len; *v = 1.0- saacos(z)/M_PI; + } else { + *v = *u = 0.0f; /* to avoid un-initialized variables */ } } @@ -3134,7 +3631,7 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4]) 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) +int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv) { float p[3], s[3], d[3], e1[3], e2[3], q[3]; @@ -3160,15 +3657,318 @@ int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], f v = f * Inpf(d, q); if ((v < 0.0)||((u + v) > 1.0)) return 0; + + if(uv) { + uv[0]= u; + uv[1]= v; + } return 1; } +/* Adapted from the paper by Kasper Fauerby */ +/* "Improved Collision detection and Response" */ +int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint) +{ + float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; + float a, b, c, d, e, x, y, z, t, t0, t1, radius2=radius*radius; + float elen2,edotv,edotbv,nordotv,vel2; + int embedded_in_plane=0, found_by_sweep=0; -/* -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 -*/ + VecSubf(e1,v1,v0); + VecSubf(e2,v2,v0); + VecSubf(vel,p2,p1); + +/*---test plane of tri---*/ + Crossf(nor,e1,e2); + Normalize(nor); + /* flip normal */ + if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f); + + a=Inpf(p1,nor)-Inpf(v0,nor); + + nordotv=Inpf(nor,vel); + + if ((nordotv > -0.000001) && (nordotv < 0.000001)) { + if(fabs(a)>=1.0f) + return 0; + else{ + embedded_in_plane=1; + t0=0.0f; + t1=1.0f; + } + } + else{ + t0=(radius-a)/nordotv; + t1=(-radius-a)/nordotv; + /* make t0<t1 */ + if(t0>t1){b=t1; t1=t0; t0=b;} + + if(t0>1.0f || t1<0.0f) return 0; + + /* clamp to [0,1] */ + t0=(t0<0.0f)?0.0f:((t0>1.0f)?1.0:t0); + t1=(t1<0.0f)?0.0f:((t1>1.0f)?1.0:t1); + } + +/*---test inside of tri---*/ + if(embedded_in_plane==0){ + /* plane intersection point */ + VecCopyf(point,vel); + VecMulf(point,t0); + VecAddf(point,point,p1); + VecCopyf(temp,nor); + VecMulf(temp,radius); + VecSubf(point,point,temp); + + /* is the point in the tri? */ + a=Inpf(e1,e1); + b=Inpf(e1,e2); + c=Inpf(e2,e2); + + VecSubf(temp,point,v0); + d=Inpf(temp,e1); + e=Inpf(temp,e2); + + x=d*c-e*b; + y=e*a-d*b; + z=x+y-(a*c-b*b); + + if(( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){ + *lambda=t0; + VecCopyf(ipoint,point); + return 1; + } + } + + *lambda=1.0f; +/*---test points---*/ + a=vel2=Inpf(vel,vel); + + /*v0*/ + VecSubf(temp,p1,v0); + b=2.0f*Inpf(vel,temp); + c=Inpf(temp,temp)-radius2; + d=b*b-4*a*c; + + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,v0); + found_by_sweep=1; + } + } + + /*v1*/ + VecSubf(temp,p1,v1); + b=2.0f*Inpf(vel,temp); + c=Inpf(temp,temp)-radius2; + d=b*b-4*a*c; + + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,v1); + found_by_sweep=1; + } + } + /*v2*/ + VecSubf(temp,p1,v2); + b=2.0f*Inpf(vel,temp); + c=Inpf(temp,temp)-radius2; + d=b*b-4*a*c; + + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,v2); + found_by_sweep=1; + } + } + +/*---test edges---*/ + /*e1*/ + VecSubf(bv,v0,p1); + elen2 = Inpf(e1,e1); + edotv = Inpf(e1,vel); + edotbv = Inpf(e1,bv); + + a=elen2*(-Inpf(vel,vel))+edotv*edotv; + b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); + c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; + d=b*b-4*a*c; + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + e=(edotv*t-edotbv)/elen2; + + if((e>=0.0f) && (e<=1.0f)){ + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,e1); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; + } + } + } + + /*e2*/ + /*bv is same*/ + elen2 = Inpf(e2,e2); + edotv = Inpf(e2,vel); + edotbv = Inpf(e2,bv); + + a=elen2*(-Inpf(vel,vel))+edotv*edotv; + b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); + c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; + d=b*b-4*a*c; + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + e=(edotv*t-edotbv)/elen2; + + if((e>=0.0f) && (e<=1.0f)){ + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,e2); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v0); + found_by_sweep=1; + } + } + } + + /*e3*/ + VecSubf(e3,v2,v1); + VecSubf(bv,v1,p1); + elen2 = Inpf(e3,e3); + edotv = Inpf(e3,vel); + edotbv = Inpf(e3,bv); + + a=elen2*(-Inpf(vel,vel))+edotv*edotv; + b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv); + c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv; + d=b*b-4*a*c; + if(d>=0.0f){ + if(d==0.0f) + t=-b/2*a; + else{ + z=sqrt(d); + x=(-b-z)*0.5/a; + y=(-b+z)*0.5/a; + t=x<y?x:y; + } + + e=(edotv*t-edotbv)/elen2; + + if((e>=0.0f) && (e<=1.0f)){ + if(t>0.0 && t < *lambda){ + *lambda=t; + VecCopyf(ipoint,e3); + VecMulf(ipoint,e); + VecAddf(ipoint,ipoint,v1); + found_by_sweep=1; + } + } + } + + return found_by_sweep; +} +int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda) +{ + float p[3], e1[3], e2[3]; + float u, v, f; + int a0=axis, a1=(axis+1)%3, a2=(axis+2)%3; + + //return LineIntersectsTriangle(p1,p2,v0,v1,v2,lambda); + + ///* first a simple bounding box test */ + //if(MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0; + //if(MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0; + //if(MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0; + //if(MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0; + + ///* then a full intersection test */ + + VecSubf(e1,v1,v0); + VecSubf(e2,v2,v0); + VecSubf(p,v0,p1); + + f= (e2[a1]*e1[a2]-e2[a2]*e1[a1]); + if ((f > -0.000001) && (f < 0.000001)) return 0; + + v= (p[a2]*e1[a1]-p[a1]*e1[a2])/f; + if ((v < 0.0)||(v > 1.0)) return 0; + + f= e1[a1]; + if((f > -0.000001) && (f < 0.000001)){ + f= e1[a2]; + if((f > -0.000001) && (f < 0.000001)) return 0; + u= (-p[a2]-v*e2[a2])/f; + } + else + u= (-p[a1]-v*e2[a1])/f; + + if ((u < 0.0)||((u + v) > 1.0)) return 0; + + *lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]); + + if ((*lambda < 0.0)||(*lambda > 1.0)) return 0; + + return 1; +} + +int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]) +{ + return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] && + min2[0]<max1[0] && min2[1]<max1[1] && min2[2]<max1[2]); +} + +/* 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; @@ -3180,6 +3980,7 @@ float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3]) 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]) { @@ -3189,7 +3990,156 @@ float lambda_cp_line(float p[3], float l1[3], float l2[3]) return(Inpf(u,h)/Inpf(u,u)); } +/* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */ +void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv) +{ + float x0,y0, x1,y1, wtot, v2d[2], w1, w2; + + /* used for paralelle lines */ + float pt3d[3], l1[3], l2[3], pt_on_line[3]; + + /* compute 2 edges of the quad intersection point */ + if (IsectLLPt2Df(v0[0],v0[1],v1[0],v1[1], v2[0],v2[1],v3[0],v3[1], &x0,&y0) == 1) { + /* the intersection point between the quad-edge intersection and the point in the quad we want the uv's for */ + /* should never be paralle !! */ + /*printf("\tnot paralelle 1\n");*/ + IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v3[0],v3[1], &x1,&y1); + + /* Get the weights from the new intersection point, to each edge */ + v2d[0] = x1-v0[0]; + v2d[1] = y1-v0[1]; + w1 = Vec2Length(v2d); + + v2d[0] = x1-v3[0]; /* some but for the other vert */ + v2d[1] = y1-v3[1]; + w2 = Vec2Length(v2d); + wtot = w1+w2; + /*w1 = w1/wtot;*/ + /*w2 = w2/wtot;*/ + uv[0] = w1/wtot; + } else { + /* lines are paralelle, lambda_cp_line_ex is 3d grrr */ + /*printf("\tparalelle1\n");*/ + pt3d[0] = pt[0]; + pt3d[1] = pt[1]; + pt3d[2] = l1[2] = l2[2] = 0.0f; + + l1[0] = v0[0]; l1[1] = v0[1]; + l2[0] = v1[0]; l2[1] = v1[1]; + lambda_cp_line_ex(pt3d, l1, l2, pt_on_line); + v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */ + v2d[1] = pt[1]-pt_on_line[1]; + w1 = Vec2Length(v2d); + + l1[0] = v2[0]; l1[1] = v2[1]; + l2[0] = v3[0]; l2[1] = v3[1]; + lambda_cp_line_ex(pt3d, l1, l2, pt_on_line); + v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */ + v2d[1] = pt[1]-pt_on_line[1]; + w2 = Vec2Length(v2d); + wtot = w1+w2; + uv[0] = w1/wtot; + } + + /* Same as above to calc the uv[1] value, alternate calculation */ + + if (IsectLLPt2Df(v0[0],v0[1],v3[0],v3[1], v1[0],v1[1],v2[0],v2[1], &x0,&y0) == 1) { /* was v0,v1 v2,v3 now v0,v3 v1,v2*/ + /* never paralle if above was not */ + /*printf("\tnot paralelle2\n");*/ + IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v1[0],v1[1], &x1,&y1);/* was v0,v3 now v0,v1*/ + + v2d[0] = x1-v0[0]; + v2d[1] = y1-v0[1]; + w1 = Vec2Length(v2d); + + v2d[0] = x1-v1[0]; + v2d[1] = y1-v1[1]; + w2 = Vec2Length(v2d); + wtot = w1+w2; + uv[1] = w1/wtot; + } else { + /* lines are paralelle, lambda_cp_line_ex is 3d grrr */ + /*printf("\tparalelle2\n");*/ + pt3d[0] = pt[0]; + pt3d[1] = pt[1]; + pt3d[2] = l1[2] = l2[2] = 0.0f; + + + l1[0] = v0[0]; l1[1] = v0[1]; + l2[0] = v3[0]; l2[1] = v3[1]; + lambda_cp_line_ex(pt3d, l1, l2, pt_on_line); + v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */ + v2d[1] = pt[1]-pt_on_line[1]; + w1 = Vec2Length(v2d); + + l1[0] = v1[0]; l1[1] = v1[1]; + l2[0] = v2[0]; l2[1] = v2[1]; + lambda_cp_line_ex(pt3d, l1, l2, pt_on_line); + v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */ + v2d[1] = pt[1]-pt_on_line[1]; + w2 = Vec2Length(v2d); + wtot = w1+w2; + uv[1] = w1/wtot; + } + /* may need to flip UV's here */ +} + +/* same as above but does tri's and quads, tri's are a bit of a hack */ +void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv) +{ + if (isquad) { + PointInQuad2DUV(v0, v1, v2, v3, pt, uv); + } + else { + /* not for quads, use for our abuse of LineIntersectsTriangleUV */ + float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda; + + p1_3d[0] = p2_3d[0] = uv[0]; + p1_3d[1] = p2_3d[1] = uv[1]; + p1_3d[2] = 1.0f; + p2_3d[2] = -1.0f; + v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0; + + /* generate a new fuv, (this is possibly a non optimal solution, + * since we only need 2d calculation but use 3d func's) + * + * this method makes an imaginary triangle in 2d space using the UV's from the derived mesh face + * Then find new uv coords using the fuv and this face with LineIntersectsTriangleUV. + * This means the new values will be correct in relation to the derived meshes face. + */ + Vec2Copyf(v0_3d, v0); + Vec2Copyf(v1_3d, v1); + Vec2Copyf(v2_3d, v2); + + /* Doing this in 3D is not nice */ + LineIntersectsTriangle(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv); + } +} + +/* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0<t<1 --> (x,v)(t) */ +void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v) +{ + float a[3],b[3]; + float t2= t*t; + float t3= t2*t; + /* cubic interpolation */ + a[0]= v1[0] + v2[0] + 2*(x1[0] - x2[0]); + a[1]= v1[1] + v2[1] + 2*(x1[1] - x2[1]); + a[2]= v1[2] + v2[2] + 2*(x1[2] - x2[2]); + + b[0]= -2*v1[0] - v2[0] - 3*(x1[0] - x2[0]); + b[1]= -2*v1[1] - v2[1] - 3*(x1[1] - x2[1]); + b[2]= -2*v1[2] - v2[2] - 3*(x1[2] - x2[2]); + + x[0]= a[0]*t3 + b[0]*t2 + v1[0]*t + x1[0]; + x[1]= a[1]*t3 + b[1]*t2 + v1[1]*t + x1[1]; + x[2]= a[2]*t3 + b[2]*t2 + v1[2]*t + x1[2]; + + v[0]= 3*a[0]*t2 + 2*b[0]*t + v1[0]; + v[1]= 3*a[1]*t2 + 2*b[1]*t + v1[1]; + v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2]; +} int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3]) { @@ -3246,46 +4196,75 @@ int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3]) 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 tmat[3][3]; + float rmat[3][3], smat[3][3], tmat[3][3]; - /* make base matrix */ - EulToMat3(eul, tmat); - - /* make new matrix */ + /* initialise new matrix */ Mat4One(mat); - mat[0][0] = tmat[0][0] * size[0]; - mat[0][1] = tmat[0][1] * size[1]; - mat[0][2] = tmat[0][2] * size[2]; - - mat[1][0] = tmat[1][0] * size[0]; - mat[1][1] = tmat[1][1] * size[1]; - mat[1][2] = tmat[1][2] * size[2]; + /* make rotation + scaling part */ + EulToMat3(eul, rmat); + SizeToMat3(size, smat); + Mat3MulMat3(tmat, rmat, smat); - mat[2][0] = tmat[2][0] * size[0]; - mat[2][1] = tmat[2][1] * size[1]; - mat[2][2] = tmat[2][2] * size[2]; + /* 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 eul[3]; + float rmat[3][3], smat[3][3], tmat[3][3]; - /* convert quaternion component to euler - * NOTE: not as good as using quat directly. Todo for later. - */ - QuatToEul(quat, eul); + /* initialise new matrix */ + Mat4One(mat); - /* make into matrix using exisiting code */ - LocEulSizeToMat4(mat, loc, eul, size); + /* 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/bpath.c b/source/blender/blenlib/intern/bpath.c new file mode 100644 index 00000000000..219ca424df8 --- /dev/null +++ b/source/blender/blenlib/intern/bpath.c @@ -0,0 +1,556 @@ +/** + * + * ***** 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 "BLI_bpath.h" +#include "BKE_global.h" +#include "DNA_ID.h" /* Library */ +#include "DNA_vfont_types.h" +#include "DNA_image_types.h" +#include "DNA_sound_types.h" +#include "DNA_scene_types.h" /* to get the current frame */ +#include <stdlib.h> +#include <string.h> + +#include "BKE_main.h" /* so we can access G.main->*.first */ +#include "BKE_image.h" /* so we can check the image's type */ + +#include "blendef.h" +#include "BKE_utildefines.h" + +/* for writing to a textblock */ +#include "BKE_text.h" +#include "BLI_blenlib.h" +#include "DNA_text_types.h" + +/* path/file handeling stuff */ +#ifndef WIN32 + #include <dirent.h> + #include <unistd.h> +#else + #include "BLI_winstuff.h" + #include <io.h> +#endif + +#include <sys/stat.h> +#include <sys/types.h> + +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +#define FILE_MAX 240 + + +/* TODO - BPATH_PLUGIN, BPATH_SEQ */ +enum BPathTypes { + BPATH_IMAGE = 0, + BPATH_SOUND, + BPATH_FONT, + BPATH_LIB, + + BPATH_DONE +}; + + +void BLI_bpathIterator_init( struct BPathIterator *bpi ) { + bpi->type = BPATH_IMAGE; + bpi->data = NULL; + BLI_bpathIterator_step(bpi); +} + +char* BLI_bpathIterator_getPath( struct BPathIterator *bpi) { + return bpi->path; +} +void BLI_bpathIterator_copyPathExpanded( struct BPathIterator *bpi, char *path_expanded) { + char *filepath, *libpath; + + filepath = BLI_bpathIterator_getPath(bpi); + libpath = BLI_bpathIterator_getLib(bpi); + + BLI_strncpy(path_expanded, filepath, FILE_MAXDIR*2); + + if (libpath) { /* check the files location relative to its library path */ + BLI_convertstringcode(path_expanded, libpath, G.scene->r.cfra); + } else { /* local data, use the blend files path */ + BLI_convertstringcode(path_expanded, G.sce, G.scene->r.cfra); + } +} +char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) { + return bpi->lib; +} +char* BLI_bpathIterator_getName( struct BPathIterator *bpi) { + return bpi->name; +} +int BLI_bpathIterator_getType( struct BPathIterator *bpi) { + return bpi->type; +} +int BLI_bpathIterator_getPathMaxLen( struct BPathIterator *bpi) { + return bpi->len; +} + +/* gets the first or the next image that has a path - not a viewer node or generated image */ +static struct Image *ima_getpath__internal(struct Image *ima, int step_next) { + if (ima==NULL) + return NULL; + + if (step_next) + ima = ima->id.next; + + while (ima) { + if (ima->packedfile==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) + break; + /* image is not a image with a path, skip it */ + ima = ima->id.next; + } + return ima; +} + +static struct VFont *vf_getpath__internal(struct VFont *vf, int step_next) { + if (vf==NULL) + return NULL; + + if (step_next) + vf = vf->id.next; + + while (vf) { + if (vf->packedfile==NULL && BLI_streq(vf->name, "<builtin>")==0) { + break; + } + + /* font with no path, skip it */ + vf = vf->id.next; + } + return vf; +} + +static struct bSound *snd_getpath__internal(struct bSound *snd, int step_next) { + if (snd==NULL) + return NULL; + + if (step_next) + snd = snd->id.next; + + while (snd) { + if (snd->packedfile==NULL) { + break; + } + + /* font with no path, skip it */ + snd = snd->id.next; + } + return snd; +} + +void BLI_bpathIterator_step( struct BPathIterator *bpi) { + while (bpi->type != BPATH_DONE) { + + if ((bpi->type) == BPATH_IMAGE) { + /*if (bpi->data) bpi->data = ((ID *)bpi->data)->next;*/ + if (bpi->data) bpi->data = ima_getpath__internal( (Image *)bpi->data, 1 ); /* must skip images that have no path */ + else bpi->data = ima_getpath__internal(G.main->image.first, 0); + + if (bpi->data) { + /* get the path info from this datatype */ + Image *ima = (Image *)bpi->data; + + bpi->lib = ima->id.lib ? ima->id.lib->filename : NULL; + bpi->path = ima->name; + bpi->name = ima->id.name+2; + bpi->len = sizeof(ima->name); + + /* we are done, advancing to the next item, this type worked fine */ + break; + + } else { + bpi->type+=1; /* advance to the next type */ + } + + + } else if ((bpi->type) == BPATH_SOUND) { + if (bpi->data) bpi->data = snd_getpath__internal( (bSound *)bpi->data, 1 ); /* must skip images that have no path */ + else bpi->data = snd_getpath__internal(G.main->sound.first, 0); + + if (bpi->data) { + /* get the path info from this datatype */ + bSound *snd = (bSound *)bpi->data; + + bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL; + bpi->path = snd->sample->name; + bpi->name = snd->id.name+2; + bpi->len = sizeof(snd->sample->name); + + /* we are done, advancing to the next item, this type worked fine */ + break; + } else { + bpi->type+=1; /* advance to the next type */ + } + + + } else if ((bpi->type) == BPATH_FONT) { + + if (bpi->data) bpi->data = vf_getpath__internal( (VFont *)bpi->data, 1 ); + else bpi->data = vf_getpath__internal( G.main->vfont.first, 0 ); + + if (bpi->data) { + /* get the path info from this datatype */ + VFont *vf = (VFont *)bpi->data; + + bpi->lib = vf->id.lib ? vf->id.lib->filename : NULL; + bpi->path = vf->name; + bpi->name = vf->id.name+2; + bpi->len = sizeof(vf->name); + + /* we are done, advancing to the next item, this type worked fine */ + break; + } else { + bpi->type+=1; /* advance to the next type */ + } + + + } else if ((bpi->type) == BPATH_LIB) { + + if (bpi->data) bpi->data = ((ID *)bpi->data)->next; + else bpi->data = G.main->library.first; + + if (bpi->data) { + /* get the path info from this datatype */ + Library *lib = (Library *)bpi->data; + + bpi->lib = NULL; + bpi->path = lib->name; + bpi->name = NULL; + bpi->len = sizeof(lib->name); + + /* we are done, advancing to the next item, this type worked fine */ + break; + } else { + bpi->type+=1; /* advance to the next type */ + } + } + } +} + +int BLI_bpathIterator_isDone( struct BPathIterator *bpi) { + return bpi->type==BPATH_DONE; +} + +/* include the path argument */ +static void bpathToText(Text *btxt, struct BPathIterator *bpi) +{ + char *name; + char path_expanded[FILE_MAXDIR*2]; + + switch(BLI_bpathIterator_getType(bpi)) { + case BPATH_IMAGE: + txt_insert_buf( btxt, "Image \"" ); + break; + case BPATH_SOUND: + txt_insert_buf( btxt, "Sound \"" ); + break; + case BPATH_FONT: + txt_insert_buf( btxt, "Font \"" ); + break; + case BPATH_LIB: + txt_insert_buf( btxt, "Library \"" ); + break; + default: + txt_insert_buf( btxt, "Unknown \"" ); + break; + } + + name = BLI_bpathIterator_getName(bpi); + + if (name) { + txt_insert_buf( btxt, name ); + } + txt_insert_buf( btxt, "\" " ); + + BLI_bpathIterator_copyPathExpanded(bpi, path_expanded); + + txt_insert_buf( btxt, path_expanded ); + txt_insert_buf( btxt, "\n" ); + txt_move_eof( btxt, 0 ); +} + +/* high level function */ +void checkMissingFiles( char *txtname ) { + Text *btxt = NULL; + struct BPathIterator bpi; + + /* be sure there is low chance of the path being too short */ + char filepath_expanded[FILE_MAXDIR*2]; + char *filepath, *libpath; + int files_missing = 0; + + BLI_bpathIterator_init(&bpi); + while (!BLI_bpathIterator_isDone(&bpi)) { + filepath = BLI_bpathIterator_getPath(&bpi); + libpath = BLI_bpathIterator_getLib(&bpi); + + BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded ); + + if (!BLI_exists(filepath_expanded)) { + if (!btxt) { + btxt = add_empty_text( "missing_files.log" ); + if (txtname) { + BLI_strncpy(txtname, btxt->id.name+2, 24); + } + } + bpathToText(btxt, &bpi); + files_missing = 1; + } + BLI_bpathIterator_step(&bpi); + } +} + +/* dont log any errors at the moment, should probably do this */ +void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked) { + struct BPathIterator bpi; + char *filepath, *libpath; + + /* be sure there is low chance of the path being too short */ + char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE]; + + Text *btxt = NULL; + + *tot = *changed = *failed = *linked = 0; + + BLI_bpathIterator_init(&bpi); + while (!BLI_bpathIterator_isDone(&bpi)) { + filepath = BLI_bpathIterator_getPath(&bpi); + libpath = BLI_bpathIterator_getLib(&bpi); + + if(strncmp(filepath, "//", 2)) { + if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */ + (*linked)++; + } else { /* local data, use the blend files path */ + BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative)); + /* Important BLI_cleanup_dir runs before the path is made relative + * because it wont work for paths that start with "//../" */ + BLI_cleanup_file(G.sce, filepath_relative); /* fix any /foo/../foo/ */ + BLI_makestringcode(G.sce, filepath_relative); + /* be safe and check the length */ + if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) { + if (!btxt) { + btxt = add_empty_text( "missing_no_rel.log" ); + if (txtname) { + BLI_strncpy(txtname, btxt->id.name+2, 24); + } + } + bpathToText(btxt, &bpi); + (*failed)++; + } else { + if(strncmp(filepath_relative, "//", 2)==0) { + strcpy(filepath, filepath_relative); + (*changed)++; + } else { + if (!btxt) { + btxt = add_empty_text( "missing_no_rel.log" ); + if (txtname) { + BLI_strncpy(txtname, btxt->id.name+2, 24); + } + } + bpathToText(btxt, &bpi); + (*failed)++; + } + } + } + } + BLI_bpathIterator_step(&bpi); + (*tot)++; + } +} + +/* dont log any errors at the moment, should probably do this - + * Verry similar to makeFilesRelative - keep in sync! */ +void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked) { + struct BPathIterator bpi; + char *filepath, *libpath; + + /* be sure there is low chance of the path being too short */ + char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE]; + + Text *btxt = NULL; + + *tot = *changed = *failed = *linked = 0; + + BLI_bpathIterator_init(&bpi); + while (!BLI_bpathIterator_isDone(&bpi)) { + filepath = BLI_bpathIterator_getPath(&bpi); + libpath = BLI_bpathIterator_getLib(&bpi); + + if(strncmp(filepath, "//", 2)==0) { + if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */ + (*linked)++; + } else { /* get the expanded path and check it is relative or too long */ + BLI_bpathIterator_copyPathExpanded( &bpi, filepath_absolute ); + BLI_cleanup_file(G.sce, filepath_absolute); /* fix any /foo/../foo/ */ + /* to be safe, check the length */ + if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_absolute)) { + if (!btxt) { + btxt = add_empty_text( "missing_no_abs.log" ); + if (txtname) { + BLI_strncpy(txtname, btxt->id.name+2, 24); + } + } + bpathToText(btxt, &bpi); + (*failed)++; + } else { + if(strncmp(filepath_absolute, "//", 2)) { + strcpy(filepath, filepath_absolute); + (*changed)++; + } else { + if (!btxt) { + btxt = add_empty_text( "missing_no_abs.log" ); + if (txtname) { + BLI_strncpy(txtname, btxt->id.name+2, 24); + } + } + bpathToText(btxt, &bpi); + (*failed)++; + } + } + } + } + BLI_bpathIterator_step(&bpi); + (*tot)++; + } +} + + +/* find this file recursively, use the biggest file so thumbnails dont get used by mistake + - dir: subdir to search + - filename: set this filename + - filesize: filesize for the file +*/ +#define MAX_RECUR 16 +static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth) +{ + /* file searching stuff */ + DIR *dir; + struct dirent *de; + struct stat status; + char path[FILE_MAX]; + int size; + + dir = opendir(dirname); + + if (dir==0) + return 0; + + if (*filesize == -1) + *filesize = 0; /* dir opened fine */ + + while ((de = readdir(dir)) != NULL) { + + if (strncmp(".", de->d_name, 2)==0 || strncmp("..", de->d_name, 3)==0) + continue; + + BLI_join_dirfile(path, dirname, de->d_name); + + if (stat(path, &status) != 0) + continue; /* cant stat, dont bother with this file, could print debug info here */ + + if (S_ISREG(status.st_mode)) { /* is file */ + if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */ + /* open the file to read its size */ + size = BLI_filepathsize(path); + if ((size > 0) && (size > *filesize)) { /* find the biggest file */ + *filesize = size; + BLI_strncpy(filename_new, path, FILE_MAX); + } + } + } else if (S_ISDIR(status.st_mode)) { /* is subdir */ + if (*recur_depth <= MAX_RECUR) { + (*recur_depth)++; + findFileRecursive(filename_new, path, filename, filesize, recur_depth); + (*recur_depth)--; + } + } + } + closedir(dir); + return 1; +} + +/* high level function - call from fileselector */ +void findMissingFiles(char *str) { + struct BPathIterator bpi; + + /* be sure there is low chance of the path being too short */ + char filepath_expanded[FILE_MAXDIR*2]; + char *filepath, *libpath; + int filesize, recur_depth; + + char dirname[FILE_MAX], filename[FILE_MAX], filename_new[FILE_MAX], dummyname[FILE_MAX]; + + BLI_split_dirfile(str, dirname, dummyname); + + BLI_bpathIterator_init(&bpi); + + while (!BLI_bpathIterator_isDone(&bpi)) { + filepath = BLI_bpathIterator_getPath(&bpi); + libpath = BLI_bpathIterator_getLib(&bpi); + + if (libpath==NULL) { + + BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded ); + + if (!BLI_exists(filepath_expanded)) { + /* can the dir be opened? */ + filesize = -1; + recur_depth = 0; + BLI_split_dirfile(filepath, dummyname, filename); /* the file to find */ + + findFileRecursive(filename_new, dirname, filename, &filesize, &recur_depth); + if (filesize == -1) { /* could not open dir */ + printf("Could not open dir \"%s\"\n", dirname); + return; + } + + if (filesize > 0) { + + if (BLI_bpathIterator_getPathMaxLen( &bpi ) < strlen(filename_new)) { + printf("cannot set path \"%s\" too long!", filename_new); + } else { + /* copy the found path into the old one */ + if (G.relbase_valid) + BLI_makestringcode(G.sce, filename_new); + + strcpy( BLI_bpathIterator_getPath( &bpi ), filename_new ); + } + } + } + } + BLI_bpathIterator_step(&bpi); + } +} diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index fcea30982bd..e5b11412aa1 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -79,7 +79,7 @@ char *first_slash(char *string) { else return fbslash; } -char *BLI_last_slash(char *string) { +char *BLI_last_slash(const char *string) { char *lfslash, *lbslash; lfslash= strrchr(string, '/'); @@ -92,6 +92,39 @@ char *BLI_last_slash(char *string) { else return lfslash; } +/* adds a slash if there isnt one there alredy */ +void BLI_add_slash(char *string) { + int len = strlen(string); +#ifdef WIN32 + if (string[len-1]!='\\') { + string[len] = '\\'; + string[len+1] = '\0'; + } +#else + if (string[len-1]!='/') { + string[len] = '/'; + string[len+1] = '\0'; + } +#endif +} + +/* removes a slash if there is one */ +void BLI_del_slash(char *string) { + int len = strlen(string); + while (len) { +#ifdef WIN32 + if (string[len-1]=='\\') { +#else + if (string[len-1]=='/') { +#endif + string[len-1] = '\0'; + len--; + } else { + break; + } + } +} + /* 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 @@ -140,6 +173,23 @@ int BLI_is_writable(char *filename) } } +int BLI_touch(const char *file) +{ + FILE *f = fopen(file,"r+b"); + if (f != NULL) { + char c = getc(f); + rewind(f); + putc(c,f); + } else { + f = fopen(file,"wb"); + } + if (f) { + fclose(f); + return 1; + } + return 0; +} + #ifdef WIN32 static char str[MAXPATHLEN+12]; @@ -161,12 +211,6 @@ int BLI_delete(char *file, int dir, int recursive) { 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; @@ -296,17 +340,6 @@ int BLI_delete(char *file, int dir, int recursive) 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); diff --git a/source/blender/blenlib/intern/fnmatch.c b/source/blender/blenlib/intern/fnmatch.c new file mode 100644 index 00000000000..54114ad3448 --- /dev/null +++ b/source/blender/blenlib/intern/fnmatch.c @@ -0,0 +1,250 @@ +/* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc. + + 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, 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. */ + +#ifdef WIN32 + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include <errno.h> +#include <BLI_fnmatch.h> +#include <ctype.h> + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +# ifndef errno +extern int errno; +# endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +fnmatch (const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (FOLD (*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if ((flags & FNM_FILE_NAME) && *n == '/') + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') + { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD (c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD (*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } + + cstart = cend = FOLD (cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD (cend); + + c = *p++; + } + + if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD (*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#else + +static void BLI_FNMATCH_C_IS_EMPTY_FOR_UNIX(void) +{ + /*intentionally empty*/ +} + +#endif /* WIN32 */ + + diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c index 941bf4204a8..1fcb6653dc9 100644 --- a/source/blender/blenlib/intern/psfont.c +++ b/source/blender/blenlib/intern/psfont.c @@ -1949,7 +1949,7 @@ static VFontData *objfnt_to_vfontdata(objfnt *fnt) chardesc *cd; short *_data, *data; int a, i, count, stop, ready, meet; - short first[2], last[2]; + short first[2]={0,0}, last[2]={0,0}; struct Nurb *nu; struct BezTriple *bezt, *bez2; float scale, dx, dy; diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index df01288aab8..71df0ede037 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -116,6 +116,14 @@ void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) free(temp); } +void rng_skip(RNG *rng, int n) +{ + int i; + + for(i=0; i<n; i++) + rng_getInt(rng); +} + /***/ static RNG theBLI_rng = {0}; diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index a6b91bf489d..9d70d85939e 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -50,7 +50,9 @@ #include <time.h> #include <sys/stat.h> -#if !defined(linux) && (defined(__sgi) || defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__)) +#if defined (__sun__) || defined (__sun) +#include <sys/statvfs.h> /* Other modern unix os's should probably use this also */ +#elif !defined(linux) && (defined(__sgi) || defined(__sparc) || defined(__sparc__)) #include <sys/statfs.h> #endif @@ -179,13 +181,21 @@ double BLI_diskfree(char *dir) return (double) (freec*bytesps*sectorspc); #else - struct statfs disk; - char name[100],*slash; - +#if defined (__sun__) || defined (__sun) + struct statvfs disk; +#else + struct statfs disk; +#endif + char name[FILE_MAXDIR],*slash; + int len = strlen(dir); + + if (len >= FILE_MAXDIR) /* path too long */ + return -1; + strcpy(name,dir); - if(strlen(name)){ + if(len){ slash = strrchr(name,'/'); if (slash) slash[1] = 0; } else strcpy(name,"/"); @@ -196,12 +206,12 @@ double BLI_diskfree(char *dir) #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); - } +#if defined (__sun__) || defined (__sun) + if (statvfs(name, &disk)) return(-1); +#elif !defined(linux) && (defined (__sgi) || defined(__sparc) || defined(__sparc__)) + /* WARNING - This may not be supported by geeneric unix os's - Campbell */ + if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1); #endif return ( ((double) disk.f_bsize) * ((double) disk.f_bfree)); @@ -326,11 +336,11 @@ void BLI_adddirstrings() char size[250]; static char * types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; int num, mode; - int num1, num2, num3, num4; + off_t num1, num2, num3, num4, num5; #ifdef WIN32 __int64 st_size; #else - long long st_size; + off_t st_size; #endif struct direntry * file; @@ -392,7 +402,7 @@ void BLI_adddirstrings() * 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; + st_size= (off_t)files[num].s.st_size; num1= st_size % 1000; num2= st_size/1000; @@ -401,11 +411,15 @@ void BLI_adddirstrings() 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); + num5= st_size/(1000000000000LL); + num5= num5 % 1000; + + if(num5) + sprintf(files[num].size, "%1d %03d %03d %03d K", (int)num5, (int)num4, (int)num3, (int)num2); + else if(num4) sprintf(files[num].size, "%3d %03d %03d %03d", (int)num4, (int)num3, (int)num2, (int)num1); + else if(num3) sprintf(files[num].size, "%7d %03d %03d", (int)num3, (int)num2, (int)num1); + else if(num2) sprintf(files[num].size, "%11d %03d", (int)num2, (int)num1); + else if(num1) sprintf(files[num].size, "%15d", (int)num1); else sprintf(files[num].size, "0"); strftime(datum, 32, "%d-%b-%y %H:%M", tm); @@ -469,6 +483,17 @@ int BLI_filesize(int file) return (buf.st_size); } +int BLI_filepathsize(const char *path) +{ + int size, file = open(path, O_BINARY|O_RDONLY); + + if (file <= 0) + return -1; + + size = BLI_filesize(file); + close(file); + return size; +} int BLI_exist(char *name) diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index cb10185386a..f4a44b3a0db 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -38,6 +38,15 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" +/* for checking system threads - BLI_system_thread_count */ +#ifdef WIN32 +#include "Windows.h" +#elif defined(__APPLE__) +#include <sys/types.h> +#include <sys/sysctl.h> +#else +#include <unistd.h> +#endif /* ********** basic thread control API ************ @@ -109,22 +118,26 @@ static void BLI_unlock_malloc_thread(void) pthread_mutex_unlock(&_malloc_lock); } +/* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) + problem otherwise: scene render will kill of the mutex! +*/ + void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot) { int a; - if(threadbase==NULL) - return; - threadbase->first= threadbase->last= NULL; + if(threadbase != NULL && tot > 0) { + threadbase->first= threadbase->last= NULL; - if(tot>RE_MAX_THREAD) tot= RE_MAX_THREAD; - else if(tot<1) tot= 1; + 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; + 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); @@ -190,12 +203,14 @@ 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); + if (threadbase) { + for(tslot= threadbase->first; tslot; tslot= tslot->next) { + if(tslot->avail==0) { + pthread_join(tslot->pthread, NULL); + } } + BLI_freelistN(threadbase); } - BLI_freelistN(threadbase); thread_levels--; if(thread_levels==0) @@ -218,4 +233,34 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_custom1_lock); } +/* how many threads are native on this system? */ +int BLI_system_thread_count( void ) +{ + int t; +#ifdef WIN32 + SYSTEM_INFO info; + GetSystemInfo(&info); + t = (int) info.dwNumberOfProcessors; +#else +# ifdef __APPLE__ + int mib[2]; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(t); + sysctl(mib, 2, &t, &len, NULL, 0); +# else + t = (int)sysconf(_SC_NPROCESSORS_ONLN); +# endif +#endif + + if (t>RE_MAX_THREAD) + return RE_MAX_THREAD; + if (t<1) + return 1; + + return t; +} + /* eof */ diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index cfce8e3dafa..51691499ba8 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -44,8 +44,10 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "DNA_listBase.h" +#include "DNA_userdef_types.h" + +#include "BLI_blenlib.h" #include "BLI_storage.h" #include "BLI_storage_types.h" #include "BLI_dynamiclist.h" @@ -84,37 +86,39 @@ #include <CoreFoundation/CoreFoundation.h> #endif +#ifdef __linux__ +#include "binreloc.h" +#endif + /* local */ static int add_win32_extension(char *name); /* implementation */ -/* Ripped this from blender.c - */ +/* Ripped this from blender.c */ void addlisttolist(ListBase *list1, ListBase *list2) { + if (list2->first==0) return; - if(list2->first==0) return; - - if(list1->first==0) { + if (list1->first==0) { list1->first= list2->first; list1->last= list2->last; } else { - ((struct Link *)list1->last)->next= list2->first; - ((struct Link *)list2->first)->prev= list1->last; + ((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 *staart, unsigned short *numlen) +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); + len2 = len = strlen(string); if (len > 6) { if (BLI_strncasecmp(string + len - 6, ".blend", 6) == 0) len -= 6; @@ -125,7 +129,6 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen) if (BLI_strncasecmp(string + len - 9, ".blend.gz", 9) == 0) len -= 9; } - if (len == len2) { if (len > 4) { /* handle .jf0 en .jf1 for jstreams */ @@ -143,7 +146,7 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen) } } - for (i = len - 1; i >= 0; i--){ + for (i = len - 1; i >= 0; i--) { if (string[i] == '/') break; if (isdigit(string[i])) { if (found){ @@ -155,12 +158,12 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen) found = 1; } } - else{ + else { if (found) break; } } if (found){ - if (staart) strcpy(staart,&string[nume+1]); + if (start) strcpy(start,&string[nume+1]); if (kop) { strcpy(kop,string); kop[nums]=0; @@ -168,7 +171,7 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen) if (numlen) *numlen = nume-nums+1; return ((int)atoi(&(string[nums]))); } - if (staart) strcpy(staart, string + len); + if (start) strcpy(start, string + len); if (kop) { strncpy(kop, string, len); kop[len] = 0; @@ -178,7 +181,7 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen) } -void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, int pic) +void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic) { char numstr[10]=""; unsigned short len,i; @@ -187,17 +190,17 @@ void BLI_stringenc(char *string, char *kop, char *staart, unsigned short numlen, if (pic>0 || numlen==4) { len= sprintf(numstr,"%d",pic); - + for(i=len;i<numlen;i++){ strcat(string,"0"); } strcat(string,numstr); } - strcat(string,staart); + strcat(string, start); } -void BLI_newname(char * name, int add) +void BLI_newname(char *name, int add) { char head[128], tail[128]; int pic; @@ -215,38 +218,111 @@ void BLI_newname(char * name, int add) pic += add; - if(digits==4 && pic<0) pic= 0; + if (digits==4 && pic<0) pic= 0; BLI_stringenc(name, head, tail, digits, pic); } +/* little helper macro for BLI_uniquename */ +#ifndef GIVE_STRADDR + #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset ) +#endif + +/* Generic function to set a unique name. It is only designed to be used in situations + * where the name is part of the struct, and also that the name is at most 128 chars long. + * + * For places where this is used, see constraint.c for example... + * + * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h + * len: maximum length of string (to prevent overflows, etc.) + * defname: the name that should be used by default if none is specified already + */ +void BLI_uniquename(ListBase *list, void *vlink, char defname[], short name_offs, short len) +{ + Link *link; + char tempname[128]; + int number = 1, exists = 0; + char *dot; + + /* Make sure length can be handled */ + if ((len < 0) || (len > 128)) + return; + + /* See if we are given an empty string */ + if (ELEM(NULL, vlink, defname)) + return; + + if (GIVE_STRADDR(vlink, name_offs) == '\0') { + /* give it default name first */ + BLI_strncpy(GIVE_STRADDR(vlink, name_offs), defname, len); + } + + /* See if we even need to do this */ + if (list == NULL) + return; + + for (link = list->first; link; link= link->next) { + if (link != vlink) { + if (!strcmp(GIVE_STRADDR(link, name_offs), GIVE_STRADDR(vlink, name_offs))) { + exists = 1; + break; + } + } + } + if (exists == 0) + return; + + /* Strip off the suffix */ + dot = strchr(GIVE_STRADDR(vlink, name_offs), '.'); + if (dot) + *dot=0; + + for (number = 1; number <= 999; number++) { + BLI_snprintf(tempname, 128, "%s.%03d", GIVE_STRADDR(vlink, name_offs), number); + + exists = 0; + for (link= list->first; link; link= link->next) { + if (vlink != link) { + if (!strcmp(GIVE_STRADDR(link, name_offs), tempname)) { + exists = 1; + break; + } + } + } + if (exists == 0) { + BLI_strncpy(GIVE_STRADDR(vlink, name_offs), tempname, len); + return; + } + } +} + void BLI_addhead(ListBase *listbase, void *vlink) { - struct Link *link= vlink; + Link *link= vlink; - if (link == 0) return; - if (listbase == 0) return; + if (link == NULL) return; + if (listbase == NULL) return; link->next = listbase->first; - link->prev = 0; + link->prev = NULL; - if (listbase->first) ((struct Link *)listbase->first)->prev = link; - if (listbase->last == 0) listbase->last = link; + 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) { - struct Link *link= vlink; + Link *link= vlink; - if (link == 0) return; - if (listbase == 0) return; + if (link == NULL) return; + if (listbase == NULL) return; - link->next = 0; + link->next = NULL; link->prev = listbase->last; - if (listbase->last) ((struct Link *)listbase->last)->next = link; + if (listbase->last) ((Link *)listbase->last)->next = link; if (listbase->first == 0) listbase->first = link; listbase->last = link; } @@ -254,10 +330,10 @@ void BLI_addtail(ListBase *listbase, void *vlink) void BLI_remlink(ListBase *listbase, void *vlink) { - struct Link *link= vlink; + Link *link= vlink; - if (link == 0) return; - if (listbase == 0) return; + if (link == NULL) return; + if (listbase == NULL) return; if (link->next) link->next->prev = link->prev; if (link->prev) link->prev->next = link->next; @@ -269,10 +345,10 @@ void BLI_remlink(ListBase *listbase, void *vlink) void BLI_freelinkN(ListBase *listbase, void *vlink) { - struct Link *link= vlink; + Link *link= vlink; - if (link == 0) return; - if (listbase == 0) return; + if (link == NULL) return; + if (listbase == NULL) return; BLI_remlink(listbase,link); MEM_freeN(link); @@ -281,19 +357,23 @@ void BLI_freelinkN(ListBase *listbase, void *vlink) void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink) { - struct Link *prevlink= vprevlink, *newlink= vnewlink; + Link *prevlink= vprevlink; + Link *newlink= vnewlink; /* newlink comes after prevlink */ - - if (newlink == 0) return; - if (listbase == 0) return; - - if(listbase->first==0) { /* empty list */ + if (newlink == NULL) return; + if (listbase == NULL) return; + + /* empty list */ + if (listbase->first == NULL) { + listbase->first= newlink; listbase->last= newlink; return; } - if (prevlink== 0) { /* insert before first element */ + + /* insert before first element */ + if (prevlink == NULL) { newlink->next= listbase->first; newlink->prev= 0; newlink->next->prev= newlink; @@ -301,96 +381,170 @@ void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink) return; } - if (listbase->last== prevlink) /* at end of list */ + /* 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; + if (newlink->next) newlink->next->prev= newlink; newlink->prev= prevlink; } -void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) +/* 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; current = next ) + { + next = current->next; + previous = current->prev; + + BLI_remlink(listbase, current); + + while(previous && cmp(previous, current) == 1) + { + previous = previous->prev; + } + + BLI_insertlinkafter(listbase, previous, current); + } + } +} + +void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) { - struct Link *nextlink= vnextlink, *newlink= vnewlink; + Link *prevlink= vprevlink; + Link *newlink= vnewlink; /* newlink before nextlink */ + if (newlink == NULL) return; + if (listbase == NULL) return; - if (newlink == 0) return; - if (listbase == 0) 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; +} - if(listbase->first==0) { /* empty list */ +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; } - if (nextlink== 0) { /* insert at end of list */ + + /* insert at end of list */ + if (nextlink == NULL) { newlink->prev= listbase->last; newlink->next= 0; - ((struct Link *)listbase->last)->next= newlink; + ((Link *)listbase->last)->next= newlink; listbase->last= newlink; return; } - if (listbase->first== nextlink) /* at beginning of list */ + /* 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; + if (newlink->prev) newlink->prev->next= newlink; } void BLI_freelist(ListBase *listbase) { - struct Link *link,*next; + Link *link, *next; - if (listbase == 0) return; + if (listbase == NULL) + return; + link= listbase->first; - while(link) { + while (link) { next= link->next; free(link); link= next; } - listbase->first=0; - listbase->last=0; + + listbase->first= NULL; + listbase->last= NULL; } void BLI_freelistN(ListBase *listbase) { - struct Link *link,*next; + Link *link, *next; - if (listbase == 0) return; + if (listbase == NULL) return; + link= listbase->first; - while(link) { + while (link) { next= link->next; MEM_freeN(link); link= next; } - listbase->first=0; - listbase->last=0; + + listbase->first= NULL; + listbase->last= NULL; } int BLI_countlist(ListBase *listbase) { - Link * link; + Link *link; int count = 0; - if (listbase){ + if (listbase) { link = listbase->first; - while(link) { + while (link) { count++; link= link->next; } } - return(count); + return count; } -void * BLI_findlink(ListBase *listbase, int number) +void *BLI_findlink(ListBase *listbase, int number) { - Link * link = NULL; + Link *link = NULL; if (number >= 0) { link = listbase->first; @@ -400,7 +554,27 @@ void * BLI_findlink(ListBase *listbase, int number) } } - return (link); + 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; } /*=====================================================================================*/ @@ -626,14 +800,14 @@ void BLI_dlist_reinit(DynamicList *dlist) /*=====================================================================================*/ -char *BLI_strdupn(char *str, int len) { +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(char *str) { +char *BLI_strdup(const char *str) { return BLI_strdupn(str, strlen(str)); } @@ -682,6 +856,16 @@ int BLI_strcaseeq(char *a, char *b) { void BLI_cleanup_dir(const char *relabase, char *dir) { + BLI_cleanup_file(relabase, dir); +#ifdef WIN32 + strcat(dir, "\\"); +#else + strcat(dir, "/"); +#endif +} + +void BLI_cleanup_file(const char *relabase, char *dir) +{ short a; char *start, *eind; @@ -719,9 +903,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir) dir[a] = 0; } } - - strcat(dir, "\\"); -#else +#else if(dir[0]=='.') { /* happens, for example in FILE_MAIN */ dir[0]= '/'; dir[1]= 0; @@ -755,8 +937,6 @@ void BLI_cleanup_dir(const char *relabase, char *dir) if (a<=0) break; } } - - strcat(dir, "/"); #endif } @@ -922,6 +1102,7 @@ int BLI_convertstringcode(char *path, const char *basepath, int framenum) return wasrelative; } +/* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { char *lslash= BLI_last_slash(di); @@ -1167,35 +1348,37 @@ int BLI_testextensie(const char *str, const char *ext) } - -void BLI_split_dirfile(const char *string, char *dir, char *file) +/* warning, can modify 'string' */ +void BLI_split_dirfile(char *string, char *dir, char *file) { int a; #ifdef WIN32 int sl; short is_relative = 0; + char path[FILE_MAX]; #endif dir[0]= 0; file[0]= 0; #ifdef WIN32 - BLI_char_switch(string, '/', '\\'); /* make sure we have a valid path format */ - sl = strlen(string); + BLI_strncpy(path, string, FILE_MAX); + BLI_char_switch(path, '/', '\\'); /* make sure we have a valid path format */ + sl = strlen(path); 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); + if (path[0] == '/' || path[0] == '\\') { + BLI_strncpy(dir, path, FILE_MAXDIR); + if (sl > 1 && path[0] == '\\' && path[1] == '\\') is_relative = 1; + } else if (sl > 2 && path[1] == ':' && path[2] == '\\') { + BLI_strncpy(dir, path, FILE_MAXDIR); } else { BLI_getwdN(dir); strcat(dir,"\\"); - strcat(dir,string); - BLI_strncpy(string,dir,FILE_MAXDIR+FILE_MAXFILE); + strcat(dir,path); + BLI_strncpy(path,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 @@ -1203,7 +1386,7 @@ void BLI_split_dirfile(const char *string, char *dir, char *file) if(a>=4 && dir[a-1]=='\\') dir[a-1] = 0; if (is_relative) { - printf("WARNING: BLI_split_dirfile needs absolute dir"); + printf("WARNING: BLI_split_dirfile needs absolute dir\n"); } else { BLI_make_exist(dir); @@ -1214,18 +1397,18 @@ void BLI_split_dirfile(const char *string, char *dir, char *file) /* 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); + len = FILE_MAXFILE - strlen(path); if (len < 0) - BLI_strncpy(file,string + abs(len),FILE_MAXFILE); + BLI_strncpy(file,path + abs(len),FILE_MAXFILE); else - BLI_strncpy(file,string,FILE_MAXFILE); + BLI_strncpy(file,path,FILE_MAXFILE); - if (strrchr(string,'\\')){ - BLI_strncpy(file,strrchr(string,'\\')+1,FILE_MAXFILE); + if (strrchr(path,'\\')) { + BLI_strncpy(file,strrchr(path,'\\')+1,FILE_MAXFILE); } - - if (a = strlen(dir)) { + + if ( (a = strlen(dir)) ) { if (dir[a-1] != '\\') strcat(dir,"\\"); } } @@ -1233,7 +1416,7 @@ void BLI_split_dirfile(const char *string, char *dir, char *file) a = strlen(dir) - 1; while(a>0 && dir[a] != '\\') a--; dir[a + 1] = 0; - BLI_strncpy(file, string + strlen(dir),FILE_MAXFILE); + BLI_strncpy(file, path + strlen(dir),FILE_MAXFILE); } } @@ -1288,12 +1471,20 @@ 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; + + /* only add seperator if needed */ #ifdef WIN32 - string[sl_dir] = '\\'; + if (string[sl_dir-1] != '\\') { + string[sl_dir] = '\\'; + sl_dir++; + } #else - string[sl_dir] = '/'; + if (string[sl_dir-1] != '/') { + string[sl_dir] = '/'; + sl_dir++; + } #endif - sl_dir++; + if (sl_dir <FILE_MAX) { BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir); } @@ -1340,10 +1531,10 @@ static int add_win32_extension(char *name) return (retval); } -void BLI_where_am_i(char *fullname, char *name) +void BLI_where_am_i(char *fullname, const char *name) { char filename[FILE_MAXDIR+FILE_MAXFILE]; - char *path, *temp; + char *path = NULL, *temp; int len; #ifdef _WIN32 char *seperator = ";"; @@ -1353,6 +1544,17 @@ void BLI_where_am_i(char *fullname, char *name) char *slash = "/"; #endif + +#ifdef __linux__ + /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */ + path = br_find_exe( NULL ); + if (path) { + strcpy(fullname, path); + return; + } +#endif + + /* unix and non linux */ if (name && fullname && strlen(name)) { strcpy(fullname, name); if (name[0] == '.') { @@ -1413,6 +1615,47 @@ void BLI_where_am_i(char *fullname, char *name) } } +void BLI_where_is_temp(char *fullname, int usertemp) +{ + fullname[0] = '\0'; + + if (usertemp && BLI_exists(U.tempdir)) { + strcpy(fullname, U.tempdir); + } + + +#ifdef WIN32 + if (fullname[0] == '\0') { + char *tmp = getenv("TEMP"); /* Windows */ + if (tmp && BLI_exists(tmp)) { + strcpy(fullname, tmp); + } + } +#else + /* Other OS's - Try TMP and TMPDIR */ + if (fullname[0] == '\0') { + char *tmp = getenv("TMP"); + if (tmp && BLI_exists(tmp)) { + strcpy(fullname, tmp); + } + } + + if (fullname[0] == '\0') { + char *tmp = getenv("TMPDIR"); + if (tmp && BLI_exists(tmp)) { + strcpy(fullname, tmp); + } + } +#endif + + if (fullname[0] == '\0') { + strcpy(fullname, "/tmp/"); + } else { + /* add a trailing slash if needed */ + BLI_add_slash(fullname); + } +} + /* * returns absolute path to the app bundle * only useful on OS X @@ -1491,13 +1734,45 @@ int BLI_strncasecmp(const char *s1, const char *s2, int n) { return 0; } -void BLI_timestr(double time, char *str) + +#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; + 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); |