Maths.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945
  1. #if PSX
  2. #include <kernel.h>
  3. #include <sys/types.h>
  4. #include <libetc.h>
  5. #include <libgte.h>
  6. #include <libgpu.h>
  7. #include <stdlib.h>
  8. #include <inline_c.h>
  9. #include <gtemac.h>
  10. #endif
  11. #include "3dc.h"
  12. #include "inline.h"
  13. #define UseTimsPinp Yes
  14. #define trip_debugger No
  15. #if trip_debugger
  16. int testa = 0;
  17. int testb = 100;
  18. int testc = 0;
  19. #endif
  20. /*
  21. externs for commonly used global variables and arrays
  22. */
  23. #if platform_pc
  24. extern int sine[];
  25. extern int cosine[];
  26. #endif
  27. extern short ArcCosTable[];
  28. extern short ArcSineTable[];
  29. extern short ArcTanTable[];
  30. extern LONGLONGCH ll_zero;
  31. extern int NormalFrameTime;
  32. #if PSX
  33. extern unsigned long *scratchp;
  34. #endif
  35. /*
  36. Globals
  37. */
  38. MATRIXCH IdentityMatrix = {
  39. ONE_FIXED, 0, 0,
  40. 0, ONE_FIXED, 0,
  41. 0, 0, ONE_FIXED
  42. };
  43. /*
  44. Maths functions used by the system
  45. */
  46. #if PSX
  47. inline void ch2psx(MATRIXCH *chm, MATRIX *psxm)
  48. {
  49. psxm->m[0][0] = chm->mat11 >> 4;
  50. psxm->m[0][1] = chm->mat21 >> 4;
  51. psxm->m[0][2] = chm->mat31 >> 4;
  52. psxm->m[1][0] = chm->mat12 >> 4;
  53. psxm->m[1][1] = chm->mat22 >> 4;
  54. psxm->m[1][2] = chm->mat32 >> 4;
  55. psxm->m[2][0] = chm->mat13 >> 4;
  56. psxm->m[2][1] = chm->mat23 >> 4;
  57. psxm->m[2][2] = chm->mat33 >> 4;
  58. }
  59. inline void psx2ch(MATRIX *psxm, MATRIXCH *chm)
  60. {
  61. chm->mat11 = psxm->m[0][0] << 4;
  62. chm->mat21 = psxm->m[0][1] << 4;
  63. chm->mat31 = psxm->m[0][2] << 4;
  64. chm->mat12 = psxm->m[1][0] << 4;
  65. chm->mat22 = psxm->m[1][1] << 4;
  66. chm->mat32 = psxm->m[1][2] << 4;
  67. chm->mat13 = psxm->m[2][0] << 4;
  68. chm->mat23 = psxm->m[2][1] << 4;
  69. chm->mat33 = psxm->m[2][2] << 4;
  70. }
  71. #endif
  72. /* One over sin functions - CDF 4/2/98 */
  73. extern int oneoversin[4096];
  74. void ConstructOneOverSinTable(void) {
  75. int a,sin;
  76. for (a=0; a<4096; a++) {
  77. sin=GetSin(a);
  78. if (sin!=0) {
  79. oneoversin[a]=DIV_FIXED(ONE_FIXED,sin);
  80. } else {
  81. sin=100;
  82. oneoversin[a]=DIV_FIXED(ONE_FIXED,sin);
  83. }
  84. }
  85. }
  86. int GetOneOverSin(int a) {
  87. int b;
  88. b=a&wrap360;
  89. return(oneoversin[b]);
  90. }
  91. /*
  92. Dot Product Function
  93. It accepts two pointers to vectors and returns an int result
  94. */
  95. int _DotProduct(VECTORCH *vptr1, VECTORCH *vptr2)
  96. {
  97. int dp;
  98. dp = MUL_FIXED(vptr1->vx, vptr2->vx);
  99. dp += MUL_FIXED(vptr1->vy, vptr2->vy);
  100. dp += MUL_FIXED(vptr1->vz, vptr2->vz);
  101. return(dp);
  102. }
  103. int DotProduct2d(VECTOR2D *vptr1, VECTOR2D *vptr2)
  104. {
  105. int dp;
  106. dp = MUL_FIXED(vptr1->vx, vptr2->vx);
  107. dp += MUL_FIXED(vptr1->vy, vptr2->vy);
  108. return dp;
  109. }
  110. /*
  111. This function returns the distance between two vectors
  112. */
  113. int VectorDistance(VECTORCH *v1, VECTORCH *v2)
  114. {
  115. VECTORCH v;
  116. v.vx = v1->vx - v2->vx;
  117. v.vy = v1->vy - v2->vy;
  118. v.vz = v1->vz - v2->vz;
  119. return Magnitude(&v);
  120. }
  121. /*
  122. This function compares the distance between two vectors along each of
  123. the major axes and returns Yes or No if they are within the cube defined
  124. by the argument passed.
  125. */
  126. int OutcodeVectorDistance(VECTORCH *v1, VECTORCH *v2, int d)
  127. {
  128. int i;
  129. i = v1->vx - v2->vx;
  130. if(i < 0) i = -i;
  131. if(i >= d) return No;
  132. i = v1->vy - v2->vy;
  133. if(i < 0) i = -i;
  134. if(i >= d) return No;
  135. i = v1->vz - v2->vz;
  136. if(i < 0) i = -i;
  137. if(i >= d) return No;
  138. return Yes;
  139. }
  140. /*
  141. Subtract one VECTORCH from another and return the result as a normal
  142. v3 = Normal(v1 - v2)
  143. */
  144. void GetNormalVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3)
  145. {
  146. v3->vx = v1->vx - v2->vx;
  147. v3->vy = v1->vy - v2->vy;
  148. v3->vz = v1->vz - v2->vz;
  149. Normalise(v3);
  150. }
  151. /*
  152. Normalise a vector close to, but less than, unit length
  153. */
  154. void Renormalise(VECTORCH *nvector)
  155. {
  156. int m;
  157. int xsq, ysq, zsq;
  158. /* Scale x, y and z */
  159. nvector->vx >>= 2;
  160. nvector->vy >>= 2;
  161. nvector->vz >>= 2;
  162. /* Normalise */
  163. xsq = nvector->vx * nvector->vx;
  164. ysq = nvector->vy * nvector->vy;
  165. zsq = nvector->vz * nvector->vz;
  166. m = SqRoot32(xsq + ysq + zsq);
  167. if(m == 0) m = 1; /* Just in case */
  168. nvector->vx = (nvector->vx * ONE_FIXED) / m;
  169. nvector->vy = (nvector->vy * ONE_FIXED) / m;
  170. nvector->vz = (nvector->vz * ONE_FIXED) / m;
  171. }
  172. /*
  173. Return the shift value required to get one value LTE the other value
  174. */
  175. int FindShift32(int value, int limit)
  176. {
  177. int shift = 0;
  178. /*if(limit == 0) exit(0xfa11fa11);*/
  179. if(value < 0) value = -value;
  180. while(value > limit) {
  181. #if trip_debugger
  182. if(shift > 32) {
  183. testa = testb / testc;
  184. }
  185. #endif
  186. shift++;
  187. value >>= 1;
  188. }
  189. return shift;
  190. }
  191. /*
  192. Return the largest value of an int array
  193. */
  194. int MaxInt(int *iarray, int iarraysize)
  195. {
  196. int imax = smallint;
  197. int i;
  198. for(i = iarraysize; i!=0; i--) {
  199. if(imax < *iarray) imax = *iarray;
  200. iarray++;
  201. }
  202. return imax;
  203. }
  204. /*
  205. Return the smallest value of an int array
  206. */
  207. int MinInt(int *iarray, int iarraysize)
  208. {
  209. int imin = bigint;
  210. int i;
  211. for(i = iarraysize; i!=0; i--) {
  212. if(imin > *iarray) imin = *iarray;
  213. iarray++;
  214. }
  215. return imin;
  216. }
  217. /*
  218. Create Matrix from Euler Angles
  219. It requires a pointer to some euler angles and a pointer to a matrix
  220. Construct the matrix elements using the following formula
  221. Formula for ZXY Matrix
  222. m11 = cy*cz + sx*sy*sz m12 = -cy*sz + sx*sy*cz m13 = cx*sy
  223. m21 = cx*sz m22 = cx*cz m23 = -sx
  224. m31 = -sy*cz + sx*cy*sz m32 = sy*sz + sx*cy*cz m33 = cx*cy
  225. */
  226. void CreateEulerMatrix(e, m1)
  227. EULER *e;
  228. MATRIXCH *m1;
  229. {
  230. #if 0
  231. SVECTOR eulers;
  232. eulers.vx=(e->EulerX)&4095;
  233. eulers.vy=(e->EulerY)&4095;
  234. eulers.vz=(e->EulerZ)&4095;
  235. RotMatrix(&eulers,(MATRIX *)scratchp);
  236. psx2ch((MATRIX *)scratchp,m1);
  237. #else
  238. int t, sx, sy, sz, cx, cy, cz;
  239. sx = GetSin(e->EulerX);
  240. sy = GetSin(e->EulerY);
  241. sz = GetSin(e->EulerZ);
  242. cx = GetCos(e->EulerX);
  243. cy = GetCos(e->EulerY);
  244. cz = GetCos(e->EulerZ);
  245. #if 0
  246. textprint("Euler Matrix Sines & Cosines\n");
  247. textprint("%d, %d, %d\n", sx, sy, sz);
  248. textprint("%d, %d, %d\n", cx, cy, cz);
  249. #endif
  250. /* m11 = cy*cz + sx*sy*sz */
  251. m1->mat11 = MUL_FIXED(cy, cz); /* cy*cz */
  252. t = MUL_FIXED(sx, sy); /* sx*sy */
  253. t = MUL_FIXED(t, sz); /* *sz */
  254. m1->mat11 += t;
  255. /* m12 = -cy*sz + sx*sy*cz */
  256. m1->mat12=MUL_FIXED(-cy,sz);
  257. t=MUL_FIXED(sx,sy);
  258. t=MUL_FIXED(t,cz);
  259. m1->mat12+=t;
  260. /* m13 = cx*sy */
  261. m1->mat13=MUL_FIXED(cx,sy);
  262. /* m21 = cx*sz */
  263. m1->mat21=MUL_FIXED(cx,sz);
  264. /* m22 = cx*cz */
  265. m1->mat22=MUL_FIXED(cx,cz);
  266. /* m23 = -sx */
  267. m1->mat23=-sx;
  268. /* m31 = -sy*cz + sx*cy*sz */
  269. m1->mat31=MUL_FIXED(-sy,cz);
  270. t=MUL_FIXED(sx,cy);
  271. t=MUL_FIXED(t,sz);
  272. m1->mat31+=t;
  273. /* m32 = sy*sz + sx*cy*cz */
  274. m1->mat32=MUL_FIXED(sy,sz);
  275. t=MUL_FIXED(sx,cy);
  276. t=MUL_FIXED(t,cz);
  277. m1->mat32+=t;
  278. /* m33 = cx*cy */
  279. m1->mat33=MUL_FIXED(cx,cy);
  280. #endif
  281. }
  282. /*
  283. Create a Unit Vector from three Euler Angles
  284. */
  285. void CreateEulerVector(EULER *e, VECTORCH *v)
  286. {
  287. int t, sx, sy, sz, cx, cy, cz;
  288. sx = GetSin(e->EulerX);
  289. sy = GetSin(e->EulerY);
  290. sz = GetSin(e->EulerZ);
  291. cx = GetCos(e->EulerX);
  292. cy = GetCos(e->EulerY);
  293. cz = GetCos(e->EulerZ);
  294. /* x = -sy*cz + sx*cy*sz */
  295. v->vx = MUL_FIXED(-sy, cz);
  296. t = MUL_FIXED(sx, cy);
  297. t = MUL_FIXED(t, sz);
  298. v->vx += t;
  299. /* y = sy*sz + sx*cy*cz */
  300. v->vy = MUL_FIXED(sy, sz);
  301. t = MUL_FIXED(sx, cy);
  302. t = MUL_FIXED(t, cz);
  303. v->vy += t;
  304. /* z = cx*cy */
  305. v->vz = MUL_FIXED(cx,cy);
  306. }
  307. /*
  308. Matrix Multiply Function
  309. A 3x3 Matrix is represented here as
  310. m11 m12 m13
  311. m21 m22 m23
  312. m31 m32 m33
  313. Row #1 (r1) of the matrix is m11 m12 m13
  314. Column #1 (c1) of the matrix is m11 m32 m31
  315. Under multiplication
  316. m'' = m x m'
  317. where
  318. m11'' = c1.r1'
  319. m12'' = c2.r1'
  320. m13'' = c3.r1'
  321. m21'' = c1.r2'
  322. m22'' = c2.r2'
  323. m23'' = c3.r2'
  324. m31'' = c1.r3'
  325. m32'' = c2.r3'
  326. m33'' = c3.r3'
  327. */
  328. void MatrixMultiply(m1, m2, m3)
  329. struct matrixch *m1, *m2, *m3;
  330. {
  331. #if 0
  332. PushMatrix();
  333. ch2psx(m1,(MATRIX *)scratchp);
  334. ch2psx(m2,(MATRIX *)(scratchp+(sizeof(MATRIX))));
  335. MulMatrix0((MATRIX *)scratchp,(MATRIX *)(scratchp+(sizeof(MATRIX))),(MATRIX *)(scratchp+((sizeof(MATRIX)<<1))));
  336. psx2ch((MATRIX *)(scratchp+((sizeof(MATRIX)<<1))),m3);
  337. PopMatrix();
  338. #else
  339. MATRIXCH TmpMat;
  340. /* m11'' = c1.r1' */
  341. TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11);
  342. TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12);
  343. TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13);
  344. /* m12'' = c2.r1' */
  345. TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11);
  346. TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12);
  347. TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13);
  348. /* m13'' = c3.r1' */
  349. TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11);
  350. TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12);
  351. TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13);
  352. /* m21'' = c1.r2' */
  353. TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21);
  354. TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22);
  355. TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23);
  356. /* m22'' = c2.r2' */
  357. TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21);
  358. TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22);
  359. TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23);
  360. /* m23'' = c3.r2' */
  361. TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21);
  362. TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22);
  363. TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23);
  364. /* m31'' = c1.r3' */
  365. TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31);
  366. TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32);
  367. TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33);
  368. /* m32'' = c2.r3' */
  369. TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31);
  370. TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32);
  371. TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33);
  372. /* m33'' = c3.r3' */
  373. TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31);
  374. TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32);
  375. TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33);
  376. /* Finally, copy TmpMat to m3 */
  377. CopyMatrix(&TmpMat, m3);
  378. #endif
  379. }
  380. void PSXAccurateMatrixMultiply(m1, m2, m3)
  381. struct matrixch *m1, *m2, *m3;
  382. {
  383. MATRIXCH TmpMat;
  384. /* m11'' = c1.r1' */
  385. TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11);
  386. TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12);
  387. TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13);
  388. /* m12'' = c2.r1' */
  389. TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11);
  390. TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12);
  391. TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13);
  392. /* m13'' = c3.r1' */
  393. TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11);
  394. TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12);
  395. TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13);
  396. /* m21'' = c1.r2' */
  397. TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21);
  398. TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22);
  399. TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23);
  400. /* m22'' = c2.r2' */
  401. TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21);
  402. TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22);
  403. TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23);
  404. /* m23'' = c3.r2' */
  405. TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21);
  406. TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22);
  407. TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23);
  408. /* m31'' = c1.r3' */
  409. TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31);
  410. TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32);
  411. TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33);
  412. /* m32'' = c2.r3' */
  413. TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31);
  414. TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32);
  415. TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33);
  416. /* m33'' = c3.r3' */
  417. TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31);
  418. TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32);
  419. TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33);
  420. /* Finally, copy TmpMat to m3 */
  421. CopyMatrix(&TmpMat, m3);
  422. }
  423. /*
  424. Transpose Matrix
  425. */
  426. void TransposeMatrixCH(m1)
  427. MATRIXCH *m1;
  428. {
  429. int t;
  430. t=m1->mat12;
  431. m1->mat12=m1->mat21;
  432. m1->mat21=t;
  433. t=m1->mat13;
  434. m1->mat13=m1->mat31;
  435. m1->mat31=t;
  436. t=m1->mat23;
  437. m1->mat23=m1->mat32;
  438. m1->mat32=t;
  439. }
  440. /*
  441. Copy Vector
  442. */
  443. void CopyVector(VECTORCH *v1, VECTORCH *v2)
  444. {
  445. /* Copy VECTORCH v1 -> VECTORCH v2 */
  446. v2->vx=v1->vx;
  447. v2->vy=v1->vy;
  448. v2->vz=v1->vz;
  449. }
  450. /*
  451. Copy Location
  452. */
  453. void CopyLocation(VECTORCH *v1, VECTORCH *v2)
  454. {
  455. /* Copy VECTORCH v1 -> VECTORCH v2 */
  456. v2->vx=v1->vx;
  457. v2->vy=v1->vy;
  458. v2->vz=v1->vz;
  459. }
  460. /*
  461. Copy Euler
  462. */
  463. void CopyEuler(EULER *e1, EULER *e2)
  464. {
  465. /* Copy EULER e1 -> EULER e2 */
  466. e2->EulerX=e1->EulerX;
  467. e2->EulerY=e1->EulerY;
  468. e2->EulerZ=e1->EulerZ;
  469. }
  470. /*
  471. Copy Matrix
  472. */
  473. void CopyMatrix(MATRIXCH *m1, MATRIXCH *m2)
  474. {
  475. /* Copy MATRIXCH m1 -> MATRIXCH m2 */
  476. m2->mat11=m1->mat11;
  477. m2->mat12=m1->mat12;
  478. m2->mat13=m1->mat13;
  479. m2->mat21=m1->mat21;
  480. m2->mat22=m1->mat22;
  481. m2->mat23=m1->mat23;
  482. m2->mat31=m1->mat31;
  483. m2->mat32=m1->mat32;
  484. m2->mat33=m1->mat33;
  485. }
  486. /*
  487. Make a Vector.
  488. v3 = v1 - v2
  489. */
  490. void MakeVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3)
  491. {
  492. v3->vx = v1->vx - v2->vx;
  493. v3->vy = v1->vy - v2->vy;
  494. v3->vz = v1->vz - v2->vz;
  495. }
  496. /*
  497. Add a Vector.
  498. v2 = v2 + v1
  499. */
  500. void AddVector(VECTORCH *v1, VECTORCH *v2)
  501. {
  502. v2->vx += v1->vx;
  503. v2->vy += v1->vy;
  504. v2->vz += v1->vz;
  505. }
  506. /*
  507. Subtract a Vector.
  508. v2 = v2 - v1
  509. */
  510. void SubVector(VECTORCH *v1, VECTORCH *v2)
  511. {
  512. v2->vx -= v1->vx;
  513. v2->vy -= v1->vy;
  514. v2->vz -= v1->vz;
  515. }
  516. /*
  517. Matrix Rotatation of a Vector
  518. Overwrite the Source Vector with the Rotated Vector
  519. x' = v.c1
  520. y' = v.c2
  521. z' = v.c3
  522. */
  523. void _RotateVector(VECTORCH *v, MATRIXCH* m)
  524. {
  525. int x, y, z;
  526. x = MUL_FIXED(m->mat11, v->vx);
  527. x += MUL_FIXED(m->mat21, v->vy);
  528. x += MUL_FIXED(m->mat31, v->vz);
  529. y = MUL_FIXED(m->mat12, v->vx);
  530. y += MUL_FIXED(m->mat22, v->vy);
  531. y += MUL_FIXED(m->mat32, v->vz);
  532. z = MUL_FIXED(m->mat13, v->vx);
  533. z += MUL_FIXED(m->mat23, v->vy);
  534. z += MUL_FIXED(m->mat33, v->vz);
  535. v->vx = x;
  536. v->vy = y;
  537. v->vz = z;
  538. }
  539. /*
  540. Matrix Rotation of a Source Vector using a Matrix
  541. Copying to a Destination Vector
  542. x' = v.c1
  543. y' = v.c2
  544. z' = v.c3
  545. */
  546. void _RotateAndCopyVector(v1, v2, m)
  547. VECTORCH *v1;
  548. VECTORCH *v2;
  549. MATRIXCH *m;
  550. {
  551. v2->vx=MUL_FIXED(m->mat11,v1->vx);
  552. v2->vx+=MUL_FIXED(m->mat21,v1->vy);
  553. v2->vx+=MUL_FIXED(m->mat31,v1->vz);
  554. v2->vy=MUL_FIXED(m->mat12,v1->vx);
  555. v2->vy+=MUL_FIXED(m->mat22,v1->vy);
  556. v2->vy+=MUL_FIXED(m->mat32,v1->vz);
  557. v2->vz=MUL_FIXED(m->mat13,v1->vx);
  558. v2->vz+=MUL_FIXED(m->mat23,v1->vy);
  559. v2->vz+=MUL_FIXED(m->mat33,v1->vz);
  560. }
  561. /*
  562. Matrix to Euler Angles
  563. Maths overflow is a real problem for this function. To prevent overflows
  564. the matrix Sines and Cosines are calculated using values scaled down by 4.
  565. sinx = -M23
  566. cosx = sqr ( 1 - sinx^2 )
  567. siny = M13 / cosx
  568. cosy = M33 / cosx
  569. sinz = M21 / cosx
  570. cosz = M22 / cosx
  571. */
  572. #define m2e_scale 2
  573. #define ONE_FIXED_S ((ONE_FIXED >> m2e_scale) - 1)
  574. #define m2e_shift 14
  575. #define j_and_r_change Yes
  576. void MatrixToEuler(MATRIXCH *m, EULER *e)
  577. {
  578. int x, sinx, cosx, siny, cosy, sinz, cosz;
  579. int abs_cosx, abs_cosy, abs_cosz;
  580. int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll;
  581. int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll;
  582. #if 0
  583. textprint("CosMatrixPitch = %d\n", CosMatrixPitch);
  584. /* WaitForReturn(); */
  585. #endif
  586. if(m->mat32 >-65500 && m->mat32<65500)
  587. {
  588. /* Yaw */
  589. /* Pitch */
  590. #if j_and_r_change
  591. SineMatrixPitch = -m->mat32;
  592. #else
  593. SineMatrixPitch = -m->mat23;
  594. #endif
  595. SineMatrixPitch >>= m2e_scale;
  596. #if 0
  597. textprint("SineMatrixPitch = %d\n", SineMatrixPitch);
  598. /* WaitForReturn(); */
  599. #endif
  600. CosMatrixPitch = SineMatrixPitch * SineMatrixPitch;
  601. CosMatrixPitch >>= m2e_shift;
  602. CosMatrixPitch = -CosMatrixPitch;
  603. CosMatrixPitch += ONE_FIXED_S;
  604. CosMatrixPitch *= ONE_FIXED_S;
  605. CosMatrixPitch = SqRoot32(CosMatrixPitch);
  606. if(CosMatrixPitch) {
  607. if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S;
  608. else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S;
  609. }
  610. else CosMatrixPitch = 1;
  611. SineMatrixYaw = WideMulNarrowDiv(
  612. #if j_and_r_change
  613. m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  614. #else
  615. m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  616. #endif
  617. #if 0
  618. textprint("SineMatrixYaw = %d\n", SineMatrixYaw);
  619. /* WaitForReturn(); */
  620. #endif
  621. CosMatrixYaw = WideMulNarrowDiv(
  622. m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  623. #if 0
  624. textprint("CosMatrixYaw = %d\n", CosMatrixYaw);
  625. /* WaitForReturn(); */
  626. #endif
  627. /* Roll */
  628. SineMatrixRoll = WideMulNarrowDiv(
  629. #if j_and_r_change
  630. m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  631. #else
  632. m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  633. #endif
  634. #if 0
  635. textprint("SineMatrixRoll = %d\n", SineMatrixRoll);
  636. /* WaitForReturn(); */
  637. #endif
  638. CosMatrixRoll = WideMulNarrowDiv(
  639. m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  640. #if 0
  641. textprint("CosMatrixRoll = %d\n", CosMatrixRoll);
  642. /* WaitForReturn(); */
  643. #endif
  644. /* Tables are for values +- 2^16 */
  645. sinx = SineMatrixPitch << m2e_scale;
  646. siny = SineMatrixYaw << m2e_scale;
  647. sinz = SineMatrixRoll << m2e_scale;
  648. cosx = CosMatrixPitch << m2e_scale;
  649. cosy = CosMatrixYaw << m2e_scale;
  650. cosz = CosMatrixRoll << m2e_scale;
  651. #if 0
  652. textprint("sines = %d, %d, %d\n", sinx, siny, sinz);
  653. textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz);
  654. /* WaitForReturn(); */
  655. #endif
  656. /* Absolute Cosines */
  657. abs_cosx = cosx;
  658. if(abs_cosx < 0) abs_cosx = -abs_cosx;
  659. abs_cosy = cosy;
  660. if(abs_cosy < 0) abs_cosy = -abs_cosy;
  661. abs_cosz = cosz;
  662. if(abs_cosz < 0) abs_cosz = -abs_cosz;
  663. /* Euler X */
  664. if(abs_cosx > Cosine45) {
  665. x = ArcSin(sinx);
  666. if(cosx < 0) {
  667. x = -x;
  668. x += deg180;
  669. x &= wrap360;
  670. }
  671. }
  672. else {
  673. x = ArcCos(cosx);
  674. if(sinx < 0) {
  675. x = -x;
  676. x &= wrap360;
  677. }
  678. }
  679. #if (j_and_r_change == No)
  680. x = -x;
  681. x &= wrap360;
  682. #endif
  683. e->EulerX = x;
  684. /* Euler Y */
  685. if(abs_cosy > Cosine45) {
  686. x = ArcSin(siny);
  687. if(cosy < 0) {
  688. x = -x;
  689. x += deg180;
  690. x &= wrap360;
  691. }
  692. }
  693. else {
  694. x = ArcCos(cosy);
  695. if(siny < 0) {
  696. x = -x;
  697. x &= wrap360;
  698. }
  699. }
  700. #if (j_and_r_change == No)
  701. x = -x;
  702. x &= wrap360;
  703. #endif
  704. e->EulerY = x;
  705. /* Euler Z */
  706. if(abs_cosz > Cosine45) {
  707. x = ArcSin(sinz);
  708. if(cosz < 0) {
  709. x = -x;
  710. x += deg180;
  711. x &= wrap360;
  712. }
  713. }
  714. else {
  715. x = ArcCos(cosz);
  716. if(sinz < 0) {
  717. x = -x;
  718. x &= wrap360;
  719. }
  720. }
  721. #if (j_and_r_change == No)
  722. x = -x;
  723. x &= wrap360;
  724. #endif
  725. e->EulerZ = x;
  726. }
  727. else //singularity case
  728. {
  729. if(m->mat32>0)
  730. e->EulerX = 3072;
  731. else
  732. e->EulerX = 1024;
  733. e->EulerZ=0;
  734. /* Yaw */
  735. siny = -m->mat13 ;
  736. cosy = m->mat11 ;
  737. abs_cosy = cosy;
  738. if(abs_cosy < 0) abs_cosy = -abs_cosy;
  739. if(abs_cosy > Cosine45) {
  740. x = ArcSin(siny);
  741. if(cosy < 0) {
  742. x = -x;
  743. x += deg180;
  744. x &= wrap360;
  745. }
  746. }
  747. else {
  748. x = ArcCos(cosy);
  749. if(siny < 0) {
  750. x = -x;
  751. x &= wrap360;
  752. }
  753. }
  754. #if (j_and_r_change == No)
  755. x = -x;
  756. x &= wrap360;
  757. #endif
  758. e->EulerY = x;
  759. }
  760. #if 0
  761. textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n",
  762. e->EulerX,
  763. e->EulerY,
  764. e->EulerZ
  765. );
  766. /* WaitForReturn(); */
  767. #endif
  768. }
  769. #if 1
  770. #define j_and_r_change_2 Yes
  771. void MatrixToEuler2(MATRIXCH *m, EULER *e)
  772. {
  773. int x, sinx, cosx, siny, cosy, sinz, cosz;
  774. int abs_cosx, abs_cosy, abs_cosz;
  775. int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll;
  776. int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll;
  777. /* Pitch */
  778. #if j_and_r_change_2
  779. SineMatrixPitch = -m->mat32;
  780. #else
  781. SineMatrixPitch = -m->mat23;
  782. #endif
  783. SineMatrixPitch >>= m2e_scale;
  784. #if 0
  785. textprint("SineMatrixPitch = %d\n", SineMatrixPitch);
  786. /* WaitForReturn(); */
  787. #endif
  788. CosMatrixPitch = SineMatrixPitch * SineMatrixPitch;
  789. CosMatrixPitch >>= m2e_shift;
  790. CosMatrixPitch = -CosMatrixPitch;
  791. CosMatrixPitch += ONE_FIXED_S;
  792. CosMatrixPitch *= ONE_FIXED_S;
  793. CosMatrixPitch = SqRoot32(CosMatrixPitch);
  794. if(CosMatrixPitch) {
  795. if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S;
  796. else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S;
  797. }
  798. else CosMatrixPitch = 1;
  799. #if 0
  800. textprint("CosMatrixPitch = %d\n", CosMatrixPitch);
  801. /* WaitForReturn(); */
  802. #endif
  803. /* Yaw */
  804. SineMatrixYaw = WideMulNarrowDiv(
  805. #if j_and_r_change_2
  806. m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  807. #else
  808. m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  809. #endif
  810. #if 0
  811. textprint("SineMatrixYaw = %d\n", SineMatrixYaw);
  812. /* WaitForReturn(); */
  813. #endif
  814. CosMatrixYaw = WideMulNarrowDiv(
  815. m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  816. #if 0
  817. textprint("CosMatrixYaw = %d\n", CosMatrixYaw);
  818. /* WaitForReturn(); */
  819. #endif
  820. /* Roll */
  821. SineMatrixRoll = WideMulNarrowDiv(
  822. #if j_and_r_change_2
  823. m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  824. #else
  825. m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  826. #endif
  827. #if 0
  828. textprint("SineMatrixRoll = %d\n", SineMatrixRoll);
  829. /* WaitForReturn(); */
  830. #endif
  831. CosMatrixRoll = WideMulNarrowDiv(
  832. m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch);
  833. #if 0
  834. textprint("CosMatrixRoll = %d\n", CosMatrixRoll);
  835. /* WaitForReturn(); */
  836. #endif
  837. /* Tables are for values +- 2^16 */
  838. sinx = SineMatrixPitch << m2e_scale;
  839. siny = SineMatrixYaw << m2e_scale;
  840. sinz = SineMatrixRoll << m2e_scale;
  841. cosx = CosMatrixPitch << m2e_scale;
  842. cosy = CosMatrixYaw << m2e_scale;
  843. cosz = CosMatrixRoll << m2e_scale;
  844. #if 0
  845. textprint("sines = %d, %d, %d\n", sinx, siny, sinz);
  846. textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz);
  847. /* WaitForReturn(); */
  848. #endif
  849. /* Absolute Cosines */
  850. abs_cosx = cosx;
  851. if(abs_cosx < 0) abs_cosx = -abs_cosx;
  852. abs_cosy = cosy;
  853. if(abs_cosy < 0) abs_cosy = -abs_cosy;
  854. abs_cosz = cosz;
  855. if(abs_cosz < 0) abs_cosz = -abs_cosz;
  856. /* Euler X */
  857. if(abs_cosx > Cosine45) {
  858. x = ArcSin(sinx);
  859. if(cosx < 0) {
  860. x = -x;
  861. x += deg180;
  862. x &= wrap360;
  863. }
  864. }
  865. else {
  866. x = ArcCos(cosx);
  867. if(sinx < 0) {
  868. x = -x;
  869. x &= wrap360;
  870. }
  871. }
  872. #if (j_and_r_change_2 == No)
  873. x = -x;
  874. x &= wrap360;
  875. #endif
  876. e->EulerX = x;
  877. /* Euler Y */
  878. if(abs_cosy > Cosine45) {
  879. x = ArcSin(siny);
  880. if(cosy < 0) {
  881. x = -x;
  882. x += deg180;
  883. x &= wrap360;
  884. }
  885. }
  886. else {
  887. x = ArcCos(cosy);
  888. if(siny < 0) {
  889. x = -x;
  890. x &= wrap360;
  891. }
  892. }
  893. #if (j_and_r_change_2 == No)
  894. x = -x;
  895. x &= wrap360;
  896. #endif
  897. e->EulerY = x;
  898. /* Euler Z */
  899. if(abs_cosz > Cosine45) {
  900. x = ArcSin(sinz);
  901. if(cosz < 0) {
  902. x = -x;
  903. x += deg180;
  904. x &= wrap360;
  905. }
  906. }
  907. else {
  908. x = ArcCos(cosz);
  909. if(sinz < 0) {
  910. x = -x;
  911. x &= wrap360;
  912. }
  913. }
  914. #if (j_and_r_change_2 == No)
  915. x = -x;
  916. x &= wrap360;
  917. #endif
  918. e->EulerZ = x;
  919. #if 0
  920. textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n",
  921. e->EulerX,
  922. e->EulerY,
  923. e->EulerZ
  924. );
  925. /* WaitForReturn(); */
  926. #endif
  927. }
  928. #endif
  929. /*
  930. Normalise a Matrix
  931. Dot the three vectors together (XY, XZ, YZ) and take the two nearest to
  932. 90ø from each other. Cross them to create a new third vector, then cross
  933. the first and third to create a new second.
  934. */
  935. void MNormalise(MATRIXCH *m)
  936. {
  937. VECTORCH *x = (VECTORCH *) &m->mat11;
  938. VECTORCH *y = (VECTORCH *) &m->mat21;
  939. VECTORCH *z = (VECTORCH *) &m->mat31;
  940. int dotxy = Dot(x, y);
  941. int dotxz = Dot(x, z);
  942. int dotyz = Dot(y, z);
  943. VECTORCH *s;
  944. VECTORCH *t;
  945. VECTORCH u;
  946. VECTORCH v;
  947. VECTORCH zero = {0, 0, 0};
  948. #if 0
  949. textprint("dotxy = %d\n", dotxy);
  950. textprint("dotxz = %d\n", dotxz);
  951. textprint("dotyz = %d\n", dotyz);
  952. #endif
  953. #if 0
  954. /* TEST */
  955. dotxy = 0;
  956. dotxz = 0;
  957. dotyz = 1;
  958. #endif
  959. #if 0
  960. textprint("%d %d %d\n",
  961. x->vx,
  962. x->vy,
  963. x->vz
  964. );
  965. textprint("%d %d %d\n",
  966. y->vx,
  967. y->vy,
  968. y->vz
  969. );
  970. textprint("%d %d %d\n",
  971. z->vx,
  972. z->vy,
  973. z->vz
  974. );
  975. #endif
  976. /* Find the two vectors nearest 90ø */
  977. if(dotxy > dotxz && dotxy > dotyz) {
  978. /* xy are the closest to 90ø */
  979. /*textprint("xy\n");*/
  980. s = x;
  981. t = y;
  982. MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
  983. MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
  984. v.vx = -v.vx;
  985. v.vy = -v.vy;
  986. v.vz = -v.vz;
  987. CopyVector(&u, z);
  988. CopyVector(&v, y);
  989. }
  990. else if(dotxz > dotxy && dotxz > dotyz) {
  991. /* xz are the closest to 90ø */
  992. /*textprint("xz\n");*/
  993. s = x;
  994. t = z;
  995. MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
  996. u.vx = -u.vx;
  997. u.vy = -u.vy;
  998. u.vz = -u.vz;
  999. MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
  1000. CopyVector(&u, y);
  1001. CopyVector(&v, z);
  1002. }
  1003. else {
  1004. /* yz are the closest to 90ø */
  1005. /*textprint("yz\n");*/
  1006. s = y;
  1007. t = z;
  1008. MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */
  1009. MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */
  1010. v.vx = -v.vx;
  1011. v.vy = -v.vy;
  1012. v.vz = -v.vz;
  1013. CopyVector(&u, x);
  1014. CopyVector(&v, z);
  1015. }
  1016. #if 0
  1017. textprint("%d %d %d\n",
  1018. x->vx,
  1019. x->vy,
  1020. x->vz
  1021. );
  1022. textprint("%d %d %d\n",
  1023. y->vx,
  1024. y->vy,
  1025. y->vz
  1026. );
  1027. textprint("%d %d %d\n",
  1028. z->vx,
  1029. z->vy,
  1030. z->vz
  1031. );
  1032. #endif
  1033. #if 0
  1034. textprint("mag. x = %d\n", Magnitude(x));
  1035. textprint("mag. y = %d\n", Magnitude(y));
  1036. textprint("mag. z = %d\n", Magnitude(z));
  1037. #endif
  1038. /*WaitForReturn();*/
  1039. }
  1040. /*
  1041. ArcCos
  1042. In: COS value as -65,536 -> +65,536.
  1043. Out: Angle in 0 -> 4095 form.
  1044. Notes:
  1045. The angle returned is in the range 0 -> 2,047 since the sign of SIN
  1046. is not known.
  1047. ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
  1048. ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
  1049. -65,536 = 180 Degrees
  1050. 0 = 90 Degrees
  1051. +65,536 = 0 Degrees
  1052. The table has 4,096 entries.
  1053. */
  1054. int ArcCos(int c)
  1055. {
  1056. short acos;
  1057. if(c < (-(ONE_FIXED - 1))) c = -(ONE_FIXED - 1);
  1058. else if(c > (ONE_FIXED - 1)) c = ONE_FIXED - 1;
  1059. #if 0
  1060. c = c >> 5; /* -64k -> +64k becomes -2k -> +2k */
  1061. c += 2048; /* -2k -> +2k becomes 0 -> 4k */
  1062. #endif
  1063. acos = ArcCosTable[(c >> 5) + 2048];
  1064. return (int) (acos & wrap360);
  1065. }
  1066. /*
  1067. ArcSin
  1068. In: SIN value in ax as -65,536 -> +65,536.
  1069. Out: Angle in 0 -> 4095 form in ax.
  1070. Notes:
  1071. The angle returned is in the range -1,024 -> 1,023 since the sign of COS
  1072. is not known.
  1073. ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) )
  1074. ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x)
  1075. -65,536 = 270 Degrees
  1076. 0 = 0 Degrees
  1077. +65,536 = 90 Degrees
  1078. The table has 4,096 entries.
  1079. */
  1080. int ArcSin(int s)
  1081. {
  1082. short asin;
  1083. if(s < (-(ONE_FIXED - 1))) s = -(ONE_FIXED - 1);
  1084. else if(s > (ONE_FIXED - 1)) s = ONE_FIXED - 1;
  1085. #if 0
  1086. s = s >> 5; /* -64k -> +64k becomes -2k -> +2k */
  1087. s += 2048; /* -2k -> +2k becomes 0 -> 4k */
  1088. #endif
  1089. asin = ArcSineTable[(s >> 5) + 2048];
  1090. return (int) (asin & wrap360);
  1091. }
  1092. /*
  1093. ArcTan
  1094. Pass (x,z)
  1095. And ATN(x/z) is returned such that:
  1096. 000ø is Map North
  1097. 090ø is Map East
  1098. 180ø is Map South
  1099. 270ø is Map West
  1100. */
  1101. int ArcTan(height_x, width_z)
  1102. int height_x,width_z;
  1103. {
  1104. int abs_height_x, abs_width_z, angle, sign, signsame, temp;
  1105. sign=0;
  1106. if((height_x<0 && width_z<0) || (height_x>=0 && width_z>=0))
  1107. signsame=Yes;
  1108. else
  1109. signsame=No;
  1110. abs_height_x=height_x;
  1111. if(abs_height_x<0) abs_height_x=-abs_height_x;
  1112. abs_width_z=width_z;
  1113. if(abs_width_z<0) abs_width_z=-abs_width_z;
  1114. /*
  1115. Find ATN
  1116. */
  1117. if(width_z==0) angle=-deg90;
  1118. else if(abs_width_z==abs_height_x)
  1119. angle=deg45;
  1120. else {
  1121. if(abs_width_z>abs_height_x) {
  1122. temp=abs_width_z;
  1123. abs_width_z=abs_height_x;
  1124. abs_height_x=temp;
  1125. sign=-1;
  1126. }
  1127. if(abs_height_x!=0)
  1128. /* angle = (abs_width_z << 8) / abs_height_x; */
  1129. angle = DIV_INT((abs_width_z << 8), abs_height_x);
  1130. else
  1131. angle=deg22pt5;
  1132. angle=ArcTanTable[angle];
  1133. if(sign>=0) {
  1134. angle=-angle;
  1135. angle+=deg90;
  1136. }
  1137. }
  1138. if(signsame==No) angle=-angle;
  1139. if(width_z<=0) angle+=deg180;
  1140. angle&=wrap360;
  1141. return(angle);
  1142. }
  1143. /*
  1144. Matrix from Z-Vector
  1145. */
  1146. void MatrixFromZVector(VECTORCH *v, MATRIXCH *m)
  1147. {
  1148. VECTORCH XVector;
  1149. VECTORCH YVector;
  1150. VECTORCH zero = {0, 0, 0};
  1151. XVector.vx = v->vz;
  1152. XVector.vy = 0;
  1153. XVector.vz = -v->vx;
  1154. Normalise(&XVector);
  1155. MakeNormal(&zero, &XVector, v, &YVector);
  1156. m->mat11 = XVector.vx;
  1157. m->mat12 = XVector.vy;
  1158. m->mat13 = XVector.vz;
  1159. m->mat21 = -YVector.vx;
  1160. m->mat22 = -YVector.vy;
  1161. m->mat23 = -YVector.vz;
  1162. m->mat31 = v->vx;
  1163. m->mat32 = v->vy;
  1164. m->mat33 = v->vz;
  1165. }
  1166. /*
  1167. Distance Functions
  1168. */
  1169. /*
  1170. Foley and Van Dam 2d distance function
  1171. WARNING! Returns distance x 3
  1172. Here is the F & VD distance function:
  1173. x + z + (max(x,z) * 2)
  1174. ----------------------
  1175. 3
  1176. */
  1177. int FandVD_Distance_2d(VECTOR2D *v0, VECTOR2D *v1)
  1178. {
  1179. int max;
  1180. int d;
  1181. int dx = v1->vx - v0->vx;
  1182. int dy = v1->vy - v0->vy;
  1183. if(dx < 0) dx = -dx;
  1184. if(dy < 0) dy = -dy;
  1185. if(dx > dy) max = dx;
  1186. else max = dy;
  1187. d = (dx + dy + (max * 2));
  1188. return d;
  1189. }
  1190. /*
  1191. Foley and Van Dam 3d distance function
  1192. WARNING! Returns distance x 9
  1193. For a 3d version, calculate (f(f(x,y), y*3))/9
  1194. */
  1195. int FandVD_Distance_3d(VECTORCH *v0, VECTORCH *v1)
  1196. {
  1197. int dxy, max;
  1198. int dz = v1->vz - v0->vz;
  1199. if(dz < 0) dz = -dz;
  1200. dz *= 3;
  1201. dxy = FandVD_Distance_2d((VECTOR2D *) v0, (VECTOR2D *) v1);
  1202. if(dxy > dz) max = dxy;
  1203. else max = dz;
  1204. return (dxy + dz + (max * 2));
  1205. }
  1206. /*
  1207. NextLowPower2() returns the next lowest power of 2 of the passed value.
  1208. e.g. 18 is returned as 16.
  1209. */
  1210. int NextLowPower2(int i)
  1211. {
  1212. int n = 1;
  1213. while(n <= i)
  1214. n <<= 1;
  1215. return n >> 1;
  1216. }
  1217. /*
  1218. Transform a world location into the local space of the passed matrix and
  1219. location.
  1220. Vector v1 is transformed to v2
  1221. It is made relative to vector v3 and rotated using matrix m transposed
  1222. A possible use is the transformation of world points into the local space
  1223. of a display block
  1224. e.g.
  1225. MakeVectorLocal(&v1, &v2, &dptr->ObWorld, &dptr->ObMat);
  1226. This would place vector v2 into the local space of display block dptr
  1227. */
  1228. void MakeVectorLocal(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3, MATRIXCH *m)
  1229. {
  1230. MATRIXCH transmat;
  1231. CopyMatrix(m, &transmat);
  1232. TransposeMatrixCH(&transmat);
  1233. v2->vx = v1->vx - v3->vx;
  1234. v2->vy = v1->vy - v3->vy;
  1235. v2->vz = v1->vz - v3->vz;
  1236. RotateVector(v2, &transmat);
  1237. }
  1238. /*
  1239. Returns "Yes" if "point" is inside "polygon"
  1240. **************************************************
  1241. WARNING!! Point and Polygon Data are OVERWRITTEN!!
  1242. **************************************************
  1243. The function requires point to be an integer array containing a single
  1244. XY pair. The number of points must be passed too.
  1245. Pass the size of the polygon point e.g. A Gouraud polygon has points X,Y,I
  1246. so its point size would be 3.
  1247. Item Polygon Point Size
  1248. ---- ------------------
  1249. I_Polygon 2
  1250. I_GouraudPolygon 3
  1251. I_2dTexturedPolygon 4
  1252. I_3dTexturedPolygon, 5
  1253. I_Gouraud2dTexturedPolygon 5
  1254. I_Polygon_ZBuffer 3
  1255. I_GouraudPolygon_ZBuffer 4
  1256. PASS ONLY POSITIVE COORDINATES!
  1257. */
  1258. int PointInPolygon(int *point, int *polygon, int c, int ppsize)
  1259. {
  1260. #if UseTimsPinp
  1261. /* Tim's New Point In Polygon test-- hopefully much faster, */
  1262. /* certainly much smaller. */
  1263. /* Uses Half-Line test for point-in-2D-polygon test */
  1264. /* Tests the half-line going from the point in the direction of positive z */
  1265. int x, z; /* point */
  1266. int sx, sz; /* vertex 1 */
  1267. int *polyp; /* vertex 2 pointer */
  1268. int t;
  1269. int dx, dz; /* ABS(vertex 2 - vertex 1) */
  1270. int sgnx; /* going left or going right */
  1271. int intersects; /* number of intersections so far discovered */
  1272. LONGLONGCH a_ll, b_ll;
  1273. /* reject lines and points */
  1274. if (c < 3) return(No);
  1275. intersects = 0;
  1276. x = point[ix];
  1277. z = point[iy]; /* ! */
  1278. /* get last point */
  1279. polyp = polygon + ((c - 1) * ppsize);
  1280. sx = polyp[0];
  1281. sz = polyp[1];
  1282. /* go back to first point */
  1283. polyp = polygon;
  1284. /* for each point */
  1285. while (0 != c)
  1286. {
  1287. /* is this line straddling the x co-ordinate of the point? */
  1288. /* if not it is not worth testing for intersection with the half-line */
  1289. /* we must be careful to get the strict and non-stict inequalities */
  1290. /* correct, or we may count intersections with vertices the wrong number */
  1291. /* of times. */
  1292. sgnx = 0;
  1293. if (sx < x && x <= polyp[0])
  1294. {
  1295. /* going right */
  1296. sgnx = 1;
  1297. dx = polyp[0] - sx;
  1298. }
  1299. if (polyp[0] < x && x <= sx)
  1300. {
  1301. /* going left */
  1302. sgnx = -1;
  1303. dx = sx - polyp[0];
  1304. }
  1305. /* if sgnx is zero then neither of the above conditions are true, */
  1306. /* hence the line does not straddle the point in x */
  1307. if (0 != sgnx)
  1308. {
  1309. /* next do trivial cases of line totally above or below point */
  1310. if (z < sz && z < polyp[1])
  1311. {
  1312. /* line totally above point -- intersection */
  1313. intersects++;
  1314. }
  1315. else if (z <= sz || z <= polyp[1])
  1316. {
  1317. /* line straddles point in both x and z -- we must do interpolation */
  1318. /* get absolute differences between line end z co-ordinates */
  1319. dz = (sz < polyp[1])?(polyp[1] - sz):(sz - polyp[1]);
  1320. /* B504 is the square root of 7FFFFFFF */
  1321. if (0xB504L < dx || 0xB504L < dz)
  1322. {
  1323. /* LARGE line -- use 64-bit values */
  1324. /* interpolate z */
  1325. MUL_I_WIDE(polyp[1] - sz, x - sx, &a_ll);
  1326. MUL_I_WIDE(polyp[0] - sx, z - sz, &b_ll);
  1327. if(CMP_LL(&a_ll, &b_ll) == sgnx)
  1328. {
  1329. /* we have an intersection */
  1330. intersects++;
  1331. }
  1332. }
  1333. else
  1334. {
  1335. /* small line -- use 32-bit values */
  1336. /* interpolate z */
  1337. t = (polyp[1] - sz) * (x - sx) - (polyp[0] - sx) * (z - sz);
  1338. if (t < 0 && sgnx < 0 || 0 < t && 0 < sgnx)
  1339. {
  1340. /* we have an intersection */
  1341. intersects++;
  1342. }
  1343. }
  1344. } /* (if line straddles point in z) */
  1345. } /* (if line straddles point in x) */
  1346. /* get next line : */
  1347. /* new vertex 1 is old vertex 2 */
  1348. sx = polyp[0];
  1349. sz = polyp[1];
  1350. /* new vertex 2 is next point */
  1351. polyp += ppsize;
  1352. /* next vertex */
  1353. c--;
  1354. }
  1355. if (intersects & 1)
  1356. {
  1357. /* Odd number of intersections -- point is inside polygon */
  1358. return(Yes);
  1359. }
  1360. else
  1361. {
  1362. /* even number of intersections -- point is outside polygon */
  1363. return(No);
  1364. }
  1365. #else
  1366. int i;
  1367. int si, ti;
  1368. int s0, t0;
  1369. int s1, t1;
  1370. int *v0;
  1371. int *v1;
  1372. int ivdot, ivdotcnt, sgn_currivdot, sgn_ivdot, ivstate;
  1373. int ns, nt;
  1374. int x_scale, y_scale;
  1375. int DotNudge;
  1376. int x, z;
  1377. LONGLONGCH xx;
  1378. LONGLONGCH zz;
  1379. LONGLONGCH xx_tmp;
  1380. LONGLONGCH zz_tmp;
  1381. VECTORCH PolyAvgPt;
  1382. /* Reject points and lines */
  1383. if(c < 3) return No;
  1384. /* Find the average point */
  1385. v0 = polygon;
  1386. EQUALS_LL(&xx, &ll_zero);
  1387. EQUALS_LL(&zz, &ll_zero);
  1388. for(i = c; i!=0; i--) {
  1389. x = v0[0];
  1390. z = v0[1];
  1391. IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */
  1392. IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */
  1393. ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */
  1394. ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */
  1395. v0 += ppsize;
  1396. }
  1397. PolyAvgPt.vx = NarrowDivide(&xx, c);
  1398. PolyAvgPt.vz = NarrowDivide(&zz, c);
  1399. /* Centre the polygon */
  1400. v0 = polygon;
  1401. for(i = c; i!=0; i--) {
  1402. v0[0] -= PolyAvgPt.vx;
  1403. v0[1] -= PolyAvgPt.vz;
  1404. v0 += ppsize;
  1405. }
  1406. /* Centre the test point */
  1407. point[0] -= PolyAvgPt.vx;
  1408. point[1] -= PolyAvgPt.vz;
  1409. /* Scale to avoid maths overflow */
  1410. v0 = polygon;
  1411. s0 = 0;
  1412. t0 = 0;
  1413. for(i = c; i!=0; i--) {
  1414. si = v0[0]; if(si < 0) si = -si;
  1415. if(si > s0) s0 = si;
  1416. ti = v0[1]; if(ti < 0) ti = -ti;
  1417. if(ti > t0) t0 = ti;
  1418. v0 += ppsize;
  1419. }
  1420. si = point[ix]; if(si < 0) si = -si;
  1421. if(si > s0) s0 = si;
  1422. ti = point[iy]; if(ti < 0) ti = -ti;
  1423. if(ti > t0) t0 = ti;
  1424. #if 0
  1425. textprint("\nmax x = %d\n", s0);
  1426. textprint("max y = %d\n", t0);
  1427. #endif
  1428. x_scale = FindShift32(s0, 16383);
  1429. y_scale = FindShift32(t0, 16383);
  1430. #if 0
  1431. textprint("scales = %d, %d\n", x_scale, y_scale);
  1432. #endif
  1433. v0 = polygon;
  1434. for(i = c; i!=0; i--) {
  1435. v0[0] >>= x_scale;
  1436. v0[1] >>= y_scale;
  1437. /*textprint("(%d, %d)\n", v0[0], v0[1]);*/
  1438. v0 += ppsize;
  1439. }
  1440. point[ix] >>= x_scale;
  1441. point[iy] >>= y_scale;
  1442. #if 1
  1443. /* Clockwise or Anti-Clockwise? */
  1444. ns = -(polygon[iy + ppsize] - polygon[iy]);
  1445. nt = (polygon[ix + ppsize] - polygon[ix]);
  1446. si = polygon[(ppsize*2) + ix] - polygon[ix];
  1447. ti = polygon[(ppsize*2) + iy] - polygon[iy];
  1448. ivdot = (ns * si) + (nt * ti);
  1449. if(ivdot < 0) DotNudge = -1;
  1450. else DotNudge = 1;
  1451. #endif
  1452. #if 0
  1453. if(ivdot < 0) textprint("Clockwise\n");
  1454. WaitForReturn();
  1455. #endif
  1456. /* Point to test */
  1457. si = point[ix];
  1458. ti = point[iy];
  1459. #if 0
  1460. textprint("p_test %d, %d\n", si, ti);
  1461. #endif
  1462. /* Polygon Vector pointers */
  1463. v0 = polygon;
  1464. v1 = v0 + ppsize;
  1465. /* Dot result monitor */
  1466. ivdotcnt = 0;
  1467. ivstate = Yes; /* assume inside */
  1468. /* Test v(s, t) against the vectors */
  1469. for(i = c; i!=0 && ivstate == Yes; i--) {
  1470. /* second vector pointer wraps once */
  1471. if(i == 1) v1 = polygon;
  1472. /* get the vector */
  1473. s0 = v0[ix];
  1474. t0 = v0[iy];
  1475. s1 = v1[ix];
  1476. t1 = v1[iy];
  1477. #if 0
  1478. textprint("%d,%d; %d,%d\n", s0, t0, s1, t1);
  1479. #endif
  1480. /* get the vector normal */
  1481. ns = -(t1 - t0); /* s -> -t */
  1482. nt = s1 - s0; /* t -> s */
  1483. /* Dot with intersection point */
  1484. ivdot = (ns * (si - s0)) + (nt * (ti - t0));
  1485. /* TEST */
  1486. ivdot += DotNudge;
  1487. sgn_ivdot = 1;
  1488. if(ivdot < 0) sgn_ivdot = -1;
  1489. /* only continue if current dot is same as last, else quit */
  1490. if(ivdotcnt == 0) sgn_currivdot = sgn_ivdot;
  1491. else {
  1492. if(sgn_ivdot != sgn_currivdot) ivstate = No;
  1493. sgn_currivdot = sgn_ivdot;
  1494. }
  1495. v0 += ppsize;
  1496. v1 += ppsize;
  1497. ivdotcnt++;
  1498. }
  1499. if(ivstate) return Yes;
  1500. else return No;
  1501. #endif
  1502. }
  1503. /*
  1504. #defines and statics required for Jamie's Most Excellent
  1505. random number generator
  1506. */
  1507. #define DEG_3 31
  1508. #define SEP_3 3
  1509. static long table [DEG_3] =
  1510. {
  1511. -851904987, -43806228, -2029755270, 1390239686, -1912102820,
  1512. -485608943, 1969813258, -1590463333, -1944053249, 455935928,
  1513. 508023712, -1714531963, 1800685987, -2015299881, 654595283,
  1514. -1149023258, -1470005550, -1143256056, -1325577603, -1568001885,
  1515. 1275120390, -607508183, -205999574, -1696891592, 1492211999,
  1516. -1528267240, -952028296, -189082757, 362343714, 1424981831,
  1517. 2039449641
  1518. };
  1519. #define TABLE_END (table + sizeof (table) / sizeof (table [0]))
  1520. static long * front_ptr = table + SEP_3;
  1521. static long * rear_ptr = table;
  1522. /*
  1523. This code (FastRandom and SetFastRandom) stolen from Jamie Lokier
  1524. September 95. The original version was part of a C library
  1525. implementation
  1526. */
  1527. /* This is derived from the GNU C library source, which is in turn
  1528. derived from Berkeley source. The algorithm, the polynomial, and the
  1529. initial numbers are the same, but the code has been reworked for the
  1530. needs of this version.
  1531. This version doesn't support different types of random number
  1532. generators, or saving and restoring the state. It is fast, short and
  1533. as simple as it can be while still generating numbers as good as the
  1534. Berkeley one. The basic algorithm is to have a linear-feedback shift
  1535. register, whose bits are the least significant bits of each word in
  1536. the `table' array. The higher-order bits are generated by carries
  1537. from the arithmetic on the shift register bits, and have an even
  1538. longer period than the shift register. */
  1539. /* x**31 + x**3 + 1. */
  1540. void SetSeededFastRandom(int seed);
  1541. void SetFastRandom(void)
  1542. {
  1543. int i;
  1544. long number = GetTickCount();
  1545. for(i = 0; i < DEG_3; ++i) {
  1546. number = 1103515145 * number + 12345;
  1547. table[i] = number;
  1548. }
  1549. front_ptr = table + SEP_3;
  1550. rear_ptr = table;
  1551. for(i = 0; i < 10 * DEG_3; ++i)
  1552. (void) FastRandom ();
  1553. SetSeededFastRandom(FastRandom());
  1554. }
  1555. int FastRandom(void)
  1556. {
  1557. long i;
  1558. /*
  1559. Discard least random bit.
  1560. Shift as unsigned to avoid replicating sign bit.
  1561. Faster than masking.
  1562. */
  1563. *front_ptr += *rear_ptr;
  1564. i = (long) ((unsigned long) *front_ptr >> 1);
  1565. /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
  1566. ++front_ptr;
  1567. if(front_ptr < TABLE_END) {
  1568. ++rear_ptr;
  1569. if (rear_ptr < TABLE_END) return i;
  1570. rear_ptr = table;
  1571. }
  1572. else { /* front_ptr >= TABLE_END */
  1573. front_ptr = table;
  1574. ++rear_ptr;
  1575. }
  1576. return (int) i;
  1577. }
  1578. /*a second copy of the random number generator for getting random numbers from a single seed*/
  1579. #define SEEDED_DEG_3 13
  1580. #define SEEDED_SEP_3 3
  1581. static long seeded_table [SEEDED_DEG_3];
  1582. #define SEEDED_TABLE_END (seeded_table + sizeof (seeded_table) / sizeof (seeded_table [0]))
  1583. static long * seeded_front_ptr = seeded_table + SEEDED_SEP_3;
  1584. static long * seeded_rear_ptr = seeded_table;
  1585. int SeededFastRandom(void)
  1586. {
  1587. long i;
  1588. /*
  1589. Discard least random bit.
  1590. Shift as unsigned to avoid replicating sign bit.
  1591. Faster than masking.
  1592. */
  1593. *seeded_front_ptr += *seeded_rear_ptr;
  1594. i = (long) ((unsigned long) *seeded_front_ptr >> 1);
  1595. /* `front_ptr' and `rear_ptr' can't wrap at the same time. */
  1596. ++seeded_front_ptr;
  1597. if(seeded_front_ptr < SEEDED_TABLE_END) {
  1598. ++seeded_rear_ptr;
  1599. if (seeded_rear_ptr < SEEDED_TABLE_END) return i;
  1600. seeded_rear_ptr = seeded_table;
  1601. }
  1602. else { /* front_ptr >= TABLE_END */
  1603. seeded_front_ptr = seeded_table;
  1604. ++seeded_rear_ptr;
  1605. }
  1606. return (int) i;
  1607. }
  1608. void SetSeededFastRandom(int seed)
  1609. {
  1610. int i;
  1611. long number = seed;
  1612. for(i = 0; i < SEEDED_DEG_3; ++i) {
  1613. number = 1103515145 * number + 12345;
  1614. seeded_table[i] = number;
  1615. }
  1616. seeded_front_ptr = seeded_table + SEEDED_SEP_3;
  1617. seeded_rear_ptr = seeded_table;
  1618. for(i = 0; i < 2 * SEEDED_DEG_3; ++i)
  1619. (void) SeededFastRandom ();
  1620. }
  1621. #if StandardShapeLanguage
  1622. /*
  1623. Calculate the average point on this polygon
  1624. */
  1625. void PolyAveragePoint(POLYHEADER *pheader, int *spts, VECTORCH *apt)
  1626. {
  1627. int x, y, z;
  1628. LONGLONGCH xx;
  1629. LONGLONGCH yy;
  1630. LONGLONGCH zz;
  1631. LONGLONGCH xx_tmp;
  1632. LONGLONGCH yy_tmp;
  1633. LONGLONGCH zz_tmp;
  1634. int *mypolystart = &pheader->Poly1stPt;
  1635. int numpolypts;
  1636. /* Find the average point */
  1637. EQUALS_LL(&xx, &ll_zero);
  1638. EQUALS_LL(&yy, &ll_zero);
  1639. EQUALS_LL(&zz, &ll_zero);
  1640. numpolypts = 0;
  1641. while(*mypolystart != Term) {
  1642. x = *(spts + *mypolystart + ix);
  1643. y = *(spts + *mypolystart + iy);
  1644. z = *(spts + *mypolystart + iz);
  1645. IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */
  1646. IntToLL(&yy_tmp, &y); /* yy_tmp = (long long)y */
  1647. IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */
  1648. ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */
  1649. ADD_LL_PP(&yy, &yy_tmp); /* yy += yy_tmp */
  1650. ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */
  1651. numpolypts++;
  1652. mypolystart++;
  1653. }
  1654. apt->vx = NarrowDivide(&xx, numpolypts);
  1655. apt->vy = NarrowDivide(&yy, numpolypts);
  1656. apt->vz = NarrowDivide(&zz, numpolypts);
  1657. }
  1658. #endif /* StandardShapeLanguage */
  1659. /* KJL 15:07:39 01/08/97 - Returns the magnitude of the
  1660. cross product of two vectors a and b. */
  1661. int MagnitudeOfCrossProduct(VECTORCH *a, VECTORCH *b)
  1662. {
  1663. VECTORCH c;
  1664. c.vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy);
  1665. c.vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz);
  1666. c.vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx);
  1667. return Magnitude(&c);
  1668. }
  1669. /* KJL 15:08:01 01/08/97 - sets the vector c to be the
  1670. cross product of the vectors a and b. */
  1671. void CrossProduct(VECTORCH *a, VECTORCH *b, VECTORCH *c)
  1672. {
  1673. c->vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy);
  1674. c->vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz);
  1675. c->vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx);
  1676. }
  1677. /* KJL 12:01:08 7/16/97 - returns the magnitude of a vector - max error about 13%, though average error
  1678. less than half this. Very fast compared to other approaches. */
  1679. int Approximate3dMagnitude(VECTORCH *v)
  1680. {
  1681. int dx,dy,dz;
  1682. dx = v->vx;
  1683. if (dx<0) dx = -dx;
  1684. dy = v->vy;
  1685. if (dy<0) dy = -dy;
  1686. dz = v->vz;
  1687. if (dz<0) dz = -dz;
  1688. if (dx>dy)
  1689. {
  1690. if (dx>dz)
  1691. {
  1692. return dx + ((dy+dz)>>2);
  1693. }
  1694. else
  1695. {
  1696. return dz + ((dy+dx)>>2);
  1697. }
  1698. }
  1699. else
  1700. {
  1701. if (dy>dz)
  1702. {
  1703. return dy + ((dx+dz)>>2);
  1704. }
  1705. else
  1706. {
  1707. return dz + ((dx+dy)>>2);
  1708. }
  1709. }
  1710. }
  1711. /*
  1712. Quaternion to Matrix
  1713. This is the column(row) matrix that is produced. Our matrices are
  1714. row(column) and so are a transpose of this.
  1715. 1 - 2yy - 2zz 2xy + 2wz 2xz - 2wy
  1716. 2xy - 2wz 1 - 2xx - 2zz 2yz + 2wx
  1717. 2xz + 2wy 2yz - 2wx 1 - 2xx - 2yy
  1718. */
  1719. void QuatToMat(QUAT *q,MATRIXCH *m)
  1720. {
  1721. int q_w, q_x, q_y, q_z;
  1722. int q_2x, q_2y, q_2z;
  1723. int q_2xw;
  1724. int q_2xx;
  1725. int q_2xy;
  1726. int q_2xz;
  1727. int q_2yw;
  1728. int q_2yy;
  1729. int q_2yz;
  1730. int q_2zw;
  1731. int q_2zz;
  1732. /*
  1733. The most efficient way to create the matrix is as follows
  1734. 1/ Double x, y & z
  1735. */
  1736. q_w=q->quatw;
  1737. q_x=q->quatx;
  1738. q_y=q->quaty;
  1739. q_z=q->quatz;
  1740. q_2x=q_x*2;
  1741. q_2y=q_y*2;
  1742. q_2z=q_z*2;
  1743. /*
  1744. 2/ Form their products with w, x, y & z
  1745. These are
  1746. (2x)w (2y)w (2z)w
  1747. (2x)x
  1748. (2x)y (2y)y
  1749. (2x)z (2y)z (2z)z
  1750. */
  1751. q_2xw=MUL_FIXED(q_2x,q_w);
  1752. q_2yw=MUL_FIXED(q_2y,q_w);
  1753. q_2zw=MUL_FIXED(q_2z,q_w);
  1754. q_2xx=MUL_FIXED(q_2x,q_x);
  1755. q_2xy=MUL_FIXED(q_2x,q_y);
  1756. q_2yy=MUL_FIXED(q_2y,q_y);
  1757. q_2xz=MUL_FIXED(q_2x,q_z);
  1758. q_2yz=MUL_FIXED(q_2y,q_z);
  1759. q_2zz=MUL_FIXED(q_2z,q_z);
  1760. /* mat11 = 1 - 2y^2 - 2z^2 */
  1761. m->mat11=ONE_FIXED-q_2yy-q_2zz;
  1762. /* mat12 = 2xy - 2wz */
  1763. m->mat12=q_2xy-q_2zw;
  1764. /* mat13 = 2xz + 2wy */
  1765. m->mat13=q_2xz+q_2yw;
  1766. /* mat21 = 2xy + 2wz */
  1767. m->mat21=q_2xy+q_2zw;
  1768. /* mat22 = 1 - 2x^2 - 2z^2 */
  1769. m->mat22=ONE_FIXED-q_2xx-q_2zz;
  1770. /* mat23 = 2yz - 2wx */
  1771. m->mat23=q_2yz-q_2xw;
  1772. /* mat31 = 2xz - 2wy */
  1773. m->mat31=q_2xz-q_2yw;
  1774. /* mat32 = 2yz + 2wx */
  1775. m->mat32=q_2yz+q_2xw;
  1776. /* mat33 = 1 - 2x^2 - 2y^2 */
  1777. m->mat33=ONE_FIXED-q_2xx-q_2yy;
  1778. }