123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583 |
- /***************************************************************************
- * *
- * _____ ____ *
- * | __ \ / __ \ _ _ _____ *
- * | | \ \ / / \_\ | | | | _ \ *
- * | | \ \| | | | | | |_| | *
- * | | | || | | | | | ___/ *
- * | | / /| | __ | | | | _ \ *
- * | |__/ / \ \__/ / | |___| | |_| | *
- * |_____/ \____/ |_____|_|_____/ *
- * *
- * Wiimms source code library *
- * *
- ***************************************************************************
- * *
- * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> *
- * *
- ***************************************************************************
- * *
- * This library is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This library 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. *
- * *
- * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
- * *
- ***************************************************************************/
- #define _GNU_SOURCE 1
- #include <string.h>
- #include "dclib-basics.h"
- #include "dclib-numeric.h"
- #include "dclib-debug.h"
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// float3 list support ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeF3L
- (
- float3List_t *f3l, // valid data
- uint bin_search // >0: enable binary search
- // and allocate 'bin_search' elements
- )
- {
- DASSERT(f3l);
- memset(f3l,0,sizeof(*f3l));
- if (bin_search)
- {
- f3l->size = bin_search;
- f3l->list = MALLOC( f3l->size * sizeof(*f3l->list) );
- f3l->sort = MALLOC( f3l->size * sizeof(*f3l->sort) );
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetF3L ( float3List_t * f3l )
- {
- DASSERT(f3l);
- FREE(f3l->list);
- FREE(f3l->sort);
- memset(f3l,0,sizeof(*f3l));
- }
- ///////////////////////////////////////////////////////////////////////////////
- float3 * AppendF3L ( float3List_t * f3l )
- {
- DASSERT( f3l );
- DASSERT( f3l->used <= f3l->size );
- DASSERT( !f3l->list == !f3l->size );
- if ( f3l->used == f3l->size )
- {
- f3l->size = 3*f3l->size/2 + 100;
- f3l->list = REALLOC( f3l->list, f3l->size * sizeof(*f3l->list) );
- if (f3l->sort)
- f3l->sort = REALLOC( f3l->sort, f3l->size * sizeof(*f3l->sort) );
- }
- DASSERT( f3l->list );
- DASSERT( f3l->used < f3l->size );
- if (f3l->sort)
- f3l->sort[f3l->used] = 0;
- float3 * item = f3l->list + f3l->used++;
- item->x = item->y = item->z = 0.0;
- return item;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint FindInsertFloatF3L ( float3List_t * f3l, float3 *val, bool fast )
- {
- DASSERT( f3l );
- DASSERT( f3l->used <= f3l->size );
- DASSERT( !f3l->list == !f3l->size );
- DASSERT( val );
- int beg = 0;
- if (!fast)
- {
- if (f3l->sort)
- {
- int end = f3l->used - 1;
- while ( beg <= end )
- {
- uint idx = (beg+end)/2;
- DASSERT( idx >= 0 && idx < f3l->used );
- DASSERT_MSG( f3l->sort[idx] < f3l->used,
- "idx=%d, sort-idx=%d, used=%u, size=%u\n",
- idx, f3l->sort[idx], f3l->used, f3l->size );
- int stat = memcmp( val,f3l->list + f3l->sort[idx], sizeof(*val) );
- if ( stat < 0 )
- end = idx - 1 ;
- else if ( stat > 0 )
- beg = idx + 1;
- else
- return f3l->sort[idx];
- }
- }
- else
- {
- float3 *ptr = f3l->list;
- float3 *end = ptr + f3l->used;
- for ( ; ptr < end; ptr++ )
- if (!memcmp(val,ptr,sizeof(*val)))
- return ptr - f3l->list;
- }
- }
- else if (f3l->sort)
- {
- // 'sort' not needed
- BINGO; // don't remove this line!
- FREE(f3l->sort);
- f3l->sort = 0;
- }
- float3 *res = AppendF3L(f3l);
- DASSERT(res);
- memcpy(res,val,sizeof(*res));
- const uint idx = f3l->used - 1;
- DASSERT( idx < f3l->used );
- if (f3l->sort)
- {
- DASSERT( beg >= 0 && beg <= idx );
- uint *dest = f3l->sort + beg;
- memmove( dest+1, dest, (idx-beg)*sizeof(*f3l->sort) );
- *dest = idx;
- #if HAVE_PRINT0
- if ( f3l->used < 10 )
- {
- uint i;
- for ( i = 0; i < f3l->used; i++ )
- {
- float3 *f = f3l->list + f3l->sort[i];
- PRINT("INS %2u: %2u -> %08x %08x %08x %11.5f %11.5f %11.5f\n",
- i, f3l->sort[i],
- be32(&f->x), be32(&f->y), be32(&f->z),
- f->x, f->y, f->z );
- }
- PRINT("---\n");
- }
- #endif
- }
- return idx;
- }
- ///////////////////////////////////////////////////////////////////////////////
- float3 * GrowF3L ( float3List_t * f3l, uint n )
- {
- DASSERT( f3l );
- DASSERT( f3l->used <= f3l->size );
- DASSERT( !f3l->list == !f3l->size );
- const uint new_used = f3l->used + n;
- if ( new_used > f3l->size || !f3l->size )
- {
- f3l->size = new_used ? new_used : 10;
- f3l->list = REALLOC( f3l->list, f3l->size * sizeof(*f3l->list)) ;
- }
- DASSERT( f3l->list );
- DASSERT( f3l->used + n <= f3l->size );
- float3 * result = f3l->list + f3l->used;
- f3l->used = new_used;
- return result;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// double3 list support ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeD3L ( double3List_t * d3l )
- {
- DASSERT(d3l);
- memset(d3l,0,sizeof(*d3l));
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetD3L ( double3List_t * d3l )
- {
- DASSERT(d3l);
- FREE(d3l->list);
- memset(d3l,0,sizeof(*d3l));
- }
- ///////////////////////////////////////////////////////////////////////////////
- double3 * AppendD3L ( double3List_t * d3l )
- {
- DASSERT( d3l );
- DASSERT( d3l->used <= d3l->size );
- DASSERT( !d3l->list == !d3l->size );
- if ( d3l->used == d3l->size )
- {
- d3l->size = 3*d3l->size/2 + 100;
- d3l->list = REALLOC( d3l->list, d3l->size * sizeof(*d3l->list)) ;
- }
- DASSERT( d3l->list );
- DASSERT( d3l->used < d3l->size );
- double3 * item = d3l->list + d3l->used++;
- item->x = item->y = item->z = 0.0;
- return item;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint FindInsertFloatD3L ( double3List_t * d3l, double3 *val, bool fast )
- {
- DASSERT( d3l );
- DASSERT( d3l->used <= d3l->size );
- DASSERT( !d3l->list == !d3l->size );
- DASSERT( val );
- // first: reduce precision
- double3 temp;
- temp.x = double2float(val->x);
- temp.y = double2float(val->y);
- temp.z = double2float(val->z);
- if (!fast)
- {
- double3 *ptr = d3l->list;
- double3 *end = ptr + d3l->used;
- for ( ; ptr < end; ptr++ )
- if (!memcmp(&temp,ptr,sizeof(temp)))
- return ptr - d3l->list;
- }
- double3 *res = AppendD3L(d3l);
- DASSERT(res);
- memcpy(res,&temp,sizeof(*res));
- return d3l->used - 1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- double3 * GrowD3L ( double3List_t * d3l, uint n )
- {
- DASSERT( d3l );
- DASSERT( d3l->used <= d3l->size );
- DASSERT( !d3l->list == !d3l->size );
- const uint new_used = d3l->used + n;
- if ( new_used > d3l->size || !d3l->size )
- {
- d3l->size = new_used ? new_used : 10;
- d3l->list = REALLOC( d3l->list, d3l->size * sizeof(*d3l->list)) ;
- }
- DASSERT( d3l->list );
- DASSERT( d3l->used + n <= d3l->size );
- double3 * result = d3l->list + d3l->used;
- d3l->used = new_used;
- return result;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// check numbers ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool IsNormalF3 ( float *f3 )
- {
- DASSERT(f3);
- const int fpclass = fpclassify(*f3++);
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(*f3++);
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(*f3);
- return fpclass == FP_NORMAL || fpclass == FP_ZERO;
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsNormalF3be ( float *f3 )
- {
- DASSERT(f3);
- const int fpclass = fpclassify(bef4(f3));
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(bef4(++f3));
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(bef4(++f3));
- return fpclass == FP_NORMAL || fpclass == FP_ZERO;
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsNormalD3 ( double *d3 )
- {
- DASSERT(d3);
- const int fpclass = fpclassify(*d3++);
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(*d3++);
- if ( fpclass == FP_NORMAL || fpclass == FP_ZERO )
- {
- const int fpclass = fpclassify(*d3);
- return fpclass == FP_NORMAL || fpclass == FP_ZERO;
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsEqualD3 ( const double3 *a, const double3 *b,
- double null_epsilon, double diff_epsilon )
- {
- DASSERT(a);
- DASSERT(b);
- DASSERT( null_epsilon > 0.0 );
- DASSERT( diff_epsilon > 0.0 );
- double diff;
- diff = fabs( a->x - b->x );
- if ( diff > null_epsilon )
- {
- const double abs_a = fabs(a->x);
- const double abs_b = fabs(b->x);
- if ( diff > ( abs_a > abs_b ? abs_a : abs_b ) * diff_epsilon )
- return false;
- }
- diff = fabs( a->y - b->y );
- if ( diff > null_epsilon )
- {
- const double abs_a = fabs(a->y);
- const double abs_b = fabs(b->y);
- if ( diff > ( abs_a > abs_b ? abs_a : abs_b ) * diff_epsilon )
- return false;
- }
- diff = fabs( a->z - b->z );
- if ( diff > null_epsilon )
- {
- const double abs_a = fabs(a->z);
- const double abs_b = fabs(b->z);
- if ( diff > ( abs_a > abs_b ? abs_a : abs_b ) * diff_epsilon )
- return false;
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsSameF ( float a, float b, int bit_diff )
- {
- float delta = ldexpf( fabsf(a-b), 23-bit_diff );
- return IsNormalF(delta) && delta <= fabsf(a) && delta <= fabsf(b);
- }
- bool IsSameD ( double a, double b, int bit_diff )
- {
- double delta = ldexp( fabs(a-b), 52-bit_diff );
- return IsNormalD(delta) && delta <= fabs(a) && delta <= fabs(b);
- }
- bool IsSameF3 ( const float *a, const float *b, int bit_diff )
- {
- return IsSameF(a[0],b[0],bit_diff)
- && IsSameF(a[1],b[1],bit_diff)
- && IsSameF(a[2],b[2],bit_diff);
- }
- bool IsSameD3 ( const double *a, const double *b, int bit_diff )
- {
- return IsSameD(a[0],b[0],bit_diff)
- && IsSameD(a[1],b[1],bit_diff)
- && IsSameD(a[2],b[2],bit_diff);
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// 2D vector functions ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- uint PointsInConvexPolygonF
- (
- // return, how many points are inside the polygon
- float *pts, // points: pointer to a array with '2*n_pts' elements
- uint n_pts, // Number of (x,y) pairs in 'pts'
- float *pol, // polygon: pointer to a array with '2*n_pol' elements
- uint n_pol, // number of (x,y) pairs in 'pol'
- bool all, // false: count the numbers of points inside
- // true: return '1' for all points inside and otherwise '0'
- int *r_dir // If not NULL then return:
- // -1: polygon is defined counterclockwise
- // 0: unknown
- // +1: polygon is defined clockwise
- // If at least one point is inside, the result is known.
- )
- {
- if ( !n_pts || n_pol < 3 )
- return 0;
- DASSERT(pts);
- DASSERT(pol);
- int pol_dir = 0;
- uint count = 0;
- for(;;)
- {
- float *a = pol + 2*(n_pol-1);
- float *b = pol;
- int dir = pol_dir;
- uint i = n_pol;
- for(;;)
- {
- const double dstat = SideOfLine(a[0],a[1],b[0],b[1],pts[0],pts[1]);
- const int new_dir = dstat > 0.0 ? -1 : dstat < 0;
- noPRINT("STAT: %2d %2d %2d %4g\n", pol_dir, dir, new_dir, dstat );
- if (!dir)
- dir = new_dir;
- else if ( new_dir && dir != new_dir )
- {
- if (!all)
- break;
- if (r_dir)
- *r_dir = pol_dir;
- return 0;
- }
- if ( --i > 0 )
- {
- a = b;
- b += 2;
- continue;
- }
- if (!pol_dir)
- pol_dir = dir;
- count++;
- break;
- }
- if ( --n_pts > 0 )
- {
- pts += 2;
- continue;
- }
- if (r_dir)
- *r_dir = pol_dir;
- noPRINT("DIR: %2d\n",pol_dir);
- return all ? 1 : count;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint PointsInConvexPolygonD
- (
- // return, how many points are inside the polygon
- double *pts, // points: pointer to a array with '2*n_pts' elements
- uint n_pts, // Number of (x,y) pairs in 'pts'
- double *pol, // polygon: pointer to a array with '2*n_pol' elements
- uint n_pol, // number of (x,y) pairs in 'pol'
- bool all, // false: count the numbers of points inside
- // true: return '1' for all points inside and otherwise '0'
- int *r_dir // If not NULL then return:
- // -1: polygon is defined counterclockwise
- // 0: unknown
- // +1: polygon is defined clockwise
- // If at least one point is inside, the result is known.
- )
- {
- if ( !n_pts || n_pol < 3 )
- return 0;
- DASSERT(pts);
- DASSERT(pol);
- int pol_dir = 0;
- uint count = 0;
- for(;;)
- {
- double *a = pol + 2*(n_pol-1);
- double *b = pol;
- int dir = pol_dir;
- uint i = n_pol;
- for(;;)
- {
- const double dstat = SideOfLine(a[0],a[1],b[0],b[1],pts[0],pts[1]);
- const int new_dir = dstat > 0.0 ? -1 : dstat < 0;
- noPRINT("STAT: %2d %2d %2d %4g\n", pol_dir, dir, new_dir, dstat );
- if (!dir)
- dir = new_dir;
- else if ( new_dir && dir != new_dir )
- {
- if (!all)
- break;
- if (r_dir)
- *r_dir = pol_dir;
- return 0;
- }
- if ( --i > 0 )
- {
- a = b;
- b += 2;
- continue;
- }
- if (!pol_dir)
- pol_dir = dir;
- count++;
- break;
- }
- if ( --n_pts > 0 )
- {
- pts += 2;
- continue;
- }
- if (r_dir)
- *r_dir = pol_dir;
- noPRINT("DIR: %2d\n",pol_dir);
- return all ? 1 : count;
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// float34 ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void ClearFloat34 ( float34 *f34 )
- {
- DASSERT(f34);
- float *d = f34->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = 0.0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupFloat34 ( float34 *f34 )
- {
- DASSERT(f34);
- float *d = f34->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = 0.0;
- f34->m[0][0] = f34->m[1][1] = f34->m[2][2] = 1.0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupMatrixF34
- (
- float34 *mat, // data to setup
- float3 *scale, // NULL or scaling vector
- float3 *rotate, // NULL or rotation vector in *radiant*
- float3 *translate // NULL or translation vector
- )
- {
- // This function use 'scale', 'rotate' and 'translate' to calculate the
- // transformation matrix. The calculations have been verified against
- // original MDL files of Nintendo. The rotation is done in right-handed
- // rotation with Euler angles (in degree) and x-y-z convention:
- // => http://en.wikipedia.org/wiki/Matrix_rotation#General_rotations
- DASSERT(mat);
- float *t = mat->v;
- //--- setup scale
- float3 myscale;
- if (scale)
- {
- myscale.x = fabs(scale->x) < NULL_EPSILON ? 1.0 : scale->x;
- myscale.y = fabs(scale->y) < NULL_EPSILON ? 1.0 : scale->y;
- myscale.z = fabs(scale->z) < NULL_EPSILON ? 1.0 : scale->z;
- }
- else
- myscale.x = myscale.y = myscale.z = 1.0;
- //--- calc translation matrix by scale and rotation
- if (rotate)
- {
- // be sure, that null values are exact
- const double sin_x = fabs(rotate->x) < NULL_EPSILON ? 0.0 : sin( rotate->x );
- const double cos_x = fabs(rotate->x) < NULL_EPSILON ? 1.0 : cos( rotate->x );
- const double sin_y = fabs(rotate->y) < NULL_EPSILON ? 0.0 : sin( rotate->y );
- const double cos_y = fabs(rotate->y) < NULL_EPSILON ? 1.0 : cos( rotate->y );
- const double sin_z = fabs(rotate->z) < NULL_EPSILON ? 0.0 : sin( rotate->z );
- const double cos_z = fabs(rotate->z) < NULL_EPSILON ? 1.0 : cos( rotate->z );
- t[ 0] = myscale.x * ( cos_y * cos_z );
- t[ 1] = myscale.y * ( - cos_x * sin_z + sin_x * sin_y * cos_z );
- t[ 2] = myscale.z * ( sin_x * sin_z + cos_x * sin_y * cos_z );
- t[4+0] = myscale.x * ( cos_y * sin_z );
- t[4+1] = myscale.y * ( cos_x * cos_z + sin_x * sin_y * sin_z );
- t[4+2] = myscale.z * ( - sin_x * cos_z + cos_x * sin_y * sin_z );
- t[8+0] = myscale.x * ( - sin_y );
- t[8+1] = myscale.y * ( sin_x * cos_y );
- t[8+2] = myscale.z * ( cos_x * cos_y );
- }
- else
- {
- t[ 0] = myscale.x;
- t[4+1] = myscale.y;
- t[8+2] = myscale.z;
- t[ 1] = 0.0;
- t[ 2] = 0.0;
- t[4+0] = 0.0;
- t[4+2] = 0.0;
- t[8+0] = 0.0;
- t[8+1] = 0.0;
- }
- //--- assign translation
- if (translate)
- {
- t[ 3] = translate->x;
- t[4+3] = translate->y;
- t[8+3] = translate->z;
- }
- else
- {
- t[ 3] = 0.0;
- t[4+3] = 0.0;
- t[8+3] = 0.0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CalcInverseMatrixF34
- (
- float34 *i, // store inverse matrix here
- const float34 *t // transformation matrix
- )
- {
- DASSERT(i);
- DASSERT(t);
- //--- calc inverse matrix
- const double det = t->v[ 0] * t->v[4+1] * t->v[8+2]
- + t->v[ 1] * t->v[4+2] * t->v[8+0]
- + t->v[ 2] * t->v[4+0] * t->v[8+1]
- - t->v[ 2] * t->v[4+1] * t->v[8+0]
- - t->v[ 1] * t->v[4+0] * t->v[8+2]
- - t->v[ 0] * t->v[4+2] * t->v[8+1];
- if ( fabs(det) < NULL_EPSILON )
- {
- // this should never happen => initialize inv_matrix with 0.0
- ClearFloat34(i);
- }
- else
- {
- const double det1 = 1.0 / det; // multplication is faster than division
- i->v[ 0] = ( t->v[4+1] * t->v[8+2] - t->v[4+2] * t->v[8+1] ) * det1;
- i->v[ 1] = ( t->v[ 2] * t->v[8+1] - t->v[ 1] * t->v[8+2] ) * det1;
- i->v[ 2] = ( t->v[ 1] * t->v[4+2] - t->v[ 2] * t->v[4+1] ) * det1;
- i->v[4+0] = ( t->v[4+2] * t->v[8+0] - t->v[4+0] * t->v[8+2] ) * det1;
- i->v[4+1] = ( t->v[ 0] * t->v[8+2] - t->v[ 2] * t->v[8+0] ) * det1;
- i->v[4+2] = ( t->v[ 2] * t->v[4+0] - t->v[ 0] * t->v[4+2] ) * det1;
- i->v[8+0] = ( t->v[4+0] * t->v[8+1] - t->v[4+1] * t->v[8+0] ) * det1;
- i->v[8+1] = ( t->v[ 1] * t->v[8+0] - t->v[ 0] * t->v[8+1] ) * det1;
- i->v[8+2] = ( t->v[ 0] * t->v[4+1] - t->v[ 1] * t->v[4+0] ) * det1;
- }
- //--- calc inverse translation
- i->v[ 3] = - t->v[ 3] * i->v[ 0]
- - t->v[4+3] * i->v[ 1]
- - t->v[8+3] * i->v[ 2];
- i->v[4+3] = - t->v[ 3] * i->v[4+0]
- - t->v[4+3] * i->v[4+1]
- - t->v[8+3] * i->v[4+2];
- i->v[8+3] = - t->v[ 3] * i->v[8+0]
- - t->v[4+3] * i->v[8+1]
- - t->v[8+3] * i->v[8+2];
- }
- ///////////////////////////////////////////////////////////////////////////////
- void MultiplyF34
- (
- float34 *dest, // valid, store result here, may be 'src1' or 'src2'
- const float34 *src1, // first valid source, if NULL use dest
- const float34 *src2 // second valid source, if NULL use dest
- )
- {
- DASSERT(dest);
- if ( dest == src1 || dest == src2 || !src1 || !src2 )
- {
- float34 temp;
- MultiplyF34( &temp, src1 ? src1 : dest, src2 ? src2 : dest );
- *dest = temp;
- return;
- }
- DASSERT( src1 && src1 != dest );
- DASSERT( src2 && src2 != dest );
- float *res = dest->v;
- const float *a = src1->v;
- const float *b = src2->v;
- res[0+0] = a[0+0]*b[0+0] + a[4+0]*b[0+1] + a[8+0]*b[0+2];
- res[0+1] = a[0+1]*b[0+0] + a[4+1]*b[0+1] + a[8+1]*b[0+2];
- res[0+2] = a[0+2]*b[0+0] + a[4+2]*b[0+1] + a[8+2]*b[0+2];
- res[0+3] = a[0+3]*b[0+0] + a[4+3]*b[0+1] + a[8+3]*b[0+2] + b[0+3];
- res[4+0] = a[0+0]*b[4+0] + a[4+0]*b[4+1] + a[8+0]*b[4+2];
- res[4+1] = a[0+1]*b[4+0] + a[4+1]*b[4+1] + a[8+1]*b[4+2];
- res[4+2] = a[0+2]*b[4+0] + a[4+2]*b[4+1] + a[8+2]*b[4+2];
- res[4+3] = a[0+3]*b[4+0] + a[4+3]*b[4+1] + a[8+3]*b[4+2] + b[4+3];
- res[8+0] = a[0+0]*b[8+0] + a[4+0]*b[8+1] + a[8+0]*b[8+2];
- res[8+1] = a[0+1]*b[8+0] + a[4+1]*b[8+1] + a[8+1]*b[8+2];
- res[8+2] = a[0+2]*b[8+0] + a[4+2]*b[8+1] + a[8+2]*b[8+2];
- res[8+3] = a[0+3]*b[8+0] + a[4+3]*b[8+1] + a[8+3]*b[8+2] + b[8+3];
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// double34 ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void ClearDouble34 ( double34 *d34 )
- {
- DASSERT(d34);
- double *d = d34->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = 0.0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupDouble34 ( double34 *d34 )
- {
- DASSERT(d34);
- double *d = d34->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = 0.0;
- d34->m[0][0] = d34->m[1][1] = d34->m[2][2] = 1.0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupMatrixD34
- (
- double34 *mat, // data to setup
- double3 *scale, // NULL or scaling vector
- double3 *rotate, // NULL or rotation vector in *radiant*
- double3 *translate // NULL or translation vector
- )
- {
- // This function use 'scale', 'rotate' and 'translate' to calculate the
- // transformation matrix. The calculations have been verified against
- // original MDL files of Nintendo. The rotation is done in right-handed
- // rotation with Euler angles (in degree) and x-y-z convention:
- // => http://en.wikipedia.org/wiki/Matrix_rotation#General_rotations
- DASSERT(mat);
- double *t = mat->v;
- //--- setup scale
- double3 myscale;
- if (scale)
- {
- myscale.x = fabs(scale->x) < NULL_EPSILON ? 1.0 : scale->x;
- myscale.y = fabs(scale->y) < NULL_EPSILON ? 1.0 : scale->y;
- myscale.z = fabs(scale->z) < NULL_EPSILON ? 1.0 : scale->z;
- }
- else
- myscale.x = myscale.y = myscale.z = 1.0;
- //--- calc translation matrix by scale and rotation
- if (rotate)
- {
- // be sure, that null values are exact
- const double sin_x = fabs(rotate->x) < NULL_EPSILON ? 0.0 : sin( rotate->x );
- const double cos_x = fabs(rotate->x) < NULL_EPSILON ? 1.0 : cos( rotate->x );
- const double sin_y = fabs(rotate->y) < NULL_EPSILON ? 0.0 : sin( rotate->y );
- const double cos_y = fabs(rotate->y) < NULL_EPSILON ? 1.0 : cos( rotate->y );
- const double sin_z = fabs(rotate->z) < NULL_EPSILON ? 0.0 : sin( rotate->z );
- const double cos_z = fabs(rotate->z) < NULL_EPSILON ? 1.0 : cos( rotate->z );
- t[ 0] = myscale.x * ( cos_y * cos_z );
- t[ 1] = myscale.y * ( - cos_x * sin_z + sin_x * sin_y * cos_z );
- t[ 2] = myscale.z * ( sin_x * sin_z + cos_x * sin_y * cos_z );
- t[4+0] = myscale.x * ( cos_y * sin_z );
- t[4+1] = myscale.y * ( cos_x * cos_z + sin_x * sin_y * sin_z );
- t[4+2] = myscale.z * ( - sin_x * cos_z + cos_x * sin_y * sin_z );
- t[8+0] = myscale.x * ( - sin_y );
- t[8+1] = myscale.y * ( sin_x * cos_y );
- t[8+2] = myscale.z * ( cos_x * cos_y );
- }
- else
- {
- t[ 0] = myscale.x;
- t[4+1] = myscale.y;
- t[8+2] = myscale.z;
- t[ 1] = 0.0;
- t[ 2] = 0.0;
- t[4+0] = 0.0;
- t[4+2] = 0.0;
- t[8+0] = 0.0;
- t[8+1] = 0.0;
- }
- //--- assign translation
- if (translate)
- {
- t[ 3] = translate->x;
- t[4+3] = translate->y;
- t[8+3] = translate->z;
- }
- else
- {
- t[ 3] = 0.0;
- t[4+3] = 0.0;
- t[8+3] = 0.0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CalcInverseMatrixD34
- (
- double34 *i, // store inverse matrix here
- const double34 *t // transformation matrix
- )
- {
- DASSERT(i);
- DASSERT(t);
- //--- calc inverse matrix
- const double det = t->v[ 0] * t->v[4+1] * t->v[8+2]
- + t->v[ 1] * t->v[4+2] * t->v[8+0]
- + t->v[ 2] * t->v[4+0] * t->v[8+1]
- - t->v[ 2] * t->v[4+1] * t->v[8+0]
- - t->v[ 1] * t->v[4+0] * t->v[8+2]
- - t->v[ 0] * t->v[4+2] * t->v[8+1];
- if ( fabs(det) < NULL_EPSILON )
- {
- // this should never happen => initialize inv_matrix with 0.0
- ClearDouble34(i);
- }
- else
- {
- const double det1 = 1.0 / det; // multplication is faster than division
- i->v[ 0] = ( t->v[4+1] * t->v[8+2] - t->v[4+2] * t->v[8+1] ) * det1;
- i->v[ 1] = ( t->v[ 2] * t->v[8+1] - t->v[ 1] * t->v[8+2] ) * det1;
- i->v[ 2] = ( t->v[ 1] * t->v[4+2] - t->v[ 2] * t->v[4+1] ) * det1;
- i->v[4+0] = ( t->v[4+2] * t->v[8+0] - t->v[4+0] * t->v[8+2] ) * det1;
- i->v[4+1] = ( t->v[ 0] * t->v[8+2] - t->v[ 2] * t->v[8+0] ) * det1;
- i->v[4+2] = ( t->v[ 2] * t->v[4+0] - t->v[ 0] * t->v[4+2] ) * det1;
- i->v[8+0] = ( t->v[4+0] * t->v[8+1] - t->v[4+1] * t->v[8+0] ) * det1;
- i->v[8+1] = ( t->v[ 1] * t->v[8+0] - t->v[ 0] * t->v[8+1] ) * det1;
- i->v[8+2] = ( t->v[ 0] * t->v[4+1] - t->v[ 1] * t->v[4+0] ) * det1;
- }
- //--- calc inverse translation
- i->v[ 3] = - t->v[ 3] * i->v[ 0]
- - t->v[4+3] * i->v[ 1]
- - t->v[8+3] * i->v[ 2];
- i->v[4+3] = - t->v[ 3] * i->v[4+0]
- - t->v[4+3] * i->v[4+1]
- - t->v[8+3] * i->v[4+2];
- i->v[8+3] = - t->v[ 3] * i->v[8+0]
- - t->v[4+3] * i->v[8+1]
- - t->v[8+3] * i->v[8+2];
- }
- ///////////////////////////////////////////////////////////////////////////////
- void MultiplyD34
- (
- double34 *dest, // valid, store result here, may be 'src1' or 'src2'
- const double34 *src1, // first valid source, if NULL use dest
- const double34 *src2 // second valid source, if NULL use dest
- )
- {
- DASSERT(dest);
- if ( dest == src1 || dest == src2 || !src1 || !src2 )
- {
- double34 temp;
- MultiplyD34( &temp, src1 ? src1 : dest, src2 ? src2 : dest );
- *dest = temp;
- return;
- }
- DASSERT( src1 && src1 != dest );
- DASSERT( src2 && src2 != dest );
- double *res = dest->v;
- const double *a = src1->v;
- const double *b = src2->v;
- res[0+0] = a[0+0]*b[0+0] + a[4+0]*b[0+1] + a[8+0]*b[0+2];
- res[0+1] = a[0+1]*b[0+0] + a[4+1]*b[0+1] + a[8+1]*b[0+2];
- res[0+2] = a[0+2]*b[0+0] + a[4+2]*b[0+1] + a[8+2]*b[0+2];
- res[0+3] = a[0+3]*b[0+0] + a[4+3]*b[0+1] + a[8+3]*b[0+2] + b[0+3];
- res[4+0] = a[0+0]*b[4+0] + a[4+0]*b[4+1] + a[8+0]*b[4+2];
- res[4+1] = a[0+1]*b[4+0] + a[4+1]*b[4+1] + a[8+1]*b[4+2];
- res[4+2] = a[0+2]*b[4+0] + a[4+2]*b[4+1] + a[8+2]*b[4+2];
- res[4+3] = a[0+3]*b[4+0] + a[4+3]*b[4+1] + a[8+3]*b[4+2] + b[4+3];
- res[8+0] = a[0+0]*b[8+0] + a[4+0]*b[8+1] + a[8+0]*b[8+2];
- res[8+1] = a[0+1]*b[8+0] + a[4+1]*b[8+1] + a[8+1]*b[8+2];
- res[8+2] = a[0+2]*b[8+0] + a[4+2]*b[8+1] + a[8+2]*b[8+2];
- res[8+3] = a[0+3]*b[8+0] + a[4+3]*b[8+1] + a[8+3]*b[8+2] + b[8+3];
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void CopyF34toD34
- (
- double34 *dest, // destination matrix
- const float34 *src // source matrix
- )
- {
- DASSERT(dest);
- DASSERT(src);
- double *d = dest->v;
- const float *s = src->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = *s++;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CopyD34toF34
- (
- float34 *dest, // destination matrix
- const double34 *src // source matrix
- )
- {
- DASSERT(dest);
- DASSERT(src);
- float *d = dest->v;
- const double *s = src->v;
- uint n;
- for ( n = 0; n < 12; n++ )
- *d++ = *s++;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: setup ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- // statistics
- u64 N_MatrixD_forward = 0; // total number of forward transformations
- u64 N_MatrixD_inverse = 0; // total number of inverse transformations
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeMatrixD ( MatrixD_t * mat )
- {
- DASSERT(mat);
- // const uint seqnum = mat->valid ? mat->sequence_number : 0;
- memset(mat,0,sizeof(*mat));
- // mat->sequence_number = seqnum;
- mat->scale.x = mat->scale.y = mat->scale.z = 1.0;
- mat->scale_origin.x = mat->scale_origin.y = mat->scale_origin.z = 0.0;
- mat->shift = mat->scale_origin;
- mat->rotate_deg = mat->scale_origin;
- mat->rotate_rad = mat->scale_origin;
- mat->translate = mat->scale_origin;
- double *d = (double*)mat->rotate_origin;
- uint n;
- for ( n = 0; n < 9; n++ )
- *d++ = 0.0;
- mat->valid = true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CopyMatrixD
- (
- MatrixD_t *dest, // valid destination
- const
- MatrixD_t *src // NULL or source
- )
- {
- DASSERT(dest);
- if ( src && src->valid )
- {
- const uint seqnum = dest->sequence_number;
- *dest = *src;
- dest->sequence_number = seqnum+1;
- }
- else
- InitializeMatrixD(dest);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetScaleMatrixD
- (
- MatrixD_t * mat, // valid data structure
- double3 * scale, // NULL: clear scale, not NULL: set scale
- double3 * origin // not NULL: Origin for scaling
- )
- {
- DASSERT(mat);
- if (!mat->valid)
- InitializeMatrixD(mat);
- mat->norm_valid = mat->tmatrix_valid = mat->imatrix_valid = false;
- if (scale)
- mat->scale = *scale;
- else
- {
- mat->scale.x = mat->scale.y = mat->scale.z = 1.0;
- origin = 0;
- }
- if (origin)
- mat->scale_origin = *origin;
- else
- mat->scale_origin.x = mat->scale_origin.y = mat->scale_origin.z = 0.0;
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetShiftMatrixD
- (
- MatrixD_t * mat, // valid data structure
- double3 * shift // NULL: clear Shift, not NULL: set Shift
- )
- {
- DASSERT(mat);
- if (!mat->valid)
- InitializeMatrixD(mat);
- mat->norm_valid = mat->tmatrix_valid = mat->imatrix_valid = false;
- if (shift)
- mat->shift = *shift;
- else
- mat->shift.x = mat->shift.y = mat->shift.z = 0.0;
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetScaleShiftMatrixD
- (
- MatrixD_t * mat, // valid data structure
- uint xyz, // 0..2: x/y/z coordinate to set
- double old1, // old value of first point
- double new1, // new value of first point
- double old2, // old value of second point
- double new2 // new value of second point
- )
- {
- DASSERT(mat);
- if (!mat->valid)
- InitializeMatrixD(mat);
- if ( fabs(old1-old2) >= NULL_EPSILON ) // ignore othwerwise
- {
- mat->norm_valid = mat->tmatrix_valid = mat->imatrix_valid = false;
- const double scale = ( new2 - new1 ) / ( old2 - old1 );
- mat->scale.v[xyz] = scale;
- mat->scale_origin.v[xyz] = 0.0;
- // new = old * scale + shift
- mat->shift.v[xyz] = new1 - old1 * scale;
- }
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetRotateMatrixD
- (
- MatrixD_t * mat, // valid data structure
- uint xyz, // 0..2: x/y/z coordinate to set
- double degree, // angle in degree
- double radiant, // angle in radiant
- double3 * origin // not NULL: Origin for the rotation
- )
- {
- DASSERT(mat);
- DASSERT(xyz<3);
- if (!mat->valid)
- InitializeMatrixD(mat);
- mat->norm_valid = mat->tmatrix_valid = mat->imatrix_valid = false;
- mat->rotate_deg.v[xyz] = degree;
- mat->rotate_rad.v[xyz] = radiant;
- if (origin)
- mat->rotate_origin[xyz] = *origin;
- else
- {
- origin = mat->rotate_origin + xyz;
- origin->x = origin->y = origin->z = 0.0;
- }
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetTranslateMatrixD
- (
- MatrixD_t * mat, // valid data structure
- double3 * translate // NULL: clear translate, not NULL: set translate
- )
- {
- DASSERT(mat);
- if (!mat->valid)
- InitializeMatrixD(mat);
- mat->norm_valid = mat->tmatrix_valid = mat->imatrix_valid = false;
- if (translate)
- mat->translate = *translate;
- else
- mat->translate.x = mat->translate.y = mat->translate.z = 0.0;
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * CheckStatusMatrixD
- (
- MatrixD_t * mat // valid data structure
- )
- {
- DASSERT(mat);
- if (mat->tmatrix_valid)
- {
- double *t = mat->trans_matrix.v;
- //--- check rotation (only disabled for all axis)
- if ( mat->rotate_enabled & 1
- && fabs( t[4+2] ) < NULL_EPSILON
- && fabs( t[8+1] ) < NULL_EPSILON
- )
- {
- mat->rotate_enabled &= ~1;
- t[4+2] = 0.0;
- t[8+1] = 0.0;
- }
- if ( mat->rotate_enabled & 2
- && fabs( t[ 2] ) < NULL_EPSILON
- && fabs( t[8+0] ) < NULL_EPSILON
- )
- {
- mat->rotate_enabled &= ~2;
- t[ 2] = 0.0;
- t[8+0] = 0.0;
- }
- if ( mat->rotate_enabled & 4
- && fabs( t[ 1] ) < NULL_EPSILON
- && fabs( t[4+0] ) < NULL_EPSILON
- )
- {
- mat->rotate_enabled &= ~4;
- t[ 1] = 0.0;
- t[4+0] = 0.0;
- }
- //--- check scaling (don't touch scale if roating is enabled)
- if ( mat->scale_enabled & 1
- && !( mat->rotate_enabled & ~1 )
- && fabs( t[ 0] - 1.0 ) < NULL_EPSILON )
- {
- t[ 0] = 1.0;
- mat->scale_enabled &= ~1;
- }
- if ( mat->scale_enabled & 2
- && !( mat->rotate_enabled & ~2 )
- && fabs( t[4+1] - 1.0 ) < NULL_EPSILON )
- {
- t[4+1] = 1.0;
- mat->scale_enabled &= ~2;
- }
- if ( mat->scale_enabled & 4
- && !( mat->rotate_enabled & ~4 )
- && fabs( t[8+2] - 1.0 ) < NULL_EPSILON )
- {
- t[8+2] = 1.0;
- mat->scale_enabled &= ~4;
- }
- //--- check transformation
- if ( mat->translate_enabled & 1 && fabs( t[ 3] ) < NULL_EPSILON )
- {
- t[ 3] = 0.0;
- mat->translate_enabled &= ~1;
- }
- if ( mat->translate_enabled & 2 && fabs( t[4+3] ) < NULL_EPSILON )
- {
- t[4+3] = 0.0;
- mat->translate_enabled &= ~2;
- }
- if ( mat->translate_enabled & 4 && fabs( t[8+3] ) < NULL_EPSILON )
- {
- t[8+3] = 0.0;
- mat->translate_enabled &= ~4;
- }
- mat->transform_enabled = mat->scale_enabled
- | mat->rotate_enabled
- | mat->translate_enabled
- | mat->use_matrix << 3;
- }
- return mat;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: specials ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void TermAssignMatrixD
- (
- // called after dirext matrix manipulations
- MatrixD_t * mat // valid data structure
- )
- {
- DASSERT(mat);
- mat->valid = true;
- mat->norm_valid = false;
- mat->tmatrix_valid = true;
- mat->imatrix_valid = false;
- mat->use_matrix = 2;
- mat->scale_enabled = 7;
- mat->rotate_enabled = 7;
- mat->translate_enabled = 7;
- mat->sequence_number++;
- double34 *m = &mat->trans_matrix;
- mat->norm_scale.x = m->x[0];
- mat->norm_scale.y = m->y[1];
- mat->norm_scale.z = m->z[2];
- mat->norm_translate.x = m->x[3];
- mat->norm_translate.y = m->y[3];
- mat->norm_translate.z = m->z[3];
- CheckStatusMatrixD(mat);
- if (!mat->rotate_enabled)
- {
- mat->use_matrix = 0;
- mat->norm_valid = true;
- mat->norm_rotate_deg.x = 0;
- mat->norm_rotate_deg.y = 0;
- mat->norm_rotate_deg.z = 0;
- mat->norm_rotate_rad = mat->norm_rotate_deg;
- mat->scale = mat->norm_scale;
- mat->translate = mat->norm_translate;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetMatrixD
- (
- MatrixD_t * mat, // valid data structure
- const
- double34 * src // NULL or matrix to set
- )
- {
- DASSERT(mat);
- InitializeMatrixD(mat);
- if (src)
- {
- mat->trans_matrix = *src;
- TermAssignMatrixD(mat);
- }
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetAScaleMatrixD
- (
- // calculate the matrix as rotation around a specified axis
- MatrixD_t * mat, // valid data structure
- double scale, // scale factor
- double3 * dir // NULL or scaling direction as vector
- )
- {
- DASSERT(mat);
- InitializeMatrixD(mat);
- if (dir)
- {
- const double hrot = atan2(dir->x,dir->z);
- const double hlen = sqrt( dir->x*dir->x + dir->z*dir->z );
- const double vrot = -atan2(dir->y,hlen);
- PRINT("HROT: %6.4f %7.2f / %11.3f\n",hrot,hrot*180.0/M_PI,hlen);
- PRINT("VROT: %6.4f %7.2f\n",vrot,vrot*180.0/M_PI);
- MatrixD_t mrot;
- InitializeMatrixD(&mrot);
- mrot.rotate_rad.x = vrot;
- mrot.rotate_rad.y = hrot;
- CalcMatrixD(&mrot,true);
- DASSERT(mrot.imatrix_valid);
- SetMatrixD(mat,&mrot.inv_matrix);
- double3 scale3;
- scale3.x = scale3.y = 0;
- scale3.z = scale;
- SetScaleMatrixD(&mrot,&scale3,0);
- MultiplyMatrixD(mat,0,&mrot,0);
- TermAssignMatrixD(mat);
- }
- //--- terminate
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * SetARotateMatrixD
- (
- // calculate the matrix as rotation around a specified axis
- MatrixD_t * mat, // valid data structure
- double degree, // angle in degree
- double radiant, // angle in radiant, add to degree with factor
- double3 * pt1, // point #1 to define the axis; if NULL use (0,0,0)
- double3 * pt2 // point #2 to define the axis; if NULL use (0,0,0)
- )
- {
- DASSERT(mat);
- InitializeMatrixD(mat);
- double3 dir, base;
- if (pt1)
- base = *pt1;
- else
- base.x = base.y = base.z = 0.0;
- if (pt2)
- Sub3(dir,*pt2,base);
- else
- {
- dir.x = -base.x;
- dir.y = -base.y;
- dir.z = -base.z;
- }
- #if 1
- radiant += degree * (M_PI/180.0);
- const double len = Length3(dir);
- if ( len >= NULL_EPSILON )
- #else
- radiant = fmod( degree * (M_PI/180.0) + radiant + M_PI, 2*M_PI) - M_PI;
- const double len = Length3(dir);
- if ( len >= NULL_EPSILON && fabs(radiant) >= NULL_EPSILON )
- #endif
- {
- dir.x /= len;
- dir.y /= len;
- dir.z /= len;
- const double sin0 = sin(radiant);
- const double cos0 = cos(radiant);
- const double cos1 = 1.0 - cos0;
- double *t = mat->trans_matrix.v;
- t[ 0] = dir.x * dir.x * cos1 + cos0;
- t[ 1] = dir.x * dir.y * cos1 - dir.z * sin0;
- t[ 2] = dir.x * dir.z * cos1 + dir.y * sin0;
- t[4+0] = dir.y * dir.x * cos1 + dir.z * sin0;
- t[4+1] = dir.y * dir.y * cos1 + cos0;
- t[4+2] = dir.y * dir.z * cos1 - dir.x * sin0;
- t[8+0] = dir.z * dir.x * cos1 - dir.y * sin0;
- t[8+1] = dir.z * dir.y * cos1 + dir.x * sin0;
- t[8+2] = dir.z * dir.z * cos1 + cos0;
- double3 delta = TransformD3D34(&mat->trans_matrix,&base);
- t[ 3] = base.x - delta.x;
- t[4+3] = base.y - delta.y;
- t[8+3] = base.z - delta.z;
- TermAssignMatrixD(mat);
- }
- //--- terminate
- return mat;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: calc ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * CalcNormMatrixD
- (
- MatrixD_t * mat // valid data structure
- )
- {
- DASSERT(mat);
- if (!mat->valid)
- InitializeMatrixD(mat);
- if ( mat->norm_valid || mat->tmatrix_valid )
- return mat;
- mat->sequence_number++;
- mat->norm_valid = true;
- mat->scale_enabled = mat->rotate_enabled = mat->translate_enabled = 0;
- //--- scale & shift
- double3 trans;
- uint xyz;
- for ( xyz = 0; xyz < 3; xyz++ )
- {
- double scale = mat->scale.v[xyz];
- if ( fabs(scale) < NULL_EPSILON || fabs(scale-1.0) < NULL_EPSILON )
- mat->scale.v[xyz] = scale = 1.0;
- else
- mat->scale_enabled |= 1 << xyz;
- mat->norm_scale.v[xyz] = scale;
- trans.v[xyz] = mat->shift.v[xyz]
- + ( 1.0 - scale ) * mat->scale_origin.v[xyz];
- }
- //--- rotate
- mat->norm_pos2d.x = mat->norm_pos2d.y = mat->norm_pos2d.z = 0;
- for ( xyz = 0; xyz < 3; xyz++ )
- {
- double deg = fmod( mat->rotate_deg.v[xyz]
- + mat->rotate_rad.v[xyz] * (180.0/M_PI)
- + 180.0, 360.0 ) - 180.0;
- if ( fabs(deg) < MIN_DEGREE )
- {
- mat->norm_rotate_deg.v[xyz] = 0.0;
- mat->norm_rotate_rad.v[xyz] = 0.0;
- }
- else
- {
- mat->rotate_enabled |= 1 << xyz;
- mat->norm_rotate_deg.v[xyz] = deg;
- double rad = deg * (M_PI/180.0);
- mat->norm_rotate_rad.v[xyz] = rad;
- // translate = rot_origin + rotated(translate-rot_origin)
- Sub3(trans,trans,mat->rotate_origin[xyz]);
- const uint a = (xyz+2) % 3;
- const uint b = (xyz+1) % 3;
- rad += atan2(trans.v[a],trans.v[b]);
- const double len = sqrt(trans.v[a]*trans.v[a]+trans.v[b]*trans.v[b]);
- trans.v[a] = sin(rad) * len;
- trans.v[b] = cos(rad) * len;
- Add3(trans,trans,mat->rotate_origin[xyz]);
- mat->norm_pos2d.v[a] += mat->rotate_origin[xyz].v[a];
- mat->norm_pos2d.v[b] += mat->rotate_origin[xyz].v[b];
- }
- }
- if ( (mat->rotate_enabled|1) == 7 ) mat->norm_pos2d.x /= 2;
- if ( (mat->rotate_enabled|2) == 7 ) mat->norm_pos2d.y /= 2;
- if ( (mat->rotate_enabled|4) == 7 ) mat->norm_pos2d.z /= 2;
- //--- translate
- mat->translate_enabled = false;
- for ( xyz = 0; xyz < 3; xyz++ )
- {
- const double temp = trans.v[xyz] + mat->translate.v[xyz];
- if ( fabs(temp) < NULL_EPSILON )
- mat->norm_translate.v[xyz] = 0.0;
- else
- {
- mat->norm_translate.v[xyz] = temp;
- mat->translate_enabled |= 1 << xyz;
- }
- }
- //--- status
- if ( mat->use_matrix < 2 )
- {
- mat->use_matrix = mat->rotate_enabled ? 1 : 0;
- mat->tmatrix_valid = mat->imatrix_valid = false;
- }
- mat->transform_enabled = mat->scale_enabled
- | mat->rotate_enabled
- | mat->translate_enabled
- | mat->use_matrix << 3;
- TRACE("%%%%%%%%%% CalcNormMatrixD(%p) => %u|%u|%u = %02x %%%%%%%%%%\n",
- mat, mat->scale_enabled, mat->rotate_enabled,
- mat->translate_enabled, mat->transform_enabled );
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * CalcTransMatrixD
- (
- MatrixD_t * mat, // valid data structure
- bool always // false: calc transformation matrix only
- // if needed for transformation
- // true: calc matrix always
- // if 'tmatrix_valid', the matrix is never calculated
- )
- {
- DASSERT(mat);
- CalcNormMatrixD(mat);
- if ( mat->tmatrix_valid || !always && !mat->use_matrix )
- return mat;
- TRACE("%%%%%%%%%% CalcTransMatrixD(%p,%d) => %u|%u|%u = %02x %%%%%%%%%%\n",
- mat, always, mat->scale_enabled, mat->rotate_enabled,
- mat->translate_enabled, mat->transform_enabled );
- DASSERT(mat->use_matrix<2);
- SetupMatrixD34( &mat->trans_matrix,
- &mat->norm_scale,
- &mat->norm_rotate_rad,
- &mat->norm_translate );
- mat->tmatrix_valid = true;
- mat->imatrix_valid = false;
- CheckStatusMatrixD(mat);
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * CalcMatrixD
- (
- MatrixD_t * mat, // valid data structure
- bool always // false: calc both matrices only
- // if needed for transformation
- // true: calc matrices always
- )
- {
- DASSERT(mat);
- if ( mat->imatrix_valid || !always && !mat->use_matrix )
- return mat;
- CalcTransMatrixD(mat,true);
- TRACE("%%%%%%%%%% CalcMatrixD (%p,%d) => %u|%u|%u = %02x %%%%%%%%%%\n",
- mat, always, mat->scale_enabled, mat->rotate_enabled,
- mat->translate_enabled, mat->transform_enabled );
- CalcInverseMatrixD34(&mat->inv_matrix,&mat->trans_matrix);
- mat->imatrix_valid = true;
- return mat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * MultiplyMatrixD
- (
- MatrixD_t *dest, // valid, store result here, may be 'src1' or 'src2'
- MatrixD_t *src1, // first valid source, if NULL use dest
- MatrixD_t *src2, // second valid source, if NULL use dest
- uint inverse_mode // bit field:
- // 1: use inverse matrix of src1
- // 2: use inverse matrix of src2
- )
- {
- DASSERT(dest);
- if ( dest == src1 || dest == src2 || !src1 || !src2 )
- {
- MatrixD_t temp;
- MultiplyMatrixD( &temp, src1 ? src1 : dest, src2 ? src2 : dest, inverse_mode );
- *dest = temp;
- return dest;
- }
- DASSERT( src1 && src1 != dest );
- DASSERT( src2 && src2 != dest );
- CalcMatrixD(src1,true);
- CalcMatrixD(src2,true);
- InitializeMatrixD(dest);
- MultiplyD34( &dest->trans_matrix,
- inverse_mode & 1 ? &src1->inv_matrix : &src1->trans_matrix,
- inverse_mode & 2 ? &src2->inv_matrix : &src2->trans_matrix );
- //--- setup normals, simply assumption
- dest->norm_scale.x = dest->trans_matrix.m[0][0];
- dest->norm_scale.y = dest->trans_matrix.m[1][1];
- dest->norm_scale.z = dest->trans_matrix.m[2][2];
- dest->norm_rotate_deg.x = src1->norm_rotate_deg.x + src2->norm_rotate_deg.x;
- dest->norm_rotate_deg.y = src1->norm_rotate_deg.y + src2->norm_rotate_deg.y;
- dest->norm_rotate_deg.z = src1->norm_rotate_deg.z + src2->norm_rotate_deg.z;
- Mult3f(dest->norm_rotate_rad,dest->norm_rotate_deg,M_PI/180.0);
- dest->norm_translate.x = dest->trans_matrix.m[0][3];
- dest->norm_translate.y = dest->trans_matrix.m[1][3];
- dest->norm_translate.z = dest->trans_matrix.m[2][3];
- //--- setup base values
- dest->scale = dest->norm_scale;
- dest->rotate_deg = dest->norm_rotate_deg;
- dest->translate = dest->norm_translate;
- //--- terminate
- TermAssignMatrixD(dest);
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- MatrixD_t * CalcVectorsMatrixD
- (
- MatrixD_t * mat, // valid data structure
- bool always // false: calc vectors only if matrix is valid
- // true: calc matrix if invalid & vectors always
- )
- {
- DASSERT(mat);
- // search: Decomposing a rotation matrix
- if ( !always && !mat->tmatrix_valid )
- return mat;
- CalcMatrixD(mat,false);
- // [[2do]] ??? calculate scale
- //mat->norm_scale.x = 1.0;
- //mat->norm_scale.y = 1.0;
- //mat->norm_scale.z = 1.0;
- double (*m)[4] = mat->trans_matrix.m;
- // [[2do]] ??? works only for scale == 1 ==>
- mat->norm_rotate_rad.x = atan2( m[2][1], m[2][2] );
- mat->norm_rotate_rad.y = atan2( -m[2][0], sqrt( m[2][1]*m[2][1] + m[2][2]*m[2][2] ) );
- mat->norm_rotate_rad.z = atan2( m[1][0], m[0][0] );
- mat->norm_rotate_deg.x = rad2deg(mat->norm_rotate_rad.x);
- mat->norm_rotate_deg.y = rad2deg(mat->norm_rotate_rad.y);
- mat->norm_rotate_deg.z = rad2deg(mat->norm_rotate_rad.z);
- mat->norm_translate.x = m[0][3];
- mat->norm_translate.y = m[1][3];
- mat->norm_translate.z = m[2][3];
- return mat;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: double transform ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- double3 TransformD3MatrixD
- (
- MatrixD_t * mat, // valid data structure
- const
- double3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- N_MatrixD_forward++;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->tmatrix_valid)
- CalcTransMatrixD(mat,true);
- return TransformD3D34(&mat->trans_matrix,val);
- }
- double3 res;
- res.x = val->x * mat->norm_scale.x + mat->norm_translate.x;
- res.y = val->y * mat->norm_scale.y + mat->norm_translate.y;
- res.z = val->z * mat->norm_scale.z + mat->norm_translate.z;
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- double3 InvTransformD3MatrixD
- (
- MatrixD_t * mat, // valid data structure
- const
- double3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- N_MatrixD_inverse++;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->imatrix_valid)
- CalcMatrixD(mat,true);
- return TransformD3D34(&mat->inv_matrix,val);
- }
- double3 res;
- res.x = ( val->x - mat->norm_translate.x ) / mat->norm_scale.x;
- res.y = ( val->y - mat->norm_translate.y ) / mat->norm_scale.y;
- res.z = ( val->z - mat->norm_translate.z ) / mat->norm_scale.z;
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void TransformD3NMatrixD
- (
- MatrixD_t * mat, // valid data structure
- double3 * val, // value array to transform
- int n, // number of 3D vectors in 'val'
- uint off // if n>1: offset from one to next 'val' vector
- )
- {
- DASSERT(mat);
- DASSERT(val);
- DASSERT( n <= 1 || off >= sizeof(*val) );
- N_MatrixD_forward += n;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->tmatrix_valid)
- CalcTransMatrixD(mat,true);
- while ( n-- > 0 )
- {
- *val = TransformD3D34(&mat->trans_matrix,val);
- val = (double3*)( (u8*)val + off );
- }
- }
- else if (mat->transform_enabled)
- {
- while ( n-- > 0 )
- {
- val->x = val->x * mat->norm_scale.x + mat->norm_translate.x;
- val->y = val->y * mat->norm_scale.y + mat->norm_translate.y;
- val->z = val->z * mat->norm_scale.z + mat->norm_translate.z;
- val = (double3*)( (u8*)val + off );
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void InvTransformD3NMatrixD
- (
- MatrixD_t * mat, // valid data structure
- double3 * val, // value array to transform
- int n, // number of 3D vectors in 'val'
- uint off // if n>1: offset from one to next 'val' vector
- )
- {
- DASSERT(mat);
- DASSERT(val);
- DASSERT( n <= 1 || off >= sizeof(*val) );
- N_MatrixD_inverse += n;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->imatrix_valid)
- CalcMatrixD(mat,true);
- while ( n-- > 0 )
- {
- *val = TransformD3D34(&mat->inv_matrix,val);
- val = (double3*)( (u8*)val + off );
- }
- }
- else if (mat->transform_enabled)
- {
- double3 f; // multiplication is faster than division
- f.x = 1.0 / mat->norm_scale.x;
- f.y = 1.0 / mat->norm_scale.y;
- f.z = 1.0 / mat->norm_scale.z;
- while ( n-- > 0 )
- {
- val->x = ( val->x - mat->norm_translate.x ) * f.x;
- val->y = ( val->y - mat->norm_translate.y ) * f.y;
- val->z = ( val->z - mat->norm_translate.z ) * f.z;
- val = (double3*)( (u8*)val + off );
- }
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: float transform ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- float3 TransformF3MatrixD
- (
- MatrixD_t * mat, // valid data structure
- const
- float3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- N_MatrixD_forward++;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->tmatrix_valid)
- CalcTransMatrixD(mat,true);
- return TransformF3D34(&mat->trans_matrix,val);
- }
- float3 res;
- res.x = val->x * mat->norm_scale.x + mat->norm_translate.x;
- res.y = val->y * mat->norm_scale.y + mat->norm_translate.y;
- res.z = val->z * mat->norm_scale.z + mat->norm_translate.z;
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- float3 InvTransformF3MatrixD
- (
- MatrixD_t * mat, // valid data structure
- const
- float3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- N_MatrixD_inverse++;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->imatrix_valid)
- CalcMatrixD(mat,true);
- return TransformF3D34(&mat->inv_matrix,val);
- }
- float3 res;
- res.x = ( val->x - mat->norm_translate.x ) / mat->norm_scale.x;
- res.y = ( val->y - mat->norm_translate.y ) / mat->norm_scale.y;
- res.z = ( val->z - mat->norm_translate.z ) / mat->norm_scale.z;
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void TransformF3NMatrixD
- (
- MatrixD_t * mat, // valid data structure
- float3 * val, // value array to transform
- int n, // number of 3D vectors in 'val'
- uint off // if n>1: offset from one to next 'val' vector
- )
- {
- DASSERT(mat);
- DASSERT(val);
- DASSERT_MSG( n <= 1 || off >= sizeof(*val), "n=%u,off=%u\n",n,off );
- N_MatrixD_forward += n;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->tmatrix_valid)
- CalcTransMatrixD(mat,true);
- while ( n-- > 0 )
- {
- *val = TransformF3D34(&mat->trans_matrix,val);
- val = (float3*)( (u8*)val + off );
- }
- }
- else if (mat->transform_enabled)
- {
- while ( n-- > 0 )
- {
- val->x = val->x * mat->norm_scale.x + mat->norm_translate.x;
- val->y = val->y * mat->norm_scale.y + mat->norm_translate.y;
- val->z = val->z * mat->norm_scale.z + mat->norm_translate.z;
- val = (float3*)( (u8*)val + off );
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void InvTransformF3NMatrixD
- (
- MatrixD_t * mat, // valid data structure
- float3 * val, // value array to transform
- int n, // number of 3D vectors in 'val'
- uint off // if n>1: offset from one to next 'val' vector
- )
- {
- DASSERT(mat);
- DASSERT(val);
- DASSERT( n <= 1 || off >= sizeof(*val) );
- N_MatrixD_inverse += n;
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if (mat->use_matrix)
- {
- if (!mat->imatrix_valid)
- CalcMatrixD(mat,true);
- while ( n-- > 0 )
- {
- *val = TransformF3D34(&mat->inv_matrix,val);
- val = (float3*)( (u8*)val + off );
- }
- }
- else if (mat->transform_enabled)
- {
- double3 f; // multiplication is faster than division
- f.x = 1.0 / mat->norm_scale.x;
- f.y = 1.0 / mat->norm_scale.y;
- f.z = 1.0 / mat->norm_scale.z;
- while ( n-- > 0 )
- {
- val->x = ( val->x - mat->norm_translate.x ) * f.x;
- val->y = ( val->y - mat->norm_translate.y ) * f.y;
- val->z = ( val->z - mat->norm_translate.z ) * f.z;
- val = (float3*)( (u8*)val + off );
- }
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: direct transform ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- double3 BaseTransformD3MatrixD
- (
- // transform using the base parameters
- MatrixD_t * mat, // valid data structure
- const
- double3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- if (!mat->valid)
- InitializeMatrixD(mat);
- if ( mat->use_matrix > 1 )
- return TransformD3MatrixD(mat,val);
- double3 rot = mat->rotate_rad;
- Mult3f(rot,rot,180.0/M_PI);
- Add3(rot,rot,mat->rotate_deg);
- return TransformHelperD3MatrixD
- ( &mat->scale,
- &mat->scale_origin,
- &mat->shift,
- &rot,
- mat->rotate_origin+0,
- mat->rotate_origin+1,
- mat->rotate_origin+2,
- &mat->translate,
- val
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- double3 NormTransformD3MatrixD
- (
- // transform using the norm parameters
- MatrixD_t * mat, // valid data structure
- const
- double3 * val // value to transform
- )
- {
- DASSERT(mat);
- DASSERT(val);
- if ( !mat->norm_valid && !mat->tmatrix_valid )
- CalcNormMatrixD(mat);
- if ( mat->use_matrix > 1 )
- return TransformD3MatrixD(mat,val);
- return TransformHelperD3MatrixD
- ( &mat->norm_scale,
- 0,
- 0,
- &mat->norm_rotate_deg,
- 0,
- 0,
- 0,
- &mat->norm_translate,
- val
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- double3 TransformHelperD3MatrixD
- (
- // transform using vectors
- double3 *scale, // NULL or scale vector
- double3 *scale_origin, // NULL or origin for scaling
- double3 *shift, // NULL or shift vector
- double3 *rotate_deg, // NULL or rotation in degree
- double3 *xrot_origin, // NULL or origin for x-rotation
- double3 *yrot_origin, // NULL or origin for y-rotation
- double3 *zrot_origin, // NULL or origin for z-rotation
- double3 *translate, // NULL or translation vector
- const
- double3 * val // value to transform
- )
- {
- DASSERT(val);
- double3 res; //, null3 = { 0.0, 0.0, 0.0 };
- //--- scale
- if (!scale)
- res = *val;
- else if (scale_origin)
- {
- res.x = ( val->x - scale_origin->x ) * scale->x + scale_origin->x;
- res.y = ( val->y - scale_origin->y ) * scale->y + scale_origin->y;
- res.z = ( val->z - scale_origin->z ) * scale->z + scale_origin->z;
- }
- else
- {
- res.x = val->x * scale->x;
- res.y = val->y * scale->y;
- res.z = val->z * scale->z;
- }
- //--- shift
- if (shift)
- {
- res.x += shift->x;
- res.y += shift->y;
- res.z += shift->z;
- }
- //--- rotate
- if (rotate_deg)
- {
- uint xyz;
- for ( xyz = 0; xyz < 3; xyz++ )
- {
- const double deg = fmod(rotate_deg->v[xyz]+180.0,360.0) - 180.0;
- if ( fabs(deg) >= MIN_DEGREE )
- {
- uint a = xyz + 2; if ( a >= 3 ) a -= 3;
- uint b = xyz + 1; if ( b >= 3 ) b -= 3;
- double rad = deg * (M_PI/180.0);
- if (xrot_origin)
- {
- const double da = res.v[a] - xrot_origin->v[a];
- const double db = res.v[b] - xrot_origin->v[b];
- rad += atan2(da,db);
- const double len = sqrt(da*da+db*db);
- res.v[a] = sin(rad) * len + xrot_origin->v[a];
- res.v[b] = cos(rad) * len + xrot_origin->v[b];
- }
- else
- {
- rad += atan2(res.v[a],res.v[b]);
- const double len = sqrt(res.v[a]*res.v[a]+res.v[b]*res.v[b]);
- res.v[a] = sin(rad) * len;
- res.v[b] = cos(rad) * len;
- }
- }
- xrot_origin = yrot_origin;
- yrot_origin = zrot_origin;
- }
- }
- //--- translate
- if (translate)
- {
- res.x += translate->x;
- res.y += translate->y;
- res.z += translate->z;
- }
- return res;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// MatrixD_t: printing ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- static ccp print_matrix_stat
- ( MatrixD_t * mat, char * buf, uint bufsize, bool for_inverse )
- {
- DASSERT(buf);
- DASSERT(bufsize>10);
- char *dest = buf, *bufend = buf + bufsize;
- if (mat->scale_enabled)
- dest = StringCopyE(dest,bufend,"+scale");
- if (mat->rotate_enabled)
- dest = StringCopyE(dest,bufend,"+rotate");
- if (mat->translate_enabled)
- dest = StringCopyE(dest,bufend,"+translate");
- if ( mat->use_matrix > 1 && !for_inverse )
- dest = StringCopyE(dest,bufend,",source");
- else if (mat->use_matrix)
- dest = StringCopyE(dest,bufend,",required");
- if ( dest == buf )
- StringCopyE(dest,bufend,"+no transformation");
- return buf+1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void PrintMatrixD
- (
- FILE * f, // file to print to
- uint indent, // indention
- ccp eol, // not NULL: print as 'end of line'
- MatrixD_t * mat, // valid data structure
- uint create, // bitfield for setup:
- // 1: create normals if invalid
- // 2: create transform matrix if invalid
- // 4: create inverse matrix if invalid
- uint print // bitfield print selection:
- // 1: print base vectors
- // 2: print normalized values, if valid
- // 4: print transformation matrix, if valid
- // 8: print inverse matrix, if valid
- // 0x10: print also header, if only 1 section is print
- // 0x20: print all, don't suppress NULL vectors
- // 0x40: print an additional EOL behind each section
- )
- {
- DASSERT(f);
- DASSERT(mat);
- //--- setup
- indent = NormalizeIndent(indent);
- if (!eol)
- eol = "\n";
- ccp sep = print & 0x40 ? eol : "";
- if ( create & 4 )
- CalcMatrixD(mat,true);
- else if ( create & 2 )
- CalcTransMatrixD(mat,true);
- else if ( create & 1 )
- CalcNormMatrixD(mat);
- else if (!mat->valid)
- InitializeMatrixD(mat);
- if (!mat->norm_valid)
- print &= ~2;
- if (!mat->tmatrix_valid)
- print &= ~4;
- else if (mat->use_matrix>1)
- print &= ~1;
- if (!mat->imatrix_valid)
- print &= ~8;
- const uint print_all = print & 0x20;
- uint print_head = print & 0x10;
- print &= 0x0f;
- if ( print != 1 && print != 2 && print != 4 && print != 8 )
- print_head = 1;
- //--- print base vectors
- if ( print & 1 )
- {
- if (print_head)
- fprintf(f,"%*sBase Vectors:%s", indent,"", eol );
- if ( print_all || !IsOne3(mat->scale) )
- fprintf(f,"%*s Scale: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->scale.x, mat->scale.y, mat->scale.z,
- eol );
- if ( print_all || !IsNull3(mat->scale_origin) )
- fprintf(f,"%*s Origin: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->scale_origin.x, mat->scale_origin.y, mat->scale_origin.z,
- eol );
- if ( print_all || !IsNull3(mat->shift) )
- fprintf(f,"%*s Shift: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->shift.x, mat->shift.y, mat->shift.z,
- eol );
- bool print_rot = false;
- if ( print_all || !IsNull3(mat->rotate_deg) )
- {
- print_rot = true;
- fprintf(f,"%*s Rotate/deg: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->rotate_deg.x, mat->rotate_deg.y, mat->rotate_deg.z,
- eol );
- }
- if ( print_all || !IsNull3(mat->rotate_rad) )
- {
- print_rot = true;
- fprintf(f,"%*s Rotate/rad: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->rotate_rad.x, mat->rotate_rad.y, mat->rotate_rad.z,
- eol );
- }
- if (print_rot)
- {
- double3 *d = mat->rotate_origin;
- uint xyz;
- for ( xyz = 0; xyz < 3; xyz++, d++ )
- if ( print_all || !IsNull3(*d) )
- fprintf(f,"%*s %c-origin: %11.3f %11.3f %11.3f%s",
- indent,"", 'x'+xyz,
- d->x, d->y, d->z,
- eol );
- }
- if ( print_all || !IsNull3(mat->translate) )
- fprintf(f,"%*s Translate: %11.3f %11.3f %11.3f%s",
- indent,"",
- mat->translate.x, mat->translate.y, mat->translate.z,
- eol );
- fputs(sep,f);
- }
- //--- print normalized vectors
- if ( print & 2 )
- {
- if (print_head)
- fprintf(f,"%*sNormalized Vectors (seq=%u):%s",
- indent,"", mat->sequence_number, eol );
- fprintf(f,
- "%*s Scale: %11.3f %11.3f %11.3f [%c%c%c]%s"
- "%*s Rotate/deg: %11.3f %11.3f %11.3f [%c%c%c]%s"
- #if TEST0
- "%*s Rotate/rad: %11.3f %11.3f %11.3f%s"
- #endif
- "%*s Translate: %11.3f %11.3f %11.3f [%c%c%c]%s",
- indent,"",
- mat->norm_scale.x, mat->norm_scale.y, mat->norm_scale.z,
- mat->scale_enabled & 1 ? 'x' : '-',
- mat->scale_enabled & 2 ? 'y' : '-',
- mat->scale_enabled & 4 ? 'z' : '-',
- eol,
- indent,"",
- mat->norm_rotate_deg.x, mat->norm_rotate_deg.y, mat->norm_rotate_deg.z,
- mat->rotate_enabled & 1 ? 'x' : '-',
- mat->rotate_enabled & 2 ? 'y' : '-',
- mat->rotate_enabled & 4 ? 'z' : '-',
- eol,
- #if TEST0
- indent,"",
- mat->norm_rotate_rad.x, mat->norm_rotate_rad.y, mat->norm_rotate_rad.z,
- eol,
- #endif
- indent,"",
- mat->norm_translate.x, mat->norm_translate.y, mat->norm_translate.z,
- mat->translate_enabled & 1 ? 'x' : '-',
- mat->translate_enabled & 2 ? 'y' : '-',
- mat->translate_enabled & 4 ? 'z' : '-',
- eol );
- if ( print_all || !IsNull3(mat->norm_pos2d) )
- fprintf(f,"%*s 2D tf-base: %11.3f %11.3f %11.3f (for 2D transform)%s",
- indent,"",
- mat->norm_pos2d.x, mat->norm_pos2d.y, mat->norm_pos2d.z,
- eol );
- fputs(sep,f);
- }
- //--- print transformation matrix
- char buf[50];
- if ( print & 4 )
- {
- if (print_head)
- fprintf(f,"%*sTransformation Matrix (%s):%s",
- indent,"", print_matrix_stat(mat,buf,sizeof(buf),false), eol );
- fprintf(f,
- "%*s x' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%*s y' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%*s z' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%s",
- indent,"",
- mat->trans_matrix.x[0],
- mat->trans_matrix.x[1],
- mat->trans_matrix.x[2],
- mat->trans_matrix.x[3],
- eol,
- indent,"",
- mat->trans_matrix.y[0],
- mat->trans_matrix.y[1],
- mat->trans_matrix.y[2],
- mat->trans_matrix.y[3],
- eol,
- indent,"",
- mat->trans_matrix.z[0],
- mat->trans_matrix.z[1],
- mat->trans_matrix.z[2],
- mat->trans_matrix.z[3],
- eol, sep );
- }
- //--- print inverse matrix
- if ( print & 8 )
- {
- if (print_head)
- fprintf(f,"%*sInverse Matrix (%s):%s",
- indent,"", print_matrix_stat(mat,buf,sizeof(buf),true), eol );
- fprintf(f,
- "%*s x' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%*s y' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%*s z' = %11.3f * x + %11.3f * y + %11.3f * z + %11.3f%s"
- "%s",
- indent,"",
- mat->inv_matrix.x[0],
- mat->inv_matrix.x[1],
- mat->inv_matrix.x[2],
- mat->inv_matrix.x[3],
- eol,
- indent,"",
- mat->inv_matrix.y[0],
- mat->inv_matrix.y[1],
- mat->inv_matrix.y[2],
- mat->inv_matrix.y[3],
- eol,
- indent,"",
- mat->inv_matrix.z[0],
- mat->inv_matrix.z[1],
- mat->inv_matrix.z[2],
- mat->inv_matrix.z[3],
- eol, sep );
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// END ///////////////
- ///////////////////////////////////////////////////////////////////////////////
|