VHACD.h 254 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447
  1. /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
  2. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  4. 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  5. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  6. 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
  7. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  8. */
  9. #pragma once
  10. #ifndef VHACD_H
  11. # define VHACD_H
  12. // Please view this slide deck which describes usage and how the algorithm works.
  13. // https://docs.google.com/presentation/d/1OZ4mtZYrGEC8qffqb8F7Le2xzufiqvaPpRbLHKKgTIM/edit?usp=sharing
  14. // VHACD is now a header only library.
  15. // In just *one* of your CPP files *before* you include 'VHACD.h' you must declare
  16. // #define ENABLE_VHACD_IMPLEMENTATION 1
  17. // This will compile the implementation code into your project. If you don't
  18. // have this define, you will get link errors since the implementation code will
  19. // not be present. If you define it more than once in your code base, you will get
  20. // link errors due to a duplicate implementation. This is the same pattern used by
  21. // ImGui and StbLib and other popular open source libraries.
  22. # define VHACD_VERSION_MAJOR 4
  23. # define VHACD_VERSION_MINOR 1
  24. // Changes for version 4.1
  25. //
  26. // Various minor tweaks mostly to the test application and some default values.
  27. // Changes for version 4.0
  28. //
  29. // * The code has been significantly refactored to be cleaner and easier to maintain
  30. // * All OpenCL related code removed
  31. // * All Bullet code removed
  32. // * All SIMD code removed
  33. // * Old plane splitting code removed
  34. //
  35. // * The code is now delivered as a single header file 'VHACD.h' which has both the API
  36. // * declaration as well as the implementation. Simply add '#define ENABLE_VHACD_IMPLEMENTATION 1'
  37. // * to any CPP in your application prior to including 'VHACD.h'. Only do this in one CPP though.
  38. // * If you do not have this define once, you will get link errors since the implementation code
  39. // * will not be compiled in. If you have this define more than once, you are likely to get
  40. // * duplicate symbol link errors.
  41. //
  42. // * Since the library is now delivered as a single header file, we do not provide binaries
  43. // * or build scripts as these are not needed.
  44. //
  45. // * The old DebugView and test code has all been removed and replaced with a much smaller and
  46. // * simpler test console application with some test meshes to work with.
  47. //
  48. // * The convex hull generation code has changed. The previous version came from Bullet.
  49. // * However, the new version is courtesy of Julio Jerez, the author of the Newton
  50. // * physics engine. His new version is faster and more numerically stable.
  51. //
  52. // * The code can now detect if the input mesh is, itself, already a convex object and
  53. // * can early out.
  54. //
  55. // * Significant performance improvements have been made to the code and it is now much
  56. // * faster, stable, and is easier to tune than previous versions.
  57. //
  58. // * A bug was fixed with the shrink wrapping code (project hull vertices) that could
  59. // * sometime produce artifacts in the results. The new version uses a 'closest point'
  60. // * algorithm that is more reliable.
  61. //
  62. // * You can now select which 'fill mode' to use. For perfectly closed meshes, the default
  63. // * behavior using a flood fill generally works fine. However, some meshes have small
  64. // * holes in them and therefore the flood fill will fail, treating the mesh as being
  65. // * hollow. In these cases, you can use the 'raycast' fill option to determine which
  66. // * parts of the voxelized mesh are 'inside' versus being 'outside'. Finally, there
  67. // * are some rare instances where a user might actually want the mesh to be treated as
  68. // * hollow, in which case you can pass in 'surface' only.
  69. // *
  70. // * A new optional virtual interface called 'IUserProfiler' was provided.
  71. // * This allows the user to provide an optional profiling callback interface to assist in
  72. // * diagnosing performance issues. This change was made by Danny Couture at Epic for the UE4 integration.
  73. // * Some profiling macros were also declared in support of this feature.
  74. // *
  75. // * Another new optional virtual interface called 'IUserTaskRunner' was provided.
  76. // * This interface is used to run logical 'tasks' in a background thread. If none is provided
  77. // * then a default implementation using std::thread will be executed.
  78. // * This change was made by Danny Couture at Epic to speed up the voxelization step.
  79. // *
  80. // The history of V-HACD:
  81. //
  82. // The initial version was written by John W. Ratcliff and was called 'ACD'
  83. // This version did not perform CSG operations on the source mesh, so if you
  84. // recursed too deeply it would produce hollow results.
  85. //
  86. // The next version was written by Khaled Mamou and was called 'HACD'
  87. // In this version Khaled tried to perform a CSG operation on the source
  88. // mesh to produce more robust results. However, Khaled learned that the
  89. // CSG library he was using had licensing issues so he started work on the
  90. // next version.
  91. //
  92. // The next version was called 'V-HACD' because Khaled made the observation
  93. // that plane splitting would be far easier to implement working in voxel space.
  94. //
  95. // V-HACD has been integrated into UE4, Blender, and a number of other projects.
  96. // This new release, version4, is a significant refactor of the code to fix
  97. // some bugs, improve performance, and to make the codebase easier to maintain
  98. // going forward.
  99. #ifndef _STDINT
  100. #include <stdint.h>
  101. #endif
  102. #ifndef _FUNCTIONAL_
  103. #include <functional>
  104. #endif
  105. #ifndef _VECTOR_
  106. #include <vector>
  107. #endif
  108. #ifndef _ARRAY_
  109. #include <array>
  110. #endif
  111. #ifndef _CMATH_
  112. #include <cmath>
  113. #endif
  114. #ifndef _ALGORITHM_
  115. #include <algorithm>
  116. #endif
  117. namespace VHACD {
  118. struct Vertex
  119. {
  120. double mX;
  121. double mY;
  122. double mZ;
  123. Vertex() = default;
  124. Vertex(double x, double y, double z) : mX(x), mY(y), mZ(z) {}
  125. const double& operator[](size_t idx) const
  126. {
  127. switch(idx)
  128. {
  129. case 0: return mX;
  130. case 1: return mY;
  131. case 2: return mZ;
  132. };
  133. return mX;
  134. }
  135. };
  136. struct Triangle
  137. {
  138. uint32_t mI0;
  139. uint32_t mI1;
  140. uint32_t mI2;
  141. Triangle() = default;
  142. Triangle(uint32_t i0, uint32_t i1, uint32_t i2) : mI0(i0), mI1(i1), mI2(i2) {}
  143. };
  144. template <typename T>
  145. class Vector3
  146. {
  147. public:
  148. /*
  149. * Getters
  150. */
  151. T& operator[](size_t i);
  152. const T& operator[](size_t i) const;
  153. T& GetX();
  154. T& GetY();
  155. T& GetZ();
  156. const T& GetX() const;
  157. const T& GetY() const;
  158. const T& GetZ() const;
  159. /*
  160. * Normalize and norming
  161. */
  162. T Normalize();
  163. Vector3 Normalized();
  164. T GetNorm() const;
  165. T GetNormSquared() const;
  166. int LongestAxis() const;
  167. /*
  168. * Vector-vector operations
  169. */
  170. Vector3& operator=(const Vector3& rhs);
  171. Vector3& operator+=(const Vector3& rhs);
  172. Vector3& operator-=(const Vector3& rhs);
  173. Vector3 CWiseMul(const Vector3& rhs) const;
  174. Vector3 Cross(const Vector3& rhs) const;
  175. T Dot(const Vector3& rhs) const;
  176. Vector3 operator+(const Vector3& rhs) const;
  177. Vector3 operator-(const Vector3& rhs) const;
  178. /*
  179. * Vector-scalar operations
  180. */
  181. Vector3& operator-=(T a);
  182. Vector3& operator+=(T a);
  183. Vector3& operator/=(T a);
  184. Vector3& operator*=(T a);
  185. Vector3 operator*(T rhs) const;
  186. Vector3 operator/(T rhs) const;
  187. /*
  188. * Unary operations
  189. */
  190. Vector3 operator-() const;
  191. /*
  192. * Comparison operators
  193. */
  194. bool operator<(const Vector3& rhs) const;
  195. bool operator>(const Vector3& rhs) const;
  196. /*
  197. * Returns true if all elements of *this are greater than or equal to all elements of rhs, coefficient wise
  198. * LE is less than or equal
  199. */
  200. bool CWiseAllGE(const Vector3<T>& rhs) const;
  201. bool CWiseAllLE(const Vector3<T>& rhs) const;
  202. Vector3 CWiseMin(const Vector3& rhs) const;
  203. Vector3 CWiseMax(const Vector3& rhs) const;
  204. T MinCoeff() const;
  205. T MaxCoeff() const;
  206. T MinCoeff(uint32_t& idx) const;
  207. T MaxCoeff(uint32_t& idx) const;
  208. /*
  209. * Constructors
  210. */
  211. Vector3() = default;
  212. Vector3(T a);
  213. Vector3(T x, T y, T z);
  214. Vector3(const Vector3& rhs);
  215. ~Vector3() = default;
  216. template <typename U>
  217. Vector3(const Vector3<U>& rhs);
  218. Vector3(const VHACD::Vertex&);
  219. Vector3(const VHACD::Triangle&);
  220. operator VHACD::Vertex() const;
  221. private:
  222. std::array<T, 3> m_data{ T(0.0) };
  223. };
  224. typedef VHACD::Vector3<double> Vect3;
  225. struct BoundsAABB
  226. {
  227. BoundsAABB() = default;
  228. BoundsAABB(const std::vector<VHACD::Vertex>& points);
  229. BoundsAABB(const Vect3& min,
  230. const Vect3& max);
  231. BoundsAABB Union(const BoundsAABB& b);
  232. bool Intersects(const BoundsAABB& b) const;
  233. double SurfaceArea() const;
  234. double Volume() const;
  235. BoundsAABB Inflate(double ratio) const;
  236. VHACD::Vect3 ClosestPoint(const VHACD::Vect3& p) const;
  237. VHACD::Vect3& GetMin();
  238. VHACD::Vect3& GetMax();
  239. const VHACD::Vect3& GetMin() const;
  240. const VHACD::Vect3& GetMax() const;
  241. VHACD::Vect3 GetSize() const;
  242. VHACD::Vect3 GetCenter() const;
  243. VHACD::Vect3 m_min{ double(0.0) };
  244. VHACD::Vect3 m_max{ double(0.0) };
  245. };
  246. /**
  247. * This enumeration determines how the voxels as filled to create a solid
  248. * object. The default should be 'FLOOD_FILL' which generally works fine
  249. * for closed meshes. However, if the mesh is not watertight, then using
  250. * RAYCAST_FILL may be preferable as it will determine if a voxel is part
  251. * of the interior of the source mesh by raycasting around it.
  252. *
  253. * Finally, there are some cases where you might actually want a convex
  254. * decomposition to treat the source mesh as being hollow. If that is the
  255. * case you can pass in 'SURFACE_ONLY' and then the convex decomposition
  256. * will converge only onto the 'skin' of the surface mesh.
  257. */
  258. enum class FillMode
  259. {
  260. FLOOD_FILL, // This is the default behavior, after the voxelization step it uses a flood fill to determine 'inside'
  261. // from 'outside'. However, meshes with holes can fail and create hollow results.
  262. SURFACE_ONLY, // Only consider the 'surface', will create 'skins' with hollow centers.
  263. RAYCAST_FILL, // Uses raycasting to determine inside from outside.
  264. };
  265. class IVHACD
  266. {
  267. public:
  268. /**
  269. * This optional pure virtual interface is used to notify the caller of the progress
  270. * of convex decomposition as well as a signal when it is complete when running in
  271. * a background thread
  272. */
  273. class IUserCallback
  274. {
  275. public:
  276. virtual ~IUserCallback(){};
  277. /**
  278. * Notifies the application of the current state of the convex decomposition operation
  279. *
  280. * @param overallProgress : Total progress from 0-100%
  281. * @param stageProgress : Progress of the current stage 0-100%
  282. * @param stage : A text description of the current stage we are in
  283. * @param operation : A text description of what operation is currently being performed.
  284. */
  285. virtual void Update(const double overallProgress,
  286. const double stageProgress,
  287. const char* const stage,
  288. const char* operation) = 0;
  289. // This is an optional user callback which is only called when running V-HACD asynchronously.
  290. // This is a callback performed to notify the user that the
  291. // convex decomposition background process is completed. This call back will occur from
  292. // a different thread so the user should take that into account.
  293. virtual void NotifyVHACDComplete()
  294. {
  295. }
  296. };
  297. /**
  298. * Optional user provided pure virtual interface to be notified of warning or informational messages
  299. */
  300. class IUserLogger
  301. {
  302. public:
  303. virtual ~IUserLogger(){};
  304. virtual void Log(const char* const msg) = 0;
  305. };
  306. /**
  307. * An optional user provided pure virtual interface to perform a background task.
  308. * This was added by Danny Couture at Epic as they wanted to use their own
  309. * threading system instead of the standard library version which is the default.
  310. */
  311. class IUserTaskRunner
  312. {
  313. public:
  314. virtual ~IUserTaskRunner(){};
  315. virtual void* StartTask(std::function<void()> func) = 0;
  316. virtual void JoinTask(void* Task) = 0;
  317. };
  318. /**
  319. * A simple class that represents a convex hull as a triangle mesh with
  320. * double precision vertices. Polygons are not currently provided.
  321. */
  322. class ConvexHull
  323. {
  324. public:
  325. std::vector<VHACD::Vertex> m_points;
  326. std::vector<VHACD::Triangle> m_triangles;
  327. double m_volume{ 0 }; // The volume of the convex hull
  328. VHACD::Vect3 m_center{ 0, 0, 0 }; // The centroid of the convex hull
  329. uint32_t m_meshId{ 0 }; // A unique id for this convex hull
  330. VHACD::Vect3 mBmin; // Bounding box minimum of the AABB
  331. VHACD::Vect3 mBmax; // Bounding box maximum of the AABB
  332. };
  333. /**
  334. * This class provides the parameters controlling the convex decomposition operation
  335. */
  336. class Parameters
  337. {
  338. public:
  339. IUserCallback* m_callback{nullptr}; // Optional user provided callback interface for progress
  340. IUserLogger* m_logger{nullptr}; // Optional user provided callback interface for log messages
  341. IUserTaskRunner* m_taskRunner{nullptr}; // Optional user provided interface for creating tasks
  342. uint32_t m_maxConvexHulls{ 64 }; // The maximum number of convex hulls to produce
  343. uint32_t m_resolution{ 400000 }; // The voxel resolution to use
  344. double m_minimumVolumePercentErrorAllowed{ 1 }; // if the voxels are within 1% of the volume of the hull, we consider this a close enough approximation
  345. uint32_t m_maxRecursionDepth{ 10 }; // The maximum recursion depth
  346. bool m_shrinkWrap{true}; // Whether or not to shrinkwrap the voxel positions to the source mesh on output
  347. FillMode m_fillMode{ FillMode::FLOOD_FILL }; // How to fill the interior of the voxelized mesh
  348. uint32_t m_maxNumVerticesPerCH{ 64 }; // The maximum number of vertices allowed in any output convex hull
  349. bool m_asyncACD{ true }; // Whether or not to run asynchronously, taking advantage of additional cores
  350. uint32_t m_minEdgeLength{ 2 }; // Once a voxel patch has an edge length of less than 4 on all 3 sides, we don't keep recursing
  351. bool m_findBestPlane{ false }; // Whether or not to attempt to split planes along the best location. Experimental feature. False by default.
  352. };
  353. /**
  354. * Will cause the convex decomposition operation to be canceled early. No results will be produced but the background operation will end as soon as it can.
  355. */
  356. virtual void Cancel() = 0;
  357. /**
  358. * Compute a convex decomposition of a triangle mesh using float vertices and the provided user parameters.
  359. *
  360. * @param points : The vertices of the source mesh as floats in the form of X1,Y1,Z1, X2,Y2,Z2,.. etc.
  361. * @param countPoints : The number of vertices in the source mesh.
  362. * @param triangles : The indices of triangles in the source mesh in the form of I1,I2,I3, ....
  363. * @param countTriangles : The number of triangles in the source mesh
  364. * @param params : The convex decomposition parameters to apply
  365. * @return : Returns true if the convex decomposition operation can be started
  366. */
  367. virtual bool Compute(const float* const points,
  368. const uint32_t countPoints,
  369. const uint32_t* const triangles,
  370. const uint32_t countTriangles,
  371. const Parameters& params) = 0;
  372. /**
  373. * Compute a convex decomposition of a triangle mesh using double vertices and the provided user parameters.
  374. *
  375. * @param points : The vertices of the source mesh as floats in the form of X1,Y1,Z1, X2,Y2,Z2,.. etc.
  376. * @param countPoints : The number of vertices in the source mesh.
  377. * @param triangles : The indices of triangles in the source mesh in the form of I1,I2,I3, ....
  378. * @param countTriangles : The number of triangles in the source mesh
  379. * @param params : The convex decomposition parameters to apply
  380. * @return : Returns true if the convex decomposition operation can be started
  381. */
  382. virtual bool Compute(const double* const points,
  383. const uint32_t countPoints,
  384. const uint32_t* const triangles,
  385. const uint32_t countTriangles,
  386. const Parameters& params) = 0;
  387. /**
  388. * Returns the number of convex hulls that were produced.
  389. *
  390. * @return : Returns the number of convex hulls produced, or zero if it failed or was canceled
  391. */
  392. virtual uint32_t GetNConvexHulls() const = 0;
  393. /**
  394. * Retrieves one of the convex hulls in the solution set
  395. *
  396. * @param index : Which convex hull to retrieve
  397. * @param ch : The convex hull descriptor to return
  398. * @return : Returns true if the convex hull exists and could be retrieved
  399. */
  400. virtual bool GetConvexHull(const uint32_t index,
  401. ConvexHull& ch) const = 0;
  402. /**
  403. * Releases any memory allocated by the V-HACD class
  404. */
  405. virtual void Clean() = 0; // release internally allocated memory
  406. /**
  407. * Releases this instance of the V-HACD class
  408. */
  409. virtual void Release() = 0; // release IVHACD
  410. // Will compute the center of mass of the convex hull decomposition results and return it
  411. // in 'centerOfMass'. Returns false if the center of mass could not be computed.
  412. virtual bool ComputeCenterOfMass(double centerOfMass[3]) const = 0;
  413. // In synchronous mode (non-multi-threaded) the state is always 'ready'
  414. // In asynchronous mode, this returns true if the background thread is not still actively computing
  415. // a new solution. In an asynchronous config the 'IsReady' call will report any update or log
  416. // messages in the caller's current thread.
  417. virtual bool IsReady() const
  418. {
  419. return true;
  420. }
  421. /**
  422. * At the request of LegionFu : [email protected]
  423. * This method will return which convex hull is closest to the source position.
  424. * You can use this method to figure out, for example, which vertices in the original
  425. * source mesh are best associated with which convex hull.
  426. *
  427. * @param pos : The input 3d position to test against
  428. *
  429. * @return : Returns which convex hull this position is closest to.
  430. */
  431. virtual uint32_t findNearestConvexHull(const double pos[3],
  432. double& distanceToHull) = 0;
  433. protected:
  434. virtual ~IVHACD()
  435. {
  436. }
  437. };
  438. /*
  439. * Out of line definitions
  440. */
  441. template <typename T>
  442. T clamp(const T& v, const T& lo, const T& hi)
  443. {
  444. if (v < lo)
  445. {
  446. return lo;
  447. }
  448. if (v > hi)
  449. {
  450. return hi;
  451. }
  452. return v ;
  453. }
  454. /*
  455. * Getters
  456. */
  457. template <typename T>
  458. inline T& Vector3<T>::operator[](size_t i)
  459. {
  460. return m_data[i];
  461. }
  462. template <typename T>
  463. inline const T& Vector3<T>::operator[](size_t i) const
  464. {
  465. return m_data[i];
  466. }
  467. template <typename T>
  468. inline T& Vector3<T>::GetX()
  469. {
  470. return m_data[0];
  471. }
  472. template <typename T>
  473. inline T& Vector3<T>::GetY()
  474. {
  475. return m_data[1];
  476. }
  477. template <typename T>
  478. inline T& Vector3<T>::GetZ()
  479. {
  480. return m_data[2];
  481. }
  482. template <typename T>
  483. inline const T& Vector3<T>::GetX() const
  484. {
  485. return m_data[0];
  486. }
  487. template <typename T>
  488. inline const T& Vector3<T>::GetY() const
  489. {
  490. return m_data[1];
  491. }
  492. template <typename T>
  493. inline const T& Vector3<T>::GetZ() const
  494. {
  495. return m_data[2];
  496. }
  497. /*
  498. * Normalize and norming
  499. */
  500. template <typename T>
  501. inline T Vector3<T>::Normalize()
  502. {
  503. T n = GetNorm();
  504. if (n != T(0.0)) (*this) /= n;
  505. return n;
  506. }
  507. template <typename T>
  508. inline Vector3<T> Vector3<T>::Normalized()
  509. {
  510. Vector3<T> ret = *this;
  511. T n = GetNorm();
  512. if (n != T(0.0)) ret /= n;
  513. return ret;
  514. }
  515. template <typename T>
  516. inline T Vector3<T>::GetNorm() const
  517. {
  518. return std::sqrt(GetNormSquared());
  519. }
  520. template <typename T>
  521. inline T Vector3<T>::GetNormSquared() const
  522. {
  523. return this->Dot(*this);
  524. }
  525. template <typename T>
  526. inline int Vector3<T>::LongestAxis() const
  527. {
  528. auto it = std::max_element(m_data.begin(), m_data.end());
  529. return int(std::distance(m_data.begin(), it));
  530. }
  531. /*
  532. * Vector-vector operations
  533. */
  534. template <typename T>
  535. inline Vector3<T>& Vector3<T>::operator=(const Vector3<T>& rhs)
  536. {
  537. GetX() = rhs.GetX();
  538. GetY() = rhs.GetY();
  539. GetZ() = rhs.GetZ();
  540. return *this;
  541. }
  542. template <typename T>
  543. inline Vector3<T>& Vector3<T>::operator+=(const Vector3<T>& rhs)
  544. {
  545. GetX() += rhs.GetX();
  546. GetY() += rhs.GetY();
  547. GetZ() += rhs.GetZ();
  548. return *this;
  549. }
  550. template <typename T>
  551. inline Vector3<T>& Vector3<T>::operator-=(const Vector3<T>& rhs)
  552. {
  553. GetX() -= rhs.GetX();
  554. GetY() -= rhs.GetY();
  555. GetZ() -= rhs.GetZ();
  556. return *this;
  557. }
  558. template <typename T>
  559. inline Vector3<T> Vector3<T>::CWiseMul(const Vector3<T>& rhs) const
  560. {
  561. return Vector3<T>(GetX() * rhs.GetX(),
  562. GetY() * rhs.GetY(),
  563. GetZ() * rhs.GetZ());
  564. }
  565. template <typename T>
  566. inline Vector3<T> Vector3<T>::Cross(const Vector3<T>& rhs) const
  567. {
  568. return Vector3<T>(GetY() * rhs.GetZ() - GetZ() * rhs.GetY(),
  569. GetZ() * rhs.GetX() - GetX() * rhs.GetZ(),
  570. GetX() * rhs.GetY() - GetY() * rhs.GetX());
  571. }
  572. template <typename T>
  573. inline T Vector3<T>::Dot(const Vector3<T>& rhs) const
  574. {
  575. return GetX() * rhs.GetX()
  576. + GetY() * rhs.GetY()
  577. + GetZ() * rhs.GetZ();
  578. }
  579. template <typename T>
  580. inline Vector3<T> Vector3<T>::operator+(const Vector3<T>& rhs) const
  581. {
  582. return Vector3<T>(GetX() + rhs.GetX(),
  583. GetY() + rhs.GetY(),
  584. GetZ() + rhs.GetZ());
  585. }
  586. template <typename T>
  587. inline Vector3<T> Vector3<T>::operator-(const Vector3<T>& rhs) const
  588. {
  589. return Vector3<T>(GetX() - rhs.GetX(),
  590. GetY() - rhs.GetY(),
  591. GetZ() - rhs.GetZ());
  592. }
  593. template <typename T>
  594. inline Vector3<T> operator*(T lhs, const Vector3<T>& rhs)
  595. {
  596. return Vector3<T>(lhs * rhs.GetX(),
  597. lhs * rhs.GetY(),
  598. lhs * rhs.GetZ());
  599. }
  600. /*
  601. * Vector-scalar operations
  602. */
  603. template <typename T>
  604. inline Vector3<T>& Vector3<T>::operator-=(T a)
  605. {
  606. GetX() -= a;
  607. GetY() -= a;
  608. GetZ() -= a;
  609. return *this;
  610. }
  611. template <typename T>
  612. inline Vector3<T>& Vector3<T>::operator+=(T a)
  613. {
  614. GetX() += a;
  615. GetY() += a;
  616. GetZ() += a;
  617. return *this;
  618. }
  619. template <typename T>
  620. inline Vector3<T>& Vector3<T>::operator/=(T a)
  621. {
  622. GetX() /= a;
  623. GetY() /= a;
  624. GetZ() /= a;
  625. return *this;
  626. }
  627. template <typename T>
  628. inline Vector3<T>& Vector3<T>::operator*=(T a)
  629. {
  630. GetX() *= a;
  631. GetY() *= a;
  632. GetZ() *= a;
  633. return *this;
  634. }
  635. template <typename T>
  636. inline Vector3<T> Vector3<T>::operator*(T rhs) const
  637. {
  638. return Vector3<T>(GetX() * rhs,
  639. GetY() * rhs,
  640. GetZ() * rhs);
  641. }
  642. template <typename T>
  643. inline Vector3<T> Vector3<T>::operator/(T rhs) const
  644. {
  645. return Vector3<T>(GetX() / rhs,
  646. GetY() / rhs,
  647. GetZ() / rhs);
  648. }
  649. /*
  650. * Unary operations
  651. */
  652. template <typename T>
  653. inline Vector3<T> Vector3<T>::operator-() const
  654. {
  655. return Vector3<T>(-GetX(),
  656. -GetY(),
  657. -GetZ());
  658. }
  659. /*
  660. * Comparison operators
  661. */
  662. template <typename T>
  663. inline bool Vector3<T>::operator<(const Vector3<T>& rhs) const
  664. {
  665. if (GetX() == rhs.GetX())
  666. {
  667. if (GetY() == rhs.GetY())
  668. {
  669. return (GetZ() < rhs.GetZ());
  670. }
  671. return (GetY() < rhs.GetY());
  672. }
  673. return (GetX() < rhs.GetX());
  674. }
  675. template <typename T>
  676. inline bool Vector3<T>::operator>(const Vector3<T>& rhs) const
  677. {
  678. if (GetX() == rhs.GetX())
  679. {
  680. if (GetY() == rhs.GetY())
  681. {
  682. return (GetZ() > rhs.GetZ());
  683. }
  684. return (GetY() > rhs.GetY());
  685. }
  686. return (GetX() > rhs.GetZ());
  687. }
  688. template <typename T>
  689. inline bool Vector3<T>::CWiseAllGE(const Vector3<T>& rhs) const
  690. {
  691. return GetX() >= rhs.GetX()
  692. && GetY() >= rhs.GetY()
  693. && GetZ() >= rhs.GetZ();
  694. }
  695. template <typename T>
  696. inline bool Vector3<T>::CWiseAllLE(const Vector3<T>& rhs) const
  697. {
  698. return GetX() <= rhs.GetX()
  699. && GetY() <= rhs.GetY()
  700. && GetZ() <= rhs.GetZ();
  701. }
  702. template <typename T>
  703. inline Vector3<T> Vector3<T>::CWiseMin(const Vector3<T>& rhs) const
  704. {
  705. return Vector3<T>(std::min(GetX(), rhs.GetX()),
  706. std::min(GetY(), rhs.GetY()),
  707. std::min(GetZ(), rhs.GetZ()));
  708. }
  709. template <typename T>
  710. inline Vector3<T> Vector3<T>::CWiseMax(const Vector3<T>& rhs) const
  711. {
  712. return Vector3<T>(std::max(GetX(), rhs.GetX()),
  713. std::max(GetY(), rhs.GetY()),
  714. std::max(GetZ(), rhs.GetZ()));
  715. }
  716. template <typename T>
  717. inline T Vector3<T>::MinCoeff() const
  718. {
  719. return *std::min_element(m_data.begin(), m_data.end());
  720. }
  721. template <typename T>
  722. inline T Vector3<T>::MaxCoeff() const
  723. {
  724. return *std::max_element(m_data.begin(), m_data.end());
  725. }
  726. template <typename T>
  727. inline T Vector3<T>::MinCoeff(uint32_t& idx) const
  728. {
  729. auto it = std::min_element(m_data.begin(), m_data.end());
  730. idx = uint32_t(std::distance(m_data.begin(), it));
  731. return *it;
  732. }
  733. template <typename T>
  734. inline T Vector3<T>::MaxCoeff(uint32_t& idx) const
  735. {
  736. auto it = std::max_element(m_data.begin(), m_data.end());
  737. idx = uint32_t(std::distance(m_data.begin(), it));
  738. return *it;
  739. }
  740. /*
  741. * Constructors
  742. */
  743. template <typename T>
  744. inline Vector3<T>::Vector3(T a)
  745. : m_data{a, a, a}
  746. {
  747. }
  748. template <typename T>
  749. inline Vector3<T>::Vector3(T x, T y, T z)
  750. : m_data{x, y, z}
  751. {
  752. }
  753. template <typename T>
  754. inline Vector3<T>::Vector3(const Vector3& rhs)
  755. : m_data{rhs.m_data}
  756. {
  757. }
  758. template <typename T>
  759. template <typename U>
  760. inline Vector3<T>::Vector3(const Vector3<U>& rhs)
  761. : m_data{T(rhs.GetX()), T(rhs.GetY()), T(rhs.GetZ())}
  762. {
  763. }
  764. template <typename T>
  765. inline Vector3<T>::Vector3(const VHACD::Vertex& rhs)
  766. : Vector3<T>(rhs.mX, rhs.mY, rhs.mZ)
  767. {
  768. static_assert(std::is_same<T, double>::value, "Vertex to Vector3 constructor only enabled for double");
  769. }
  770. template <typename T>
  771. inline Vector3<T>::Vector3(const VHACD::Triangle& rhs)
  772. : Vector3<T>(rhs.mI0, rhs.mI1, rhs.mI2)
  773. {
  774. static_assert(std::is_same<T, uint32_t>::value, "Triangle to Vector3 constructor only enabled for uint32_t");
  775. }
  776. template <typename T>
  777. inline Vector3<T>::operator VHACD::Vertex() const
  778. {
  779. static_assert(std::is_same<T, double>::value, "Vector3 to Vertex conversion only enable for double");
  780. return ::VHACD::Vertex( GetX(), GetY(), GetZ());
  781. }
  782. IVHACD* CreateVHACD(); // Create a synchronous (blocking) implementation of V-HACD
  783. IVHACD* CreateVHACD_ASYNC(); // Create an asynchronous (non-blocking) implementation of V-HACD
  784. } // namespace VHACD
  785. #if ENABLE_VHACD_IMPLEMENTATION
  786. #include <assert.h>
  787. #ifndef _INC_MATH
  788. #include <math.h>
  789. #endif
  790. #ifndef _INC_STDLIB
  791. #include <stdlib.h>
  792. #endif
  793. #ifndef _INC_STRING
  794. #include <string.h>
  795. #endif
  796. #ifndef _INC_FLOAT
  797. #include <float.h>
  798. #endif
  799. #ifndef _INC_LIMITS
  800. #include <limits.h>
  801. #endif
  802. #ifndef _ARRAY_
  803. #include <array>
  804. #endif
  805. #ifndef _ATOMIC_
  806. #include <atomic>
  807. #endif
  808. #ifndef _CHRONO_
  809. #include <chrono>
  810. #endif
  811. #ifndef _CONDITION_VARIABLE_
  812. #include <condition_variable>
  813. #endif
  814. #ifndef _DEQUE_
  815. #include <deque>
  816. #endif
  817. #ifndef _FUTURE_
  818. #include <future>
  819. #endif
  820. #ifndef _IOSTREAM_
  821. #include <iostream>
  822. #endif
  823. #ifndef _LIST_
  824. #include <list>
  825. #endif
  826. #ifndef _MEMORY_
  827. #include <memory>
  828. #endif
  829. #ifndef _MUTEX_
  830. #include <mutex>
  831. #endif
  832. #ifndef _QUEUE_
  833. #include <queue>
  834. #endif
  835. #ifndef _THREAD_
  836. #include <thread>
  837. #endif
  838. #ifndef _UNORDERED_MAP_
  839. #include <unordered_map>
  840. #endif
  841. #ifndef _UNORDERED_SET_
  842. #include <unordered_set>
  843. #endif
  844. #ifndef _UTILITY_
  845. #include <utility>
  846. #endif
  847. #ifndef _VECTOR_
  848. #include <vector>
  849. #endif
  850. #ifdef _MSC_VER
  851. #pragma warning(push)
  852. #pragma warning(disable:4100 4127 4189 4244 4456 4701 4702 4996)
  853. #endif // _MSC_VER
  854. #ifdef __GNUC__
  855. #pragma GCC diagnostic push
  856. // Minimum set of warnings used for cleanup
  857. // #pragma GCC diagnostic warning "-Wall"
  858. // #pragma GCC diagnostic warning "-Wextra"
  859. // #pragma GCC diagnostic warning "-Wpedantic"
  860. // #pragma GCC diagnostic warning "-Wold-style-cast"
  861. // #pragma GCC diagnostic warning "-Wnon-virtual-dtor"
  862. // #pragma GCC diagnostic warning "-Wshadow"
  863. #endif // __GNUC__
  864. // Scoped Timer
  865. namespace VHACD {
  866. class Timer
  867. {
  868. public:
  869. Timer()
  870. : m_startTime(std::chrono::high_resolution_clock::now())
  871. {
  872. }
  873. void Reset()
  874. {
  875. m_startTime = std::chrono::high_resolution_clock::now();
  876. }
  877. double GetElapsedSeconds()
  878. {
  879. auto s = PeekElapsedSeconds();
  880. Reset();
  881. return s;
  882. }
  883. double PeekElapsedSeconds()
  884. {
  885. auto now = std::chrono::high_resolution_clock::now();
  886. std::chrono::duration<double> diff = now - m_startTime;
  887. return diff.count();
  888. }
  889. private:
  890. std::chrono::time_point<std::chrono::high_resolution_clock> m_startTime;
  891. };
  892. class ScopedTime
  893. {
  894. public:
  895. ScopedTime(const char* action,
  896. VHACD::IVHACD::IUserLogger* logger)
  897. : m_action(action)
  898. , m_logger(logger)
  899. {
  900. m_timer.Reset();
  901. }
  902. ~ScopedTime()
  903. {
  904. double dtime = m_timer.GetElapsedSeconds();
  905. if( m_logger )
  906. {
  907. char scratch[512];
  908. snprintf(scratch,
  909. sizeof(scratch),"%s took %0.5f seconds",
  910. m_action,
  911. dtime);
  912. m_logger->Log(scratch);
  913. }
  914. }
  915. const char* m_action{ nullptr };
  916. Timer m_timer;
  917. VHACD::IVHACD::IUserLogger* m_logger{ nullptr };
  918. };
  919. BoundsAABB::BoundsAABB(const std::vector<VHACD::Vertex>& points)
  920. : m_min(points[0])
  921. , m_max(points[0])
  922. {
  923. for (uint32_t i = 1; i < points.size(); ++i)
  924. {
  925. const VHACD::Vertex& p = points[i];
  926. m_min = m_min.CWiseMin(p);
  927. m_max = m_max.CWiseMax(p);
  928. }
  929. }
  930. BoundsAABB::BoundsAABB(const VHACD::Vect3& min,
  931. const VHACD::Vect3& max)
  932. : m_min(min)
  933. , m_max(max)
  934. {
  935. }
  936. BoundsAABB BoundsAABB::Union(const BoundsAABB& b)
  937. {
  938. return BoundsAABB(GetMin().CWiseMin(b.GetMin()),
  939. GetMax().CWiseMax(b.GetMax()));
  940. }
  941. bool VHACD::BoundsAABB::Intersects(const VHACD::BoundsAABB& b) const
  942. {
  943. if ( ( GetMin().GetX() > b.GetMax().GetX())
  944. || (b.GetMin().GetX() > GetMax().GetX()))
  945. return false;
  946. if ( ( GetMin().GetY() > b.GetMax().GetY())
  947. || (b.GetMin().GetY() > GetMax().GetY()))
  948. return false;
  949. if ( ( GetMin().GetZ() > b.GetMax().GetZ())
  950. || (b.GetMin().GetZ() > GetMax().GetZ()))
  951. return false;
  952. return true;
  953. }
  954. double BoundsAABB::SurfaceArea() const
  955. {
  956. VHACD::Vect3 d = GetMax() - GetMin();
  957. return double(2.0) * (d.GetX() * d.GetY() + d.GetX() * d.GetZ() + d.GetY() * d.GetZ());
  958. }
  959. double VHACD::BoundsAABB::Volume() const
  960. {
  961. VHACD::Vect3 d = GetMax() - GetMin();
  962. return d.GetX() * d.GetY() * d.GetZ();
  963. }
  964. BoundsAABB VHACD::BoundsAABB::Inflate(double ratio) const
  965. {
  966. double inflate = (GetMin() - GetMax()).GetNorm() * double(0.5) * ratio;
  967. return BoundsAABB(GetMin() - inflate,
  968. GetMax() + inflate);
  969. }
  970. VHACD::Vect3 VHACD::BoundsAABB::ClosestPoint(const VHACD::Vect3& p) const
  971. {
  972. return p.CWiseMax(GetMin()).CWiseMin(GetMax());
  973. }
  974. VHACD::Vect3& VHACD::BoundsAABB::GetMin()
  975. {
  976. return m_min;
  977. }
  978. VHACD::Vect3& VHACD::BoundsAABB::GetMax()
  979. {
  980. return m_max;
  981. }
  982. inline const VHACD::Vect3& VHACD::BoundsAABB::GetMin() const
  983. {
  984. return m_min;
  985. }
  986. const VHACD::Vect3& VHACD::BoundsAABB::GetMax() const
  987. {
  988. return m_max;
  989. }
  990. VHACD::Vect3 VHACD::BoundsAABB::GetSize() const
  991. {
  992. return GetMax() - GetMin();
  993. }
  994. VHACD::Vect3 VHACD::BoundsAABB::GetCenter() const
  995. {
  996. return (GetMin() + GetMax()) * double(0.5);
  997. }
  998. /*
  999. * Relies on three way comparison, which std::sort doesn't use
  1000. */
  1001. template <class T, class dCompareKey>
  1002. void Sort(T* const array, int elements)
  1003. {
  1004. const int batchSize = 8;
  1005. int stack[1024][2];
  1006. stack[0][0] = 0;
  1007. stack[0][1] = elements - 1;
  1008. int stackIndex = 1;
  1009. const dCompareKey comparator;
  1010. while (stackIndex)
  1011. {
  1012. stackIndex--;
  1013. int lo = stack[stackIndex][0];
  1014. int hi = stack[stackIndex][1];
  1015. if ((hi - lo) > batchSize)
  1016. {
  1017. int mid = (lo + hi) >> 1;
  1018. if (comparator.Compare(array[lo], array[mid]) > 0)
  1019. {
  1020. std::swap(array[lo],
  1021. array[mid]);
  1022. }
  1023. if (comparator.Compare(array[mid], array[hi]) > 0)
  1024. {
  1025. std::swap(array[mid],
  1026. array[hi]);
  1027. }
  1028. if (comparator.Compare(array[lo], array[mid]) > 0)
  1029. {
  1030. std::swap(array[lo],
  1031. array[mid]);
  1032. }
  1033. int i = lo + 1;
  1034. int j = hi - 1;
  1035. const T pivot(array[mid]);
  1036. do
  1037. {
  1038. while (comparator.Compare(array[i], pivot) < 0)
  1039. {
  1040. i++;
  1041. }
  1042. while (comparator.Compare(array[j], pivot) > 0)
  1043. {
  1044. j--;
  1045. }
  1046. if (i <= j)
  1047. {
  1048. std::swap(array[i],
  1049. array[j]);
  1050. i++;
  1051. j--;
  1052. }
  1053. } while (i <= j);
  1054. if (i < hi)
  1055. {
  1056. stack[stackIndex][0] = i;
  1057. stack[stackIndex][1] = hi;
  1058. stackIndex++;
  1059. }
  1060. if (lo < j)
  1061. {
  1062. stack[stackIndex][0] = lo;
  1063. stack[stackIndex][1] = j;
  1064. stackIndex++;
  1065. }
  1066. assert(stackIndex < int(sizeof(stack) / (2 * sizeof(stack[0][0]))));
  1067. }
  1068. }
  1069. int stride = batchSize + 1;
  1070. if (elements < stride)
  1071. {
  1072. stride = elements;
  1073. }
  1074. for (int i = 1; i < stride; ++i)
  1075. {
  1076. if (comparator.Compare(array[0], array[i]) > 0)
  1077. {
  1078. std::swap(array[0],
  1079. array[i]);
  1080. }
  1081. }
  1082. for (int i = 1; i < elements; ++i)
  1083. {
  1084. int j = i;
  1085. const T tmp(array[i]);
  1086. for (; comparator.Compare(array[j - 1], tmp) > 0; --j)
  1087. {
  1088. assert(j > 0);
  1089. array[j] = array[j - 1];
  1090. }
  1091. array[j] = tmp;
  1092. }
  1093. }
  1094. /*
  1095. Maintaining comment due to attribution
  1096. Purpose:
  1097. TRIANGLE_AREA_3D computes the area of a triangle in 3D.
  1098. Modified:
  1099. 22 April 1999
  1100. Author:
  1101. John Burkardt
  1102. Parameters:
  1103. Input, double X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, the (getX,getY,getZ)
  1104. coordinates of the corners of the triangle.
  1105. Output, double TRIANGLE_AREA_3D, the area of the triangle.
  1106. */
  1107. double ComputeArea(const VHACD::Vect3& p1,
  1108. const VHACD::Vect3& p2,
  1109. const VHACD::Vect3& p3)
  1110. {
  1111. /*
  1112. Find the projection of (P3-P1) onto (P2-P1).
  1113. */
  1114. double base = (p2 - p1).GetNorm();
  1115. /*
  1116. The height of the triangle is the length of (P3-P1) after its
  1117. projection onto (P2-P1) has been subtracted.
  1118. */
  1119. double height;
  1120. if (base == double(0.0))
  1121. {
  1122. height = double(0.0);
  1123. }
  1124. else
  1125. {
  1126. double dot = (p3 - p1).Dot(p2 - p1);
  1127. double alpha = dot / (base * base);
  1128. VHACD::Vect3 a = p3 - p1 - alpha * (p2 - p1);
  1129. height = a.GetNorm();
  1130. }
  1131. return double(0.5) * base * height;
  1132. }
  1133. bool ComputeCentroid(const std::vector<VHACD::Vertex>& points,
  1134. const std::vector<VHACD::Triangle>& indices,
  1135. VHACD::Vect3& center)
  1136. {
  1137. bool ret = false;
  1138. if (points.size())
  1139. {
  1140. center = VHACD::Vect3(0);
  1141. VHACD::Vect3 numerator(0);
  1142. double denominator = 0;
  1143. for (uint32_t i = 0; i < indices.size(); i++)
  1144. {
  1145. uint32_t i1 = indices[i].mI0;
  1146. uint32_t i2 = indices[i].mI1;
  1147. uint32_t i3 = indices[i].mI2;
  1148. const VHACD::Vect3& p1 = points[i1];
  1149. const VHACD::Vect3& p2 = points[i2];
  1150. const VHACD::Vect3& p3 = points[i3];
  1151. // Compute the average of the sum of the three positions
  1152. VHACD::Vect3 sum = (p1 + p2 + p3) / 3;
  1153. // Compute the area of this triangle
  1154. double area = ComputeArea(p1,
  1155. p2,
  1156. p3);
  1157. numerator += (sum * area);
  1158. denominator += area;
  1159. }
  1160. double recip = 1 / denominator;
  1161. center = numerator * recip;
  1162. ret = true;
  1163. }
  1164. return ret;
  1165. }
  1166. double Determinant3x3(const std::array<VHACD::Vect3, 3>& matrix,
  1167. double& error)
  1168. {
  1169. double det = double(0.0);
  1170. error = double(0.0);
  1171. double a01xa12 = matrix[0].GetY() * matrix[1].GetZ();
  1172. double a02xa11 = matrix[0].GetZ() * matrix[1].GetY();
  1173. error += (std::abs(a01xa12) + std::abs(a02xa11)) * std::abs(matrix[2].GetX());
  1174. det += (a01xa12 - a02xa11) * matrix[2].GetX();
  1175. double a00xa12 = matrix[0].GetX() * matrix[1].GetZ();
  1176. double a02xa10 = matrix[0].GetZ() * matrix[1].GetX();
  1177. error += (std::abs(a00xa12) + std::abs(a02xa10)) * std::abs(matrix[2].GetY());
  1178. det -= (a00xa12 - a02xa10) * matrix[2].GetY();
  1179. double a00xa11 = matrix[0].GetX() * matrix[1].GetY();
  1180. double a01xa10 = matrix[0].GetY() * matrix[1].GetX();
  1181. error += (std::abs(a00xa11) + std::abs(a01xa10)) * std::abs(matrix[2].GetZ());
  1182. det += (a00xa11 - a01xa10) * matrix[2].GetZ();
  1183. return det;
  1184. }
  1185. double ComputeMeshVolume(const std::vector<VHACD::Vertex>& vertices,
  1186. const std::vector<VHACD::Triangle>& indices)
  1187. {
  1188. double volume = 0;
  1189. for (uint32_t i = 0; i < indices.size(); i++)
  1190. {
  1191. const std::array<VHACD::Vect3, 3> m = {
  1192. vertices[indices[i].mI0],
  1193. vertices[indices[i].mI1],
  1194. vertices[indices[i].mI2]
  1195. };
  1196. double placeholder;
  1197. volume += Determinant3x3(m,
  1198. placeholder);
  1199. }
  1200. volume *= (double(1.0) / double(6.0));
  1201. if (volume < 0)
  1202. volume *= -1;
  1203. return volume;
  1204. }
  1205. /*
  1206. * To minimize memory allocations while maintaining pointer stability.
  1207. * Used in KdTreeNode and ConvexHull, as both use tree data structures that rely on pointer stability
  1208. * Neither rely on random access or iteration
  1209. * They just dump elements into a memory pool, then refer to pointers to the elements
  1210. * All elements are default constructed in NodeStorage's m_nodes array
  1211. */
  1212. template <typename T, std::size_t MaxBundleSize = 1024>
  1213. class NodeBundle
  1214. {
  1215. struct NodeStorage {
  1216. bool IsFull() const;
  1217. T& GetNextNode();
  1218. std::size_t m_index;
  1219. std::array<T, MaxBundleSize> m_nodes;
  1220. };
  1221. std::list<NodeStorage> m_list;
  1222. typename std::list<NodeStorage>::iterator m_head{ m_list.end() };
  1223. public:
  1224. T& GetNextNode();
  1225. T& GetFirstNode();
  1226. void Clear();
  1227. };
  1228. template <typename T, std::size_t MaxBundleSize>
  1229. bool NodeBundle<T, MaxBundleSize>::NodeStorage::IsFull() const
  1230. {
  1231. return m_index == MaxBundleSize;
  1232. }
  1233. template <typename T, std::size_t MaxBundleSize>
  1234. T& NodeBundle<T, MaxBundleSize>::NodeStorage::GetNextNode()
  1235. {
  1236. assert(m_index < MaxBundleSize);
  1237. T& ret = m_nodes[m_index];
  1238. m_index++;
  1239. return ret;
  1240. }
  1241. template <typename T, std::size_t MaxBundleSize>
  1242. T& NodeBundle<T, MaxBundleSize>::GetNextNode()
  1243. {
  1244. /*
  1245. * || short circuits, so doesn't dereference if m_bundle == m_bundleHead.end()
  1246. */
  1247. if ( m_head == m_list.end()
  1248. || m_head->IsFull())
  1249. {
  1250. m_head = m_list.emplace(m_list.end());
  1251. }
  1252. return m_head->GetNextNode();
  1253. }
  1254. template <typename T, std::size_t MaxBundleSize>
  1255. T& NodeBundle<T, MaxBundleSize>::GetFirstNode()
  1256. {
  1257. assert(m_head != m_list.end());
  1258. return m_list.front().m_nodes[0];
  1259. }
  1260. template <typename T, std::size_t MaxBundleSize>
  1261. void NodeBundle<T, MaxBundleSize>::Clear()
  1262. {
  1263. m_list.clear();
  1264. }
  1265. /*
  1266. * Returns index of highest set bit in x
  1267. */
  1268. inline int dExp2(int x)
  1269. {
  1270. int exp;
  1271. for (exp = -1; x; x >>= 1)
  1272. {
  1273. exp++;
  1274. }
  1275. return exp;
  1276. }
  1277. /*
  1278. * Reverses the order of the bits in v and returns the result
  1279. * Does not put fill any of the bits higher than the highest bit in v
  1280. * Only used to calculate index of ndNormalMap::m_normal when tessellating a triangle
  1281. */
  1282. inline int dBitReversal(int v,
  1283. int base)
  1284. {
  1285. int x = 0;
  1286. int power = dExp2(base) - 1;
  1287. do
  1288. {
  1289. x += (v & 1) << power;
  1290. v >>= 1;
  1291. power--;
  1292. } while (v);
  1293. return x;
  1294. }
  1295. class Googol
  1296. {
  1297. #define VHACD_GOOGOL_SIZE 4
  1298. public:
  1299. Googol() = default;
  1300. Googol(double value);
  1301. operator double() const;
  1302. Googol operator+(const Googol &A) const;
  1303. Googol operator-(const Googol &A) const;
  1304. Googol operator*(const Googol &A) const;
  1305. Googol operator/ (const Googol &A) const;
  1306. Googol& operator+= (const Googol &A);
  1307. Googol& operator-= (const Googol &A);
  1308. bool operator>(const Googol &A) const;
  1309. bool operator>=(const Googol &A) const;
  1310. bool operator<(const Googol &A) const;
  1311. bool operator<=(const Googol &A) const;
  1312. bool operator==(const Googol &A) const;
  1313. bool operator!=(const Googol &A) const;
  1314. Googol Abs() const;
  1315. Googol Floor() const;
  1316. Googol InvSqrt() const;
  1317. Googol Sqrt() const;
  1318. void ToString(char* const string) const;
  1319. private:
  1320. void NegateMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const;
  1321. void CopySignedMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const;
  1322. int NormalizeMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const;
  1323. void ShiftRightMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa,
  1324. int bits) const;
  1325. uint64_t CheckCarrier(uint64_t a, uint64_t b) const;
  1326. int LeadingZeros(uint64_t a) const;
  1327. void ExtendedMultiply(uint64_t a,
  1328. uint64_t b,
  1329. uint64_t& high,
  1330. uint64_t& low) const;
  1331. void ScaleMantissa(uint64_t* out,
  1332. uint64_t scale) const;
  1333. int m_sign{ 0 };
  1334. int m_exponent{ 0 };
  1335. std::array<uint64_t, VHACD_GOOGOL_SIZE> m_mantissa{ 0 };
  1336. public:
  1337. static Googol m_zero;
  1338. static Googol m_one;
  1339. static Googol m_two;
  1340. static Googol m_three;
  1341. static Googol m_half;
  1342. };
  1343. Googol Googol::m_zero(double(0.0));
  1344. Googol Googol::m_one(double(1.0));
  1345. Googol Googol::m_two(double(2.0));
  1346. Googol Googol::m_three(double(3.0));
  1347. Googol Googol::m_half(double(0.5));
  1348. Googol::Googol(double value)
  1349. {
  1350. int exp;
  1351. double mantissa = fabs(frexp(value, &exp));
  1352. m_exponent = exp;
  1353. m_sign = (value >= 0) ? 0 : 1;
  1354. m_mantissa[0] = uint64_t(double(uint64_t(1) << 62) * mantissa);
  1355. }
  1356. Googol::operator double() const
  1357. {
  1358. double mantissa = (double(1.0) / double(uint64_t(1) << 62)) * double(m_mantissa[0]);
  1359. mantissa = ldexp(mantissa, m_exponent) * (m_sign ? double(-1.0) : double(1.0));
  1360. return mantissa;
  1361. }
  1362. Googol Googol::operator+(const Googol &A) const
  1363. {
  1364. Googol tmp;
  1365. if (m_mantissa[0] && A.m_mantissa[0])
  1366. {
  1367. std::array<uint64_t, VHACD_GOOGOL_SIZE> mantissa0;
  1368. std::array<uint64_t, VHACD_GOOGOL_SIZE> mantissa1;
  1369. std::array<uint64_t, VHACD_GOOGOL_SIZE> mantissa;
  1370. CopySignedMantissa(mantissa0);
  1371. A.CopySignedMantissa(mantissa1);
  1372. int exponentDiff = m_exponent - A.m_exponent;
  1373. int exponent = m_exponent;
  1374. if (exponentDiff > 0)
  1375. {
  1376. ShiftRightMantissa(mantissa1,
  1377. exponentDiff);
  1378. }
  1379. else if (exponentDiff < 0)
  1380. {
  1381. exponent = A.m_exponent;
  1382. ShiftRightMantissa(mantissa0,
  1383. -exponentDiff);
  1384. }
  1385. uint64_t carrier = 0;
  1386. for (int i = VHACD_GOOGOL_SIZE - 1; i >= 0; i--)
  1387. {
  1388. uint64_t m0 = mantissa0[i];
  1389. uint64_t m1 = mantissa1[i];
  1390. mantissa[i] = m0 + m1 + carrier;
  1391. carrier = CheckCarrier(m0, m1) | CheckCarrier(m0 + m1, carrier);
  1392. }
  1393. int sign = 0;
  1394. if (int64_t(mantissa[0]) < 0)
  1395. {
  1396. sign = 1;
  1397. NegateMantissa(mantissa);
  1398. }
  1399. int bits = NormalizeMantissa(mantissa);
  1400. if (bits <= (-64 * VHACD_GOOGOL_SIZE))
  1401. {
  1402. tmp.m_sign = 0;
  1403. tmp.m_exponent = 0;
  1404. }
  1405. else
  1406. {
  1407. tmp.m_sign = sign;
  1408. tmp.m_exponent = int(exponent + bits);
  1409. }
  1410. tmp.m_mantissa = mantissa;
  1411. }
  1412. else if (A.m_mantissa[0])
  1413. {
  1414. tmp = A;
  1415. }
  1416. else
  1417. {
  1418. tmp = *this;
  1419. }
  1420. return tmp;
  1421. }
  1422. Googol Googol::operator-(const Googol &A) const
  1423. {
  1424. Googol tmp(A);
  1425. tmp.m_sign = !tmp.m_sign;
  1426. return *this + tmp;
  1427. }
  1428. Googol Googol::operator*(const Googol &A) const
  1429. {
  1430. if (m_mantissa[0] && A.m_mantissa[0])
  1431. {
  1432. std::array<uint64_t, VHACD_GOOGOL_SIZE * 2> mantissaAcc{ 0 };
  1433. for (int i = VHACD_GOOGOL_SIZE - 1; i >= 0; i--)
  1434. {
  1435. uint64_t a = m_mantissa[i];
  1436. if (a)
  1437. {
  1438. uint64_t mantissaScale[2 * VHACD_GOOGOL_SIZE] = { 0 };
  1439. A.ScaleMantissa(&mantissaScale[i], a);
  1440. uint64_t carrier = 0;
  1441. for (int j = 0; j < 2 * VHACD_GOOGOL_SIZE; j++)
  1442. {
  1443. const int k = 2 * VHACD_GOOGOL_SIZE - 1 - j;
  1444. uint64_t m0 = mantissaAcc[k];
  1445. uint64_t m1 = mantissaScale[k];
  1446. mantissaAcc[k] = m0 + m1 + carrier;
  1447. carrier = CheckCarrier(m0, m1) | CheckCarrier(m0 + m1, carrier);
  1448. }
  1449. }
  1450. }
  1451. uint64_t carrier = 0;
  1452. int bits = LeadingZeros(mantissaAcc[0]) - 2;
  1453. for (int i = 0; i < 2 * VHACD_GOOGOL_SIZE; i++)
  1454. {
  1455. const int k = 2 * VHACD_GOOGOL_SIZE - 1 - i;
  1456. uint64_t a = mantissaAcc[k];
  1457. mantissaAcc[k] = (a << uint64_t(bits)) | carrier;
  1458. carrier = a >> uint64_t(64 - bits);
  1459. }
  1460. int exp = m_exponent + A.m_exponent - (bits - 2);
  1461. Googol tmp;
  1462. tmp.m_sign = m_sign ^ A.m_sign;
  1463. tmp.m_exponent = exp;
  1464. for (std::size_t i = 0; i < tmp.m_mantissa.size(); ++i)
  1465. {
  1466. tmp.m_mantissa[i] = mantissaAcc[i];
  1467. }
  1468. return tmp;
  1469. }
  1470. return Googol(double(0.0));
  1471. }
  1472. Googol Googol::operator/(const Googol &A) const
  1473. {
  1474. Googol tmp(double(1.0) / A);
  1475. tmp = tmp * (m_two - A * tmp);
  1476. tmp = tmp * (m_two - A * tmp);
  1477. bool test = false;
  1478. int passes = 0;
  1479. do
  1480. {
  1481. passes++;
  1482. Googol tmp0(tmp);
  1483. tmp = tmp * (m_two - A * tmp);
  1484. test = tmp0 == tmp;
  1485. } while (test && (passes < (2 * VHACD_GOOGOL_SIZE)));
  1486. return (*this) * tmp;
  1487. }
  1488. Googol& Googol::operator+=(const Googol &A)
  1489. {
  1490. *this = *this + A;
  1491. return *this;
  1492. }
  1493. Googol& Googol::operator-=(const Googol &A)
  1494. {
  1495. *this = *this - A;
  1496. return *this;
  1497. }
  1498. bool Googol::operator>(const Googol &A) const
  1499. {
  1500. Googol tmp(*this - A);
  1501. return double(tmp) > double(0.0);
  1502. }
  1503. bool Googol::operator>=(const Googol &A) const
  1504. {
  1505. Googol tmp(*this - A);
  1506. return double(tmp) >= double(0.0);
  1507. }
  1508. bool Googol::operator<(const Googol &A) const
  1509. {
  1510. Googol tmp(*this - A);
  1511. return double(tmp) < double(0.0);
  1512. }
  1513. bool Googol::operator<=(const Googol &A) const
  1514. {
  1515. Googol tmp(*this - A);
  1516. return double(tmp) <= double(0.0);
  1517. }
  1518. bool Googol::operator==(const Googol &A) const
  1519. {
  1520. return m_sign == A.m_sign
  1521. && m_exponent == A.m_exponent
  1522. && m_mantissa == A.m_mantissa;
  1523. }
  1524. bool Googol::operator!=(const Googol &A) const
  1525. {
  1526. return !(*this == A);
  1527. }
  1528. Googol Googol::Abs() const
  1529. {
  1530. Googol tmp(*this);
  1531. tmp.m_sign = 0;
  1532. return tmp;
  1533. }
  1534. Googol Googol::Floor() const
  1535. {
  1536. if (m_exponent < 1)
  1537. {
  1538. return Googol(double(0.0));
  1539. }
  1540. int bits = m_exponent + 2;
  1541. int start = 0;
  1542. while (bits >= 64)
  1543. {
  1544. bits -= 64;
  1545. start++;
  1546. }
  1547. Googol tmp(*this);
  1548. for (int i = VHACD_GOOGOL_SIZE - 1; i > start; i--)
  1549. {
  1550. tmp.m_mantissa[i] = 0;
  1551. }
  1552. // some compilers do no like this and I do not know why is that
  1553. //uint64_t mask = (-1LL) << (64 - bits);
  1554. uint64_t mask(~0ULL);
  1555. mask <<= (64 - bits);
  1556. tmp.m_mantissa[start] &= mask;
  1557. return tmp;
  1558. }
  1559. Googol Googol::InvSqrt() const
  1560. {
  1561. const Googol& me = *this;
  1562. Googol x(double(1.0) / sqrt(me));
  1563. int test = 0;
  1564. int passes = 0;
  1565. do
  1566. {
  1567. passes++;
  1568. Googol tmp(x);
  1569. x = m_half * x * (m_three - me * x * x);
  1570. test = (x != tmp);
  1571. } while (test && (passes < (2 * VHACD_GOOGOL_SIZE)));
  1572. return x;
  1573. }
  1574. Googol Googol::Sqrt() const
  1575. {
  1576. return *this * InvSqrt();
  1577. }
  1578. void Googol::ToString(char* const string) const
  1579. {
  1580. Googol tmp(*this);
  1581. Googol base(double(10.0));
  1582. while (double(tmp) > double(1.0))
  1583. {
  1584. tmp = tmp / base;
  1585. }
  1586. int index = 0;
  1587. while (tmp.m_mantissa[0])
  1588. {
  1589. tmp = tmp * base;
  1590. Googol digit(tmp.Floor());
  1591. tmp -= digit;
  1592. double val = digit;
  1593. string[index] = char(val) + '0';
  1594. index++;
  1595. }
  1596. string[index] = 0;
  1597. }
  1598. void Googol::NegateMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const
  1599. {
  1600. uint64_t carrier = 1;
  1601. for (size_t i = mantissa.size() - 1; i >= 0 && i < mantissa.size(); i--)
  1602. {
  1603. uint64_t a = ~mantissa[i] + carrier;
  1604. if (a)
  1605. {
  1606. carrier = 0;
  1607. }
  1608. mantissa[i] = a;
  1609. }
  1610. }
  1611. void Googol::CopySignedMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const
  1612. {
  1613. mantissa = m_mantissa;
  1614. if (m_sign)
  1615. {
  1616. NegateMantissa(mantissa);
  1617. }
  1618. }
  1619. int Googol::NormalizeMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa) const
  1620. {
  1621. int bits = 0;
  1622. if (int64_t(mantissa[0] * 2) < 0)
  1623. {
  1624. bits = 1;
  1625. ShiftRightMantissa(mantissa, 1);
  1626. }
  1627. else
  1628. {
  1629. while (!mantissa[0] && bits > (-64 * VHACD_GOOGOL_SIZE))
  1630. {
  1631. bits -= 64;
  1632. for (int i = 1; i < VHACD_GOOGOL_SIZE; i++) {
  1633. mantissa[i - 1] = mantissa[i];
  1634. }
  1635. mantissa[VHACD_GOOGOL_SIZE - 1] = 0;
  1636. }
  1637. if (bits > (-64 * VHACD_GOOGOL_SIZE))
  1638. {
  1639. int n = LeadingZeros(mantissa[0]) - 2;
  1640. if (n > 0)
  1641. {
  1642. uint64_t carrier = 0;
  1643. for (int i = VHACD_GOOGOL_SIZE - 1; i >= 0; i--)
  1644. {
  1645. uint64_t a = mantissa[i];
  1646. mantissa[i] = (a << n) | carrier;
  1647. carrier = a >> (64 - n);
  1648. }
  1649. bits -= n;
  1650. }
  1651. else if (n < 0)
  1652. {
  1653. // this is very rare but it does happens, whee the leading zeros of the mantissa is an exact multiple of 64
  1654. uint64_t carrier = 0;
  1655. int shift = -n;
  1656. for (int i = 0; i < VHACD_GOOGOL_SIZE; i++)
  1657. {
  1658. uint64_t a = mantissa[i];
  1659. mantissa[i] = (a >> shift) | carrier;
  1660. carrier = a << (64 - shift);
  1661. }
  1662. bits -= n;
  1663. }
  1664. }
  1665. }
  1666. return bits;
  1667. }
  1668. void Googol::ShiftRightMantissa(std::array<uint64_t, VHACD_GOOGOL_SIZE>& mantissa,
  1669. int bits) const
  1670. {
  1671. uint64_t carrier = 0;
  1672. if (int64_t(mantissa[0]) < int64_t(0))
  1673. {
  1674. carrier = uint64_t(-1);
  1675. }
  1676. while (bits >= 64)
  1677. {
  1678. for (int i = VHACD_GOOGOL_SIZE - 2; i >= 0; i--)
  1679. {
  1680. mantissa[i + 1] = mantissa[i];
  1681. }
  1682. mantissa[0] = carrier;
  1683. bits -= 64;
  1684. }
  1685. if (bits > 0)
  1686. {
  1687. carrier <<= (64 - bits);
  1688. for (int i = 0; i < VHACD_GOOGOL_SIZE; i++)
  1689. {
  1690. uint64_t a = mantissa[i];
  1691. mantissa[i] = (a >> bits) | carrier;
  1692. carrier = a << (64 - bits);
  1693. }
  1694. }
  1695. }
  1696. uint64_t Googol::CheckCarrier(uint64_t a, uint64_t b) const
  1697. {
  1698. return ((uint64_t(-1) - b) < a) ? uint64_t(1) : 0;
  1699. }
  1700. int Googol::LeadingZeros(uint64_t a) const
  1701. {
  1702. #define VHACD_COUNTBIT(mask, add) \
  1703. do { \
  1704. uint64_t test = a & mask; \
  1705. n += test ? 0 : add; \
  1706. a = test ? test : (a & ~mask); \
  1707. } while (false)
  1708. int n = 0;
  1709. VHACD_COUNTBIT(0xffffffff00000000LL, 32);
  1710. VHACD_COUNTBIT(0xffff0000ffff0000LL, 16);
  1711. VHACD_COUNTBIT(0xff00ff00ff00ff00LL, 8);
  1712. VHACD_COUNTBIT(0xf0f0f0f0f0f0f0f0LL, 4);
  1713. VHACD_COUNTBIT(0xccccccccccccccccLL, 2);
  1714. VHACD_COUNTBIT(0xaaaaaaaaaaaaaaaaLL, 1);
  1715. return n;
  1716. }
  1717. void Googol::ExtendedMultiply(uint64_t a,
  1718. uint64_t b,
  1719. uint64_t& high,
  1720. uint64_t& low) const
  1721. {
  1722. uint64_t bLow = b & 0xffffffff;
  1723. uint64_t bHigh = b >> 32;
  1724. uint64_t aLow = a & 0xffffffff;
  1725. uint64_t aHigh = a >> 32;
  1726. uint64_t l = bLow * aLow;
  1727. uint64_t c1 = bHigh * aLow;
  1728. uint64_t c2 = bLow * aHigh;
  1729. uint64_t m = c1 + c2;
  1730. uint64_t carrier = CheckCarrier(c1, c2) << 32;
  1731. uint64_t h = bHigh * aHigh + carrier;
  1732. uint64_t ml = m << 32;
  1733. uint64_t ll = l + ml;
  1734. uint64_t mh = (m >> 32) + CheckCarrier(l, ml);
  1735. uint64_t hh = h + mh;
  1736. low = ll;
  1737. high = hh;
  1738. }
  1739. void Googol::ScaleMantissa(uint64_t* dst,
  1740. uint64_t scale) const
  1741. {
  1742. uint64_t carrier = 0;
  1743. for (int i = VHACD_GOOGOL_SIZE - 1; i >= 0; i--)
  1744. {
  1745. if (m_mantissa[i])
  1746. {
  1747. uint64_t low;
  1748. uint64_t high;
  1749. ExtendedMultiply(scale,
  1750. m_mantissa[i],
  1751. high,
  1752. low);
  1753. uint64_t acc = low + carrier;
  1754. carrier = CheckCarrier(low,
  1755. carrier);
  1756. carrier += high;
  1757. dst[i + 1] = acc;
  1758. }
  1759. else
  1760. {
  1761. dst[i + 1] = carrier;
  1762. carrier = 0;
  1763. }
  1764. }
  1765. dst[0] = carrier;
  1766. }
  1767. Googol Determinant3x3(const std::array<VHACD::Vector3<Googol>, 3>& matrix)
  1768. {
  1769. Googol det = double(0.0);
  1770. Googol a01xa12 = matrix[0].GetY() * matrix[1].GetZ();
  1771. Googol a02xa11 = matrix[0].GetZ() * matrix[1].GetY();
  1772. det += (a01xa12 - a02xa11) * matrix[2].GetX();
  1773. Googol a00xa12 = matrix[0].GetX() * matrix[1].GetZ();
  1774. Googol a02xa10 = matrix[0].GetZ() * matrix[1].GetX();
  1775. det -= (a00xa12 - a02xa10) * matrix[2].GetY();
  1776. Googol a00xa11 = matrix[0].GetX() * matrix[1].GetY();
  1777. Googol a01xa10 = matrix[0].GetY() * matrix[1].GetX();
  1778. det += (a00xa11 - a01xa10) * matrix[2].GetZ();
  1779. return det;
  1780. }
  1781. class HullPlane : public VHACD::Vect3
  1782. {
  1783. public:
  1784. HullPlane(const HullPlane&) = default;
  1785. HullPlane(double x,
  1786. double y,
  1787. double z,
  1788. double w);
  1789. HullPlane(const VHACD::Vect3& p,
  1790. double w);
  1791. HullPlane(const VHACD::Vect3& p0,
  1792. const VHACD::Vect3& p1,
  1793. const VHACD::Vect3& p2);
  1794. HullPlane Scale(double s) const;
  1795. HullPlane& operator=(const HullPlane& rhs);
  1796. double Evalue(const VHACD::Vect3 &point) const;
  1797. double& GetW();
  1798. const double& GetW() const;
  1799. private:
  1800. double m_w;
  1801. };
  1802. HullPlane::HullPlane(double x,
  1803. double y,
  1804. double z,
  1805. double w)
  1806. : VHACD::Vect3(x, y, z)
  1807. , m_w(w)
  1808. {
  1809. }
  1810. HullPlane::HullPlane(const VHACD::Vect3& p,
  1811. double w)
  1812. : VHACD::Vect3(p)
  1813. , m_w(w)
  1814. {
  1815. }
  1816. HullPlane::HullPlane(const VHACD::Vect3& p0,
  1817. const VHACD::Vect3& p1,
  1818. const VHACD::Vect3& p2)
  1819. : VHACD::Vect3((p1 - p0).Cross(p2 - p0))
  1820. , m_w(-Dot(p0))
  1821. {
  1822. }
  1823. HullPlane HullPlane::Scale(double s) const
  1824. {
  1825. return HullPlane(*this * s,
  1826. m_w * s);
  1827. }
  1828. HullPlane& HullPlane::operator=(const HullPlane& rhs)
  1829. {
  1830. GetX() = rhs.GetX();
  1831. GetY() = rhs.GetY();
  1832. GetZ() = rhs.GetZ();
  1833. m_w = rhs.m_w;
  1834. return *this;
  1835. }
  1836. double HullPlane::Evalue(const VHACD::Vect3& point) const
  1837. {
  1838. return Dot(point) + m_w;
  1839. }
  1840. double& HullPlane::GetW()
  1841. {
  1842. return m_w;
  1843. }
  1844. const double& HullPlane::GetW() const
  1845. {
  1846. return m_w;
  1847. }
  1848. class ConvexHullFace
  1849. {
  1850. public:
  1851. ConvexHullFace() = default;
  1852. double Evalue(const std::vector<VHACD::Vect3>& pointArray,
  1853. const VHACD::Vect3& point) const;
  1854. HullPlane GetPlaneEquation(const std::vector<VHACD::Vect3>& pointArray,
  1855. bool& isValid) const;
  1856. std::array<int, 3> m_index;
  1857. private:
  1858. int m_mark{ 0 };
  1859. std::array<std::list<ConvexHullFace>::iterator, 3> m_twin;
  1860. friend class ConvexHull;
  1861. };
  1862. double ConvexHullFace::Evalue(const std::vector<VHACD::Vect3>& pointArray,
  1863. const VHACD::Vect3& point) const
  1864. {
  1865. const VHACD::Vect3& p0 = pointArray[m_index[0]];
  1866. const VHACD::Vect3& p1 = pointArray[m_index[1]];
  1867. const VHACD::Vect3& p2 = pointArray[m_index[2]];
  1868. std::array<VHACD::Vect3, 3> matrix = { p2 - p0, p1 - p0, point - p0 };
  1869. double error;
  1870. double det = Determinant3x3(matrix,
  1871. error);
  1872. // the code use double, however the threshold for accuracy test is the machine precision of a float.
  1873. // by changing this to a smaller number, the code should run faster since many small test will be considered valid
  1874. // the precision must be a power of two no smaller than the machine precision of a double, (1<<48)
  1875. // float64(1<<30) can be a good value
  1876. // double precision = double (1.0f) / double (1<<30);
  1877. double precision = double(1.0) / double(1 << 24);
  1878. double errbound = error * precision;
  1879. if (fabs(det) > errbound)
  1880. {
  1881. return det;
  1882. }
  1883. const VHACD::Vector3<Googol> p0g = pointArray[m_index[0]];
  1884. const VHACD::Vector3<Googol> p1g = pointArray[m_index[1]];
  1885. const VHACD::Vector3<Googol> p2g = pointArray[m_index[2]];
  1886. const VHACD::Vector3<Googol> pointg = point;
  1887. std::array<VHACD::Vector3<Googol>, 3> exactMatrix = { p2g - p0g, p1g - p0g, pointg - p0g };
  1888. return Determinant3x3(exactMatrix);
  1889. }
  1890. HullPlane ConvexHullFace::GetPlaneEquation(const std::vector<VHACD::Vect3>& pointArray,
  1891. bool& isvalid) const
  1892. {
  1893. const VHACD::Vect3& p0 = pointArray[m_index[0]];
  1894. const VHACD::Vect3& p1 = pointArray[m_index[1]];
  1895. const VHACD::Vect3& p2 = pointArray[m_index[2]];
  1896. HullPlane plane(p0, p1, p2);
  1897. isvalid = false;
  1898. double mag2 = plane.Dot(plane);
  1899. if (mag2 > double(1.0e-16))
  1900. {
  1901. isvalid = true;
  1902. plane = plane.Scale(double(1.0) / sqrt(mag2));
  1903. }
  1904. return plane;
  1905. }
  1906. class ConvexHullVertex : public VHACD::Vect3
  1907. {
  1908. public:
  1909. ConvexHullVertex() = default;
  1910. ConvexHullVertex(const ConvexHullVertex&) = default;
  1911. ConvexHullVertex& operator=(const ConvexHullVertex& rhs) = default;
  1912. using VHACD::Vect3::operator=;
  1913. int m_mark{ 0 };
  1914. };
  1915. class ConvexHullAABBTreeNode
  1916. {
  1917. #define VHACD_CONVEXHULL_3D_VERTEX_CLUSTER_SIZE 8
  1918. public:
  1919. ConvexHullAABBTreeNode() = default;
  1920. ConvexHullAABBTreeNode(ConvexHullAABBTreeNode* parent);
  1921. VHACD::Vect3 m_box[2];
  1922. ConvexHullAABBTreeNode* m_left{ nullptr };
  1923. ConvexHullAABBTreeNode* m_right{ nullptr };
  1924. ConvexHullAABBTreeNode* m_parent{ nullptr };
  1925. size_t m_count;
  1926. std::array<size_t, VHACD_CONVEXHULL_3D_VERTEX_CLUSTER_SIZE> m_indices;
  1927. };
  1928. ConvexHullAABBTreeNode::ConvexHullAABBTreeNode(ConvexHullAABBTreeNode* parent)
  1929. : m_parent(parent)
  1930. {
  1931. }
  1932. class ConvexHull
  1933. {
  1934. class ndNormalMap;
  1935. public:
  1936. ConvexHull(const ConvexHull& source);
  1937. ConvexHull(const std::vector<::VHACD::Vertex>& vertexCloud,
  1938. double distTol,
  1939. int maxVertexCount = 0x7fffffff);
  1940. ~ConvexHull() = default;
  1941. const std::vector<VHACD::Vect3>& GetVertexPool() const;
  1942. const std::list<ConvexHullFace>& GetList() const { return m_list; }
  1943. private:
  1944. void BuildHull(const std::vector<::VHACD::Vertex>& vertexCloud,
  1945. double distTol,
  1946. int maxVertexCount);
  1947. void GetUniquePoints(std::vector<ConvexHullVertex>& points);
  1948. int InitVertexArray(std::vector<ConvexHullVertex>& points,
  1949. NodeBundle<ConvexHullAABBTreeNode>& memoryPool);
  1950. ConvexHullAABBTreeNode* BuildTreeNew(std::vector<ConvexHullVertex>& points,
  1951. std::vector<ConvexHullAABBTreeNode>& memoryPool) const;
  1952. ConvexHullAABBTreeNode* BuildTreeOld(std::vector<ConvexHullVertex>& points,
  1953. NodeBundle<ConvexHullAABBTreeNode>& memoryPool);
  1954. ConvexHullAABBTreeNode* BuildTreeRecurse(ConvexHullAABBTreeNode* const parent,
  1955. ConvexHullVertex* const points,
  1956. int count,
  1957. int baseIndex,
  1958. NodeBundle<ConvexHullAABBTreeNode>& memoryPool) const;
  1959. std::list<ConvexHullFace>::iterator AddFace(int i0,
  1960. int i1,
  1961. int i2);
  1962. void CalculateConvexHull3D(ConvexHullAABBTreeNode* vertexTree,
  1963. std::vector<ConvexHullVertex>& points,
  1964. int count,
  1965. double distTol,
  1966. int maxVertexCount);
  1967. int SupportVertex(ConvexHullAABBTreeNode** const tree,
  1968. const std::vector<ConvexHullVertex>& points,
  1969. const VHACD::Vect3& dir,
  1970. const bool removeEntry = true) const;
  1971. double TetrahedrumVolume(const VHACD::Vect3& p0,
  1972. const VHACD::Vect3& p1,
  1973. const VHACD::Vect3& p2,
  1974. const VHACD::Vect3& p3) const;
  1975. std::list<ConvexHullFace> m_list;
  1976. VHACD::Vect3 m_aabbP0{ 0 };
  1977. VHACD::Vect3 m_aabbP1{ 0 };
  1978. double m_diag{ 0.0 };
  1979. std::vector<VHACD::Vect3> m_points;
  1980. };
  1981. class ConvexHull::ndNormalMap
  1982. {
  1983. public:
  1984. ndNormalMap();
  1985. static const ndNormalMap& GetNormalMap();
  1986. void TessellateTriangle(int level,
  1987. const VHACD::Vect3& p0,
  1988. const VHACD::Vect3& p1,
  1989. const VHACD::Vect3& p2,
  1990. int& count);
  1991. std::array<VHACD::Vect3, 128> m_normal;
  1992. int m_count{ 128 };
  1993. };
  1994. const ConvexHull::ndNormalMap& ConvexHull::ndNormalMap::GetNormalMap()
  1995. {
  1996. static ndNormalMap normalMap;
  1997. return normalMap;
  1998. }
  1999. void ConvexHull::ndNormalMap::TessellateTriangle(int level,
  2000. const VHACD::Vect3& p0,
  2001. const VHACD::Vect3& p1,
  2002. const VHACD::Vect3& p2,
  2003. int& count)
  2004. {
  2005. if (level)
  2006. {
  2007. assert(fabs(p0.Dot(p0) - double(1.0)) < double(1.0e-4));
  2008. assert(fabs(p1.Dot(p1) - double(1.0)) < double(1.0e-4));
  2009. assert(fabs(p2.Dot(p2) - double(1.0)) < double(1.0e-4));
  2010. VHACD::Vect3 p01(p0 + p1);
  2011. VHACD::Vect3 p12(p1 + p2);
  2012. VHACD::Vect3 p20(p2 + p0);
  2013. p01 = p01 * (double(1.0) / p01.GetNorm());
  2014. p12 = p12 * (double(1.0) / p12.GetNorm());
  2015. p20 = p20 * (double(1.0) / p20.GetNorm());
  2016. assert(fabs(p01.GetNormSquared() - double(1.0)) < double(1.0e-4));
  2017. assert(fabs(p12.GetNormSquared() - double(1.0)) < double(1.0e-4));
  2018. assert(fabs(p20.GetNormSquared() - double(1.0)) < double(1.0e-4));
  2019. TessellateTriangle(level - 1, p0, p01, p20, count);
  2020. TessellateTriangle(level - 1, p1, p12, p01, count);
  2021. TessellateTriangle(level - 1, p2, p20, p12, count);
  2022. TessellateTriangle(level - 1, p01, p12, p20, count);
  2023. }
  2024. else
  2025. {
  2026. /*
  2027. * This is just m_normal[index] = n.Normalized(), but due to tiny floating point errors, causes
  2028. * different outputs, so I'm leaving it
  2029. */
  2030. HullPlane n(p0, p1, p2);
  2031. n = n.Scale(double(1.0) / n.GetNorm());
  2032. n.GetW() = double(0.0);
  2033. int index = dBitReversal(count,
  2034. int(m_normal.size()));
  2035. m_normal[index] = n;
  2036. count++;
  2037. assert(count <= int(m_normal.size()));
  2038. }
  2039. }
  2040. ConvexHull::ndNormalMap::ndNormalMap()
  2041. {
  2042. VHACD::Vect3 p0(double( 1.0), double( 0.0), double( 0.0));
  2043. VHACD::Vect3 p1(double(-1.0), double( 0.0), double( 0.0));
  2044. VHACD::Vect3 p2(double( 0.0), double( 1.0), double( 0.0));
  2045. VHACD::Vect3 p3(double( 0.0), double(-1.0), double( 0.0));
  2046. VHACD::Vect3 p4(double( 0.0), double( 0.0), double( 1.0));
  2047. VHACD::Vect3 p5(double( 0.0), double( 0.0), double(-1.0));
  2048. int count = 0;
  2049. int subdivisions = 2;
  2050. TessellateTriangle(subdivisions, p4, p0, p2, count);
  2051. TessellateTriangle(subdivisions, p0, p5, p2, count);
  2052. TessellateTriangle(subdivisions, p5, p1, p2, count);
  2053. TessellateTriangle(subdivisions, p1, p4, p2, count);
  2054. TessellateTriangle(subdivisions, p0, p4, p3, count);
  2055. TessellateTriangle(subdivisions, p5, p0, p3, count);
  2056. TessellateTriangle(subdivisions, p1, p5, p3, count);
  2057. TessellateTriangle(subdivisions, p4, p1, p3, count);
  2058. }
  2059. ConvexHull::ConvexHull(const std::vector<::VHACD::Vertex>& vertexCloud,
  2060. double distTol,
  2061. int maxVertexCount)
  2062. {
  2063. if (vertexCloud.size() >= 4)
  2064. {
  2065. BuildHull(vertexCloud,
  2066. distTol,
  2067. maxVertexCount);
  2068. }
  2069. }
  2070. const std::vector<VHACD::Vect3>& ConvexHull::GetVertexPool() const
  2071. {
  2072. return m_points;
  2073. }
  2074. void ConvexHull::BuildHull(const std::vector<::VHACD::Vertex>& vertexCloud,
  2075. double distTol,
  2076. int maxVertexCount)
  2077. {
  2078. size_t treeCount = vertexCloud.size() / (VHACD_CONVEXHULL_3D_VERTEX_CLUSTER_SIZE >> 1);
  2079. treeCount = std::max(treeCount, size_t(4)) * 2;
  2080. std::vector<ConvexHullVertex> points(vertexCloud.size());
  2081. /*
  2082. * treePool provides a memory pool for the AABB tree
  2083. * Each node is either a leaf or non-leaf node
  2084. * Non-leaf nodes have up to 8 vertices
  2085. * Vertices are specified by the m_indices array and are accessed via the points array
  2086. *
  2087. * Later on in ConvexHull::SupportVertex, the tree is used directly
  2088. * It differentiates between ConvexHullAABBTreeNode and ConvexHull3DPointCluster by whether the m_left and m_right
  2089. * pointers are null or not
  2090. *
  2091. * Pointers have to be stable
  2092. */
  2093. NodeBundle<ConvexHullAABBTreeNode> treePool;
  2094. for (size_t i = 0; i < vertexCloud.size(); ++i)
  2095. {
  2096. points[i] = VHACD::Vect3(vertexCloud[i]);
  2097. }
  2098. int count = InitVertexArray(points,
  2099. treePool);
  2100. if (m_points.size() >= 4)
  2101. {
  2102. CalculateConvexHull3D(&treePool.GetFirstNode(),
  2103. points,
  2104. count,
  2105. distTol,
  2106. maxVertexCount);
  2107. }
  2108. }
  2109. void ConvexHull::GetUniquePoints(std::vector<ConvexHullVertex>& points)
  2110. {
  2111. class CompareVertex
  2112. {
  2113. public:
  2114. int Compare(const ConvexHullVertex& elementA, const ConvexHullVertex& elementB) const
  2115. {
  2116. for (int i = 0; i < 3; i++)
  2117. {
  2118. if (elementA[i] < elementB[i])
  2119. {
  2120. return -1;
  2121. }
  2122. else if (elementA[i] > elementB[i])
  2123. {
  2124. return 1;
  2125. }
  2126. }
  2127. return 0;
  2128. }
  2129. };
  2130. int count = int(points.size());
  2131. Sort<ConvexHullVertex, CompareVertex>(points.data(),
  2132. count);
  2133. int indexCount = 0;
  2134. CompareVertex compareVertex;
  2135. for (int i = 1; i < count; ++i)
  2136. {
  2137. for (; i < count; ++i)
  2138. {
  2139. if (compareVertex.Compare(points[indexCount], points[i]))
  2140. {
  2141. indexCount++;
  2142. points[indexCount] = points[i];
  2143. break;
  2144. }
  2145. }
  2146. }
  2147. points.resize(indexCount + 1);
  2148. }
  2149. ConvexHullAABBTreeNode* ConvexHull::BuildTreeRecurse(ConvexHullAABBTreeNode* const parent,
  2150. ConvexHullVertex* const points,
  2151. int count,
  2152. int baseIndex,
  2153. NodeBundle<ConvexHullAABBTreeNode>& memoryPool) const
  2154. {
  2155. ConvexHullAABBTreeNode* tree = nullptr;
  2156. assert(count);
  2157. VHACD::Vect3 minP( double(1.0e15));
  2158. VHACD::Vect3 maxP(-double(1.0e15));
  2159. if (count <= VHACD_CONVEXHULL_3D_VERTEX_CLUSTER_SIZE)
  2160. {
  2161. ConvexHullAABBTreeNode& clump = memoryPool.GetNextNode();
  2162. clump.m_count = count;
  2163. for (int i = 0; i < count; ++i)
  2164. {
  2165. clump.m_indices[i] = i + baseIndex;
  2166. const VHACD::Vect3& p = points[i];
  2167. minP = minP.CWiseMin(p);
  2168. maxP = maxP.CWiseMax(p);
  2169. }
  2170. clump.m_left = nullptr;
  2171. clump.m_right = nullptr;
  2172. tree = &clump;
  2173. }
  2174. else
  2175. {
  2176. VHACD::Vect3 median(0);
  2177. VHACD::Vect3 varian(0);
  2178. for (int i = 0; i < count; ++i)
  2179. {
  2180. const VHACD::Vect3& p = points[i];
  2181. minP = minP.CWiseMin(p);
  2182. maxP = maxP.CWiseMax(p);
  2183. median += p;
  2184. varian += p.CWiseMul(p);
  2185. }
  2186. varian = varian * double(count) - median.CWiseMul(median);
  2187. int index = 0;
  2188. double maxVarian = double(-1.0e10);
  2189. for (int i = 0; i < 3; ++i)
  2190. {
  2191. if (varian[i] > maxVarian)
  2192. {
  2193. index = i;
  2194. maxVarian = varian[i];
  2195. }
  2196. }
  2197. VHACD::Vect3 center(median * (double(1.0) / double(count)));
  2198. double test = center[index];
  2199. int i0 = 0;
  2200. int i1 = count - 1;
  2201. do
  2202. {
  2203. for (; i0 <= i1; i0++)
  2204. {
  2205. double val = points[i0][index];
  2206. if (val > test)
  2207. {
  2208. break;
  2209. }
  2210. }
  2211. for (; i1 >= i0; i1--)
  2212. {
  2213. double val = points[i1][index];
  2214. if (val < test)
  2215. {
  2216. break;
  2217. }
  2218. }
  2219. if (i0 < i1)
  2220. {
  2221. std::swap(points[i0],
  2222. points[i1]);
  2223. i0++;
  2224. i1--;
  2225. }
  2226. } while (i0 <= i1);
  2227. if (i0 == 0)
  2228. {
  2229. i0 = count / 2;
  2230. }
  2231. if (i0 >= (count - 1))
  2232. {
  2233. i0 = count / 2;
  2234. }
  2235. tree = &memoryPool.GetNextNode();
  2236. assert(i0);
  2237. assert(count - i0);
  2238. tree->m_left = BuildTreeRecurse(tree,
  2239. points,
  2240. i0,
  2241. baseIndex,
  2242. memoryPool);
  2243. tree->m_right = BuildTreeRecurse(tree,
  2244. &points[i0],
  2245. count - i0,
  2246. i0 + baseIndex,
  2247. memoryPool);
  2248. }
  2249. assert(tree);
  2250. tree->m_parent = parent;
  2251. /*
  2252. * WARNING: Changing the compiler conversion of 1.0e-3f changes the results of the convex decomposition
  2253. * Inflate the tree's bounding box slightly
  2254. */
  2255. tree->m_box[0] = minP - VHACD::Vect3(double(1.0e-3f));
  2256. tree->m_box[1] = maxP + VHACD::Vect3(double(1.0e-3f));
  2257. return tree;
  2258. }
  2259. ConvexHullAABBTreeNode* ConvexHull::BuildTreeOld(std::vector<ConvexHullVertex>& points,
  2260. NodeBundle<ConvexHullAABBTreeNode>& memoryPool)
  2261. {
  2262. GetUniquePoints(points);
  2263. int count = int(points.size());
  2264. if (count < 4)
  2265. {
  2266. return nullptr;
  2267. }
  2268. return BuildTreeRecurse(nullptr,
  2269. points.data(),
  2270. count,
  2271. 0,
  2272. memoryPool);
  2273. }
  2274. ConvexHullAABBTreeNode* ConvexHull::BuildTreeNew(std::vector<ConvexHullVertex>& points,
  2275. std::vector<ConvexHullAABBTreeNode>& memoryPool) const
  2276. {
  2277. class dCluster
  2278. {
  2279. public:
  2280. VHACD::Vect3 m_sum{ double(0.0) };
  2281. VHACD::Vect3 m_sum2{ double(0.0) };
  2282. int m_start{ 0 };
  2283. int m_count{ 0 };
  2284. };
  2285. dCluster firstCluster;
  2286. firstCluster.m_count = int(points.size());
  2287. for (int i = 0; i < firstCluster.m_count; ++i)
  2288. {
  2289. const VHACD::Vect3& p = points[i];
  2290. firstCluster.m_sum += p;
  2291. firstCluster.m_sum2 += p.CWiseMul(p);
  2292. }
  2293. int baseCount = 0;
  2294. const int clusterSize = 16;
  2295. if (firstCluster.m_count > clusterSize)
  2296. {
  2297. dCluster spliteStack[128];
  2298. spliteStack[0] = firstCluster;
  2299. size_t stack = 1;
  2300. while (stack)
  2301. {
  2302. stack--;
  2303. dCluster cluster (spliteStack[stack]);
  2304. const VHACD::Vect3 origin(cluster.m_sum * (double(1.0) / cluster.m_count));
  2305. const VHACD::Vect3 variance2(cluster.m_sum2 * (double(1.0) / cluster.m_count) - origin.CWiseMul(origin));
  2306. double maxVariance2 = variance2.MaxCoeff();
  2307. if ( (cluster.m_count <= clusterSize)
  2308. || (stack > (sizeof(spliteStack) / sizeof(spliteStack[0]) - 4))
  2309. || (maxVariance2 < 1.e-4f))
  2310. {
  2311. // no sure if this is beneficial,
  2312. // the array is so small that seem too much overhead
  2313. //int maxIndex = 0;
  2314. //double min_x = 1.0e20f;
  2315. //for (int i = 0; i < cluster.m_count; ++i)
  2316. //{
  2317. // if (points[cluster.m_start + i].getX() < min_x)
  2318. // {
  2319. // maxIndex = i;
  2320. // min_x = points[cluster.m_start + i].getX();
  2321. // }
  2322. //}
  2323. //Swap(points[cluster.m_start], points[cluster.m_start + maxIndex]);
  2324. //
  2325. //for (int i = 2; i < cluster.m_count; ++i)
  2326. //{
  2327. // int j = i;
  2328. // ConvexHullVertex tmp(points[cluster.m_start + i]);
  2329. // for (; points[cluster.m_start + j - 1].getX() > tmp.getX(); --j)
  2330. // {
  2331. // assert(j > 0);
  2332. // points[cluster.m_start + j] = points[cluster.m_start + j - 1];
  2333. // }
  2334. // points[cluster.m_start + j] = tmp;
  2335. //}
  2336. int count = cluster.m_count;
  2337. for (int i = cluster.m_count - 1; i > 0; --i)
  2338. {
  2339. for (int j = i - 1; j >= 0; --j)
  2340. {
  2341. VHACD::Vect3 error(points[cluster.m_start + j] - points[cluster.m_start + i]);
  2342. double mag2 = error.Dot(error);
  2343. if (mag2 < double(1.0e-6))
  2344. {
  2345. points[cluster.m_start + j] = points[cluster.m_start + i];
  2346. count--;
  2347. break;
  2348. }
  2349. }
  2350. }
  2351. assert(baseCount <= cluster.m_start);
  2352. for (int i = 0; i < count; ++i)
  2353. {
  2354. points[baseCount] = points[cluster.m_start + i];
  2355. baseCount++;
  2356. }
  2357. }
  2358. else
  2359. {
  2360. const int firstSortAxis = variance2.LongestAxis();
  2361. double axisVal = origin[firstSortAxis];
  2362. int i0 = 0;
  2363. int i1 = cluster.m_count - 1;
  2364. const int start = cluster.m_start;
  2365. while (i0 < i1)
  2366. {
  2367. while ( (points[start + i0][firstSortAxis] <= axisVal)
  2368. && (i0 < i1))
  2369. {
  2370. ++i0;
  2371. };
  2372. while ( (points[start + i1][firstSortAxis] > axisVal)
  2373. && (i0 < i1))
  2374. {
  2375. --i1;
  2376. }
  2377. assert(i0 <= i1);
  2378. if (i0 < i1)
  2379. {
  2380. std::swap(points[start + i0],
  2381. points[start + i1]);
  2382. ++i0;
  2383. --i1;
  2384. }
  2385. }
  2386. while ( (points[start + i0][firstSortAxis] <= axisVal)
  2387. && (i0 < cluster.m_count))
  2388. {
  2389. ++i0;
  2390. };
  2391. #ifdef _DEBUG
  2392. for (int i = 0; i < i0; ++i)
  2393. {
  2394. assert(points[start + i][firstSortAxis] <= axisVal);
  2395. }
  2396. for (int i = i0; i < cluster.m_count; ++i)
  2397. {
  2398. assert(points[start + i][firstSortAxis] > axisVal);
  2399. }
  2400. #endif
  2401. VHACD::Vect3 xc(0);
  2402. VHACD::Vect3 x2c(0);
  2403. for (int i = 0; i < i0; ++i)
  2404. {
  2405. const VHACD::Vect3& x = points[start + i];
  2406. xc += x;
  2407. x2c += x.CWiseMul(x);
  2408. }
  2409. dCluster cluster_i1(cluster);
  2410. cluster_i1.m_start = start + i0;
  2411. cluster_i1.m_count = cluster.m_count - i0;
  2412. cluster_i1.m_sum -= xc;
  2413. cluster_i1.m_sum2 -= x2c;
  2414. spliteStack[stack] = cluster_i1;
  2415. assert(cluster_i1.m_count > 0);
  2416. stack++;
  2417. dCluster cluster_i0(cluster);
  2418. cluster_i0.m_start = start;
  2419. cluster_i0.m_count = i0;
  2420. cluster_i0.m_sum = xc;
  2421. cluster_i0.m_sum2 = x2c;
  2422. assert(cluster_i0.m_count > 0);
  2423. spliteStack[stack] = cluster_i0;
  2424. stack++;
  2425. }
  2426. }
  2427. }
  2428. points.resize(baseCount);
  2429. if (baseCount < 4)
  2430. {
  2431. return nullptr;
  2432. }
  2433. VHACD::Vect3 sum(0);
  2434. VHACD::Vect3 sum2(0);
  2435. VHACD::Vect3 minP(double( 1.0e15));
  2436. VHACD::Vect3 maxP(double(-1.0e15));
  2437. class dTreeBox
  2438. {
  2439. public:
  2440. VHACD::Vect3 m_min;
  2441. VHACD::Vect3 m_max;
  2442. VHACD::Vect3 m_sum;
  2443. VHACD::Vect3 m_sum2;
  2444. ConvexHullAABBTreeNode* m_parent;
  2445. ConvexHullAABBTreeNode** m_child;
  2446. int m_start;
  2447. int m_count;
  2448. };
  2449. for (int i = 0; i < baseCount; ++i)
  2450. {
  2451. const VHACD::Vect3& p = points[i];
  2452. sum += p;
  2453. sum2 += p.CWiseMul(p);
  2454. minP = minP.CWiseMin(p);
  2455. maxP = maxP.CWiseMax(p);
  2456. }
  2457. dTreeBox treeBoxStack[128];
  2458. treeBoxStack[0].m_start = 0;
  2459. treeBoxStack[0].m_count = baseCount;
  2460. treeBoxStack[0].m_sum = sum;
  2461. treeBoxStack[0].m_sum2 = sum2;
  2462. treeBoxStack[0].m_min = minP;
  2463. treeBoxStack[0].m_max = maxP;
  2464. treeBoxStack[0].m_child = nullptr;
  2465. treeBoxStack[0].m_parent = nullptr;
  2466. int stack = 1;
  2467. ConvexHullAABBTreeNode* root = nullptr;
  2468. while (stack)
  2469. {
  2470. stack--;
  2471. dTreeBox box(treeBoxStack[stack]);
  2472. if (box.m_count <= VHACD_CONVEXHULL_3D_VERTEX_CLUSTER_SIZE)
  2473. {
  2474. assert(memoryPool.size() != memoryPool.capacity()
  2475. && "memoryPool is going to be reallocated, pointers will be invalid");
  2476. memoryPool.emplace_back();
  2477. ConvexHullAABBTreeNode& clump = memoryPool.back();
  2478. clump.m_count = box.m_count;
  2479. for (int i = 0; i < box.m_count; ++i)
  2480. {
  2481. clump.m_indices[i] = i + box.m_start;
  2482. }
  2483. clump.m_box[0] = box.m_min;
  2484. clump.m_box[1] = box.m_max;
  2485. if (box.m_child)
  2486. {
  2487. *box.m_child = &clump;
  2488. }
  2489. if (!root)
  2490. {
  2491. root = &clump;
  2492. }
  2493. }
  2494. else
  2495. {
  2496. const VHACD::Vect3 origin(box.m_sum * (double(1.0) / box.m_count));
  2497. const VHACD::Vect3 variance2(box.m_sum2 * (double(1.0) / box.m_count) - origin.CWiseMul(origin));
  2498. int firstSortAxis = 0;
  2499. if ((variance2.GetY() >= variance2.GetX()) && (variance2.GetY() >= variance2.GetZ()))
  2500. {
  2501. firstSortAxis = 1;
  2502. }
  2503. else if ((variance2.GetZ() >= variance2.GetX()) && (variance2.GetZ() >= variance2.GetY()))
  2504. {
  2505. firstSortAxis = 2;
  2506. }
  2507. double axisVal = origin[firstSortAxis];
  2508. int i0 = 0;
  2509. int i1 = box.m_count - 1;
  2510. const int start = box.m_start;
  2511. while (i0 < i1)
  2512. {
  2513. while ((points[start + i0][firstSortAxis] <= axisVal) && (i0 < i1))
  2514. {
  2515. ++i0;
  2516. };
  2517. while ((points[start + i1][firstSortAxis] > axisVal) && (i0 < i1))
  2518. {
  2519. --i1;
  2520. }
  2521. assert(i0 <= i1);
  2522. if (i0 < i1)
  2523. {
  2524. std::swap(points[start + i0],
  2525. points[start + i1]);
  2526. ++i0;
  2527. --i1;
  2528. }
  2529. }
  2530. while ((points[start + i0][firstSortAxis] <= axisVal) && (i0 < box.m_count))
  2531. {
  2532. ++i0;
  2533. };
  2534. #ifdef _DEBUG
  2535. for (int i = 0; i < i0; ++i)
  2536. {
  2537. assert(points[start + i][firstSortAxis] <= axisVal);
  2538. }
  2539. for (int i = i0; i < box.m_count; ++i)
  2540. {
  2541. assert(points[start + i][firstSortAxis] > axisVal);
  2542. }
  2543. #endif
  2544. assert(memoryPool.size() != memoryPool.capacity()
  2545. && "memoryPool is going to be reallocated, pointers will be invalid");
  2546. memoryPool.emplace_back();
  2547. ConvexHullAABBTreeNode& node = memoryPool.back();
  2548. node.m_box[0] = box.m_min;
  2549. node.m_box[1] = box.m_max;
  2550. if (box.m_child)
  2551. {
  2552. *box.m_child = &node;
  2553. }
  2554. if (!root)
  2555. {
  2556. root = &node;
  2557. }
  2558. {
  2559. VHACD::Vect3 xc(0);
  2560. VHACD::Vect3 x2c(0);
  2561. VHACD::Vect3 p0(double( 1.0e15));
  2562. VHACD::Vect3 p1(double(-1.0e15));
  2563. for (int i = i0; i < box.m_count; ++i)
  2564. {
  2565. const VHACD::Vect3& p = points[start + i];
  2566. xc += p;
  2567. x2c += p.CWiseMul(p);
  2568. p0 = p0.CWiseMin(p);
  2569. p1 = p1.CWiseMax(p);
  2570. }
  2571. dTreeBox cluster_i1(box);
  2572. cluster_i1.m_start = start + i0;
  2573. cluster_i1.m_count = box.m_count - i0;
  2574. cluster_i1.m_sum = xc;
  2575. cluster_i1.m_sum2 = x2c;
  2576. cluster_i1.m_min = p0;
  2577. cluster_i1.m_max = p1;
  2578. cluster_i1.m_parent = &node;
  2579. cluster_i1.m_child = &node.m_right;
  2580. treeBoxStack[stack] = cluster_i1;
  2581. assert(cluster_i1.m_count > 0);
  2582. stack++;
  2583. }
  2584. {
  2585. VHACD::Vect3 xc(0);
  2586. VHACD::Vect3 x2c(0);
  2587. VHACD::Vect3 p0(double( 1.0e15));
  2588. VHACD::Vect3 p1(double(-1.0e15));
  2589. for (int i = 0; i < i0; ++i)
  2590. {
  2591. const VHACD::Vect3& p = points[start + i];
  2592. xc += p;
  2593. x2c += p.CWiseMul(p);
  2594. p0 = p0.CWiseMin(p);
  2595. p1 = p1.CWiseMax(p);
  2596. }
  2597. dTreeBox cluster_i0(box);
  2598. cluster_i0.m_start = start;
  2599. cluster_i0.m_count = i0;
  2600. cluster_i0.m_min = p0;
  2601. cluster_i0.m_max = p1;
  2602. cluster_i0.m_sum = xc;
  2603. cluster_i0.m_sum2 = x2c;
  2604. cluster_i0.m_parent = &node;
  2605. cluster_i0.m_child = &node.m_left;
  2606. assert(cluster_i0.m_count > 0);
  2607. treeBoxStack[stack] = cluster_i0;
  2608. stack++;
  2609. }
  2610. }
  2611. }
  2612. return root;
  2613. }
  2614. int ConvexHull::SupportVertex(ConvexHullAABBTreeNode** const treePointer,
  2615. const std::vector<ConvexHullVertex>& points,
  2616. const VHACD::Vect3& dirPlane,
  2617. const bool removeEntry) const
  2618. {
  2619. #define VHACD_STACK_DEPTH_3D 64
  2620. double aabbProjection[VHACD_STACK_DEPTH_3D];
  2621. ConvexHullAABBTreeNode* stackPool[VHACD_STACK_DEPTH_3D];
  2622. VHACD::Vect3 dir(dirPlane);
  2623. int index = -1;
  2624. int stack = 1;
  2625. stackPool[0] = *treePointer;
  2626. aabbProjection[0] = double(1.0e20);
  2627. double maxProj = double(-1.0e20);
  2628. int ix = (dir[0] > double(0.0)) ? 1 : 0;
  2629. int iy = (dir[1] > double(0.0)) ? 1 : 0;
  2630. int iz = (dir[2] > double(0.0)) ? 1 : 0;
  2631. while (stack)
  2632. {
  2633. stack--;
  2634. double boxSupportValue = aabbProjection[stack];
  2635. if (boxSupportValue > maxProj)
  2636. {
  2637. ConvexHullAABBTreeNode* me = stackPool[stack];
  2638. /*
  2639. * If the node is not a leaf node...
  2640. */
  2641. if (me->m_left && me->m_right)
  2642. {
  2643. const VHACD::Vect3 leftSupportPoint(me->m_left->m_box[ix].GetX(),
  2644. me->m_left->m_box[iy].GetY(),
  2645. me->m_left->m_box[iz].GetZ());
  2646. double leftSupportDist = leftSupportPoint.Dot(dir);
  2647. const VHACD::Vect3 rightSupportPoint(me->m_right->m_box[ix].GetX(),
  2648. me->m_right->m_box[iy].GetY(),
  2649. me->m_right->m_box[iz].GetZ());
  2650. double rightSupportDist = rightSupportPoint.Dot(dir);
  2651. /*
  2652. * ...push the shorter side first
  2653. * So we can explore the tree in the larger side first
  2654. */
  2655. if (rightSupportDist >= leftSupportDist)
  2656. {
  2657. aabbProjection[stack] = leftSupportDist;
  2658. stackPool[stack] = me->m_left;
  2659. stack++;
  2660. assert(stack < VHACD_STACK_DEPTH_3D);
  2661. aabbProjection[stack] = rightSupportDist;
  2662. stackPool[stack] = me->m_right;
  2663. stack++;
  2664. assert(stack < VHACD_STACK_DEPTH_3D);
  2665. }
  2666. else
  2667. {
  2668. aabbProjection[stack] = rightSupportDist;
  2669. stackPool[stack] = me->m_right;
  2670. stack++;
  2671. assert(stack < VHACD_STACK_DEPTH_3D);
  2672. aabbProjection[stack] = leftSupportDist;
  2673. stackPool[stack] = me->m_left;
  2674. stack++;
  2675. assert(stack < VHACD_STACK_DEPTH_3D);
  2676. }
  2677. }
  2678. /*
  2679. * If it is a node...
  2680. */
  2681. else
  2682. {
  2683. ConvexHullAABBTreeNode* cluster = me;
  2684. for (size_t i = 0; i < cluster->m_count; ++i)
  2685. {
  2686. const ConvexHullVertex& p = points[cluster->m_indices[i]];
  2687. assert(p.GetX() >= cluster->m_box[0].GetX());
  2688. assert(p.GetX() <= cluster->m_box[1].GetX());
  2689. assert(p.GetY() >= cluster->m_box[0].GetY());
  2690. assert(p.GetY() <= cluster->m_box[1].GetY());
  2691. assert(p.GetZ() >= cluster->m_box[0].GetZ());
  2692. assert(p.GetZ() <= cluster->m_box[1].GetZ());
  2693. if (!p.m_mark)
  2694. {
  2695. //assert(p.m_w == double(0.0f));
  2696. double dist = p.Dot(dir);
  2697. if (dist > maxProj)
  2698. {
  2699. maxProj = dist;
  2700. index = cluster->m_indices[i];
  2701. }
  2702. }
  2703. else if (removeEntry)
  2704. {
  2705. cluster->m_indices[i] = cluster->m_indices[cluster->m_count - 1];
  2706. cluster->m_count = cluster->m_count - 1;
  2707. i--;
  2708. }
  2709. }
  2710. if (cluster->m_count == 0)
  2711. {
  2712. ConvexHullAABBTreeNode* const parent = cluster->m_parent;
  2713. if (parent)
  2714. {
  2715. ConvexHullAABBTreeNode* const sibling = (parent->m_left != cluster) ? parent->m_left : parent->m_right;
  2716. assert(sibling != cluster);
  2717. ConvexHullAABBTreeNode* const grandParent = parent->m_parent;
  2718. if (grandParent)
  2719. {
  2720. sibling->m_parent = grandParent;
  2721. if (grandParent->m_right == parent)
  2722. {
  2723. grandParent->m_right = sibling;
  2724. }
  2725. else
  2726. {
  2727. grandParent->m_left = sibling;
  2728. }
  2729. }
  2730. else
  2731. {
  2732. sibling->m_parent = nullptr;
  2733. *treePointer = sibling;
  2734. }
  2735. }
  2736. }
  2737. }
  2738. }
  2739. }
  2740. assert(index != -1);
  2741. return index;
  2742. }
  2743. double ConvexHull::TetrahedrumVolume(const VHACD::Vect3& p0,
  2744. const VHACD::Vect3& p1,
  2745. const VHACD::Vect3& p2,
  2746. const VHACD::Vect3& p3) const
  2747. {
  2748. const VHACD::Vect3 p1p0(p1 - p0);
  2749. const VHACD::Vect3 p2p0(p2 - p0);
  2750. const VHACD::Vect3 p3p0(p3 - p0);
  2751. return p3p0.Dot(p1p0.Cross(p2p0));
  2752. }
  2753. int ConvexHull::InitVertexArray(std::vector<ConvexHullVertex>& points,
  2754. NodeBundle<ConvexHullAABBTreeNode>& memoryPool)
  2755. // std::vector<ConvexHullAABBTreeNode>& memoryPool)
  2756. {
  2757. #if 1
  2758. ConvexHullAABBTreeNode* tree = BuildTreeOld(points,
  2759. memoryPool);
  2760. #else
  2761. ConvexHullAABBTreeNode* tree = BuildTreeNew(points, (char**)&memoryPool, maxMemSize);
  2762. #endif
  2763. int count = int(points.size());
  2764. if (count < 4)
  2765. {
  2766. m_points.resize(0);
  2767. return 0;
  2768. }
  2769. m_points.resize(count);
  2770. m_aabbP0 = tree->m_box[0];
  2771. m_aabbP1 = tree->m_box[1];
  2772. VHACD::Vect3 boxSize(tree->m_box[1] - tree->m_box[0]);
  2773. m_diag = boxSize.GetNorm();
  2774. const ndNormalMap& normalMap = ndNormalMap::GetNormalMap();
  2775. int index0 = SupportVertex(&tree,
  2776. points,
  2777. normalMap.m_normal[0]);
  2778. m_points[0] = points[index0];
  2779. points[index0].m_mark = 1;
  2780. bool validTetrahedrum = false;
  2781. VHACD::Vect3 e1(double(0.0));
  2782. for (int i = 1; i < normalMap.m_count; ++i)
  2783. {
  2784. int index = SupportVertex(&tree,
  2785. points,
  2786. normalMap.m_normal[i]);
  2787. assert(index >= 0);
  2788. e1 = points[index] - m_points[0];
  2789. double error2 = e1.GetNormSquared();
  2790. if (error2 > (double(1.0e-4) * m_diag * m_diag))
  2791. {
  2792. m_points[1] = points[index];
  2793. points[index].m_mark = 1;
  2794. validTetrahedrum = true;
  2795. break;
  2796. }
  2797. }
  2798. if (!validTetrahedrum)
  2799. {
  2800. m_points.resize(0);
  2801. assert(0);
  2802. return count;
  2803. }
  2804. validTetrahedrum = false;
  2805. VHACD::Vect3 e2(double(0.0));
  2806. VHACD::Vect3 normal(double(0.0));
  2807. for (int i = 2; i < normalMap.m_count; ++i)
  2808. {
  2809. int index = SupportVertex(&tree,
  2810. points,
  2811. normalMap.m_normal[i]);
  2812. assert(index >= 0);
  2813. e2 = points[index] - m_points[0];
  2814. normal = e1.Cross(e2);
  2815. double error2 = normal.GetNorm();
  2816. if (error2 > (double(1.0e-4) * m_diag * m_diag))
  2817. {
  2818. m_points[2] = points[index];
  2819. points[index].m_mark = 1;
  2820. validTetrahedrum = true;
  2821. break;
  2822. }
  2823. }
  2824. if (!validTetrahedrum)
  2825. {
  2826. m_points.resize(0);
  2827. assert(0);
  2828. return count;
  2829. }
  2830. // find the largest possible tetrahedron
  2831. validTetrahedrum = false;
  2832. VHACD::Vect3 e3(double(0.0));
  2833. index0 = SupportVertex(&tree,
  2834. points,
  2835. normal);
  2836. e3 = points[index0] - m_points[0];
  2837. double err2 = normal.Dot(e3);
  2838. if (fabs(err2) > (double(1.0e-6) * m_diag * m_diag))
  2839. {
  2840. // we found a valid tetrahedral, about and start build the hull by adding the rest of the points
  2841. m_points[3] = points[index0];
  2842. points[index0].m_mark = 1;
  2843. validTetrahedrum = true;
  2844. }
  2845. if (!validTetrahedrum)
  2846. {
  2847. VHACD::Vect3 n(-normal);
  2848. int index = SupportVertex(&tree,
  2849. points,
  2850. n);
  2851. e3 = points[index] - m_points[0];
  2852. double error2 = normal.Dot(e3);
  2853. if (fabs(error2) > (double(1.0e-6) * m_diag * m_diag))
  2854. {
  2855. // we found a valid tetrahedral, about and start build the hull by adding the rest of the points
  2856. m_points[3] = points[index];
  2857. points[index].m_mark = 1;
  2858. validTetrahedrum = true;
  2859. }
  2860. }
  2861. if (!validTetrahedrum)
  2862. {
  2863. for (int i = 3; i < normalMap.m_count; ++i)
  2864. {
  2865. int index = SupportVertex(&tree,
  2866. points,
  2867. normalMap.m_normal[i]);
  2868. assert(index >= 0);
  2869. //make sure the volume of the fist tetrahedral is no negative
  2870. e3 = points[index] - m_points[0];
  2871. double error2 = normal.Dot(e3);
  2872. if (fabs(error2) > (double(1.0e-6) * m_diag * m_diag))
  2873. {
  2874. // we found a valid tetrahedral, about and start build the hull by adding the rest of the points
  2875. m_points[3] = points[index];
  2876. points[index].m_mark = 1;
  2877. validTetrahedrum = true;
  2878. break;
  2879. }
  2880. }
  2881. }
  2882. if (!validTetrahedrum)
  2883. {
  2884. // the points do not form a convex hull
  2885. m_points.resize(0);
  2886. return count;
  2887. }
  2888. m_points.resize(4);
  2889. double volume = TetrahedrumVolume(m_points[0],
  2890. m_points[1],
  2891. m_points[2],
  2892. m_points[3]);
  2893. if (volume > double(0.0))
  2894. {
  2895. std::swap(m_points[2],
  2896. m_points[3]);
  2897. }
  2898. assert(TetrahedrumVolume(m_points[0], m_points[1], m_points[2], m_points[3]) < double(0.0));
  2899. return count;
  2900. }
  2901. std::list<ConvexHullFace>::iterator ConvexHull::AddFace(int i0,
  2902. int i1,
  2903. int i2)
  2904. {
  2905. ConvexHullFace face;
  2906. face.m_index[0] = i0;
  2907. face.m_index[1] = i1;
  2908. face.m_index[2] = i2;
  2909. std::list<ConvexHullFace>::iterator node = m_list.emplace(m_list.end(), face);
  2910. return node;
  2911. }
  2912. void ConvexHull::CalculateConvexHull3D(ConvexHullAABBTreeNode* vertexTree,
  2913. std::vector<ConvexHullVertex>& points,
  2914. int count,
  2915. double distTol,
  2916. int maxVertexCount)
  2917. {
  2918. distTol = fabs(distTol) * m_diag;
  2919. std::list<ConvexHullFace>::iterator f0Node = AddFace(0, 1, 2);
  2920. std::list<ConvexHullFace>::iterator f1Node = AddFace(0, 2, 3);
  2921. std::list<ConvexHullFace>::iterator f2Node = AddFace(2, 1, 3);
  2922. std::list<ConvexHullFace>::iterator f3Node = AddFace(1, 0, 3);
  2923. ConvexHullFace& f0 = *f0Node;
  2924. ConvexHullFace& f1 = *f1Node;
  2925. ConvexHullFace& f2 = *f2Node;
  2926. ConvexHullFace& f3 = *f3Node;
  2927. f0.m_twin[0] = f3Node;
  2928. f0.m_twin[1] = f2Node;
  2929. f0.m_twin[2] = f1Node;
  2930. f1.m_twin[0] = f0Node;
  2931. f1.m_twin[1] = f2Node;
  2932. f1.m_twin[2] = f3Node;
  2933. f2.m_twin[0] = f0Node;
  2934. f2.m_twin[1] = f3Node;
  2935. f2.m_twin[2] = f1Node;
  2936. f3.m_twin[0] = f0Node;
  2937. f3.m_twin[1] = f1Node;
  2938. f3.m_twin[2] = f2Node;
  2939. std::list<std::list<ConvexHullFace>::iterator> boundaryFaces;
  2940. boundaryFaces.push_back(f0Node);
  2941. boundaryFaces.push_back(f1Node);
  2942. boundaryFaces.push_back(f2Node);
  2943. boundaryFaces.push_back(f3Node);
  2944. m_points.resize(count);
  2945. count -= 4;
  2946. maxVertexCount -= 4;
  2947. int currentIndex = 4;
  2948. /*
  2949. * Some are iterators into boundaryFaces, others into m_list
  2950. */
  2951. std::vector<std::list<ConvexHullFace>::iterator> stack;
  2952. std::vector<std::list<ConvexHullFace>::iterator> coneList;
  2953. std::vector<std::list<ConvexHullFace>::iterator> deleteList;
  2954. stack.reserve(1024 + count);
  2955. coneList.reserve(1024 + count);
  2956. deleteList.reserve(1024 + count);
  2957. while (boundaryFaces.size() && count && (maxVertexCount > 0))
  2958. {
  2959. // my definition of the optimal convex hull of a given vertex count,
  2960. // is the convex hull formed by a subset of the input vertex that minimizes the volume difference
  2961. // between the perfect hull formed from all input vertex and the hull of the sub set of vertex.
  2962. // When using a priority heap this algorithms will generate the an optimal of a fix vertex count.
  2963. // Since all Newton's tools do not have a limit on the point count of a convex hull, I can use either a stack or a queue.
  2964. // a stack maximize construction speed, a Queue tend to maximize the volume of the generated Hull approaching a perfect Hull.
  2965. // For now we use a queue.
  2966. // For general hulls it does not make a difference if we use a stack, queue, or a priority heap.
  2967. // perfect optimal hull only apply for when build hull of a limited vertex count.
  2968. //
  2969. // Also when building Hulls of a limited vertex count, this function runs in constant time.
  2970. // yes that is correct, it does not makes a difference if you build a N point hull from 100 vertex
  2971. // or from 100000 vertex input array.
  2972. // using a queue (some what slower by better hull when reduced vertex count is desired)
  2973. bool isvalid;
  2974. std::list<ConvexHullFace>::iterator faceNode = boundaryFaces.back();
  2975. ConvexHullFace& face = *faceNode;
  2976. HullPlane planeEquation(face.GetPlaneEquation(m_points, isvalid));
  2977. int index = 0;
  2978. double dist = 0;
  2979. VHACD::Vect3 p;
  2980. if (isvalid)
  2981. {
  2982. index = SupportVertex(&vertexTree,
  2983. points,
  2984. planeEquation);
  2985. p = points[index];
  2986. dist = planeEquation.Evalue(p);
  2987. }
  2988. if ( isvalid
  2989. && (dist >= distTol)
  2990. && (face.Evalue(m_points, p) < double(0.0)))
  2991. {
  2992. stack.push_back(faceNode);
  2993. deleteList.clear();
  2994. while (stack.size())
  2995. {
  2996. std::list<ConvexHullFace>::iterator node1 = stack.back();
  2997. ConvexHullFace& face1 = *node1;
  2998. stack.pop_back();
  2999. if (!face1.m_mark && (face1.Evalue(m_points, p) < double(0.0)))
  3000. {
  3001. #ifdef _DEBUG
  3002. for (const auto node : deleteList)
  3003. {
  3004. assert(node != node1);
  3005. }
  3006. #endif
  3007. deleteList.push_back(node1);
  3008. face1.m_mark = 1;
  3009. for (std::list<ConvexHullFace>::iterator& twinNode : face1.m_twin)
  3010. {
  3011. ConvexHullFace& twinFace = *twinNode;
  3012. if (!twinFace.m_mark)
  3013. {
  3014. stack.push_back(twinNode);
  3015. }
  3016. }
  3017. }
  3018. }
  3019. m_points[currentIndex] = points[index];
  3020. points[index].m_mark = 1;
  3021. coneList.clear();
  3022. for (std::list<ConvexHullFace>::iterator node1 : deleteList)
  3023. {
  3024. ConvexHullFace& face1 = *node1;
  3025. assert(face1.m_mark == 1);
  3026. for (std::size_t j0 = 0; j0 < face1.m_twin.size(); ++j0)
  3027. {
  3028. std::list<ConvexHullFace>::iterator twinNode = face1.m_twin[j0];
  3029. ConvexHullFace& twinFace = *twinNode;
  3030. if (!twinFace.m_mark)
  3031. {
  3032. std::size_t j1 = (j0 == 2) ? 0 : j0 + 1;
  3033. std::list<ConvexHullFace>::iterator newNode = AddFace(currentIndex,
  3034. face1.m_index[j0],
  3035. face1.m_index[j1]);
  3036. boundaryFaces.push_front(newNode);
  3037. ConvexHullFace& newFace = *newNode;
  3038. newFace.m_twin[1] = twinNode;
  3039. for (std::size_t k = 0; k < twinFace.m_twin.size(); ++k)
  3040. {
  3041. if (twinFace.m_twin[k] == node1)
  3042. {
  3043. twinFace.m_twin[k] = newNode;
  3044. }
  3045. }
  3046. coneList.push_back(newNode);
  3047. }
  3048. }
  3049. }
  3050. for (std::size_t i = 0; i < coneList.size() - 1; ++i)
  3051. {
  3052. std::list<ConvexHullFace>::iterator nodeA = coneList[i];
  3053. ConvexHullFace& faceA = *nodeA;
  3054. assert(faceA.m_mark == 0);
  3055. for (std::size_t j = i + 1; j < coneList.size(); j++)
  3056. {
  3057. std::list<ConvexHullFace>::iterator nodeB = coneList[j];
  3058. ConvexHullFace& faceB = *nodeB;
  3059. assert(faceB.m_mark == 0);
  3060. if (faceA.m_index[2] == faceB.m_index[1])
  3061. {
  3062. faceA.m_twin[2] = nodeB;
  3063. faceB.m_twin[0] = nodeA;
  3064. break;
  3065. }
  3066. }
  3067. for (std::size_t j = i + 1; j < coneList.size(); j++)
  3068. {
  3069. std::list<ConvexHullFace>::iterator nodeB = coneList[j];
  3070. ConvexHullFace& faceB = *nodeB;
  3071. assert(faceB.m_mark == 0);
  3072. if (faceA.m_index[1] == faceB.m_index[2])
  3073. {
  3074. faceA.m_twin[0] = nodeB;
  3075. faceB.m_twin[2] = nodeA;
  3076. break;
  3077. }
  3078. }
  3079. }
  3080. for (std::list<ConvexHullFace>::iterator node : deleteList)
  3081. {
  3082. auto it = std::find(boundaryFaces.begin(),
  3083. boundaryFaces.end(),
  3084. node);
  3085. if (it != boundaryFaces.end())
  3086. {
  3087. boundaryFaces.erase(it);
  3088. }
  3089. m_list.erase(node);
  3090. }
  3091. maxVertexCount--;
  3092. currentIndex++;
  3093. count--;
  3094. }
  3095. else
  3096. {
  3097. auto it = std::find(boundaryFaces.begin(),
  3098. boundaryFaces.end(),
  3099. faceNode);
  3100. if (it != boundaryFaces.end())
  3101. {
  3102. boundaryFaces.erase(it);
  3103. }
  3104. }
  3105. }
  3106. m_points.resize(currentIndex);
  3107. }
  3108. //***********************************************************************************************
  3109. // End of ConvexHull generation code by Julio Jerez <[email protected]>
  3110. //***********************************************************************************************
  3111. class KdTreeNode;
  3112. enum Axes
  3113. {
  3114. X_AXIS = 0,
  3115. Y_AXIS = 1,
  3116. Z_AXIS = 2
  3117. };
  3118. class KdTreeFindNode
  3119. {
  3120. public:
  3121. KdTreeFindNode() = default;
  3122. KdTreeNode* m_node{ nullptr };
  3123. double m_distance{ 0.0 };
  3124. };
  3125. class KdTree
  3126. {
  3127. public:
  3128. KdTree() = default;
  3129. const VHACD::Vertex& GetPosition(uint32_t index) const;
  3130. uint32_t Search(const VHACD::Vect3& pos,
  3131. double radius,
  3132. uint32_t maxObjects,
  3133. KdTreeFindNode* found) const;
  3134. uint32_t Add(const VHACD::Vertex& v);
  3135. KdTreeNode& GetNewNode(uint32_t index);
  3136. uint32_t GetNearest(const VHACD::Vect3& pos,
  3137. double radius,
  3138. bool& _found) const; // returns the nearest possible neighbor's index.
  3139. const std::vector<VHACD::Vertex>& GetVertices() const;
  3140. std::vector<VHACD::Vertex>&& TakeVertices();
  3141. uint32_t GetVCount() const;
  3142. private:
  3143. KdTreeNode* m_root{ nullptr };
  3144. NodeBundle<KdTreeNode> m_bundle;
  3145. std::vector<VHACD::Vertex> m_vertices;
  3146. };
  3147. class KdTreeNode
  3148. {
  3149. public:
  3150. KdTreeNode() = default;
  3151. KdTreeNode(uint32_t index);
  3152. void Add(KdTreeNode& node,
  3153. Axes dim,
  3154. const KdTree& iface);
  3155. uint32_t GetIndex() const;
  3156. void Search(Axes axis,
  3157. const VHACD::Vect3& pos,
  3158. double radius,
  3159. uint32_t& count,
  3160. uint32_t maxObjects,
  3161. KdTreeFindNode* found,
  3162. const KdTree& iface);
  3163. private:
  3164. uint32_t m_index = 0;
  3165. KdTreeNode* m_left = nullptr;
  3166. KdTreeNode* m_right = nullptr;
  3167. };
  3168. const VHACD::Vertex& KdTree::GetPosition(uint32_t index) const
  3169. {
  3170. assert(index < m_vertices.size());
  3171. return m_vertices[index];
  3172. }
  3173. uint32_t KdTree::Search(const VHACD::Vect3& pos,
  3174. double radius,
  3175. uint32_t maxObjects,
  3176. KdTreeFindNode* found) const
  3177. {
  3178. if (!m_root)
  3179. return 0;
  3180. uint32_t count = 0;
  3181. m_root->Search(X_AXIS, pos, radius, count, maxObjects, found, *this);
  3182. return count;
  3183. }
  3184. uint32_t KdTree::Add(const VHACD::Vertex& v)
  3185. {
  3186. uint32_t ret = uint32_t(m_vertices.size());
  3187. m_vertices.emplace_back(v);
  3188. KdTreeNode& node = GetNewNode(ret);
  3189. if (m_root)
  3190. {
  3191. m_root->Add(node,
  3192. X_AXIS,
  3193. *this);
  3194. }
  3195. else
  3196. {
  3197. m_root = &node;
  3198. }
  3199. return ret;
  3200. }
  3201. KdTreeNode& KdTree::GetNewNode(uint32_t index)
  3202. {
  3203. KdTreeNode& node = m_bundle.GetNextNode();
  3204. node = KdTreeNode(index);
  3205. return node;
  3206. }
  3207. uint32_t KdTree::GetNearest(const VHACD::Vect3& pos,
  3208. double radius,
  3209. bool& _found) const // returns the nearest possible neighbor's index.
  3210. {
  3211. uint32_t ret = 0;
  3212. _found = false;
  3213. KdTreeFindNode found;
  3214. uint32_t count = Search(pos, radius, 1, &found);
  3215. if (count)
  3216. {
  3217. KdTreeNode* node = found.m_node;
  3218. ret = node->GetIndex();
  3219. _found = true;
  3220. }
  3221. return ret;
  3222. }
  3223. const std::vector<VHACD::Vertex>& KdTree::GetVertices() const
  3224. {
  3225. return m_vertices;
  3226. }
  3227. std::vector<VHACD::Vertex>&& KdTree::TakeVertices()
  3228. {
  3229. return std::move(m_vertices);
  3230. }
  3231. uint32_t KdTree::GetVCount() const
  3232. {
  3233. return uint32_t(m_vertices.size());
  3234. }
  3235. KdTreeNode::KdTreeNode(uint32_t index)
  3236. : m_index(index)
  3237. {
  3238. }
  3239. void KdTreeNode::Add(KdTreeNode& node,
  3240. Axes dim,
  3241. const KdTree& tree)
  3242. {
  3243. Axes axis = X_AXIS;
  3244. uint32_t idx = 0;
  3245. switch (dim)
  3246. {
  3247. case X_AXIS:
  3248. idx = 0;
  3249. axis = Y_AXIS;
  3250. break;
  3251. case Y_AXIS:
  3252. idx = 1;
  3253. axis = Z_AXIS;
  3254. break;
  3255. case Z_AXIS:
  3256. idx = 2;
  3257. axis = X_AXIS;
  3258. break;
  3259. }
  3260. const VHACD::Vertex& nodePosition = tree.GetPosition(node.m_index);
  3261. const VHACD::Vertex& position = tree.GetPosition(m_index);
  3262. if (nodePosition[idx] <= position[idx])
  3263. {
  3264. if (m_left)
  3265. m_left->Add(node, axis, tree);
  3266. else
  3267. m_left = &node;
  3268. }
  3269. else
  3270. {
  3271. if (m_right)
  3272. m_right->Add(node, axis, tree);
  3273. else
  3274. m_right = &node;
  3275. }
  3276. }
  3277. uint32_t KdTreeNode::GetIndex() const
  3278. {
  3279. return m_index;
  3280. }
  3281. void KdTreeNode::Search(Axes axis,
  3282. const VHACD::Vect3& pos,
  3283. double radius,
  3284. uint32_t& count,
  3285. uint32_t maxObjects,
  3286. KdTreeFindNode* found,
  3287. const KdTree& iface)
  3288. {
  3289. const VHACD::Vect3 position = iface.GetPosition(m_index);
  3290. const VHACD::Vect3 d = pos - position;
  3291. KdTreeNode* search1 = 0;
  3292. KdTreeNode* search2 = 0;
  3293. uint32_t idx = 0;
  3294. switch (axis)
  3295. {
  3296. case X_AXIS:
  3297. idx = 0;
  3298. axis = Y_AXIS;
  3299. break;
  3300. case Y_AXIS:
  3301. idx = 1;
  3302. axis = Z_AXIS;
  3303. break;
  3304. case Z_AXIS:
  3305. idx = 2;
  3306. axis = X_AXIS;
  3307. break;
  3308. }
  3309. if (d[idx] <= 0) // JWR if we are to the left
  3310. {
  3311. search1 = m_left; // JWR then search to the left
  3312. if (-d[idx] < radius) // JWR if distance to the right is less than our search radius, continue on the right
  3313. // as well.
  3314. search2 = m_right;
  3315. }
  3316. else
  3317. {
  3318. search1 = m_right; // JWR ok, we go down the left tree
  3319. if (d[idx] < radius) // JWR if the distance from the right is less than our search radius
  3320. search2 = m_left;
  3321. }
  3322. double r2 = radius * radius;
  3323. double m = d.GetNormSquared();
  3324. if (m < r2)
  3325. {
  3326. switch (count)
  3327. {
  3328. case 0:
  3329. {
  3330. found[count].m_node = this;
  3331. found[count].m_distance = m;
  3332. break;
  3333. }
  3334. case 1:
  3335. {
  3336. if (m < found[0].m_distance)
  3337. {
  3338. if (maxObjects == 1)
  3339. {
  3340. found[0].m_node = this;
  3341. found[0].m_distance = m;
  3342. }
  3343. else
  3344. {
  3345. found[1] = found[0];
  3346. found[0].m_node = this;
  3347. found[0].m_distance = m;
  3348. }
  3349. }
  3350. else if (maxObjects > 1)
  3351. {
  3352. found[1].m_node = this;
  3353. found[1].m_distance = m;
  3354. }
  3355. break;
  3356. }
  3357. default:
  3358. {
  3359. bool inserted = false;
  3360. for (uint32_t i = 0; i < count; i++)
  3361. {
  3362. if (m < found[i].m_distance) // if this one is closer than a pre-existing one...
  3363. {
  3364. // insertion sort...
  3365. uint32_t scan = count;
  3366. if (scan >= maxObjects)
  3367. scan = maxObjects - 1;
  3368. for (uint32_t j = scan; j > i; j--)
  3369. {
  3370. found[j] = found[j - 1];
  3371. }
  3372. found[i].m_node = this;
  3373. found[i].m_distance = m;
  3374. inserted = true;
  3375. break;
  3376. }
  3377. }
  3378. if (!inserted && count < maxObjects)
  3379. {
  3380. found[count].m_node = this;
  3381. found[count].m_distance = m;
  3382. }
  3383. }
  3384. break;
  3385. }
  3386. count++;
  3387. if (count > maxObjects)
  3388. {
  3389. count = maxObjects;
  3390. }
  3391. }
  3392. if (search1)
  3393. search1->Search(axis, pos, radius, count, maxObjects, found, iface);
  3394. if (search2)
  3395. search2->Search(axis, pos, radius, count, maxObjects, found, iface);
  3396. }
  3397. class VertexIndex
  3398. {
  3399. public:
  3400. VertexIndex(double granularity,
  3401. bool snapToGrid);
  3402. VHACD::Vect3 SnapToGrid(VHACD::Vect3 p);
  3403. uint32_t GetIndex(VHACD::Vect3 p,
  3404. bool& newPos);
  3405. const std::vector<VHACD::Vertex>& GetVertices() const;
  3406. std::vector<VHACD::Vertex>&& TakeVertices();
  3407. uint32_t GetVCount() const;
  3408. bool SaveAsObj(const char* fname,
  3409. uint32_t tcount,
  3410. uint32_t* indices)
  3411. {
  3412. bool ret = false;
  3413. FILE* fph = fopen(fname, "wb");
  3414. if (fph)
  3415. {
  3416. ret = true;
  3417. const std::vector<VHACD::Vertex>& v = GetVertices();
  3418. for (uint32_t i = 0; i < v.size(); ++i)
  3419. {
  3420. fprintf(fph, "v %0.9f %0.9f %0.9f\r\n",
  3421. v[i].mX,
  3422. v[i].mY,
  3423. v[i].mZ);
  3424. }
  3425. for (uint32_t i = 0; i < tcount; i++)
  3426. {
  3427. uint32_t i1 = *indices++;
  3428. uint32_t i2 = *indices++;
  3429. uint32_t i3 = *indices++;
  3430. fprintf(fph, "f %d %d %d\r\n",
  3431. i1 + 1,
  3432. i2 + 1,
  3433. i3 + 1);
  3434. }
  3435. fclose(fph);
  3436. }
  3437. return ret;
  3438. }
  3439. private:
  3440. bool m_snapToGrid : 1;
  3441. double m_granularity;
  3442. KdTree m_KdTree;
  3443. };
  3444. VertexIndex::VertexIndex(double granularity,
  3445. bool snapToGrid)
  3446. : m_snapToGrid(snapToGrid)
  3447. , m_granularity(granularity)
  3448. {
  3449. }
  3450. VHACD::Vect3 VertexIndex::SnapToGrid(VHACD::Vect3 p)
  3451. {
  3452. for (int i = 0; i < 3; ++i)
  3453. {
  3454. double m = fmod(p[i], m_granularity);
  3455. p[i] -= m;
  3456. }
  3457. return p;
  3458. }
  3459. uint32_t VertexIndex::GetIndex(VHACD::Vect3 p,
  3460. bool& newPos)
  3461. {
  3462. uint32_t ret;
  3463. newPos = false;
  3464. if (m_snapToGrid)
  3465. {
  3466. p = SnapToGrid(p);
  3467. }
  3468. bool found;
  3469. ret = m_KdTree.GetNearest(p, m_granularity, found);
  3470. if (!found)
  3471. {
  3472. newPos = true;
  3473. ret = m_KdTree.Add(VHACD::Vertex(p.GetX(), p.GetY(), p.GetZ()));
  3474. }
  3475. return ret;
  3476. }
  3477. const std::vector<VHACD::Vertex>& VertexIndex::GetVertices() const
  3478. {
  3479. return m_KdTree.GetVertices();
  3480. }
  3481. std::vector<VHACD::Vertex>&& VertexIndex::TakeVertices()
  3482. {
  3483. return std::move(m_KdTree.TakeVertices());
  3484. }
  3485. uint32_t VertexIndex::GetVCount() const
  3486. {
  3487. return m_KdTree.GetVCount();
  3488. }
  3489. /*
  3490. * A wrapper class for 3 10 bit integers packed into a 32 bit integer
  3491. * Layout is [PAD][X][Y][Z]
  3492. * Pad is bits 31-30, X is 29-20, Y is 19-10, and Z is 9-0
  3493. */
  3494. class Voxel
  3495. {
  3496. /*
  3497. * Specify all of them for consistency
  3498. */
  3499. static constexpr int VoxelBitsZStart = 0;
  3500. static constexpr int VoxelBitsYStart = 10;
  3501. static constexpr int VoxelBitsXStart = 20;
  3502. static constexpr int VoxelBitMask = 0x03FF; // bits 0 through 9 inclusive
  3503. public:
  3504. Voxel() = default;
  3505. Voxel(uint32_t index);
  3506. Voxel(uint32_t x,
  3507. uint32_t y,
  3508. uint32_t z);
  3509. bool operator==(const Voxel &v) const;
  3510. VHACD::Vector3<uint32_t> GetVoxel() const;
  3511. uint32_t GetX() const;
  3512. uint32_t GetY() const;
  3513. uint32_t GetZ() const;
  3514. uint32_t GetVoxelAddress() const;
  3515. private:
  3516. uint32_t m_voxel{ 0 };
  3517. };
  3518. Voxel::Voxel(uint32_t index)
  3519. : m_voxel(index)
  3520. {
  3521. }
  3522. Voxel::Voxel(uint32_t x,
  3523. uint32_t y,
  3524. uint32_t z)
  3525. : m_voxel((x << VoxelBitsXStart) | (y << VoxelBitsYStart) | (z << VoxelBitsZStart))
  3526. {
  3527. assert(x < 1024 && "Voxel constructed with X outside of range");
  3528. assert(y < 1024 && "Voxel constructed with Y outside of range");
  3529. assert(z < 1024 && "Voxel constructed with Z outside of range");
  3530. }
  3531. bool Voxel::operator==(const Voxel& v) const
  3532. {
  3533. return m_voxel == v.m_voxel;
  3534. }
  3535. VHACD::Vector3<uint32_t> Voxel::GetVoxel() const
  3536. {
  3537. return VHACD::Vector3<uint32_t>(GetX(), GetY(), GetZ());
  3538. }
  3539. uint32_t Voxel::GetX() const
  3540. {
  3541. return (m_voxel >> VoxelBitsXStart) & VoxelBitMask;
  3542. }
  3543. uint32_t Voxel::GetY() const
  3544. {
  3545. return (m_voxel >> VoxelBitsYStart) & VoxelBitMask;
  3546. }
  3547. uint32_t Voxel::GetZ() const
  3548. {
  3549. return (m_voxel >> VoxelBitsZStart) & VoxelBitMask;
  3550. }
  3551. uint32_t Voxel::GetVoxelAddress() const
  3552. {
  3553. return m_voxel;
  3554. }
  3555. struct SimpleMesh
  3556. {
  3557. std::vector<VHACD::Vertex> m_vertices;
  3558. std::vector<VHACD::Triangle> m_indices;
  3559. };
  3560. /*======================== 0-tests ========================*/
  3561. inline bool IntersectRayAABB(const VHACD::Vect3& start,
  3562. const VHACD::Vect3& dir,
  3563. const VHACD::BoundsAABB& bounds,
  3564. double& t)
  3565. {
  3566. //! calculate candidate plane on each axis
  3567. bool inside = true;
  3568. VHACD::Vect3 ta(double(-1.0));
  3569. //! use unrolled loops
  3570. for (uint32_t i = 0; i < 3; ++i)
  3571. {
  3572. if (start[i] < bounds.GetMin()[i])
  3573. {
  3574. if (dir[i] != double(0.0))
  3575. ta[i] = (bounds.GetMin()[i] - start[i]) / dir[i];
  3576. inside = false;
  3577. }
  3578. else if (start[i] > bounds.GetMax()[i])
  3579. {
  3580. if (dir[i] != double(0.0))
  3581. ta[i] = (bounds.GetMax()[i] - start[i]) / dir[i];
  3582. inside = false;
  3583. }
  3584. }
  3585. //! if point inside all planes
  3586. if (inside)
  3587. {
  3588. t = double(0.0);
  3589. return true;
  3590. }
  3591. //! we now have t values for each of possible intersection planes
  3592. //! find the maximum to get the intersection point
  3593. uint32_t taxis;
  3594. double tmax = ta.MaxCoeff(taxis);
  3595. if (tmax < double(0.0))
  3596. return false;
  3597. //! check that the intersection point lies on the plane we picked
  3598. //! we don't test the axis of closest intersection for precision reasons
  3599. //! no eps for now
  3600. double eps = double(0.0);
  3601. VHACD::Vect3 hit = start + dir * tmax;
  3602. if (( hit.GetX() < bounds.GetMin().GetX() - eps
  3603. || hit.GetX() > bounds.GetMax().GetX() + eps)
  3604. && taxis != 0)
  3605. return false;
  3606. if (( hit.GetY() < bounds.GetMin().GetY() - eps
  3607. || hit.GetY() > bounds.GetMax().GetY() + eps)
  3608. && taxis != 1)
  3609. return false;
  3610. if (( hit.GetZ() < bounds.GetMin().GetZ() - eps
  3611. || hit.GetZ() > bounds.GetMax().GetZ() + eps)
  3612. && taxis != 2)
  3613. return false;
  3614. //! output results
  3615. t = tmax;
  3616. return true;
  3617. }
  3618. // Moller and Trumbore's method
  3619. inline bool IntersectRayTriTwoSided(const VHACD::Vect3& p,
  3620. const VHACD::Vect3& dir,
  3621. const VHACD::Vect3& a,
  3622. const VHACD::Vect3& b,
  3623. const VHACD::Vect3& c,
  3624. double& t,
  3625. double& u,
  3626. double& v,
  3627. double& w,
  3628. double& sign,
  3629. VHACD::Vect3* normal)
  3630. {
  3631. VHACD::Vect3 ab = b - a;
  3632. VHACD::Vect3 ac = c - a;
  3633. VHACD::Vect3 n = ab.Cross(ac);
  3634. double d = -dir.Dot(n);
  3635. double ood = double(1.0) / d; // No need to check for division by zero here as infinity arithmetic will save us...
  3636. VHACD::Vect3 ap = p - a;
  3637. t = ap.Dot(n) * ood;
  3638. if (t < double(0.0))
  3639. {
  3640. return false;
  3641. }
  3642. VHACD::Vect3 e = -dir.Cross(ap);
  3643. v = ac.Dot(e) * ood;
  3644. if (v < double(0.0) || v > double(1.0)) // ...here...
  3645. {
  3646. return false;
  3647. }
  3648. w = -ab.Dot(e) * ood;
  3649. if (w < double(0.0) || v + w > double(1.0)) // ...and here
  3650. {
  3651. return false;
  3652. }
  3653. u = double(1.0) - v - w;
  3654. if (normal)
  3655. {
  3656. *normal = n;
  3657. }
  3658. sign = d;
  3659. return true;
  3660. }
  3661. // RTCD 5.1.5, page 142
  3662. inline VHACD::Vect3 ClosestPointOnTriangle(const VHACD::Vect3& a,
  3663. const VHACD::Vect3& b,
  3664. const VHACD::Vect3& c,
  3665. const VHACD::Vect3& p,
  3666. double& v,
  3667. double& w)
  3668. {
  3669. VHACD::Vect3 ab = b - a;
  3670. VHACD::Vect3 ac = c - a;
  3671. VHACD::Vect3 ap = p - a;
  3672. double d1 = ab.Dot(ap);
  3673. double d2 = ac.Dot(ap);
  3674. if ( d1 <= double(0.0)
  3675. && d2 <= double(0.0))
  3676. {
  3677. v = double(0.0);
  3678. w = double(0.0);
  3679. return a;
  3680. }
  3681. VHACD::Vect3 bp = p - b;
  3682. double d3 = ab.Dot(bp);
  3683. double d4 = ac.Dot(bp);
  3684. if ( d3 >= double(0.0)
  3685. && d4 <= d3)
  3686. {
  3687. v = double(1.0);
  3688. w = double(0.0);
  3689. return b;
  3690. }
  3691. double vc = d1 * d4 - d3 * d2;
  3692. if ( vc <= double(0.0)
  3693. && d1 >= double(0.0)
  3694. && d3 <= double(0.0))
  3695. {
  3696. v = d1 / (d1 - d3);
  3697. w = double(0.0);
  3698. return a + v * ab;
  3699. }
  3700. VHACD::Vect3 cp = p - c;
  3701. double d5 = ab.Dot(cp);
  3702. double d6 = ac.Dot(cp);
  3703. if (d6 >= double(0.0) && d5 <= d6)
  3704. {
  3705. v = double(0.0);
  3706. w = double(1.0);
  3707. return c;
  3708. }
  3709. double vb = d5 * d2 - d1 * d6;
  3710. if ( vb <= double(0.0)
  3711. && d2 >= double(0.0)
  3712. && d6 <= double(0.0))
  3713. {
  3714. v = double(0.0);
  3715. w = d2 / (d2 - d6);
  3716. return a + w * ac;
  3717. }
  3718. double va = d3 * d6 - d5 * d4;
  3719. if ( va <= double(0.0)
  3720. && (d4 - d3) >= double(0.0)
  3721. && (d5 - d6) >= double(0.0))
  3722. {
  3723. w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
  3724. v = double(1.0) - w;
  3725. return b + w * (c - b);
  3726. }
  3727. double denom = double(1.0) / (va + vb + vc);
  3728. v = vb * denom;
  3729. w = vc * denom;
  3730. return a + ab * v + ac * w;
  3731. }
  3732. class AABBTree
  3733. {
  3734. public:
  3735. AABBTree() = default;
  3736. AABBTree(AABBTree&&) = default;
  3737. AABBTree& operator=(AABBTree&&) = default;
  3738. AABBTree(const std::vector<VHACD::Vertex>& vertices,
  3739. const std::vector<VHACD::Triangle>& indices);
  3740. bool TraceRay(const VHACD::Vect3& start,
  3741. const VHACD::Vect3& to,
  3742. double& outT,
  3743. double& faceSign,
  3744. VHACD::Vect3& hitLocation) const;
  3745. bool TraceRay(const VHACD::Vect3& start,
  3746. const VHACD::Vect3& dir,
  3747. uint32_t& insideCount,
  3748. uint32_t& outsideCount) const;
  3749. bool TraceRay(const VHACD::Vect3& start,
  3750. const VHACD::Vect3& dir,
  3751. double& outT,
  3752. double& u,
  3753. double& v,
  3754. double& w,
  3755. double& faceSign,
  3756. uint32_t& faceIndex) const;
  3757. VHACD::Vect3 GetCenter() const;
  3758. VHACD::Vect3 GetMinExtents() const;
  3759. VHACD::Vect3 GetMaxExtents() const;
  3760. bool GetClosestPointWithinDistance(const VHACD::Vect3& point,
  3761. double maxDistance,
  3762. VHACD::Vect3& closestPoint) const;
  3763. private:
  3764. struct Node
  3765. {
  3766. union
  3767. {
  3768. uint32_t m_children;
  3769. uint32_t m_numFaces{ 0 };
  3770. };
  3771. uint32_t* m_faces{ nullptr };
  3772. VHACD::BoundsAABB m_extents;
  3773. };
  3774. struct FaceSorter
  3775. {
  3776. FaceSorter(const std::vector<VHACD::Vertex>& positions,
  3777. const std::vector<VHACD::Triangle>& indices,
  3778. uint32_t axis);
  3779. bool operator()(uint32_t lhs, uint32_t rhs) const;
  3780. double GetCentroid(uint32_t face) const;
  3781. const std::vector<VHACD::Vertex>& m_vertices;
  3782. const std::vector<VHACD::Triangle>& m_indices;
  3783. uint32_t m_axis;
  3784. };
  3785. // partition the objects and return the number of objects in the lower partition
  3786. uint32_t PartitionMedian(Node& n,
  3787. uint32_t* faces,
  3788. uint32_t numFaces);
  3789. uint32_t PartitionSAH(Node& n,
  3790. uint32_t* faces,
  3791. uint32_t numFaces);
  3792. void Build();
  3793. void BuildRecursive(uint32_t nodeIndex,
  3794. uint32_t* faces,
  3795. uint32_t numFaces);
  3796. void TraceRecursive(uint32_t nodeIndex,
  3797. const VHACD::Vect3& start,
  3798. const VHACD::Vect3& dir,
  3799. double& outT,
  3800. double& u,
  3801. double& v,
  3802. double& w,
  3803. double& faceSign,
  3804. uint32_t& faceIndex) const;
  3805. bool GetClosestPointWithinDistance(const VHACD::Vect3& point,
  3806. const double maxDis,
  3807. double& dis,
  3808. double& v,
  3809. double& w,
  3810. uint32_t& faceIndex,
  3811. VHACD::Vect3& closest) const;
  3812. void GetClosestPointWithinDistanceSqRecursive(uint32_t nodeIndex,
  3813. const VHACD::Vect3& point,
  3814. double& outDisSq,
  3815. double& outV,
  3816. double& outW,
  3817. uint32_t& outFaceIndex,
  3818. VHACD::Vect3& closest) const;
  3819. VHACD::BoundsAABB CalculateFaceBounds(uint32_t* faces,
  3820. uint32_t numFaces);
  3821. // track the next free node
  3822. uint32_t m_freeNode;
  3823. const std::vector<VHACD::Vertex>* m_vertices{ nullptr };
  3824. const std::vector<VHACD::Triangle>* m_indices{ nullptr };
  3825. std::vector<uint32_t> m_faces;
  3826. std::vector<Node> m_nodes;
  3827. std::vector<VHACD::BoundsAABB> m_faceBounds;
  3828. // stats
  3829. uint32_t m_treeDepth{ 0 };
  3830. uint32_t m_innerNodes{ 0 };
  3831. uint32_t m_leafNodes{ 0 };
  3832. uint32_t s_depth{ 0 };
  3833. };
  3834. AABBTree::FaceSorter::FaceSorter(const std::vector<VHACD::Vertex>& positions,
  3835. const std::vector<VHACD::Triangle>& indices,
  3836. uint32_t axis)
  3837. : m_vertices(positions)
  3838. , m_indices(indices)
  3839. , m_axis(axis)
  3840. {
  3841. }
  3842. inline bool AABBTree::FaceSorter::operator()(uint32_t lhs,
  3843. uint32_t rhs) const
  3844. {
  3845. double a = GetCentroid(lhs);
  3846. double b = GetCentroid(rhs);
  3847. if (a == b)
  3848. {
  3849. return lhs < rhs;
  3850. }
  3851. else
  3852. {
  3853. return a < b;
  3854. }
  3855. }
  3856. inline double AABBTree::FaceSorter::GetCentroid(uint32_t face) const
  3857. {
  3858. const VHACD::Vect3& a = m_vertices[m_indices[face].mI0];
  3859. const VHACD::Vect3& b = m_vertices[m_indices[face].mI1];
  3860. const VHACD::Vect3& c = m_vertices[m_indices[face].mI2];
  3861. return (a[m_axis] + b[m_axis] + c[m_axis]) / double(3.0);
  3862. }
  3863. AABBTree::AABBTree(const std::vector<VHACD::Vertex>& vertices,
  3864. const std::vector<VHACD::Triangle>& indices)
  3865. : m_vertices(&vertices)
  3866. , m_indices(&indices)
  3867. {
  3868. Build();
  3869. }
  3870. bool AABBTree::TraceRay(const VHACD::Vect3& start,
  3871. const VHACD::Vect3& to,
  3872. double& outT,
  3873. double& faceSign,
  3874. VHACD::Vect3& hitLocation) const
  3875. {
  3876. VHACD::Vect3 dir = to - start;
  3877. double distance = dir.Normalize();
  3878. double u, v, w;
  3879. uint32_t faceIndex;
  3880. bool hit = TraceRay(start,
  3881. dir,
  3882. outT,
  3883. u,
  3884. v,
  3885. w,
  3886. faceSign,
  3887. faceIndex);
  3888. if (hit)
  3889. {
  3890. hitLocation = start + dir * outT;
  3891. }
  3892. if (hit && outT > distance)
  3893. {
  3894. hit = false;
  3895. }
  3896. return hit;
  3897. }
  3898. bool AABBTree::TraceRay(const VHACD::Vect3& start,
  3899. const VHACD::Vect3& dir,
  3900. uint32_t& insideCount,
  3901. uint32_t& outsideCount) const
  3902. {
  3903. double outT, u, v, w, faceSign;
  3904. uint32_t faceIndex;
  3905. bool hit = TraceRay(start,
  3906. dir,
  3907. outT,
  3908. u,
  3909. v,
  3910. w,
  3911. faceSign,
  3912. faceIndex);
  3913. if (hit)
  3914. {
  3915. if (faceSign >= 0)
  3916. {
  3917. insideCount++;
  3918. }
  3919. else
  3920. {
  3921. outsideCount++;
  3922. }
  3923. }
  3924. return hit;
  3925. }
  3926. bool AABBTree::TraceRay(const VHACD::Vect3& start,
  3927. const VHACD::Vect3& dir,
  3928. double& outT,
  3929. double& u,
  3930. double& v,
  3931. double& w,
  3932. double& faceSign,
  3933. uint32_t& faceIndex) const
  3934. {
  3935. outT = FLT_MAX;
  3936. TraceRecursive(0,
  3937. start,
  3938. dir,
  3939. outT,
  3940. u,
  3941. v,
  3942. w,
  3943. faceSign,
  3944. faceIndex);
  3945. return (outT != FLT_MAX);
  3946. }
  3947. VHACD::Vect3 AABBTree::GetCenter() const
  3948. {
  3949. return m_nodes[0].m_extents.GetCenter();
  3950. }
  3951. VHACD::Vect3 AABBTree::GetMinExtents() const
  3952. {
  3953. return m_nodes[0].m_extents.GetMin();
  3954. }
  3955. VHACD::Vect3 AABBTree::GetMaxExtents() const
  3956. {
  3957. return m_nodes[0].m_extents.GetMax();
  3958. }
  3959. bool AABBTree::GetClosestPointWithinDistance(const VHACD::Vect3& point,
  3960. double maxDistance,
  3961. VHACD::Vect3& closestPoint) const
  3962. {
  3963. double dis, v, w;
  3964. uint32_t faceIndex;
  3965. bool hit = GetClosestPointWithinDistance(point,
  3966. maxDistance,
  3967. dis,
  3968. v,
  3969. w,
  3970. faceIndex,
  3971. closestPoint);
  3972. return hit;
  3973. }
  3974. // partition faces around the median face
  3975. uint32_t AABBTree::PartitionMedian(Node& n,
  3976. uint32_t* faces,
  3977. uint32_t numFaces)
  3978. {
  3979. FaceSorter predicate(*m_vertices,
  3980. *m_indices,
  3981. n.m_extents.GetSize().LongestAxis());
  3982. std::nth_element(faces,
  3983. faces + numFaces / 2,
  3984. faces + numFaces,
  3985. predicate);
  3986. return numFaces / 2;
  3987. }
  3988. // partition faces based on the surface area heuristic
  3989. uint32_t AABBTree::PartitionSAH(Node&,
  3990. uint32_t* faces,
  3991. uint32_t numFaces)
  3992. {
  3993. uint32_t bestAxis = 0;
  3994. uint32_t bestIndex = 0;
  3995. double bestCost = FLT_MAX;
  3996. for (uint32_t a = 0; a < 3; ++a)
  3997. {
  3998. // sort faces by centroids
  3999. FaceSorter predicate(*m_vertices,
  4000. *m_indices,
  4001. a);
  4002. std::sort(faces,
  4003. faces + numFaces,
  4004. predicate);
  4005. // two passes over data to calculate upper and lower bounds
  4006. std::vector<double> cumulativeLower(numFaces);
  4007. std::vector<double> cumulativeUpper(numFaces);
  4008. VHACD::BoundsAABB lower;
  4009. VHACD::BoundsAABB upper;
  4010. for (uint32_t i = 0; i < numFaces; ++i)
  4011. {
  4012. lower.Union(m_faceBounds[faces[i]]);
  4013. upper.Union(m_faceBounds[faces[numFaces - i - 1]]);
  4014. cumulativeLower[i] = lower.SurfaceArea();
  4015. cumulativeUpper[numFaces - i - 1] = upper.SurfaceArea();
  4016. }
  4017. double invTotalSA = double(1.0) / cumulativeUpper[0];
  4018. // test all split positions
  4019. for (uint32_t i = 0; i < numFaces - 1; ++i)
  4020. {
  4021. double pBelow = cumulativeLower[i] * invTotalSA;
  4022. double pAbove = cumulativeUpper[i] * invTotalSA;
  4023. double cost = double(0.125) + (pBelow * i + pAbove * (numFaces - i));
  4024. if (cost <= bestCost)
  4025. {
  4026. bestCost = cost;
  4027. bestIndex = i;
  4028. bestAxis = a;
  4029. }
  4030. }
  4031. }
  4032. // re-sort by best axis
  4033. FaceSorter predicate(*m_vertices,
  4034. *m_indices,
  4035. bestAxis);
  4036. std::sort(faces,
  4037. faces + numFaces,
  4038. predicate);
  4039. return bestIndex + 1;
  4040. }
  4041. void AABBTree::Build()
  4042. {
  4043. const uint32_t numFaces = uint32_t(m_indices->size());
  4044. // build initial list of faces
  4045. m_faces.reserve(numFaces);
  4046. // calculate bounds of each face and store
  4047. m_faceBounds.reserve(numFaces);
  4048. std::vector<VHACD::BoundsAABB> stack;
  4049. for (uint32_t i = 0; i < numFaces; ++i)
  4050. {
  4051. VHACD::BoundsAABB top = CalculateFaceBounds(&i,
  4052. 1);
  4053. m_faces.push_back(i);
  4054. m_faceBounds.push_back(top);
  4055. }
  4056. m_nodes.reserve(uint32_t(numFaces * double(1.5)));
  4057. // allocate space for all the nodes
  4058. m_freeNode = 1;
  4059. // start building
  4060. BuildRecursive(0,
  4061. m_faces.data(),
  4062. numFaces);
  4063. assert(s_depth == 0);
  4064. }
  4065. void AABBTree::BuildRecursive(uint32_t nodeIndex,
  4066. uint32_t* faces,
  4067. uint32_t numFaces)
  4068. {
  4069. const uint32_t kMaxFacesPerLeaf = 6;
  4070. // if we've run out of nodes allocate some more
  4071. if (nodeIndex >= m_nodes.size())
  4072. {
  4073. uint32_t s = std::max(uint32_t(double(1.5) * m_nodes.size()), 512U);
  4074. m_nodes.resize(s);
  4075. }
  4076. // a reference to the current node, need to be careful here as this reference may become invalid if array is resized
  4077. Node& n = m_nodes[nodeIndex];
  4078. // track max tree depth
  4079. ++s_depth;
  4080. m_treeDepth = std::max(m_treeDepth, s_depth);
  4081. n.m_extents = CalculateFaceBounds(faces,
  4082. numFaces);
  4083. // calculate bounds of faces and add node
  4084. if (numFaces <= kMaxFacesPerLeaf)
  4085. {
  4086. n.m_faces = faces;
  4087. n.m_numFaces = numFaces;
  4088. ++m_leafNodes;
  4089. }
  4090. else
  4091. {
  4092. ++m_innerNodes;
  4093. // face counts for each branch
  4094. const uint32_t leftCount = PartitionMedian(n, faces, numFaces);
  4095. // const uint32_t leftCount = PartitionSAH(n, faces, numFaces);
  4096. const uint32_t rightCount = numFaces - leftCount;
  4097. // alloc 2 nodes
  4098. m_nodes[nodeIndex].m_children = m_freeNode;
  4099. // allocate two nodes
  4100. m_freeNode += 2;
  4101. // split faces in half and build each side recursively
  4102. BuildRecursive(m_nodes[nodeIndex].m_children + 0, faces, leftCount);
  4103. BuildRecursive(m_nodes[nodeIndex].m_children + 1, faces + leftCount, rightCount);
  4104. }
  4105. --s_depth;
  4106. }
  4107. void AABBTree::TraceRecursive(uint32_t nodeIndex,
  4108. const VHACD::Vect3& start,
  4109. const VHACD::Vect3& dir,
  4110. double& outT,
  4111. double& outU,
  4112. double& outV,
  4113. double& outW,
  4114. double& faceSign,
  4115. uint32_t& faceIndex) const
  4116. {
  4117. const Node& node = m_nodes[nodeIndex];
  4118. if (node.m_faces == NULL)
  4119. {
  4120. // find closest node
  4121. const Node& leftChild = m_nodes[node.m_children + 0];
  4122. const Node& rightChild = m_nodes[node.m_children + 1];
  4123. double dist[2] = { FLT_MAX, FLT_MAX };
  4124. IntersectRayAABB(start,
  4125. dir,
  4126. leftChild.m_extents,
  4127. dist[0]);
  4128. IntersectRayAABB(start,
  4129. dir,
  4130. rightChild.m_extents,
  4131. dist[1]);
  4132. uint32_t closest = 0;
  4133. uint32_t furthest = 1;
  4134. if (dist[1] < dist[0])
  4135. {
  4136. closest = 1;
  4137. furthest = 0;
  4138. }
  4139. if (dist[closest] < outT)
  4140. {
  4141. TraceRecursive(node.m_children + closest,
  4142. start,
  4143. dir,
  4144. outT,
  4145. outU,
  4146. outV,
  4147. outW,
  4148. faceSign,
  4149. faceIndex);
  4150. }
  4151. if (dist[furthest] < outT)
  4152. {
  4153. TraceRecursive(node.m_children + furthest,
  4154. start,
  4155. dir,
  4156. outT,
  4157. outU,
  4158. outV,
  4159. outW,
  4160. faceSign,
  4161. faceIndex);
  4162. }
  4163. }
  4164. else
  4165. {
  4166. double t, u, v, w, s;
  4167. for (uint32_t i = 0; i < node.m_numFaces; ++i)
  4168. {
  4169. uint32_t indexStart = node.m_faces[i];
  4170. const VHACD::Vect3& a = (*m_vertices)[(*m_indices)[indexStart].mI0];
  4171. const VHACD::Vect3& b = (*m_vertices)[(*m_indices)[indexStart].mI1];
  4172. const VHACD::Vect3& c = (*m_vertices)[(*m_indices)[indexStart].mI2];
  4173. if (IntersectRayTriTwoSided(start, dir, a, b, c, t, u, v, w, s, NULL))
  4174. {
  4175. if (t < outT)
  4176. {
  4177. outT = t;
  4178. outU = u;
  4179. outV = v;
  4180. outW = w;
  4181. faceSign = s;
  4182. faceIndex = node.m_faces[i];
  4183. }
  4184. }
  4185. }
  4186. }
  4187. }
  4188. bool AABBTree::GetClosestPointWithinDistance(const VHACD::Vect3& point,
  4189. const double maxDis,
  4190. double& dis,
  4191. double& v,
  4192. double& w,
  4193. uint32_t& faceIndex,
  4194. VHACD::Vect3& closest) const
  4195. {
  4196. dis = maxDis;
  4197. faceIndex = uint32_t(~0);
  4198. double disSq = dis * dis;
  4199. GetClosestPointWithinDistanceSqRecursive(0,
  4200. point,
  4201. disSq,
  4202. v,
  4203. w,
  4204. faceIndex,
  4205. closest);
  4206. dis = sqrt(disSq);
  4207. return (faceIndex < (~(static_cast<unsigned int>(0))));
  4208. }
  4209. void AABBTree::GetClosestPointWithinDistanceSqRecursive(uint32_t nodeIndex,
  4210. const VHACD::Vect3& point,
  4211. double& outDisSq,
  4212. double& outV,
  4213. double& outW,
  4214. uint32_t& outFaceIndex,
  4215. VHACD::Vect3& closestPoint) const
  4216. {
  4217. const Node& node = m_nodes[nodeIndex];
  4218. if (node.m_faces == nullptr)
  4219. {
  4220. // find closest node
  4221. const Node& leftChild = m_nodes[node.m_children + 0];
  4222. const Node& rightChild = m_nodes[node.m_children + 1];
  4223. // double dist[2] = { FLT_MAX, FLT_MAX };
  4224. VHACD::Vect3 lp = leftChild.m_extents.ClosestPoint(point);
  4225. VHACD::Vect3 rp = rightChild.m_extents.ClosestPoint(point);
  4226. uint32_t closest = 0;
  4227. uint32_t furthest = 1;
  4228. double dcSq = (point - lp).GetNormSquared();
  4229. double dfSq = (point - rp).GetNormSquared();
  4230. if (dfSq < dcSq)
  4231. {
  4232. closest = 1;
  4233. furthest = 0;
  4234. std::swap(dfSq, dcSq);
  4235. }
  4236. if (dcSq < outDisSq)
  4237. {
  4238. GetClosestPointWithinDistanceSqRecursive(node.m_children + closest,
  4239. point,
  4240. outDisSq,
  4241. outV,
  4242. outW,
  4243. outFaceIndex,
  4244. closestPoint);
  4245. }
  4246. if (dfSq < outDisSq)
  4247. {
  4248. GetClosestPointWithinDistanceSqRecursive(node.m_children + furthest,
  4249. point,
  4250. outDisSq,
  4251. outV,
  4252. outW,
  4253. outFaceIndex,
  4254. closestPoint);
  4255. }
  4256. }
  4257. else
  4258. {
  4259. double v, w;
  4260. for (uint32_t i = 0; i < node.m_numFaces; ++i)
  4261. {
  4262. uint32_t indexStart = node.m_faces[i];
  4263. const VHACD::Vect3& a = (*m_vertices)[(*m_indices)[indexStart].mI0];
  4264. const VHACD::Vect3& b = (*m_vertices)[(*m_indices)[indexStart].mI1];
  4265. const VHACD::Vect3& c = (*m_vertices)[(*m_indices)[indexStart].mI2];
  4266. VHACD::Vect3 cp = ClosestPointOnTriangle(a, b, c, point, v, w);
  4267. double disSq = (cp - point).GetNormSquared();
  4268. if (disSq < outDisSq)
  4269. {
  4270. closestPoint = cp;
  4271. outDisSq = disSq;
  4272. outV = v;
  4273. outW = w;
  4274. outFaceIndex = node.m_faces[i];
  4275. }
  4276. }
  4277. }
  4278. }
  4279. VHACD::BoundsAABB AABBTree::CalculateFaceBounds(uint32_t* faces,
  4280. uint32_t numFaces)
  4281. {
  4282. VHACD::Vect3 minExtents( FLT_MAX);
  4283. VHACD::Vect3 maxExtents(-FLT_MAX);
  4284. // calculate face bounds
  4285. for (uint32_t i = 0; i < numFaces; ++i)
  4286. {
  4287. VHACD::Vect3 a = (*m_vertices)[(*m_indices)[faces[i]].mI0];
  4288. VHACD::Vect3 b = (*m_vertices)[(*m_indices)[faces[i]].mI1];
  4289. VHACD::Vect3 c = (*m_vertices)[(*m_indices)[faces[i]].mI2];
  4290. minExtents = a.CWiseMin(minExtents);
  4291. maxExtents = a.CWiseMax(maxExtents);
  4292. minExtents = b.CWiseMin(minExtents);
  4293. maxExtents = b.CWiseMax(maxExtents);
  4294. minExtents = c.CWiseMin(minExtents);
  4295. maxExtents = c.CWiseMax(maxExtents);
  4296. }
  4297. return VHACD::BoundsAABB(minExtents,
  4298. maxExtents);
  4299. }
  4300. enum class VoxelValue : uint8_t
  4301. {
  4302. PRIMITIVE_UNDEFINED = 0,
  4303. PRIMITIVE_OUTSIDE_SURFACE_TOWALK = 1,
  4304. PRIMITIVE_OUTSIDE_SURFACE = 2,
  4305. PRIMITIVE_INSIDE_SURFACE = 3,
  4306. PRIMITIVE_ON_SURFACE = 4
  4307. };
  4308. class Volume
  4309. {
  4310. public:
  4311. void Voxelize(const std::vector<VHACD::Vertex>& points,
  4312. const std::vector<VHACD::Triangle>& triangles,
  4313. const size_t dim,
  4314. FillMode fillMode,
  4315. const AABBTree& aabbTree);
  4316. void RaycastFill(const AABBTree& aabbTree);
  4317. void SetVoxel(const size_t i,
  4318. const size_t j,
  4319. const size_t k,
  4320. VoxelValue value);
  4321. VoxelValue& GetVoxel(const size_t i,
  4322. const size_t j,
  4323. const size_t k);
  4324. const VoxelValue& GetVoxel(const size_t i,
  4325. const size_t j,
  4326. const size_t k) const;
  4327. const std::vector<Voxel>& GetSurfaceVoxels() const;
  4328. const std::vector<Voxel>& GetInteriorVoxels() const;
  4329. double GetScale() const;
  4330. const VHACD::BoundsAABB& GetBounds() const;
  4331. const VHACD::Vector3<uint32_t>& GetDimensions() const;
  4332. VHACD::BoundsAABB m_bounds;
  4333. double m_scale{ 1.0 };
  4334. VHACD::Vector3<uint32_t> m_dim{ 0 };
  4335. size_t m_numVoxelsOnSurface{ 0 };
  4336. size_t m_numVoxelsInsideSurface{ 0 };
  4337. size_t m_numVoxelsOutsideSurface{ 0 };
  4338. std::vector<VoxelValue> m_data;
  4339. private:
  4340. void MarkOutsideSurface(const size_t i0,
  4341. const size_t j0,
  4342. const size_t k0,
  4343. const size_t i1,
  4344. const size_t j1,
  4345. const size_t k1);
  4346. void FillOutsideSurface();
  4347. void FillInsideSurface();
  4348. std::vector<VHACD::Voxel> m_surfaceVoxels;
  4349. std::vector<VHACD::Voxel> m_interiorVoxels;
  4350. };
  4351. bool PlaneBoxOverlap(const VHACD::Vect3& normal,
  4352. const VHACD::Vect3& vert,
  4353. const VHACD::Vect3& maxbox)
  4354. {
  4355. int32_t q;
  4356. VHACD::Vect3 vmin;
  4357. VHACD::Vect3 vmax;
  4358. double v;
  4359. for (q = 0; q < 3; q++)
  4360. {
  4361. v = vert[q];
  4362. if (normal[q] > double(0.0))
  4363. {
  4364. vmin[q] = -maxbox[q] - v;
  4365. vmax[q] = maxbox[q] - v;
  4366. }
  4367. else
  4368. {
  4369. vmin[q] = maxbox[q] - v;
  4370. vmax[q] = -maxbox[q] - v;
  4371. }
  4372. }
  4373. if (normal.Dot(vmin) > double(0.0))
  4374. return false;
  4375. if (normal.Dot(vmax) >= double(0.0))
  4376. return true;
  4377. return false;
  4378. }
  4379. bool AxisTest(double a, double b, double fa, double fb,
  4380. double v0, double v1, double v2, double v3,
  4381. double boxHalfSize1, double boxHalfSize2)
  4382. {
  4383. double p0 = a * v0 + b * v1;
  4384. double p1 = a * v2 + b * v3;
  4385. double min = std::min(p0, p1);
  4386. double max = std::max(p0, p1);
  4387. double rad = fa * boxHalfSize1 + fb * boxHalfSize2;
  4388. if (min > rad || max < -rad)
  4389. {
  4390. return false;
  4391. }
  4392. return true;
  4393. }
  4394. bool TriBoxOverlap(const VHACD::Vect3& boxCenter,
  4395. const VHACD::Vect3& boxHalfSize,
  4396. const VHACD::Vect3& triVer0,
  4397. const VHACD::Vect3& triVer1,
  4398. const VHACD::Vect3& triVer2)
  4399. {
  4400. /* use separating axis theorem to test overlap between triangle and box */
  4401. /* need to test for overlap in these directions: */
  4402. /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
  4403. /* we do not even need to test these) */
  4404. /* 2) normal of the triangle */
  4405. /* 3) crossproduct(edge from tri, {x,y,z}-direction) */
  4406. /* this gives 3x3=9 more tests */
  4407. VHACD::Vect3 v0 = triVer0 - boxCenter;
  4408. VHACD::Vect3 v1 = triVer1 - boxCenter;
  4409. VHACD::Vect3 v2 = triVer2 - boxCenter;
  4410. VHACD::Vect3 e0 = v1 - v0;
  4411. VHACD::Vect3 e1 = v2 - v1;
  4412. VHACD::Vect3 e2 = v0 - v2;
  4413. /* This is the fastest branch on Sun */
  4414. /* move everything so that the boxcenter is in (0,0,0) */
  4415. /* Bullet 3: */
  4416. /* test the 9 tests first (this was faster) */
  4417. double fex = fabs(e0[0]);
  4418. double fey = fabs(e0[1]);
  4419. double fez = fabs(e0[2]);
  4420. /*
  4421. * These should use Get*() instead of subscript for consistency, but the function calls are long enough already
  4422. */
  4423. if (!AxisTest( e0[2], -e0[1], fez, fey, v0[1], v0[2], v2[1], v2[2], boxHalfSize[1], boxHalfSize[2])) return 0; // X01
  4424. if (!AxisTest(-e0[2], e0[0], fez, fex, v0[0], v0[2], v2[0], v2[2], boxHalfSize[0], boxHalfSize[2])) return 0; // Y02
  4425. if (!AxisTest( e0[1], -e0[0], fey, fex, v1[0], v1[1], v2[0], v2[1], boxHalfSize[0], boxHalfSize[1])) return 0; // Z12
  4426. fex = fabs(e1[0]);
  4427. fey = fabs(e1[1]);
  4428. fez = fabs(e1[2]);
  4429. if (!AxisTest( e1[2], -e1[1], fez, fey, v0[1], v0[2], v2[1], v2[2], boxHalfSize[1], boxHalfSize[2])) return 0; // X01
  4430. if (!AxisTest(-e1[2], e1[0], fez, fex, v0[0], v0[2], v2[0], v2[2], boxHalfSize[0], boxHalfSize[2])) return 0; // Y02
  4431. if (!AxisTest( e1[1], -e1[0], fey, fex, v0[0], v0[1], v1[0], v1[1], boxHalfSize[0], boxHalfSize[2])) return 0; // Z0
  4432. fex = fabs(e2[0]);
  4433. fey = fabs(e2[1]);
  4434. fez = fabs(e2[2]);
  4435. if (!AxisTest( e2[2], -e2[1], fez, fey, v0[1], v0[2], v1[1], v1[2], boxHalfSize[1], boxHalfSize[2])) return 0; // X2
  4436. if (!AxisTest(-e2[2], e2[0], fez, fex, v0[0], v0[2], v1[0], v1[2], boxHalfSize[0], boxHalfSize[2])) return 0; // Y1
  4437. if (!AxisTest( e2[1], -e2[0], fey, fex, v1[0], v1[1], v2[0], v2[1], boxHalfSize[0], boxHalfSize[1])) return 0; // Z12
  4438. /* Bullet 1: */
  4439. /* first test overlap in the {x,y,z}-directions */
  4440. /* find min, max of the triangle each direction, and test for overlap in */
  4441. /* that direction -- this is equivalent to testing a minimal AABB around */
  4442. /* the triangle against the AABB */
  4443. /* test in 0-direction */
  4444. double min = std::min({v0.GetX(), v1.GetX(), v2.GetX()});
  4445. double max = std::max({v0.GetX(), v1.GetX(), v2.GetX()});
  4446. if (min > boxHalfSize[0] || max < -boxHalfSize[0])
  4447. return false;
  4448. /* test in 1-direction */
  4449. min = std::min({v0.GetY(), v1.GetY(), v2.GetY()});
  4450. max = std::max({v0.GetY(), v1.GetY(), v2.GetY()});
  4451. if (min > boxHalfSize[1] || max < -boxHalfSize[1])
  4452. return false;
  4453. /* test in getZ-direction */
  4454. min = std::min({v0.GetZ(), v1.GetZ(), v2.GetZ()});
  4455. max = std::max({v0.GetZ(), v1.GetZ(), v2.GetZ()});
  4456. if (min > boxHalfSize[2] || max < -boxHalfSize[2])
  4457. return false;
  4458. /* Bullet 2: */
  4459. /* test if the box intersects the plane of the triangle */
  4460. /* compute plane equation of triangle: normal*x+d=0 */
  4461. VHACD::Vect3 normal = e0.Cross(e1);
  4462. if (!PlaneBoxOverlap(normal, v0, boxHalfSize))
  4463. return false;
  4464. return true; /* box and triangle overlaps */
  4465. }
  4466. void Volume::Voxelize(const std::vector<VHACD::Vertex>& points,
  4467. const std::vector<VHACD::Triangle>& indices,
  4468. const size_t dimensions,
  4469. FillMode fillMode,
  4470. const AABBTree& aabbTree)
  4471. {
  4472. double a = std::pow(dimensions, 0.33);
  4473. size_t dim = a * double(1.5);
  4474. dim = std::max(dim, size_t(32));
  4475. if (points.size() == 0)
  4476. {
  4477. return;
  4478. }
  4479. m_bounds = BoundsAABB(points);
  4480. VHACD::Vect3 d = m_bounds.GetSize();
  4481. double r;
  4482. // Equal comparison is important here to avoid taking the last branch when d[0] == d[1] with d[2] being the smallest
  4483. // dimension. That would lead to dimensions in i and j to be a lot bigger than expected and make the amount of
  4484. // voxels in the volume totally unmanageable.
  4485. if (d[0] >= d[1] && d[0] >= d[2])
  4486. {
  4487. r = d[0];
  4488. m_dim[0] = uint32_t(dim);
  4489. m_dim[1] = uint32_t(2 + static_cast<size_t>(dim * d[1] / d[0]));
  4490. m_dim[2] = uint32_t(2 + static_cast<size_t>(dim * d[2] / d[0]));
  4491. }
  4492. else if (d[1] >= d[0] && d[1] >= d[2])
  4493. {
  4494. r = d[1];
  4495. m_dim[1] = uint32_t(dim);
  4496. m_dim[0] = uint32_t(2 + static_cast<size_t>(dim * d[0] / d[1]));
  4497. m_dim[2] = uint32_t(2 + static_cast<size_t>(dim * d[2] / d[1]));
  4498. }
  4499. else
  4500. {
  4501. r = d[2];
  4502. m_dim[2] = uint32_t(dim);
  4503. m_dim[0] = uint32_t(2 + static_cast<size_t>(dim * d[0] / d[2]));
  4504. m_dim[1] = uint32_t(2 + static_cast<size_t>(dim * d[1] / d[2]));
  4505. }
  4506. m_scale = r / (dim - 1);
  4507. double invScale = (dim - 1) / r;
  4508. m_data = std::vector<VoxelValue>(m_dim[0] * m_dim[1] * m_dim[2],
  4509. VoxelValue::PRIMITIVE_UNDEFINED);
  4510. m_numVoxelsOnSurface = 0;
  4511. m_numVoxelsInsideSurface = 0;
  4512. m_numVoxelsOutsideSurface = 0;
  4513. VHACD::Vect3 p[3];
  4514. VHACD::Vect3 boxcenter;
  4515. VHACD::Vect3 pt;
  4516. const VHACD::Vect3 boxhalfsize(double(0.5));
  4517. for (size_t t = 0; t < indices.size(); ++t)
  4518. {
  4519. size_t i0, j0, k0;
  4520. size_t i1, j1, k1;
  4521. VHACD::Vector3<uint32_t> tri = indices[t];
  4522. for (int32_t c = 0; c < 3; ++c)
  4523. {
  4524. pt = points[tri[c]];
  4525. p[c] = (pt - m_bounds.GetMin()) * invScale;
  4526. size_t i = static_cast<size_t>(p[c][0] + double(0.5));
  4527. size_t j = static_cast<size_t>(p[c][1] + double(0.5));
  4528. size_t k = static_cast<size_t>(p[c][2] + double(0.5));
  4529. assert(i < m_dim[0] && i >= 0 && j < m_dim[1] && j >= 0 && k < m_dim[2] && k >= 0);
  4530. if (c == 0)
  4531. {
  4532. i0 = i1 = i;
  4533. j0 = j1 = j;
  4534. k0 = k1 = k;
  4535. }
  4536. else
  4537. {
  4538. i0 = std::min(i0, i);
  4539. j0 = std::min(j0, j);
  4540. k0 = std::min(k0, k);
  4541. i1 = std::max(i1, i);
  4542. j1 = std::max(j1, j);
  4543. k1 = std::max(k1, k);
  4544. }
  4545. }
  4546. if (i0 > 0)
  4547. --i0;
  4548. if (j0 > 0)
  4549. --j0;
  4550. if (k0 > 0)
  4551. --k0;
  4552. if (i1 < m_dim[0])
  4553. ++i1;
  4554. if (j1 < m_dim[1])
  4555. ++j1;
  4556. if (k1 < m_dim[2])
  4557. ++k1;
  4558. for (size_t i_id = i0; i_id < i1; ++i_id)
  4559. {
  4560. boxcenter[0] = uint32_t(i_id);
  4561. for (size_t j_id = j0; j_id < j1; ++j_id)
  4562. {
  4563. boxcenter[1] = uint32_t(j_id);
  4564. for (size_t k_id = k0; k_id < k1; ++k_id)
  4565. {
  4566. boxcenter[2] = uint32_t(k_id);
  4567. bool res = TriBoxOverlap(boxcenter,
  4568. boxhalfsize,
  4569. p[0],
  4570. p[1],
  4571. p[2]);
  4572. VoxelValue& value = GetVoxel(i_id,
  4573. j_id,
  4574. k_id);
  4575. if ( res
  4576. && value == VoxelValue::PRIMITIVE_UNDEFINED)
  4577. {
  4578. value = VoxelValue::PRIMITIVE_ON_SURFACE;
  4579. ++m_numVoxelsOnSurface;
  4580. m_surfaceVoxels.emplace_back(uint32_t(i_id),
  4581. uint32_t(j_id),
  4582. uint32_t(k_id));
  4583. }
  4584. }
  4585. }
  4586. }
  4587. }
  4588. if (fillMode == FillMode::SURFACE_ONLY)
  4589. {
  4590. const size_t i0_local = m_dim[0];
  4591. const size_t j0_local = m_dim[1];
  4592. const size_t k0_local = m_dim[2];
  4593. for (size_t i_id = 0; i_id < i0_local; ++i_id)
  4594. {
  4595. for (size_t j_id = 0; j_id < j0_local; ++j_id)
  4596. {
  4597. for (size_t k_id = 0; k_id < k0_local; ++k_id)
  4598. {
  4599. const VoxelValue& voxel = GetVoxel(i_id,
  4600. j_id,
  4601. k_id);
  4602. if (voxel != VoxelValue::PRIMITIVE_ON_SURFACE)
  4603. {
  4604. SetVoxel(i_id,
  4605. j_id,
  4606. k_id,
  4607. VoxelValue::PRIMITIVE_OUTSIDE_SURFACE);
  4608. }
  4609. }
  4610. }
  4611. }
  4612. }
  4613. else if (fillMode == FillMode::FLOOD_FILL)
  4614. {
  4615. /*
  4616. * Marking the outside edges of the voxel cube to be outside surfaces to walk
  4617. */
  4618. MarkOutsideSurface(0, 0, 0, m_dim[0], m_dim[1], 1);
  4619. MarkOutsideSurface(0, 0, m_dim[2] - 1, m_dim[0], m_dim[1], m_dim[2]);
  4620. MarkOutsideSurface(0, 0, 0, m_dim[0], 1, m_dim[2]);
  4621. MarkOutsideSurface(0, m_dim[1] - 1, 0, m_dim[0], m_dim[1], m_dim[2]);
  4622. MarkOutsideSurface(0, 0, 0, 1, m_dim[1], m_dim[2]);
  4623. MarkOutsideSurface(m_dim[0] - 1, 0, 0, m_dim[0], m_dim[1], m_dim[2]);
  4624. FillOutsideSurface();
  4625. FillInsideSurface();
  4626. }
  4627. else if (fillMode == FillMode::RAYCAST_FILL)
  4628. {
  4629. RaycastFill(aabbTree);
  4630. }
  4631. }
  4632. void Volume::RaycastFill(const AABBTree& aabbTree)
  4633. {
  4634. const uint32_t i0 = m_dim[0];
  4635. const uint32_t j0 = m_dim[1];
  4636. const uint32_t k0 = m_dim[2];
  4637. size_t maxSize = i0 * j0 * k0;
  4638. std::vector<Voxel> temp;
  4639. temp.reserve(maxSize);
  4640. uint32_t count{ 0 };
  4641. m_numVoxelsInsideSurface = 0;
  4642. for (uint32_t i = 0; i < i0; ++i)
  4643. {
  4644. for (uint32_t j = 0; j < j0; ++j)
  4645. {
  4646. for (uint32_t k = 0; k < k0; ++k)
  4647. {
  4648. VoxelValue& voxel = GetVoxel(i, j, k);
  4649. if (voxel != VoxelValue::PRIMITIVE_ON_SURFACE)
  4650. {
  4651. VHACD::Vect3 start = VHACD::Vect3(i, j, k) * m_scale + m_bounds.GetMin();
  4652. uint32_t insideCount = 0;
  4653. uint32_t outsideCount = 0;
  4654. VHACD::Vect3 directions[6] = {
  4655. VHACD::Vect3( 1, 0, 0),
  4656. VHACD::Vect3(-1, 0, 0), // this was 1, 0, 0 in the original code, but looks wrong
  4657. VHACD::Vect3( 0, 1, 0),
  4658. VHACD::Vect3( 0, -1, 0),
  4659. VHACD::Vect3( 0, 0, 1),
  4660. VHACD::Vect3( 0, 0, -1)
  4661. };
  4662. for (uint32_t r = 0; r < 6; r++)
  4663. {
  4664. aabbTree.TraceRay(start,
  4665. directions[r],
  4666. insideCount,
  4667. outsideCount);
  4668. // Early out if we hit the outside of the mesh
  4669. if (outsideCount)
  4670. {
  4671. break;
  4672. }
  4673. // Early out if we accumulated 3 inside hits
  4674. if (insideCount >= 3)
  4675. {
  4676. break;
  4677. }
  4678. }
  4679. if (outsideCount == 0 && insideCount >= 3)
  4680. {
  4681. voxel = VoxelValue::PRIMITIVE_INSIDE_SURFACE;
  4682. temp.emplace_back(i, j, k);
  4683. count++;
  4684. m_numVoxelsInsideSurface++;
  4685. }
  4686. else
  4687. {
  4688. voxel = VoxelValue::PRIMITIVE_OUTSIDE_SURFACE;
  4689. }
  4690. }
  4691. }
  4692. }
  4693. }
  4694. if (count)
  4695. {
  4696. m_interiorVoxels = std::move(temp);
  4697. }
  4698. }
  4699. void Volume::SetVoxel(const size_t i,
  4700. const size_t j,
  4701. const size_t k,
  4702. VoxelValue value)
  4703. {
  4704. assert(i < m_dim[0] || i >= 0);
  4705. assert(j < m_dim[1] || j >= 0);
  4706. assert(k < m_dim[2] || k >= 0);
  4707. m_data[k + j * m_dim[2] + i * m_dim[1] * m_dim[2]] = value;
  4708. }
  4709. VoxelValue& Volume::GetVoxel(const size_t i,
  4710. const size_t j,
  4711. const size_t k)
  4712. {
  4713. assert(i < m_dim[0] || i >= 0);
  4714. assert(j < m_dim[1] || j >= 0);
  4715. assert(k < m_dim[2] || k >= 0);
  4716. return m_data[k + j * m_dim[2] + i * m_dim[1] * m_dim[2]];
  4717. }
  4718. const VoxelValue& Volume::GetVoxel(const size_t i,
  4719. const size_t j,
  4720. const size_t k) const
  4721. {
  4722. assert(i < m_dim[0] || i >= 0);
  4723. assert(j < m_dim[1] || j >= 0);
  4724. assert(k < m_dim[2] || k >= 0);
  4725. return m_data[k + j * m_dim[2] + i * m_dim[1] * m_dim[2]];
  4726. }
  4727. const std::vector<Voxel>& Volume::GetSurfaceVoxels() const
  4728. {
  4729. return m_surfaceVoxels;
  4730. }
  4731. const std::vector<Voxel>& Volume::GetInteriorVoxels() const
  4732. {
  4733. return m_interiorVoxels;
  4734. }
  4735. double Volume::GetScale() const
  4736. {
  4737. return m_scale;
  4738. }
  4739. const VHACD::BoundsAABB& Volume::GetBounds() const
  4740. {
  4741. return m_bounds;
  4742. }
  4743. const VHACD::Vector3<uint32_t>& Volume::GetDimensions() const
  4744. {
  4745. return m_dim;
  4746. }
  4747. void Volume::MarkOutsideSurface(const size_t i0,
  4748. const size_t j0,
  4749. const size_t k0,
  4750. const size_t i1,
  4751. const size_t j1,
  4752. const size_t k1)
  4753. {
  4754. for (size_t i = i0; i < i1; ++i)
  4755. {
  4756. for (size_t j = j0; j < j1; ++j)
  4757. {
  4758. for (size_t k = k0; k < k1; ++k)
  4759. {
  4760. VoxelValue& v = GetVoxel(i, j, k);
  4761. if (v == VoxelValue::PRIMITIVE_UNDEFINED)
  4762. {
  4763. v = VoxelValue::PRIMITIVE_OUTSIDE_SURFACE_TOWALK;
  4764. }
  4765. }
  4766. }
  4767. }
  4768. }
  4769. inline void WalkForward(int64_t start,
  4770. int64_t end,
  4771. VoxelValue* ptr,
  4772. int64_t stride,
  4773. int64_t maxDistance)
  4774. {
  4775. for (int64_t i = start, count = 0;
  4776. count < maxDistance && i < end && *ptr == VoxelValue::PRIMITIVE_UNDEFINED;
  4777. ++i, ptr += stride, ++count)
  4778. {
  4779. *ptr = VoxelValue::PRIMITIVE_OUTSIDE_SURFACE_TOWALK;
  4780. }
  4781. }
  4782. inline void WalkBackward(int64_t start,
  4783. int64_t end,
  4784. VoxelValue* ptr,
  4785. int64_t stride,
  4786. int64_t maxDistance)
  4787. {
  4788. for (int64_t i = start, count = 0;
  4789. count < maxDistance && i >= end && *ptr == VoxelValue::PRIMITIVE_UNDEFINED;
  4790. --i, ptr -= stride, ++count)
  4791. {
  4792. *ptr = VoxelValue::PRIMITIVE_OUTSIDE_SURFACE_TOWALK;
  4793. }
  4794. }
  4795. void Volume::FillOutsideSurface()
  4796. {
  4797. size_t voxelsWalked = 0;
  4798. const int64_t i0 = m_dim[0];
  4799. const int64_t j0 = m_dim[1];
  4800. const int64_t k0 = m_dim[2];
  4801. // Avoid striding too far in each direction to stay in L1 cache as much as possible.
  4802. // The cache size required for the walk is roughly (4 * walkDistance * 64) since
  4803. // the k direction doesn't count as it's walking byte per byte directly in a cache lines.
  4804. // ~16k is required for a walk distance of 64 in each directions.
  4805. const size_t walkDistance = 64;
  4806. // using the stride directly instead of calling GetVoxel for each iterations saves
  4807. // a lot of multiplications and pipeline stalls due to data dependencies on imul.
  4808. const size_t istride = &GetVoxel(1, 0, 0) - &GetVoxel(0, 0, 0);
  4809. const size_t jstride = &GetVoxel(0, 1, 0) - &GetVoxel(0, 0, 0);
  4810. const size_t kstride = &GetVoxel(0, 0, 1) - &GetVoxel(0, 0, 0);
  4811. // It might seem counter intuitive to go over the whole voxel range multiple times
  4812. // but since we do the run in memory order, it leaves us with far fewer cache misses
  4813. // than a BFS algorithm and it has the additional benefit of not requiring us to
  4814. // store and manipulate a fifo for recursion that might become huge when the number
  4815. // of voxels is large.
  4816. // This will outperform the BFS algorithm by several orders of magnitude in practice.
  4817. do
  4818. {
  4819. voxelsWalked = 0;
  4820. for (int64_t i = 0; i < i0; ++i)
  4821. {
  4822. for (int64_t j = 0; j < j0; ++j)
  4823. {
  4824. for (int64_t k = 0; k < k0; ++k)
  4825. {
  4826. VoxelValue& voxel = GetVoxel(i, j, k);
  4827. if (voxel == VoxelValue::PRIMITIVE_OUTSIDE_SURFACE_TOWALK)
  4828. {
  4829. voxelsWalked++;
  4830. voxel = VoxelValue::PRIMITIVE_OUTSIDE_SURFACE;
  4831. // walk in each direction to mark other voxel that should be walked.
  4832. // this will generate a 3d pattern that will help the overall
  4833. // algorithm converge faster while remaining cache friendly.
  4834. WalkForward(k + 1, k0, &voxel + kstride, kstride, walkDistance);
  4835. WalkBackward(k - 1, 0, &voxel - kstride, kstride, walkDistance);
  4836. WalkForward(j + 1, j0, &voxel + jstride, jstride, walkDistance);
  4837. WalkBackward(j - 1, 0, &voxel - jstride, jstride, walkDistance);
  4838. WalkForward(i + 1, i0, &voxel + istride, istride, walkDistance);
  4839. WalkBackward(i - 1, 0, &voxel - istride, istride, walkDistance);
  4840. }
  4841. }
  4842. }
  4843. }
  4844. m_numVoxelsOutsideSurface += voxelsWalked;
  4845. } while (voxelsWalked != 0);
  4846. }
  4847. void Volume::FillInsideSurface()
  4848. {
  4849. const uint32_t i0 = uint32_t(m_dim[0]);
  4850. const uint32_t j0 = uint32_t(m_dim[1]);
  4851. const uint32_t k0 = uint32_t(m_dim[2]);
  4852. size_t maxSize = i0 * j0 * k0;
  4853. std::vector<Voxel> temp;
  4854. temp.reserve(maxSize);
  4855. uint32_t count{ 0 };
  4856. for (uint32_t i = 0; i < i0; ++i)
  4857. {
  4858. for (uint32_t j = 0; j < j0; ++j)
  4859. {
  4860. for (uint32_t k = 0; k < k0; ++k)
  4861. {
  4862. VoxelValue& v = GetVoxel(i, j, k);
  4863. if (v == VoxelValue::PRIMITIVE_UNDEFINED)
  4864. {
  4865. v = VoxelValue::PRIMITIVE_INSIDE_SURFACE;
  4866. temp.emplace_back(i, j, k);
  4867. count++;
  4868. ++m_numVoxelsInsideSurface;
  4869. }
  4870. }
  4871. }
  4872. }
  4873. if ( count )
  4874. {
  4875. m_interiorVoxels = std::move(temp);
  4876. }
  4877. }
  4878. //******************************************************************************************
  4879. // ShrinkWrap helper class
  4880. //******************************************************************************************
  4881. // This is a code snippet which 'shrinkwraps' a convex hull
  4882. // to a source mesh.
  4883. //
  4884. // It is a somewhat complicated algorithm. It works as follows:
  4885. //
  4886. // * Step #1 : Compute the mean unit normal vector for each vertex in the convex hull
  4887. // * Step #2 : For each vertex in the conex hull we project is slightly outwards along the mean normal vector
  4888. // * Step #3 : We then raycast from this slightly extruded point back into the opposite direction of the mean normal vector
  4889. // resulting in a raycast from slightly beyond the vertex in the hull into the source mesh we are trying
  4890. // to 'shrink wrap' against
  4891. // * Step #4 : If the raycast fails we leave the original vertex alone
  4892. // * Step #5 : If the raycast hits a backface we leave the original vertex alone
  4893. // * Step #6 : If the raycast hits too far away (no more than a certain threshold distance) we live it alone
  4894. // * Step #7 : If the point we hit on the source mesh is not still within the convex hull, we reject it.
  4895. // * Step #8 : If all of the previous conditions are met, then we take the raycast hit location as the 'new position'
  4896. // * Step #9 : Once all points have been projected, if possible, we need to recompute the convex hull again based on these shrinkwrapped points
  4897. // * Step #10 : In theory that should work.. let's see...
  4898. //***********************************************************************************************
  4899. // QuickHull implementation
  4900. //***********************************************************************************************
  4901. //////////////////////////////////////////////////////////////////////////
  4902. // Quickhull base class holding the hull during construction
  4903. //////////////////////////////////////////////////////////////////////////
  4904. class QuickHull
  4905. {
  4906. public:
  4907. uint32_t ComputeConvexHull(const std::vector<VHACD::Vertex>& vertices,
  4908. uint32_t maxHullVertices);
  4909. const std::vector<VHACD::Vertex>& GetVertices() const;
  4910. const std::vector<VHACD::Triangle>& GetIndices() const;
  4911. private:
  4912. std::vector<VHACD::Vertex> m_vertices;
  4913. std::vector<VHACD::Triangle> m_indices;
  4914. };
  4915. uint32_t QuickHull::ComputeConvexHull(const std::vector<VHACD::Vertex>& vertices,
  4916. uint32_t maxHullVertices)
  4917. {
  4918. m_indices.clear();
  4919. VHACD::ConvexHull ch(vertices,
  4920. double(0.0001),
  4921. maxHullVertices);
  4922. auto& vlist = ch.GetVertexPool();
  4923. if ( !vlist.empty() )
  4924. {
  4925. size_t vcount = vlist.size();
  4926. m_vertices.resize(vcount);
  4927. std::copy(vlist.begin(),
  4928. vlist.end(),
  4929. m_vertices.begin());
  4930. }
  4931. for (std::list<ConvexHullFace>::const_iterator node = ch.GetList().begin(); node != ch.GetList().end(); ++node)
  4932. {
  4933. const VHACD::ConvexHullFace& face = *node;
  4934. m_indices.emplace_back(face.m_index[0],
  4935. face.m_index[1],
  4936. face.m_index[2]);
  4937. }
  4938. return uint32_t(m_indices.size());
  4939. }
  4940. const std::vector<VHACD::Vertex>& QuickHull::GetVertices() const
  4941. {
  4942. return m_vertices;
  4943. }
  4944. const std::vector<VHACD::Triangle>& QuickHull::GetIndices() const
  4945. {
  4946. return m_indices;
  4947. }
  4948. //******************************************************************************************
  4949. // Implementation of the ShrinkWrap function
  4950. //******************************************************************************************
  4951. void ShrinkWrap(SimpleMesh& sourceConvexHull,
  4952. const AABBTree& aabbTree,
  4953. uint32_t maxHullVertexCount,
  4954. double distanceThreshold,
  4955. bool doShrinkWrap)
  4956. {
  4957. std::vector<VHACD::Vertex> verts; // New verts for the new convex hull
  4958. verts.reserve(sourceConvexHull.m_vertices.size());
  4959. // Examine each vertex and see if it is within the voxel distance.
  4960. // If it is, then replace the point with the shrinkwrapped / projected point
  4961. for (uint32_t j = 0; j < sourceConvexHull.m_vertices.size(); j++)
  4962. {
  4963. VHACD::Vertex& p = sourceConvexHull.m_vertices[j];
  4964. if (doShrinkWrap)
  4965. {
  4966. VHACD::Vect3 closest;
  4967. if (aabbTree.GetClosestPointWithinDistance(p, distanceThreshold, closest))
  4968. {
  4969. p = closest;
  4970. }
  4971. }
  4972. verts.emplace_back(p);
  4973. }
  4974. // Final step is to recompute the convex hull
  4975. VHACD::QuickHull qh;
  4976. uint32_t tcount = qh.ComputeConvexHull(verts,
  4977. maxHullVertexCount);
  4978. if (tcount)
  4979. {
  4980. sourceConvexHull.m_vertices = qh.GetVertices();
  4981. sourceConvexHull.m_indices = qh.GetIndices();
  4982. }
  4983. }
  4984. //********************************************************************************************************************
  4985. #if !VHACD_DISABLE_THREADING
  4986. //********************************************************************************************************************
  4987. // Definition of the ThreadPool
  4988. //********************************************************************************************************************
  4989. class ThreadPool {
  4990. public:
  4991. ThreadPool();
  4992. ThreadPool(int worker);
  4993. ~ThreadPool();
  4994. template<typename F, typename... Args>
  4995. auto enqueue(F&& f, Args&& ... args)
  4996. #ifndef __cpp_lib_is_invocable
  4997. -> std::future< typename std::result_of< F( Args... ) >::type>;
  4998. #else
  4999. -> std::future< typename std::invoke_result_t<F, Args...>>;
  5000. #endif
  5001. private:
  5002. std::vector<std::thread> workers;
  5003. std::deque<std::function<void()>> tasks;
  5004. std::mutex task_mutex;
  5005. std::condition_variable cv;
  5006. bool closed;
  5007. int count;
  5008. };
  5009. ThreadPool::ThreadPool()
  5010. : ThreadPool(1)
  5011. {
  5012. }
  5013. ThreadPool::ThreadPool(int worker)
  5014. : closed(false)
  5015. , count(0)
  5016. {
  5017. workers.reserve(worker);
  5018. for(int i=0; i<worker; i++)
  5019. {
  5020. workers.emplace_back(
  5021. [this]
  5022. {
  5023. std::unique_lock<std::mutex> lock(this->task_mutex);
  5024. while(true)
  5025. {
  5026. while (this->tasks.empty())
  5027. {
  5028. if (this->closed)
  5029. {
  5030. return;
  5031. }
  5032. this->cv.wait(lock);
  5033. }
  5034. auto task = this->tasks.front();
  5035. this->tasks.pop_front();
  5036. lock.unlock();
  5037. task();
  5038. lock.lock();
  5039. }
  5040. }
  5041. );
  5042. }
  5043. }
  5044. template<typename F, typename... Args>
  5045. auto ThreadPool::enqueue(F&& f, Args&& ... args)
  5046. #ifndef __cpp_lib_is_invocable
  5047. -> std::future< typename std::result_of< F( Args... ) >::type>
  5048. #else
  5049. -> std::future< typename std::invoke_result_t<F, Args...>>
  5050. #endif
  5051. {
  5052. #ifndef __cpp_lib_is_invocable
  5053. using return_type = typename std::result_of< F( Args... ) >::type;
  5054. #else
  5055. using return_type = typename std::invoke_result_t< F, Args... >;
  5056. #endif
  5057. auto task = std::make_shared<std::packaged_task<return_type()> > (
  5058. std::bind(std::forward<F>(f), std::forward<Args>(args)...)
  5059. );
  5060. auto result = task->get_future();
  5061. {
  5062. std::unique_lock<std::mutex> lock(task_mutex);
  5063. if (!closed)
  5064. {
  5065. tasks.emplace_back([task]
  5066. {
  5067. (*task)();
  5068. });
  5069. cv.notify_one();
  5070. }
  5071. }
  5072. return result;
  5073. }
  5074. ThreadPool::~ThreadPool() {
  5075. {
  5076. std::unique_lock<std::mutex> lock(task_mutex);
  5077. closed = true;
  5078. }
  5079. cv.notify_all();
  5080. for (auto && worker : workers)
  5081. {
  5082. worker.join();
  5083. }
  5084. }
  5085. #endif
  5086. enum class Stages
  5087. {
  5088. COMPUTE_BOUNDS_OF_INPUT_MESH,
  5089. REINDEXING_INPUT_MESH,
  5090. CREATE_RAYCAST_MESH,
  5091. VOXELIZING_INPUT_MESH,
  5092. BUILD_INITIAL_CONVEX_HULL,
  5093. PERFORMING_DECOMPOSITION,
  5094. INITIALIZING_CONVEX_HULLS_FOR_MERGING,
  5095. COMPUTING_COST_MATRIX,
  5096. MERGING_CONVEX_HULLS,
  5097. FINALIZING_RESULTS,
  5098. NUM_STAGES
  5099. };
  5100. class VHACDCallbacks
  5101. {
  5102. public:
  5103. virtual void ProgressUpdate(Stages stage,
  5104. double stageProgress,
  5105. const char *operation) = 0;
  5106. virtual bool IsCanceled() const = 0;
  5107. virtual ~VHACDCallbacks() = default;
  5108. };
  5109. enum class SplitAxis
  5110. {
  5111. X_AXIS_NEGATIVE,
  5112. X_AXIS_POSITIVE,
  5113. Y_AXIS_NEGATIVE,
  5114. Y_AXIS_POSITIVE,
  5115. Z_AXIS_NEGATIVE,
  5116. Z_AXIS_POSITIVE,
  5117. };
  5118. // This class represents a collection of voxels, the convex hull
  5119. // which surrounds them, and a triangle mesh representation of those voxels
  5120. class VoxelHull
  5121. {
  5122. public:
  5123. // This method constructs a new VoxelHull based on a plane split of the parent
  5124. // convex hull
  5125. VoxelHull(const VoxelHull& parent,
  5126. SplitAxis axis,
  5127. uint32_t splitLoc);
  5128. // Here we construct the initial convex hull around the
  5129. // entire voxel set
  5130. VoxelHull(Volume& voxels,
  5131. const IVHACD::Parameters &params,
  5132. VHACDCallbacks *callbacks);
  5133. ~VoxelHull() = default;
  5134. // Helper method to refresh the min/max voxel bounding region
  5135. void MinMaxVoxelRegion(const Voxel &v);
  5136. void BuildRaycastMesh();
  5137. // We now compute the convex hull relative to a triangle mesh generated
  5138. // from the voxels
  5139. void ComputeConvexHull();
  5140. // Returns true if this convex hull should be considered done
  5141. bool IsComplete();
  5142. // Convert a voxel position into it's correct double precision location
  5143. VHACD::Vect3 GetPoint(const int32_t x,
  5144. const int32_t y,
  5145. const int32_t z,
  5146. const double scale,
  5147. const VHACD::Vect3& bmin) const;
  5148. // Sees if we have already got an index for this voxel position.
  5149. // If the voxel position has already been indexed, we just return
  5150. // that index value.
  5151. // If not, then we convert it into the floating point position and
  5152. // add it to the index map
  5153. uint32_t GetVertexIndex(const VHACD::Vector3<uint32_t>& p);
  5154. // This method will convert the voxels into an actual indexed triangle mesh of boxes
  5155. // This serves two purposes.
  5156. // The primary purpose is so that when we compute a convex hull it considered all of the points
  5157. // for each voxel, not just the center point. If you don't do this, then the hulls don't fit the
  5158. // mesh accurately enough.
  5159. // The second reason we convert it into a triangle mesh is so that we can do raycasting against it
  5160. // to search for the best splitting plane fairly quickly. That algorithm will be discussed in the
  5161. // method which computes the best splitting plane.
  5162. void BuildVoxelMesh();
  5163. // Convert a single voxel position into an actual 3d box mesh comprised
  5164. // of 12 triangles
  5165. void AddVoxelBox(const Voxel &v);
  5166. // Add the triangle represented by these 3 indices into the 'box' set of vertices
  5167. // to the output mesh
  5168. void AddTri(const std::array<VHACD::Vector3<uint32_t>, 8>& box,
  5169. uint32_t i1,
  5170. uint32_t i2,
  5171. uint32_t i3);
  5172. // Here we convert from voxel space to a 3d position, index it, and add
  5173. // the triangle positions and indices for the output mesh
  5174. void AddTriangle(const VHACD::Vector3<uint32_t>& p1,
  5175. const VHACD::Vector3<uint32_t>& p2,
  5176. const VHACD::Vector3<uint32_t>& p3);
  5177. // When computing the split plane, we start by simply
  5178. // taking the midpoint of the longest side. However,
  5179. // we can also search the surface and look for the greatest
  5180. // spot of concavity and use that as the split location.
  5181. // This will make the convex decomposition more efficient
  5182. // as it will tend to cut across the greatest point of
  5183. // concavity on the surface.
  5184. SplitAxis ComputeSplitPlane(uint32_t& location);
  5185. VHACD::Vect3 GetPosition(const VHACD::Vector3<int32_t>& ip) const;
  5186. double Raycast(const VHACD::Vector3<int32_t>& p1,
  5187. const VHACD::Vector3<int32_t>& p2) const;
  5188. bool FindConcavity(uint32_t idx,
  5189. uint32_t& splitLoc);
  5190. // Finding the greatest area of concavity..
  5191. bool FindConcavityX(uint32_t& splitLoc);
  5192. // Finding the greatest area of concavity..
  5193. bool FindConcavityY(uint32_t& splitLoc);
  5194. // Finding the greatest area of concavity..
  5195. bool FindConcavityZ(uint32_t& splitLoc);
  5196. // This operation is performed in a background thread.
  5197. // It splits the voxels by a plane
  5198. void PerformPlaneSplit();
  5199. // Used only for debugging. Saves the voxelized mesh to disk
  5200. // Optionally saves the original source mesh as well for comparison
  5201. void SaveVoxelMesh(const SimpleMesh& inputMesh,
  5202. bool saveVoxelMesh,
  5203. bool saveSourceMesh);
  5204. void SaveOBJ(const char* fname,
  5205. const VoxelHull* h);
  5206. void SaveOBJ(const char* fname);
  5207. private:
  5208. void WriteOBJ(FILE* fph,
  5209. const std::vector<VHACD::Vertex>& vertices,
  5210. const std::vector<VHACD::Triangle>& indices,
  5211. uint32_t baseIndex);
  5212. public:
  5213. SplitAxis m_axis{ SplitAxis::X_AXIS_NEGATIVE };
  5214. Volume* m_voxels{ nullptr }; // The voxelized data set
  5215. double m_voxelScale{ 0 }; // Size of a single voxel
  5216. double m_voxelScaleHalf{ 0 }; // 1/2 of the size of a single voxel
  5217. VHACD::BoundsAABB m_voxelBounds;
  5218. VHACD::Vect3 m_voxelAdjust; // Minimum coordinates of the voxel space, with adjustment
  5219. uint32_t m_depth{ 0 }; // How deep in the recursion of the binary tree this hull is
  5220. uint32_t m_index{ 0 }; // Each convex hull is given a unique id to distinguish it from the others
  5221. double m_volumeError{ 0 }; // The percentage error from the convex hull volume vs. the voxel volume
  5222. double m_voxelVolume{ 0 }; // The volume of the voxels
  5223. double m_hullVolume{ 0 }; // The volume of the enclosing convex hull
  5224. std::unique_ptr<IVHACD::ConvexHull> m_convexHull{ nullptr }; // The convex hull which encloses this set of voxels.
  5225. std::vector<Voxel> m_surfaceVoxels; // The voxels which are on the surface of the source mesh.
  5226. std::vector<Voxel> m_newSurfaceVoxels; // Voxels which are on the surface as a result of a plane split
  5227. std::vector<Voxel> m_interiorVoxels; // Voxels which are part of the interior of the hull
  5228. std::unique_ptr<VoxelHull> m_hullA{ nullptr }; // hull resulting from one side of the plane split
  5229. std::unique_ptr<VoxelHull> m_hullB{ nullptr }; // hull resulting from the other side of the plane split
  5230. // Defines the coordinates this convex hull comprises within the voxel volume
  5231. // of the entire source
  5232. VHACD::Vector3<uint32_t> m_1{ 0 };
  5233. VHACD::Vector3<uint32_t> m_2{ 0 };
  5234. AABBTree m_AABBTree;
  5235. std::unordered_map<uint32_t, uint32_t> m_voxelIndexMap; // Maps from a voxel coordinate space into a vertex index space
  5236. std::vector<VHACD::Vertex> m_vertices;
  5237. std::vector<VHACD::Triangle> m_indices;
  5238. static uint32_t m_voxelHullCount;
  5239. IVHACD::Parameters m_params;
  5240. VHACDCallbacks* m_callbacks{ nullptr };
  5241. };
  5242. uint32_t VoxelHull::m_voxelHullCount = 0;
  5243. VoxelHull::VoxelHull(const VoxelHull& parent,
  5244. SplitAxis axis,
  5245. uint32_t splitLoc)
  5246. : m_axis(axis)
  5247. , m_voxels(parent.m_voxels)
  5248. , m_voxelScale(m_voxels->GetScale())
  5249. , m_voxelScaleHalf(m_voxelScale * double(0.5))
  5250. , m_voxelBounds(m_voxels->GetBounds())
  5251. , m_voxelAdjust(m_voxelBounds.GetMin() - m_voxelScaleHalf)
  5252. , m_depth(parent.m_depth + 1)
  5253. , m_index(++m_voxelHullCount)
  5254. , m_1(parent.m_1)
  5255. , m_2(parent.m_2)
  5256. , m_params(parent.m_params)
  5257. {
  5258. // Default copy the voxel region from the parent, but values will
  5259. // be adjusted next based on the split axis and location
  5260. switch ( m_axis )
  5261. {
  5262. case SplitAxis::X_AXIS_NEGATIVE:
  5263. m_2.GetX() = splitLoc;
  5264. break;
  5265. case SplitAxis::X_AXIS_POSITIVE:
  5266. m_1.GetX() = splitLoc + 1;
  5267. break;
  5268. case SplitAxis::Y_AXIS_NEGATIVE:
  5269. m_2.GetY() = splitLoc;
  5270. break;
  5271. case SplitAxis::Y_AXIS_POSITIVE:
  5272. m_1.GetY() = splitLoc + 1;
  5273. break;
  5274. case SplitAxis::Z_AXIS_NEGATIVE:
  5275. m_2.GetZ() = splitLoc;
  5276. break;
  5277. case SplitAxis::Z_AXIS_POSITIVE:
  5278. m_1.GetZ() = splitLoc + 1;
  5279. break;
  5280. }
  5281. // First, we copy all of the interior voxels from our parent
  5282. // which intersect our region
  5283. for (auto& i : parent.m_interiorVoxels)
  5284. {
  5285. VHACD::Vector3<uint32_t> v = i.GetVoxel();
  5286. if (v.CWiseAllGE(m_1) && v.CWiseAllLE(m_2))
  5287. {
  5288. bool newSurface = false;
  5289. switch ( m_axis )
  5290. {
  5291. case SplitAxis::X_AXIS_NEGATIVE:
  5292. if ( v.GetX() == splitLoc )
  5293. {
  5294. newSurface = true;
  5295. }
  5296. break;
  5297. case SplitAxis::X_AXIS_POSITIVE:
  5298. if ( v.GetX() == m_1.GetX() )
  5299. {
  5300. newSurface = true;
  5301. }
  5302. break;
  5303. case SplitAxis::Y_AXIS_NEGATIVE:
  5304. if ( v.GetY() == splitLoc )
  5305. {
  5306. newSurface = true;
  5307. }
  5308. break;
  5309. case SplitAxis::Y_AXIS_POSITIVE:
  5310. if ( v.GetY() == m_1.GetY() )
  5311. {
  5312. newSurface = true;
  5313. }
  5314. break;
  5315. case SplitAxis::Z_AXIS_NEGATIVE:
  5316. if ( v.GetZ() == splitLoc )
  5317. {
  5318. newSurface = true;
  5319. }
  5320. break;
  5321. case SplitAxis::Z_AXIS_POSITIVE:
  5322. if ( v.GetZ() == m_1.GetZ() )
  5323. {
  5324. newSurface = true;
  5325. }
  5326. break;
  5327. }
  5328. // If his interior voxels lie directly on the split plane then
  5329. // these become new surface voxels for our patch
  5330. if ( newSurface )
  5331. {
  5332. m_newSurfaceVoxels.push_back(i);
  5333. }
  5334. else
  5335. {
  5336. m_interiorVoxels.push_back(i);
  5337. }
  5338. }
  5339. }
  5340. // Next we copy all of the surface voxels which intersect our region
  5341. for (auto& i : parent.m_surfaceVoxels)
  5342. {
  5343. VHACD::Vector3<uint32_t> v = i.GetVoxel();
  5344. if (v.CWiseAllGE(m_1) && v.CWiseAllLE(m_2))
  5345. {
  5346. m_surfaceVoxels.push_back(i);
  5347. }
  5348. }
  5349. // Our parent's new surface voxels become our new surface voxels so long as they intersect our region
  5350. for (auto& i : parent.m_newSurfaceVoxels)
  5351. {
  5352. VHACD::Vector3<uint32_t> v = i.GetVoxel();
  5353. if (v.CWiseAllGE(m_1) && v.CWiseAllLE(m_2))
  5354. {
  5355. m_newSurfaceVoxels.push_back(i);
  5356. }
  5357. }
  5358. // Recompute the min-max bounding box which would be different after the split occurs
  5359. m_1 = VHACD::Vector3<uint32_t>(0x7FFFFFFF);
  5360. m_2 = VHACD::Vector3<uint32_t>(0);
  5361. for (auto& i : m_surfaceVoxels)
  5362. {
  5363. MinMaxVoxelRegion(i);
  5364. }
  5365. for (auto& i : m_newSurfaceVoxels)
  5366. {
  5367. MinMaxVoxelRegion(i);
  5368. }
  5369. for (auto& i : m_interiorVoxels)
  5370. {
  5371. MinMaxVoxelRegion(i);
  5372. }
  5373. BuildVoxelMesh();
  5374. BuildRaycastMesh(); // build a raycast mesh of the voxel mesh
  5375. ComputeConvexHull();
  5376. }
  5377. VoxelHull::VoxelHull(Volume& voxels,
  5378. const IVHACD::Parameters& params,
  5379. VHACDCallbacks* callbacks)
  5380. : m_voxels(&voxels)
  5381. , m_voxelScale(m_voxels->GetScale())
  5382. , m_voxelScaleHalf(m_voxelScale * double(0.5))
  5383. , m_voxelBounds(m_voxels->GetBounds())
  5384. , m_voxelAdjust(m_voxelBounds.GetMin() - m_voxelScaleHalf)
  5385. , m_index(++m_voxelHullCount)
  5386. // Here we get a copy of all voxels which lie on the surface mesh
  5387. , m_surfaceVoxels(m_voxels->GetSurfaceVoxels())
  5388. // Now we get a copy of all voxels which are considered part of the 'interior' of the source mesh
  5389. , m_interiorVoxels(m_voxels->GetInteriorVoxels())
  5390. , m_2(m_voxels->GetDimensions() - 1)
  5391. , m_params(params)
  5392. , m_callbacks(callbacks)
  5393. {
  5394. BuildVoxelMesh();
  5395. BuildRaycastMesh(); // build a raycast mesh of the voxel mesh
  5396. ComputeConvexHull();
  5397. }
  5398. void VoxelHull::MinMaxVoxelRegion(const Voxel& v)
  5399. {
  5400. VHACD::Vector3<uint32_t> x = v.GetVoxel();
  5401. m_1 = m_1.CWiseMin(x);
  5402. m_2 = m_2.CWiseMax(x);
  5403. }
  5404. void VoxelHull::BuildRaycastMesh()
  5405. {
  5406. // Create a raycast mesh representation of the voxelized surface mesh
  5407. if ( !m_indices.empty() )
  5408. {
  5409. m_AABBTree = AABBTree(m_vertices,
  5410. m_indices);
  5411. }
  5412. }
  5413. void VoxelHull::ComputeConvexHull()
  5414. {
  5415. if ( !m_vertices.empty() )
  5416. {
  5417. // we compute the convex hull as follows...
  5418. VHACD::QuickHull qh;
  5419. uint32_t tcount = qh.ComputeConvexHull(m_vertices,
  5420. uint32_t(m_vertices.size()));
  5421. if ( tcount )
  5422. {
  5423. m_convexHull = std::unique_ptr<IVHACD::ConvexHull>(new IVHACD::ConvexHull);
  5424. m_convexHull->m_points = qh.GetVertices();
  5425. m_convexHull->m_triangles = qh.GetIndices();
  5426. VHACD::ComputeCentroid(m_convexHull->m_points,
  5427. m_convexHull->m_triangles,
  5428. m_convexHull->m_center);
  5429. m_convexHull->m_volume = VHACD::ComputeMeshVolume(m_convexHull->m_points,
  5430. m_convexHull->m_triangles);
  5431. }
  5432. }
  5433. if ( m_convexHull )
  5434. {
  5435. m_hullVolume = m_convexHull->m_volume;
  5436. }
  5437. // This is the volume of a single voxel
  5438. double singleVoxelVolume = m_voxelScale * m_voxelScale * m_voxelScale;
  5439. size_t voxelCount = m_interiorVoxels.size() + m_newSurfaceVoxels.size() + m_surfaceVoxels.size();
  5440. m_voxelVolume = singleVoxelVolume * double(voxelCount);
  5441. double diff = fabs(m_hullVolume - m_voxelVolume);
  5442. m_volumeError = (diff * 100) / m_voxelVolume;
  5443. }
  5444. bool VoxelHull::IsComplete()
  5445. {
  5446. bool ret = false;
  5447. if ( m_convexHull == nullptr )
  5448. {
  5449. ret = true;
  5450. }
  5451. else if ( m_volumeError < m_params.m_minimumVolumePercentErrorAllowed )
  5452. {
  5453. ret = true;
  5454. }
  5455. else if ( m_depth > m_params.m_maxRecursionDepth )
  5456. {
  5457. ret = true;
  5458. }
  5459. else
  5460. {
  5461. // We compute the voxel width on all 3 axes and see if they are below the min threshold size
  5462. VHACD::Vector3<uint32_t> d = m_2 - m_1;
  5463. if ( d.GetX() <= m_params.m_minEdgeLength &&
  5464. d.GetY() <= m_params.m_minEdgeLength &&
  5465. d.GetZ() <= m_params.m_minEdgeLength )
  5466. {
  5467. ret = true;
  5468. }
  5469. }
  5470. return ret;
  5471. }
  5472. VHACD::Vect3 VoxelHull::GetPoint(const int32_t x,
  5473. const int32_t y,
  5474. const int32_t z,
  5475. const double scale,
  5476. const VHACD::Vect3& bmin) const
  5477. {
  5478. return VHACD::Vect3(x * scale + bmin.GetX(),
  5479. y * scale + bmin.GetY(),
  5480. z * scale + bmin.GetZ());
  5481. }
  5482. uint32_t VoxelHull::GetVertexIndex(const VHACD::Vector3<uint32_t>& p)
  5483. {
  5484. uint32_t ret = 0;
  5485. uint32_t address = (p.GetX() << 20) | (p.GetY() << 10) | p.GetZ();
  5486. auto found = m_voxelIndexMap.find(address);
  5487. if ( found != m_voxelIndexMap.end() )
  5488. {
  5489. ret = found->second;
  5490. }
  5491. else
  5492. {
  5493. VHACD::Vect3 vertex = GetPoint(p.GetX(),
  5494. p.GetY(),
  5495. p.GetZ(),
  5496. m_voxelScale,
  5497. m_voxelAdjust);
  5498. ret = uint32_t(m_voxelIndexMap.size());
  5499. m_voxelIndexMap[address] = ret;
  5500. m_vertices.emplace_back(vertex);
  5501. }
  5502. return ret;
  5503. }
  5504. void VoxelHull::BuildVoxelMesh()
  5505. {
  5506. // When we build the triangle mesh we do *not* need the interior voxels, only the ones
  5507. // which lie upon the logical surface of the mesh.
  5508. // Each time we perform a plane split, voxels which are along the splitting plane become
  5509. // 'new surface voxels'.
  5510. for (auto& i : m_surfaceVoxels)
  5511. {
  5512. AddVoxelBox(i);
  5513. }
  5514. for (auto& i : m_newSurfaceVoxels)
  5515. {
  5516. AddVoxelBox(i);
  5517. }
  5518. }
  5519. void VoxelHull::AddVoxelBox(const Voxel &v)
  5520. {
  5521. // The voxel position of the upper left corner of the box
  5522. VHACD::Vector3<uint32_t> bmin(v.GetX(),
  5523. v.GetY(),
  5524. v.GetZ());
  5525. // The voxel position of the lower right corner of the box
  5526. VHACD::Vector3<uint32_t> bmax(bmin.GetX() + 1,
  5527. bmin.GetY() + 1,
  5528. bmin.GetZ() + 1);
  5529. // Build the set of 8 voxel positions representing
  5530. // the coordinates of the box
  5531. std::array<VHACD::Vector3<uint32_t>, 8> box{{
  5532. { bmin.GetX(), bmin.GetY(), bmin.GetZ() },
  5533. { bmax.GetX(), bmin.GetY(), bmin.GetZ() },
  5534. { bmax.GetX(), bmax.GetY(), bmin.GetZ() },
  5535. { bmin.GetX(), bmax.GetY(), bmin.GetZ() },
  5536. { bmin.GetX(), bmin.GetY(), bmax.GetZ() },
  5537. { bmax.GetX(), bmin.GetY(), bmax.GetZ() },
  5538. { bmax.GetX(), bmax.GetY(), bmax.GetZ() },
  5539. { bmin.GetX(), bmax.GetY(), bmax.GetZ() }
  5540. }};
  5541. // Now add the 12 triangles comprising the 3d box
  5542. AddTri(box, 2, 1, 0);
  5543. AddTri(box, 3, 2, 0);
  5544. AddTri(box, 7, 2, 3);
  5545. AddTri(box, 7, 6, 2);
  5546. AddTri(box, 5, 1, 2);
  5547. AddTri(box, 5, 2, 6);
  5548. AddTri(box, 5, 4, 1);
  5549. AddTri(box, 4, 0, 1);
  5550. AddTri(box, 4, 6, 7);
  5551. AddTri(box, 4, 5, 6);
  5552. AddTri(box, 4, 7, 0);
  5553. AddTri(box, 7, 3, 0);
  5554. }
  5555. void VoxelHull::AddTri(const std::array<VHACD::Vector3<uint32_t>, 8>& box,
  5556. uint32_t i1,
  5557. uint32_t i2,
  5558. uint32_t i3)
  5559. {
  5560. AddTriangle(box[i1], box[i2], box[i3]);
  5561. }
  5562. void VoxelHull::AddTriangle(const VHACD::Vector3<uint32_t>& p1,
  5563. const VHACD::Vector3<uint32_t>& p2,
  5564. const VHACD::Vector3<uint32_t>& p3)
  5565. {
  5566. uint32_t i1 = GetVertexIndex(p1);
  5567. uint32_t i2 = GetVertexIndex(p2);
  5568. uint32_t i3 = GetVertexIndex(p3);
  5569. m_indices.emplace_back(i1, i2, i3);
  5570. }
  5571. SplitAxis VoxelHull::ComputeSplitPlane(uint32_t& location)
  5572. {
  5573. SplitAxis ret = SplitAxis::X_AXIS_NEGATIVE;
  5574. VHACD::Vector3<uint32_t> d = m_2 - m_1;
  5575. if ( d.GetX() >= d.GetY() && d.GetX() >= d.GetZ() )
  5576. {
  5577. ret = SplitAxis::X_AXIS_NEGATIVE;
  5578. location = (m_2.GetX() + 1 + m_1.GetX()) / 2;
  5579. uint32_t edgeLoc;
  5580. if ( m_params.m_findBestPlane && FindConcavityX(edgeLoc) )
  5581. {
  5582. location = edgeLoc;
  5583. }
  5584. }
  5585. else if ( d.GetY() >= d.GetX() && d.GetY() >= d.GetZ() )
  5586. {
  5587. ret = SplitAxis::Y_AXIS_NEGATIVE;
  5588. location = (m_2.GetY() + 1 + m_1.GetY()) / 2;
  5589. uint32_t edgeLoc;
  5590. if ( m_params.m_findBestPlane && FindConcavityY(edgeLoc) )
  5591. {
  5592. location = edgeLoc;
  5593. }
  5594. }
  5595. else
  5596. {
  5597. ret = SplitAxis::Z_AXIS_NEGATIVE;
  5598. location = (m_2.GetZ() + 1 + m_1.GetZ()) / 2;
  5599. uint32_t edgeLoc;
  5600. if ( m_params.m_findBestPlane && FindConcavityZ(edgeLoc) )
  5601. {
  5602. location = edgeLoc;
  5603. }
  5604. }
  5605. return ret;
  5606. }
  5607. VHACD::Vect3 VoxelHull::GetPosition(const VHACD::Vector3<int32_t>& ip) const
  5608. {
  5609. return GetPoint(ip.GetX(),
  5610. ip.GetY(),
  5611. ip.GetZ(),
  5612. m_voxelScale,
  5613. m_voxelAdjust);
  5614. }
  5615. double VoxelHull::Raycast(const VHACD::Vector3<int32_t>& p1,
  5616. const VHACD::Vector3<int32_t>& p2) const
  5617. {
  5618. double ret;
  5619. VHACD::Vect3 from = GetPosition(p1);
  5620. VHACD::Vect3 to = GetPosition(p2);
  5621. double outT;
  5622. double faceSign;
  5623. VHACD::Vect3 hitLocation;
  5624. if (m_AABBTree.TraceRay(from, to, outT, faceSign, hitLocation))
  5625. {
  5626. ret = (from - hitLocation).GetNorm();
  5627. }
  5628. else
  5629. {
  5630. ret = 0; // if it doesn't hit anything, just assign it to zero.
  5631. }
  5632. return ret;
  5633. }
  5634. bool VoxelHull::FindConcavity(uint32_t idx,
  5635. uint32_t& splitLoc)
  5636. {
  5637. bool ret = false;
  5638. int32_t d = (m_2[idx] - m_1[idx]) + 1; // The length of the getX axis in voxel space
  5639. uint32_t idx1;
  5640. uint32_t idx2;
  5641. uint32_t idx3;
  5642. switch (idx)
  5643. {
  5644. case 0: // X
  5645. idx1 = 0;
  5646. idx2 = 1;
  5647. idx3 = 2;
  5648. break;
  5649. case 1: // Y
  5650. idx1 = 1;
  5651. idx2 = 0;
  5652. idx3 = 2;
  5653. break;
  5654. case 2:
  5655. idx1 = 2;
  5656. idx2 = 1;
  5657. idx3 = 0;
  5658. break;
  5659. default:
  5660. /*
  5661. * To silence uninitialized variable warnings
  5662. */
  5663. idx1 = 0;
  5664. idx2 = 0;
  5665. idx3 = 0;
  5666. assert(0 && "findConcavity::idx must be 0, 1, or 2");
  5667. break;
  5668. }
  5669. // We will compute the edge error on the XY plane and the XZ plane
  5670. // searching for the greatest location of concavity
  5671. std::vector<double> edgeError1 = std::vector<double>(d);
  5672. std::vector<double> edgeError2 = std::vector<double>(d);
  5673. // Counter of number of voxel samples on the XY plane we have accumulated
  5674. uint32_t index1 = 0;
  5675. // Compute Edge Error on the XY plane
  5676. for (uint32_t i0 = m_1[idx1]; i0 <= m_2[idx1]; i0++)
  5677. {
  5678. double errorTotal = 0;
  5679. // We now perform a raycast from the sides inward on the XY plane to
  5680. // determine the total error (distance of the surface from the sides)
  5681. // along this getX position.
  5682. for (uint32_t i1 = m_1[idx2]; i1 <= m_2[idx2]; i1++)
  5683. {
  5684. VHACD::Vector3<int32_t> p1;
  5685. VHACD::Vector3<int32_t> p2;
  5686. switch (idx)
  5687. {
  5688. case 0:
  5689. {
  5690. p1 = VHACD::Vector3<int32_t>(i0, i1, m_1.GetZ() - 2);
  5691. p2 = VHACD::Vector3<int32_t>(i0, i1, m_2.GetZ() + 2);
  5692. break;
  5693. }
  5694. case 1:
  5695. {
  5696. p1 = VHACD::Vector3<int32_t>(i1, i0, m_1.GetZ() - 2);
  5697. p2 = VHACD::Vector3<int32_t>(i1, i0, m_2.GetZ() + 2);
  5698. break;
  5699. }
  5700. case 2:
  5701. {
  5702. p1 = VHACD::Vector3<int32_t>(m_1.GetX() - 2, i1, i0);
  5703. p2 = VHACD::Vector3<int32_t>(m_2.GetX() + 2, i1, i0);
  5704. break;
  5705. }
  5706. }
  5707. double e1 = Raycast(p1, p2);
  5708. double e2 = Raycast(p2, p1);
  5709. errorTotal = errorTotal + e1 + e2;
  5710. }
  5711. // The total amount of edge error along this voxel location
  5712. edgeError1[index1] = errorTotal;
  5713. index1++;
  5714. }
  5715. // Compute edge error along the XZ plane
  5716. uint32_t index2 = 0;
  5717. for (uint32_t i0 = m_1[idx1]; i0 <= m_2[idx1]; i0++)
  5718. {
  5719. double errorTotal = 0;
  5720. for (uint32_t i1 = m_1[idx3]; i1 <= m_2[idx3]; i1++)
  5721. {
  5722. VHACD::Vector3<int32_t> p1;
  5723. VHACD::Vector3<int32_t> p2;
  5724. switch (idx)
  5725. {
  5726. case 0:
  5727. {
  5728. p1 = VHACD::Vector3<int32_t>(i0, m_1.GetY() - 2, i1);
  5729. p2 = VHACD::Vector3<int32_t>(i0, m_2.GetY() + 2, i1);
  5730. break;
  5731. }
  5732. case 1:
  5733. {
  5734. p1 = VHACD::Vector3<int32_t>(m_1.GetX() - 2, i0, i1);
  5735. p2 = VHACD::Vector3<int32_t>(m_2.GetX() + 2, i0, i1);
  5736. break;
  5737. }
  5738. case 2:
  5739. {
  5740. p1 = VHACD::Vector3<int32_t>(i1, m_1.GetY() - 2, i0);
  5741. p2 = VHACD::Vector3<int32_t>(i1, m_2.GetY() + 2, i0);
  5742. break;
  5743. }
  5744. }
  5745. double e1 = Raycast(p1, p2); // raycast from one side to the interior
  5746. double e2 = Raycast(p2, p1); // raycast from the other side to the interior
  5747. errorTotal = errorTotal + e1 + e2;
  5748. }
  5749. edgeError2[index2] = errorTotal;
  5750. index2++;
  5751. }
  5752. // we now compute the first derivative to find the greatest spot of concavity on the XY plane
  5753. double maxDiff = 0;
  5754. uint32_t maxC = 0;
  5755. for (uint32_t x = 1; x < index1; x++)
  5756. {
  5757. if ( edgeError1[x] > 0 && edgeError1[x - 1] > 0 )
  5758. {
  5759. double diff = abs(edgeError1[x] - edgeError1[x - 1]);
  5760. if ( diff > maxDiff )
  5761. {
  5762. maxDiff = diff;
  5763. maxC = x-1;
  5764. }
  5765. }
  5766. }
  5767. // Now see if there is a greater concavity on the XZ plane
  5768. for (uint32_t x = 1; x < index2; x++)
  5769. {
  5770. if ( edgeError2[x] > 0 && edgeError2[x - 1] > 0 )
  5771. {
  5772. double diff = abs(edgeError2[x] - edgeError2[x - 1]);
  5773. if ( diff > maxDiff )
  5774. {
  5775. maxDiff = diff;
  5776. maxC = x - 1;
  5777. }
  5778. }
  5779. }
  5780. splitLoc = maxC + m_1[idx1];
  5781. // we do not allow an edge split if it is too close to the ends
  5782. if ( splitLoc > (m_1[idx1] + 4)
  5783. && splitLoc < (m_2[idx1] - 4) )
  5784. {
  5785. ret = true;
  5786. }
  5787. return ret;
  5788. }
  5789. // Finding the greatest area of concavity..
  5790. bool VoxelHull::FindConcavityX(uint32_t& splitLoc)
  5791. {
  5792. return FindConcavity(0, splitLoc);
  5793. }
  5794. // Finding the greatest area of concavity..
  5795. bool VoxelHull::FindConcavityY(uint32_t& splitLoc)
  5796. {
  5797. return FindConcavity(1, splitLoc);
  5798. }
  5799. // Finding the greatest area of concavity..
  5800. bool VoxelHull::FindConcavityZ(uint32_t &splitLoc)
  5801. {
  5802. return FindConcavity(2, splitLoc);
  5803. }
  5804. void VoxelHull::PerformPlaneSplit()
  5805. {
  5806. if ( IsComplete() )
  5807. {
  5808. }
  5809. else
  5810. {
  5811. uint32_t splitLoc;
  5812. SplitAxis axis = ComputeSplitPlane(splitLoc);
  5813. switch ( axis )
  5814. {
  5815. case SplitAxis::X_AXIS_NEGATIVE:
  5816. case SplitAxis::X_AXIS_POSITIVE:
  5817. // Split on the getX axis at this split location
  5818. m_hullA = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::X_AXIS_NEGATIVE, splitLoc));
  5819. m_hullB = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::X_AXIS_POSITIVE, splitLoc));
  5820. break;
  5821. case SplitAxis::Y_AXIS_NEGATIVE:
  5822. case SplitAxis::Y_AXIS_POSITIVE:
  5823. // Split on the 1 axis at this split location
  5824. m_hullA = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::Y_AXIS_NEGATIVE, splitLoc));
  5825. m_hullB = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::Y_AXIS_POSITIVE, splitLoc));
  5826. break;
  5827. case SplitAxis::Z_AXIS_NEGATIVE:
  5828. case SplitAxis::Z_AXIS_POSITIVE:
  5829. // Split on the getZ axis at this split location
  5830. m_hullA = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::Z_AXIS_NEGATIVE, splitLoc));
  5831. m_hullB = std::unique_ptr<VoxelHull>(new VoxelHull(*this, SplitAxis::Z_AXIS_POSITIVE, splitLoc));
  5832. break;
  5833. }
  5834. }
  5835. }
  5836. void VoxelHull::SaveVoxelMesh(const SimpleMesh &inputMesh,
  5837. bool saveVoxelMesh,
  5838. bool saveSourceMesh)
  5839. {
  5840. char scratch[512];
  5841. snprintf(scratch,
  5842. sizeof(scratch),
  5843. "voxel-mesh-%03d.obj",
  5844. m_index);
  5845. FILE *fph = fopen(scratch,
  5846. "wb");
  5847. if ( fph )
  5848. {
  5849. uint32_t baseIndex = 1;
  5850. if ( saveVoxelMesh )
  5851. {
  5852. WriteOBJ(fph,
  5853. m_vertices,
  5854. m_indices,
  5855. baseIndex);
  5856. baseIndex += uint32_t(m_vertices.size());
  5857. }
  5858. if ( saveSourceMesh )
  5859. {
  5860. WriteOBJ(fph,
  5861. inputMesh.m_vertices,
  5862. inputMesh.m_indices,
  5863. baseIndex);
  5864. }
  5865. fclose(fph);
  5866. }
  5867. }
  5868. void VoxelHull::SaveOBJ(const char* fname,
  5869. const VoxelHull* h)
  5870. {
  5871. FILE *fph = fopen(fname,"wb");
  5872. if ( fph )
  5873. {
  5874. uint32_t baseIndex = 1;
  5875. WriteOBJ(fph,
  5876. m_vertices,
  5877. m_indices,
  5878. baseIndex);
  5879. baseIndex += uint32_t(m_vertices.size());
  5880. WriteOBJ(fph,
  5881. h->m_vertices,
  5882. h->m_indices,
  5883. baseIndex);
  5884. fclose(fph);
  5885. }
  5886. }
  5887. void VoxelHull::SaveOBJ(const char *fname)
  5888. {
  5889. FILE *fph = fopen(fname, "wb");
  5890. if ( fph )
  5891. {
  5892. printf("Saving '%s' with %d vertices and %d triangles\n",
  5893. fname,
  5894. uint32_t(m_vertices.size()),
  5895. uint32_t(m_indices.size()));
  5896. WriteOBJ(fph,
  5897. m_vertices,
  5898. m_indices,
  5899. 1);
  5900. fclose(fph);
  5901. }
  5902. }
  5903. void VoxelHull::WriteOBJ(FILE* fph,
  5904. const std::vector<VHACD::Vertex>& vertices,
  5905. const std::vector<VHACD::Triangle>& indices,
  5906. uint32_t baseIndex)
  5907. {
  5908. if (!fph)
  5909. {
  5910. return;
  5911. }
  5912. for (size_t i = 0; i < vertices.size(); ++i)
  5913. {
  5914. const VHACD::Vertex& v = vertices[i];
  5915. fprintf(fph, "v %0.9f %0.9f %0.9f\n",
  5916. v.mX,
  5917. v.mY,
  5918. v.mZ);
  5919. }
  5920. for (size_t i = 0; i < indices.size(); ++i)
  5921. {
  5922. const VHACD::Triangle& t = indices[i];
  5923. fprintf(fph, "f %d %d %d\n",
  5924. t.mI0 + baseIndex,
  5925. t.mI1 + baseIndex,
  5926. t.mI2 + baseIndex);
  5927. }
  5928. }
  5929. class VHACDImpl;
  5930. // This class represents a single task to compute the volume error
  5931. // of two convex hulls combined
  5932. class CostTask
  5933. {
  5934. public:
  5935. VHACDImpl* m_this{ nullptr };
  5936. IVHACD::ConvexHull* m_hullA{ nullptr };
  5937. IVHACD::ConvexHull* m_hullB{ nullptr };
  5938. double m_concavity{ 0 }; // concavity of the two combined
  5939. std::future<void> m_future;
  5940. };
  5941. class HullPair
  5942. {
  5943. public:
  5944. HullPair() = default;
  5945. HullPair(uint32_t hullA,
  5946. uint32_t hullB,
  5947. double concavity);
  5948. bool operator<(const HullPair &h) const;
  5949. uint32_t m_hullA{ 0 };
  5950. uint32_t m_hullB{ 0 };
  5951. double m_concavity{ 0 };
  5952. };
  5953. HullPair::HullPair(uint32_t hullA,
  5954. uint32_t hullB,
  5955. double concavity)
  5956. : m_hullA(hullA)
  5957. , m_hullB(hullB)
  5958. , m_concavity(concavity)
  5959. {
  5960. }
  5961. bool HullPair::operator<(const HullPair &h) const
  5962. {
  5963. return m_concavity > h.m_concavity ? true : false;
  5964. }
  5965. // void jobCallback(void* userPtr);
  5966. class VHACDImpl : public IVHACD, public VHACDCallbacks
  5967. {
  5968. // Don't consider more than 100,000 convex hulls.
  5969. static constexpr uint32_t MaxConvexHullFragments{ 100000 };
  5970. public:
  5971. VHACDImpl() = default;
  5972. /*
  5973. * Overrides VHACD::IVHACD
  5974. */
  5975. ~VHACDImpl() override
  5976. {
  5977. Clean();
  5978. }
  5979. void Cancel() override final;
  5980. bool Compute(const float* const points,
  5981. const uint32_t countPoints,
  5982. const uint32_t* const triangles,
  5983. const uint32_t countTriangles,
  5984. const Parameters& params) override final;
  5985. bool Compute(const double* const points,
  5986. const uint32_t countPoints,
  5987. const uint32_t* const triangles,
  5988. const uint32_t countTriangles,
  5989. const Parameters& params) override final;
  5990. uint32_t GetNConvexHulls() const override final;
  5991. bool GetConvexHull(const uint32_t index,
  5992. ConvexHull& ch) const override final;
  5993. void Clean() override final; // release internally allocated memory
  5994. void Release() override final;
  5995. // Will compute the center of mass of the convex hull decomposition results and return it
  5996. // in 'centerOfMass'. Returns false if the center of mass could not be computed.
  5997. bool ComputeCenterOfMass(double centerOfMass[3]) const override final;
  5998. // In synchronous mode (non-multi-threaded) the state is always 'ready'
  5999. // In asynchronous mode, this returns true if the background thread is not still actively computing
  6000. // a new solution. In an asynchronous config the 'IsReady' call will report any update or log
  6001. // messages in the caller's current thread.
  6002. bool IsReady(void) const override final;
  6003. /**
  6004. * At the request of LegionFu : [email protected]
  6005. * This method will return which convex hull is closest to the source position.
  6006. * You can use this method to figure out, for example, which vertices in the original
  6007. * source mesh are best associated with which convex hull.
  6008. *
  6009. * @param pos : The input 3d position to test against
  6010. *
  6011. * @return : Returns which convex hull this position is closest to.
  6012. */
  6013. uint32_t findNearestConvexHull(const double pos[3],
  6014. double& distanceToHull) override final;
  6015. // private:
  6016. bool Compute(const std::vector<VHACD::Vertex>& points,
  6017. const std::vector<VHACD::Triangle>& triangles,
  6018. const Parameters& params);
  6019. // Take the source position, normalize it, and then convert it into an index position
  6020. uint32_t GetIndex(VHACD::VertexIndex& vi,
  6021. const VHACD::Vertex& p);
  6022. // This copies the input mesh while scaling the input positions
  6023. // to fit into a normalized unit cube. It also re-indexes all of the
  6024. // vertex positions in case they weren't clean coming in.
  6025. void CopyInputMesh(const std::vector<VHACD::Vertex>& points,
  6026. const std::vector<VHACD::Triangle>& triangles);
  6027. void ScaleOutputConvexHull(ConvexHull &ch);
  6028. void AddCostToPriorityQueue(CostTask& task);
  6029. void ReleaseConvexHull(ConvexHull* ch);
  6030. void PerformConvexDecomposition();
  6031. double ComputeConvexHullVolume(const ConvexHull& sm);
  6032. double ComputeVolume4(const VHACD::Vect3& a,
  6033. const VHACD::Vect3& b,
  6034. const VHACD::Vect3& c,
  6035. const VHACD::Vect3& d);
  6036. double ComputeConcavity(double volumeSeparate,
  6037. double volumeCombined,
  6038. double volumeMesh);
  6039. // See if we can compute the cost without having to actually merge convex hulls.
  6040. // If the axis aligned bounding boxes (slightly inflated) of the two convex hulls
  6041. // do not intersect, then we don't need to actually compute the merged convex hull
  6042. // volume.
  6043. bool DoFastCost(CostTask& mt);
  6044. void PerformMergeCostTask(CostTask& mt);
  6045. ConvexHull* ComputeReducedConvexHull(const ConvexHull& ch,
  6046. uint32_t maxVerts,
  6047. bool projectHullVertices);
  6048. // Take the points in convex hull A and the points in convex hull B and generate
  6049. // a new convex hull on the combined set of points.
  6050. // Once completed, we create a SimpleMesh instance to hold the triangle mesh
  6051. // and we compute an inflated AABB for it.
  6052. ConvexHull* ComputeCombinedConvexHull(const ConvexHull& sm1,
  6053. const ConvexHull& sm2);
  6054. ConvexHull* GetHull(uint32_t index);
  6055. bool RemoveHull(uint32_t index);
  6056. ConvexHull* CopyConvexHull(const ConvexHull& source);
  6057. const char* GetStageName(Stages stage) const;
  6058. /*
  6059. * Overrides VHACD::VHACDCallbacks
  6060. */
  6061. void ProgressUpdate(Stages stage,
  6062. double stageProgress,
  6063. const char* operation) override final;
  6064. bool IsCanceled() const override final;
  6065. std::atomic<bool> m_canceled{ false };
  6066. Parameters m_params; // Convex decomposition parameters
  6067. std::vector<IVHACD::ConvexHull*> m_convexHulls; // Finalized convex hulls
  6068. std::vector<std::unique_ptr<VoxelHull>> m_voxelHulls; // completed voxel hulls
  6069. std::vector<std::unique_ptr<VoxelHull>> m_pendingHulls;
  6070. std::vector<std::unique_ptr<AABBTree>> m_trees;
  6071. VHACD::AABBTree m_AABBTree;
  6072. VHACD::Volume m_voxelize;
  6073. VHACD::Vect3 m_center;
  6074. double m_scale{ double(1.0) };
  6075. double m_recipScale{ double(1.0) };
  6076. SimpleMesh m_inputMesh; // re-indexed and normalized input mesh
  6077. std::vector<VHACD::Vertex> m_vertices;
  6078. std::vector<VHACD::Triangle> m_indices;
  6079. double m_overallHullVolume{ double(0.0) };
  6080. double m_voxelScale{ double(0.0) };
  6081. double m_voxelHalfScale{ double(0.0) };
  6082. VHACD::Vect3 m_voxelBmin;
  6083. VHACD::Vect3 m_voxelBmax;
  6084. uint32_t m_meshId{ 0 };
  6085. std::priority_queue<HullPair> m_hullPairQueue;
  6086. #if !VHACD_DISABLE_THREADING
  6087. std::unique_ptr<ThreadPool> m_threadPool{ nullptr };
  6088. #endif
  6089. std::unordered_map<uint32_t, IVHACD::ConvexHull*> m_hulls;
  6090. double m_overallProgress{ double(0.0) };
  6091. double m_stageProgress{ double(0.0) };
  6092. double m_operationProgress{ double(0.0) };
  6093. };
  6094. void VHACDImpl::Cancel()
  6095. {
  6096. m_canceled = true;
  6097. }
  6098. bool VHACDImpl::Compute(const float* const points,
  6099. const uint32_t countPoints,
  6100. const uint32_t* const triangles,
  6101. const uint32_t countTriangles,
  6102. const Parameters& params)
  6103. {
  6104. std::vector<VHACD::Vertex> v;
  6105. v.reserve(countPoints);
  6106. for (uint32_t i = 0; i < countPoints; ++i)
  6107. {
  6108. v.emplace_back(points[i * 3 + 0],
  6109. points[i * 3 + 1],
  6110. points[i * 3 + 2]);
  6111. }
  6112. std::vector<VHACD::Triangle> t;
  6113. t.reserve(countTriangles);
  6114. for (uint32_t i = 0; i < countTriangles; ++i)
  6115. {
  6116. t.emplace_back(triangles[i * 3 + 0],
  6117. triangles[i * 3 + 1],
  6118. triangles[i * 3 + 2]);
  6119. }
  6120. return Compute(v, t, params);
  6121. }
  6122. bool VHACDImpl::Compute(const double* const points,
  6123. const uint32_t countPoints,
  6124. const uint32_t* const triangles,
  6125. const uint32_t countTriangles,
  6126. const Parameters& params)
  6127. {
  6128. std::vector<VHACD::Vertex> v;
  6129. v.reserve(countPoints);
  6130. for (uint32_t i = 0; i < countPoints; ++i)
  6131. {
  6132. v.emplace_back(points[i * 3 + 0],
  6133. points[i * 3 + 1],
  6134. points[i * 3 + 2]);
  6135. }
  6136. std::vector<VHACD::Triangle> t;
  6137. t.reserve(countTriangles);
  6138. for (uint32_t i = 0; i < countTriangles; ++i)
  6139. {
  6140. t.emplace_back(triangles[i * 3 + 0],
  6141. triangles[i * 3 + 1],
  6142. triangles[i * 3 + 2]);
  6143. }
  6144. return Compute(v, t, params);
  6145. }
  6146. uint32_t VHACDImpl::GetNConvexHulls() const
  6147. {
  6148. return uint32_t(m_convexHulls.size());
  6149. }
  6150. bool VHACDImpl::GetConvexHull(const uint32_t index,
  6151. ConvexHull& ch) const
  6152. {
  6153. bool ret = false;
  6154. if ( index < uint32_t(m_convexHulls.size() ))
  6155. {
  6156. ch = *m_convexHulls[index];
  6157. ret = true;
  6158. }
  6159. return ret;
  6160. }
  6161. void VHACDImpl::Clean()
  6162. {
  6163. #if !VHACD_DISABLE_THREADING
  6164. m_threadPool = nullptr;
  6165. #endif
  6166. m_trees.clear();
  6167. for (auto& ch : m_convexHulls)
  6168. {
  6169. ReleaseConvexHull(ch);
  6170. }
  6171. m_convexHulls.clear();
  6172. for (auto& ch : m_hulls)
  6173. {
  6174. ReleaseConvexHull(ch.second);
  6175. }
  6176. m_hulls.clear();
  6177. m_voxelHulls.clear();
  6178. m_pendingHulls.clear();
  6179. m_vertices.clear();
  6180. m_indices.clear();
  6181. }
  6182. void VHACDImpl::Release()
  6183. {
  6184. delete this;
  6185. }
  6186. bool VHACDImpl::ComputeCenterOfMass(double centerOfMass[3]) const
  6187. {
  6188. bool ret = false;
  6189. return ret;
  6190. }
  6191. bool VHACDImpl::IsReady() const
  6192. {
  6193. return true;
  6194. }
  6195. uint32_t VHACDImpl::findNearestConvexHull(const double pos[3],
  6196. double& distanceToHull)
  6197. {
  6198. uint32_t ret = 0; // The default return code is zero
  6199. uint32_t hullCount = GetNConvexHulls();
  6200. distanceToHull = 0;
  6201. // First, make sure that we have valid and completed results
  6202. if ( hullCount )
  6203. {
  6204. // See if we already have AABB trees created for each convex hull
  6205. if ( m_trees.empty() )
  6206. {
  6207. // For each convex hull, we generate an AABB tree for fast closest point queries
  6208. for (uint32_t i = 0; i < hullCount; i++)
  6209. {
  6210. VHACD::IVHACD::ConvexHull ch;
  6211. GetConvexHull(i,ch);
  6212. // Pass the triangle mesh to create an AABB tree instance based on it.
  6213. m_trees.emplace_back(new AABBTree(ch.m_points,
  6214. ch.m_triangles));
  6215. }
  6216. }
  6217. // We now compute the closest point to each convex hull and save the nearest one
  6218. double closest = 1e99;
  6219. for (uint32_t i = 0; i < hullCount; i++)
  6220. {
  6221. std::unique_ptr<AABBTree>& t = m_trees[i];
  6222. if ( t )
  6223. {
  6224. VHACD::Vect3 closestPoint;
  6225. VHACD::Vect3 position(pos[0],
  6226. pos[1],
  6227. pos[2]);
  6228. if ( t->GetClosestPointWithinDistance(position, 1e99, closestPoint))
  6229. {
  6230. VHACD::Vect3 d = position - closestPoint;
  6231. double distanceSquared = d.GetNormSquared();
  6232. if ( distanceSquared < closest )
  6233. {
  6234. closest = distanceSquared;
  6235. ret = i;
  6236. }
  6237. }
  6238. }
  6239. }
  6240. distanceToHull = sqrt(closest); // compute the distance to the nearest convex hull
  6241. }
  6242. return ret;
  6243. }
  6244. bool VHACDImpl::Compute(const std::vector<VHACD::Vertex>& points,
  6245. const std::vector<VHACD::Triangle>& triangles,
  6246. const Parameters& params)
  6247. {
  6248. bool ret = false;
  6249. m_params = params;
  6250. m_canceled = false;
  6251. Clean(); // release any previous results
  6252. #if !VHACD_DISABLE_THREADING
  6253. if ( m_params.m_asyncACD )
  6254. {
  6255. m_threadPool = std::unique_ptr<ThreadPool>(new ThreadPool(8));
  6256. }
  6257. #endif
  6258. CopyInputMesh(points,
  6259. triangles);
  6260. if ( !m_canceled )
  6261. {
  6262. // We now recursively perform convex decomposition until complete
  6263. PerformConvexDecomposition();
  6264. }
  6265. if ( m_canceled )
  6266. {
  6267. Clean();
  6268. ret = false;
  6269. if ( m_params.m_logger )
  6270. {
  6271. m_params.m_logger->Log("VHACD operation canceled before it was complete.");
  6272. }
  6273. }
  6274. else
  6275. {
  6276. ret = true;
  6277. }
  6278. #if !VHACD_DISABLE_THREADING
  6279. m_threadPool = nullptr;
  6280. #endif
  6281. return ret;
  6282. }
  6283. uint32_t VHACDImpl::GetIndex(VHACD::VertexIndex& vi,
  6284. const VHACD::Vertex& p)
  6285. {
  6286. VHACD::Vect3 pos = (VHACD::Vect3(p) - m_center) * m_recipScale;
  6287. bool newPos;
  6288. uint32_t ret = vi.GetIndex(pos,
  6289. newPos);
  6290. return ret;
  6291. }
  6292. void VHACDImpl::CopyInputMesh(const std::vector<VHACD::Vertex>& points,
  6293. const std::vector<VHACD::Triangle>& triangles)
  6294. {
  6295. m_vertices.clear();
  6296. m_indices.clear();
  6297. m_indices.reserve(triangles.size());
  6298. // First we must find the bounding box of this input vertices and normalize them into a unit-cube
  6299. VHACD::Vect3 bmin( FLT_MAX);
  6300. VHACD::Vect3 bmax(-FLT_MAX);
  6301. ProgressUpdate(Stages::COMPUTE_BOUNDS_OF_INPUT_MESH,
  6302. 0,
  6303. "ComputingBounds");
  6304. for (uint32_t i = 0; i < points.size(); i++)
  6305. {
  6306. const VHACD::Vertex& p = points[i];
  6307. bmin = bmin.CWiseMin(p);
  6308. bmax = bmax.CWiseMax(p);
  6309. }
  6310. ProgressUpdate(Stages::COMPUTE_BOUNDS_OF_INPUT_MESH,
  6311. 100,
  6312. "ComputingBounds");
  6313. m_center = (bmax + bmin) * double(0.5);
  6314. VHACD::Vect3 scale = bmax - bmin;
  6315. m_scale = scale.MaxCoeff();
  6316. m_recipScale = m_scale > double(0.0) ? double(1.0) / m_scale : double(0.0);
  6317. {
  6318. VHACD::VertexIndex vi = VHACD::VertexIndex(double(0.001), false);
  6319. uint32_t dcount = 0;
  6320. for (uint32_t i = 0; i < triangles.size() && !m_canceled; ++i)
  6321. {
  6322. const VHACD::Triangle& t = triangles[i];
  6323. const VHACD::Vertex& p1 = points[t.mI0];
  6324. const VHACD::Vertex& p2 = points[t.mI1];
  6325. const VHACD::Vertex& p3 = points[t.mI2];
  6326. uint32_t i1 = GetIndex(vi, p1);
  6327. uint32_t i2 = GetIndex(vi, p2);
  6328. uint32_t i3 = GetIndex(vi, p3);
  6329. if ( i1 == i2 || i1 == i3 || i2 == i3 )
  6330. {
  6331. dcount++;
  6332. }
  6333. else
  6334. {
  6335. m_indices.emplace_back(i1, i2, i3);
  6336. }
  6337. }
  6338. if ( dcount )
  6339. {
  6340. if ( m_params.m_logger )
  6341. {
  6342. char scratch[512];
  6343. snprintf(scratch,
  6344. sizeof(scratch),
  6345. "Skipped %d degenerate triangles", dcount);
  6346. m_params.m_logger->Log(scratch);
  6347. }
  6348. }
  6349. m_vertices = vi.TakeVertices();
  6350. }
  6351. // Create the raycast mesh
  6352. if ( !m_canceled )
  6353. {
  6354. ProgressUpdate(Stages::CREATE_RAYCAST_MESH,
  6355. 0,
  6356. "Building RaycastMesh");
  6357. m_AABBTree = VHACD::AABBTree(m_vertices,
  6358. m_indices);
  6359. ProgressUpdate(Stages::CREATE_RAYCAST_MESH,
  6360. 100,
  6361. "RaycastMesh completed");
  6362. }
  6363. if ( !m_canceled )
  6364. {
  6365. ProgressUpdate(Stages::VOXELIZING_INPUT_MESH,
  6366. 0,
  6367. "Voxelizing Input Mesh");
  6368. m_voxelize = VHACD::Volume();
  6369. m_voxelize.Voxelize(m_vertices,
  6370. m_indices,
  6371. m_params.m_resolution,
  6372. m_params.m_fillMode,
  6373. m_AABBTree);
  6374. m_voxelScale = m_voxelize.GetScale();
  6375. m_voxelHalfScale = m_voxelScale * double(0.5);
  6376. m_voxelBmin = m_voxelize.GetBounds().GetMin();
  6377. m_voxelBmax = m_voxelize.GetBounds().GetMax();
  6378. ProgressUpdate(Stages::VOXELIZING_INPUT_MESH,
  6379. 100,
  6380. "Voxelization complete");
  6381. }
  6382. m_inputMesh.m_vertices = m_vertices;
  6383. m_inputMesh.m_indices = m_indices;
  6384. if ( !m_canceled )
  6385. {
  6386. ProgressUpdate(Stages::BUILD_INITIAL_CONVEX_HULL,
  6387. 0,
  6388. "Build initial ConvexHull");
  6389. std::unique_ptr<VoxelHull> vh = std::unique_ptr<VoxelHull>(new VoxelHull(m_voxelize,
  6390. m_params,
  6391. this));
  6392. if ( vh->m_convexHull )
  6393. {
  6394. m_overallHullVolume = vh->m_convexHull->m_volume;
  6395. }
  6396. m_pendingHulls.push_back(std::move(vh));
  6397. ProgressUpdate(Stages::BUILD_INITIAL_CONVEX_HULL,
  6398. 100,
  6399. "Initial ConvexHull complete");
  6400. }
  6401. }
  6402. void VHACDImpl::ScaleOutputConvexHull(ConvexHull& ch)
  6403. {
  6404. for (uint32_t i = 0; i < ch.m_points.size(); i++)
  6405. {
  6406. VHACD::Vect3 p = ch.m_points[i];
  6407. p = (p * m_scale) + m_center;
  6408. ch.m_points[i] = p;
  6409. }
  6410. ch.m_volume = ComputeConvexHullVolume(ch); // get the combined volume
  6411. VHACD::BoundsAABB b(ch.m_points);
  6412. ch.mBmin = b.GetMin();
  6413. ch.mBmax = b.GetMax();
  6414. ComputeCentroid(ch.m_points,
  6415. ch.m_triangles,
  6416. ch.m_center);
  6417. }
  6418. void VHACDImpl::AddCostToPriorityQueue(CostTask& task)
  6419. {
  6420. HullPair hp(task.m_hullA->m_meshId,
  6421. task.m_hullB->m_meshId,
  6422. task.m_concavity);
  6423. m_hullPairQueue.push(hp);
  6424. }
  6425. void VHACDImpl::ReleaseConvexHull(ConvexHull* ch)
  6426. {
  6427. if ( ch )
  6428. {
  6429. delete ch;
  6430. }
  6431. }
  6432. void jobCallback(std::unique_ptr<VoxelHull>& userPtr)
  6433. {
  6434. userPtr->PerformPlaneSplit();
  6435. }
  6436. void computeMergeCostTask(CostTask& ptr)
  6437. {
  6438. ptr.m_this->PerformMergeCostTask(ptr);
  6439. }
  6440. void VHACDImpl::PerformConvexDecomposition()
  6441. {
  6442. {
  6443. ScopedTime st("Convex Decomposition",
  6444. m_params.m_logger);
  6445. double maxHulls = pow(2, m_params.m_maxRecursionDepth);
  6446. // We recursively split convex hulls until we can
  6447. // no longer recurse further.
  6448. Timer t;
  6449. while ( !m_pendingHulls.empty() && !m_canceled )
  6450. {
  6451. size_t count = m_pendingHulls.size() + m_voxelHulls.size();
  6452. double e = t.PeekElapsedSeconds();
  6453. if ( e >= double(0.1) )
  6454. {
  6455. t.Reset();
  6456. double stageProgress = (double(count) * double(100.0)) / maxHulls;
  6457. ProgressUpdate(Stages::PERFORMING_DECOMPOSITION,
  6458. stageProgress,
  6459. "Performing recursive decomposition of convex hulls");
  6460. }
  6461. // First we make a copy of the hulls we are processing
  6462. std::vector<std::unique_ptr<VoxelHull>> oldList = std::move(m_pendingHulls);
  6463. // For each hull we want to split, we either
  6464. // immediately perform the plane split or we post it as
  6465. // a job to be performed in a background thread
  6466. std::vector<std::future<void>> futures(oldList.size());
  6467. uint32_t futureCount = 0;
  6468. for (auto& i : oldList)
  6469. {
  6470. if ( i->IsComplete() || count > MaxConvexHullFragments )
  6471. {
  6472. }
  6473. else
  6474. {
  6475. #if !VHACD_DISABLE_THREADING
  6476. if ( m_threadPool )
  6477. {
  6478. futures[futureCount] = m_threadPool->enqueue([&i]
  6479. {
  6480. jobCallback(i);
  6481. });
  6482. futureCount++;
  6483. }
  6484. else
  6485. #endif
  6486. {
  6487. i->PerformPlaneSplit();
  6488. }
  6489. }
  6490. }
  6491. // Wait for any outstanding jobs to complete in the background threads
  6492. if ( futureCount )
  6493. {
  6494. for (uint32_t i = 0; i < futureCount; i++)
  6495. {
  6496. futures[i].get();
  6497. }
  6498. }
  6499. // Now, we rebuild the pending convex hulls list by
  6500. // adding the two children to the output list if
  6501. // we need to recurse them further
  6502. for (auto& vh : oldList)
  6503. {
  6504. if ( vh->IsComplete() || count > MaxConvexHullFragments )
  6505. {
  6506. if ( vh->m_convexHull )
  6507. {
  6508. m_voxelHulls.push_back(std::move(vh));
  6509. }
  6510. }
  6511. else
  6512. {
  6513. if ( vh->m_hullA )
  6514. {
  6515. m_pendingHulls.push_back(std::move(vh->m_hullA));
  6516. }
  6517. if ( vh->m_hullB )
  6518. {
  6519. m_pendingHulls.push_back(std::move(vh->m_hullB));
  6520. }
  6521. }
  6522. }
  6523. }
  6524. }
  6525. if ( !m_canceled )
  6526. {
  6527. // Give each convex hull a unique guid
  6528. m_meshId = 0;
  6529. m_hulls.clear();
  6530. // Build the convex hull id map
  6531. std::vector<ConvexHull*> hulls;
  6532. ProgressUpdate(Stages::INITIALIZING_CONVEX_HULLS_FOR_MERGING,
  6533. 0,
  6534. "Initializing ConvexHulls");
  6535. for (auto& vh : m_voxelHulls)
  6536. {
  6537. if ( m_canceled )
  6538. {
  6539. break;
  6540. }
  6541. ConvexHull* ch = CopyConvexHull(*vh->m_convexHull);
  6542. m_meshId++;
  6543. ch->m_meshId = m_meshId;
  6544. m_hulls[m_meshId] = ch;
  6545. // Compute the volume of the convex hull
  6546. ch->m_volume = ComputeConvexHullVolume(*ch);
  6547. // Compute the AABB of the convex hull
  6548. VHACD::BoundsAABB b = VHACD::BoundsAABB(ch->m_points).Inflate(double(0.1));
  6549. ch->mBmin = b.GetMin();
  6550. ch->mBmax = b.GetMax();
  6551. ComputeCentroid(ch->m_points,
  6552. ch->m_triangles,
  6553. ch->m_center);
  6554. hulls.push_back(ch);
  6555. }
  6556. ProgressUpdate(Stages::INITIALIZING_CONVEX_HULLS_FOR_MERGING,
  6557. 100,
  6558. "ConvexHull initialization complete");
  6559. m_voxelHulls.clear();
  6560. // here we merge convex hulls as needed until the match the
  6561. // desired maximum hull count.
  6562. size_t hullCount = hulls.size();
  6563. if ( hullCount > m_params.m_maxConvexHulls && !m_canceled)
  6564. {
  6565. size_t costMatrixSize = ((hullCount * hullCount) - hullCount) >> 1;
  6566. std::vector<CostTask> tasks;
  6567. tasks.reserve(costMatrixSize);
  6568. ScopedTime st("Computing the Cost Matrix",
  6569. m_params.m_logger);
  6570. // First thing we need to do is compute the cost matrix
  6571. // This is computed as the volume error of any two convex hulls
  6572. // combined
  6573. ProgressUpdate(Stages::COMPUTING_COST_MATRIX,
  6574. 0,
  6575. "Computing Hull Merge Cost Matrix");
  6576. for (size_t i = 1; i < hullCount && !m_canceled; i++)
  6577. {
  6578. ConvexHull* chA = hulls[i];
  6579. for (size_t j = 0; j < i && !m_canceled; j++)
  6580. {
  6581. ConvexHull* chB = hulls[j];
  6582. CostTask t;
  6583. t.m_hullA = chA;
  6584. t.m_hullB = chB;
  6585. t.m_this = this;
  6586. if ( DoFastCost(t) )
  6587. {
  6588. }
  6589. else
  6590. {
  6591. tasks.push_back(std::move(t));
  6592. CostTask* task = &tasks.back();
  6593. #if !VHACD_DISABLE_THREADING
  6594. if ( m_threadPool )
  6595. {
  6596. task->m_future = m_threadPool->enqueue([task]
  6597. {
  6598. computeMergeCostTask(*task);
  6599. });
  6600. }
  6601. #endif
  6602. }
  6603. }
  6604. }
  6605. if ( !m_canceled )
  6606. {
  6607. #if !VHACD_DISABLE_THREADING
  6608. if ( m_threadPool )
  6609. {
  6610. for (CostTask& task : tasks)
  6611. {
  6612. task.m_future.get();
  6613. }
  6614. for (CostTask& task : tasks)
  6615. {
  6616. AddCostToPriorityQueue(task);
  6617. }
  6618. }
  6619. else
  6620. #endif
  6621. {
  6622. for (CostTask& task : tasks)
  6623. {
  6624. PerformMergeCostTask(task);
  6625. AddCostToPriorityQueue(task);
  6626. }
  6627. }
  6628. ProgressUpdate(Stages::COMPUTING_COST_MATRIX,
  6629. 100,
  6630. "Finished cost matrix");
  6631. }
  6632. if ( !m_canceled )
  6633. {
  6634. ScopedTime stMerging("Merging Convex Hulls",
  6635. m_params.m_logger);
  6636. Timer t;
  6637. // Now that we know the cost to merge each hull, we can begin merging them.
  6638. bool cancel = false;
  6639. uint32_t maxMergeCount = uint32_t(m_hulls.size()) - m_params.m_maxConvexHulls;
  6640. uint32_t startCount = uint32_t(m_hulls.size());
  6641. while ( !cancel
  6642. && m_hulls.size() > m_params.m_maxConvexHulls
  6643. && !m_hullPairQueue.empty()
  6644. && !m_canceled)
  6645. {
  6646. double e = t.PeekElapsedSeconds();
  6647. if ( e >= double(0.1) )
  6648. {
  6649. t.Reset();
  6650. uint32_t hullsProcessed = startCount - uint32_t(m_hulls.size() );
  6651. double stageProgress = double(hullsProcessed * 100) / double(maxMergeCount);
  6652. ProgressUpdate(Stages::MERGING_CONVEX_HULLS,
  6653. stageProgress,
  6654. "Merging Convex Hulls");
  6655. }
  6656. HullPair hp = m_hullPairQueue.top();
  6657. m_hullPairQueue.pop();
  6658. // It is entirely possible that the hull pair queue can
  6659. // have references to convex hulls that are no longer valid
  6660. // because they were previously merged. So we check for this
  6661. // and if either hull referenced in this pair no longer
  6662. // exists, then we skip it.
  6663. // Look up this pair of hulls by ID
  6664. ConvexHull* ch1 = GetHull(hp.m_hullA);
  6665. ConvexHull* ch2 = GetHull(hp.m_hullB);
  6666. // If both hulls are still valid, then we merge them, delete the old
  6667. // two hulls and recompute the cost matrix for the new combined hull
  6668. // we have created
  6669. if ( ch1 && ch2 )
  6670. {
  6671. // This is the convex hull which results from combining the
  6672. // vertices in the two source hulls
  6673. ConvexHull* combinedHull = ComputeCombinedConvexHull(*ch1,
  6674. *ch2);
  6675. // The two old convex hulls are going to get removed
  6676. RemoveHull(hp.m_hullA);
  6677. RemoveHull(hp.m_hullB);
  6678. m_meshId++;
  6679. combinedHull->m_meshId = m_meshId;
  6680. tasks.clear();
  6681. tasks.reserve(m_hulls.size());
  6682. // Compute the cost between this new merged hull
  6683. // and all existing convex hulls and then
  6684. // add that to the priority queue
  6685. for (auto& i : m_hulls)
  6686. {
  6687. if ( m_canceled )
  6688. {
  6689. break;
  6690. }
  6691. ConvexHull* secondHull = i.second;
  6692. CostTask t;
  6693. t.m_hullA = combinedHull;
  6694. t.m_hullB = secondHull;
  6695. t.m_this = this;
  6696. if ( DoFastCost(t) )
  6697. {
  6698. }
  6699. else
  6700. {
  6701. tasks.push_back(std::move(t));
  6702. }
  6703. }
  6704. m_hulls[combinedHull->m_meshId] = combinedHull;
  6705. // See how many merge cost tasks were posted
  6706. // If there are 8 or more and we are running asynchronously, then do them that way.
  6707. #if !VHACD_DISABLE_THREADING
  6708. if ( m_threadPool && tasks.size() >= 2)
  6709. {
  6710. for (CostTask& task : tasks)
  6711. {
  6712. task.m_future = m_threadPool->enqueue([&task]
  6713. {
  6714. computeMergeCostTask(task);
  6715. });
  6716. }
  6717. for (CostTask& task : tasks)
  6718. {
  6719. task.m_future.get();
  6720. }
  6721. }
  6722. else
  6723. #endif
  6724. {
  6725. for (CostTask& task : tasks)
  6726. {
  6727. PerformMergeCostTask(task);
  6728. }
  6729. }
  6730. for (CostTask& task : tasks)
  6731. {
  6732. AddCostToPriorityQueue(task);
  6733. }
  6734. }
  6735. }
  6736. // Ok...once we are done, we copy the results!
  6737. m_meshId -= 0;
  6738. ProgressUpdate(Stages::FINALIZING_RESULTS,
  6739. 0,
  6740. "Finalizing results");
  6741. for (auto& i : m_hulls)
  6742. {
  6743. if ( m_canceled )
  6744. {
  6745. break;
  6746. }
  6747. ConvexHull* ch = i.second;
  6748. // We now must reduce the convex hull
  6749. if ( ch->m_points.size() > m_params.m_maxNumVerticesPerCH || m_params.m_shrinkWrap)
  6750. {
  6751. ConvexHull* reduce = ComputeReducedConvexHull(*ch,
  6752. m_params.m_maxNumVerticesPerCH,
  6753. m_params.m_shrinkWrap);
  6754. ReleaseConvexHull(ch);
  6755. ch = reduce;
  6756. }
  6757. ScaleOutputConvexHull(*ch);
  6758. ch->m_meshId = m_meshId;
  6759. m_meshId++;
  6760. m_convexHulls.push_back(ch);
  6761. }
  6762. m_hulls.clear(); // since the hulls were moved into the output list, we don't need to delete them from this container
  6763. ProgressUpdate(Stages::FINALIZING_RESULTS,
  6764. 100,
  6765. "Finalized results complete");
  6766. }
  6767. }
  6768. else
  6769. {
  6770. ProgressUpdate(Stages::FINALIZING_RESULTS,
  6771. 0,
  6772. "Finalizing results");
  6773. m_meshId = 0;
  6774. for (auto& ch : hulls)
  6775. {
  6776. // We now must reduce the convex hull
  6777. if ( ch->m_points.size() > m_params.m_maxNumVerticesPerCH || m_params.m_shrinkWrap )
  6778. {
  6779. ConvexHull* reduce = ComputeReducedConvexHull(*ch,
  6780. m_params.m_maxNumVerticesPerCH,
  6781. m_params.m_shrinkWrap);
  6782. ReleaseConvexHull(ch);
  6783. ch = reduce;
  6784. }
  6785. ScaleOutputConvexHull(*ch);
  6786. ch->m_meshId = m_meshId;
  6787. m_meshId++;
  6788. m_convexHulls.push_back(ch);
  6789. }
  6790. m_hulls.clear();
  6791. ProgressUpdate(Stages::FINALIZING_RESULTS,
  6792. 100,
  6793. "Finalized results");
  6794. }
  6795. }
  6796. }
  6797. double VHACDImpl::ComputeConvexHullVolume(const ConvexHull& sm)
  6798. {
  6799. double totalVolume = 0;
  6800. VHACD::Vect3 bary(0, 0, 0);
  6801. for (uint32_t i = 0; i < sm.m_points.size(); i++)
  6802. {
  6803. VHACD::Vect3 p(sm.m_points[i]);
  6804. bary += p;
  6805. }
  6806. bary /= double(sm.m_points.size());
  6807. for (uint32_t i = 0; i < sm.m_triangles.size(); i++)
  6808. {
  6809. uint32_t i1 = sm.m_triangles[i].mI0;
  6810. uint32_t i2 = sm.m_triangles[i].mI1;
  6811. uint32_t i3 = sm.m_triangles[i].mI2;
  6812. VHACD::Vect3 ver0(sm.m_points[i1]);
  6813. VHACD::Vect3 ver1(sm.m_points[i2]);
  6814. VHACD::Vect3 ver2(sm.m_points[i3]);
  6815. totalVolume += ComputeVolume4(ver0,
  6816. ver1,
  6817. ver2,
  6818. bary);
  6819. }
  6820. totalVolume = totalVolume / double(6.0);
  6821. return totalVolume;
  6822. }
  6823. double VHACDImpl::ComputeVolume4(const VHACD::Vect3& a,
  6824. const VHACD::Vect3& b,
  6825. const VHACD::Vect3& c,
  6826. const VHACD::Vect3& d)
  6827. {
  6828. VHACD::Vect3 ad = a - d;
  6829. VHACD::Vect3 bd = b - d;
  6830. VHACD::Vect3 cd = c - d;
  6831. VHACD::Vect3 bcd = bd.Cross(cd);
  6832. double dot = ad.Dot(bcd);
  6833. return dot;
  6834. }
  6835. double VHACDImpl::ComputeConcavity(double volumeSeparate,
  6836. double volumeCombined,
  6837. double volumeMesh)
  6838. {
  6839. return fabs(volumeSeparate - volumeCombined) / volumeMesh;
  6840. }
  6841. bool VHACDImpl::DoFastCost(CostTask& mt)
  6842. {
  6843. bool ret = false;
  6844. ConvexHull* ch1 = mt.m_hullA;
  6845. ConvexHull* ch2 = mt.m_hullB;
  6846. VHACD::BoundsAABB ch1b(ch1->mBmin,
  6847. ch1->mBmax);
  6848. VHACD::BoundsAABB ch2b(ch2->mBmin,
  6849. ch2->mBmax);
  6850. if (!ch1b.Intersects(ch2b))
  6851. {
  6852. VHACD::BoundsAABB b = ch1b.Union(ch2b);
  6853. double combinedVolume = b.Volume();
  6854. double concavity = ComputeConcavity(ch1->m_volume + ch2->m_volume,
  6855. combinedVolume,
  6856. m_overallHullVolume);
  6857. HullPair hp(ch1->m_meshId,
  6858. ch2->m_meshId,
  6859. concavity);
  6860. m_hullPairQueue.push(hp);
  6861. ret = true;
  6862. }
  6863. return ret;
  6864. }
  6865. void VHACDImpl::PerformMergeCostTask(CostTask& mt)
  6866. {
  6867. ConvexHull* ch1 = mt.m_hullA;
  6868. ConvexHull* ch2 = mt.m_hullB;
  6869. double volume1 = ch1->m_volume;
  6870. double volume2 = ch2->m_volume;
  6871. ConvexHull* combined = ComputeCombinedConvexHull(*ch1,
  6872. *ch2); // Build the combined convex hull
  6873. double combinedVolume = ComputeConvexHullVolume(*combined); // get the combined volume
  6874. mt.m_concavity = ComputeConcavity(volume1 + volume2,
  6875. combinedVolume,
  6876. m_overallHullVolume);
  6877. ReleaseConvexHull(combined);
  6878. }
  6879. IVHACD::ConvexHull* VHACDImpl::ComputeReducedConvexHull(const ConvexHull& ch,
  6880. uint32_t maxVerts,
  6881. bool projectHullVertices)
  6882. {
  6883. SimpleMesh sourceConvexHull;
  6884. sourceConvexHull.m_vertices = ch.m_points;
  6885. sourceConvexHull.m_indices = ch.m_triangles;
  6886. ShrinkWrap(sourceConvexHull,
  6887. m_AABBTree,
  6888. maxVerts,
  6889. m_voxelScale * 4,
  6890. projectHullVertices);
  6891. ConvexHull *ret = new ConvexHull;
  6892. ret->m_points = sourceConvexHull.m_vertices;
  6893. ret->m_triangles = sourceConvexHull.m_indices;
  6894. VHACD::BoundsAABB b = VHACD::BoundsAABB(ret->m_points).Inflate(double(0.1));
  6895. ret->mBmin = b.GetMin();
  6896. ret->mBmax = b.GetMax();
  6897. ComputeCentroid(ret->m_points,
  6898. ret->m_triangles,
  6899. ret->m_center);
  6900. ret->m_volume = ComputeConvexHullVolume(*ret);
  6901. // Return the convex hull
  6902. return ret;
  6903. }
  6904. IVHACD::ConvexHull* VHACDImpl::ComputeCombinedConvexHull(const ConvexHull& sm1,
  6905. const ConvexHull& sm2)
  6906. {
  6907. uint32_t vcount = uint32_t(sm1.m_points.size() + sm2.m_points.size()); // Total vertices from both hulls
  6908. std::vector<VHACD::Vertex> vertices(vcount);
  6909. auto it = std::copy(sm1.m_points.begin(),
  6910. sm1.m_points.end(),
  6911. vertices.begin());
  6912. std::copy(sm2.m_points.begin(),
  6913. sm2.m_points.end(),
  6914. it);
  6915. VHACD::QuickHull qh;
  6916. qh.ComputeConvexHull(vertices,
  6917. vcount);
  6918. ConvexHull* ret = new ConvexHull;
  6919. ret->m_points = qh.GetVertices();
  6920. ret->m_triangles = qh.GetIndices();
  6921. ret->m_volume = ComputeConvexHullVolume(*ret);
  6922. VHACD::BoundsAABB b = VHACD::BoundsAABB(qh.GetVertices()).Inflate(double(0.1));
  6923. ret->mBmin = b.GetMin();
  6924. ret->mBmax = b.GetMax();
  6925. ComputeCentroid(ret->m_points,
  6926. ret->m_triangles,
  6927. ret->m_center);
  6928. // Return the convex hull
  6929. return ret;
  6930. }
  6931. IVHACD::ConvexHull* VHACDImpl::GetHull(uint32_t index)
  6932. {
  6933. ConvexHull* ret = nullptr;
  6934. auto found = m_hulls.find(index);
  6935. if ( found != m_hulls.end() )
  6936. {
  6937. ret = found->second;
  6938. }
  6939. return ret;
  6940. }
  6941. bool VHACDImpl::RemoveHull(uint32_t index)
  6942. {
  6943. bool ret = false;
  6944. auto found = m_hulls.find(index);
  6945. if ( found != m_hulls.end() )
  6946. {
  6947. ret = true;
  6948. ReleaseConvexHull(found->second);
  6949. m_hulls.erase(found);
  6950. }
  6951. return ret;
  6952. }
  6953. IVHACD::ConvexHull* VHACDImpl::CopyConvexHull(const ConvexHull& source)
  6954. {
  6955. ConvexHull *ch = new ConvexHull;
  6956. *ch = source;
  6957. return ch;
  6958. }
  6959. const char* VHACDImpl::GetStageName(Stages stage) const
  6960. {
  6961. const char *ret = "unknown";
  6962. switch ( stage )
  6963. {
  6964. case Stages::COMPUTE_BOUNDS_OF_INPUT_MESH:
  6965. ret = "COMPUTE_BOUNDS_OF_INPUT_MESH";
  6966. break;
  6967. case Stages::REINDEXING_INPUT_MESH:
  6968. ret = "REINDEXING_INPUT_MESH";
  6969. break;
  6970. case Stages::CREATE_RAYCAST_MESH:
  6971. ret = "CREATE_RAYCAST_MESH";
  6972. break;
  6973. case Stages::VOXELIZING_INPUT_MESH:
  6974. ret = "VOXELIZING_INPUT_MESH";
  6975. break;
  6976. case Stages::BUILD_INITIAL_CONVEX_HULL:
  6977. ret = "BUILD_INITIAL_CONVEX_HULL";
  6978. break;
  6979. case Stages::PERFORMING_DECOMPOSITION:
  6980. ret = "PERFORMING_DECOMPOSITION";
  6981. break;
  6982. case Stages::INITIALIZING_CONVEX_HULLS_FOR_MERGING:
  6983. ret = "INITIALIZING_CONVEX_HULLS_FOR_MERGING";
  6984. break;
  6985. case Stages::COMPUTING_COST_MATRIX:
  6986. ret = "COMPUTING_COST_MATRIX";
  6987. break;
  6988. case Stages::MERGING_CONVEX_HULLS:
  6989. ret = "MERGING_CONVEX_HULLS";
  6990. break;
  6991. case Stages::FINALIZING_RESULTS:
  6992. ret = "FINALIZING_RESULTS";
  6993. break;
  6994. case Stages::NUM_STAGES:
  6995. // Should be unreachable, here to silence enumeration value not handled in switch warnings
  6996. // GCC/Clang's -Wswitch
  6997. break;
  6998. }
  6999. return ret;
  7000. }
  7001. void VHACDImpl::ProgressUpdate(Stages stage,
  7002. double stageProgress,
  7003. const char* operation)
  7004. {
  7005. if ( m_params.m_callback )
  7006. {
  7007. double overallProgress = (double(stage) * 100) / double(Stages::NUM_STAGES);
  7008. const char *s = GetStageName(stage);
  7009. m_params.m_callback->Update(overallProgress,
  7010. stageProgress,
  7011. s,
  7012. operation);
  7013. }
  7014. }
  7015. bool VHACDImpl::IsCanceled() const
  7016. {
  7017. return m_canceled;
  7018. }
  7019. IVHACD* CreateVHACD(void)
  7020. {
  7021. VHACDImpl *ret = new VHACDImpl;
  7022. return static_cast< IVHACD *>(ret);
  7023. }
  7024. IVHACD* CreateVHACD(void);
  7025. #if !VHACD_DISABLE_THREADING
  7026. class LogMessage
  7027. {
  7028. public:
  7029. double m_overallProgress{ double(-1.0) };
  7030. double m_stageProgress{ double(-1.0) };
  7031. std::string m_stage;
  7032. std::string m_operation;
  7033. };
  7034. class VHACDAsyncImpl : public VHACD::IVHACD,
  7035. public VHACD::IVHACD::IUserCallback,
  7036. VHACD::IVHACD::IUserLogger,
  7037. VHACD::IVHACD::IUserTaskRunner
  7038. {
  7039. public:
  7040. VHACDAsyncImpl() = default;
  7041. ~VHACDAsyncImpl() override;
  7042. void Cancel() override final;
  7043. bool Compute(const float* const points,
  7044. const uint32_t countPoints,
  7045. const uint32_t* const triangles,
  7046. const uint32_t countTriangles,
  7047. const Parameters& params) override final;
  7048. bool Compute(const double* const points,
  7049. const uint32_t countPoints,
  7050. const uint32_t* const triangles,
  7051. const uint32_t countTriangles,
  7052. const Parameters& params) override final;
  7053. bool GetConvexHull(const uint32_t index,
  7054. VHACD::IVHACD::ConvexHull& ch) const override final;
  7055. uint32_t GetNConvexHulls() const override final;
  7056. void Clean() override final; // release internally allocated memory
  7057. void Release() override final; // release IVHACD
  7058. // Will compute the center of mass of the convex hull decomposition results and return it
  7059. // in 'centerOfMass'. Returns false if the center of mass could not be computed.
  7060. bool ComputeCenterOfMass(double centerOfMass[3]) const override;
  7061. bool IsReady() const override final;
  7062. /**
  7063. * At the request of LegionFu : [email protected]
  7064. * This method will return which convex hull is closest to the source position.
  7065. * You can use this method to figure out, for example, which vertices in the original
  7066. * source mesh are best associated with which convex hull.
  7067. *
  7068. * @param pos : The input 3d position to test against
  7069. *
  7070. * @return : Returns which convex hull this position is closest to.
  7071. */
  7072. uint32_t findNearestConvexHull(const double pos[3],
  7073. double& distanceToHull) override final;
  7074. void Update(const double overallProgress,
  7075. const double stageProgress,
  7076. const char* const stage,
  7077. const char *operation) override final;
  7078. void Log(const char* const msg) override final;
  7079. void* StartTask(std::function<void()> func) override;
  7080. void JoinTask(void* Task) override;
  7081. bool Compute(const Parameters params);
  7082. bool ComputeNow(const std::vector<VHACD::Vertex>& points,
  7083. const std::vector<VHACD::Triangle>& triangles,
  7084. const Parameters& _desc);
  7085. // As a convenience for the calling application we only send it update and log messages from it's own main
  7086. // thread. This reduces the complexity burden on the caller by making sure it only has to deal with log
  7087. // messages in it's main application thread.
  7088. void ProcessPendingMessages() const;
  7089. private:
  7090. VHACD::VHACDImpl m_VHACD;
  7091. std::vector<VHACD::Vertex> m_vertices;
  7092. std::vector<VHACD::Triangle> m_indices;
  7093. VHACD::IVHACD::IUserCallback* m_callback{ nullptr };
  7094. VHACD::IVHACD::IUserLogger* m_logger{ nullptr };
  7095. VHACD::IVHACD::IUserTaskRunner* m_taskRunner{ nullptr };
  7096. void* m_task{ nullptr };
  7097. std::atomic<bool> m_running{ false };
  7098. std::atomic<bool> m_cancel{ false };
  7099. // Thread safe caching mechanism for messages and update status.
  7100. // This is so that caller always gets messages in his own thread
  7101. // Member variables are marked as 'mutable' since the message dispatch function
  7102. // is called from const query methods.
  7103. mutable std::mutex m_messageMutex;
  7104. mutable std::vector<LogMessage> m_messages;
  7105. mutable std::atomic<bool> m_haveMessages{ false };
  7106. };
  7107. VHACDAsyncImpl::~VHACDAsyncImpl()
  7108. {
  7109. Cancel();
  7110. }
  7111. void VHACDAsyncImpl::Cancel()
  7112. {
  7113. m_cancel = true;
  7114. m_VHACD.Cancel();
  7115. if (m_task)
  7116. {
  7117. m_taskRunner->JoinTask(m_task); // Wait for the thread to fully exit before we delete the instance
  7118. m_task = nullptr;
  7119. }
  7120. m_cancel = false; // clear the cancel semaphore
  7121. }
  7122. bool VHACDAsyncImpl::Compute(const float* const points,
  7123. const uint32_t countPoints,
  7124. const uint32_t* const triangles,
  7125. const uint32_t countTriangles,
  7126. const Parameters& params)
  7127. {
  7128. m_vertices.reserve(countPoints);
  7129. for (uint32_t i = 0; i < countPoints; ++i)
  7130. {
  7131. m_vertices.emplace_back(points[i * 3 + 0],
  7132. points[i * 3 + 1],
  7133. points[i * 3 + 2]);
  7134. }
  7135. m_indices.reserve(countTriangles);
  7136. for (uint32_t i = 0; i < countTriangles; ++i)
  7137. {
  7138. m_indices.emplace_back(triangles[i * 3 + 0],
  7139. triangles[i * 3 + 1],
  7140. triangles[i * 3 + 2]);
  7141. }
  7142. return Compute(params);
  7143. }
  7144. bool VHACDAsyncImpl::Compute(const double* const points,
  7145. const uint32_t countPoints,
  7146. const uint32_t* const triangles,
  7147. const uint32_t countTriangles,
  7148. const Parameters& params)
  7149. {
  7150. // We need to copy the input vertices and triangles into our own buffers so we can operate
  7151. // on them safely from the background thread.
  7152. // Can't be local variables due to being asynchronous
  7153. m_vertices.reserve(countPoints);
  7154. for (uint32_t i = 0; i < countPoints; ++i)
  7155. {
  7156. m_vertices.emplace_back(points[i * 3 + 0],
  7157. points[i * 3 + 1],
  7158. points[i * 3 + 2]);
  7159. }
  7160. m_indices.reserve(countTriangles);
  7161. for (uint32_t i = 0; i < countTriangles; ++i)
  7162. {
  7163. m_indices.emplace_back(triangles[i * 3 + 0],
  7164. triangles[i * 3 + 1],
  7165. triangles[i * 3 + 2]);
  7166. }
  7167. return Compute(params);
  7168. }
  7169. bool VHACDAsyncImpl::GetConvexHull(const uint32_t index,
  7170. VHACD::IVHACD::ConvexHull& ch) const
  7171. {
  7172. return m_VHACD.GetConvexHull(index,
  7173. ch);
  7174. }
  7175. uint32_t VHACDAsyncImpl::GetNConvexHulls() const
  7176. {
  7177. ProcessPendingMessages();
  7178. return m_VHACD.GetNConvexHulls();
  7179. }
  7180. void VHACDAsyncImpl::Clean()
  7181. {
  7182. Cancel();
  7183. m_VHACD.Clean();
  7184. }
  7185. void VHACDAsyncImpl::Release()
  7186. {
  7187. delete this;
  7188. }
  7189. bool VHACDAsyncImpl::ComputeCenterOfMass(double centerOfMass[3]) const
  7190. {
  7191. bool ret = false;
  7192. centerOfMass[0] = 0;
  7193. centerOfMass[1] = 0;
  7194. centerOfMass[2] = 0;
  7195. if (IsReady())
  7196. {
  7197. ret = m_VHACD.ComputeCenterOfMass(centerOfMass);
  7198. }
  7199. return ret;
  7200. }
  7201. bool VHACDAsyncImpl::IsReady() const
  7202. {
  7203. ProcessPendingMessages();
  7204. return !m_running;
  7205. }
  7206. uint32_t VHACDAsyncImpl::findNearestConvexHull(const double pos[3],
  7207. double& distanceToHull)
  7208. {
  7209. uint32_t ret = 0; // The default return code is zero
  7210. distanceToHull = 0;
  7211. // First, make sure that we have valid and completed results
  7212. if (IsReady() )
  7213. {
  7214. ret = m_VHACD.findNearestConvexHull(pos,distanceToHull);
  7215. }
  7216. return ret;
  7217. }
  7218. void VHACDAsyncImpl::Update(const double overallProgress,
  7219. const double stageProgress,
  7220. const char* const stage,
  7221. const char* operation)
  7222. {
  7223. m_messageMutex.lock();
  7224. LogMessage m;
  7225. m.m_operation = std::string(operation);
  7226. m.m_overallProgress = overallProgress;
  7227. m.m_stageProgress = stageProgress;
  7228. m.m_stage = std::string(stage);
  7229. m_messages.push_back(m);
  7230. m_haveMessages = true;
  7231. m_messageMutex.unlock();
  7232. }
  7233. void VHACDAsyncImpl::Log(const char* const msg)
  7234. {
  7235. m_messageMutex.lock();
  7236. LogMessage m;
  7237. m.m_operation = std::string(msg);
  7238. m_haveMessages = true;
  7239. m_messages.push_back(m);
  7240. m_messageMutex.unlock();
  7241. }
  7242. void* VHACDAsyncImpl::StartTask(std::function<void()> func)
  7243. {
  7244. return new std::thread(func);
  7245. }
  7246. void VHACDAsyncImpl::JoinTask(void* Task)
  7247. {
  7248. std::thread* t = static_cast<std::thread*>(Task);
  7249. t->join();
  7250. delete t;
  7251. }
  7252. bool VHACDAsyncImpl::Compute(Parameters params)
  7253. {
  7254. Cancel(); // if we previously had a solution running; cancel it.
  7255. m_taskRunner = params.m_taskRunner ? params.m_taskRunner : this;
  7256. params.m_taskRunner = m_taskRunner;
  7257. m_running = true;
  7258. m_task = m_taskRunner->StartTask([this, params]() {
  7259. ComputeNow(m_vertices,
  7260. m_indices,
  7261. params);
  7262. // If we have a user provided callback and the user did *not* call 'cancel' we notify him that the
  7263. // task is completed. However..if the user selected 'cancel' we do not send a completed notification event.
  7264. if (params.m_callback && !m_cancel)
  7265. {
  7266. params.m_callback->NotifyVHACDComplete();
  7267. }
  7268. m_running = false;
  7269. });
  7270. return true;
  7271. }
  7272. bool VHACDAsyncImpl::ComputeNow(const std::vector<VHACD::Vertex>& points,
  7273. const std::vector<VHACD::Triangle>& triangles,
  7274. const Parameters& _desc)
  7275. {
  7276. uint32_t ret = 0;
  7277. Parameters desc;
  7278. m_callback = _desc.m_callback;
  7279. m_logger = _desc.m_logger;
  7280. desc = _desc;
  7281. // Set our intercepting callback interfaces if non-null
  7282. desc.m_callback = _desc.m_callback ? this : nullptr;
  7283. desc.m_logger = _desc.m_logger ? this : nullptr;
  7284. // If not task runner provided, then use the default one
  7285. if (desc.m_taskRunner == nullptr)
  7286. {
  7287. desc.m_taskRunner = this;
  7288. }
  7289. bool ok = m_VHACD.Compute(points,
  7290. triangles,
  7291. desc);
  7292. if (ok)
  7293. {
  7294. ret = m_VHACD.GetNConvexHulls();
  7295. }
  7296. return ret ? true : false;
  7297. }
  7298. void VHACDAsyncImpl::ProcessPendingMessages() const
  7299. {
  7300. if (m_cancel)
  7301. {
  7302. return;
  7303. }
  7304. if ( m_haveMessages )
  7305. {
  7306. m_messageMutex.lock();
  7307. for (auto& i : m_messages)
  7308. {
  7309. if ( i.m_overallProgress == -1 )
  7310. {
  7311. if ( m_logger )
  7312. {
  7313. m_logger->Log(i.m_operation.c_str());
  7314. }
  7315. }
  7316. else if ( m_callback )
  7317. {
  7318. m_callback->Update(i.m_overallProgress,
  7319. i.m_stageProgress,
  7320. i.m_stage.c_str(),
  7321. i.m_operation.c_str());
  7322. }
  7323. }
  7324. m_messages.clear();
  7325. m_haveMessages = false;
  7326. m_messageMutex.unlock();
  7327. }
  7328. }
  7329. IVHACD* CreateVHACD_ASYNC()
  7330. {
  7331. VHACDAsyncImpl* m = new VHACDAsyncImpl;
  7332. return static_cast<IVHACD*>(m);
  7333. }
  7334. #endif
  7335. } // namespace VHACD
  7336. #ifdef _MSC_VER
  7337. #pragma warning(pop)
  7338. #endif // _MSC_VER
  7339. #ifdef __GNUC__
  7340. #pragma GCC diagnostic pop
  7341. #endif // __GNUC__
  7342. #endif // ENABLE_VHACD_IMPLEMENTATION
  7343. #endif // VHACD_H