NvStanHull.cpp 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464
  1. /*
  2. NvStanHull.cpp : A convex hull generator written by Stan Melax
  3. */
  4. /*!
  5. **
  6. ** Copyright (c) 2009 by John W. Ratcliff mailto:[email protected]
  7. **
  8. ** Portions of this source has been released with the PhysXViewer application, as well as
  9. ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
  10. **
  11. ** If you find this code useful or you are feeling particularily generous I would
  12. ** ask that you please go to http://www.amillionpixels.us and make a donation
  13. ** to Troy DeMolay.
  14. **
  15. ** DeMolay is a youth group for young men between the ages of 12 and 21.
  16. ** It teaches strong moral principles, as well as leadership skills and
  17. ** public speaking. The donations page uses the 'pay for pixels' paradigm
  18. ** where, in this case, a pixel is only a single penny. Donations can be
  19. ** made for as small as $4 or as high as a $100 block. Each person who donates
  20. ** will get a link to their own site as well as acknowledgement on the
  21. ** donations blog located here http://www.amillionpixels.blogspot.com/
  22. **
  23. ** If you wish to contact me you can use the following methods:
  24. **
  25. ** Skype ID: jratcliff63367
  26. ** Yahoo: jratcliff63367
  27. ** AOL: jratcliff1961
  28. ** email: [email protected]
  29. **
  30. **
  31. ** The MIT license:
  32. **
  33. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  34. ** of this software and associated documentation files (the "Software"), to deal
  35. ** in the Software without restriction, including without limitation the rights
  36. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  37. ** copies of the Software, and to permit persons to whom the Software is furnished
  38. ** to do so, subject to the following conditions:
  39. **
  40. ** The above copyright notice and this permission notice shall be included in all
  41. ** copies or substantial portions of the Software.
  42. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  43. ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  44. ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  45. ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  46. ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  47. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. */
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <assert.h>
  53. #include <math.h>
  54. #include <float.h>
  55. #include <stdarg.h>
  56. #include <setjmp.h>
  57. #include "NvStanHull.h"
  58. namespace CONVEX_DECOMPOSITION
  59. {
  60. //*****************************************************
  61. //*** DARRAY.H
  62. //*****************************************************
  63. template <class Type> class ArrayRet;
  64. template <class Type> class Array
  65. {
  66. public:
  67. Array(NxI32 s=0);
  68. Array(Array<Type> &array);
  69. Array(ArrayRet<Type> &array);
  70. ~Array();
  71. void allocate(NxI32 s);
  72. void SetSize(NxI32 s);
  73. void Pack();
  74. Type& Add(Type);
  75. void AddUnique(Type);
  76. NxI32 Contains(Type);
  77. void Insert(Type,NxI32);
  78. NxI32 IndexOf(Type);
  79. void Remove(Type);
  80. void DelIndex(NxI32 i);
  81. Type * element;
  82. NxI32 count;
  83. NxI32 array_size;
  84. const Type &operator[](NxI32 i) const { assert(i>=0 && i<count); return element[i]; }
  85. Type &operator[](NxI32 i) { assert(i>=0 && i<count); return element[i]; }
  86. Type &Pop() { assert(count); count--; return element[count]; }
  87. Array<Type> &operator=(Array<Type> &array);
  88. Array<Type> &operator=(ArrayRet<Type> &array);
  89. // operator ArrayRet<Type> &() { return *(ArrayRet<Type> *)this;} // this worked but i suspect could be dangerous
  90. };
  91. template <class Type> class ArrayRet:public Array<Type>
  92. {
  93. };
  94. template <class Type> Array<Type>::Array(NxI32 s)
  95. {
  96. count=0;
  97. array_size = 0;
  98. element = NULL;
  99. if(s)
  100. {
  101. allocate(s);
  102. }
  103. }
  104. template <class Type> Array<Type>::Array(Array<Type> &array)
  105. {
  106. count=0;
  107. array_size = 0;
  108. element = NULL;
  109. for(NxI32 i=0;i<array.count;i++)
  110. {
  111. Add(array[i]);
  112. }
  113. }
  114. template <class Type> Array<Type>::Array(ArrayRet<Type> &array)
  115. {
  116. *this = array;
  117. }
  118. template <class Type> Array<Type> &Array<Type>::operator=(ArrayRet<Type> &array)
  119. {
  120. count=array.count;
  121. array_size = array.array_size;
  122. element = array.element;
  123. array.element=NULL;
  124. array.count=0;
  125. array.array_size=0;
  126. return *this;
  127. }
  128. template <class Type> Array<Type> &Array<Type>::operator=(Array<Type> &array)
  129. {
  130. count=0;
  131. for(NxI32 i=0;i<array.count;i++)
  132. {
  133. Add(array[i]);
  134. }
  135. return *this;
  136. }
  137. template <class Type> Array<Type>::~Array()
  138. {
  139. if (element != NULL)
  140. {
  141. MEMALLOC_FREE(element);
  142. }
  143. count=0;array_size=0;element=NULL;
  144. }
  145. template <class Type> void Array<Type>::allocate(NxI32 s)
  146. {
  147. assert(s>0);
  148. assert(s>=count);
  149. Type *old = element;
  150. array_size =s;
  151. element = (Type *) MEMALLOC_MALLOC( sizeof(Type)*array_size );
  152. assert(element);
  153. for(NxI32 i=0;i<count;i++)
  154. {
  155. element[i]=old[i];
  156. }
  157. if(old)
  158. {
  159. MEMALLOC_FREE(old);
  160. }
  161. }
  162. template <class Type> void Array<Type>::SetSize(NxI32 s)
  163. {
  164. if(s==0)
  165. {
  166. if(element)
  167. {
  168. MEMALLOC_FREE(element);
  169. element = NULL;
  170. }
  171. array_size = s;
  172. }
  173. else
  174. {
  175. allocate(s);
  176. }
  177. count=s;
  178. }
  179. template <class Type> void Array<Type>::Pack()
  180. {
  181. allocate(count);
  182. }
  183. template <class Type> Type& Array<Type>::Add(Type t)
  184. {
  185. assert(count<=array_size);
  186. if(count==array_size)
  187. {
  188. allocate((array_size)?array_size *2:16);
  189. }
  190. element[count++] = t;
  191. return element[count-1];
  192. }
  193. template <class Type> NxI32 Array<Type>::Contains(Type t)
  194. {
  195. NxI32 i;
  196. NxI32 found=0;
  197. for(i=0;i<count;i++)
  198. {
  199. if(element[i] == t) found++;
  200. }
  201. return found;
  202. }
  203. template <class Type> void Array<Type>::AddUnique(Type t)
  204. {
  205. if(!Contains(t)) Add(t);
  206. }
  207. template <class Type> void Array<Type>::DelIndex(NxI32 i)
  208. {
  209. assert(i<count);
  210. count--;
  211. while(i<count)
  212. {
  213. element[i] = element[i+1];
  214. i++;
  215. }
  216. }
  217. template <class Type> void Array<Type>::Remove(Type t)
  218. {
  219. NxI32 i;
  220. for(i=0;i<count;i++)
  221. {
  222. if(element[i] == t)
  223. {
  224. break;
  225. }
  226. }
  227. assert(i<count); // assert object t is in the array.
  228. DelIndex(i);
  229. for(i=0;i<count;i++)
  230. {
  231. assert(element[i] != t);
  232. }
  233. }
  234. template <class Type> void Array<Type>::Insert(Type t,NxI32 k)
  235. {
  236. NxI32 i=count;
  237. Add(t); // to allocate space
  238. while(i>k)
  239. {
  240. element[i]=element[i-1];
  241. i--;
  242. }
  243. assert(i==k);
  244. element[k]=t;
  245. }
  246. template <class Type> NxI32 Array<Type>::IndexOf(Type t)
  247. {
  248. NxI32 i;
  249. for(i=0;i<count;i++)
  250. {
  251. if(element[i] == t)
  252. {
  253. return i;
  254. }
  255. }
  256. assert(0);
  257. return -1;
  258. }
  259. //****************************************************
  260. //** VECMATH.H
  261. //****************************************************
  262. #define PI (3.1415926535897932384626433832795f)
  263. #define DEG2RAD (PI / 180.0f)
  264. #define RAD2DEG (180.0f / PI)
  265. #define SQRT_OF_2 (1.4142135f)
  266. #define OFFSET(Class,Member) (((char*) (&(((Class*)NULL)-> Member )))- ((char*)NULL))
  267. NxI32 argmin(NxF32 a[],NxI32 n);
  268. NxF32 sqr(NxF32 a);
  269. NxF32 clampf(NxF32 a) ;
  270. NxF32 Round(NxF32 a,NxF32 precision);
  271. NxF32 Interpolate(const NxF32 &f0,const NxF32 &f1,NxF32 alpha) ;
  272. template <class T>
  273. void Swap(T &a,T &b)
  274. {
  275. T tmp = a;
  276. a=b;
  277. b=tmp;
  278. }
  279. template <class T>
  280. T Max(const T &a,const T &b)
  281. {
  282. return (a>b)?a:b;
  283. }
  284. template <class T>
  285. T Min(const T &a,const T &b)
  286. {
  287. return (a<b)?a:b;
  288. }
  289. //----------------------------------
  290. class int3 : public Memalloc
  291. {
  292. public:
  293. NxI32 x,y,z;
  294. int3(){};
  295. int3(NxI32 _x,NxI32 _y, NxI32 _z){x=_x;y=_y;z=_z;}
  296. const NxI32& operator[](NxI32 i) const {return (&x)[i];}
  297. NxI32& operator[](NxI32 i) {return (&x)[i];}
  298. };
  299. //-------- 2D --------
  300. class float2 : public Memalloc
  301. {
  302. public:
  303. NxF32 x,y;
  304. float2(){x=0;y=0;};
  305. float2(NxF32 _x,NxF32 _y){x=_x;y=_y;}
  306. NxF32& operator[](NxI32 i) {assert(i>=0&&i<2);return ((NxF32*)this)[i];}
  307. const NxF32& operator[](NxI32 i) const {assert(i>=0&&i<2);return ((NxF32*)this)[i];}
  308. };
  309. inline float2 operator-( const float2& a, const float2& b ){return float2(a.x-b.x,a.y-b.y);}
  310. inline float2 operator+( const float2& a, const float2& b ){return float2(a.x+b.x,a.y+b.y);}
  311. //--------- 3D ---------
  312. class float3 : public Memalloc // 3D
  313. {
  314. public:
  315. NxF32 x,y,z;
  316. float3(){x=0;y=0;z=0;};
  317. float3(NxF32 _x,NxF32 _y,NxF32 _z){x=_x;y=_y;z=_z;};
  318. //operator NxF32 *() { return &x;};
  319. NxF32& operator[](NxI32 i) {assert(i>=0&&i<3);return ((NxF32*)this)[i];}
  320. const NxF32& operator[](NxI32 i) const {assert(i>=0&&i<3);return ((NxF32*)this)[i];}
  321. };
  322. float3& operator+=( float3 &a, const float3& b );
  323. float3& operator-=( float3 &a ,const float3& b );
  324. float3& operator*=( float3 &v ,const NxF32 s );
  325. float3& operator/=( float3 &v, const NxF32 s );
  326. NxF32 magnitude( const float3& v );
  327. float3 normalize( const float3& v );
  328. float3 safenormalize(const float3 &v);
  329. float3 vabs(const float3 &v);
  330. float3 operator+( const float3& a, const float3& b );
  331. float3 operator-( const float3& a, const float3& b );
  332. float3 operator-( const float3& v );
  333. float3 operator*( const float3& v, const NxF32 s );
  334. float3 operator*( const NxF32 s, const float3& v );
  335. float3 operator/( const float3& v, const NxF32 s );
  336. inline NxI32 operator==( const float3 &a, const float3 &b ) { return (a.x==b.x && a.y==b.y && a.z==b.z); }
  337. inline NxI32 operator!=( const float3 &a, const float3 &b ) { return (a.x!=b.x || a.y!=b.y || a.z!=b.z); }
  338. // due to ambiguity and inconsistent standards ther are no overloaded operators for mult such as va*vb.
  339. NxF32 dot( const float3& a, const float3& b );
  340. float3 cmul( const float3 &a, const float3 &b);
  341. float3 cross( const float3& a, const float3& b );
  342. float3 Interpolate(const float3 &v0,const float3 &v1,NxF32 alpha);
  343. float3 Round(const float3& a,NxF32 precision);
  344. float3 VectorMax(const float3 &a, const float3 &b);
  345. float3 VectorMin(const float3 &a, const float3 &b);
  346. class float3x3 : public Memalloc
  347. {
  348. public:
  349. float3 x,y,z; // the 3 rows of the Matrix
  350. float3x3(){}
  351. float3x3(NxF32 xx,NxF32 xy,NxF32 xz,NxF32 yx,NxF32 yy,NxF32 yz,NxF32 zx,NxF32 zy,NxF32 zz):x(xx,xy,xz),y(yx,yy,yz),z(zx,zy,zz){}
  352. float3x3(float3 _x,float3 _y,float3 _z):x(_x),y(_y),z(_z){}
  353. float3& operator[](NxI32 i) {assert(i>=0&&i<3);return (&x)[i];}
  354. const float3& operator[](NxI32 i) const {assert(i>=0&&i<3);return (&x)[i];}
  355. NxF32& operator()(NxI32 r, NxI32 c) {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
  356. const NxF32& operator()(NxI32 r, NxI32 c) const {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
  357. };
  358. float3x3 Transpose( const float3x3& m );
  359. float3 operator*( const float3& v , const float3x3& m );
  360. float3 operator*( const float3x3& m , const float3& v );
  361. float3x3 operator*( const float3x3& m , const NxF32& s );
  362. float3x3 operator*( const float3x3& ma, const float3x3& mb );
  363. float3x3 operator/( const float3x3& a, const NxF32& s ) ;
  364. float3x3 operator+( const float3x3& a, const float3x3& b );
  365. float3x3 operator-( const float3x3& a, const float3x3& b );
  366. float3x3 &operator+=( float3x3& a, const float3x3& b );
  367. float3x3 &operator-=( float3x3& a, const float3x3& b );
  368. float3x3 &operator*=( float3x3& a, const NxF32& s );
  369. NxF32 Determinant(const float3x3& m );
  370. float3x3 Inverse(const float3x3& a); // its just 3x3 so we simply do that cofactor method
  371. //-------- 4D Math --------
  372. class float4 : public Memalloc
  373. {
  374. public:
  375. NxF32 x,y,z,w;
  376. float4(){x=0;y=0;z=0;w=0;};
  377. float4(NxF32 _x,NxF32 _y,NxF32 _z,NxF32 _w){x=_x;y=_y;z=_z;w=_w;}
  378. float4(const float3 &v,NxF32 _w){x=v.x;y=v.y;z=v.z;w=_w;}
  379. //operator NxF32 *() { return &x;};
  380. NxF32& operator[](NxI32 i) {assert(i>=0&&i<4);return ((NxF32*)this)[i];}
  381. const NxF32& operator[](NxI32 i) const {assert(i>=0&&i<4);return ((NxF32*)this)[i];}
  382. const float3& xyz() const { return *((float3*)this);}
  383. float3& xyz() { return *((float3*)this);}
  384. };
  385. struct D3DXMATRIX;
  386. class float4x4 : public Memalloc
  387. {
  388. public:
  389. float4 x,y,z,w; // the 4 rows
  390. float4x4(){}
  391. float4x4(const float4 &_x, const float4 &_y, const float4 &_z, const float4 &_w):x(_x),y(_y),z(_z),w(_w){}
  392. float4x4(NxF32 m00, NxF32 m01, NxF32 m02, NxF32 m03,
  393. NxF32 m10, NxF32 m11, NxF32 m12, NxF32 m13,
  394. NxF32 m20, NxF32 m21, NxF32 m22, NxF32 m23,
  395. NxF32 m30, NxF32 m31, NxF32 m32, NxF32 m33 )
  396. :x(m00,m01,m02,m03),y(m10,m11,m12,m13),z(m20,m21,m22,m23),w(m30,m31,m32,m33){}
  397. NxF32& operator()(NxI32 r, NxI32 c) {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
  398. const NxF32& operator()(NxI32 r, NxI32 c) const {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
  399. operator NxF32* () {return &x.x;}
  400. operator const NxF32* () const {return &x.x;}
  401. operator struct D3DXMATRIX* () { return (struct D3DXMATRIX*) this;}
  402. operator const struct D3DXMATRIX* () const { return (struct D3DXMATRIX*) this;}
  403. };
  404. NxI32 operator==( const float4 &a, const float4 &b );
  405. float4 Homogenize(const float3 &v3,const NxF32 &w=1.0f); // Turns a 3D float3 4D vector4 by appending w
  406. float4 cmul( const float4 &a, const float4 &b);
  407. float4 operator*( const float4 &v, NxF32 s);
  408. float4 operator*( NxF32 s, const float4 &v);
  409. float4 operator+( const float4 &a, const float4 &b);
  410. float4 operator-( const float4 &a, const float4 &b);
  411. float4x4 operator*( const float4x4& a, const float4x4& b );
  412. float4 operator*( const float4& v, const float4x4& m );
  413. float4x4 Inverse(const float4x4 &m);
  414. float4x4 MatrixRigidInverse(const float4x4 &m);
  415. float4x4 MatrixTranspose(const float4x4 &m);
  416. float4x4 MatrixPerspectiveFov(NxF32 fovy, NxF32 Aspect, NxF32 zn, NxF32 zf );
  417. float4x4 MatrixTranslation(const float3 &t);
  418. float4x4 MatrixRotationZ(const NxF32 angle_radians);
  419. float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up);
  420. NxI32 operator==( const float4x4 &a, const float4x4 &b );
  421. //-------- Quaternion ------------
  422. class Quaternion :public float4
  423. {
  424. public:
  425. Quaternion() { x = y = z = 0.0f; w = 1.0f; }
  426. Quaternion( float3 v, NxF32 t ) { v = normalize(v); w = cosf(t/2.0f); v = v*sinf(t/2.0f); x = v.x; y = v.y; z = v.z; }
  427. Quaternion(NxF32 _x, NxF32 _y, NxF32 _z, NxF32 _w){x=_x;y=_y;z=_z;w=_w;}
  428. NxF32 angle() const { return acosf(w)*2.0f; }
  429. float3 axis() const { float3 a(x,y,z); if(fabsf(angle())<0.0000001f) return float3(1,0,0); return a*(1/sinf(angle()/2.0f)); }
  430. float3 xdir() const { return float3( 1-2*(y*y+z*z), 2*(x*y+w*z), 2*(x*z-w*y) ); }
  431. float3 ydir() const { return float3( 2*(x*y-w*z),1-2*(x*x+z*z), 2*(y*z+w*x) ); }
  432. float3 zdir() const { return float3( 2*(x*z+w*y), 2*(y*z-w*x),1-2*(x*x+y*y) ); }
  433. float3x3 getmatrix() const { return float3x3( xdir(), ydir(), zdir() ); }
  434. operator float3x3() { return getmatrix(); }
  435. void Normalize();
  436. };
  437. Quaternion& operator*=(Quaternion& a, NxF32 s );
  438. Quaternion operator*( const Quaternion& a, NxF32 s );
  439. Quaternion operator*( const Quaternion& a, const Quaternion& b);
  440. Quaternion operator+( const Quaternion& a, const Quaternion& b );
  441. Quaternion normalize( Quaternion a );
  442. NxF32 dot( const Quaternion &a, const Quaternion &b );
  443. float3 operator*( const Quaternion& q, const float3& v );
  444. float3 operator*( const float3& v, const Quaternion& q );
  445. Quaternion slerp( Quaternion a, const Quaternion& b, NxF32 interp );
  446. Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,NxF32 alpha);
  447. Quaternion RotationArc(float3 v0, float3 v1 ); // returns quat q where q*v0=v1
  448. Quaternion Inverse(const Quaternion &q);
  449. float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v);
  450. //------ Euler Angle -----
  451. Quaternion YawPitchRoll( NxF32 yaw, NxF32 pitch, NxF32 roll );
  452. NxF32 Yaw( const Quaternion& q );
  453. NxF32 Pitch( const Quaternion& q );
  454. NxF32 Roll( Quaternion q );
  455. NxF32 Yaw( const float3& v );
  456. NxF32 Pitch( const float3& v );
  457. //------- Plane ----------
  458. class Plane
  459. {
  460. public:
  461. float3 normal;
  462. NxF32 dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
  463. Plane(const float3 &n,NxF32 d):normal(n),dist(d){}
  464. Plane():normal(),dist(0){}
  465. void Transform(const float3 &position, const Quaternion &orientation);
  466. };
  467. inline Plane PlaneFlip(const Plane &plane){return Plane(-plane.normal,-plane.dist);}
  468. inline NxI32 operator==( const Plane &a, const Plane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
  469. inline NxI32 coplanar( const Plane &a, const Plane &b ) { return (a==b || a==PlaneFlip(b)); }
  470. //--------- Utility Functions ------
  471. float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1);
  472. float3 PlaneProject(const Plane &plane, const float3 &point);
  473. float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a); // projects a onto infinite line p0p1
  474. NxF32 LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a);
  475. float3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2);
  476. NxI32 PolyHit(const float3 *vert,const NxI32 n,const float3 &v0, const float3 &v1, float3 *impact=NULL, float3 *normal=NULL);
  477. NxI32 BoxInside(const float3 &p,const float3 &bmin, const float3 &bmax) ;
  478. NxI32 BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax, float3 *impact);
  479. NxF32 DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint=NULL, float3 *vpoint=NULL);
  480. float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2);
  481. float3 NormalOf(const float3 *vert, const NxI32 n);
  482. Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir0, const float3 &dir1);
  483. //*****************************************************
  484. // ** VECMATH.CPP
  485. //*****************************************************
  486. NxF32 sqr(NxF32 a) {return a*a;}
  487. NxF32 clampf(NxF32 a) {return Min(1.0f,Max(0.0f,a));}
  488. NxF32 Round(NxF32 a,NxF32 precision)
  489. {
  490. return floorf(0.5f+a/precision)*precision;
  491. }
  492. NxF32 Interpolate(const NxF32 &f0,const NxF32 &f1,NxF32 alpha)
  493. {
  494. return f0*(1-alpha) + f1*alpha;
  495. }
  496. NxI32 argmin(NxF32 a[],NxI32 n)
  497. {
  498. NxI32 r=0;
  499. for(NxI32 i=1;i<n;i++)
  500. {
  501. if(a[i]<a[r])
  502. {
  503. r = i;
  504. }
  505. }
  506. return r;
  507. }
  508. //------------ float3 (3D) --------------
  509. float3 operator+( const float3& a, const float3& b )
  510. {
  511. return float3(a.x+b.x, a.y+b.y, a.z+b.z);
  512. }
  513. float3 operator-( const float3& a, const float3& b )
  514. {
  515. return float3( a.x-b.x, a.y-b.y, a.z-b.z );
  516. }
  517. float3 operator-( const float3& v )
  518. {
  519. return float3( -v.x, -v.y, -v.z );
  520. }
  521. float3 operator*( const float3& v, NxF32 s )
  522. {
  523. return float3( v.x*s, v.y*s, v.z*s );
  524. }
  525. float3 operator*( NxF32 s, const float3& v )
  526. {
  527. return float3( v.x*s, v.y*s, v.z*s );
  528. }
  529. float3 operator/( const float3& v, NxF32 s )
  530. {
  531. return v*(1.0f/s);
  532. }
  533. NxF32 dot( const float3& a, const float3& b )
  534. {
  535. return a.x*b.x + a.y*b.y + a.z*b.z;
  536. }
  537. float3 cmul( const float3 &v1, const float3 &v2)
  538. {
  539. return float3(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
  540. }
  541. float3 cross( const float3& a, const float3& b )
  542. {
  543. return float3( a.y*b.z - a.z*b.y,
  544. a.z*b.x - a.x*b.z,
  545. a.x*b.y - a.y*b.x );
  546. }
  547. float3& operator+=( float3& a , const float3& b )
  548. {
  549. a.x += b.x;
  550. a.y += b.y;
  551. a.z += b.z;
  552. return a;
  553. }
  554. float3& operator-=( float3& a , const float3& b )
  555. {
  556. a.x -= b.x;
  557. a.y -= b.y;
  558. a.z -= b.z;
  559. return a;
  560. }
  561. float3& operator*=(float3& v , NxF32 s )
  562. {
  563. v.x *= s;
  564. v.y *= s;
  565. v.z *= s;
  566. return v;
  567. }
  568. float3& operator/=(float3& v , NxF32 s )
  569. {
  570. NxF32 sinv = 1.0f / s;
  571. v.x *= sinv;
  572. v.y *= sinv;
  573. v.z *= sinv;
  574. return v;
  575. }
  576. float3 vabs(const float3 &v)
  577. {
  578. return float3(fabsf(v.x),fabsf(v.y),fabsf(v.z));
  579. }
  580. NxF32 magnitude( const float3& v )
  581. {
  582. return sqrtf(sqr(v.x) + sqr( v.y)+ sqr(v.z));
  583. }
  584. float3 normalize( const float3 &v )
  585. {
  586. // this routine, normalize, is ok, provided magnitude works!!
  587. NxF32 d=magnitude(v);
  588. if (d==0)
  589. {
  590. printf("Cant normalize ZERO vector\n");
  591. assert(0);// yes this could go here
  592. d=0.1f;
  593. }
  594. d = 1/d;
  595. return float3(v.x*d,v.y*d,v.z*d);
  596. }
  597. float3 safenormalize(const float3 &v)
  598. {
  599. if(magnitude(v)<=0.0f)
  600. {
  601. return float3(1,0,0);
  602. }
  603. return normalize(v);
  604. }
  605. float3 Round(const float3 &a,NxF32 precision)
  606. {
  607. return float3(Round(a.x,precision),Round(a.y,precision),Round(a.z,precision));
  608. }
  609. float3 Interpolate(const float3 &v0,const float3 &v1,NxF32 alpha)
  610. {
  611. return v0*(1-alpha) + v1*alpha;
  612. }
  613. float3 VectorMin(const float3 &a,const float3 &b)
  614. {
  615. return float3(Min(a.x,b.x),Min(a.y,b.y),Min(a.z,b.z));
  616. }
  617. float3 VectorMax(const float3 &a,const float3 &b)
  618. {
  619. return float3(Max(a.x,b.x),Max(a.y,b.y),Max(a.z,b.z));
  620. }
  621. // the statement v1*v2 is ambiguous since there are 3 types
  622. // of vector multiplication
  623. // - componantwise (for example combining colors)
  624. // - dot product
  625. // - cross product
  626. // Therefore we never declare/implement this function.
  627. // So we will never see: float3 operator*(float3 a,float3 b)
  628. //------------ float3x3 ---------------
  629. NxF32 Determinant(const float3x3 &m)
  630. {
  631. return m.x.x*m.y.y*m.z.z + m.y.x*m.z.y*m.x.z + m.z.x*m.x.y*m.y.z
  632. -m.x.x*m.z.y*m.y.z - m.y.x*m.x.y*m.z.z - m.z.x*m.y.y*m.x.z ;
  633. }
  634. float3x3 Inverse(const float3x3 &a)
  635. {
  636. float3x3 b;
  637. NxF32 d=Determinant(a);
  638. assert(d!=0);
  639. for(NxI32 i=0;i<3;i++)
  640. {
  641. for(NxI32 j=0;j<3;j++)
  642. {
  643. NxI32 i1=(i+1)%3;
  644. NxI32 i2=(i+2)%3;
  645. NxI32 j1=(j+1)%3;
  646. NxI32 j2=(j+2)%3;
  647. // reverse indexs i&j to take transpose
  648. b[j][i] = (a[i1][j1]*a[i2][j2]-a[i1][j2]*a[i2][j1])/d;
  649. }
  650. }
  651. // Matrix check=a*b; // Matrix 'check' should be the identity (or close to it)
  652. return b;
  653. }
  654. float3x3 Transpose( const float3x3& m )
  655. {
  656. return float3x3( float3(m.x.x,m.y.x,m.z.x),
  657. float3(m.x.y,m.y.y,m.z.y),
  658. float3(m.x.z,m.y.z,m.z.z));
  659. }
  660. float3 operator*(const float3& v , const float3x3 &m ) {
  661. return float3((m.x.x*v.x + m.y.x*v.y + m.z.x*v.z),
  662. (m.x.y*v.x + m.y.y*v.y + m.z.y*v.z),
  663. (m.x.z*v.x + m.y.z*v.y + m.z.z*v.z));
  664. }
  665. float3 operator*(const float3x3 &m,const float3& v ) {
  666. return float3(dot(m.x,v),dot(m.y,v),dot(m.z,v));
  667. }
  668. float3x3 operator*( const float3x3& a, const float3x3& b )
  669. {
  670. return float3x3(a.x*b,a.y*b,a.z*b);
  671. }
  672. float3x3 operator*( const float3x3& a, const NxF32& s )
  673. {
  674. return float3x3(a.x*s, a.y*s ,a.z*s);
  675. }
  676. float3x3 operator/( const float3x3& a, const NxF32& s )
  677. {
  678. NxF32 t=1/s;
  679. return float3x3(a.x*t, a.y*t ,a.z*t);
  680. }
  681. float3x3 operator+( const float3x3& a, const float3x3& b )
  682. {
  683. return float3x3(a.x+b.x, a.y+b.y, a.z+b.z);
  684. }
  685. float3x3 operator-( const float3x3& a, const float3x3& b )
  686. {
  687. return float3x3(a.x-b.x, a.y-b.y, a.z-b.z);
  688. }
  689. float3x3 &operator+=( float3x3& a, const float3x3& b )
  690. {
  691. a.x+=b.x;
  692. a.y+=b.y;
  693. a.z+=b.z;
  694. return a;
  695. }
  696. float3x3 &operator-=( float3x3& a, const float3x3& b )
  697. {
  698. a.x-=b.x;
  699. a.y-=b.y;
  700. a.z-=b.z;
  701. return a;
  702. }
  703. float3x3 &operator*=( float3x3& a, const NxF32& s )
  704. {
  705. a.x*=s;
  706. a.y*=s;
  707. a.z*=s;
  708. return a;
  709. }
  710. float3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2){
  711. float3x3 mp =Transpose(float3x3(p0.normal,p1.normal,p2.normal));
  712. float3x3 mi = Inverse(mp);
  713. float3 b(p0.dist,p1.dist,p2.dist);
  714. return -b * mi;
  715. }
  716. //--------------- 4D ----------------
  717. float4 operator*( const float4& v, const float4x4& m )
  718. {
  719. return v.x*m.x + v.y*m.y + v.z*m.z + v.w*m.w; // yes this actually works
  720. }
  721. NxI32 operator==( const float4 &a, const float4 &b )
  722. {
  723. return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
  724. }
  725. // Dont implement m*v for now, since that might confuse us
  726. // All our transforms are based on multiplying the "row" vector on the left
  727. //float4 operator*(const float4x4& m , const float4& v )
  728. //{
  729. // return float4(dot(v,m.x),dot(v,m.y),dot(v,m.z),dot(v,m.w));
  730. //}
  731. float4 cmul( const float4 &a, const float4 &b)
  732. {
  733. return float4(a.x*b.x,a.y*b.y,a.z*b.z,a.w*b.w);
  734. }
  735. float4 operator*( const float4 &v, NxF32 s)
  736. {
  737. return float4(v.x*s,v.y*s,v.z*s,v.w*s);
  738. }
  739. float4 operator*( NxF32 s, const float4 &v)
  740. {
  741. return float4(v.x*s,v.y*s,v.z*s,v.w*s);
  742. }
  743. float4 operator+( const float4 &a, const float4 &b)
  744. {
  745. return float4(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);
  746. }
  747. float4 operator-( const float4 &a, const float4 &b)
  748. {
  749. return float4(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);
  750. }
  751. float4 Homogenize(const float3 &v3,const NxF32 &w)
  752. {
  753. return float4(v3.x,v3.y,v3.z,w);
  754. }
  755. float4x4 operator*( const float4x4& a, const float4x4& b )
  756. {
  757. return float4x4(a.x*b,a.y*b,a.z*b,a.w*b);
  758. }
  759. float4x4 MatrixTranspose(const float4x4 &m)
  760. {
  761. return float4x4(
  762. m.x.x, m.y.x, m.z.x, m.w.x,
  763. m.x.y, m.y.y, m.z.y, m.w.y,
  764. m.x.z, m.y.z, m.z.z, m.w.z,
  765. m.x.w, m.y.w, m.z.w, m.w.w );
  766. }
  767. float4x4 MatrixRigidInverse(const float4x4 &m)
  768. {
  769. float4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
  770. float4x4 rot = m;
  771. rot.w = float4(0,0,0,1);
  772. return trans_inverse * MatrixTranspose(rot);
  773. }
  774. float4x4 MatrixPerspectiveFov(NxF32 fovy, NxF32 aspect, NxF32 zn, NxF32 zf )
  775. {
  776. NxF32 h = 1.0f/tanf(fovy/2.0f); // view space height
  777. NxF32 w = h / aspect ; // view space width
  778. return float4x4(
  779. w, 0, 0 , 0,
  780. 0, h, 0 , 0,
  781. 0, 0, zf/(zn-zf) , -1,
  782. 0, 0, zn*zf/(zn-zf) , 0 );
  783. }
  784. float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up)
  785. {
  786. float4x4 m;
  787. m.w.w = 1.0f;
  788. m.w.xyz() = eye;
  789. m.z.xyz() = normalize(eye-at);
  790. m.x.xyz() = normalize(cross(up,m.z.xyz()));
  791. m.y.xyz() = cross(m.z.xyz(),m.x.xyz());
  792. return MatrixRigidInverse(m);
  793. }
  794. float4x4 MatrixTranslation(const float3 &t)
  795. {
  796. return float4x4(
  797. 1, 0, 0, 0,
  798. 0, 1, 0, 0,
  799. 0, 0, 1, 0,
  800. t.x,t.y,t.z,1 );
  801. }
  802. float4x4 MatrixRotationZ(const NxF32 angle_radians)
  803. {
  804. NxF32 s = sinf(angle_radians);
  805. NxF32 c = cosf(angle_radians);
  806. return float4x4(
  807. c, s, 0, 0,
  808. -s, c, 0, 0,
  809. 0, 0, 1, 0,
  810. 0, 0, 0, 1 );
  811. }
  812. NxI32 operator==( const float4x4 &a, const float4x4 &b )
  813. {
  814. return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
  815. }
  816. float4x4 Inverse(const float4x4 &m)
  817. {
  818. float4x4 d;
  819. NxF32 *dst = &d.x.x;
  820. NxF32 tmp[12]; /* temp array for pairs */
  821. NxF32 src[16]; /* array of transpose source matrix */
  822. NxF32 det; /* determinant */
  823. /* transpose matrix */
  824. for ( NxI32 i = 0; i < 4; i++) {
  825. src[i] = m(i,0) ;
  826. src[i + 4] = m(i,1);
  827. src[i + 8] = m(i,2);
  828. src[i + 12] = m(i,3);
  829. }
  830. /* calculate pairs for first 8 elements (cofactors) */
  831. tmp[0] = src[10] * src[15];
  832. tmp[1] = src[11] * src[14];
  833. tmp[2] = src[9] * src[15];
  834. tmp[3] = src[11] * src[13];
  835. tmp[4] = src[9] * src[14];
  836. tmp[5] = src[10] * src[13];
  837. tmp[6] = src[8] * src[15];
  838. tmp[7] = src[11] * src[12];
  839. tmp[8] = src[8] * src[14];
  840. tmp[9] = src[10] * src[12];
  841. tmp[10] = src[8] * src[13];
  842. tmp[11] = src[9] * src[12];
  843. /* calculate first 8 elements (cofactors) */
  844. dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
  845. dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
  846. dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
  847. dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
  848. dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
  849. dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
  850. dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
  851. dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
  852. dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
  853. dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
  854. dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
  855. dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
  856. dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
  857. dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
  858. dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
  859. dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
  860. /* calculate pairs for second 8 elements (cofactors) */
  861. tmp[0] = src[2]*src[7];
  862. tmp[1] = src[3]*src[6];
  863. tmp[2] = src[1]*src[7];
  864. tmp[3] = src[3]*src[5];
  865. tmp[4] = src[1]*src[6];
  866. tmp[5] = src[2]*src[5];
  867. tmp[6] = src[0]*src[7];
  868. tmp[7] = src[3]*src[4];
  869. tmp[8] = src[0]*src[6];
  870. tmp[9] = src[2]*src[4];
  871. tmp[10] = src[0]*src[5];
  872. tmp[11] = src[1]*src[4];
  873. /* calculate second 8 elements (cofactors) */
  874. dst[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
  875. dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
  876. dst[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
  877. dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
  878. dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
  879. dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
  880. dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
  881. dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
  882. dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
  883. dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
  884. dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
  885. dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
  886. dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
  887. dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
  888. dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
  889. dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
  890. /* calculate determinant */
  891. det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
  892. /* calculate matrix inverse */
  893. det = 1/det;
  894. for ( NxI32 j = 0; j < 16; j++)
  895. dst[j] *= det;
  896. return d;
  897. }
  898. //--------- Quaternion --------------
  899. Quaternion operator*( const Quaternion& a, const Quaternion& b )
  900. {
  901. Quaternion c;
  902. c.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z;
  903. c.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y;
  904. c.y = a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x;
  905. c.z = a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w;
  906. return c;
  907. }
  908. Quaternion operator*( const Quaternion& a, NxF32 b )
  909. {
  910. return Quaternion(a.x*b, a.y*b, a.z*b ,a.w*b);
  911. }
  912. Quaternion Inverse(const Quaternion &q)
  913. {
  914. return Quaternion(-q.x,-q.y,-q.z,q.w);
  915. }
  916. Quaternion& operator*=( Quaternion& q, const NxF32 s )
  917. {
  918. q.x *= s;
  919. q.y *= s;
  920. q.z *= s;
  921. q.w *= s;
  922. return q;
  923. }
  924. void Quaternion::Normalize()
  925. {
  926. NxF32 m = sqrtf(sqr(w)+sqr(x)+sqr(y)+sqr(z));
  927. if(m<0.000000001f) {
  928. w=1.0f;
  929. x=y=z=0.0f;
  930. return;
  931. }
  932. (*this) *= (1.0f/m);
  933. }
  934. float3 operator*( const Quaternion& q, const float3& v )
  935. {
  936. // The following is equivalent to:
  937. //return (q.getmatrix() * v);
  938. NxF32 qx2 = q.x*q.x;
  939. NxF32 qy2 = q.y*q.y;
  940. NxF32 qz2 = q.z*q.z;
  941. NxF32 qxqy = q.x*q.y;
  942. NxF32 qxqz = q.x*q.z;
  943. NxF32 qxqw = q.x*q.w;
  944. NxF32 qyqz = q.y*q.z;
  945. NxF32 qyqw = q.y*q.w;
  946. NxF32 qzqw = q.z*q.w;
  947. return float3(
  948. (1-2*(qy2+qz2))*v.x + (2*(qxqy-qzqw))*v.y + (2*(qxqz+qyqw))*v.z ,
  949. (2*(qxqy+qzqw))*v.x + (1-2*(qx2+qz2))*v.y + (2*(qyqz-qxqw))*v.z ,
  950. (2*(qxqz-qyqw))*v.x + (2*(qyqz+qxqw))*v.y + (1-2*(qx2+qy2))*v.z );
  951. }
  952. Quaternion operator+( const Quaternion& a, const Quaternion& b )
  953. {
  954. return Quaternion(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
  955. }
  956. NxF32 dot( const Quaternion &a,const Quaternion &b )
  957. {
  958. return (a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z);
  959. }
  960. Quaternion normalize( Quaternion a )
  961. {
  962. NxF32 m = sqrtf(sqr(a.w)+sqr(a.x)+sqr(a.y)+sqr(a.z));
  963. if(m<0.000000001)
  964. {
  965. a.w=1;
  966. a.x=a.y=a.z=0;
  967. return a;
  968. }
  969. return a * (1/m);
  970. }
  971. Quaternion slerp( Quaternion a, const Quaternion& b, NxF32 interp )
  972. {
  973. if(dot(a,b) <0.0)
  974. {
  975. a.w=-a.w;
  976. a.x=-a.x;
  977. a.y=-a.y;
  978. a.z=-a.z;
  979. }
  980. NxF32 d = dot(a,b);
  981. if(d>=1.0) {
  982. return a;
  983. }
  984. NxF32 theta = acosf(d);
  985. if(theta==0.0f) { return(a);}
  986. return a*(sinf(theta-interp*theta)/sinf(theta)) + b*(sinf(interp*theta)/sinf(theta));
  987. }
  988. Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,NxF32 alpha) {
  989. return slerp(q0,q1,alpha);
  990. }
  991. Quaternion YawPitchRoll( NxF32 yaw, NxF32 pitch, NxF32 roll )
  992. {
  993. roll *= DEG2RAD;
  994. yaw *= DEG2RAD;
  995. pitch *= DEG2RAD;
  996. return Quaternion(float3(0.0f,0.0f,1.0f),yaw)*Quaternion(float3(1.0f,0.0f,0.0f),pitch)*Quaternion(float3(0.0f,1.0f,0.0f),roll);
  997. }
  998. NxF32 Yaw( const Quaternion& q )
  999. {
  1000. static float3 v;
  1001. v=q.ydir();
  1002. return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG;
  1003. }
  1004. NxF32 Pitch( const Quaternion& q )
  1005. {
  1006. static float3 v;
  1007. v=q.ydir();
  1008. return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG;
  1009. }
  1010. NxF32 Roll( Quaternion q )
  1011. {
  1012. q = Quaternion(float3(0.0f,0.0f,1.0f),-Yaw(q)*DEG2RAD) *q;
  1013. q = Quaternion(float3(1.0f,0.0f,0.0f),-Pitch(q)*DEG2RAD) *q;
  1014. return atan2f(-q.xdir().z,q.xdir().x)*RAD2DEG;
  1015. }
  1016. NxF32 Yaw( const float3& v )
  1017. {
  1018. return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG;
  1019. }
  1020. NxF32 Pitch( const float3& v )
  1021. {
  1022. return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG;
  1023. }
  1024. //------------- Plane --------------
  1025. void Plane::Transform(const float3 &position, const Quaternion &orientation) {
  1026. // Transforms the plane to the space defined by the
  1027. // given position/orientation.
  1028. static float3 newnormal;
  1029. static float3 origin;
  1030. newnormal = Inverse(orientation)*normal;
  1031. origin = Inverse(orientation)*(-normal*dist - position);
  1032. normal = newnormal;
  1033. dist = -dot(newnormal, origin);
  1034. }
  1035. //--------- utility functions -------------
  1036. // RotationArc()
  1037. // Given two vectors v0 and v1 this function
  1038. // returns quaternion q where q*v0==v1.
  1039. // Routine taken from game programming gems.
  1040. Quaternion RotationArc(float3 v0,float3 v1){
  1041. static Quaternion q;
  1042. v0 = normalize(v0); // Comment these two lines out if you know its not needed.
  1043. v1 = normalize(v1); // If vector is already unit length then why do it again?
  1044. float3 c = cross(v0,v1);
  1045. NxF32 d = dot(v0,v1);
  1046. if(d<=-1.0f) { return Quaternion(1,0,0,0);} // 180 about x axis
  1047. NxF32 s = sqrtf((1+d)*2);
  1048. q.x = c.x / s;
  1049. q.y = c.y / s;
  1050. q.z = c.z / s;
  1051. q.w = s /2.0f;
  1052. return q;
  1053. }
  1054. float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v)
  1055. {
  1056. // builds a 4x4 transformation matrix based on orientation q and translation v
  1057. NxF32 qx2 = q.x*q.x;
  1058. NxF32 qy2 = q.y*q.y;
  1059. NxF32 qz2 = q.z*q.z;
  1060. NxF32 qxqy = q.x*q.y;
  1061. NxF32 qxqz = q.x*q.z;
  1062. NxF32 qxqw = q.x*q.w;
  1063. NxF32 qyqz = q.y*q.z;
  1064. NxF32 qyqw = q.y*q.w;
  1065. NxF32 qzqw = q.z*q.w;
  1066. return float4x4(
  1067. 1-2*(qy2+qz2),
  1068. 2*(qxqy+qzqw),
  1069. 2*(qxqz-qyqw),
  1070. 0 ,
  1071. 2*(qxqy-qzqw),
  1072. 1-2*(qx2+qz2),
  1073. 2*(qyqz+qxqw),
  1074. 0 ,
  1075. 2*(qxqz+qyqw),
  1076. 2*(qyqz-qxqw),
  1077. 1-2*(qx2+qy2),
  1078. 0 ,
  1079. v.x ,
  1080. v.y ,
  1081. v.z ,
  1082. 1.0f );
  1083. }
  1084. float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1)
  1085. {
  1086. // returns the point where the line p0-p1 intersects the plane n&d
  1087. static float3 dif;
  1088. dif = p1-p0;
  1089. NxF32 dn= dot(plane.normal,dif);
  1090. NxF32 t = -(plane.dist+dot(plane.normal,p0) )/dn;
  1091. return p0 + (dif*t);
  1092. }
  1093. float3 PlaneProject(const Plane &plane, const float3 &point)
  1094. {
  1095. return point - plane.normal * (dot(point,plane.normal)+plane.dist);
  1096. }
  1097. float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a)
  1098. {
  1099. float3 w;
  1100. w = p1-p0;
  1101. NxF32 t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
  1102. return p0+ w*t;
  1103. }
  1104. NxF32 LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a)
  1105. {
  1106. float3 w;
  1107. w = p1-p0;
  1108. NxF32 t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
  1109. return t;
  1110. }
  1111. float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2)
  1112. {
  1113. // return the normal of the triangle
  1114. // inscribed by v0, v1, and v2
  1115. float3 cp=cross(v1-v0,v2-v1);
  1116. NxF32 m=magnitude(cp);
  1117. if(m==0) return float3(1,0,0);
  1118. return cp*(1.0f/m);
  1119. }
  1120. NxI32 BoxInside(const float3 &p, const float3 &bmin, const float3 &bmax)
  1121. {
  1122. return (p.x >= bmin.x && p.x <=bmax.x &&
  1123. p.y >= bmin.y && p.y <=bmax.y &&
  1124. p.z >= bmin.z && p.z <=bmax.z );
  1125. }
  1126. NxI32 BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax,float3 *impact)
  1127. {
  1128. if(BoxInside(v0,bmin,bmax))
  1129. {
  1130. *impact=v0;
  1131. return 1;
  1132. }
  1133. if(v0.x<=bmin.x && v1.x>=bmin.x)
  1134. {
  1135. NxF32 a = (bmin.x-v0.x)/(v1.x-v0.x);
  1136. //v.x = bmin.x;
  1137. NxF32 vy = (1-a) *v0.y + a*v1.y;
  1138. NxF32 vz = (1-a) *v0.z + a*v1.z;
  1139. if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
  1140. {
  1141. impact->x = bmin.x;
  1142. impact->y = vy;
  1143. impact->z = vz;
  1144. return 1;
  1145. }
  1146. }
  1147. else if(v0.x >= bmax.x && v1.x <= bmax.x)
  1148. {
  1149. NxF32 a = (bmax.x-v0.x)/(v1.x-v0.x);
  1150. //v.x = bmax.x;
  1151. NxF32 vy = (1-a) *v0.y + a*v1.y;
  1152. NxF32 vz = (1-a) *v0.z + a*v1.z;
  1153. if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
  1154. {
  1155. impact->x = bmax.x;
  1156. impact->y = vy;
  1157. impact->z = vz;
  1158. return 1;
  1159. }
  1160. }
  1161. if(v0.y<=bmin.y && v1.y>=bmin.y)
  1162. {
  1163. NxF32 a = (bmin.y-v0.y)/(v1.y-v0.y);
  1164. NxF32 vx = (1-a) *v0.x + a*v1.x;
  1165. //v.y = bmin.y;
  1166. NxF32 vz = (1-a) *v0.z + a*v1.z;
  1167. if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
  1168. {
  1169. impact->x = vx;
  1170. impact->y = bmin.y;
  1171. impact->z = vz;
  1172. return 1;
  1173. }
  1174. }
  1175. else if(v0.y >= bmax.y && v1.y <= bmax.y)
  1176. {
  1177. NxF32 a = (bmax.y-v0.y)/(v1.y-v0.y);
  1178. NxF32 vx = (1-a) *v0.x + a*v1.x;
  1179. // vy = bmax.y;
  1180. NxF32 vz = (1-a) *v0.z + a*v1.z;
  1181. if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
  1182. {
  1183. impact->x = vx;
  1184. impact->y = bmax.y;
  1185. impact->z = vz;
  1186. return 1;
  1187. }
  1188. }
  1189. if(v0.z<=bmin.z && v1.z>=bmin.z)
  1190. {
  1191. NxF32 a = (bmin.z-v0.z)/(v1.z-v0.z);
  1192. NxF32 vx = (1-a) *v0.x + a*v1.x;
  1193. NxF32 vy = (1-a) *v0.y + a*v1.y;
  1194. // v.z = bmin.z;
  1195. if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
  1196. {
  1197. impact->x = vx;
  1198. impact->y = vy;
  1199. impact->z = bmin.z;
  1200. return 1;
  1201. }
  1202. }
  1203. else if(v0.z >= bmax.z && v1.z <= bmax.z)
  1204. {
  1205. NxF32 a = (bmax.z-v0.z)/(v1.z-v0.z);
  1206. NxF32 vx = (1-a) *v0.x + a*v1.x;
  1207. NxF32 vy = (1-a) *v0.y + a*v1.y;
  1208. // v.z = bmax.z;
  1209. if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
  1210. {
  1211. impact->x = vx;
  1212. impact->y = vy;
  1213. impact->z = bmax.z;
  1214. return 1;
  1215. }
  1216. }
  1217. return 0;
  1218. }
  1219. NxF32 DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint, float3 *vpoint)
  1220. {
  1221. static float3 cp;
  1222. cp = normalize(cross(udir,vdir));
  1223. NxF32 distu = -dot(cp,ustart);
  1224. NxF32 distv = -dot(cp,vstart);
  1225. NxF32 dist = (NxF32)fabs(distu-distv);
  1226. if(upoint)
  1227. {
  1228. Plane plane;
  1229. plane.normal = normalize(cross(vdir,cp));
  1230. plane.dist = -dot(plane.normal,vstart);
  1231. *upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
  1232. }
  1233. if(vpoint)
  1234. {
  1235. Plane plane;
  1236. plane.normal = normalize(cross(udir,cp));
  1237. plane.dist = -dot(plane.normal,ustart);
  1238. *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
  1239. }
  1240. return dist;
  1241. }
  1242. Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir1, const float3 &dir2)
  1243. {
  1244. // routine taken from game programming gems.
  1245. // Implement track ball functionality to spin stuf on the screen
  1246. // cop center of projection
  1247. // cor center of rotation
  1248. // dir1 old mouse direction
  1249. // dir2 new mouse direction
  1250. // pretend there is a sphere around cor. Then find the points
  1251. // where dir1 and dir2 intersect that sphere. Find the
  1252. // rotation that takes the first point to the second.
  1253. NxF32 m;
  1254. // compute plane
  1255. float3 nrml = cor - cop;
  1256. NxF32 fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop
  1257. nrml = normalize(nrml);
  1258. NxF32 dist = -dot(nrml,cor);
  1259. float3 u= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir1);
  1260. u=u-cor;
  1261. u=u*fudgefactor;
  1262. m= magnitude(u);
  1263. if(m>1)
  1264. {
  1265. u/=m;
  1266. }
  1267. else
  1268. {
  1269. u=u - (nrml * sqrtf(1-m*m));
  1270. }
  1271. float3 v= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir2);
  1272. v=v-cor;
  1273. v=v*fudgefactor;
  1274. m= magnitude(v);
  1275. if(m>1)
  1276. {
  1277. v/=m;
  1278. }
  1279. else
  1280. {
  1281. v=v - (nrml * sqrtf(1-m*m));
  1282. }
  1283. return RotationArc(u,v);
  1284. }
  1285. NxI32 countpolyhit=0;
  1286. NxI32 PolyHit(const float3 *vert, const NxI32 n, const float3 &v0, const float3 &v1, float3 *impact, float3 *normal)
  1287. {
  1288. countpolyhit++;
  1289. NxI32 i;
  1290. float3 nrml(0,0,0);
  1291. for(i=0;i<n;i++)
  1292. {
  1293. NxI32 i1=(i+1)%n;
  1294. NxI32 i2=(i+2)%n;
  1295. nrml = nrml + cross(vert[i1]-vert[i],vert[i2]-vert[i1]);
  1296. }
  1297. NxF32 m = magnitude(nrml);
  1298. if(m==0.0)
  1299. {
  1300. return 0;
  1301. }
  1302. nrml = nrml * (1.0f/m);
  1303. NxF32 dist = -dot(nrml,vert[0]);
  1304. NxF32 d0,d1;
  1305. if((d0=dot(v0,nrml)+dist) <0 || (d1=dot(v1,nrml)+dist) >0)
  1306. {
  1307. return 0;
  1308. }
  1309. static float3 the_point;
  1310. // By using the cached plane distances d0 and d1
  1311. // we can optimize the following:
  1312. // the_point = planelineintersection(nrml,dist,v0,v1);
  1313. NxF32 a = d0/(d0-d1);
  1314. the_point = v0*(1-a) + v1*a;
  1315. NxI32 inside=1;
  1316. for(NxI32 j=0;inside && j<n;j++)
  1317. {
  1318. // let inside = 0 if outside
  1319. float3 pp1,pp2,side;
  1320. pp1 = vert[j] ;
  1321. pp2 = vert[(j+1)%n];
  1322. side = cross((pp2-pp1),(the_point-pp1));
  1323. inside = (dot(nrml,side) >= 0.0);
  1324. }
  1325. if(inside)
  1326. {
  1327. if(normal){*normal=nrml;}
  1328. if(impact){*impact=the_point;}
  1329. }
  1330. return inside;
  1331. }
  1332. //****************************************************
  1333. // HULL.H source code goes here
  1334. //****************************************************
  1335. class PHullResult
  1336. {
  1337. public:
  1338. PHullResult(void)
  1339. {
  1340. mVcount = 0;
  1341. mIndexCount = 0;
  1342. mFaceCount = 0;
  1343. mVertices = 0;
  1344. mIndices = 0;
  1345. }
  1346. NxU32 mVcount;
  1347. NxU32 mIndexCount;
  1348. NxU32 mFaceCount;
  1349. NxF32 *mVertices;
  1350. NxU32 *mIndices;
  1351. };
  1352. bool ComputeHull(NxU32 vcount,const NxF32 *vertices,PHullResult &result,NxU32 maxverts,NxF32 inflate);
  1353. void ReleaseHull(PHullResult &result);
  1354. //*****************************************************
  1355. // HULL.cpp source code goes here
  1356. //*****************************************************
  1357. #define REAL3 float3
  1358. #define REAL NxF32
  1359. #define COPLANAR (0)
  1360. #define UNDER (1)
  1361. #define OVER (2)
  1362. #define SPLIT (OVER|UNDER)
  1363. #define PAPERWIDTH (0.001f)
  1364. #define VOLUME_EPSILON (1e-20f)
  1365. NxF32 planetestepsilon = PAPERWIDTH;
  1366. class ConvexH : public Memalloc
  1367. {
  1368. public:
  1369. class HalfEdge
  1370. {
  1371. public:
  1372. short ea; // the other half of the edge (index into edges list)
  1373. NxU8 v; // the vertex at the start of this edge (index into vertices list)
  1374. NxU8 p; // the facet on which this edge lies (index into facets list)
  1375. HalfEdge(){}
  1376. HalfEdge(short _ea,NxU8 _v, NxU8 _p):ea(_ea),v(_v),p(_p){}
  1377. };
  1378. Array<REAL3> vertices;
  1379. Array<HalfEdge> edges;
  1380. Array<Plane> facets;
  1381. ConvexH(NxI32 vertices_size,NxI32 edges_size,NxI32 facets_size);
  1382. };
  1383. typedef ConvexH::HalfEdge HalfEdge;
  1384. ConvexH::ConvexH(NxI32 vertices_size,NxI32 edges_size,NxI32 facets_size)
  1385. :vertices(vertices_size)
  1386. ,edges(edges_size)
  1387. ,facets(facets_size)
  1388. {
  1389. vertices.count=vertices_size;
  1390. edges.count = edges_size;
  1391. facets.count = facets_size;
  1392. }
  1393. ConvexH *ConvexHDup(ConvexH *src)
  1394. {
  1395. ConvexH *dst = MEMALLOC_NEW(ConvexH)(src->vertices.count,src->edges.count,src->facets.count);
  1396. memcpy(dst->vertices.element,src->vertices.element,sizeof(float3)*src->vertices.count);
  1397. memcpy(dst->edges.element,src->edges.element,sizeof(HalfEdge)*src->edges.count);
  1398. memcpy(dst->facets.element,src->facets.element,sizeof(Plane)*src->facets.count);
  1399. return dst;
  1400. }
  1401. NxI32 PlaneTest(const Plane &p, const REAL3 &v) {
  1402. REAL a = dot(v,p.normal)+p.dist;
  1403. NxI32 flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
  1404. return flag;
  1405. }
  1406. NxI32 SplitTest(ConvexH &convex,const Plane &plane) {
  1407. NxI32 flag=0;
  1408. for(NxI32 i=0;i<convex.vertices.count;i++) {
  1409. flag |= PlaneTest(plane,convex.vertices[i]);
  1410. }
  1411. return flag;
  1412. }
  1413. class VertFlag
  1414. {
  1415. public:
  1416. NxU8 planetest;
  1417. NxU8 junk;
  1418. NxU8 undermap;
  1419. NxU8 overmap;
  1420. };
  1421. class EdgeFlag
  1422. {
  1423. public:
  1424. NxU8 planetest;
  1425. NxU8 fixes;
  1426. short undermap;
  1427. short overmap;
  1428. };
  1429. class PlaneFlag
  1430. {
  1431. public:
  1432. NxU8 undermap;
  1433. NxU8 overmap;
  1434. };
  1435. class Coplanar{
  1436. public:
  1437. unsigned short ea;
  1438. NxU8 v0;
  1439. NxU8 v1;
  1440. };
  1441. NxI32 AssertIntact(ConvexH &convex) {
  1442. NxI32 i;
  1443. NxI32 estart=0;
  1444. for(i=0;i<convex.edges.count;i++) {
  1445. if(convex.edges[estart].p!= convex.edges[i].p) {
  1446. estart=i;
  1447. }
  1448. NxI32 inext = i+1;
  1449. if(inext>= convex.edges.count || convex.edges[inext].p != convex.edges[i].p) {
  1450. inext = estart;
  1451. }
  1452. assert(convex.edges[inext].p == convex.edges[i].p);
  1453. NxI32 nb = convex.edges[i].ea;
  1454. assert(nb!=255);
  1455. if(nb==255 || nb==-1) return 0;
  1456. assert(nb!=-1);
  1457. assert(i== convex.edges[nb].ea);
  1458. }
  1459. for(i=0;i<convex.edges.count;i++) {
  1460. assert(COPLANAR==PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v]));
  1461. if(COPLANAR!=PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v])) return 0;
  1462. if(convex.edges[estart].p!= convex.edges[i].p) {
  1463. estart=i;
  1464. }
  1465. NxI32 i1 = i+1;
  1466. if(i1>= convex.edges.count || convex.edges[i1].p != convex.edges[i].p) {
  1467. i1 = estart;
  1468. }
  1469. NxI32 i2 = i1+1;
  1470. if(i2>= convex.edges.count || convex.edges[i2].p != convex.edges[i].p) {
  1471. i2 = estart;
  1472. }
  1473. if(i==i2) continue; // i sliced tangent to an edge and created 2 meaningless edges
  1474. REAL3 localnormal = TriNormal(convex.vertices[convex.edges[i ].v],
  1475. convex.vertices[convex.edges[i1].v],
  1476. convex.vertices[convex.edges[i2].v]);
  1477. //assert(dot(localnormal,convex.facets[convex.edges[i].p].normal)>0);//Commented out on Stan Melax' advice
  1478. if(dot(localnormal,convex.facets[convex.edges[i].p].normal)<=0)return 0;
  1479. }
  1480. return 1;
  1481. }
  1482. ConvexH *ConvexHCrop(ConvexH &convex,const Plane &slice)
  1483. {
  1484. NxI32 i;
  1485. NxI32 vertcountunder=0;
  1486. NxI32 vertcountover =0;
  1487. static Array<NxI32> vertscoplanar; // existing vertex members of convex that are coplanar
  1488. vertscoplanar.count=0;
  1489. static Array<NxI32> edgesplit; // existing edges that members of convex that cross the splitplane
  1490. edgesplit.count=0;
  1491. assert(convex.edges.count<480);
  1492. EdgeFlag edgeflag[512];
  1493. VertFlag vertflag[256];
  1494. PlaneFlag planeflag[128];
  1495. HalfEdge tmpunderedges[512];
  1496. Plane tmpunderplanes[128];
  1497. Coplanar coplanaredges[512];
  1498. NxI32 coplanaredges_num=0;
  1499. Array<REAL3> createdverts;
  1500. // do the side-of-plane tests
  1501. for(i=0;i<convex.vertices.count;i++) {
  1502. vertflag[i].planetest = (NxU8)PlaneTest(slice,convex.vertices[i]);
  1503. if(vertflag[i].planetest == COPLANAR) {
  1504. // ? vertscoplanar.Add(i);
  1505. vertflag[i].undermap = (NxU8)vertcountunder++;
  1506. vertflag[i].overmap = (NxU8)vertcountover++;
  1507. }
  1508. else if(vertflag[i].planetest == UNDER) {
  1509. vertflag[i].undermap = (NxU8)vertcountunder++;
  1510. }
  1511. else {
  1512. assert(vertflag[i].planetest == OVER);
  1513. vertflag[i].overmap = (NxU8)vertcountover++;
  1514. vertflag[i].undermap = (NxU8)-1; // for debugging purposes
  1515. }
  1516. }
  1517. NxI32 under_edge_count =0;
  1518. NxI32 underplanescount=0;
  1519. NxI32 e0=0;
  1520. for(NxI32 currentplane=0; currentplane<convex.facets.count; currentplane++) {
  1521. NxI32 estart =e0;
  1522. NxI32 enextface=0;
  1523. NxI32 planeside = 0;
  1524. NxI32 e1 = e0+1;
  1525. NxI32 vout=-1;
  1526. NxI32 vin =-1;
  1527. NxI32 coplanaredge = -1;
  1528. do{
  1529. if(e1 >= convex.edges.count || convex.edges[e1].p!=currentplane) {
  1530. enextface = e1;
  1531. e1=estart;
  1532. }
  1533. HalfEdge &edge0 = convex.edges[e0];
  1534. HalfEdge &edge1 = convex.edges[e1];
  1535. HalfEdge &edgea = convex.edges[edge0.ea];
  1536. planeside |= vertflag[edge0.v].planetest;
  1537. //if((vertflag[edge0.v].planetest & vertflag[edge1.v].planetest) == COPLANAR) {
  1538. // assert(ecop==-1);
  1539. // ecop=e;
  1540. //}
  1541. if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == OVER){
  1542. // both endpoints over plane
  1543. edgeflag[e0].undermap = -1;
  1544. }
  1545. else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == UNDER) {
  1546. // at least one endpoint under, the other coplanar or under
  1547. edgeflag[e0].undermap = (short)under_edge_count;
  1548. tmpunderedges[under_edge_count].v = (NxU8)vertflag[edge0.v].undermap;
  1549. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1550. if(edge0.ea < e0) {
  1551. // connect the neighbors
  1552. assert(edgeflag[edge0.ea].undermap !=-1);
  1553. tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
  1554. tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count;
  1555. }
  1556. under_edge_count++;
  1557. }
  1558. else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == COPLANAR) {
  1559. // both endpoints coplanar
  1560. // must check a 3rd point to see if UNDER
  1561. NxI32 e2 = e1+1;
  1562. if(e2>=convex.edges.count || convex.edges[e2].p!=currentplane) {
  1563. e2 = estart;
  1564. }
  1565. assert(convex.edges[e2].p==currentplane);
  1566. HalfEdge &edge2 = convex.edges[e2];
  1567. if(vertflag[edge2.v].planetest==UNDER) {
  1568. edgeflag[e0].undermap = (short)under_edge_count;
  1569. tmpunderedges[under_edge_count].v = (NxU8)vertflag[edge0.v].undermap;
  1570. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1571. tmpunderedges[under_edge_count].ea = -1;
  1572. // make sure this edge is added to the "coplanar" list
  1573. coplanaredge = under_edge_count;
  1574. vout = vertflag[edge0.v].undermap;
  1575. vin = vertflag[edge1.v].undermap;
  1576. under_edge_count++;
  1577. }
  1578. else {
  1579. edgeflag[e0].undermap = -1;
  1580. }
  1581. }
  1582. else if(vertflag[edge0.v].planetest == UNDER && vertflag[edge1.v].planetest == OVER) {
  1583. // first is under 2nd is over
  1584. edgeflag[e0].undermap = (short) under_edge_count;
  1585. tmpunderedges[under_edge_count].v = (NxU8)vertflag[edge0.v].undermap;
  1586. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1587. if(edge0.ea < e0) {
  1588. assert(edgeflag[edge0.ea].undermap !=-1);
  1589. // connect the neighbors
  1590. tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
  1591. tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count;
  1592. vout = tmpunderedges[edgeflag[edge0.ea].undermap].v;
  1593. }
  1594. else {
  1595. Plane &p0 = convex.facets[edge0.p];
  1596. Plane &pa = convex.facets[edgea.p];
  1597. createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
  1598. //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
  1599. //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
  1600. vout = vertcountunder++;
  1601. }
  1602. under_edge_count++;
  1603. /// hmmm something to think about: i might be able to output this edge regarless of
  1604. // wheter or not we know v-in yet. ok i;ll try this now:
  1605. tmpunderedges[under_edge_count].v = (NxU8)vout;
  1606. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1607. tmpunderedges[under_edge_count].ea = -1;
  1608. coplanaredge = under_edge_count;
  1609. under_edge_count++;
  1610. if(vin!=-1) {
  1611. // we previously processed an edge where we came under
  1612. // now we know about vout as well
  1613. // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
  1614. }
  1615. }
  1616. else if(vertflag[edge0.v].planetest == COPLANAR && vertflag[edge1.v].planetest == OVER) {
  1617. // first is coplanar 2nd is over
  1618. edgeflag[e0].undermap = -1;
  1619. vout = vertflag[edge0.v].undermap;
  1620. // I hate this but i have to make sure part of this face is UNDER before ouputting this vert
  1621. NxI32 k=estart;
  1622. assert(edge0.p == currentplane);
  1623. while(!(planeside&UNDER) && k<convex.edges.count && convex.edges[k].p==edge0.p) {
  1624. planeside |= vertflag[convex.edges[k].v].planetest;
  1625. k++;
  1626. }
  1627. if(planeside&UNDER){
  1628. tmpunderedges[under_edge_count].v = (NxU8)vout;
  1629. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1630. tmpunderedges[under_edge_count].ea = -1;
  1631. coplanaredge = under_edge_count; // hmmm should make a note of the edge # for later on
  1632. under_edge_count++;
  1633. }
  1634. }
  1635. else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == UNDER) {
  1636. // first is over next is under
  1637. // new vertex!!!
  1638. if (vin!=-1) return NULL;
  1639. if(e0<edge0.ea) {
  1640. Plane &p0 = convex.facets[edge0.p];
  1641. Plane &pa = convex.facets[edgea.p];
  1642. createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
  1643. //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
  1644. //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
  1645. vin = vertcountunder++;
  1646. }
  1647. else {
  1648. // find the new vertex that was created by edge[edge0.ea]
  1649. NxI32 nea = edgeflag[edge0.ea].undermap;
  1650. assert(tmpunderedges[nea].p==tmpunderedges[nea+1].p);
  1651. vin = tmpunderedges[nea+1].v;
  1652. assert(vin < vertcountunder);
  1653. }
  1654. if(vout!=-1) {
  1655. // we previously processed an edge where we went over
  1656. // now we know vin too
  1657. // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
  1658. }
  1659. // output edge
  1660. tmpunderedges[under_edge_count].v = (NxU8)vin;
  1661. tmpunderedges[under_edge_count].p = (NxU8)underplanescount;
  1662. edgeflag[e0].undermap = (short)under_edge_count;
  1663. if(e0>edge0.ea) {
  1664. assert(edgeflag[edge0.ea].undermap !=-1);
  1665. // connect the neighbors
  1666. tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
  1667. tmpunderedges[edgeflag[edge0.ea].undermap].ea = (short)under_edge_count;
  1668. }
  1669. assert(edgeflag[e0].undermap == under_edge_count);
  1670. under_edge_count++;
  1671. }
  1672. else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == COPLANAR) {
  1673. // first is over next is coplanar
  1674. edgeflag[e0].undermap = -1;
  1675. vin = vertflag[edge1.v].undermap;
  1676. if (vin==-1) return NULL;
  1677. if(vout!=-1) {
  1678. // we previously processed an edge where we came under
  1679. // now we know both endpoints
  1680. // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
  1681. }
  1682. }
  1683. else {
  1684. assert(0);
  1685. }
  1686. e0=e1;
  1687. e1++; // do the modulo at the beginning of the loop
  1688. } while(e0!=estart) ;
  1689. e0 = enextface;
  1690. if(planeside&UNDER) {
  1691. planeflag[currentplane].undermap = (NxU8)underplanescount;
  1692. tmpunderplanes[underplanescount] = convex.facets[currentplane];
  1693. underplanescount++;
  1694. }
  1695. else {
  1696. planeflag[currentplane].undermap = 0;
  1697. }
  1698. if(vout>=0 && (planeside&UNDER)) {
  1699. assert(vin>=0);
  1700. assert(coplanaredge>=0);
  1701. assert(coplanaredge!=511);
  1702. coplanaredges[coplanaredges_num].ea = (short)coplanaredge;
  1703. coplanaredges[coplanaredges_num].v0 = (NxU8)vin;
  1704. coplanaredges[coplanaredges_num].v1 = (NxU8)vout;
  1705. coplanaredges_num++;
  1706. }
  1707. }
  1708. // add the new plane to the mix:
  1709. if(coplanaredges_num>0) {
  1710. tmpunderplanes[underplanescount++]=slice;
  1711. }
  1712. for(i=0;i<coplanaredges_num-1;i++) {
  1713. if(coplanaredges[i].v1 != coplanaredges[i+1].v0) {
  1714. NxI32 j = 0;
  1715. for(j=i+2;j<coplanaredges_num;j++) {
  1716. if(coplanaredges[i].v1 == coplanaredges[j].v0) {
  1717. Coplanar tmp = coplanaredges[i+1];
  1718. coplanaredges[i+1] = coplanaredges[j];
  1719. coplanaredges[j] = tmp;
  1720. break;
  1721. }
  1722. }
  1723. if(j>=coplanaredges_num)
  1724. {
  1725. // assert(j<coplanaredges_num);
  1726. return NULL;
  1727. }
  1728. }
  1729. }
  1730. ConvexH *punder = MEMALLOC_NEW(ConvexH)(vertcountunder,under_edge_count+coplanaredges_num,underplanescount);
  1731. ConvexH &under = *punder;
  1732. NxI32 k=0;
  1733. for(i=0;i<convex.vertices.count;i++) {
  1734. if(vertflag[i].planetest != OVER){
  1735. under.vertices[k++] = convex.vertices[i];
  1736. }
  1737. }
  1738. i=0;
  1739. while(k<vertcountunder) {
  1740. under.vertices[k++] = createdverts[i++];
  1741. }
  1742. assert(i==createdverts.count);
  1743. for(i=0;i<coplanaredges_num;i++) {
  1744. under.edges[under_edge_count+i].p = (NxU8)(underplanescount-1);
  1745. under.edges[under_edge_count+i].ea = coplanaredges[i].ea;
  1746. tmpunderedges[coplanaredges[i].ea].ea = (short)(under_edge_count+i);
  1747. under.edges[under_edge_count+i].v = coplanaredges[i].v0;
  1748. }
  1749. memcpy(under.edges.element,tmpunderedges,sizeof(HalfEdge)*under_edge_count);
  1750. memcpy(under.facets.element,tmpunderplanes,sizeof(Plane)*underplanescount);
  1751. return punder;
  1752. }
  1753. NxF32 minadjangle = 3.0f; // in degrees - result wont have two adjacent facets within this angle of each other.
  1754. static NxI32 candidateplane(Plane *planes,NxI32 planes_count,ConvexH *convex,NxF32 epsilon)
  1755. {
  1756. NxI32 p =-1;
  1757. REAL md=0;
  1758. NxI32 i,j;
  1759. NxF32 maxdot_minang = cosf(DEG2RAD*minadjangle);
  1760. for(i=0;i<planes_count;i++)
  1761. {
  1762. NxF32 d=0;
  1763. NxF32 dmax=0;
  1764. NxF32 dmin=0;
  1765. for(j=0;j<convex->vertices.count;j++)
  1766. {
  1767. dmax = Max(dmax,dot(convex->vertices[j],planes[i].normal)+planes[i].dist);
  1768. dmin = Min(dmin,dot(convex->vertices[j],planes[i].normal)+planes[i].dist);
  1769. }
  1770. NxF32 dr = dmax-dmin;
  1771. if(dr<planetestepsilon) dr=1.0f; // shouldn't happen.
  1772. d = dmax /dr;
  1773. if(d<=md) continue;
  1774. for(j=0;j<convex->facets.count;j++)
  1775. {
  1776. if(planes[i]==convex->facets[j])
  1777. {
  1778. d=0;continue;
  1779. }
  1780. if(dot(planes[i].normal,convex->facets[j].normal)>maxdot_minang)
  1781. {
  1782. for(NxI32 k=0;k<convex->edges.count;k++)
  1783. {
  1784. if(convex->edges[k].p!=j) continue;
  1785. if(dot(convex->vertices[convex->edges[k].v],planes[i].normal)+planes[i].dist<0)
  1786. {
  1787. d=0; // so this plane wont get selected.
  1788. break;
  1789. }
  1790. }
  1791. }
  1792. }
  1793. if(d>md)
  1794. {
  1795. p=i;
  1796. md=d;
  1797. }
  1798. }
  1799. return (md>epsilon)?p:-1;
  1800. }
  1801. template<class T>
  1802. inline NxI32 maxdir(const T *p,NxI32 count,const T &dir)
  1803. {
  1804. assert(count);
  1805. NxI32 m=0;
  1806. for(NxI32 i=1;i<count;i++)
  1807. {
  1808. if(dot(p[i],dir)>dot(p[m],dir)) m=i;
  1809. }
  1810. return m;
  1811. }
  1812. template<class T>
  1813. NxI32 maxdirfiltered(const T *p,NxI32 count,const T &dir,Array<NxI32> &allow)
  1814. {
  1815. assert(count);
  1816. NxI32 m=-1;
  1817. for(NxI32 i=0;i<count;i++) if(allow[i])
  1818. {
  1819. if(m==-1 || dot(p[i],dir)>dot(p[m],dir)) m=i;
  1820. }
  1821. assert(m!=-1);
  1822. return m;
  1823. }
  1824. float3 orth(const float3 &v)
  1825. {
  1826. float3 a=cross(v,float3(0,0,1));
  1827. float3 b=cross(v,float3(0,1,0));
  1828. return normalize((magnitude(a)>magnitude(b))?a:b);
  1829. }
  1830. template<class T>
  1831. NxI32 maxdirsterid(const T *p,NxI32 count,const T &dir,Array<NxI32> &allow)
  1832. {
  1833. NxI32 m=-1;
  1834. while(m==-1)
  1835. {
  1836. m = maxdirfiltered(p,count,dir,allow);
  1837. if(allow[m]==3) return m;
  1838. T u = orth(dir);
  1839. T v = cross(u,dir);
  1840. NxI32 ma=-1;
  1841. for(NxF32 x = 0.0f ; x<= 360.0f ; x+= 45.0f)
  1842. {
  1843. NxF32 s = sinf(DEG2RAD*(x));
  1844. NxF32 c = cosf(DEG2RAD*(x));
  1845. NxI32 mb = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
  1846. if(ma==m && mb==m)
  1847. {
  1848. allow[m]=3;
  1849. return m;
  1850. }
  1851. if(ma!=-1 && ma!=mb) // Yuck - this is really ugly
  1852. {
  1853. NxI32 mc = ma;
  1854. for(NxF32 xx = x-40.0f ; xx <= x ; xx+= 5.0f)
  1855. {
  1856. NxF32 s = sinf(DEG2RAD*(xx));
  1857. NxF32 c = cosf(DEG2RAD*(xx));
  1858. NxI32 md = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
  1859. if(mc==m && md==m)
  1860. {
  1861. allow[m]=3;
  1862. return m;
  1863. }
  1864. mc=md;
  1865. }
  1866. }
  1867. ma=mb;
  1868. }
  1869. allow[m]=0;
  1870. m=-1;
  1871. }
  1872. assert(0);
  1873. return m;
  1874. }
  1875. NxI32 operator ==(const int3 &a,const int3 &b)
  1876. {
  1877. for(NxI32 i=0;i<3;i++)
  1878. {
  1879. if(a[i]!=b[i]) return 0;
  1880. }
  1881. return 1;
  1882. }
  1883. int3 roll3(int3 a)
  1884. {
  1885. NxI32 tmp=a[0];
  1886. a[0]=a[1];
  1887. a[1]=a[2];
  1888. a[2]=tmp;
  1889. return a;
  1890. }
  1891. NxI32 isa(const int3 &a,const int3 &b)
  1892. {
  1893. return ( a==b || roll3(a)==b || a==roll3(b) );
  1894. }
  1895. NxI32 b2b(const int3 &a,const int3 &b)
  1896. {
  1897. return isa(a,int3(b[2],b[1],b[0]));
  1898. }
  1899. NxI32 above(float3* vertices,const int3& t, const float3 &p, NxF32 epsilon)
  1900. {
  1901. float3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
  1902. return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
  1903. }
  1904. NxI32 hasedge(const int3 &t, NxI32 a,NxI32 b)
  1905. {
  1906. for(NxI32 i=0;i<3;i++)
  1907. {
  1908. NxI32 i1= (i+1)%3;
  1909. if(t[i]==a && t[i1]==b) return 1;
  1910. }
  1911. return 0;
  1912. }
  1913. NxI32 hasvert(const int3 &t, NxI32 v)
  1914. {
  1915. return (t[0]==v || t[1]==v || t[2]==v) ;
  1916. }
  1917. NxI32 shareedge(const int3 &a,const int3 &b)
  1918. {
  1919. NxI32 i;
  1920. for(i=0;i<3;i++)
  1921. {
  1922. NxI32 i1= (i+1)%3;
  1923. if(hasedge(a,b[i1],b[i])) return 1;
  1924. }
  1925. return 0;
  1926. }
  1927. class Tri;
  1928. static Array<Tri*> tris; // djs: For heaven's sake!!!!
  1929. class Tri : public int3
  1930. {
  1931. public:
  1932. int3 n;
  1933. NxI32 id;
  1934. NxI32 vmax;
  1935. NxF32 rise;
  1936. Tri(NxI32 a,NxI32 b,NxI32 c):int3(a,b,c),n(-1,-1,-1)
  1937. {
  1938. id = tris.count;
  1939. tris.Add(this);
  1940. vmax=-1;
  1941. rise = 0.0f;
  1942. }
  1943. ~Tri()
  1944. {
  1945. assert(tris[id]==this);
  1946. tris[id]=NULL;
  1947. }
  1948. NxI32 &neib(NxI32 a,NxI32 b);
  1949. };
  1950. NxI32 &Tri::neib(NxI32 a,NxI32 b)
  1951. {
  1952. static NxI32 er=-1;
  1953. NxI32 i;
  1954. for(i=0;i<3;i++)
  1955. {
  1956. NxI32 i1=(i+1)%3;
  1957. NxI32 i2=(i+2)%3;
  1958. if((*this)[i]==a && (*this)[i1]==b) return n[i2];
  1959. if((*this)[i]==b && (*this)[i1]==a) return n[i2];
  1960. }
  1961. assert(0);
  1962. return er;
  1963. }
  1964. void b2bfix(Tri* s,Tri*t)
  1965. {
  1966. NxI32 i;
  1967. for(i=0;i<3;i++)
  1968. {
  1969. NxI32 i1=(i+1)%3;
  1970. NxI32 i2=(i+2)%3;
  1971. NxI32 a = (*s)[i1];
  1972. NxI32 b = (*s)[i2];
  1973. assert(tris[s->neib(a,b)]->neib(b,a) == s->id);
  1974. assert(tris[t->neib(a,b)]->neib(b,a) == t->id);
  1975. tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
  1976. tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
  1977. }
  1978. }
  1979. void removeb2b(Tri* s,Tri*t)
  1980. {
  1981. b2bfix(s,t);
  1982. delete s;
  1983. delete t;
  1984. }
  1985. void extrude(Tri *t0,NxI32 v)
  1986. {
  1987. int3 t= *t0;
  1988. NxI32 n = tris.count;
  1989. Tri* ta = MEMALLOC_NEW(Tri)(v,t[1],t[2]);
  1990. ta->n = int3(t0->n[0],n+1,n+2);
  1991. tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
  1992. Tri* tb = MEMALLOC_NEW(Tri)(v,t[2],t[0]);
  1993. tb->n = int3(t0->n[1],n+2,n+0);
  1994. tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
  1995. Tri* tc = MEMALLOC_NEW(Tri)(v,t[0],t[1]);
  1996. tc->n = int3(t0->n[2],n+0,n+1);
  1997. tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
  1998. if(hasvert(*tris[ta->n[0]],v)) removeb2b(ta,tris[ta->n[0]]);
  1999. if(hasvert(*tris[tb->n[0]],v)) removeb2b(tb,tris[tb->n[0]]);
  2000. if(hasvert(*tris[tc->n[0]],v)) removeb2b(tc,tris[tc->n[0]]);
  2001. delete t0;
  2002. }
  2003. Tri *extrudable(NxF32 epsilon)
  2004. {
  2005. NxI32 i;
  2006. Tri *t=NULL;
  2007. for(i=0;i<tris.count;i++)
  2008. {
  2009. if(!t || (tris[i] && t->rise<tris[i]->rise))
  2010. {
  2011. t = tris[i];
  2012. }
  2013. }
  2014. return (t->rise >epsilon)?t:NULL ;
  2015. }
  2016. class int4
  2017. {
  2018. public:
  2019. NxI32 x,y,z,w;
  2020. int4(){};
  2021. int4(NxI32 _x,NxI32 _y, NxI32 _z,NxI32 _w){x=_x;y=_y;z=_z;w=_w;}
  2022. const NxI32& operator[](NxI32 i) const {return (&x)[i];}
  2023. NxI32& operator[](NxI32 i) {return (&x)[i];}
  2024. };
  2025. bool hasVolume(float3 *verts, NxI32 p0, NxI32 p1, NxI32 p2, NxI32 p3)
  2026. {
  2027. float3 result3 = cross(verts[p1]-verts[p0], verts[p2]-verts[p0]);
  2028. if (magnitude(result3) < VOLUME_EPSILON && magnitude(result3) > -VOLUME_EPSILON) // Almost collinear or otherwise very close to each other
  2029. return false;
  2030. NxF32 result = dot(normalize(result3), verts[p3]-verts[p0]);
  2031. return (result > VOLUME_EPSILON || result < -VOLUME_EPSILON); // Returns true iff volume is significantly non-zero
  2032. }
  2033. int4 FindSimplex(float3 *verts,NxI32 verts_count,Array<NxI32> &allow)
  2034. {
  2035. float3 basis[3];
  2036. basis[0] = float3( 0.01f, 0.02f, 1.0f );
  2037. NxI32 p0 = maxdirsterid(verts,verts_count, basis[0],allow);
  2038. NxI32 p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
  2039. basis[0] = verts[p0]-verts[p1];
  2040. if(p0==p1 || basis[0]==float3(0,0,0))
  2041. return int4(-1,-1,-1,-1);
  2042. basis[1] = cross(float3( 1, 0.02f, 0),basis[0]);
  2043. basis[2] = cross(float3(-0.02f, 1, 0),basis[0]);
  2044. basis[1] = normalize( (magnitude(basis[1])>magnitude(basis[2])) ? basis[1]:basis[2]);
  2045. NxI32 p2 = maxdirsterid(verts,verts_count,basis[1],allow);
  2046. if(p2 == p0 || p2 == p1)
  2047. {
  2048. p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
  2049. }
  2050. if(p2 == p0 || p2 == p1)
  2051. return int4(-1,-1,-1,-1);
  2052. basis[1] = verts[p2] - verts[p0];
  2053. basis[2] = normalize(cross(basis[1],basis[0]));
  2054. NxI32 p3 = maxdirsterid(verts,verts_count,basis[2],allow);
  2055. if(p3==p0||p3==p1||p3==p2||!hasVolume(verts, p0, p1, p2, p3)) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
  2056. if(p3==p0||p3==p1||p3==p2)
  2057. return int4(-1,-1,-1,-1);
  2058. assert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
  2059. if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
  2060. return int4(p0,p1,p2,p3);
  2061. }
  2062. #pragma warning(push)
  2063. #pragma warning(disable:4706)
  2064. NxI32 calchullgen(float3 *verts,NxI32 verts_count, NxI32 vlimit)
  2065. {
  2066. if(verts_count <4) return 0;
  2067. if(vlimit==0) vlimit=1000000000;
  2068. NxI32 j;
  2069. float3 bmin(*verts),bmax(*verts);
  2070. Array<NxI32> isextreme(verts_count);
  2071. Array<NxI32> allow(verts_count);
  2072. for(j=0;j<verts_count;j++)
  2073. {
  2074. allow.Add(1);
  2075. isextreme.Add(0);
  2076. bmin = VectorMin(bmin,verts[j]);
  2077. bmax = VectorMax(bmax,verts[j]);
  2078. }
  2079. NxF32 epsilon = magnitude(bmax-bmin) * 0.001f;
  2080. int4 p = FindSimplex(verts,verts_count,allow);
  2081. if(p.x==-1) return 0; // simplex failed
  2082. float3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) /4.0f; // a valid interior point
  2083. Tri *t0 = MEMALLOC_NEW(Tri)(p[2],p[3],p[1]); t0->n=int3(2,3,1);
  2084. Tri *t1 = MEMALLOC_NEW(Tri)(p[3],p[2],p[0]); t1->n=int3(3,2,0);
  2085. Tri *t2 = MEMALLOC_NEW(Tri)(p[0],p[1],p[3]); t2->n=int3(0,1,3);
  2086. Tri *t3 = MEMALLOC_NEW(Tri)(p[1],p[0],p[2]); t3->n=int3(1,0,2);
  2087. isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
  2088. for(j=0;j<tris.count;j++)
  2089. {
  2090. Tri *t=tris[j];
  2091. assert(t);
  2092. assert(t->vmax<0);
  2093. float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
  2094. t->vmax = maxdirsterid(verts,verts_count,n,allow);
  2095. t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
  2096. }
  2097. Tri *te;
  2098. vlimit-=4;
  2099. while(vlimit >0 && (te=extrudable(epsilon)))
  2100. {
  2101. int3 ti=*te;
  2102. NxI32 v=te->vmax;
  2103. assert(!isextreme[v]); // wtf we've already done this vertex
  2104. isextreme[v]=1;
  2105. //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
  2106. j=tris.count;
  2107. while(j--) {
  2108. if(!tris[j]) continue;
  2109. int3 t=*tris[j];
  2110. if(above(verts,t,verts[v],0.01f*epsilon))
  2111. {
  2112. extrude(tris[j],v);
  2113. }
  2114. }
  2115. // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
  2116. j=tris.count;
  2117. while(j--)
  2118. {
  2119. if(!tris[j]) continue;
  2120. if(!hasvert(*tris[j],v)) break;
  2121. int3 nt=*tris[j];
  2122. if(above(verts,nt,center,0.01f*epsilon) || magnitude(cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]))< epsilon*epsilon*0.1f )
  2123. {
  2124. Tri *nb = tris[tris[j]->n[0]];
  2125. assert(nb);assert(!hasvert(*nb,v));assert(nb->id<j);
  2126. extrude(nb,v);
  2127. j=tris.count;
  2128. }
  2129. }
  2130. j=tris.count;
  2131. while(j--)
  2132. {
  2133. Tri *t=tris[j];
  2134. if(!t) continue;
  2135. if(t->vmax>=0) break;
  2136. float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
  2137. t->vmax = maxdirsterid(verts,verts_count,n,allow);
  2138. if(isextreme[t->vmax])
  2139. {
  2140. t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
  2141. }
  2142. else
  2143. {
  2144. t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
  2145. }
  2146. }
  2147. vlimit --;
  2148. }
  2149. return 1;
  2150. }
  2151. #pragma warning(pop)
  2152. NxI32 calchull(float3 *verts,NxI32 verts_count, NxI32 *&tris_out, NxI32 &tris_count,NxI32 vlimit)
  2153. {
  2154. NxI32 rc=calchullgen(verts,verts_count, vlimit) ;
  2155. if(!rc) return 0;
  2156. Array<NxI32> ts;
  2157. for(NxI32 i=0;i<tris.count;i++)if(tris[i])
  2158. {
  2159. for(NxI32 j=0;j<3;j++)ts.Add((*tris[i])[j]);
  2160. delete tris[i];
  2161. }
  2162. tris_count = ts.count/3;
  2163. tris_out = ts.element;
  2164. ts.element=NULL; ts.count=ts.array_size=0;
  2165. // please reset here, otherwise, we get a nice virtual function call (R6025) error with NxCooking library
  2166. tris.SetSize( 0 );
  2167. return 1;
  2168. }
  2169. static NxF32 area2(const float3 &v0,const float3 &v1,const float3 &v2)
  2170. {
  2171. float3 cp = cross(v0-v1,v2-v0);
  2172. return dot(cp,cp);
  2173. }
  2174. NxI32 calchullpbev(float3 *verts,NxI32 verts_count,NxI32 vlimit, Array<Plane> &planes,NxF32 bevangle)
  2175. {
  2176. NxI32 i,j;
  2177. Array<Plane> bplanes;
  2178. planes.count=0;
  2179. NxI32 rc = calchullgen(verts,verts_count,vlimit);
  2180. if(!rc) return 0;
  2181. extern NxF32 minadjangle; // default is 3.0f; // in degrees - result wont have two adjacent facets within this angle of each other.
  2182. NxF32 maxdot_minang = cosf(DEG2RAD*minadjangle);
  2183. for(i=0;i<tris.count;i++)if(tris[i])
  2184. {
  2185. Plane p;
  2186. Tri *t = tris[i];
  2187. p.normal = TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
  2188. p.dist = -dot(p.normal, verts[(*t)[0]]);
  2189. for(j=0;j<3;j++)
  2190. {
  2191. if(t->n[j]<t->id) continue;
  2192. Tri *s = tris[t->n[j]];
  2193. REAL3 snormal = TriNormal(verts[(*s)[0]],verts[(*s)[1]],verts[(*s)[2]]);
  2194. if(dot(snormal,p.normal)>=cos(bevangle*DEG2RAD)) continue;
  2195. REAL3 e = verts[(*t)[(j+2)%3]] - verts[(*t)[(j+1)%3]];
  2196. REAL3 n = (e!=REAL3(0,0,0))? cross(snormal,e)+cross(e,p.normal) : snormal+p.normal;
  2197. assert(n!=REAL3(0,0,0));
  2198. if(n==REAL3(0,0,0)) return 0;
  2199. n=normalize(n);
  2200. bplanes.Add(Plane(n,-dot(n,verts[maxdir(verts,verts_count,n)])));
  2201. }
  2202. }
  2203. for(i=0;i<tris.count;i++)if(tris[i])for(j=i+1;j<tris.count;j++)if(tris[i] && tris[j])
  2204. {
  2205. Tri *ti = tris[i];
  2206. Tri *tj = tris[j];
  2207. REAL3 ni = TriNormal(verts[(*ti)[0]],verts[(*ti)[1]],verts[(*ti)[2]]);
  2208. REAL3 nj = TriNormal(verts[(*tj)[0]],verts[(*tj)[1]],verts[(*tj)[2]]);
  2209. if(dot(ni,nj)>maxdot_minang)
  2210. {
  2211. // somebody has to die, keep the biggest triangle
  2212. if( area2(verts[(*ti)[0]],verts[(*ti)[1]],verts[(*ti)[2]]) < area2(verts[(*tj)[0]],verts[(*tj)[1]],verts[(*tj)[2]]))
  2213. {
  2214. delete tris[i];
  2215. }
  2216. else
  2217. {
  2218. delete tris[j];
  2219. }
  2220. }
  2221. }
  2222. for(i=0;i<tris.count;i++)if(tris[i])
  2223. {
  2224. Plane p;
  2225. Tri *t = tris[i];
  2226. p.normal = TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
  2227. p.dist = -dot(p.normal, verts[(*t)[0]]);
  2228. planes.Add(p);
  2229. }
  2230. for(i=0;i<bplanes.count;i++)
  2231. {
  2232. for(j=0;j<planes.count;j++)
  2233. {
  2234. if(dot(bplanes[i].normal,planes[j].normal)>maxdot_minang) break;
  2235. }
  2236. if(j==planes.count)
  2237. {
  2238. planes.Add(bplanes[i]);
  2239. }
  2240. }
  2241. for(i=0;i<tris.count;i++)if(tris[i])
  2242. {
  2243. delete tris[i];
  2244. }
  2245. tris.count = 0; //bad place to do the tris.SetSize(0) fix, this line is executed many times, and will result in a whole lot of allocations if the array is totally cleared here
  2246. return 1;
  2247. }
  2248. ConvexH *test_cube()
  2249. {
  2250. ConvexH *convex = MEMALLOC_NEW(ConvexH)(8,24,6);
  2251. convex->vertices[0] = REAL3(0,0,0);
  2252. convex->vertices[1] = REAL3(0,0,1);
  2253. convex->vertices[2] = REAL3(0,1,0);
  2254. convex->vertices[3] = REAL3(0,1,1);
  2255. convex->vertices[4] = REAL3(1,0,0);
  2256. convex->vertices[5] = REAL3(1,0,1);
  2257. convex->vertices[6] = REAL3(1,1,0);
  2258. convex->vertices[7] = REAL3(1,1,1);
  2259. convex->facets[0] = Plane(REAL3(-1,0,0),0);
  2260. convex->facets[1] = Plane(REAL3(1,0,0),-1);
  2261. convex->facets[2] = Plane(REAL3(0,-1,0),0);
  2262. convex->facets[3] = Plane(REAL3(0,1,0),-1);
  2263. convex->facets[4] = Plane(REAL3(0,0,-1),0);
  2264. convex->facets[5] = Plane(REAL3(0,0,1),-1);
  2265. convex->edges[0 ] = HalfEdge(11,0,0);
  2266. convex->edges[1 ] = HalfEdge(23,1,0);
  2267. convex->edges[2 ] = HalfEdge(15,3,0);
  2268. convex->edges[3 ] = HalfEdge(16,2,0);
  2269. convex->edges[4 ] = HalfEdge(13,6,1);
  2270. convex->edges[5 ] = HalfEdge(21,7,1);
  2271. convex->edges[6 ] = HalfEdge( 9,5,1);
  2272. convex->edges[7 ] = HalfEdge(18,4,1);
  2273. convex->edges[8 ] = HalfEdge(19,0,2);
  2274. convex->edges[9 ] = HalfEdge( 6,4,2);
  2275. convex->edges[10] = HalfEdge(20,5,2);
  2276. convex->edges[11] = HalfEdge( 0,1,2);
  2277. convex->edges[12] = HalfEdge(22,3,3);
  2278. convex->edges[13] = HalfEdge( 4,7,3);
  2279. convex->edges[14] = HalfEdge(17,6,3);
  2280. convex->edges[15] = HalfEdge( 2,2,3);
  2281. convex->edges[16] = HalfEdge( 3,0,4);
  2282. convex->edges[17] = HalfEdge(14,2,4);
  2283. convex->edges[18] = HalfEdge( 7,6,4);
  2284. convex->edges[19] = HalfEdge( 8,4,4);
  2285. convex->edges[20] = HalfEdge(10,1,5);
  2286. convex->edges[21] = HalfEdge( 5,5,5);
  2287. convex->edges[22] = HalfEdge(12,7,5);
  2288. convex->edges[23] = HalfEdge( 1,3,5);
  2289. return convex;
  2290. }
  2291. ConvexH *ConvexHMakeCube(const REAL3 &bmin, const REAL3 &bmax)
  2292. {
  2293. ConvexH *convex = test_cube();
  2294. convex->vertices[0] = REAL3(bmin.x,bmin.y,bmin.z);
  2295. convex->vertices[1] = REAL3(bmin.x,bmin.y,bmax.z);
  2296. convex->vertices[2] = REAL3(bmin.x,bmax.y,bmin.z);
  2297. convex->vertices[3] = REAL3(bmin.x,bmax.y,bmax.z);
  2298. convex->vertices[4] = REAL3(bmax.x,bmin.y,bmin.z);
  2299. convex->vertices[5] = REAL3(bmax.x,bmin.y,bmax.z);
  2300. convex->vertices[6] = REAL3(bmax.x,bmax.y,bmin.z);
  2301. convex->vertices[7] = REAL3(bmax.x,bmax.y,bmax.z);
  2302. convex->facets[0] = Plane(REAL3(-1,0,0), bmin.x);
  2303. convex->facets[1] = Plane(REAL3(1,0,0), -bmax.x);
  2304. convex->facets[2] = Plane(REAL3(0,-1,0), bmin.y);
  2305. convex->facets[3] = Plane(REAL3(0,1,0), -bmax.y);
  2306. convex->facets[4] = Plane(REAL3(0,0,-1), bmin.z);
  2307. convex->facets[5] = Plane(REAL3(0,0,1), -bmax.z);
  2308. return convex;
  2309. }
  2310. static NxI32 overhull(Plane *planes,NxI32 planes_count,float3 *verts, NxI32 verts_count,NxI32 maxplanes,
  2311. float3 *&verts_out, NxI32 &verts_count_out, NxI32 *&faces_out, NxI32 &faces_count_out ,NxF32 inflate)
  2312. {
  2313. NxI32 i,j;
  2314. if(verts_count <4) return NULL;
  2315. maxplanes = Min(maxplanes,planes_count);
  2316. float3 bmin(verts[0]),bmax(verts[0]);
  2317. for(i=0;i<verts_count;i++)
  2318. {
  2319. bmin = VectorMin(bmin,verts[i]);
  2320. bmax = VectorMax(bmax,verts[i]);
  2321. }
  2322. NxF32 diameter = magnitude(bmax-bmin);
  2323. // inflate *=diameter; // RELATIVE INFLATION
  2324. bmin -= float3(inflate*2.5f,inflate*2.5f,inflate*2.5f);
  2325. bmax += float3(inflate*2.5f,inflate*2.5f,inflate*2.5f);
  2326. // 2 is from the formula:
  2327. // D = d*|n1+n2|/(1-n1 dot n2), where d is "inflate" and
  2328. // n1 and n2 are the normals of two planes at bevelAngle to each other
  2329. // for 120 degrees, D is 2d
  2330. //bmin -= float3(inflate,inflate,inflate);
  2331. //bmax += float3(inflate,inflate,inflate);
  2332. for(i=0;i<planes_count;i++)
  2333. {
  2334. planes[i].dist -= inflate;
  2335. }
  2336. float3 emin = bmin; // VectorMin(bmin,float3(0,0,0));
  2337. float3 emax = bmax; // VectorMax(bmax,float3(0,0,0));
  2338. NxF32 epsilon = 0.01f; // size of object is taken into account within candidate plane function. Used to multiply here by magnitude(emax-emin)
  2339. planetestepsilon = magnitude(emax-emin) * PAPERWIDTH;
  2340. // todo: add bounding cube planes to force bevel. or try instead not adding the diameter expansion ??? must think.
  2341. // ConvexH *convex = ConvexHMakeCube(bmin - float3(diameter,diameter,diameter),bmax+float3(diameter,diameter,diameter));
  2342. NxF32 maxdot_minang = cosf(DEG2RAD*minadjangle);
  2343. for(j=0;j<6;j++)
  2344. {
  2345. float3 n(0,0,0);
  2346. n[j/2] = (j%2)? 1.0f : -1.0f;
  2347. for(i=0;i<planes_count;i++)
  2348. {
  2349. if(dot(n,planes[i].normal)> maxdot_minang)
  2350. {
  2351. (*((j%2)?&bmax:&bmin)) += n * (diameter*0.5f);
  2352. break;
  2353. }
  2354. }
  2355. }
  2356. ConvexH *c = ConvexHMakeCube(REAL3(bmin),REAL3(bmax));
  2357. NxI32 k;
  2358. while(maxplanes-- && (k=candidateplane(planes,planes_count,c,epsilon))>=0)
  2359. {
  2360. ConvexH *tmp = c;
  2361. c = ConvexHCrop(*tmp,planes[k]);
  2362. if(c==NULL) {c=tmp; break;} // might want to debug this case better!!!
  2363. if(!AssertIntact(*c)) {c=tmp; break;} // might want to debug this case better too!!!
  2364. delete tmp;
  2365. }
  2366. assert(AssertIntact(*c));
  2367. //return c;
  2368. faces_out = (NxI32*)MEMALLOC_MALLOC(sizeof(NxI32)*(1+c->facets.count+c->edges.count)); // new NxI32[1+c->facets.count+c->edges.count];
  2369. faces_count_out=0;
  2370. i=0;
  2371. faces_out[faces_count_out++]=-1;
  2372. k=0;
  2373. while(i<c->edges.count)
  2374. {
  2375. j=1;
  2376. while(j+i<c->edges.count && c->edges[i].p==c->edges[i+j].p) { j++; }
  2377. faces_out[faces_count_out++]=j;
  2378. while(j--)
  2379. {
  2380. faces_out[faces_count_out++] = c->edges[i].v;
  2381. i++;
  2382. }
  2383. k++;
  2384. }
  2385. faces_out[0]=k; // number of faces.
  2386. assert(k==c->facets.count);
  2387. assert(faces_count_out == 1+c->facets.count+c->edges.count);
  2388. verts_out = c->vertices.element; // new float3[c->vertices.count];
  2389. verts_count_out = c->vertices.count;
  2390. for(i=0;i<c->vertices.count;i++)
  2391. {
  2392. verts_out[i] = float3(c->vertices[i]);
  2393. }
  2394. c->vertices.count=c->vertices.array_size=0; c->vertices.element=NULL;
  2395. delete c;
  2396. return 1;
  2397. }
  2398. static NxI32 overhullv(float3 *verts, NxI32 verts_count,NxI32 maxplanes,
  2399. float3 *&verts_out, NxI32 &verts_count_out, NxI32 *&faces_out, NxI32 &faces_count_out ,NxF32 inflate,NxF32 bevangle,NxI32 vlimit)
  2400. {
  2401. if(!verts_count) return 0;
  2402. extern NxI32 calchullpbev(float3 *verts,NxI32 verts_count,NxI32 vlimit, Array<Plane> &planes,NxF32 bevangle) ;
  2403. Array<Plane> planes;
  2404. NxI32 rc=calchullpbev(verts,verts_count,vlimit,planes,bevangle) ;
  2405. if(!rc) return 0;
  2406. return overhull(planes.element,planes.count,verts,verts_count,maxplanes,verts_out,verts_count_out,faces_out,faces_count_out,inflate);
  2407. }
  2408. //*****************************************************
  2409. //*****************************************************
  2410. bool ComputeHull(NxU32 vcount,const NxF32 *vertices,PHullResult &result,NxU32 vlimit,NxF32 inflate)
  2411. {
  2412. NxI32 index_count;
  2413. NxI32 *faces;
  2414. float3 *verts_out;
  2415. NxI32 verts_count_out;
  2416. if(inflate==0.0f)
  2417. {
  2418. NxI32 *tris_out;
  2419. NxI32 tris_count;
  2420. NxI32 ret = calchull( (float3 *) vertices, (NxI32) vcount, tris_out, tris_count, vlimit );
  2421. if(!ret) return false;
  2422. result.mIndexCount = (NxU32) (tris_count*3);
  2423. result.mFaceCount = (NxU32) tris_count;
  2424. result.mVertices = (NxF32*) vertices;
  2425. result.mVcount = (NxU32) vcount;
  2426. result.mIndices = (NxU32 *) tris_out;
  2427. return true;
  2428. }
  2429. NxI32 ret = overhullv((float3*)vertices,vcount,35,verts_out,verts_count_out,faces,index_count,inflate,120.0f,vlimit);
  2430. if(!ret) {
  2431. tris.SetSize(0); //have to set the size to 0 in order to protect from a "pure virtual function call" problem
  2432. return false;
  2433. }
  2434. Array<int3> tris;
  2435. NxI32 n=faces[0];
  2436. NxI32 k=1;
  2437. for(NxI32 i=0;i<n;i++)
  2438. {
  2439. NxI32 pn = faces[k++];
  2440. for(NxI32 j=2;j<pn;j++) tris.Add(int3(faces[k],faces[k+j-1],faces[k+j]));
  2441. k+=pn;
  2442. }
  2443. assert(tris.count == index_count-1-(n*3));
  2444. MEMALLOC_FREE(faces); // PT: I added that. Is it ok ?
  2445. result.mIndexCount = (NxU32) (tris.count*3);
  2446. result.mFaceCount = (NxU32) tris.count;
  2447. result.mVertices = (NxF32*) verts_out;
  2448. result.mVcount = (NxU32) verts_count_out;
  2449. result.mIndices = (NxU32 *) tris.element;
  2450. tris.element=NULL; tris.count = tris.array_size=0;
  2451. CONVEX_DECOMPOSITION::tris.SetSize(0); //have to set the size to 0 in order to protect from a "pure virtual function call" problem
  2452. return true;
  2453. }
  2454. void ReleaseHull(PHullResult &result)
  2455. {
  2456. MEMALLOC_FREE(result.mIndices); // PT: I added that. Is it ok ?
  2457. MEMALLOC_FREE(result.mVertices); // PT: I added that. Is it ok ?
  2458. result.mVcount = 0;
  2459. result.mIndexCount = 0;
  2460. result.mIndices = 0;
  2461. result.mVertices = 0;
  2462. result.mIndices = 0;
  2463. }
  2464. //****** HULLLIB source code
  2465. HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
  2466. HullResult &result) // contains the resulst
  2467. {
  2468. HullError ret = QE_FAIL;
  2469. PHullResult hr;
  2470. NxU32 vcount = desc.mVcount;
  2471. if ( vcount < 8 ) vcount = 8;
  2472. NxF32 *vsource = (NxF32 *) MEMALLOC_MALLOC( sizeof(NxF32)*vcount*3 );
  2473. NxF32 scale[3];
  2474. NxU32 ovcount;
  2475. bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, vsource, desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
  2476. if ( ok )
  2477. {
  2478. {
  2479. for (NxU32 i=0; i<ovcount; i++)
  2480. {
  2481. NxF32 *v = &vsource[i*3];
  2482. v[0]*=scale[0];
  2483. v[1]*=scale[1];
  2484. v[2]*=scale[2];
  2485. }
  2486. }
  2487. NxF32 skinwidth = 0;
  2488. if ( desc.HasHullFlag(QF_SKIN_WIDTH) )
  2489. skinwidth = desc.mSkinWidth;
  2490. ok = ComputeHull(ovcount,vsource,hr,desc.mMaxVertices,skinwidth);
  2491. if ( ok )
  2492. {
  2493. // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
  2494. NxF32 *vscratch = (NxF32 *) MEMALLOC_MALLOC( sizeof(NxF32)*hr.mVcount*3);
  2495. BringOutYourDead(hr.mVertices,hr.mVcount, vscratch, ovcount, hr.mIndices, hr.mIndexCount );
  2496. ret = QE_OK;
  2497. if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
  2498. {
  2499. result.mPolygons = false;
  2500. result.mNumOutputVertices = ovcount;
  2501. result.mOutputVertices = (NxF32 *)MEMALLOC_MALLOC( sizeof(NxF32)*ovcount*3);
  2502. result.mNumFaces = hr.mFaceCount;
  2503. result.mNumIndices = hr.mIndexCount;
  2504. result.mIndices = (NxU32 *) MEMALLOC_MALLOC( sizeof(NxU32)*hr.mIndexCount);
  2505. memcpy(result.mOutputVertices, vscratch, sizeof(NxF32)*3*ovcount );
  2506. if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
  2507. {
  2508. const NxU32 *source = hr.mIndices;
  2509. NxU32 *dest = result.mIndices;
  2510. for (NxU32 i=0; i<hr.mFaceCount; i++)
  2511. {
  2512. dest[0] = source[2];
  2513. dest[1] = source[1];
  2514. dest[2] = source[0];
  2515. dest+=3;
  2516. source+=3;
  2517. }
  2518. }
  2519. else
  2520. {
  2521. memcpy(result.mIndices, hr.mIndices, sizeof(NxU32)*hr.mIndexCount);
  2522. }
  2523. }
  2524. else
  2525. {
  2526. result.mPolygons = true;
  2527. result.mNumOutputVertices = ovcount;
  2528. result.mOutputVertices = (NxF32 *)MEMALLOC_MALLOC( sizeof(NxF32)*ovcount*3);
  2529. result.mNumFaces = hr.mFaceCount;
  2530. result.mNumIndices = hr.mIndexCount+hr.mFaceCount;
  2531. result.mIndices = (NxU32 *) MEMALLOC_MALLOC( sizeof(NxU32)*result.mNumIndices);
  2532. memcpy(result.mOutputVertices, vscratch, sizeof(NxF32)*3*ovcount );
  2533. {
  2534. const NxU32 *source = hr.mIndices;
  2535. NxU32 *dest = result.mIndices;
  2536. for (NxU32 i=0; i<hr.mFaceCount; i++)
  2537. {
  2538. dest[0] = 3;
  2539. if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
  2540. {
  2541. dest[1] = source[2];
  2542. dest[2] = source[1];
  2543. dest[3] = source[0];
  2544. }
  2545. else
  2546. {
  2547. dest[1] = source[0];
  2548. dest[2] = source[1];
  2549. dest[3] = source[2];
  2550. }
  2551. dest+=4;
  2552. source+=3;
  2553. }
  2554. }
  2555. }
  2556. // ReleaseHull frees memory for hr.mVertices, which can be the
  2557. // same pointer as vsource, so be sure to set it to NULL if necessary
  2558. if ( hr.mVertices == vsource) vsource = NULL;
  2559. ReleaseHull(hr);
  2560. if ( vscratch )
  2561. {
  2562. MEMALLOC_FREE(vscratch);
  2563. }
  2564. }
  2565. }
  2566. // this pointer is usually freed in ReleaseHull()
  2567. if ( vsource )
  2568. {
  2569. MEMALLOC_FREE(vsource);
  2570. }
  2571. return ret;
  2572. }
  2573. HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
  2574. {
  2575. if ( result.mOutputVertices )
  2576. {
  2577. MEMALLOC_FREE(result.mOutputVertices);
  2578. result.mOutputVertices = 0;
  2579. }
  2580. if ( result.mIndices )
  2581. {
  2582. MEMALLOC_FREE(result.mIndices);
  2583. result.mIndices = 0;
  2584. }
  2585. return QE_OK;
  2586. }
  2587. static void AddPoint(NxU32 &vcount,NxF32 *p,NxF32 x,NxF32 y,NxF32 z)
  2588. {
  2589. NxF32 *dest = &p[vcount*3];
  2590. dest[0] = x;
  2591. dest[1] = y;
  2592. dest[2] = z;
  2593. vcount++;
  2594. }
  2595. NxF32 GetDist(NxF32 px,NxF32 py,NxF32 pz,const NxF32 *p2)
  2596. {
  2597. NxF32 dx = px - p2[0];
  2598. NxF32 dy = py - p2[1];
  2599. NxF32 dz = pz - p2[2];
  2600. return dx*dx+dy*dy+dz*dz;
  2601. }
  2602. bool HullLibrary::CleanupVertices(NxU32 svcount,
  2603. const NxF32 *svertices,
  2604. NxU32 stride,
  2605. NxU32 &vcount, // output number of vertices
  2606. NxF32 *vertices, // location to store the results.
  2607. NxF32 normalepsilon,
  2608. NxF32 *scale)
  2609. {
  2610. if ( svcount == 0 ) return false;
  2611. #define EPSILON 0.000001f // close enough to consider two floating point numbers to be 'the same'.
  2612. vcount = 0;
  2613. NxF32 recip[3];
  2614. if ( scale )
  2615. {
  2616. scale[0] = 1;
  2617. scale[1] = 1;
  2618. scale[2] = 1;
  2619. }
  2620. NxF32 bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
  2621. NxF32 bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
  2622. const char *vtx = (const char *) svertices;
  2623. {
  2624. for (NxU32 i=0; i<svcount; i++)
  2625. {
  2626. const NxF32 *p = (const NxF32 *) vtx;
  2627. vtx+=stride;
  2628. for (NxI32 j=0; j<3; j++)
  2629. {
  2630. if ( p[j] < bmin[j] ) bmin[j] = p[j];
  2631. if ( p[j] > bmax[j] ) bmax[j] = p[j];
  2632. }
  2633. }
  2634. }
  2635. NxF32 dx = bmax[0] - bmin[0];
  2636. NxF32 dy = bmax[1] - bmin[1];
  2637. NxF32 dz = bmax[2] - bmin[2];
  2638. NxF32 center[3];
  2639. center[0] = dx*0.5f + bmin[0];
  2640. center[1] = dy*0.5f + bmin[1];
  2641. center[2] = dz*0.5f + bmin[2];
  2642. if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
  2643. {
  2644. NxF32 len = FLT_MAX;
  2645. if ( dx > EPSILON && dx < len ) len = dx;
  2646. if ( dy > EPSILON && dy < len ) len = dy;
  2647. if ( dz > EPSILON && dz < len ) len = dz;
  2648. if ( len == FLT_MAX )
  2649. {
  2650. dx = dy = dz = 0.01f; // one centimeter
  2651. }
  2652. else
  2653. {
  2654. if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
  2655. if ( dy < EPSILON ) dy = len * 0.05f;
  2656. if ( dz < EPSILON ) dz = len * 0.05f;
  2657. }
  2658. NxF32 x1 = center[0] - dx;
  2659. NxF32 x2 = center[0] + dx;
  2660. NxF32 y1 = center[1] - dy;
  2661. NxF32 y2 = center[1] + dy;
  2662. NxF32 z1 = center[2] - dz;
  2663. NxF32 z2 = center[2] + dz;
  2664. AddPoint(vcount,vertices,x1,y1,z1);
  2665. AddPoint(vcount,vertices,x2,y1,z1);
  2666. AddPoint(vcount,vertices,x2,y2,z1);
  2667. AddPoint(vcount,vertices,x1,y2,z1);
  2668. AddPoint(vcount,vertices,x1,y1,z2);
  2669. AddPoint(vcount,vertices,x2,y1,z2);
  2670. AddPoint(vcount,vertices,x2,y2,z2);
  2671. AddPoint(vcount,vertices,x1,y2,z2);
  2672. return true; // return cube
  2673. }
  2674. else
  2675. {
  2676. if ( scale )
  2677. {
  2678. scale[0] = dx;
  2679. scale[1] = dy;
  2680. scale[2] = dz;
  2681. recip[0] = 1 / dx;
  2682. recip[1] = 1 / dy;
  2683. recip[2] = 1 / dz;
  2684. center[0]*=recip[0];
  2685. center[1]*=recip[1];
  2686. center[2]*=recip[2];
  2687. }
  2688. }
  2689. vtx = (const char *) svertices;
  2690. for (NxU32 i=0; i<svcount; i++)
  2691. {
  2692. const NxF32 *p = (const NxF32 *)vtx;
  2693. vtx+=stride;
  2694. NxF32 px = p[0];
  2695. NxF32 py = p[1];
  2696. NxF32 pz = p[2];
  2697. if ( scale )
  2698. {
  2699. px = px*recip[0]; // normalize
  2700. py = py*recip[1]; // normalize
  2701. pz = pz*recip[2]; // normalize
  2702. }
  2703. {
  2704. NxU32 j;
  2705. for (j=0; j<vcount; j++)
  2706. {
  2707. NxF32 *v = &vertices[j*3];
  2708. NxF32 x = v[0];
  2709. NxF32 y = v[1];
  2710. NxF32 z = v[2];
  2711. NxF32 dx = fabsf(x - px );
  2712. NxF32 dy = fabsf(y - py );
  2713. NxF32 dz = fabsf(z - pz );
  2714. if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
  2715. {
  2716. // ok, it is close enough to the old one
  2717. // now let us see if it is further from the center of the point cloud than the one we already recorded.
  2718. // in which case we keep this one instead.
  2719. NxF32 dist1 = GetDist(px,py,pz,center);
  2720. NxF32 dist2 = GetDist(v[0],v[1],v[2],center);
  2721. if ( dist1 > dist2 )
  2722. {
  2723. v[0] = px;
  2724. v[1] = py;
  2725. v[2] = pz;
  2726. }
  2727. break;
  2728. }
  2729. }
  2730. if ( j == vcount )
  2731. {
  2732. NxF32 *dest = &vertices[vcount*3];
  2733. dest[0] = px;
  2734. dest[1] = py;
  2735. dest[2] = pz;
  2736. vcount++;
  2737. }
  2738. }
  2739. }
  2740. // ok..now make sure we didn't prune so many vertices it is now invalid.
  2741. {
  2742. NxF32 bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
  2743. NxF32 bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
  2744. for (NxU32 i=0; i<vcount; i++)
  2745. {
  2746. const NxF32 *p = &vertices[i*3];
  2747. for (NxI32 j=0; j<3; j++)
  2748. {
  2749. if ( p[j] < bmin[j] ) bmin[j] = p[j];
  2750. if ( p[j] > bmax[j] ) bmax[j] = p[j];
  2751. }
  2752. }
  2753. NxF32 dx = bmax[0] - bmin[0];
  2754. NxF32 dy = bmax[1] - bmin[1];
  2755. NxF32 dz = bmax[2] - bmin[2];
  2756. if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
  2757. {
  2758. NxF32 cx = dx*0.5f + bmin[0];
  2759. NxF32 cy = dy*0.5f + bmin[1];
  2760. NxF32 cz = dz*0.5f + bmin[2];
  2761. NxF32 len = FLT_MAX;
  2762. if ( dx >= EPSILON && dx < len ) len = dx;
  2763. if ( dy >= EPSILON && dy < len ) len = dy;
  2764. if ( dz >= EPSILON && dz < len ) len = dz;
  2765. if ( len == FLT_MAX )
  2766. {
  2767. dx = dy = dz = 0.01f; // one centimeter
  2768. }
  2769. else
  2770. {
  2771. if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
  2772. if ( dy < EPSILON ) dy = len * 0.05f;
  2773. if ( dz < EPSILON ) dz = len * 0.05f;
  2774. }
  2775. NxF32 x1 = cx - dx;
  2776. NxF32 x2 = cx + dx;
  2777. NxF32 y1 = cy - dy;
  2778. NxF32 y2 = cy + dy;
  2779. NxF32 z1 = cz - dz;
  2780. NxF32 z2 = cz + dz;
  2781. vcount = 0; // add box
  2782. AddPoint(vcount,vertices,x1,y1,z1);
  2783. AddPoint(vcount,vertices,x2,y1,z1);
  2784. AddPoint(vcount,vertices,x2,y2,z1);
  2785. AddPoint(vcount,vertices,x1,y2,z1);
  2786. AddPoint(vcount,vertices,x1,y1,z2);
  2787. AddPoint(vcount,vertices,x2,y1,z2);
  2788. AddPoint(vcount,vertices,x2,y2,z2);
  2789. AddPoint(vcount,vertices,x1,y2,z2);
  2790. return true;
  2791. }
  2792. }
  2793. return true;
  2794. }
  2795. void HullLibrary::BringOutYourDead(const NxF32 *verts,NxU32 vcount, NxF32 *overts,NxU32 &ocount,NxU32 *indices,NxU32 indexcount)
  2796. {
  2797. NxU32 *used = (NxU32 *)MEMALLOC_MALLOC(sizeof(NxU32)*vcount);
  2798. memset(used,0,sizeof(NxU32)*vcount);
  2799. ocount = 0;
  2800. for (NxU32 i=0; i<indexcount; i++)
  2801. {
  2802. NxU32 v = indices[i]; // original array index
  2803. assert( v < vcount );
  2804. if ( used[v] ) // if already remapped
  2805. {
  2806. indices[i] = used[v]-1; // index to new array
  2807. }
  2808. else
  2809. {
  2810. indices[i] = ocount; // new index mapping
  2811. overts[ocount*3+0] = verts[v*3+0]; // copy old vert to new vert array
  2812. overts[ocount*3+1] = verts[v*3+1];
  2813. overts[ocount*3+2] = verts[v*3+2];
  2814. ocount++; // increment output vert count
  2815. assert( ocount <= vcount );
  2816. used[v] = ocount; // assign new index remapping
  2817. }
  2818. }
  2819. MEMALLOC_FREE(used);
  2820. }
  2821. //==================================================================================
  2822. HullError HullLibrary::CreateTriangleMesh(HullResult &answer,ConvexHullTriangleInterface *iface)
  2823. {
  2824. HullError ret = QE_FAIL;
  2825. const NxF32 *p = answer.mOutputVertices;
  2826. const NxU32 *idx = answer.mIndices;
  2827. NxU32 fcount = answer.mNumFaces;
  2828. if ( p && idx && fcount )
  2829. {
  2830. ret = QE_OK;
  2831. for (NxU32 i=0; i<fcount; i++)
  2832. {
  2833. NxU32 pcount = *idx++;
  2834. NxU32 i1 = *idx++;
  2835. NxU32 i2 = *idx++;
  2836. NxU32 i3 = *idx++;
  2837. const NxF32 *p1 = &p[i1*3];
  2838. const NxF32 *p2 = &p[i2*3];
  2839. const NxF32 *p3 = &p[i3*3];
  2840. AddConvexTriangle(iface,p1,p2,p3);
  2841. pcount-=3;
  2842. while ( pcount )
  2843. {
  2844. i3 = *idx++;
  2845. p2 = p3;
  2846. p3 = &p[i3*3];
  2847. AddConvexTriangle(iface,p1,p2,p3);
  2848. pcount--;
  2849. }
  2850. }
  2851. }
  2852. return ret;
  2853. }
  2854. //==================================================================================
  2855. void HullLibrary::AddConvexTriangle(ConvexHullTriangleInterface *callback,const NxF32 *p1,const NxF32 *p2,const NxF32 *p3)
  2856. {
  2857. ConvexHullVertex v1,v2,v3;
  2858. #define TSCALE1 (1.0f/4.0f)
  2859. v1.mPos[0] = p1[0];
  2860. v1.mPos[1] = p1[1];
  2861. v1.mPos[2] = p1[2];
  2862. v2.mPos[0] = p2[0];
  2863. v2.mPos[1] = p2[1];
  2864. v2.mPos[2] = p2[2];
  2865. v3.mPos[0] = p3[0];
  2866. v3.mPos[1] = p3[1];
  2867. v3.mPos[2] = p3[2];
  2868. NxF32 n[3];
  2869. ComputeNormal(n,p1,p2,p3);
  2870. v1.mNormal[0] = n[0];
  2871. v1.mNormal[1] = n[1];
  2872. v1.mNormal[2] = n[2];
  2873. v2.mNormal[0] = n[0];
  2874. v2.mNormal[1] = n[1];
  2875. v2.mNormal[2] = n[2];
  2876. v3.mNormal[0] = n[0];
  2877. v3.mNormal[1] = n[1];
  2878. v3.mNormal[2] = n[2];
  2879. const NxF32 *tp1 = p1;
  2880. const NxF32 *tp2 = p2;
  2881. const NxF32 *tp3 = p3;
  2882. NxI32 i1 = 0;
  2883. NxI32 i2 = 0;
  2884. NxF32 nx = fabsf(n[0]);
  2885. NxF32 ny = fabsf(n[1]);
  2886. NxF32 nz = fabsf(n[2]);
  2887. if ( nx <= ny && nx <= nz )
  2888. i1 = 0;
  2889. if ( ny <= nx && ny <= nz )
  2890. i1 = 1;
  2891. if ( nz <= nx && nz <= ny )
  2892. i1 = 2;
  2893. switch ( i1 )
  2894. {
  2895. case 0:
  2896. if ( ny < nz )
  2897. i2 = 1;
  2898. else
  2899. i2 = 2;
  2900. break;
  2901. case 1:
  2902. if ( nx < nz )
  2903. i2 = 0;
  2904. else
  2905. i2 = 2;
  2906. break;
  2907. case 2:
  2908. if ( nx < ny )
  2909. i2 = 0;
  2910. else
  2911. i2 = 1;
  2912. break;
  2913. }
  2914. v1.mTexel[0] = tp1[i1]*TSCALE1;
  2915. v1.mTexel[1] = tp1[i2]*TSCALE1;
  2916. v2.mTexel[0] = tp2[i1]*TSCALE1;
  2917. v2.mTexel[1] = tp2[i2]*TSCALE1;
  2918. v3.mTexel[0] = tp3[i1]*TSCALE1;
  2919. v3.mTexel[1] = tp3[i2]*TSCALE1;
  2920. callback->ConvexHullTriangle(v3,v2,v1);
  2921. }
  2922. //==================================================================================
  2923. NxF32 HullLibrary::ComputeNormal(NxF32 *n,const NxF32 *A,const NxF32 *B,const NxF32 *C)
  2924. {
  2925. NxF32 vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag;
  2926. vx = (B[0] - C[0]);
  2927. vy = (B[1] - C[1]);
  2928. vz = (B[2] - C[2]);
  2929. wx = (A[0] - B[0]);
  2930. wy = (A[1] - B[1]);
  2931. wz = (A[2] - B[2]);
  2932. vw_x = vy * wz - vz * wy;
  2933. vw_y = vz * wx - vx * wz;
  2934. vw_z = vx * wy - vy * wx;
  2935. mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
  2936. if ( mag < 0.000001f )
  2937. {
  2938. mag = 0;
  2939. }
  2940. else
  2941. {
  2942. mag = 1.0f/mag;
  2943. }
  2944. n[0] = vw_x * mag;
  2945. n[1] = vw_y * mag;
  2946. n[2] = vw_z * mag;
  2947. return mag;
  2948. }
  2949. }; // End of namespace