12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945 |
- #if PSX
- #include <kernel.h>
- #include <sys/types.h>
- #include <libetc.h>
- #include <libgte.h>
- #include <libgpu.h>
- #include <stdlib.h>
- #include <inline_c.h>
- #include <gtemac.h>
- #endif
- #include "3dc.h"
- #include "inline.h"
- #define UseTimsPinp Yes
- #define trip_debugger No
- #if trip_debugger
- int testa = 0;
- int testb = 100;
- int testc = 0;
- #endif
- /*
- externs for commonly used global variables and arrays
- */
- #if platform_pc
- extern int sine[];
- extern int cosine[];
- #endif
- extern short ArcCosTable[];
- extern short ArcSineTable[];
- extern short ArcTanTable[];
- extern LONGLONGCH ll_zero;
- extern int NormalFrameTime;
- #if PSX
- extern unsigned long *scratchp;
- #endif
- /*
- Globals
- */
- MATRIXCH IdentityMatrix = {
- ONE_FIXED, 0, 0,
- 0, ONE_FIXED, 0,
- 0, 0, ONE_FIXED
- };
- /*
- Maths functions used by the system
- */
- #if PSX
- inline void ch2psx(MATRIXCH *chm, MATRIX *psxm)
- {
- psxm->m[0][0] = chm->mat11 >> 4;
- psxm->m[0][1] = chm->mat21 >> 4;
- psxm->m[0][2] = chm->mat31 >> 4;
- psxm->m[1][0] = chm->mat12 >> 4;
- psxm->m[1][1] = chm->mat22 >> 4;
- psxm->m[1][2] = chm->mat32 >> 4;
- psxm->m[2][0] = chm->mat13 >> 4;
- psxm->m[2][1] = chm->mat23 >> 4;
- psxm->m[2][2] = chm->mat33 >> 4;
- }
- inline void psx2ch(MATRIX *psxm, MATRIXCH *chm)
- {
-
- chm->mat11 = psxm->m[0][0] << 4;
- chm->mat21 = psxm->m[0][1] << 4;
- chm->mat31 = psxm->m[0][2] << 4;
- chm->mat12 = psxm->m[1][0] << 4;
- chm->mat22 = psxm->m[1][1] << 4;
- chm->mat32 = psxm->m[1][2] << 4;
- chm->mat13 = psxm->m[2][0] << 4;
- chm->mat23 = psxm->m[2][1] << 4;
- chm->mat33 = psxm->m[2][2] << 4;
- }
- #endif
- /* One over sin functions - CDF 4/2/98 */
- extern int oneoversin[4096];
- void ConstructOneOverSinTable(void) {
- int a,sin;
- for (a=0; a<4096; a++) {
- sin=GetSin(a);
- if (sin!=0) {
- oneoversin[a]=DIV_FIXED(ONE_FIXED,sin);
- } else {
- sin=100;
- oneoversin[a]=DIV_FIXED(ONE_FIXED,sin);
- }
- }
- }
- int GetOneOverSin(int a) {
- int b;
- b=a&wrap360;
-
- return(oneoversin[b]);
- }
- /*
- Dot Product Function
- It accepts two pointers to vectors and returns an int result
- */
- int _DotProduct(VECTORCH *vptr1, VECTORCH *vptr2)
- {
- int dp;
- dp = MUL_FIXED(vptr1->vx, vptr2->vx);
- dp += MUL_FIXED(vptr1->vy, vptr2->vy);
- dp += MUL_FIXED(vptr1->vz, vptr2->vz);
- return(dp);
- }
- int DotProduct2d(VECTOR2D *vptr1, VECTOR2D *vptr2)
- {
- int dp;
- dp = MUL_FIXED(vptr1->vx, vptr2->vx);
- dp += MUL_FIXED(vptr1->vy, vptr2->vy);
- return dp;
- }
- /*
- This function returns the distance between two vectors
- */
- int VectorDistance(VECTORCH *v1, VECTORCH *v2)
- {
- VECTORCH v;
- v.vx = v1->vx - v2->vx;
- v.vy = v1->vy - v2->vy;
- v.vz = v1->vz - v2->vz;
- return Magnitude(&v);
- }
- /*
- This function compares the distance between two vectors along each of
- the major axes and returns Yes or No if they are within the cube defined
- by the argument passed.
- */
- int OutcodeVectorDistance(VECTORCH *v1, VECTORCH *v2, int d)
- {
- int i;
- i = v1->vx - v2->vx;
- if(i < 0) i = -i;
- if(i >= d) return No;
- i = v1->vy - v2->vy;
- if(i < 0) i = -i;
- if(i >= d) return No;
- i = v1->vz - v2->vz;
- if(i < 0) i = -i;
- if(i >= d) return No;
- return Yes;
- }
- /*
- Subtract one VECTORCH from another and return the result as a normal
- v3 = Normal(v1 - v2)
- */
- void GetNormalVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3)
- {
- v3->vx = v1->vx - v2->vx;
- v3->vy = v1->vy - v2->vy;
- v3->vz = v1->vz - v2->vz;
- Normalise(v3);
- }
- /*
- Normalise a vector close to, but less than, unit length
- */
- void Renormalise(VECTORCH *nvector)
- {
- int m;
- int xsq, ysq, zsq;
- /* Scale x, y and z */
- nvector->vx >>= 2;
- nvector->vy >>= 2;
- nvector->vz >>= 2;
- /* Normalise */
- xsq = nvector->vx * nvector->vx;
- ysq = nvector->vy * nvector->vy;
- zsq = nvector->vz * nvector->vz;
- m = SqRoot32(xsq + ysq + zsq);
- if(m == 0) m = 1; /* Just in case */
- nvector->vx = (nvector->vx * ONE_FIXED) / m;
- nvector->vy = (nvector->vy * ONE_FIXED) / m;
- nvector->vz = (nvector->vz * ONE_FIXED) / m;
- }
- /*
- Return the shift value required to get one value LTE the other value
- */
- int FindShift32(int value, int limit)
- {
- int shift = 0;
- /*if(limit == 0) exit(0xfa11fa11);*/
- if(value < 0) value = -value;
- while(value > limit) {
- #if trip_debugger
- if(shift > 32) {
- testa = testb / testc;
- }
- #endif
- shift++;
- value >>= 1;
- }
- return shift;
- }
- /*
- Return the largest value of an int array
- */
- int MaxInt(int *iarray, int iarraysize)
- {
- int imax = smallint;
- int i;
- for(i = iarraysize; i!=0; i--) {
- if(imax < *iarray) imax = *iarray;
- iarray++;
- }
- return imax;
- }
- /*
- Return the smallest value of an int array
- */
- int MinInt(int *iarray, int iarraysize)
- {
- int imin = bigint;
- int i;
- for(i = iarraysize; i!=0; i--) {
- if(imin > *iarray) imin = *iarray;
- iarray++;
- }
- return imin;
- }
- /*
- Create Matrix from Euler Angles
- It requires a pointer to some euler angles and a pointer to a matrix
- Construct the matrix elements using the following formula
- Formula for ZXY Matrix
- m11 = cy*cz + sx*sy*sz m12 = -cy*sz + sx*sy*cz m13 = cx*sy
- m21 = cx*sz m22 = cx*cz m23 = -sx
- m31 = -sy*cz + sx*cy*sz m32 = sy*sz + sx*cy*cz m33 = cx*cy
- */
- void CreateEulerMatrix(e, m1)
- EULER *e;
- MATRIXCH *m1;
- {
- #if 0
- SVECTOR eulers;
- eulers.vx=(e->EulerX)&4095;
- eulers.vy=(e->EulerY)&4095;
- eulers.vz=(e->EulerZ)&4095;
- RotMatrix(&eulers,(MATRIX *)scratchp);
- psx2ch((MATRIX *)scratchp,m1);
- #else
- int t, sx, sy, sz, cx, cy, cz;
- sx = GetSin(e->EulerX);
- sy = GetSin(e->EulerY);
- sz = GetSin(e->EulerZ);
- cx = GetCos(e->EulerX);
- cy = GetCos(e->EulerY);
- cz = GetCos(e->EulerZ);
- #if 0
- textprint("Euler Matrix Sines & Cosines\n");
- textprint("%d, %d, %d\n", sx, sy, sz);
- textprint("%d, %d, %d\n", cx, cy, cz);
- #endif
- /* m11 = cy*cz + sx*sy*sz */
- m1->mat11 = MUL_FIXED(cy, cz); /* cy*cz */
- t = MUL_FIXED(sx, sy); /* sx*sy */
- t = MUL_FIXED(t, sz); /* *sz */
- m1->mat11 += t;
- /* m12 = -cy*sz + sx*sy*cz */
- m1->mat12=MUL_FIXED(-cy,sz);
- t=MUL_FIXED(sx,sy);
- t=MUL_FIXED(t,cz);
- m1->mat12+=t;
- /* m13 = cx*sy */
- m1->mat13=MUL_FIXED(cx,sy);
- /* m21 = cx*sz */
- m1->mat21=MUL_FIXED(cx,sz);
- /* m22 = cx*cz */
- m1->mat22=MUL_FIXED(cx,cz);
- /* m23 = -sx */
- m1->mat23=-sx;
- /* m31 = -sy*cz + sx*cy*sz */
- m1->mat31=MUL_FIXED(-sy,cz);
- t=MUL_FIXED(sx,cy);
- t=MUL_FIXED(t,sz);
- m1->mat31+=t;
- /* m32 = sy*sz + sx*cy*cz */
- m1->mat32=MUL_FIXED(sy,sz);
- t=MUL_FIXED(sx,cy);
- t=MUL_FIXED(t,cz);
- m1->mat32+=t;
- /* m33 = cx*cy */
- m1->mat33=MUL_FIXED(cx,cy);
- #endif
- }
- /*
- Create a Unit Vector from three Euler Angles
- */
- void CreateEulerVector(EULER *e, VECTORCH *v)
- {
- int t, sx, sy, sz, cx, cy, cz;
- sx = GetSin(e->EulerX);
- sy = GetSin(e->EulerY);
- sz = GetSin(e->EulerZ);
- cx = GetCos(e->EulerX);
- cy = GetCos(e->EulerY);
- cz = GetCos(e->EulerZ);
- /* x = -sy*cz + sx*cy*sz */
- v->vx = MUL_FIXED(-sy, cz);
- t = MUL_FIXED(sx, cy);
- t = MUL_FIXED(t, sz);
- v->vx += t;
- /* y = sy*sz + sx*cy*cz */
- v->vy = MUL_FIXED(sy, sz);
- t = MUL_FIXED(sx, cy);
- t = MUL_FIXED(t, cz);
- v->vy += t;
- /* z = cx*cy */
- v->vz = MUL_FIXED(cx,cy);
- }
- /*
- Matrix Multiply Function
- A 3x3 Matrix is represented here as
- m11 m12 m13
- m21 m22 m23
- m31 m32 m33
- Row #1 (r1) of the matrix is m11 m12 m13
- Column #1 (c1) of the matrix is m11 m32 m31
- Under multiplication
- m'' = m x m'
- where
- m11'' = c1.r1'
- m12'' = c2.r1'
- m13'' = c3.r1'
- m21'' = c1.r2'
- m22'' = c2.r2'
- m23'' = c3.r2'
- m31'' = c1.r3'
- m32'' = c2.r3'
- m33'' = c3.r3'
- */
- void MatrixMultiply(m1, m2, m3)
- struct matrixch *m1, *m2, *m3;
- {
-
- #if 0
-
- PushMatrix();
- ch2psx(m1,(MATRIX *)scratchp);
- ch2psx(m2,(MATRIX *)(scratchp+(sizeof(MATRIX))));
- MulMatrix0((MATRIX *)scratchp,(MATRIX *)(scratchp+(sizeof(MATRIX))),(MATRIX *)(scratchp+((sizeof(MATRIX)<<1))));
- psx2ch((MATRIX *)(scratchp+((sizeof(MATRIX)<<1))),m3);
- PopMatrix();
-
- #else
-
- MATRIXCH TmpMat;
-
- /* m11'' = c1.r1' */
- TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11);
- TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12);
- TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13);
- /* m12'' = c2.r1' */
- TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11);
- TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12);
- TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13);
- /* m13'' = c3.r1' */
- TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11);
- TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12);
- TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13);
- /* m21'' = c1.r2' */
- TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21);
- TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22);
- TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23);
- /* m22'' = c2.r2' */
- TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21);
- TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22);
- TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23);
- /* m23'' = c3.r2' */
- TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21);
- TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22);
- TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23);
- /* m31'' = c1.r3' */
- TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31);
- TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32);
- TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33);
- /* m32'' = c2.r3' */
- TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31);
- TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32);
- TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33);
- /* m33'' = c3.r3' */
- TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31);
- TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32);
- TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33);
- /* Finally, copy TmpMat to m3 */
- CopyMatrix(&TmpMat, m3);
- #endif
- }
- void PSXAccurateMatrixMultiply(m1, m2, m3)
- struct matrixch *m1, *m2, *m3;
- {
-
- MATRIXCH TmpMat;
-
- /* m11'' = c1.r1' */
- TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11);
- TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12);
- TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13);
- /* m12'' = c2.r1' */
- TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11);
- TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12);
- TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13);
- /* m13'' = c3.r1' */
- TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11);
- TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12);
- TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13);
- /* m21'' = c1.r2' */
- TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21);
- TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22);
- TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23);
- /* m22'' = c2.r2' */
- TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21);
- TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22);
- TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23);
- /* m23'' = c3.r2' */
- TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21);
- TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22);
- TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23);
- /* m31'' = c1.r3' */
- TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31);
- TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32);
- TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33);
- /* m32'' = c2.r3' */
- TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31);
- TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32);
- TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33);
- /* m33'' = c3.r3' */
- TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31);
- TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32);
- TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33);
- /* Finally, copy TmpMat to m3 */
- CopyMatrix(&TmpMat, m3);
- }
- /*
- Transpose Matrix
- */
- void TransposeMatrixCH(m1)
- MATRIXCH *m1;
- {
- int t;
- t=m1->mat12;
- m1->mat12=m1->mat21;
- m1->mat21=t;
- t=m1->mat13;
- m1->mat13=m1->mat31;
- m1->mat31=t;
- t=m1->mat23;
- m1->mat23=m1->mat32;
- m1->mat32=t;
- }
- /*
- Copy Vector
- */
- void CopyVector(VECTORCH *v1, VECTORCH *v2)
- {
- /* Copy VECTORCH v1 -> VECTORCH v2 */
- v2->vx=v1->vx;
- v2->vy=v1->vy;
- v2->vz=v1->vz;
- }
- /*
- Copy Location
- */
- void CopyLocation(VECTORCH *v1, VECTORCH *v2)
- {
- /* Copy VECTORCH v1 -> VECTORCH v2 */
- v2->vx=v1->vx;
- v2->vy=v1->vy;
- v2->vz=v1->vz;
- }
- /*
- Copy Euler
- */
- void CopyEuler(EULER *e1, EULER *e2)
- {
- /* Copy EULER e1 -> EULER e2 */
- e2->EulerX=e1->EulerX;
- e2->EulerY=e1->EulerY;
- e2->EulerZ=e1->EulerZ;
- }
- /*
- Copy Matrix
- */
- void CopyMatrix(MATRIXCH *m1, MATRIXCH *m2)
- {
- /* Copy MATRIXCH m1 -> MATRIXCH m2 */
- m2->mat11=m1->mat11;
- m2->mat12=m1->mat12;
- m2->mat13=m1->mat13;
- m2->mat21=m1->mat21;
- m2->mat22=m1->mat22;
- m2->mat23=m1->mat23;
- m2->mat31=m1->mat31;
- m2->mat32=m1->mat32;
- m2->mat33=m1->mat33;
- }
- /*
- Make a Vector.
- v3 = v1 - v2
- */
- void MakeVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3)
- {
- v3->vx = v1->vx - v2->vx;
- v3->vy = v1->vy - v2->vy;
- v3->vz = v1->vz - v2->vz;
- }
- /*
- Add a Vector.
- v2 = v2 + v1
- */
- void AddVector(VECTORCH *v1, VECTORCH *v2)
- {
- v2->vx += v1->vx;
- v2->vy += v1->vy;
- v2->vz += v1->vz;
- }
- /*
- Subtract a Vector.
- v2 = v2 - v1
- */
- void SubVector(VECTORCH *v1, VECTORCH *v2)
- {
- v2->vx -= v1->vx;
- v2->vy -= v1->vy;
- v2->vz -= v1->vz;
- }
- /*
- Matrix Rotatation of a Vector
- Overwrite the Source Vector with the Rotated Vector
- x' = v.c1
- y' = v.c2
- z' = v.c3
- */
- void _RotateVector(VECTORCH *v, MATRIXCH* m)
- {
- int x, y, z;
-
- x = MUL_FIXED(m->mat11, v->vx);
- x += MUL_FIXED(m->mat21, v->vy);
- x += MUL_FIXED(m->mat31, v->vz);
- y = MUL_FIXED(m->mat12, v->vx);
- y += MUL_FIXED(m->mat22, v->vy);
- y += MUL_FIXED(m->mat32, v->vz);
- z = MUL_FIXED(m->mat13, v->vx);
- z += MUL_FIXED(m->mat23, v->vy);
- z += MUL_FIXED(m->mat33, v->vz);
- v->vx = x;
- v->vy = y;
- v->vz = z;
- }
- /*
- Matrix Rotation of a Source Vector using a Matrix
- Copying to a Destination Vector
- x' = v.c1
- y' = v.c2
- z' = v.c3
- */
- void _RotateAndCopyVector(v1, v2, m)
- VECTORCH *v1;
- VECTORCH *v2;
- MATRIXCH *m;
- {
- v2->vx=MUL_FIXED(m->mat11,v1->vx);
- v2->vx+=MUL_FIXED(m->mat21,v1->vy);
- v2->vx+=MUL_FIXED(m->mat31,v1->vz);
- v2->vy=MUL_FIXED(m->mat12,v1->vx);
- v2->vy+=MUL_FIXED(m->mat22,v1->vy);
- v2->vy+=MUL_FIXED(m->mat32,v1->vz);
- v2->vz=MUL_FIXED(m->mat13,v1->vx);
- v2->vz+=MUL_FIXED(m->mat23,v1->vy);
- v2->vz+=MUL_FIXED(m->mat33,v1->vz);
- }
- /*
- Matrix to Euler Angles
- Maths overflow is a real problem for this function. To prevent overflows
- the matrix Sines and Cosines are calculated using values scaled down by 4.
- sinx = -M23
- cosx = sqr ( 1 - sinx^2 )
- siny = M13 / cosx
- cosy = M33 / cosx
- sinz = M21 / cosx
- cosz = M22 / cosx
- */
- #define m2e_scale 2
- #define ONE_FIXED_S ((ONE_FIXED >> m2e_scale) - 1)
- #define m2e_shift 14
- #define j_and_r_change Yes
- void MatrixToEuler(MATRIXCH *m, EULER *e)
- {
- int x, sinx, cosx, siny, cosy, sinz, cosz;
- int abs_cosx, abs_cosy, abs_cosz;
- int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll;
- int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll;
- #if 0
- textprint("CosMatrixPitch = %d\n", CosMatrixPitch);
- /* WaitForReturn(); */
- #endif
- if(m->mat32 >-65500 && m->mat32<65500)
- {
- /* Yaw */
- /* Pitch */
- #if j_and_r_change
- SineMatrixPitch = -m->mat32;
- #else
- SineMatrixPitch = -m->mat23;
- #endif
- SineMatrixPitch >>= m2e_scale;
- #if 0
- textprint("SineMatrixPitch = %d\n", SineMatrixPitch);
- /* WaitForReturn(); */
- #endif
- CosMatrixPitch = SineMatrixPitch * SineMatrixPitch;
- CosMatrixPitch >>= m2e_shift;
- CosMatrixPitch = -CosMatrixPitch;
- CosMatrixPitch += ONE_FIXED_S;
- CosMatrixPitch *= ONE_FIXED_S;
- CosMatrixPitch = SqRoot32(CosMatrixPitch);
- if(CosMatrixPitch) {
- if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S;
- else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S;
- }
- else CosMatrixPitch = 1;
-
- SineMatrixYaw = WideMulNarrowDiv(
- #if j_and_r_change
- m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #else
- m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #endif
- #if 0
- textprint("SineMatrixYaw = %d\n", SineMatrixYaw);
- /* WaitForReturn(); */
- #endif
- CosMatrixYaw = WideMulNarrowDiv(
- m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #if 0
- textprint("CosMatrixYaw = %d\n", CosMatrixYaw);
- /* WaitForReturn(); */
- #endif
- /* Roll */
- SineMatrixRoll = WideMulNarrowDiv(
- #if j_and_r_change
- m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #else
- m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #endif
- #if 0
- textprint("SineMatrixRoll = %d\n", SineMatrixRoll);
- /* WaitForReturn(); */
- #endif
- CosMatrixRoll = WideMulNarrowDiv(
- m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #if 0
- textprint("CosMatrixRoll = %d\n", CosMatrixRoll);
- /* WaitForReturn(); */
- #endif
-
- /* Tables are for values +- 2^16 */
- sinx = SineMatrixPitch << m2e_scale;
- siny = SineMatrixYaw << m2e_scale;
- sinz = SineMatrixRoll << m2e_scale;
- cosx = CosMatrixPitch << m2e_scale;
- cosy = CosMatrixYaw << m2e_scale;
- cosz = CosMatrixRoll << m2e_scale;
- #if 0
- textprint("sines = %d, %d, %d\n", sinx, siny, sinz);
- textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz);
- /* WaitForReturn(); */
- #endif
- /* Absolute Cosines */
- abs_cosx = cosx;
- if(abs_cosx < 0) abs_cosx = -abs_cosx;
- abs_cosy = cosy;
- if(abs_cosy < 0) abs_cosy = -abs_cosy;
- abs_cosz = cosz;
- if(abs_cosz < 0) abs_cosz = -abs_cosz;
- /* Euler X */
- if(abs_cosx > Cosine45) {
- x = ArcSin(sinx);
- if(cosx < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosx);
- if(sinx < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerX = x;
- /* Euler Y */
- if(abs_cosy > Cosine45) {
- x = ArcSin(siny);
- if(cosy < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosy);
- if(siny < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerY = x;
- /* Euler Z */
- if(abs_cosz > Cosine45) {
- x = ArcSin(sinz);
- if(cosz < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosz);
- if(sinz < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerZ = x;
- }
- else //singularity case
- {
- if(m->mat32>0)
- e->EulerX = 3072;
- else
- e->EulerX = 1024;
-
- e->EulerZ=0;
-
- /* Yaw */
-
- siny = -m->mat13 ;
- cosy = m->mat11 ;
- abs_cosy = cosy;
- if(abs_cosy < 0) abs_cosy = -abs_cosy;
- if(abs_cosy > Cosine45) {
- x = ArcSin(siny);
- if(cosy < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosy);
- if(siny < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerY = x;
- }
- #if 0
- textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n",
- e->EulerX,
- e->EulerY,
- e->EulerZ
- );
- /* WaitForReturn(); */
- #endif
- }
- #if 1
- #define j_and_r_change_2 Yes
- void MatrixToEuler2(MATRIXCH *m, EULER *e)
- {
- int x, sinx, cosx, siny, cosy, sinz, cosz;
- int abs_cosx, abs_cosy, abs_cosz;
- int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll;
- int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll;
- /* Pitch */
- #if j_and_r_change_2
- SineMatrixPitch = -m->mat32;
- #else
- SineMatrixPitch = -m->mat23;
- #endif
- SineMatrixPitch >>= m2e_scale;
- #if 0
- textprint("SineMatrixPitch = %d\n", SineMatrixPitch);
- /* WaitForReturn(); */
- #endif
- CosMatrixPitch = SineMatrixPitch * SineMatrixPitch;
- CosMatrixPitch >>= m2e_shift;
- CosMatrixPitch = -CosMatrixPitch;
- CosMatrixPitch += ONE_FIXED_S;
- CosMatrixPitch *= ONE_FIXED_S;
- CosMatrixPitch = SqRoot32(CosMatrixPitch);
- if(CosMatrixPitch) {
- if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S;
- else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S;
- }
- else CosMatrixPitch = 1;
- #if 0
- textprint("CosMatrixPitch = %d\n", CosMatrixPitch);
- /* WaitForReturn(); */
- #endif
- /* Yaw */
- SineMatrixYaw = WideMulNarrowDiv(
- #if j_and_r_change_2
- m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #else
- m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #endif
- #if 0
- textprint("SineMatrixYaw = %d\n", SineMatrixYaw);
- /* WaitForReturn(); */
- #endif
- CosMatrixYaw = WideMulNarrowDiv(
- m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #if 0
- textprint("CosMatrixYaw = %d\n", CosMatrixYaw);
- /* WaitForReturn(); */
- #endif
- /* Roll */
- SineMatrixRoll = WideMulNarrowDiv(
- #if j_and_r_change_2
- m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #else
- m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #endif
- #if 0
- textprint("SineMatrixRoll = %d\n", SineMatrixRoll);
- /* WaitForReturn(); */
- #endif
- CosMatrixRoll = WideMulNarrowDiv(
- m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
- #if 0
- textprint("CosMatrixRoll = %d\n", CosMatrixRoll);
- /* WaitForReturn(); */
- #endif
- /* Tables are for values +- 2^16 */
- sinx = SineMatrixPitch << m2e_scale;
- siny = SineMatrixYaw << m2e_scale;
- sinz = SineMatrixRoll << m2e_scale;
- cosx = CosMatrixPitch << m2e_scale;
- cosy = CosMatrixYaw << m2e_scale;
- cosz = CosMatrixRoll << m2e_scale;
- #if 0
- textprint("sines = %d, %d, %d\n", sinx, siny, sinz);
- textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz);
- /* WaitForReturn(); */
- #endif
- /* Absolute Cosines */
- abs_cosx = cosx;
- if(abs_cosx < 0) abs_cosx = -abs_cosx;
- abs_cosy = cosy;
- if(abs_cosy < 0) abs_cosy = -abs_cosy;
- abs_cosz = cosz;
- if(abs_cosz < 0) abs_cosz = -abs_cosz;
- /* Euler X */
- if(abs_cosx > Cosine45) {
- x = ArcSin(sinx);
- if(cosx < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosx);
- if(sinx < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change_2 == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerX = x;
- /* Euler Y */
- if(abs_cosy > Cosine45) {
- x = ArcSin(siny);
- if(cosy < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosy);
- if(siny < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change_2 == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerY = x;
- /* Euler Z */
- if(abs_cosz > Cosine45) {
- x = ArcSin(sinz);
- if(cosz < 0) {
- x = -x;
- x += deg180;
- x &= wrap360;
- }
- }
- else {
- x = ArcCos(cosz);
- if(sinz < 0) {
- x = -x;
- x &= wrap360;
- }
- }
- #if (j_and_r_change_2 == No)
- x = -x;
- x &= wrap360;
- #endif
- e->EulerZ = x;
- #if 0
- textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n",
- e->EulerX,
- e->EulerY,
- e->EulerZ
- );
- /* WaitForReturn(); */
- #endif
- }
- #endif
- /*
- Normalise a Matrix
- Dot the three vectors together (XY, XZ, YZ) and take the two nearest to
- 90ø from each other. Cross them to create a new third vector, then cross
- the first and third to create a new second.
- */
- void MNormalise(MATRIXCH *m)
- {
- VECTORCH *x = (VECTORCH *) &m->mat11;
- VECTORCH *y = (VECTORCH *) &m->mat21;
- VECTORCH *z = (VECTORCH *) &m->mat31;
- int dotxy = Dot(x, y);
- int dotxz = Dot(x, z);
- int dotyz = Dot(y, z);
- VECTORCH *s;
- VECTORCH *t;
- VECTORCH u;
- VECTORCH v;
- VECTORCH zero = {0, 0, 0};
- #if 0
- textprint("dotxy = %d\n", dotxy);
- textprint("dotxz = %d\n", dotxz);
- textprint("dotyz = %d\n", dotyz);
- #endif
- #if 0
- /* TEST */
- dotxy = 0;
- dotxz = 0;
- dotyz = 1;
- #endif
- #if 0
- textprint("%d %d %d\n",
- x->vx,
- x->vy,
- x->vz
- );
- textprint("%d %d %d\n",
- y->vx,
- y->vy,
- y->vz
- );
- textprint("%d %d %d\n",
- z->vx,
- z->vy,
- z->vz
- );
- #endif
- /* Find the two vectors nearest 90ø */
- if(dotxy > dotxz && dotxy > dotyz) {
- /* xy are the closest to 90ø */
- /*textprint("xy\n");*/
- s = x;
- t = y;
- MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
- MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
- v.vx = -v.vx;
- v.vy = -v.vy;
- v.vz = -v.vz;
- CopyVector(&u, z);
- CopyVector(&v, y);
- }
- else if(dotxz > dotxy && dotxz > dotyz) {
- /* xz are the closest to 90ø */
- /*textprint("xz\n");*/
- s = x;
- t = z;
- MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
- u.vx = -u.vx;
- u.vy = -u.vy;
- u.vz = -u.vz;
- MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
- CopyVector(&u, y);
- CopyVector(&v, z);
- }
- else {
- /* yz are the closest to 90ø */
- /*textprint("yz\n");*/
- s = y;
- t = z;
- MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
- MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
- v.vx = -v.vx;
- v.vy = -v.vy;
- v.vz = -v.vz;
- CopyVector(&u, x);
- CopyVector(&v, z);
- }
- #if 0
- textprint("%d %d %d\n",
- x->vx,
- x->vy,
- x->vz
- );
- textprint("%d %d %d\n",
- y->vx,
- y->vy,
- y->vz
- );
- textprint("%d %d %d\n",
- z->vx,
- z->vy,
- z->vz
- );
- #endif
- #if 0
- textprint("mag. x = %d\n", Magnitude(x));
- textprint("mag. y = %d\n", Magnitude(y));
- textprint("mag. z = %d\n", Magnitude(z));
- #endif
- /*WaitForReturn();*/
- }
- /*
- ArcCos
- In: COS value as -65,536 -> +65,536.
- Out: Angle in 0 -> 4095 form.
- Notes:
- The angle returned is in the range 0 -> 2,047 since the sign of SIN
- is not known.
- ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
- ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
- -65,536 = 180 Degrees
- 0 = 90 Degrees
- +65,536 = 0 Degrees
- The table has 4,096 entries.
- */
- int ArcCos(int c)
- {
- short acos;
- if(c < (-(ONE_FIXED - 1))) c = -(ONE_FIXED - 1);
- else if(c > (ONE_FIXED - 1)) c = ONE_FIXED - 1;
- #if 0
- c = c >> 5; /* -64k -> +64k becomes -2k -> +2k */
- c += 2048; /* -2k -> +2k becomes 0 -> 4k */
- #endif
- acos = ArcCosTable[(c >> 5) + 2048];
- return (int) (acos & wrap360);
- }
- /*
- ArcSin
- In: SIN value in ax as -65,536 -> +65,536.
- Out: Angle in 0 -> 4095 form in ax.
- Notes:
- The angle returned is in the range -1,024 -> 1,023 since the sign of COS
- is not known.
- ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
- ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
- -65,536 = 270 Degrees
- 0 = 0 Degrees
- +65,536 = 90 Degrees
- The table has 4,096 entries.
- */
- int ArcSin(int s)
- {
- short asin;
- if(s < (-(ONE_FIXED - 1))) s = -(ONE_FIXED - 1);
- else if(s > (ONE_FIXED - 1)) s = ONE_FIXED - 1;
- #if 0
- s = s >> 5; /* -64k -> +64k becomes -2k -> +2k */
- s += 2048; /* -2k -> +2k becomes 0 -> 4k */
- #endif
- asin = ArcSineTable[(s >> 5) + 2048];
- return (int) (asin & wrap360);
- }
- /*
- ArcTan
- Pass (x,z)
- And ATN(x/z) is returned such that:
- 000ø is Map North
- 090ø is Map East
- 180ø is Map South
- 270ø is Map West
- */
- int ArcTan(height_x, width_z)
- int height_x,width_z;
- {
- int abs_height_x, abs_width_z, angle, sign, signsame, temp;
- sign=0;
- if((height_x<0 && width_z<0) || (height_x>=0 && width_z>=0))
- signsame=Yes;
- else
- signsame=No;
- abs_height_x=height_x;
- if(abs_height_x<0) abs_height_x=-abs_height_x;
- abs_width_z=width_z;
- if(abs_width_z<0) abs_width_z=-abs_width_z;
- /*
- Find ATN
- */
- if(width_z==0) angle=-deg90;
- else if(abs_width_z==abs_height_x)
- angle=deg45;
- else {
- if(abs_width_z>abs_height_x) {
- temp=abs_width_z;
- abs_width_z=abs_height_x;
- abs_height_x=temp;
- sign=-1;
- }
- if(abs_height_x!=0)
- /* angle = (abs_width_z << 8) / abs_height_x; */
- angle = DIV_INT((abs_width_z << 8), abs_height_x);
- else
- angle=deg22pt5;
- angle=ArcTanTable[angle];
- if(sign>=0) {
- angle=-angle;
- angle+=deg90;
- }
- }
- if(signsame==No) angle=-angle;
- if(width_z<=0) angle+=deg180;
- angle&=wrap360;
- return(angle);
- }
- /*
- Matrix from Z-Vector
- */
- void MatrixFromZVector(VECTORCH *v, MATRIXCH *m)
- {
- VECTORCH XVector;
- VECTORCH YVector;
- VECTORCH zero = {0, 0, 0};
- XVector.vx = v->vz;
- XVector.vy = 0;
- XVector.vz = -v->vx;
- Normalise(&XVector);
- MakeNormal(&zero, &XVector, v, &YVector);
- m->mat11 = XVector.vx;
- m->mat12 = XVector.vy;
- m->mat13 = XVector.vz;
- m->mat21 = -YVector.vx;
- m->mat22 = -YVector.vy;
- m->mat23 = -YVector.vz;
- m->mat31 = v->vx;
- m->mat32 = v->vy;
- m->mat33 = v->vz;
- }
- /*
- Distance Functions
- */
- /*
- Foley and Van Dam 2d distance function
- WARNING! Returns distance x 3
- Here is the F & VD distance function:
- x + z + (max(x,z) * 2)
- ----------------------
- 3
- */
- int FandVD_Distance_2d(VECTOR2D *v0, VECTOR2D *v1)
- {
- int max;
- int d;
- int dx = v1->vx - v0->vx;
- int dy = v1->vy - v0->vy;
- if(dx < 0) dx = -dx;
- if(dy < 0) dy = -dy;
- if(dx > dy) max = dx;
- else max = dy;
- d = (dx + dy + (max * 2));
- return d;
- }
- /*
- Foley and Van Dam 3d distance function
- WARNING! Returns distance x 9
- For a 3d version, calculate (f(f(x,y), y*3))/9
- */
- int FandVD_Distance_3d(VECTORCH *v0, VECTORCH *v1)
- {
- int dxy, max;
- int dz = v1->vz - v0->vz;
- if(dz < 0) dz = -dz;
- dz *= 3;
- dxy = FandVD_Distance_2d((VECTOR2D *) v0, (VECTOR2D *) v1);
- if(dxy > dz) max = dxy;
- else max = dz;
- return (dxy + dz + (max * 2));
- }
- /*
- NextLowPower2() returns the next lowest power of 2 of the passed value.
- e.g. 18 is returned as 16.
- */
- int NextLowPower2(int i)
- {
- int n = 1;
- while(n <= i)
- n <<= 1;
- return n >> 1;
- }
- /*
- Transform a world location into the local space of the passed matrix and
- location.
- Vector v1 is transformed to v2
- It is made relative to vector v3 and rotated using matrix m transposed
- A possible use is the transformation of world points into the local space
- of a display block
- e.g.
- MakeVectorLocal(&v1, &v2, &dptr->ObWorld, &dptr->ObMat);
- This would place vector v2 into the local space of display block dptr
- */
- void MakeVectorLocal(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3, MATRIXCH *m)
- {
- MATRIXCH transmat;
- CopyMatrix(m, &transmat);
- TransposeMatrixCH(&transmat);
- v2->vx = v1->vx - v3->vx;
- v2->vy = v1->vy - v3->vy;
- v2->vz = v1->vz - v3->vz;
- RotateVector(v2, &transmat);
- }
- /*
- Returns "Yes" if "point" is inside "polygon"
- **************************************************
- WARNING!! Point and Polygon Data are OVERWRITTEN!!
- **************************************************
- The function requires point to be an integer array containing a single
- XY pair. The number of points must be passed too.
- Pass the size of the polygon point e.g. A Gouraud polygon has points X,Y,I
- so its point size would be 3.
- Item Polygon Point Size
- ---- ------------------
- I_Polygon 2
- I_GouraudPolygon 3
- I_2dTexturedPolygon 4
- I_3dTexturedPolygon, 5
- I_Gouraud2dTexturedPolygon 5
- I_Polygon_ZBuffer 3
- I_GouraudPolygon_ZBuffer 4
- PASS ONLY POSITIVE COORDINATES!
- */
- int PointInPolygon(int *point, int *polygon, int c, int ppsize)
- {
- #if UseTimsPinp
- /* Tim's New Point In Polygon test-- hopefully much faster, */
- /* certainly much smaller. */
- /* Uses Half-Line test for point-in-2D-polygon test */
- /* Tests the half-line going from the point in the direction of positive z */
- int x, z; /* point */
- int sx, sz; /* vertex 1 */
- int *polyp; /* vertex 2 pointer */
- int t;
- int dx, dz; /* ABS(vertex 2 - vertex 1) */
- int sgnx; /* going left or going right */
- int intersects; /* number of intersections so far discovered */
- LONGLONGCH a_ll, b_ll;
- /* reject lines and points */
- if (c < 3) return(No);
- intersects = 0;
- x = point[ix];
- z = point[iy]; /* ! */
- /* get last point */
- polyp = polygon + ((c - 1) * ppsize);
- sx = polyp[0];
- sz = polyp[1];
- /* go back to first point */
- polyp = polygon;
- /* for each point */
- while (0 != c)
- {
- /* is this line straddling the x co-ordinate of the point? */
- /* if not it is not worth testing for intersection with the half-line */
- /* we must be careful to get the strict and non-stict inequalities */
- /* correct, or we may count intersections with vertices the wrong number */
- /* of times. */
- sgnx = 0;
- if (sx < x && x <= polyp[0])
- {
- /* going right */
- sgnx = 1;
- dx = polyp[0] - sx;
- }
- if (polyp[0] < x && x <= sx)
- {
- /* going left */
- sgnx = -1;
- dx = sx - polyp[0];
- }
- /* if sgnx is zero then neither of the above conditions are true, */
- /* hence the line does not straddle the point in x */
- if (0 != sgnx)
- {
- /* next do trivial cases of line totally above or below point */
- if (z < sz && z < polyp[1])
- {
- /* line totally above point -- intersection */
- intersects++;
- }
- else if (z <= sz || z <= polyp[1])
- {
- /* line straddles point in both x and z -- we must do interpolation */
- /* get absolute differences between line end z co-ordinates */
- dz = (sz < polyp[1])?(polyp[1] - sz):(sz - polyp[1]);
- /* B504 is the square root of 7FFFFFFF */
- if (0xB504L < dx || 0xB504L < dz)
- {
- /* LARGE line -- use 64-bit values */
- /* interpolate z */
- MUL_I_WIDE(polyp[1] - sz, x - sx, &a_ll);
- MUL_I_WIDE(polyp[0] - sx, z - sz, &b_ll);
- if(CMP_LL(&a_ll, &b_ll) == sgnx)
- {
- /* we have an intersection */
- intersects++;
- }
- }
- else
- {
- /* small line -- use 32-bit values */
- /* interpolate z */
- t = (polyp[1] - sz) * (x - sx) - (polyp[0] - sx) * (z - sz);
- if (t < 0 && sgnx < 0 || 0 < t && 0 < sgnx)
- {
- /* we have an intersection */
- intersects++;
- }
- }
- } /* (if line straddles point in z) */
- } /* (if line straddles point in x) */
- /* get next line : */
- /* new vertex 1 is old vertex 2 */
- sx = polyp[0];
- sz = polyp[1];
- /* new vertex 2 is next point */
- polyp += ppsize;
- /* next vertex */
- c--;
- }
- if (intersects & 1)
- {
- /* Odd number of intersections -- point is inside polygon */
- return(Yes);
- }
- else
- {
- /* even number of intersections -- point is outside polygon */
- return(No);
- }
- #else
- int i;
- int si, ti;
- int s0, t0;
- int s1, t1;
- int *v0;
- int *v1;
- int ivdot, ivdotcnt, sgn_currivdot, sgn_ivdot, ivstate;
- int ns, nt;
- int x_scale, y_scale;
- int DotNudge;
- int x, z;
- LONGLONGCH xx;
- LONGLONGCH zz;
- LONGLONGCH xx_tmp;
- LONGLONGCH zz_tmp;
- VECTORCH PolyAvgPt;
- /* Reject points and lines */
- if(c < 3) return No;
- /* Find the average point */
- v0 = polygon;
- EQUALS_LL(&xx, &ll_zero);
- EQUALS_LL(&zz, &ll_zero);
- for(i = c; i!=0; i--) {
- x = v0[0];
- z = v0[1];
- IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */
- IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */
- ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */
- ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */
- v0 += ppsize;
- }
- PolyAvgPt.vx = NarrowDivide(&xx, c);
- PolyAvgPt.vz = NarrowDivide(&zz, c);
- /* Centre the polygon */
- v0 = polygon;
- for(i = c; i!=0; i--) {
- v0[0] -= PolyAvgPt.vx;
- v0[1] -= PolyAvgPt.vz;
- v0 += ppsize;
- }
- /* Centre the test point */
- point[0] -= PolyAvgPt.vx;
- point[1] -= PolyAvgPt.vz;
- /* Scale to avoid maths overflow */
- v0 = polygon;
- s0 = 0;
- t0 = 0;
- for(i = c; i!=0; i--) {
- si = v0[0]; if(si < 0) si = -si;
- if(si > s0) s0 = si;
- ti = v0[1]; if(ti < 0) ti = -ti;
- if(ti > t0) t0 = ti;
- v0 += ppsize;
- }
- si = point[ix]; if(si < 0) si = -si;
- if(si > s0) s0 = si;
- ti = point[iy]; if(ti < 0) ti = -ti;
- if(ti > t0) t0 = ti;
- #if 0
- textprint("\nmax x = %d\n", s0);
- textprint("max y = %d\n", t0);
- #endif
- x_scale = FindShift32(s0, 16383);
- y_scale = FindShift32(t0, 16383);
- #if 0
- textprint("scales = %d, %d\n", x_scale, y_scale);
- #endif
- v0 = polygon;
- for(i = c; i!=0; i--) {
- v0[0] >>= x_scale;
- v0[1] >>= y_scale;
- /*textprint("(%d, %d)\n", v0[0], v0[1]);*/
- v0 += ppsize;
- }
- point[ix] >>= x_scale;
- point[iy] >>= y_scale;
- #if 1
- /* Clockwise or Anti-Clockwise? */
- ns = -(polygon[iy + ppsize] - polygon[iy]);
- nt = (polygon[ix + ppsize] - polygon[ix]);
- si = polygon[(ppsize*2) + ix] - polygon[ix];
- ti = polygon[(ppsize*2) + iy] - polygon[iy];
- ivdot = (ns * si) + (nt * ti);
- if(ivdot < 0) DotNudge = -1;
- else DotNudge = 1;
- #endif
- #if 0
- if(ivdot < 0) textprint("Clockwise\n");
- WaitForReturn();
- #endif
- /* Point to test */
- si = point[ix];
- ti = point[iy];
- #if 0
- textprint("p_test %d, %d\n", si, ti);
- #endif
- /* Polygon Vector pointers */
- v0 = polygon;
- v1 = v0 + ppsize;
- /* Dot result monitor */
- ivdotcnt = 0;
- ivstate = Yes; /* assume inside */
- /* Test v(s, t) against the vectors */
- for(i = c; i!=0 && ivstate == Yes; i--) {
- /* second vector pointer wraps once */
- if(i == 1) v1 = polygon;
- /* get the vector */
- s0 = v0[ix];
- t0 = v0[iy];
- s1 = v1[ix];
- t1 = v1[iy];
- #if 0
- textprint("%d,%d; %d,%d\n", s0, t0, s1, t1);
- #endif
- /* get the vector normal */
- ns = -(t1 - t0); /* s -> -t */
- nt = s1 - s0; /* t -> s */
- /* Dot with intersection point */
- ivdot = (ns * (si - s0)) + (nt * (ti - t0));
- /* TEST */
- ivdot += DotNudge;
- sgn_ivdot = 1;
- if(ivdot < 0) sgn_ivdot = -1;
- /* only continue if current dot is same as last, else quit */
- if(ivdotcnt == 0) sgn_currivdot = sgn_ivdot;
- else {
- if(sgn_ivdot != sgn_currivdot) ivstate = No;
- sgn_currivdot = sgn_ivdot;
- }
- v0 += ppsize;
- v1 += ppsize;
- ivdotcnt++;
- }
- if(ivstate) return Yes;
- else return No;
- #endif
- }
- /*
- #defines and statics required for Jamie's Most Excellent
- random number generator
- */
- #define DEG_3 31
- #define SEP_3 3
- static long table [DEG_3] =
- {
- -851904987, -43806228, -2029755270, 1390239686, -1912102820,
- -485608943, 1969813258, -1590463333, -1944053249, 455935928,
- 508023712, -1714531963, 1800685987, -2015299881, 654595283,
- -1149023258, -1470005550, -1143256056, -1325577603, -1568001885,
- 1275120390, -607508183, -205999574, -1696891592, 1492211999,
- -1528267240, -952028296, -189082757, 362343714, 1424981831,
- 2039449641
- };
- #define TABLE_END (table + sizeof (table) / sizeof (table [0]))
- static long * front_ptr = table + SEP_3;
- static long * rear_ptr = table;
- /*
- This code (FastRandom and SetFastRandom) stolen from Jamie Lokier
- September 95. The original version was part of a C library
- implementation
- */
- /* This is derived from the GNU C library source, which is in turn
- derived from Berkeley source. The algorithm, the polynomial, and the
- initial numbers are the same, but the code has been reworked for the
- needs of this version.
- This version doesn't support different types of random number
- generators, or saving and restoring the state. It is fast, short and
- as simple as it can be while still generating numbers as good as the
- Berkeley one. The basic algorithm is to have a linear-feedback shift
- register, whose bits are the least significant bits of each word in
- the `table' array. The higher-order bits are generated by carries
- from the arithmetic on the shift register bits, and have an even
- longer period than the shift register. */
- /* x**31 + x**3 + 1. */
- void SetSeededFastRandom(int seed);
- void SetFastRandom(void)
- {
- int i;
- long number = GetTickCount();
- for(i = 0; i < DEG_3; ++i) {
- number = 1103515145 * number + 12345;
- table[i] = number;
- }
- front_ptr = table + SEP_3;
- rear_ptr = table;
- for(i = 0; i < 10 * DEG_3; ++i)
- (void) FastRandom ();
- SetSeededFastRandom(FastRandom());
- }
- int FastRandom(void)
- {
- long i;
- /*
- Discard least random bit.
- Shift as unsigned to avoid replicating sign bit.
- Faster than masking.
- */
- *front_ptr += *rear_ptr;
- i = (long) ((unsigned long) *front_ptr >> 1);
- /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
- ++front_ptr;
- if(front_ptr < TABLE_END) {
- ++rear_ptr;
- if (rear_ptr < TABLE_END) return i;
- rear_ptr = table;
- }
- else { /* front_ptr >= TABLE_END */
- front_ptr = table;
- ++rear_ptr;
- }
- return (int) i;
- }
- /*a second copy of the random number generator for getting random numbers from a single seed*/
- #define SEEDED_DEG_3 13
- #define SEEDED_SEP_3 3
- static long seeded_table [SEEDED_DEG_3];
- #define SEEDED_TABLE_END (seeded_table + sizeof (seeded_table) / sizeof (seeded_table [0]))
- static long * seeded_front_ptr = seeded_table + SEEDED_SEP_3;
- static long * seeded_rear_ptr = seeded_table;
- int SeededFastRandom(void)
- {
- long i;
- /*
- Discard least random bit.
- Shift as unsigned to avoid replicating sign bit.
- Faster than masking.
- */
- *seeded_front_ptr += *seeded_rear_ptr;
- i = (long) ((unsigned long) *seeded_front_ptr >> 1);
- /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
- ++seeded_front_ptr;
- if(seeded_front_ptr < SEEDED_TABLE_END) {
- ++seeded_rear_ptr;
- if (seeded_rear_ptr < SEEDED_TABLE_END) return i;
- seeded_rear_ptr = seeded_table;
- }
- else { /* front_ptr >= TABLE_END */
- seeded_front_ptr = seeded_table;
- ++seeded_rear_ptr;
- }
- return (int) i;
- }
- void SetSeededFastRandom(int seed)
- {
- int i;
- long number = seed;
- for(i = 0; i < SEEDED_DEG_3; ++i) {
- number = 1103515145 * number + 12345;
- seeded_table[i] = number;
- }
- seeded_front_ptr = seeded_table + SEEDED_SEP_3;
- seeded_rear_ptr = seeded_table;
- for(i = 0; i < 2 * SEEDED_DEG_3; ++i)
- (void) SeededFastRandom ();
- }
- #if StandardShapeLanguage
- /*
- Calculate the average point on this polygon
- */
- void PolyAveragePoint(POLYHEADER *pheader, int *spts, VECTORCH *apt)
- {
- int x, y, z;
- LONGLONGCH xx;
- LONGLONGCH yy;
- LONGLONGCH zz;
- LONGLONGCH xx_tmp;
- LONGLONGCH yy_tmp;
- LONGLONGCH zz_tmp;
- int *mypolystart = &pheader->Poly1stPt;
- int numpolypts;
- /* Find the average point */
- EQUALS_LL(&xx, &ll_zero);
- EQUALS_LL(&yy, &ll_zero);
- EQUALS_LL(&zz, &ll_zero);
- numpolypts = 0;
- while(*mypolystart != Term) {
- x = *(spts + *mypolystart + ix);
- y = *(spts + *mypolystart + iy);
- z = *(spts + *mypolystart + iz);
- IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */
- IntToLL(&yy_tmp, &y); /* yy_tmp = (long long)y */
- IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */
- ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */
- ADD_LL_PP(&yy, &yy_tmp); /* yy += yy_tmp */
- ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */
- numpolypts++;
- mypolystart++;
- }
- apt->vx = NarrowDivide(&xx, numpolypts);
- apt->vy = NarrowDivide(&yy, numpolypts);
- apt->vz = NarrowDivide(&zz, numpolypts);
- }
- #endif /* StandardShapeLanguage */
- /* KJL 15:07:39 01/08/97 - Returns the magnitude of the
- cross product of two vectors a and b. */
- int MagnitudeOfCrossProduct(VECTORCH *a, VECTORCH *b)
- {
- VECTORCH c;
-
- c.vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy);
- c.vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz);
- c.vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx);
-
- return Magnitude(&c);
- }
- /* KJL 15:08:01 01/08/97 - sets the vector c to be the
- cross product of the vectors a and b. */
- void CrossProduct(VECTORCH *a, VECTORCH *b, VECTORCH *c)
- {
- c->vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy);
- c->vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz);
- c->vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx);
- }
- /* KJL 12:01:08 7/16/97 - returns the magnitude of a vector - max error about 13%, though average error
- less than half this. Very fast compared to other approaches. */
- int Approximate3dMagnitude(VECTORCH *v)
- {
- int dx,dy,dz;
- dx = v->vx;
- if (dx<0) dx = -dx;
-
- dy = v->vy;
- if (dy<0) dy = -dy;
-
- dz = v->vz;
- if (dz<0) dz = -dz;
-
-
- if (dx>dy)
- {
- if (dx>dz)
- {
- return dx + ((dy+dz)>>2);
- }
- else
- {
- return dz + ((dy+dx)>>2);
- }
- }
- else
- {
- if (dy>dz)
- {
- return dy + ((dx+dz)>>2);
- }
- else
- {
- return dz + ((dx+dy)>>2);
- }
- }
- }
- /*
- Quaternion to Matrix
- This is the column(row) matrix that is produced. Our matrices are
- row(column) and so are a transpose of this.
- 1 - 2yy - 2zz 2xy + 2wz 2xz - 2wy
- 2xy - 2wz 1 - 2xx - 2zz 2yz + 2wx
- 2xz + 2wy 2yz - 2wx 1 - 2xx - 2yy
- */
- void QuatToMat(QUAT *q,MATRIXCH *m)
- {
- int q_w, q_x, q_y, q_z;
- int q_2x, q_2y, q_2z;
- int q_2xw;
- int q_2xx;
- int q_2xy;
- int q_2xz;
- int q_2yw;
- int q_2yy;
- int q_2yz;
- int q_2zw;
- int q_2zz;
- /*
- The most efficient way to create the matrix is as follows
- 1/ Double x, y & z
- */
- q_w=q->quatw;
- q_x=q->quatx;
- q_y=q->quaty;
- q_z=q->quatz;
- q_2x=q_x*2;
- q_2y=q_y*2;
- q_2z=q_z*2;
- /*
- 2/ Form their products with w, x, y & z
- These are
- (2x)w (2y)w (2z)w
- (2x)x
- (2x)y (2y)y
- (2x)z (2y)z (2z)z
- */
- q_2xw=MUL_FIXED(q_2x,q_w);
- q_2yw=MUL_FIXED(q_2y,q_w);
- q_2zw=MUL_FIXED(q_2z,q_w);
- q_2xx=MUL_FIXED(q_2x,q_x);
- q_2xy=MUL_FIXED(q_2x,q_y);
- q_2yy=MUL_FIXED(q_2y,q_y);
- q_2xz=MUL_FIXED(q_2x,q_z);
- q_2yz=MUL_FIXED(q_2y,q_z);
- q_2zz=MUL_FIXED(q_2z,q_z);
- /* mat11 = 1 - 2y^2 - 2z^2 */
- m->mat11=ONE_FIXED-q_2yy-q_2zz;
- /* mat12 = 2xy - 2wz */
- m->mat12=q_2xy-q_2zw;
- /* mat13 = 2xz + 2wy */
- m->mat13=q_2xz+q_2yw;
- /* mat21 = 2xy + 2wz */
- m->mat21=q_2xy+q_2zw;
- /* mat22 = 1 - 2x^2 - 2z^2 */
- m->mat22=ONE_FIXED-q_2xx-q_2zz;
- /* mat23 = 2yz - 2wx */
- m->mat23=q_2yz-q_2xw;
- /* mat31 = 2xz - 2wy */
- m->mat31=q_2xz-q_2yw;
- /* mat32 = 2yz + 2wx */
- m->mat32=q_2yz+q_2xw;
- /* mat33 = 1 - 2x^2 - 2y^2 */
- m->mat33=ONE_FIXED-q_2xx-q_2yy;
- }
|