GXS.VectorFileObjects.pas 218 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.VectorFileObjects;
  5. (*
  6. Vector File related objects for GLScene
  7. The history is logged in a former GLS version of the unit.
  8. *)
  9. interface
  10. {$I GLScene.Defines.inc}
  11. uses
  12. Winapi.OpenGL,
  13. Winapi.OpenGLext,
  14. System.Classes,
  15. System.Math,
  16. System.SysUtils,
  17. System.Types,
  18. GXS.XOpenGL,
  19. GXS.BaseClasses,
  20. GXS.VectorLists,
  21. GXS.PersistentClasses,
  22. GLScene.VectorTypes,
  23. GLScene.VectorGeometry,
  24. GLScene.Strings,
  25. GLScene.Utils,
  26. GXS.GeometryBB,
  27. GXS.ApplicationFileIO,
  28. GXS.Scene,
  29. GXS.Texture,
  30. GXS.Material,
  31. GXS.Mesh,
  32. GXS.Octree,
  33. GXS.Silhouette,
  34. GXS.Context,
  35. GXS.Color,
  36. GXS.RenderContextInfo,
  37. GXS.Coordinates,
  38. GXS.TextureFormat,
  39. GXS.State,
  40. GXS.ImageUtils;
  41. type
  42. TgxMeshObjectList = class;
  43. TgxFaceGroups = class;
  44. TgxMeshAutoCentering = (macCenterX, macCenterY, macCenterZ, macUseBarycenter, macRestorePosition);
  45. TgxMeshAutoCenterings = set of TgxMeshAutoCentering;
  46. TgxMeshObjectMode = (momTriangles, momTriangleStrip, momFaceGroups);
  47. (* A base class for mesh objects.
  48. The class introduces a set of vertices and normals for the object but
  49. does no rendering of its own. *)
  50. TgxBaseMeshObject = class(TgxPersistentObject)
  51. private
  52. FName: string;
  53. FVertices: TgxAffineVectorList;
  54. FNormals: TgxAffineVectorList;
  55. FVisible: Boolean;
  56. protected
  57. procedure SetVertices(const val: TgxAffineVectorList);
  58. procedure SetNormals(const val: TgxAffineVectorList);
  59. procedure ContributeToBarycenter(var currentSum: TAffineVector; var nb: Integer); virtual;
  60. public
  61. constructor Create; override;
  62. destructor Destroy; override;
  63. procedure Assign(Source: TPersistent); override;
  64. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  65. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  66. // Clears all mesh object data, submeshes, facegroups, etc.
  67. procedure Clear; virtual;
  68. // Translates all the vertices by the given delta.
  69. procedure Translate(const delta: TAffineVector); virtual;
  70. (* Builds (smoothed) normals for the vertex list.
  71. If normalIndices is nil, the method assumes a bijection between
  72. vertices and normals sets, and when performed, Normals and Vertices
  73. list will have the same number of items (whatever previously was in
  74. the Normals list is ignored/removed).
  75. If normalIndices is defined, normals will be added to the list and
  76. their indices will be added to normalIndices. Already defined
  77. normals and indices are preserved.
  78. The only valid modes are currently momTriangles and momTriangleStrip
  79. (ie. momFaceGroups not supported). *)
  80. procedure BuildNormals(vertexIndices: TgxIntegerList; mode: TgxMeshObjectMode; normalIndices: TgxIntegerList = nil);
  81. (* Extracts all mesh triangles as a triangles list.
  82. The resulting list size is a multiple of 3, each group of 3 vertices
  83. making up and independant triangle.
  84. The returned list can be used independantly from the mesh object
  85. (all data is duplicated) and should be freed by caller.
  86. If texCoords is specified, per vertex texture coordinates will be
  87. placed there, when available. *)
  88. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList; virtual;
  89. property Name: string read FName write FName;
  90. property Visible: Boolean read FVisible write FVisible;
  91. property Vertices: TgxAffineVectorList read FVertices write SetVertices;
  92. property normals: TgxAffineVectorList read FNormals write SetNormals;
  93. end;
  94. TgxSkeletonFrameList = class;
  95. TgxSkeletonFrameTransform = (sftRotation, sftQuaternion);
  96. (* Stores position and rotation for skeleton joints.
  97. If you directly alter some values, make sure to call FlushLocalMatrixList
  98. so that the local matrices will be recalculated (the call to Flush does
  99. not recalculate the matrices, but marks the current ones as dirty). *)
  100. TgxSkeletonFrame = class(TgxPersistentObject)
  101. private
  102. FOwner: TgxSkeletonFrameList;
  103. FName: string;
  104. FPosition: TgxAffineVectorList;
  105. FRotation: TgxAffineVectorList;
  106. FQuaternion: TQuaternionList;
  107. FLocalMatrixList: PMatrixArray;
  108. FTransformMode: TgxSkeletonFrameTransform;
  109. protected
  110. procedure SetPosition(const val: TgxAffineVectorList);
  111. procedure SetRotation(const val: TgxAffineVectorList);
  112. procedure SetQuaternion(const val: TQuaternionList);
  113. public
  114. constructor CreateOwned(aOwner: TgxSkeletonFrameList);
  115. constructor Create; override;
  116. destructor Destroy; override;
  117. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  118. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  119. property Owner: TgxSkeletonFrameList read FOwner;
  120. property Name: string read FName write FName;
  121. // Position values for the joints.
  122. property Position: TgxAffineVectorList read FPosition write SetPosition;
  123. // Rotation values for the joints.
  124. property Rotation: TgxAffineVectorList read FRotation write SetRotation;
  125. (* Quaternions are an alternative to Euler rotations to build the
  126. global matrices for the skeleton bones. *)
  127. property Quaternion: TQuaternionList read FQuaternion write SetQuaternion;
  128. (* TransformMode indicates whether to use Rotation or Quaternion to build
  129. the local transform matrices. *)
  130. property TransformMode: TgxSkeletonFrameTransform read FTransformMode write FTransformMode;
  131. (* Calculate or retrieves an array of local bone matrices.
  132. This array is calculated on the first call after creation, and the
  133. first call following a FlushLocalMatrixList. Subsequent calls return
  134. the same arrays. *)
  135. function LocalMatrixList: PMatrixArray;
  136. (* Flushes (frees) then LocalMatrixList data.
  137. Call this function to allow a recalculation of local matrices. *)
  138. procedure FlushLocalMatrixList;
  139. // As the name states; Convert Quaternions to Rotations or vice-versa.
  140. procedure ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True);
  141. procedure ConvertRotationsToQuaternions(KeepRotations: Boolean = True);
  142. end;
  143. // A list of TgxSkeletonFrame objects.
  144. TgxSkeletonFrameList = class(TgxPersistentObjectList)
  145. private
  146. FOwner: TPersistent;
  147. protected
  148. function GetSkeletonFrame(Index: Integer): TgxSkeletonFrame;
  149. public
  150. constructor CreateOwned(aOwner: TPersistent);
  151. destructor Destroy; override;
  152. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  153. // As the name states; Convert Quaternions to Rotations or vice-versa.
  154. procedure ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True; SetTransformMode: Boolean = True);
  155. procedure ConvertRotationsToQuaternions(KeepRotations: Boolean = True; SetTransformMode: Boolean = True);
  156. property Owner: TPersistent read FOwner;
  157. procedure Clear; override;
  158. property Items[Index: Integer]: TgxSkeletonFrame read GetSkeletonFrame; default;
  159. end;
  160. TgxSkeleton = class;
  161. TgxSkeletonBone = class;
  162. // A list of skeleton bones.
  163. TgxSkeletonBoneList = class(TgxPersistentObjectList)
  164. private
  165. FSkeleton: TgxSkeleton; // not persistent
  166. protected
  167. FGlobalMatrix: TMatrix4f;
  168. function GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  169. procedure AfterObjectCreatedByReader(Sender: TObject); override;
  170. public
  171. constructor CreateOwned(aOwner: TgxSkeleton);
  172. constructor Create; override;
  173. destructor Destroy; override;
  174. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  175. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  176. property Skeleton: TgxSkeleton read FSkeleton;
  177. property Items[Index: Integer]: TgxSkeletonBone read GetSkeletonBone; default;
  178. // Returns a bone by its BoneID, nil if not found.
  179. function BoneByID(anID: Integer): TgxSkeletonBone; virtual;
  180. // Returns a bone by its Name, nil if not found.
  181. function BoneByName(const aName: string): TgxSkeletonBone; virtual;
  182. // Number of bones (including all children and self).
  183. function BoneCount: Integer;
  184. // Render skeleton wireframe
  185. procedure BuildList(var mrci: TgxRenderContextInfo); virtual; abstract;
  186. procedure PrepareGlobalMatrices; virtual;
  187. end;
  188. // This list store skeleton root bones exclusively.
  189. TgxSkeletonRootBoneList = class(TgxSkeletonBoneList)
  190. public
  191. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  192. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  193. // Render skeleton wireframe
  194. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  195. property GlobalMatrix: TMatrix4f read FGlobalMatrix write FGlobalMatrix;
  196. end;
  197. (* A skeleton bone or node and its children.
  198. This class is the base item of the bones hierarchy in a skeletal model.
  199. The joint values are stored in a TgxSkeletonFrame, but the calculated bone
  200. matrices are stored here. *)
  201. TgxSkeletonBone = class(TgxSkeletonBoneList)
  202. private
  203. FOwner: TgxSkeletonBoneList; // indirectly persistent
  204. FBoneID: Integer;
  205. FName: string;
  206. FColor: Cardinal;
  207. protected
  208. function GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  209. procedure SetColor(const val: Cardinal);
  210. public
  211. constructor CreateOwned(aOwner: TgxSkeletonBoneList);
  212. constructor Create; override;
  213. destructor Destroy; override;
  214. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  215. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  216. // Render skeleton wireframe
  217. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  218. property Owner: TgxSkeletonBoneList read FOwner;
  219. property Name: string read FName write FName;
  220. property BoneID: Integer read FBoneID write FBoneID;
  221. property Color: Cardinal read FColor write SetColor;
  222. property Items[Index: Integer]: TgxSkeletonBone read GetSkeletonBone; default;
  223. // Returns a bone by its BoneID, nil if not found.
  224. function BoneByID(anID: Integer): TgxSkeletonBone; override;
  225. function BoneByName(const aName: string): TgxSkeletonBone; override;
  226. // Set the bone's matrix. Becareful using this.
  227. procedure SetGlobalMatrix(Matrix: TMatrix4f); // Ragdoll
  228. // Set the bone's GlobalMatrix. Used for Ragdoll.
  229. procedure SetGlobalMatrixForRagDoll(RagDollMatrix: TMatrix4f); // Ragdoll
  230. (* Calculates the global matrix for the bone and its sub-bone.
  231. Call this function directly only the RootBone. *)
  232. procedure PrepareGlobalMatrices; override;
  233. (* Global Matrix for the bone in the current frame.
  234. Global matrices must be prepared by invoking PrepareGlobalMatrices
  235. on the root bone. *)
  236. property GlobalMatrix: TMatrix4f read FGlobalMatrix;
  237. // Free all sub bones and reset BoneID and Name.
  238. procedure Clean; override;
  239. end;
  240. TgxSkeletonColliderList = class;
  241. (* A general class storing the base level info required for skeleton
  242. based collision methods. This class is meant to be inherited from
  243. to create skeleton driven Verlet Constraints, ODE Geoms, etc.
  244. Overriden classes should be named as TSCxxxxx. *)
  245. TgxSkeletonCollider = class(TgxPersistentObject)
  246. private
  247. FOwner: TgxSkeletonColliderList;
  248. FBone: TgxSkeletonBone;
  249. FBoneID: Integer;
  250. FLocalMatrix, FGlobalMatrix: TMatrix4f;
  251. FAutoUpdate: Boolean;
  252. protected
  253. procedure SetBone(const val: TgxSkeletonBone);
  254. procedure SetLocalMatrix(const val: TMatrix4f);
  255. public
  256. constructor Create; override;
  257. constructor CreateOwned(aOwner: TgxSkeletonColliderList);
  258. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  259. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  260. (* This method is used to align the colliders and their
  261. derived objects to their associated skeleton bone.
  262. Override to set up descendant class alignment properties. *)
  263. procedure AlignCollider; virtual;
  264. property Owner: TgxSkeletonColliderList read FOwner;
  265. // The bone that this collider associates with.
  266. property Bone: TgxSkeletonBone read FBone write SetBone;
  267. (* Offset and orientation of the collider in the associated
  268. bone's space. *)
  269. property LocalMatrix: TMatrix4f read FLocalMatrix write SetLocalMatrix;
  270. (* Global offset and orientation of the collider. This
  271. gets set in the AlignCollider method. *)
  272. property GlobalMatrix: TMatrix4f read FGlobalMatrix;
  273. property AutoUpdate: Boolean read FAutoUpdate write FAutoUpdate;
  274. end;
  275. // List class for storing TgxSkeletonCollider objects.
  276. TgxSkeletonColliderList = class(TgxPersistentObjectList)
  277. private
  278. FOwner: TPersistent;
  279. protected
  280. function GetSkeletonCollider(Index: Integer): TgxSkeletonCollider;
  281. public
  282. constructor CreateOwned(aOwner: TPersistent);
  283. destructor Destroy; override;
  284. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  285. procedure Clear; override;
  286. // Calls AlignCollider for each collider in the list.
  287. procedure AlignColliders;
  288. property Owner: TPersistent read FOwner;
  289. property Items[Index: Integer]: TgxSkeletonCollider read GetSkeletonCollider; default;
  290. end;
  291. TgxBaseMesh = class;
  292. // Small structure to store a weighted lerp for use in blending.
  293. TgxBlendedLerpInfo = record
  294. frameIndex1, frameIndex2: Integer;
  295. lerpFactor: Single;
  296. weight: Single;
  297. externalPositions: TgxAffineVectorList;
  298. externalRotations: TgxAffineVectorList;
  299. externalQuaternions: TQuaternionList;
  300. end;
  301. (* Main skeleton object.
  302. This class stores the bones hierarchy and animation frames.
  303. It is also responsible for maintaining the "CurrentFrame" and allowing
  304. various frame blending operations. *)
  305. TgxSkeleton = class(TgxPersistentObject)
  306. private
  307. FOwner: TgxBaseMesh;
  308. FRootBones: TgxSkeletonRootBoneList;
  309. FFrames: TgxSkeletonFrameList;
  310. FCurrentFrame: TgxSkeletonFrame; // not persistent
  311. FBonesByIDCache: TList;
  312. FColliders: TgxSkeletonColliderList;
  313. FRagDollEnabled: Boolean; // ragdoll
  314. FMorphInvisibleParts: Boolean;
  315. protected
  316. procedure SetRootBones(const val: TgxSkeletonRootBoneList);
  317. procedure SetFrames(const val: TgxSkeletonFrameList);
  318. function GetCurrentFrame: TgxSkeletonFrame;
  319. procedure SetCurrentFrame(val: TgxSkeletonFrame);
  320. procedure SetColliders(const val: TgxSkeletonColliderList);
  321. public
  322. constructor CreateOwned(aOwner: TgxBaseMesh);
  323. constructor Create; override;
  324. destructor Destroy; override;
  325. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  326. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  327. property Owner: TgxBaseMesh read FOwner;
  328. property RootBones: TgxSkeletonRootBoneList read FRootBones write SetRootBones;
  329. property Frames: TgxSkeletonFrameList read FFrames write SetFrames;
  330. property CurrentFrame: TgxSkeletonFrame read GetCurrentFrame write SetCurrentFrame;
  331. property Colliders: TgxSkeletonColliderList read FColliders write SetColliders;
  332. procedure FlushBoneByIDCache;
  333. function BoneByID(anID: Integer): TgxSkeletonBone;
  334. function BoneByName(const aName: string): TgxSkeletonBone;
  335. function BoneCount: Integer;
  336. procedure MorphTo(frameIndex: Integer); overload;
  337. procedure MorphTo(frame: TgxSkeletonFrame); overload;
  338. procedure Lerp(frameIndex1, frameIndex2: Integer; lerpFactor: Single);
  339. procedure BlendedLerps(const lerpInfos: array of TgxBlendedLerpInfo);
  340. (* Linearly removes the translation component between skeletal frames.
  341. This function will compute the translation of the first bone (index 0)
  342. and linearly subtract this translation in all frames between startFrame
  343. and endFrame. Its purpose is essentially to remove the 'slide' that
  344. exists in some animation formats (f.i. SMD). *)
  345. procedure MakeSkeletalTranslationStatic(startFrame, endFrame: Integer);
  346. (* Removes the absolute rotation component of the skeletal frames.
  347. Some formats will store frames with absolute rotation information,
  348. if this correct if the animation is the "main" animation.
  349. This function removes that absolute information, making the animation
  350. frames suitable for blending purposes. *)
  351. procedure MakeSkeletalRotationDelta(startFrame, endFrame: Integer);
  352. // Applies current frame to morph all mesh objects.
  353. procedure MorphMesh(normalize: Boolean);
  354. // Copy bone rotations from reference skeleton.
  355. procedure Synchronize(reference: TgxSkeleton);
  356. // Release bones and frames info.
  357. procedure Clear;
  358. // Backup and prepare the BoneMatrixInvertedMeshes to use with ragdolls
  359. procedure StartRagdoll; // ragdoll
  360. // Restore the BoneMatrixInvertedMeshes to stop the ragdoll
  361. procedure StopRagdoll; // ragdoll
  362. (* Turning this option off (by default) alows to increase FPS,
  363. but may break backwards-compatibility, because some may choose to
  364. attach other objects to invisible parts. *)
  365. property MorphInvisibleParts: Boolean read FMorphInvisibleParts write FMorphInvisibleParts;
  366. end;
  367. (* Rendering options per TgxMeshObject.
  368. moroGroupByMaterial : if set, the facegroups will be rendered by material
  369. in batchs, this will optimize rendering by reducing material switches, but
  370. also implies that facegroups will not be rendered in the order they are in
  371. the list. *)
  372. TgxMeshObjectRenderingOption = (moroGroupByMaterial);
  373. TgxMeshObjectRenderingOptions = set of TgxMeshObjectRenderingOption;
  374. TVBOBuffer = (vbVertices, vbNormals, vbColors, vbTexCoords, vbLightMapTexCoords, vbTexCoordsEx);
  375. TVBOBuffers = set of TVBOBuffer;
  376. (* Base mesh class.
  377. Introduces base methods and properties for mesh objects.
  378. Subclasses are named "TMOxxx". *)
  379. TgxMeshObject = class(TgxBaseMeshObject)
  380. private
  381. FOwner: TgxMeshObjectList;
  382. FExtentCacheRevision: Cardinal;
  383. FTexCoords: TgxAffineVectorList; // provision for 3D textures
  384. FLightMapTexCoords: TgxAffineVectorList; // reserved for 2D surface needs
  385. FColors: TgxVectorList;
  386. FFaceGroups: TgxFaceGroups;
  387. FMode: TgxMeshObjectMode;
  388. FRenderingOptions: TgxMeshObjectRenderingOptions;
  389. FArraysDeclared: Boolean; // not persistent
  390. FLightMapArrayEnabled: Boolean; // not persistent
  391. FLastLightMapIndex: Integer; // not persistent
  392. FTexCoordsEx: TList;
  393. FBinormalsTexCoordIndex: Integer;
  394. FTangentsTexCoordIndex: Integer;
  395. FLastXOpenGLTexMapping: Cardinal;
  396. FUseVBO: Boolean;
  397. FVerticesVBO: TgxVBOHandle;
  398. FNormalsVBO: TgxVBOHandle;
  399. FColorsVBO: TgxVBOHandle;
  400. FTexCoordsVBO: array of TgxVBOHandle;
  401. FLightmapTexCoordsVBO: TgxVBOHandle;
  402. FValidBuffers: TVBOBuffers;
  403. FExtentCache: TAABB;
  404. procedure SetUseVBO(const Value: Boolean);
  405. procedure SetValidBuffers(Value: TVBOBuffers);
  406. protected
  407. procedure SetTexCoords(const val: TgxAffineVectorList);
  408. procedure SetLightmapTexCoords(const val: TgxAffineVectorList);
  409. procedure SetColors(const val: TgxVectorList);
  410. procedure BufferArrays;
  411. procedure DeclareArraysToOpenGL(var mrci: TgxRenderContextInfo; evenIfAlreadyDeclared: Boolean = False);
  412. procedure DisableOpenGLArrays(var mrci: TgxRenderContextInfo);
  413. procedure EnableLightMapArray(var mrci: TgxRenderContextInfo);
  414. procedure DisableLightMapArray(var mrci: TgxRenderContextInfo);
  415. procedure SetTexCoordsEx(Index: Integer; const val: TgxVectorList);
  416. function GetTexCoordsEx(Index: Integer): TgxVectorList;
  417. procedure SetBinormals(const val: TgxVectorList);
  418. function GetBinormals: TgxVectorList;
  419. procedure SetBinormalsTexCoordIndex(const val: Integer);
  420. procedure SetTangents(const val: TgxVectorList);
  421. function GetTangents: TgxVectorList;
  422. procedure SetTangentsTexCoordIndex(const val: Integer);
  423. property ValidBuffers: TVBOBuffers read FValidBuffers write SetValidBuffers;
  424. public
  425. // Creates, assigns Owner and adds to list.
  426. constructor CreateOwned(aOwner: TgxMeshObjectList);
  427. constructor Create; override;
  428. destructor Destroy; override;
  429. procedure Assign(Source: TPersistent); override;
  430. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  431. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  432. procedure Clear; override;
  433. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList;
  434. override;
  435. // Returns number of triangles in the mesh object.
  436. function TriangleCount: Integer; virtual;
  437. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  438. procedure DropMaterialLibraryCache;
  439. (* Prepare the texture and materials before rendering.
  440. Invoked once, before building the list and NOT while building the list. *)
  441. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  442. // Similar to regular scene object's BuildList method
  443. procedure BuildList(var mrci: TgxRenderContextInfo); virtual;
  444. // The extents of the object (min and max coordinates)
  445. procedure GetExtents(out min, max: TAffineVector); overload; virtual;
  446. procedure GetExtents(out aabb: TAABB); overload; virtual;
  447. // Barycenter from vertices data
  448. function GetBarycenter: TVector4f;
  449. // Precalculate whatever is needed for rendering, called once
  450. procedure Prepare; virtual;
  451. function PointInObject(const aPoint: TAffineVector): Boolean; virtual;
  452. // Returns the triangle data for a given triangle
  453. procedure GetTriangleData(tri: Integer; list: TgxAffineVectorList; var v0, v1, v2: TAffineVector); overload;
  454. procedure GetTriangleData(tri: Integer; list: TgxVectorList; var v0, v1, v2: TVector4f); overload;
  455. // Sets the triangle data of a given triangle
  456. procedure SetTriangleData(tri: Integer; list: TgxAffineVectorList; const v0, v1, v2: TAffineVector); overload;
  457. procedure SetTriangleData(tri: Integer; list: TgxVectorList; const v0, v1, v2: TVector4f); overload;
  458. (* Build the tangent space from the mesh object's vertex, normal
  459. and texcoord data, filling the binormals and tangents where
  460. specified. *)
  461. procedure BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  462. property Owner: TgxMeshObjectList read FOwner;
  463. property mode: TgxMeshObjectMode read FMode write FMode;
  464. property texCoords: TgxAffineVectorList read FTexCoords write SetTexCoords;
  465. property LightMapTexCoords: TgxAffineVectorList read FLightMapTexCoords write SetLightmapTexCoords;
  466. property Colors: TgxVectorList read FColors write SetColors;
  467. property FaceGroups: TgxFaceGroups read FFaceGroups;
  468. property RenderingOptions: TgxMeshObjectRenderingOptions read FRenderingOptions write FRenderingOptions;
  469. // If set, rendering will use VBO's instead of vertex arrays.
  470. property UseVBO: Boolean read FUseVBO write SetUseVBO;
  471. (* The TexCoords Extension is a list of vector lists that are used
  472. to extend the vertex data applied during rendering.
  473. The lists are applied to the GL_TEXTURE0_ARB + index texture
  474. environment. This means that if TexCoordsEx 0 or 1 have data it
  475. will override the TexCoords or LightMapTexCoords repectively.
  476. Lists are created on demand, meaning that if you request
  477. TexCoordsEx[4] it will create the list up to and including 4.
  478. The extensions are only applied to the texture environment if
  479. they contain data. *)
  480. property TexCoordsEx[index: Integer]: TgxVectorList read GetTexCoordsEx write SetTexCoordsEx;
  481. (* A TexCoordsEx list wrapper for binormals usage,
  482. returns TexCoordsEx[BinormalsTexCoordIndex]. *)
  483. property Binormals: TgxVectorList read GetBinormals write SetBinormals;
  484. (* A TexCoordsEx list wrapper for tangents usage,
  485. returns TexCoordsEx[BinormalsTexCoordIndex]. *)
  486. property Tangents: TgxVectorList read GetTangents write SetTangents;
  487. // Specify the texcoord extension index for binormals (default = 2)
  488. property BinormalsTexCoordIndex: Integer read FBinormalsTexCoordIndex write SetBinormalsTexCoordIndex;
  489. // Specify the texcoord extension index for tangents (default = 3)
  490. property TangentsTexCoordIndex: Integer read FTangentsTexCoordIndex write SetTangentsTexCoordIndex;
  491. end;
  492. // A list of TgxMeshObject objects.
  493. TgxMeshObjectList = class(TgxPersistentObjectList)
  494. private
  495. FOwner: TgxBaseMesh;
  496. // Resturns True if all its MeshObjects use VBOs.
  497. function GetUseVBO: Boolean;
  498. procedure SetUseVBO(const Value: Boolean);
  499. protected
  500. function GetMeshObject(Index: Integer): TgxMeshObject;
  501. public
  502. constructor CreateOwned(aOwner: TgxBaseMesh);
  503. destructor Destroy; override;
  504. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  505. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  506. procedure DropMaterialLibraryCache;
  507. (* Prepare the texture and materials before rendering.
  508. Invoked once, before building the list and NOT while building the list. *)
  509. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  510. // Similar to regular scene object's BuildList method
  511. procedure BuildList(var mrci: TgxRenderContextInfo); virtual;
  512. procedure MorphTo(morphTargetIndex: Integer);
  513. procedure Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  514. function MorphTargetCount: Integer;
  515. procedure GetExtents(out min, max: TAffineVector);
  516. procedure Translate(const delta: TAffineVector);
  517. function ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil): TgxAffineVectorList;
  518. // Returns number of triangles in the meshes of the list.
  519. function TriangleCount: Integer;
  520. (* Build the tangent space from the mesh object's vertex, normal
  521. and texcoord data, filling the binormals and tangents where
  522. specified. *)
  523. procedure BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  524. (* If set, rendering will use VBO's instead of vertex arrays.
  525. Resturns True if all its MeshObjects use VBOs. *)
  526. property UseVBO: Boolean read GetUseVBO write SetUseVBO;
  527. // Precalculate whatever is needed for rendering, called once
  528. procedure Prepare; virtual;
  529. function FindMeshByName(MeshName: string): TgxMeshObject;
  530. property Owner: TgxBaseMesh read FOwner;
  531. procedure Clear; override;
  532. property Items[Index: Integer]: TgxMeshObject read GetMeshObject; default;
  533. end;
  534. TgxMeshObjectListClass = class of TgxMeshObjectList;
  535. TgxMeshMorphTargetList = class;
  536. // A morph target, stores alternate lists of vertices and normals.
  537. TgxMeshMorphTarget = class(TgxBaseMeshObject)
  538. private
  539. FOwner: TgxMeshMorphTargetList;
  540. public
  541. constructor CreateOwned(aOwner: TgxMeshMorphTargetList);
  542. destructor Destroy; override;
  543. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  544. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  545. property Owner: TgxMeshMorphTargetList read FOwner;
  546. end;
  547. // A list of TgxMeshMorphTarget objects.
  548. TgxMeshMorphTargetList = class(TgxPersistentObjectList)
  549. private
  550. FOwner: TPersistent;
  551. protected
  552. function GetMeshMorphTarget(Index: Integer): TgxMeshMorphTarget;
  553. public
  554. constructor CreateOwned(aOwner: TPersistent);
  555. destructor Destroy; override;
  556. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  557. procedure Translate(const delta: TAffineVector);
  558. property Owner: TPersistent read FOwner;
  559. procedure Clear; override;
  560. property Items[Index: Integer]: TgxMeshMorphTarget read GetMeshMorphTarget; default;
  561. end;
  562. (* Mesh object with support for morph targets.
  563. The morph targets allow to change vertices and normals according to pre-
  564. existing "morph targets". *)
  565. TgxMorphableMeshObject = class(TgxMeshObject)
  566. private
  567. FMorphTargets: TgxMeshMorphTargetList;
  568. public
  569. constructor Create; override;
  570. destructor Destroy; override;
  571. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  572. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  573. procedure Clear; override;
  574. procedure Translate(const delta: TAffineVector); override;
  575. procedure MorphTo(morphTargetIndex: Integer); virtual;
  576. procedure Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single); virtual;
  577. property MorphTargets: TgxMeshMorphTargetList read FMorphTargets;
  578. end;
  579. TgxVertexBoneWeight = packed record
  580. BoneID: Integer;
  581. weight: Single;
  582. end;
  583. TgxVertexBoneWeightArray = array [0 .. MaxInt div (2 * SizeOf(TgxVertexBoneWeight))] of TgxVertexBoneWeight;
  584. PgxVertexBoneWeightArray = ^TgxVertexBoneWeightArray;
  585. TgxVerticesBoneWeights = array [0 .. MaxInt div (2 * SizeOf(PgxVertexBoneWeightArray))] of PgxVertexBoneWeightArray;
  586. PgxVerticesBoneWeights = ^TgxVerticesBoneWeights;
  587. TgxVertexBoneWeightDynArray = array of TgxVertexBoneWeight;
  588. (* A mesh object with vertice bone attachments.
  589. The class adds per vertex bone weights to the standard morphable mesh.
  590. The TgxVertexBoneWeight structures are accessed via VerticesBonesWeights,
  591. they must be initialized by adjusting the BonesPerVertex and
  592. VerticeBoneWeightCount properties, you can also add vertex by vertex
  593. by using the AddWeightedBone method.
  594. When BonesPerVertex is 1, the weight is ignored (set to 1.0). *)
  595. TgxSkeletonMeshObject = class(TgxMorphableMeshObject)
  596. private
  597. FVerticesBonesWeights: PgxVerticesBoneWeights;
  598. FVerticeBoneWeightCount, FVerticeBoneWeightCapacity: Integer;
  599. FBonesPerVertex: Integer;
  600. FLastVerticeBoneWeightCount, FLastBonesPerVertex: Integer; // not persistent
  601. FBoneMatrixInvertedMeshes: TList; // not persistent
  602. FBackupInvertedMeshes: TList; // ragdoll
  603. procedure BackupBoneMatrixInvertedMeshes; // ragdoll
  604. procedure RestoreBoneMatrixInvertedMeshes; // ragdoll
  605. protected
  606. procedure SetVerticeBoneWeightCount(const val: Integer);
  607. procedure SetVerticeBoneWeightCapacity(const val: Integer);
  608. procedure SetBonesPerVertex(const val: Integer);
  609. procedure ResizeVerticesBonesWeights;
  610. public
  611. constructor Create; override;
  612. destructor Destroy; override;
  613. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  614. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  615. procedure Clear; override;
  616. property VerticesBonesWeights: PgxVerticesBoneWeights read FVerticesBonesWeights;
  617. property VerticeBoneWeightCount: Integer read FVerticeBoneWeightCount write SetVerticeBoneWeightCount;
  618. property VerticeBoneWeightCapacity: Integer read FVerticeBoneWeightCapacity write SetVerticeBoneWeightCapacity;
  619. property BonesPerVertex: Integer read FBonesPerVertex write SetBonesPerVertex;
  620. function FindOrAdd(BoneID: Integer; const vertex, normal: TAffineVector): Integer; overload;
  621. function FindOrAdd(const boneIDs: TgxVertexBoneWeightDynArray; const vertex, normal: TAffineVector): Integer; overload;
  622. procedure AddWeightedBone(aBoneID: Integer; aWeight: Single);
  623. procedure AddWeightedBones(const boneIDs: TgxVertexBoneWeightDynArray);
  624. procedure PrepareBoneMatrixInvertedMeshes;
  625. procedure ApplyCurrentSkeletonFrame(normalize: Boolean);
  626. end;
  627. (* Describes a face group of a TgxMeshObject.
  628. Face groups should be understood as "a way to use mesh data to render
  629. a part or the whole mesh object".
  630. Subclasses implement the actual behaviours, and should have at least
  631. one "Add" method, taking in parameters all that is required to describe
  632. a single base facegroup element. *)
  633. TgxFaceGroup = class(TgxPersistentObject)
  634. private
  635. FOwner: TgxFaceGroups;
  636. FMaterialName: string;
  637. FMaterialCache: TgxLibMaterial;
  638. FLightMapIndex: Integer;
  639. FRenderGroupID: Integer;
  640. // NOT Persistent, internal use only (rendering options)
  641. protected
  642. procedure AttachLightmap(lightMap: TgxTexture; var mrci: TgxRenderContextInfo);
  643. procedure AttachOrDetachLightmap(var mrci: TgxRenderContextInfo);
  644. public
  645. constructor CreateOwned(aOwner: TgxFaceGroups); virtual;
  646. destructor Destroy; override;
  647. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  648. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  649. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  650. procedure DropMaterialLibraryCache;
  651. procedure BuildList(var mrci: TgxRenderContextInfo); virtual; abstract;
  652. (* Add to the list the triangles corresponding to the facegroup.
  653. This function is used by TgxMeshObjects ExtractTriangles to retrieve
  654. all the triangles in a mesh. *)
  655. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  656. aNormals: TgxAffineVectorList = nil); virtual;
  657. // Returns number of triangles in the facegroup.
  658. function TriangleCount: Integer; virtual; abstract;
  659. (* Reverses the rendering order of faces.
  660. Default implementation does nothing *)
  661. procedure Reverse; virtual;
  662. // Precalculate whatever is needed for rendering, called once
  663. procedure Prepare; virtual;
  664. property Owner: TgxFaceGroups read FOwner write FOwner;
  665. property MaterialName: string read FMaterialName write FMaterialName;
  666. property MaterialCache: TgxLibMaterial read FMaterialCache;
  667. // Index of lightmap in the lightmap library.
  668. property LightMapIndex: Integer read FLightMapIndex write FLightMapIndex;
  669. end;
  670. (* Known descriptions for face group mesh modes.
  671. - fgmmTriangles : issue all vertices with GL_TRIANGLES.
  672. - fgmmTriangleStrip : issue all vertices with GL_TRIANGLE_STRIP.
  673. - fgmmFlatTriangles : same as fgmmTriangles, but take advantage of having
  674. the same normal for all vertices of a triangle.
  675. - fgmmTriangleFan : issue all vertices with GL_TRIANGLE_FAN.
  676. - fgmmQuads : issue all vertices with GL_QUADS. *)
  677. TgxFaceGroupMeshMode = (fgmmTriangles, fgmmTriangleStrip, fgmmFlatTriangles, fgmmTriangleFan, fgmmQuads);
  678. (* A face group based on an indexlist.
  679. The index list refers to items in the mesh object (vertices, normals, etc.),
  680. that are all considered in sync, the render is obtained issueing the items
  681. in the order given by the vertices. *)
  682. TfgxVertexIndexList = class(TgxFaceGroup)
  683. private
  684. FVertexIndices: TgxIntegerList;
  685. FIndexVBO: TgxVBOElementArrayHandle;
  686. FMode: TgxFaceGroupMeshMode;
  687. procedure SetupVBO;
  688. procedure InvalidateVBO;
  689. protected
  690. procedure SetVertexIndices(const val: TgxIntegerList);
  691. procedure AddToList(Source, destination: TgxAffineVectorList; indices: TgxIntegerList);
  692. public
  693. constructor Create; override;
  694. destructor Destroy; override;
  695. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  696. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  697. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  698. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  699. aNormals: TgxAffineVectorList = nil); override;
  700. function TriangleCount: Integer; override;
  701. procedure Reverse; override;
  702. procedure Add(idx: Integer);
  703. procedure GetExtents(var min, max: TAffineVector);
  704. // If mode is strip or fan, convert the indices to triangle list indices.
  705. procedure ConvertToList;
  706. // Return the normal from the 1st three points in the facegroup
  707. function GetNormal: TAffineVector;
  708. property mode: TgxFaceGroupMeshMode read FMode write FMode;
  709. property vertexIndices: TgxIntegerList read FVertexIndices write SetVertexIndices;
  710. end;
  711. (* Adds normals and texcoords indices.
  712. Allows very compact description of a mesh. The Normals ad TexCoords
  713. indices are optionnal, if missing (empty), VertexIndices will be used. *)
  714. TFGVertexNormalTexIndexList = class(TfgxVertexIndexList)
  715. private
  716. FNormalIndices: TgxIntegerList;
  717. FTexCoordIndices: TgxIntegerList;
  718. protected
  719. procedure SetNormalIndices(const val: TgxIntegerList);
  720. procedure SetTexCoordIndices(const val: TgxIntegerList);
  721. public
  722. constructor Create; override;
  723. destructor Destroy; override;
  724. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  725. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  726. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  727. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  728. aNormals: TgxAffineVectorList = nil); override;
  729. procedure Add(vertexIdx, normalIdx, texCoordIdx: Integer);
  730. property normalIndices: TgxIntegerList read FNormalIndices write SetNormalIndices;
  731. property TexCoordIndices: TgxIntegerList read FTexCoordIndices write SetTexCoordIndices;
  732. end;
  733. (* Adds per index texture coordinates to its ancestor.
  734. Per index texture coordinates allows having different texture coordinates
  735. per triangle, depending on the face it is used in. *)
  736. TFGIndexTexCoordList = class(TfgxVertexIndexList)
  737. private
  738. FTexCoords: TgxAffineVectorList;
  739. protected
  740. procedure SetTexCoords(const val: TgxAffineVectorList);
  741. public
  742. constructor Create; override;
  743. destructor Destroy; override;
  744. procedure WriteToFiler(writer: TgxVirtualWriter); override;
  745. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  746. procedure BuildList(var mrci: TgxRenderContextInfo); override;
  747. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  748. aNormals: TgxAffineVectorList = nil); override;
  749. procedure Add(idx: Integer; const texCoord: TAffineVector); overload;
  750. procedure Add(idx: Integer; const s, t: Single); overload;
  751. property texCoords: TgxAffineVectorList read FTexCoords write SetTexCoords;
  752. end;
  753. // A list of TgxFaceGroup objects.
  754. TgxFaceGroups = class(TgxPersistentObjectList)
  755. private
  756. FOwner: TgxMeshObject;
  757. protected
  758. function GetFaceGroup(Index: Integer): TgxFaceGroup;
  759. public
  760. constructor CreateOwned(aOwner: TgxMeshObject);
  761. destructor Destroy; override;
  762. procedure ReadFromFiler(reader: TgxVirtualReader); override;
  763. procedure PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  764. procedure DropMaterialLibraryCache;
  765. property Owner: TgxMeshObject read FOwner;
  766. procedure Clear; override;
  767. property Items[Index: Integer]: TgxFaceGroup read GetFaceGroup; default;
  768. procedure AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil; aNormals: TgxAffineVectorList = nil);
  769. // Material Library of the owner TgxBaseMesh.
  770. function MaterialLibrary: TgxMaterialLibrary;
  771. (* Sort faces by material.
  772. Those without material first in list, followed by opaque materials,
  773. then transparent materials. *)
  774. procedure SortByMaterial;
  775. end;
  776. (* Determines how normals orientation is defined in a mesh.
  777. - mnoDefault : uses default orientation
  778. - mnoInvert : inverse of default orientation
  779. - mnoAutoSolid : autocalculate to make the mesh globally solid
  780. - mnoAutoHollow : autocalculate to make the mesh globally hollow *)
  781. TMeshNormalsOrientation = (mnoDefault, mnoInvert); // , mnoAutoSolid, mnoAutoHollow);
  782. (* Abstract base class for different vector file Formatx.
  783. The actual implementation for these files (3DS, DXF..) must be done
  784. seperately. The concept for TgxVectorFile is very similar to TGraphic
  785. (see Delphi Help). *)
  786. TgxVectorFile = class(TgxDataFile)
  787. private
  788. FNormalsOrientation: TMeshNormalsOrientation;
  789. protected
  790. procedure SetNormalsOrientation(const val: TMeshNormalsOrientation); virtual;
  791. public
  792. constructor Create(aOwner: TPersistent); override;
  793. function Owner: TgxBaseMesh;
  794. property NormalsOrientation: TMeshNormalsOrientation read FNormalsOrientation write SetNormalsOrientation;
  795. end;
  796. TgxVectorFileClass = class of TgxVectorFile;
  797. (* GLSM ( GXScene Mesh) vector file.
  798. This corresponds to the 'native' Scene format, and object persistence
  799. stream, which should be the 'fastest' of all formats to load, and supports
  800. all of GXScene features. *)
  801. TgxGLSMVectorFile = class(TgxVectorFile)
  802. public
  803. class function Capabilities: TDataFileCapabilities; override;
  804. procedure LoadFromStream(aStream: TStream); override;
  805. procedure SaveToStream(aStream: TStream); override;
  806. end;
  807. // Base class for mesh objects.
  808. TgxBaseMesh = class(TgxSceneObject)
  809. private
  810. FNormalsOrientation: TMeshNormalsOrientation;
  811. FMaterialLibrary: TgxMaterialLibrary;
  812. FLightmapLibrary: TgxMaterialLibrary;
  813. FAxisAlignedDimensionsCache: TVector4f;
  814. FBaryCenterOffsetChanged: Boolean;
  815. FBaryCenterOffset: TVector4f;
  816. FUseMeshMaterials: Boolean;
  817. FOverlaySkeleton: Boolean;
  818. FIgnoreMissingTextures: Boolean;
  819. FAutoCentering: TgxMeshAutoCenterings;
  820. FAutoScaling: TgxCoordinates;
  821. FMaterialLibraryCachesPrepared: Boolean;
  822. FConnectivity: TObject;
  823. FLastLoadedFilename: string;
  824. protected
  825. FMeshObjects: TgxMeshObjectList; // a list of mesh objects
  826. FSkeleton: TgxSkeleton; // skeleton data & frames
  827. procedure SetUseMeshMaterials(const val: Boolean);
  828. procedure SetMaterialLibrary(const val: TgxMaterialLibrary);
  829. procedure SetLightmapLibrary(const val: TgxMaterialLibrary);
  830. procedure SetNormalsOrientation(const val: TMeshNormalsOrientation);
  831. procedure SetOverlaySkeleton(const val: Boolean);
  832. procedure SetAutoScaling(const Value: TgxCoordinates);
  833. procedure DestroyHandle; override;
  834. (* Invoked after creating a TgxVectorFile and before loading.
  835. Triggered by LoadFromFile/Stream and AddDataFromFile/Stream.
  836. Allows to adjust/transfer subclass-specific features. *)
  837. procedure PrepareVectorFile(aFile: TgxVectorFile); virtual;
  838. (* Invoked after a mesh has been loaded/added.
  839. Triggered by LoadFromFile/Stream and AddDataFromFile/Stream.
  840. Allows to adjust/transfer subclass-specific features. *)
  841. procedure PrepareMesh; virtual;
  842. (* Recursively propagated to mesh object and facegroups.
  843. Notifies that they all can establish their material library caches. *)
  844. procedure PrepareMaterialLibraryCache;
  845. (* Recursively propagated to mesh object and facegroups.
  846. Notifies that they all should forget their material library caches. *)
  847. procedure DropMaterialLibraryCache;
  848. (* Prepare the texture and materials before rendering.
  849. Invoked once, before building the list and NOT while building the list,
  850. MaterialLibraryCache can be assumed to having been prepared if materials
  851. are active. Default behaviour is to prepare build lists for the
  852. meshobjects. *)
  853. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); virtual;
  854. public
  855. constructor Create(aOwner: TComponent); override;
  856. destructor Destroy; override;
  857. procedure Assign(Source: TPersistent); override;
  858. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  859. function AxisAlignedDimensionsUnscaled: TVector4f; override;
  860. function BarycenterOffset: TVector4f;
  861. function BarycenterPosition: TVector4f;
  862. function BarycenterAbsolutePosition: TVector4f; override;
  863. procedure BuildList(var rci: TgxRenderContextInfo); override;
  864. procedure DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean); override;
  865. procedure StructureChanged; override;
  866. (* Notifies that geometry data changed, but no re-preparation is needed.
  867. Using this method will usually be faster, but may result in incorrect
  868. rendering, reduced performance and/or invalid bounding box data
  869. (ie. invalid collision detection). Use with caution. *)
  870. procedure StructureChangedNoPrepare;
  871. // BEWARE! Utterly inefficient implementation!
  872. function RayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil)
  873. : Boolean; override;
  874. function GenerateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters): TgxSilhouette; override;
  875. (* This method allows fast shadow volumes for GLActors.
  876. If your actor/mesh doesn't change, you don't need to call this.
  877. It basically caches the connectivity data. *)
  878. procedure BuildSilhouetteConnectivityData;
  879. property MeshObjects: TgxMeshObjectList read FMeshObjects;
  880. property Skeleton: TgxSkeleton read FSkeleton;
  881. // Computes the extents of the mesh.
  882. procedure GetExtents(out min, max: TAffineVector);
  883. // Computes the barycenter of the mesh.
  884. function GetBarycenter: TAffineVector;
  885. (* Invoked after a mesh has been loaded.
  886. Should auto-center according to the AutoCentering property. *)
  887. procedure PerformAutoCentering; virtual;
  888. (* Invoked after a mesh has been loaded.
  889. Should auto-scale the vertices of the meshobjects to AutoScaling the property. *)
  890. procedure PerformAutoScaling; virtual;
  891. (* Loads a vector file.
  892. A vector files (for instance a ".3DS") stores the definition of
  893. a mesh as well as materials property.
  894. Loading a file replaces the current one (if any). *)
  895. procedure LoadFromFile(const filename: string); virtual;
  896. (* Loads a vector file from a stream.
  897. See LoadFromFile.
  898. The filename attribute is required to identify the type data you're
  899. streaming (3DS, OBJ, etc.) *)
  900. procedure LoadFromStream(const filename: string; aStream: TStream); virtual;
  901. (* Saves to a vector file.
  902. Note that only some of the vector files formats can be written. *)
  903. procedure SaveToFile(const filename: string); virtual;
  904. (* Saves to a vector file in a stream.
  905. Note that only some of the vector files formats can be written. *)
  906. procedure SaveToStream(const filename: string; aStream: TStream); virtual;
  907. (* Loads additionnal data from a file.
  908. Additionnal data could be more animation frames or morph target.
  909. The VectorFile importer must be able to handle addition of data
  910. flawlessly. *)
  911. procedure AddDataFromFile(const filename: string); virtual;
  912. // Loads additionnal data from stream. See AddDataFromFile.
  913. procedure AddDataFromStream(const filename: string; aStream: TStream); virtual;
  914. (* Returns the filename of the last loaded file, or a blank string if not
  915. file was loaded (or if the mesh was dinamically built). This does not
  916. take into account the data added to the mesh (through AddDataFromFile)
  917. or saved files. *)
  918. function LastLoadedFilename: string;
  919. (* Determines if a mesh should be centered and how.
  920. AutoCentering is performed only after loading a mesh, it has
  921. no effect on already loaded mesh data or when adding from a file/stream.
  922. If you want to alter mesh data, use direct manipulation methods
  923. (on the TgxMeshObjects). *)
  924. property AutoCentering: TgxMeshAutoCenterings read FAutoCentering write FAutoCentering default [];
  925. (* Scales vertices to a AutoScaling.
  926. AutoScaling is performed only after loading a mesh, it has
  927. no effect on already loaded mesh data or when adding from a file/stream.
  928. If you want to alter mesh data, use direct manipulation methods
  929. (on the TgxMeshObjects). *)
  930. property AutoScaling: TgxCoordinates read FAutoScaling write FAutoScaling;
  931. (* Material library where mesh materials will be stored/retrieved.
  932. If this property is not defined or if UseMeshMaterials is false,
  933. only the FreeForm's material will be used (and the mesh's materials
  934. will be ignored. *)
  935. property MaterialLibrary: TgxMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
  936. (* Defines wether materials declared in the vector file mesh are used.
  937. You must also define the MaterialLibrary property. *)
  938. property UseMeshMaterials: Boolean read FUseMeshMaterials write SetUseMeshMaterials default True;
  939. (* LightMap library where lightmaps will be stored/retrieved.
  940. If this property is not defined, lightmaps won't be used.
  941. Lightmaps currently *always* use the second texture unit (unit 1),
  942. and may interfere with multi-texture materials. *)
  943. property LightmapLibrary: TgxMaterialLibrary read FLightmapLibrary write SetLightmapLibrary;
  944. (* If True, exceptions about missing textures will be ignored.
  945. Implementation is up to the file loader class (ie. this property
  946. may be ignored by some loaders) *)
  947. property IgnoreMissingTextures: Boolean read FIgnoreMissingTextures write FIgnoreMissingTextures default False;
  948. // Normals orientation for owned mesh.
  949. property NormalsOrientation: TMeshNormalsOrientation read FNormalsOrientation write SetNormalsOrientation
  950. default mnoDefault;
  951. // Request rendering of skeleton bones over the mesh.
  952. property OverlaySkeleton: Boolean read FOverlaySkeleton write SetOverlaySkeleton default False;
  953. end;
  954. (* Container objects for a vector file mesh.
  955. FreeForms allows loading and rendering vector files (like 3DStudio
  956. ".3DS" file) in GLScene. Meshes can be loaded with the LoadFromFile
  957. method.
  958. A FreeForm may contain more than one mesh, but they will all be handled
  959. as a single object in a scene. *)
  960. TgxFreeForm = class(TgxBaseMesh)
  961. private
  962. FOctree: TgxOctree;
  963. protected
  964. function GetOctree: TgxOctree;
  965. public
  966. constructor Create(aOwner: TComponent); override;
  967. destructor Destroy; override;
  968. function OctreeRayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  969. intersectNormal: PVector4f = nil): Boolean;
  970. function OctreeSphereSweepIntersect(const rayStart, rayVector: TVector4f; const velocity, radius: Single;
  971. intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil): Boolean;
  972. function OctreeTriangleIntersect(const v1, v2, v3: TAffineVector): Boolean;
  973. (* Returns true if Point is inside the free form - this will only work
  974. properly on closed meshes. Requires that Octree has been prepared. *)
  975. function OctreePointInMesh(const Point: TVector4f): Boolean;
  976. function OctreeAABBIntersect(const aabb: TAABB; objMatrix, invObjMatrix: TMatrix4f;
  977. triangles: TgxAffineVectorList = nil): Boolean;
  978. // TODO: function OctreeSphereIntersect
  979. (* Octree support *experimental*.
  980. Use only if you understand what you're doing! *)
  981. property Octree: TgxOctree read GetOctree;
  982. procedure BuildOctree(TreeDepth: Integer = 3);
  983. published
  984. property AutoCentering;
  985. property AutoScaling;
  986. property MaterialLibrary;
  987. property LightmapLibrary;
  988. property UseMeshMaterials;
  989. property NormalsOrientation;
  990. end;
  991. (* Miscellanious actor options.
  992. aoSkeletonNormalizeNormals : if set the normals of a skeleton-animated
  993. mesh will be normalized, this is not required if no normals-based texture
  994. coordinates generation occurs, and thus may be unset to improve performance. *)
  995. TgxActorOption = (aoSkeletonNormalizeNormals);
  996. TgxActorOptions = set of TgxActorOption;
  997. const
  998. cDefaultActorOptions = [aoSkeletonNormalizeNormals];
  999. type
  1000. TgxActor = class;
  1001. TgxActorAnimationReference = (aarMorph, aarSkeleton, aarNone);
  1002. (* An actor animation sequence.
  1003. An animation sequence is a named set of contiguous frames that can be used
  1004. for animating an actor. The referred frames can be either morph or skeletal
  1005. frames (choose which via the Reference property).
  1006. An animation can be directly "played" by the actor by selecting it with
  1007. SwitchAnimation, and can also be "blended" via a TgxAnimationControler. *)
  1008. TgxActorAnimation = class(TCollectionItem)
  1009. private
  1010. FName: string;
  1011. FStartFrame: Integer;
  1012. FEndFrame: Integer;
  1013. FReference: TgxActorAnimationReference;
  1014. protected
  1015. function GetDisplayName: string; override;
  1016. function FrameCount: Integer;
  1017. procedure SetStartFrame(const val: Integer);
  1018. procedure SetEndFrame(const val: Integer);
  1019. procedure SetReference(val: TgxActorAnimationReference);
  1020. procedure SetAsString(const val: string);
  1021. function GetAsString: string;
  1022. public
  1023. constructor Create(Collection: TCollection); override;
  1024. destructor Destroy; override;
  1025. procedure Assign(Source: TPersistent); override;
  1026. property AsString: string read GetAsString write SetAsString;
  1027. function OwnerActor: TgxActor;
  1028. (* Linearly removes the translation component between skeletal frames.
  1029. This function will compute the translation of the first bone (index 0)
  1030. and linearly subtract this translation in all frames between startFrame
  1031. and endFrame. Its purpose is essentially to remove the 'slide' that
  1032. exists in some animation formats (f.i. SMD). *)
  1033. procedure MakeSkeletalTranslationStatic;
  1034. (* Removes the absolute rotation component of the skeletal frames.
  1035. Some formats will store frames with absolute rotation information,
  1036. if this correct if the animation is the "main" animation.
  1037. This function removes that absolute information, making the animation
  1038. frames suitable for blending purposes. *)
  1039. procedure MakeSkeletalRotationDelta;
  1040. published
  1041. property Name: string read FName write FName;
  1042. // Index of the initial frame of the animation.
  1043. property startFrame: Integer read FStartFrame write SetStartFrame;
  1044. // Index of the final frame of the animation.
  1045. property endFrame: Integer read FEndFrame write SetEndFrame;
  1046. // Indicates if this is a skeletal or a morph-based animation.
  1047. property reference: TgxActorAnimationReference read FReference write SetReference default aarMorph;
  1048. end;
  1049. TgxActorAnimationName = string;
  1050. // Collection of actor animations sequences.
  1051. TgxActorAnimations = class(TCollection)
  1052. private
  1053. FOwner: TgxActor;
  1054. protected
  1055. function GetOwner: TPersistent; override;
  1056. procedure SetItems(Index: Integer; const val: TgxActorAnimation);
  1057. function GetItems(Index: Integer): TgxActorAnimation;
  1058. public
  1059. constructor Create(aOwner: TgxActor);
  1060. function Add: TgxActorAnimation;
  1061. function FindItemID(ID: Integer): TgxActorAnimation;
  1062. function FindName(const aName: string): TgxActorAnimation;
  1063. function FindFrame(aFrame: Integer; aReference: TgxActorAnimationReference): TgxActorAnimation;
  1064. procedure SetToStrings(aStrings: TStrings);
  1065. procedure SaveToStream(aStream: TStream);
  1066. procedure LoadFromStream(aStream: TStream);
  1067. procedure SaveToFile(const filename: string);
  1068. procedure LoadFromFile(const filename: string);
  1069. property Items[index: Integer]: TgxActorAnimation read GetItems write SetItems; default;
  1070. function Last: TgxActorAnimation;
  1071. end;
  1072. // Base class for skeletal animation control.
  1073. TgxBaseAnimationControler = class(TComponent)
  1074. private
  1075. FEnabled: Boolean;
  1076. FActor: TgxActor;
  1077. protected
  1078. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1079. procedure SetEnabled(const val: Boolean);
  1080. procedure SetActor(const val: TgxActor);
  1081. procedure DoChange; virtual;
  1082. function Apply(var lerpInfo: TgxBlendedLerpInfo): Boolean; virtual;
  1083. public
  1084. constructor Create(aOwner: TComponent); override;
  1085. destructor Destroy; override;
  1086. published
  1087. property Enabled: Boolean read FEnabled write SetEnabled default True;
  1088. property Actor: TgxActor read FActor write SetActor;
  1089. end;
  1090. (* Controls the blending of an additionnal skeletal animation into an actor.
  1091. The animation controler allows animating an actor with several animations
  1092. at a time, for instance, you could use a "run" animation as base animation
  1093. (in TgxActor), blend an animation that makes the arms move differently
  1094. depending on what the actor is carrying, along with an animation that will
  1095. make the head turn toward a target. *)
  1096. TgxAnimationControler = class(TgxBaseAnimationControler)
  1097. private
  1098. FAnimationName: TgxActorAnimationName;
  1099. FRatio: Single;
  1100. protected
  1101. procedure SetAnimationName(const val: TgxActorAnimationName);
  1102. procedure SetRatio(const val: Single);
  1103. procedure DoChange; override;
  1104. function Apply(var lerpInfo: TgxBlendedLerpInfo): Boolean; override;
  1105. published
  1106. property AnimationName: string read FAnimationName write SetAnimationName;
  1107. property Ratio: Single read FRatio write SetRatio;
  1108. end;
  1109. (* Actor frame-interpolation mode.
  1110. - afpNone : no interpolation, display CurrentFrame only
  1111. - afpLinear : perform linear interpolation between current and next frame *)
  1112. TActorFrameInterpolation = (afpNone, afpLinear);
  1113. (* Defines how an actor plays between its StartFrame and EndFrame.
  1114. aamNone : no animation is performed
  1115. aamPlayOnce : play from current frame to EndFrame, once end frame has
  1116. been reached, switches to aamNone
  1117. aamLoop : play from current frame to EndFrame, once end frame has
  1118. been reached, sets CurrentFrame to StartFrame
  1119. aamBounceForward : play from current frame to EndFrame, once end frame
  1120. has been reached, switches to aamBounceBackward
  1121. aamBounceBackward : play from current frame to StartFrame, once start
  1122. frame has been reached, switches to aamBounceForward
  1123. aamExternal : Allows for external animation control *)
  1124. TgxActorAnimationMode = (aamNone, aamPlayOnce, aamLoop, aamBounceForward, aamBounceBackward, aamLoopBackward, aamExternal);
  1125. (* Mesh class specialized in animated meshes.
  1126. The TgxActor provides a quick interface to animated meshes based on morph
  1127. or skeleton frames, it is capable of performing frame interpolation and
  1128. animation blending (via TgxAnimationControler components). *)
  1129. TgxActor = class(TgxBaseMesh)
  1130. private
  1131. FStartFrame, FEndFrame: Integer;
  1132. FReference: TgxActorAnimationReference;
  1133. FCurrentFrame: Integer;
  1134. FCurrentFrameDelta: Single;
  1135. FFrameInterpolation: TActorFrameInterpolation;
  1136. FInterval: Integer;
  1137. FAnimationMode: TgxActorAnimationMode;
  1138. FOnFrameChanged: TNotifyEvent;
  1139. FOnEndFrameReached, FOnStartFrameReached: TNotifyEvent;
  1140. FAnimations: TgxActorAnimations;
  1141. FTargetSmoothAnimation: TgxActorAnimation;
  1142. FControlers: TList;
  1143. FOptions: TgxActorOptions;
  1144. protected
  1145. procedure SetCurrentFrame(val: Integer);
  1146. procedure SetStartFrame(val: Integer);
  1147. procedure SetEndFrame(val: Integer);
  1148. procedure SetReference(val: TgxActorAnimationReference);
  1149. procedure SetAnimations(const val: TgxActorAnimations);
  1150. function StoreAnimations: Boolean;
  1151. procedure SetOptions(const val: TgxActorOptions);
  1152. procedure PrepareMesh; override;
  1153. procedure PrepareBuildList(var mrci: TgxRenderContextInfo); override;
  1154. procedure DoAnimate; virtual;
  1155. procedure RegisterControler(aControler: TgxBaseAnimationControler);
  1156. procedure UnRegisterControler(aControler: TgxBaseAnimationControler);
  1157. public
  1158. constructor Create(aOwner: TComponent); override;
  1159. destructor Destroy; override;
  1160. procedure Assign(Source: TPersistent); override;
  1161. procedure BuildList(var rci: TgxRenderContextInfo); override;
  1162. procedure DoProgress(const progressTime: TgxProgressTimes); override;
  1163. procedure LoadFromStream(const filename: string; aStream: TStream); override;
  1164. procedure SwitchToAnimation(anAnimation: TgxActorAnimation; smooth: Boolean = False); overload;
  1165. procedure SwitchToAnimation(const AnimationName: string; smooth: Boolean = False); overload;
  1166. procedure SwitchToAnimation(animationIndex: Integer; smooth: Boolean = False); overload;
  1167. function CurrentAnimation: string;
  1168. (* Synchronize self animation with an other actor.
  1169. Copies Start/Current/End Frame values, CurrentFrameDelta,
  1170. AnimationMode and FrameInterpolation. *)
  1171. procedure Synchronize(referenceActor: TgxActor);
  1172. (* Provides a direct access to FCurrentFrame without any checks.
  1173. Used in TgxActorProxy. *)
  1174. procedure SetCurrentFrameDirect(const Value: Integer);
  1175. function NextFrameIndex: Integer;
  1176. procedure NextFrame(nbSteps: Integer = 1);
  1177. procedure PrevFrame(nbSteps: Integer = 1);
  1178. function FrameCount: Integer;
  1179. (* Indicates whether the actor is currently swithing animations (with
  1180. smooth interpolation). *)
  1181. function isSwitchingAnimation: Boolean;
  1182. published
  1183. property startFrame: Integer read FStartFrame write SetStartFrame default 0;
  1184. property endFrame: Integer read FEndFrame write SetEndFrame default 0;
  1185. (* Reference Frame Animation mode.
  1186. Allows specifying if the model is primarily morph or skeleton based. *)
  1187. property reference: TgxActorAnimationReference read FReference write FReference default aarMorph;
  1188. // Current animation frame.
  1189. property CurrentFrame: Integer read FCurrentFrame write SetCurrentFrame default 0;
  1190. // Value in the [0; 1] range expressing the delta to the next frame.
  1191. property CurrentFrameDelta: Single read FCurrentFrameDelta write FCurrentFrameDelta;
  1192. // Frame interpolation mode (afpNone/afpLinear).
  1193. property FrameInterpolation: TActorFrameInterpolation read FFrameInterpolation write FFrameInterpolation default afpLinear;
  1194. // See TgxActorAnimationMode.
  1195. property AnimationMode: TgxActorAnimationMode read FAnimationMode write FAnimationMode default aamNone;
  1196. // Interval between frames, in milliseconds.
  1197. property Interval: Integer read FInterval write FInterval;
  1198. // Actor and animation miscellanious options.
  1199. property Options: TgxActorOptions read FOptions write SetOptions default cDefaultActorOptions;
  1200. // Triggered after each CurrentFrame change.
  1201. property OnFrameChanged: TNotifyEvent read FOnFrameChanged write FOnFrameChanged;
  1202. // Triggered after EndFrame has been reached by progression or "nextframe"
  1203. property OnEndFrameReached: TNotifyEvent read FOnEndFrameReached write FOnEndFrameReached;
  1204. // Triggered after StartFrame has been reached by progression or "nextframe"
  1205. property OnStartFrameReached: TNotifyEvent read FOnStartFrameReached write FOnStartFrameReached;
  1206. // Collection of animations sequences.
  1207. property Animations: TgxActorAnimations read FAnimations write SetAnimations stored StoreAnimations;
  1208. property AutoCentering;
  1209. property MaterialLibrary;
  1210. property LightmapLibrary;
  1211. property UseMeshMaterials;
  1212. property NormalsOrientation;
  1213. property OverlaySkeleton;
  1214. end;
  1215. TgxVectorFileFormat = class
  1216. public
  1217. VectorFileClass: TgxVectorFileClass;
  1218. Extension: string;
  1219. Description: string;
  1220. DescResID: Integer;
  1221. end;
  1222. // Stores registered vector file Formatx.
  1223. TgxVectorFileFormatsList = class(TgxPersistentObjectList)
  1224. public
  1225. destructor Destroy; override;
  1226. procedure Add(const Ext, Desc: string; DescID: Integer; AClass: TgxVectorFileClass);
  1227. function FindExt(Ext: string): TgxVectorFileClass;
  1228. function FindFromFileName(const filename: string): TgxVectorFileClass;
  1229. procedure Remove(AClass: TgxVectorFileClass);
  1230. procedure BuildFilterStrings(VectorFileClass: TgxVectorFileClass; out descriptions, filters: string;
  1231. formatsThatCanBeOpened: Boolean = True; formatsThatCanBeSaved: Boolean = False);
  1232. function FindExtByIndex(Index: Integer; formatsThatCanBeOpened: Boolean = True;
  1233. formatsThatCanBeSaved: Boolean = False): string;
  1234. end;
  1235. EInvalidVectorFile = class(Exception);
  1236. // Read access to the list of registered vector file formats
  1237. function GetVectorFileFormats: TgxVectorFileFormatsList;
  1238. // A file extension filter suitable for dialog's 'Filter' property
  1239. function VectorFileFormatsFilter: string;
  1240. // A file extension filter suitable for a savedialog's 'Filter' property
  1241. function VectorFileFormatsSaveFilter: string;
  1242. (* Returns an extension by its index in the vector files dialogs filter.
  1243. Use VectorFileFormatsFilter to obtain the filter. *)
  1244. function VectorFileFormatExtensionByIndex(Index: Integer): string;
  1245. procedure RegisterVectorFileFormat(const aExtension, aDescription: string; AClass: TgxVectorFileClass);
  1246. procedure UnregisterVectorFileClass(AClass: TgxVectorFileClass);
  1247. var
  1248. vVectorFileObjectsAllocateMaterials: Boolean = True;
  1249. // Flag to avoid loading materials (useful for IDE Extentions or scene editors)
  1250. vVectorFileObjectsEnableVBOByDefault: Boolean = True;
  1251. // ===========================================================================
  1252. implementation
  1253. // ===========================================================================
  1254. uses
  1255. GXS.MeshUtils,
  1256. GXS.BaseMeshSilhouette;
  1257. var
  1258. vVectorFileFormats: TgxVectorFileFormatsList;
  1259. vNextRenderGroupID: Integer = 1;
  1260. const
  1261. cAAFHeader: AnsiString = 'AAF';
  1262. function GetVectorFileFormats: TgxVectorFileFormatsList;
  1263. begin
  1264. if not Assigned(vVectorFileFormats) then
  1265. vVectorFileFormats := TgxVectorFileFormatsList.Create;
  1266. Result := vVectorFileFormats;
  1267. end;
  1268. function VectorFileFormatsFilter: string;
  1269. var
  1270. f: string;
  1271. begin
  1272. GetVectorFileFormats.BuildFilterStrings(TgxVectorFile, Result, f);
  1273. end;
  1274. function VectorFileFormatsSaveFilter: string;
  1275. var
  1276. f: string;
  1277. begin
  1278. GetVectorFileFormats.BuildFilterStrings(TgxVectorFile, Result, f, False, True);
  1279. end;
  1280. procedure RegisterVectorFileFormat(const aExtension, aDescription: string; AClass: TgxVectorFileClass);
  1281. begin
  1282. RegisterClass(AClass);
  1283. GetVectorFileFormats.Add(aExtension, aDescription, 0, AClass);
  1284. end;
  1285. procedure UnregisterVectorFileClass(AClass: TgxVectorFileClass);
  1286. begin
  1287. if Assigned(vVectorFileFormats) then
  1288. vVectorFileFormats.Remove(AClass);
  1289. end;
  1290. function VectorFileFormatExtensionByIndex(Index: Integer): string;
  1291. begin
  1292. Result := GetVectorFileFormats.FindExtByIndex(index);
  1293. end;
  1294. destructor TgxVectorFileFormatsList.Destroy;
  1295. begin
  1296. Clean;
  1297. inherited;
  1298. end;
  1299. procedure TgxVectorFileFormatsList.Add(const Ext, Desc: string; DescID: Integer; AClass: TgxVectorFileClass);
  1300. var
  1301. newRec: TgxVectorFileFormat;
  1302. begin
  1303. newRec := TgxVectorFileFormat.Create;
  1304. with newRec do
  1305. begin
  1306. Extension := AnsiLowerCase(Ext);
  1307. VectorFileClass := AClass;
  1308. Description := Desc;
  1309. DescResID := DescID;
  1310. end;
  1311. inherited Add(newRec);
  1312. end;
  1313. function TgxVectorFileFormatsList.FindExt(Ext: string): TgxVectorFileClass;
  1314. var
  1315. i: Integer;
  1316. begin
  1317. Ext := AnsiLowerCase(Ext);
  1318. for i := Count - 1 downto 0 do
  1319. with TgxVectorFileFormat(Items[i]) do
  1320. begin
  1321. if Extension = Ext then
  1322. begin
  1323. Result := VectorFileClass;
  1324. Exit;
  1325. end;
  1326. end;
  1327. Result := nil;
  1328. end;
  1329. function TgxVectorFileFormatsList.FindFromFileName(const filename: string): TgxVectorFileClass;
  1330. var
  1331. Ext: string;
  1332. begin
  1333. Ext := ExtractFileExt(filename);
  1334. System.Delete(Ext, 1, 1);
  1335. Result := FindExt(Ext);
  1336. if not Assigned(Result) then
  1337. raise EInvalidVectorFile.CreateFmt(strUnknownExtension, [Ext, 'GLFile' + UpperCase(Ext)]);
  1338. end;
  1339. procedure TgxVectorFileFormatsList.Remove(AClass: TgxVectorFileClass);
  1340. var
  1341. i: Integer;
  1342. begin
  1343. for i := Count - 1 downto 0 do
  1344. begin
  1345. if TgxVectorFileFormat(Items[i]).VectorFileClass.InheritsFrom(AClass) then
  1346. DeleteAndFree(i);
  1347. end;
  1348. end;
  1349. procedure TgxVectorFileFormatsList.BuildFilterStrings(VectorFileClass: TgxVectorFileClass; out descriptions, filters: string;
  1350. formatsThatCanBeOpened: Boolean = True; formatsThatCanBeSaved: Boolean = False);
  1351. var
  1352. k, i: Integer;
  1353. p: TgxVectorFileFormat;
  1354. begin
  1355. descriptions := '';
  1356. filters := '';
  1357. k := 0;
  1358. for i := 0 to Count - 1 do
  1359. begin
  1360. p := TgxVectorFileFormat(Items[i]);
  1361. if p.VectorFileClass.InheritsFrom(VectorFileClass) and (p.Extension <> '') and
  1362. ((formatsThatCanBeOpened and (dfcRead in p.VectorFileClass.Capabilities)) or
  1363. (formatsThatCanBeSaved and (dfcWrite in p.VectorFileClass.Capabilities))) then
  1364. begin
  1365. with p do
  1366. begin
  1367. if k <> 0 then
  1368. begin
  1369. descriptions := descriptions + '|';
  1370. filters := filters + ';';
  1371. end;
  1372. if (Description = '') and (DescResID <> 0) then
  1373. Description := LoadStr(DescResID);
  1374. FmtStr(descriptions, '%s%s (*.%s)|*.%2:s', [descriptions, Description, Extension]);
  1375. filters := filters + '*.' + Extension;
  1376. Inc(k);
  1377. end;
  1378. end;
  1379. end;
  1380. if (k > 1) and (not formatsThatCanBeSaved) then
  1381. FmtStr(descriptions, '%s (%s)|%1:s|%s', [sAllFilter, filters, descriptions]);
  1382. end;
  1383. function TgxVectorFileFormatsList.FindExtByIndex(Index: Integer; formatsThatCanBeOpened: Boolean = True;
  1384. formatsThatCanBeSaved: Boolean = False): string;
  1385. var
  1386. i: Integer;
  1387. p: TgxVectorFileFormat;
  1388. begin
  1389. Result := '';
  1390. if index > 0 then
  1391. begin
  1392. for i := 0 to Count - 1 do
  1393. begin
  1394. p := TgxVectorFileFormat(Items[i]);
  1395. if (formatsThatCanBeOpened and (dfcRead in p.VectorFileClass.Capabilities)) or
  1396. (formatsThatCanBeSaved and (dfcWrite in p.VectorFileClass.Capabilities)) then
  1397. begin
  1398. if index = 1 then
  1399. begin
  1400. Result := p.Extension;
  1401. Break;
  1402. end
  1403. else
  1404. Dec(index);
  1405. end;
  1406. end;
  1407. end;
  1408. end;
  1409. // ------------------
  1410. // ------------------ TgxBaseMeshObject ------------------
  1411. // ------------------
  1412. constructor TgxBaseMeshObject.Create;
  1413. begin
  1414. FVertices := TgxAffineVectorList.Create;
  1415. FNormals := TgxAffineVectorList.Create;
  1416. FVisible := True;
  1417. inherited Create;
  1418. end;
  1419. destructor TgxBaseMeshObject.Destroy;
  1420. begin
  1421. FNormals.Free;
  1422. FVertices.Free;
  1423. inherited;
  1424. end;
  1425. procedure TgxBaseMeshObject.Assign(Source: TPersistent);
  1426. begin
  1427. if Source is TgxBaseMeshObject then
  1428. begin
  1429. FName := TgxBaseMeshObject(Source).Name;
  1430. FVertices.Assign(TgxBaseMeshObject(Source).FVertices);
  1431. FNormals.Assign(TgxBaseMeshObject(Source).FNormals);
  1432. end
  1433. else
  1434. inherited; // Die!
  1435. end;
  1436. procedure TgxBaseMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  1437. begin
  1438. inherited WriteToFiler(writer);
  1439. with writer do
  1440. begin
  1441. WriteInteger(1); // Archive Version 1, added FVisible
  1442. WriteString(FName);
  1443. FVertices.WriteToFiler(writer);
  1444. FNormals.WriteToFiler(writer);
  1445. WriteBoolean(FVisible);
  1446. end;
  1447. end;
  1448. procedure TgxBaseMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  1449. var
  1450. archiveVersion: Integer;
  1451. begin
  1452. inherited ReadFromFiler(reader);
  1453. archiveVersion := reader.ReadInteger;
  1454. if archiveVersion in [0 .. 1] then
  1455. with reader do
  1456. begin
  1457. FName := ReadString;
  1458. FVertices.ReadFromFiler(reader);
  1459. FNormals.ReadFromFiler(reader);
  1460. if archiveVersion >= 1 then
  1461. FVisible := ReadBoolean
  1462. else
  1463. FVisible := True;
  1464. end
  1465. else
  1466. RaiseFilerException(archiveVersion);
  1467. end;
  1468. procedure TgxBaseMeshObject.Clear;
  1469. begin
  1470. FNormals.Clear;
  1471. FVertices.Clear;
  1472. end;
  1473. procedure TgxBaseMeshObject.ContributeToBarycenter(var currentSum: TAffineVector; var nb: Integer);
  1474. begin
  1475. AddVector(currentSum, FVertices.Sum);
  1476. nb := nb + FVertices.Count;
  1477. end;
  1478. procedure TgxBaseMeshObject.Translate(const delta: TAffineVector);
  1479. begin
  1480. FVertices.Translate(delta);
  1481. end;
  1482. procedure TgxBaseMeshObject.BuildNormals(vertexIndices: TgxIntegerList; mode: TgxMeshObjectMode;
  1483. normalIndices: TgxIntegerList = nil);
  1484. var
  1485. i, base: Integer;
  1486. n: TAffineVector;
  1487. newNormals: TgxIntegerList;
  1488. function TranslateNewNormal(vertexIndex: Integer; const delta: TAffineVector): Integer;
  1489. var
  1490. pv: PAffineVector;
  1491. begin
  1492. Result := newNormals[vertexIndex];
  1493. if Result < base then
  1494. begin
  1495. Result := normals.Add(NullVector);
  1496. newNormals[vertexIndex] := Result;
  1497. end;
  1498. pv := @normals.list[Result];
  1499. AddVector(pv^, delta);
  1500. end;
  1501. begin
  1502. if not Assigned(normalIndices) then
  1503. begin
  1504. // build bijection
  1505. normals.Clear;
  1506. normals.Count := Vertices.Count;
  1507. case mode of
  1508. momTriangles:
  1509. begin
  1510. i := 0;
  1511. while i <= vertexIndices.Count - 3 do
  1512. with normals do
  1513. begin
  1514. with Vertices do
  1515. begin
  1516. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n);
  1517. end;
  1518. with normals do
  1519. begin
  1520. TranslateItem(vertexIndices[i + 0], n);
  1521. TranslateItem(vertexIndices[i + 1], n);
  1522. TranslateItem(vertexIndices[i + 2], n);
  1523. end;
  1524. Inc(i, 3);
  1525. end;
  1526. end;
  1527. momTriangleStrip:
  1528. begin
  1529. i := 0;
  1530. while i <= vertexIndices.Count - 3 do
  1531. with normals do
  1532. begin
  1533. with Vertices do
  1534. begin
  1535. if (i and 1) = 0 then
  1536. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n)
  1537. else
  1538. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 2]], Items[vertexIndices[i + 1]], n);
  1539. end;
  1540. with normals do
  1541. begin
  1542. TranslateItem(vertexIndices[i + 0], n);
  1543. TranslateItem(vertexIndices[i + 1], n);
  1544. TranslateItem(vertexIndices[i + 2], n);
  1545. end;
  1546. Inc(i, 1);
  1547. end;
  1548. end;
  1549. else
  1550. Assert(False);
  1551. end;
  1552. normals.normalize;
  1553. end
  1554. else
  1555. begin
  1556. // add new normals
  1557. base := normals.Count;
  1558. newNormals := TgxIntegerList.Create;
  1559. newNormals.AddSerie(-1, 0, Vertices.Count);
  1560. case mode of
  1561. momTriangles:
  1562. begin
  1563. i := 0;
  1564. while i <= vertexIndices.Count - 3 do
  1565. begin
  1566. with Vertices do
  1567. begin
  1568. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n);
  1569. end;
  1570. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 0], n));
  1571. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 1], n));
  1572. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 2], n));
  1573. Inc(i, 3);
  1574. end;
  1575. end;
  1576. momTriangleStrip:
  1577. begin
  1578. i := 0;
  1579. while i <= vertexIndices.Count - 3 do
  1580. begin
  1581. with Vertices do
  1582. begin
  1583. if (i and 1) = 0 then
  1584. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 1]], Items[vertexIndices[i + 2]], n)
  1585. else
  1586. CalcPlaneNormal(Items[vertexIndices[i + 0]], Items[vertexIndices[i + 2]], Items[vertexIndices[i + 1]], n);
  1587. end;
  1588. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 0], n));
  1589. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 1], n));
  1590. normalIndices.Add(TranslateNewNormal(vertexIndices[i + 2], n));
  1591. Inc(i, 1);
  1592. end;
  1593. end;
  1594. else
  1595. Assert(False);
  1596. end;
  1597. for i := base to normals.Count - 1 do
  1598. NormalizeVector(normals.list^[i]);
  1599. newNormals.Free;
  1600. end;
  1601. end;
  1602. function TgxBaseMeshObject.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  1603. : TgxAffineVectorList;
  1604. begin
  1605. Result := TgxAffineVectorList.Create;
  1606. if (Vertices.Count mod 3) = 0 then
  1607. begin
  1608. Result.Assign(Vertices);
  1609. if Assigned(normals) then
  1610. normals.Assign(Self.normals);
  1611. end;
  1612. end;
  1613. procedure TgxBaseMeshObject.SetVertices(const val: TgxAffineVectorList);
  1614. begin
  1615. FVertices.Assign(val);
  1616. end;
  1617. procedure TgxBaseMeshObject.SetNormals(const val: TgxAffineVectorList);
  1618. begin
  1619. FNormals.Assign(val);
  1620. end;
  1621. // ------------------
  1622. // ------------------ TgxSkeletonFrame ------------------
  1623. // ------------------
  1624. constructor TgxSkeletonFrame.CreateOwned(aOwner: TgxSkeletonFrameList);
  1625. begin
  1626. FOwner := aOwner;
  1627. aOwner.Add(Self);
  1628. Create;
  1629. end;
  1630. constructor TgxSkeletonFrame.Create;
  1631. begin
  1632. inherited Create;
  1633. FPosition := TgxAffineVectorList.Create;
  1634. FRotation := TgxAffineVectorList.Create;
  1635. FQuaternion := TQuaternionList.Create;
  1636. FTransformMode := sftRotation;
  1637. end;
  1638. destructor TgxSkeletonFrame.Destroy;
  1639. begin
  1640. FlushLocalMatrixList;
  1641. FRotation.Free;
  1642. FPosition.Free;
  1643. FQuaternion.Free;
  1644. inherited Destroy;
  1645. end;
  1646. procedure TgxSkeletonFrame.WriteToFiler(writer: TgxVirtualWriter);
  1647. begin
  1648. inherited WriteToFiler(writer);
  1649. with writer do
  1650. begin
  1651. WriteInteger(1); // Archive Version 1
  1652. WriteString(FName);
  1653. FPosition.WriteToFiler(writer);
  1654. FRotation.WriteToFiler(writer);
  1655. FQuaternion.WriteToFiler(writer);
  1656. WriteInteger(Integer(FTransformMode));
  1657. end;
  1658. end;
  1659. procedure TgxSkeletonFrame.ReadFromFiler(reader: TgxVirtualReader);
  1660. var
  1661. archiveVersion: Integer;
  1662. begin
  1663. inherited ReadFromFiler(reader);
  1664. archiveVersion := reader.ReadInteger;
  1665. if (archiveVersion = 0) or (archiveVersion = 1) then
  1666. with reader do
  1667. begin
  1668. FName := ReadString;
  1669. FPosition.ReadFromFiler(reader);
  1670. FRotation.ReadFromFiler(reader);
  1671. if (archiveVersion = 1) then
  1672. begin
  1673. FQuaternion.ReadFromFiler(reader);
  1674. FTransformMode := TgxSkeletonFrameTransform(ReadInteger);
  1675. end;
  1676. end
  1677. else
  1678. RaiseFilerException(archiveVersion);
  1679. FlushLocalMatrixList;
  1680. end;
  1681. procedure TgxSkeletonFrame.SetPosition(const val: TgxAffineVectorList);
  1682. begin
  1683. FPosition.Assign(val);
  1684. end;
  1685. procedure TgxSkeletonFrame.SetRotation(const val: TgxAffineVectorList);
  1686. begin
  1687. FRotation.Assign(val);
  1688. end;
  1689. procedure TgxSkeletonFrame.SetQuaternion(const val: TQuaternionList);
  1690. begin
  1691. FQuaternion.Assign(val);
  1692. end;
  1693. function TgxSkeletonFrame.LocalMatrixList: PMatrixArray;
  1694. var
  1695. i: Integer;
  1696. s, c: Single;
  1697. mat, rmat: TMatrix4f;
  1698. quat: TQuaternion;
  1699. begin
  1700. if not Assigned(FLocalMatrixList) then
  1701. begin
  1702. case FTransformMode of
  1703. sftRotation:
  1704. begin
  1705. FLocalMatrixList := AllocMem(SizeOf(TMatrix4f) * Rotation.Count);
  1706. for i := 0 to Rotation.Count - 1 do
  1707. begin
  1708. if Rotation[i].X <> 0 then
  1709. begin
  1710. SinCosine(Rotation[i].X, s, c);
  1711. mat := CreateRotationMatrixX(s, c);
  1712. end
  1713. else
  1714. mat := IdentityHmgMatrix;
  1715. if Rotation[i].Y <> 0 then
  1716. begin
  1717. SinCosine(Rotation[i].Y, s, c);
  1718. rmat := CreateRotationMatrixY(s, c);
  1719. mat := MatrixMultiply(mat, rmat);
  1720. end;
  1721. if Rotation[i].Z <> 0 then
  1722. begin
  1723. SinCosine(Rotation[i].Z, s, c);
  1724. rmat := CreateRotationMatrixZ(s, c);
  1725. mat := MatrixMultiply(mat, rmat);
  1726. end;
  1727. mat.W.X := Position[i].X;
  1728. mat.W.Y := Position[i].Y;
  1729. mat.W.Z := Position[i].Z;
  1730. FLocalMatrixList^[i] := mat;
  1731. end;
  1732. end;
  1733. sftQuaternion:
  1734. begin
  1735. FLocalMatrixList := AllocMem(SizeOf(TMatrix4f) * Quaternion.Count);
  1736. for i := 0 to Quaternion.Count - 1 do
  1737. begin
  1738. quat := Quaternion[i];
  1739. mat := QuaternionToMatrix(quat);
  1740. mat.W.X := Position[i].X;
  1741. mat.W.Y := Position[i].Y;
  1742. mat.W.Z := Position[i].Z;
  1743. mat.W.W := 1;
  1744. FLocalMatrixList^[i] := mat;
  1745. end;
  1746. end;
  1747. end;
  1748. end;
  1749. Result := FLocalMatrixList;
  1750. end;
  1751. procedure TgxSkeletonFrame.FlushLocalMatrixList;
  1752. begin
  1753. if Assigned(FLocalMatrixList) then
  1754. begin
  1755. FreeMem(FLocalMatrixList);
  1756. FLocalMatrixList := nil;
  1757. end;
  1758. end;
  1759. procedure TgxSkeletonFrame.ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True);
  1760. var
  1761. i: Integer;
  1762. t: TTransformations;
  1763. m: TMatrix4f;
  1764. begin
  1765. Rotation.Clear;
  1766. for i := 0 to Quaternion.Count - 1 do
  1767. begin
  1768. m := QuaternionToMatrix(Quaternion[i]);
  1769. if MatrixDecompose(m, t) then
  1770. Rotation.Add(t[ttRotateX], t[ttRotateY], t[ttRotateZ])
  1771. else
  1772. Rotation.Add(NullVector);
  1773. end;
  1774. if not KeepQuaternions then
  1775. Quaternion.Clear;
  1776. end;
  1777. procedure TgxSkeletonFrame.ConvertRotationsToQuaternions(KeepRotations: Boolean = True);
  1778. var
  1779. i: Integer;
  1780. mat, rmat: TMatrix4f;
  1781. s, c: Single;
  1782. begin
  1783. Quaternion.Clear;
  1784. for i := 0 to Rotation.Count - 1 do
  1785. begin
  1786. mat := IdentityHmgMatrix;
  1787. SinCosine(Rotation[i].X, s, c);
  1788. rmat := CreateRotationMatrixX(s, c);
  1789. mat := MatrixMultiply(mat, rmat);
  1790. SinCosine(Rotation[i].Y, s, c);
  1791. rmat := CreateRotationMatrixY(s, c);
  1792. mat := MatrixMultiply(mat, rmat);
  1793. SinCosine(Rotation[i].Z, s, c);
  1794. rmat := CreateRotationMatrixZ(s, c);
  1795. mat := MatrixMultiply(mat, rmat);
  1796. Quaternion.Add(QuaternionFromMatrix(mat));
  1797. end;
  1798. if not KeepRotations then
  1799. Rotation.Clear;
  1800. end;
  1801. // ------------------
  1802. // ------------------ TgxSkeletonFrameList ------------------
  1803. // ------------------
  1804. constructor TgxSkeletonFrameList.CreateOwned(aOwner: TPersistent);
  1805. begin
  1806. FOwner := aOwner;
  1807. Create;
  1808. end;
  1809. destructor TgxSkeletonFrameList.Destroy;
  1810. begin
  1811. Clear;
  1812. inherited;
  1813. end;
  1814. procedure TgxSkeletonFrameList.ReadFromFiler(reader: TgxVirtualReader);
  1815. var
  1816. i: Integer;
  1817. begin
  1818. inherited;
  1819. for i := 0 to Count - 1 do
  1820. Items[i].FOwner := Self;
  1821. end;
  1822. procedure TgxSkeletonFrameList.Clear;
  1823. var
  1824. i: Integer;
  1825. begin
  1826. for i := 0 to Count - 1 do
  1827. with Items[i] do
  1828. begin
  1829. FOwner := nil;
  1830. Free;
  1831. end;
  1832. inherited;
  1833. end;
  1834. function TgxSkeletonFrameList.GetSkeletonFrame(Index: Integer): TgxSkeletonFrame;
  1835. begin
  1836. Result := TgxSkeletonFrame(list^[Index]);
  1837. end;
  1838. procedure TgxSkeletonFrameList.ConvertQuaternionsToRotations(KeepQuaternions: Boolean = True; SetTransformMode: Boolean = True);
  1839. var
  1840. i: Integer;
  1841. begin
  1842. for i := 0 to Count - 1 do
  1843. begin
  1844. Items[i].ConvertQuaternionsToRotations(KeepQuaternions);
  1845. if SetTransformMode then
  1846. Items[i].TransformMode := sftRotation;
  1847. end;
  1848. end;
  1849. procedure TgxSkeletonFrameList.ConvertRotationsToQuaternions(KeepRotations: Boolean = True; SetTransformMode: Boolean = True);
  1850. var
  1851. i: Integer;
  1852. begin
  1853. for i := 0 to Count - 1 do
  1854. begin
  1855. Items[i].ConvertRotationsToQuaternions(KeepRotations);
  1856. if SetTransformMode then
  1857. Items[i].TransformMode := sftQuaternion;
  1858. end;
  1859. end;
  1860. // ------------------
  1861. // ------------------ TgxSkeletonBoneList ------------------
  1862. // ------------------
  1863. constructor TgxSkeletonBoneList.CreateOwned(aOwner: TgxSkeleton);
  1864. begin
  1865. FSkeleton := aOwner;
  1866. Create;
  1867. end;
  1868. constructor TgxSkeletonBoneList.Create;
  1869. begin
  1870. inherited;
  1871. FGlobalMatrix := IdentityHmgMatrix;
  1872. end;
  1873. destructor TgxSkeletonBoneList.Destroy;
  1874. begin
  1875. Clean;
  1876. inherited;
  1877. end;
  1878. procedure TgxSkeletonBoneList.WriteToFiler(writer: TgxVirtualWriter);
  1879. begin
  1880. inherited WriteToFiler(writer);
  1881. with writer do
  1882. begin
  1883. WriteInteger(0); // Archive Version 0
  1884. // nothing, yet
  1885. end;
  1886. end;
  1887. procedure TgxSkeletonBoneList.ReadFromFiler(reader: TgxVirtualReader);
  1888. var
  1889. archiveVersion, i: Integer;
  1890. begin
  1891. inherited ReadFromFiler(reader);
  1892. archiveVersion := reader.ReadInteger;
  1893. if archiveVersion = 0 then
  1894. with reader do
  1895. begin
  1896. // nothing, yet
  1897. end
  1898. else
  1899. RaiseFilerException(archiveVersion);
  1900. for i := 0 to Count - 1 do
  1901. Items[i].FOwner := Self;
  1902. end;
  1903. procedure TgxSkeletonBoneList.AfterObjectCreatedByReader(Sender: TObject);
  1904. begin
  1905. with (Sender as TgxSkeletonBone) do
  1906. begin
  1907. FOwner := Self;
  1908. FSkeleton := Self.Skeleton;
  1909. end;
  1910. end;
  1911. function TgxSkeletonBoneList.GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  1912. begin
  1913. Result := TgxSkeletonBone(list^[Index]);
  1914. end;
  1915. function TgxSkeletonBoneList.BoneByID(anID: Integer): TgxSkeletonBone;
  1916. var
  1917. i: Integer;
  1918. begin
  1919. Result := nil;
  1920. for i := 0 to Count - 1 do
  1921. begin
  1922. Result := Items[i].BoneByID(anID);
  1923. if Assigned(Result) then
  1924. Break;
  1925. end;
  1926. end;
  1927. function TgxSkeletonBoneList.BoneByName(const aName: string): TgxSkeletonBone;
  1928. var
  1929. i: Integer;
  1930. begin
  1931. Result := nil;
  1932. for i := 0 to Count - 1 do
  1933. begin
  1934. Result := Items[i].BoneByName(aName);
  1935. if Assigned(Result) then
  1936. Break;
  1937. end;
  1938. end;
  1939. function TgxSkeletonBoneList.BoneCount: Integer;
  1940. var
  1941. i: Integer;
  1942. begin
  1943. Result := 1;
  1944. for i := 0 to Count - 1 do
  1945. Inc(Result, Items[i].BoneCount);
  1946. end;
  1947. procedure TgxSkeletonBoneList.PrepareGlobalMatrices;
  1948. var
  1949. i: Integer;
  1950. begin
  1951. for i := 0 to Count - 1 do
  1952. Items[i].PrepareGlobalMatrices;
  1953. end;
  1954. // ------------------
  1955. // ------------------ TgxSkeletonRootBoneList ------------------
  1956. // ------------------
  1957. procedure TgxSkeletonRootBoneList.WriteToFiler(writer: TgxVirtualWriter);
  1958. begin
  1959. inherited WriteToFiler(writer);
  1960. with writer do
  1961. begin
  1962. WriteInteger(0); // Archive Version 0
  1963. // nothing, yet
  1964. end;
  1965. end;
  1966. procedure TgxSkeletonRootBoneList.ReadFromFiler(reader: TgxVirtualReader);
  1967. var
  1968. archiveVersion, i: Integer;
  1969. begin
  1970. inherited ReadFromFiler(reader);
  1971. archiveVersion := reader.ReadInteger;
  1972. if archiveVersion = 0 then
  1973. with reader do
  1974. begin
  1975. // nothing, yet
  1976. end
  1977. else
  1978. RaiseFilerException(archiveVersion);
  1979. for i := 0 to Count - 1 do
  1980. Items[i].FOwner := Self;
  1981. end;
  1982. procedure TgxSkeletonRootBoneList.BuildList(var mrci: TgxRenderContextInfo);
  1983. var
  1984. i: Integer;
  1985. begin
  1986. // root node setups and restore OpenGL stuff
  1987. mrci.gxStates.Disable(stColorMaterial);
  1988. mrci.gxStates.Disable(stLighting);
  1989. glColor3f(1, 1, 1);
  1990. // render root-bones
  1991. for i := 0 to Count - 1 do
  1992. Items[i].BuildList(mrci);
  1993. end;
  1994. // ------------------
  1995. // ------------------ TgxSkeletonBone ------------------
  1996. // ------------------
  1997. constructor TgxSkeletonBone.CreateOwned(aOwner: TgxSkeletonBoneList);
  1998. begin
  1999. FOwner := aOwner;
  2000. aOwner.Add(Self);
  2001. FSkeleton := aOwner.Skeleton;
  2002. Create;
  2003. end;
  2004. constructor TgxSkeletonBone.Create;
  2005. begin
  2006. FColor := $FFFFFFFF; // opaque white
  2007. inherited;
  2008. end;
  2009. destructor TgxSkeletonBone.Destroy;
  2010. begin
  2011. if Assigned(Owner) then
  2012. Owner.Remove(Self);
  2013. inherited Destroy;
  2014. end;
  2015. procedure TgxSkeletonBone.WriteToFiler(writer: TgxVirtualWriter);
  2016. begin
  2017. inherited WriteToFiler(writer);
  2018. with writer do
  2019. begin
  2020. WriteInteger(0); // Archive Version 0
  2021. WriteString(FName);
  2022. WriteInteger(FBoneID);
  2023. WriteInteger(Integer(FColor));
  2024. end;
  2025. end;
  2026. procedure TgxSkeletonBone.ReadFromFiler(reader: TgxVirtualReader);
  2027. var
  2028. archiveVersion, i: Integer;
  2029. begin
  2030. inherited ReadFromFiler(reader);
  2031. archiveVersion := reader.ReadInteger;
  2032. if archiveVersion = 0 then
  2033. with reader do
  2034. begin
  2035. FName := ReadString;
  2036. FBoneID := ReadInteger;
  2037. FColor := Cardinal(ReadInteger);
  2038. end
  2039. else
  2040. RaiseFilerException(archiveVersion);
  2041. for i := 0 to Count - 1 do
  2042. Items[i].FOwner := Self;
  2043. end;
  2044. procedure TgxSkeletonBone.BuildList(var mrci: TgxRenderContextInfo);
  2045. procedure IssueColor(Color: Cardinal);
  2046. begin
  2047. glColor4f(GetRValue(Color) / 255, GetGValue(Color) / 255, GetBValue(Color) / 255, ((Color shr 24) and 255) / 255);
  2048. end;
  2049. var
  2050. i: Integer;
  2051. begin
  2052. // point for self
  2053. mrci.gxStates.PointSize := 5;
  2054. glBegin(GL_POINTS);
  2055. IssueColor(Color);
  2056. glVertex3fv(@GlobalMatrix.W.X);
  2057. glEnd;
  2058. // parent-self bone line
  2059. if Owner is TgxSkeletonBone then
  2060. begin
  2061. glBegin(GL_LINES);
  2062. glVertex3fv(@TgxSkeletonBone(Owner).GlobalMatrix.W.X);
  2063. glVertex3fv(@GlobalMatrix.W.X);
  2064. glEnd;
  2065. end;
  2066. // render sub-bones
  2067. for i := 0 to Count - 1 do
  2068. Items[i].BuildList(mrci);
  2069. end;
  2070. function TgxSkeletonBone.GetSkeletonBone(Index: Integer): TgxSkeletonBone;
  2071. begin
  2072. Result := TgxSkeletonBone(list^[Index]);
  2073. end;
  2074. procedure TgxSkeletonBone.SetColor(const val: Cardinal);
  2075. begin
  2076. FColor := val;
  2077. end;
  2078. function TgxSkeletonBone.BoneByID(anID: Integer): TgxSkeletonBone;
  2079. begin
  2080. if BoneID = anID then
  2081. Result := Self
  2082. else
  2083. Result := inherited BoneByID(anID);
  2084. end;
  2085. function TgxSkeletonBone.BoneByName(const aName: string): TgxSkeletonBone;
  2086. begin
  2087. if Name = aName then
  2088. Result := Self
  2089. else
  2090. Result := inherited BoneByName(aName);
  2091. end;
  2092. procedure TgxSkeletonBone.Clean;
  2093. begin
  2094. BoneID := 0;
  2095. Name := '';
  2096. inherited;
  2097. end;
  2098. procedure TgxSkeletonBone.PrepareGlobalMatrices;
  2099. begin
  2100. if (Skeleton.FRagDollEnabled) then
  2101. Exit; // ragdoll
  2102. FGlobalMatrix := MatrixMultiply(Skeleton.CurrentFrame.LocalMatrixList^[BoneID], TgxSkeletonBoneList(Owner).FGlobalMatrix);
  2103. inherited;
  2104. end;
  2105. procedure TgxSkeletonBone.SetGlobalMatrix(Matrix: TMatrix4f); // ragdoll
  2106. begin
  2107. FGlobalMatrix := Matrix;
  2108. end;
  2109. procedure TgxSkeletonBone.SetGlobalMatrixForRagDoll(RagDollMatrix: TMatrix4f);
  2110. // ragdoll
  2111. begin
  2112. FGlobalMatrix := MatrixMultiply(RagDollMatrix, Skeleton.Owner.InvAbsoluteMatrix);
  2113. inherited;
  2114. end;
  2115. // ------------------
  2116. // ------------------ TgxSkeletonCollider ------------------
  2117. // ------------------
  2118. constructor TgxSkeletonCollider.Create;
  2119. begin
  2120. inherited;
  2121. FLocalMatrix := IdentityHmgMatrix;
  2122. FGlobalMatrix := IdentityHmgMatrix;
  2123. FAutoUpdate := True;
  2124. end;
  2125. constructor TgxSkeletonCollider.CreateOwned(aOwner: TgxSkeletonColliderList);
  2126. begin
  2127. Create;
  2128. FOwner := aOwner;
  2129. if Assigned(FOwner) then
  2130. FOwner.Add(Self);
  2131. end;
  2132. procedure TgxSkeletonCollider.WriteToFiler(writer: TgxVirtualWriter);
  2133. begin
  2134. inherited WriteToFiler(writer);
  2135. with writer do
  2136. begin
  2137. WriteInteger(0); // Archive Version 0
  2138. if Assigned(FBone) then
  2139. WriteInteger(FBone.BoneID)
  2140. else
  2141. WriteInteger(-1);
  2142. Write(FLocalMatrix, SizeOf(TMatrix4f));
  2143. end;
  2144. end;
  2145. procedure TgxSkeletonCollider.ReadFromFiler(reader: TgxVirtualReader);
  2146. var
  2147. archiveVersion: Integer;
  2148. begin
  2149. inherited ReadFromFiler(reader);
  2150. archiveVersion := reader.ReadInteger;
  2151. if archiveVersion = 0 then
  2152. with reader do
  2153. begin
  2154. FBoneID := ReadInteger;
  2155. Read(FLocalMatrix, SizeOf(TMatrix4f));
  2156. end
  2157. else
  2158. RaiseFilerException(archiveVersion);
  2159. end;
  2160. procedure TgxSkeletonCollider.AlignCollider;
  2161. var
  2162. mat: TMatrix4f;
  2163. begin
  2164. if Assigned(FBone) then
  2165. begin
  2166. if Owner.Owner is TgxSkeleton then
  2167. if TgxSkeleton(Owner.Owner).Owner is TgxBaseSceneObject then
  2168. mat := MatrixMultiply(FBone.GlobalMatrix, TgxBaseSceneObject(TgxSkeleton(Owner.Owner).Owner).AbsoluteMatrix)
  2169. else
  2170. mat := FBone.GlobalMatrix;
  2171. MatrixMultiply(FLocalMatrix, mat, FGlobalMatrix);
  2172. end
  2173. else
  2174. FGlobalMatrix := FLocalMatrix;
  2175. end;
  2176. procedure TgxSkeletonCollider.SetBone(const val: TgxSkeletonBone);
  2177. begin
  2178. if val <> FBone then
  2179. FBone := val;
  2180. end;
  2181. procedure TgxSkeletonCollider.SetLocalMatrix(const val: TMatrix4f);
  2182. begin
  2183. FLocalMatrix := val;
  2184. end;
  2185. // ------------------
  2186. // ------------------ TgxSkeletonColliderList ------------------
  2187. // ------------------
  2188. constructor TgxSkeletonColliderList.CreateOwned(aOwner: TPersistent);
  2189. begin
  2190. Create;
  2191. FOwner := aOwner;
  2192. end;
  2193. destructor TgxSkeletonColliderList.Destroy;
  2194. begin
  2195. Clear;
  2196. inherited;
  2197. end;
  2198. function TgxSkeletonColliderList.GetSkeletonCollider(Index: Integer): TgxSkeletonCollider;
  2199. begin
  2200. Result := TgxSkeletonCollider(inherited Get(index));
  2201. end;
  2202. procedure TgxSkeletonColliderList.ReadFromFiler(reader: TgxVirtualReader);
  2203. var
  2204. i: Integer;
  2205. begin
  2206. inherited;
  2207. for i := 0 to Count - 1 do
  2208. begin
  2209. Items[i].FOwner := Self;
  2210. if (Owner is TgxSkeleton) and (Items[i].FBoneID <> -1) then
  2211. Items[i].Bone := TgxSkeleton(Owner).BoneByID(Items[i].FBoneID);
  2212. end;
  2213. end;
  2214. procedure TgxSkeletonColliderList.Clear;
  2215. var
  2216. i: Integer;
  2217. begin
  2218. for i := 0 to Count - 1 do
  2219. begin
  2220. Items[i].FOwner := nil;
  2221. Items[i].Free;
  2222. end;
  2223. inherited;
  2224. end;
  2225. procedure TgxSkeletonColliderList.AlignColliders;
  2226. var
  2227. i: Integer;
  2228. begin
  2229. for i := 0 to Count - 1 do
  2230. if Items[i].AutoUpdate then
  2231. Items[i].AlignCollider;
  2232. end;
  2233. // ------------------
  2234. // ------------------ TgxSkeleton ------------------
  2235. // ------------------
  2236. constructor TgxSkeleton.CreateOwned(aOwner: TgxBaseMesh);
  2237. begin
  2238. FOwner := aOwner;
  2239. Create;
  2240. end;
  2241. constructor TgxSkeleton.Create;
  2242. begin
  2243. inherited Create;
  2244. FRootBones := TgxSkeletonRootBoneList.CreateOwned(Self);
  2245. FFrames := TgxSkeletonFrameList.CreateOwned(Self);
  2246. FColliders := TgxSkeletonColliderList.CreateOwned(Self);
  2247. end;
  2248. destructor TgxSkeleton.Destroy;
  2249. begin
  2250. FlushBoneByIDCache;
  2251. FCurrentFrame.Free;
  2252. FFrames.Free;
  2253. FRootBones.Free;
  2254. FColliders.Free;
  2255. inherited Destroy;
  2256. end;
  2257. procedure TgxSkeleton.WriteToFiler(writer: TgxVirtualWriter);
  2258. begin
  2259. inherited WriteToFiler(writer);
  2260. with writer do
  2261. begin
  2262. if FColliders.Count > 0 then
  2263. WriteInteger(1) // Archive Version 1 : with colliders
  2264. else
  2265. WriteInteger(0); // Archive Version 0
  2266. FRootBones.WriteToFiler(writer);
  2267. FFrames.WriteToFiler(writer);
  2268. if FColliders.Count > 0 then
  2269. FColliders.WriteToFiler(writer);
  2270. end;
  2271. end;
  2272. procedure TgxSkeleton.ReadFromFiler(reader: TgxVirtualReader);
  2273. var
  2274. archiveVersion: Integer;
  2275. begin
  2276. inherited ReadFromFiler(reader);
  2277. archiveVersion := reader.ReadInteger;
  2278. if (archiveVersion = 0) or (archiveVersion = 1) then
  2279. with reader do
  2280. begin
  2281. FRootBones.ReadFromFiler(reader);
  2282. FFrames.ReadFromFiler(reader);
  2283. if (archiveVersion = 1) then
  2284. FColliders.ReadFromFiler(reader);
  2285. end
  2286. else
  2287. RaiseFilerException(archiveVersion);
  2288. end;
  2289. procedure TgxSkeleton.SetRootBones(const val: TgxSkeletonRootBoneList);
  2290. begin
  2291. FRootBones.Assign(val);
  2292. end;
  2293. procedure TgxSkeleton.SetFrames(const val: TgxSkeletonFrameList);
  2294. begin
  2295. FFrames.Assign(val);
  2296. end;
  2297. function TgxSkeleton.GetCurrentFrame: TgxSkeletonFrame;
  2298. begin
  2299. if not Assigned(FCurrentFrame) then
  2300. FCurrentFrame := TgxSkeletonFrame(FFrames.Items[0].CreateClone);
  2301. Result := FCurrentFrame;
  2302. end;
  2303. procedure TgxSkeleton.SetCurrentFrame(val: TgxSkeletonFrame);
  2304. begin
  2305. if Assigned(FCurrentFrame) then
  2306. FCurrentFrame.Free;
  2307. FCurrentFrame := TgxSkeletonFrame(val.CreateClone);
  2308. end;
  2309. procedure TgxSkeleton.SetColliders(const val: TgxSkeletonColliderList);
  2310. begin
  2311. FColliders.Assign(val);
  2312. end;
  2313. procedure TgxSkeleton.FlushBoneByIDCache;
  2314. begin
  2315. FBonesByIDCache.Free;
  2316. FBonesByIDCache := nil;
  2317. end;
  2318. function TgxSkeleton.BoneByID(anID: Integer): TgxSkeletonBone;
  2319. procedure CollectBones(Bone: TgxSkeletonBone);
  2320. var
  2321. i: Integer;
  2322. begin
  2323. if Bone.BoneID >= FBonesByIDCache.Count then
  2324. FBonesByIDCache.Count := Bone.BoneID + 1;
  2325. FBonesByIDCache[Bone.BoneID] := Bone;
  2326. for i := 0 to Bone.Count - 1 do
  2327. CollectBones(Bone[i]);
  2328. end;
  2329. var
  2330. i: Integer;
  2331. begin
  2332. if not Assigned(FBonesByIDCache) then
  2333. begin
  2334. FBonesByIDCache := TList.Create;
  2335. for i := 0 to RootBones.Count - 1 do
  2336. CollectBones(RootBones[i]);
  2337. end;
  2338. Result := TgxSkeletonBone(FBonesByIDCache[anID])
  2339. end;
  2340. function TgxSkeleton.BoneByName(const aName: string): TgxSkeletonBone;
  2341. begin
  2342. Result := RootBones.BoneByName(aName);
  2343. end;
  2344. function TgxSkeleton.BoneCount: Integer;
  2345. begin
  2346. Result := RootBones.BoneCount;
  2347. end;
  2348. procedure TgxSkeleton.MorphTo(frameIndex: Integer);
  2349. begin
  2350. CurrentFrame := Frames[frameIndex];
  2351. end;
  2352. procedure TgxSkeleton.MorphTo(frame: TgxSkeletonFrame);
  2353. begin
  2354. CurrentFrame := frame;
  2355. end;
  2356. procedure TgxSkeleton.Lerp(frameIndex1, frameIndex2: Integer; lerpFactor: Single);
  2357. begin
  2358. if Assigned(FCurrentFrame) then
  2359. FCurrentFrame.Free;
  2360. FCurrentFrame := TgxSkeletonFrame.Create;
  2361. FCurrentFrame.TransformMode := Frames[frameIndex1].TransformMode;
  2362. with FCurrentFrame do
  2363. begin
  2364. Position.Lerp(Frames[frameIndex1].Position, Frames[frameIndex2].Position, lerpFactor);
  2365. case TransformMode of
  2366. sftRotation:
  2367. Rotation.AngleLerp(Frames[frameIndex1].Rotation, Frames[frameIndex2].Rotation, lerpFactor);
  2368. sftQuaternion:
  2369. Quaternion.Lerp(Frames[frameIndex1].Quaternion, Frames[frameIndex2].Quaternion, lerpFactor);
  2370. end;
  2371. end;
  2372. end;
  2373. procedure TgxSkeleton.BlendedLerps(const lerpInfos: array of TgxBlendedLerpInfo);
  2374. var
  2375. i, n: Integer;
  2376. blendPositions: TgxAffineVectorList;
  2377. blendRotations: TgxAffineVectorList;
  2378. blendQuaternions: TQuaternionList;
  2379. begin
  2380. n := High(lerpInfos) - Low(lerpInfos) + 1;
  2381. Assert(n >= 1);
  2382. i := Low(lerpInfos);
  2383. if n = 1 then
  2384. begin
  2385. // use fast lerp (no blend)
  2386. with lerpInfos[i] do
  2387. Lerp(frameIndex1, frameIndex2, lerpFactor);
  2388. end
  2389. else
  2390. begin
  2391. if Assigned(FCurrentFrame) then
  2392. FCurrentFrame.Free;
  2393. FCurrentFrame := TgxSkeletonFrame.Create;
  2394. FCurrentFrame.TransformMode := Frames[lerpInfos[i].frameIndex1].TransformMode;
  2395. with FCurrentFrame do
  2396. begin
  2397. blendPositions := TgxAffineVectorList.Create;
  2398. // lerp first item separately
  2399. Position.Lerp(Frames[lerpInfos[i].frameIndex1].Position, Frames[lerpInfos[i].frameIndex2].Position,
  2400. lerpInfos[i].lerpFactor);
  2401. if lerpInfos[i].weight <> 1 then
  2402. Position.Scale(lerpInfos[i].weight);
  2403. Inc(i);
  2404. // combine the other items
  2405. while i <= High(lerpInfos) do
  2406. begin
  2407. if not Assigned(lerpInfos[i].externalPositions) then
  2408. begin
  2409. blendPositions.Lerp(Frames[lerpInfos[i].frameIndex1].Position, Frames[lerpInfos[i].frameIndex2].Position,
  2410. lerpInfos[i].lerpFactor);
  2411. Position.AngleCombine(blendPositions, 1);
  2412. end
  2413. else
  2414. Position.Combine(lerpInfos[i].externalPositions, 1);
  2415. Inc(i);
  2416. end;
  2417. blendPositions.Free;
  2418. i := Low(lerpInfos);
  2419. case TransformMode of
  2420. sftRotation:
  2421. begin
  2422. blendRotations := TgxAffineVectorList.Create;
  2423. // lerp first item separately
  2424. Rotation.AngleLerp(Frames[lerpInfos[i].frameIndex1].Rotation, Frames[lerpInfos[i].frameIndex2].Rotation,
  2425. lerpInfos[i].lerpFactor);
  2426. Inc(i);
  2427. // combine the other items
  2428. while i <= High(lerpInfos) do
  2429. begin
  2430. if not Assigned(lerpInfos[i].externalRotations) then
  2431. begin
  2432. blendRotations.AngleLerp(Frames[lerpInfos[i].frameIndex1].Rotation, Frames[lerpInfos[i].frameIndex2].Rotation,
  2433. lerpInfos[i].lerpFactor);
  2434. Rotation.AngleCombine(blendRotations, 1);
  2435. end
  2436. else
  2437. Rotation.AngleCombine(lerpInfos[i].externalRotations, 1);
  2438. Inc(i);
  2439. end;
  2440. blendRotations.Free;
  2441. end;
  2442. sftQuaternion:
  2443. begin
  2444. blendQuaternions := TQuaternionList.Create;
  2445. // Initial frame lerp
  2446. Quaternion.Lerp(Frames[lerpInfos[i].frameIndex1].Quaternion, Frames[lerpInfos[i].frameIndex2].Quaternion,
  2447. lerpInfos[i].lerpFactor);
  2448. Inc(i);
  2449. // Combine the lerped frames together
  2450. while i <= High(lerpInfos) do
  2451. begin
  2452. if not Assigned(lerpInfos[i].externalQuaternions) then
  2453. begin
  2454. blendQuaternions.Lerp(Frames[lerpInfos[i].frameIndex1].Quaternion, Frames[lerpInfos[i].frameIndex2].Quaternion,
  2455. lerpInfos[i].lerpFactor);
  2456. Quaternion.Combine(blendQuaternions, 1);
  2457. end
  2458. else
  2459. Quaternion.Combine(lerpInfos[i].externalQuaternions, 1);
  2460. Inc(i);
  2461. end;
  2462. blendQuaternions.Free;
  2463. end;
  2464. end;
  2465. end;
  2466. end;
  2467. end;
  2468. procedure TgxSkeleton.MakeSkeletalTranslationStatic(startFrame, endFrame: Integer);
  2469. var
  2470. delta: TAffineVector;
  2471. i: Integer;
  2472. f: Single;
  2473. begin
  2474. if endFrame <= startFrame then
  2475. Exit;
  2476. delta := VectorSubtract(Frames[endFrame].Position[0], Frames[startFrame].Position[0]);
  2477. f := -1 / (endFrame - startFrame);
  2478. for i := startFrame to endFrame do
  2479. Frames[i].Position[0] := VectorCombine(Frames[i].Position[0], delta, 1, (i - startFrame) * f);
  2480. end;
  2481. procedure TgxSkeleton.MakeSkeletalRotationDelta(startFrame, endFrame: Integer);
  2482. var
  2483. i, j: Integer;
  2484. v: TAffineVector;
  2485. begin
  2486. if endFrame <= startFrame then
  2487. Exit;
  2488. for i := startFrame to endFrame do
  2489. begin
  2490. for j := 0 to Frames[i].Position.Count - 1 do
  2491. begin
  2492. Frames[i].Position[j] := NullVector;
  2493. v := VectorSubtract(Frames[i].Rotation[j], Frames[0].Rotation[j]);
  2494. if VectorNorm(v) < 1E-6 then
  2495. Frames[i].Rotation[j] := NullVector
  2496. else
  2497. Frames[i].Rotation[j] := v;
  2498. end;
  2499. end;
  2500. end;
  2501. procedure TgxSkeleton.MorphMesh(normalize: Boolean);
  2502. var
  2503. i: Integer;
  2504. Mesh: TgxBaseMeshObject;
  2505. begin
  2506. if Owner.MeshObjects.Count > 0 then
  2507. begin
  2508. RootBones.PrepareGlobalMatrices;
  2509. if Colliders.Count > 0 then
  2510. Colliders.AlignColliders;
  2511. if FMorphInvisibleParts then
  2512. for i := 0 to Owner.MeshObjects.Count - 1 do
  2513. begin
  2514. Mesh := Owner.MeshObjects.Items[i];
  2515. if (Mesh is TgxSkeletonMeshObject) then
  2516. TgxSkeletonMeshObject(Mesh).ApplyCurrentSkeletonFrame(normalize);
  2517. end
  2518. else
  2519. for i := 0 to Owner.MeshObjects.Count - 1 do
  2520. begin
  2521. Mesh := Owner.MeshObjects.Items[i];
  2522. if (Mesh is TgxSkeletonMeshObject) and Mesh.Visible then
  2523. TgxSkeletonMeshObject(Mesh).ApplyCurrentSkeletonFrame(normalize);
  2524. end
  2525. end;
  2526. end;
  2527. procedure TgxSkeleton.Synchronize(reference: TgxSkeleton);
  2528. begin
  2529. CurrentFrame.Assign(reference.CurrentFrame);
  2530. MorphMesh(True);
  2531. end;
  2532. procedure TgxSkeleton.Clear;
  2533. begin
  2534. FlushBoneByIDCache;
  2535. RootBones.Clean;
  2536. Frames.Clear;
  2537. FCurrentFrame.Free;
  2538. FCurrentFrame := nil;
  2539. FColliders.Clear;
  2540. end;
  2541. procedure TgxSkeleton.StartRagdoll; // ragdoll
  2542. var
  2543. i: Integer;
  2544. Mesh: TgxBaseMeshObject;
  2545. begin
  2546. if FRagDollEnabled then
  2547. Exit
  2548. else
  2549. FRagDollEnabled := True;
  2550. if Owner.MeshObjects.Count > 0 then
  2551. begin
  2552. for i := 0 to Owner.MeshObjects.Count - 1 do
  2553. begin
  2554. Mesh := Owner.MeshObjects.Items[i];
  2555. if Mesh is TgxSkeletonMeshObject then
  2556. begin
  2557. TgxSkeletonMeshObject(Mesh).BackupBoneMatrixInvertedMeshes;
  2558. TgxSkeletonMeshObject(Mesh).PrepareBoneMatrixInvertedMeshes;
  2559. end;
  2560. end;
  2561. end;
  2562. end;
  2563. procedure TgxSkeleton.StopRagdoll; // ragdoll
  2564. var
  2565. i: Integer;
  2566. Mesh: TgxBaseMeshObject;
  2567. begin
  2568. FRagDollEnabled := False;
  2569. if Owner.MeshObjects.Count > 0 then
  2570. begin
  2571. for i := 0 to Owner.MeshObjects.Count - 1 do
  2572. begin
  2573. Mesh := Owner.MeshObjects.Items[i];
  2574. if Mesh is TgxSkeletonMeshObject then
  2575. TgxSkeletonMeshObject(Mesh).RestoreBoneMatrixInvertedMeshes;
  2576. end;
  2577. end;
  2578. end;
  2579. // ------------------
  2580. // ------------------ TgxMeshObject ------------------
  2581. // ------------------
  2582. constructor TgxMeshObject.CreateOwned(aOwner: TgxMeshObjectList);
  2583. begin
  2584. FOwner := aOwner;
  2585. Create;
  2586. if Assigned(FOwner) then
  2587. FOwner.Add(Self);
  2588. end;
  2589. constructor TgxMeshObject.Create;
  2590. begin
  2591. FMode := momTriangles;
  2592. FTexCoords := TgxAffineVectorList.Create;
  2593. FLightMapTexCoords := TgxAffineVectorList.Create;
  2594. FColors := TgxVectorList.Create;
  2595. FFaceGroups := TgxFaceGroups.CreateOwned(Self);
  2596. FTexCoordsEx := TList.Create;
  2597. FTangentsTexCoordIndex := 1;
  2598. FBinormalsTexCoordIndex := 2;
  2599. FUseVBO := vVectorFileObjectsEnableVBOByDefault;
  2600. inherited;
  2601. end;
  2602. destructor TgxMeshObject.Destroy;
  2603. var
  2604. i: Integer;
  2605. begin
  2606. FVerticesVBO.Free;
  2607. FNormalsVBO.Free;
  2608. FColorsVBO.Free;
  2609. for i := 0 to high(FTexCoordsVBO) do
  2610. FTexCoordsVBO[i].Free;
  2611. FLightmapTexCoordsVBO.Free;
  2612. FFaceGroups.Free;
  2613. FColors.Free;
  2614. FTexCoords.Free;
  2615. FLightMapTexCoords.Free;
  2616. for i := 0 to FTexCoordsEx.Count - 1 do
  2617. TgxVectorList(FTexCoordsEx[i]).Free;
  2618. FTexCoordsEx.Free;
  2619. if Assigned(FOwner) then
  2620. FOwner.Remove(Self);
  2621. inherited;
  2622. end;
  2623. procedure TgxMeshObject.Assign(Source: TPersistent);
  2624. var
  2625. i: Integer;
  2626. begin
  2627. inherited Assign(Source);
  2628. if Source is TgxMeshObject then
  2629. begin
  2630. FTexCoords.Assign(TgxMeshObject(Source).FTexCoords);
  2631. FLightMapTexCoords.Assign(TgxMeshObject(Source).FLightMapTexCoords);
  2632. FColors.Assign(TgxMeshObject(Source).FColors);
  2633. FFaceGroups.Assign(TgxMeshObject(Source).FFaceGroups);
  2634. FMode := TgxMeshObject(Source).FMode;
  2635. FRenderingOptions := TgxMeshObject(Source).FRenderingOptions;
  2636. FBinormalsTexCoordIndex := TgxMeshObject(Source).FBinormalsTexCoordIndex;
  2637. FTangentsTexCoordIndex := TgxMeshObject(Source).FTangentsTexCoordIndex;
  2638. // Clear FTexCoordsEx.
  2639. for i := 0 to FTexCoordsEx.Count - 1 do
  2640. TgxVectorList(FTexCoordsEx[i]).Free;
  2641. FTexCoordsEx.Count := TgxMeshObject(Source).FTexCoordsEx.Count;
  2642. // Fill FTexCoordsEx.
  2643. for i := 0 to FTexCoordsEx.Count - 1 do
  2644. begin
  2645. FTexCoordsEx[i] := TgxVectorList.Create;
  2646. TgxVectorList(FTexCoordsEx[i]).Assign(TgxMeshObject(Source).FTexCoordsEx[i]);
  2647. end;
  2648. end;
  2649. end;
  2650. procedure TgxMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  2651. var
  2652. i: Integer;
  2653. begin
  2654. inherited WriteToFiler(writer);
  2655. with writer do
  2656. begin
  2657. WriteInteger(3); // Archive Version 3
  2658. FTexCoords.WriteToFiler(writer);
  2659. FLightMapTexCoords.WriteToFiler(writer);
  2660. FColors.WriteToFiler(writer);
  2661. FFaceGroups.WriteToFiler(writer);
  2662. WriteInteger(Integer(FMode));
  2663. WriteInteger(SizeOf(FRenderingOptions));
  2664. Write(FRenderingOptions, SizeOf(FRenderingOptions));
  2665. WriteInteger(FTexCoordsEx.Count);
  2666. for i := 0 to FTexCoordsEx.Count - 1 do
  2667. TexCoordsEx[i].WriteToFiler(writer);
  2668. WriteInteger(BinormalsTexCoordIndex);
  2669. WriteInteger(TangentsTexCoordIndex);
  2670. end;
  2671. end;
  2672. procedure TgxMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  2673. var
  2674. i, Count, archiveVersion: Integer;
  2675. lOldLightMapTexCoords: TgxTexPointList;
  2676. tc: TTexPoint;
  2677. size, ro: Integer;
  2678. begin
  2679. inherited ReadFromFiler(reader);
  2680. archiveVersion := reader.ReadInteger;
  2681. if archiveVersion in [0 .. 3] then
  2682. with reader do
  2683. begin
  2684. FTexCoords.ReadFromFiler(reader);
  2685. if archiveVersion = 0 then
  2686. begin
  2687. // FLightMapTexCoords did not exist back than.
  2688. FLightMapTexCoords.Clear;
  2689. end
  2690. else if (archiveVersion = 1) or (archiveVersion = 2) then
  2691. begin
  2692. lOldLightMapTexCoords := TgxTexPointList.CreateFromFiler(reader);
  2693. for i := 0 to lOldLightMapTexCoords.Count - 1 do
  2694. begin
  2695. tc := lOldLightMapTexCoords[i];
  2696. FLightMapTexCoords.Add(tc.s, tc.t);
  2697. end;
  2698. lOldLightMapTexCoords.Free;
  2699. end
  2700. else
  2701. begin
  2702. // Load FLightMapTexCoords the normal way.
  2703. FLightMapTexCoords.ReadFromFiler(reader);
  2704. end;
  2705. FColors.ReadFromFiler(reader);
  2706. FFaceGroups.ReadFromFiler(reader);
  2707. FMode := TgxMeshObjectMode(ReadInteger);
  2708. size := ReadInteger;
  2709. ro := 0;
  2710. Read(ro, size);
  2711. FRenderingOptions := TgxMeshObjectRenderingOptions(Byte(ro));
  2712. if archiveVersion >= 2 then
  2713. begin
  2714. Count := ReadInteger;
  2715. for i := 0 to Count - 1 do
  2716. TexCoordsEx[i].ReadFromFiler(reader);
  2717. BinormalsTexCoordIndex := ReadInteger;
  2718. TangentsTexCoordIndex := ReadInteger;
  2719. end;
  2720. end
  2721. else
  2722. RaiseFilerException(archiveVersion);
  2723. end;
  2724. procedure TgxMeshObject.Clear;
  2725. var
  2726. i: Integer;
  2727. begin
  2728. inherited;
  2729. FFaceGroups.Clear;
  2730. FColors.Clear;
  2731. FTexCoords.Clear;
  2732. FLightMapTexCoords.Clear;
  2733. for i := 0 to FTexCoordsEx.Count - 1 do
  2734. TexCoordsEx[i].Clear;
  2735. end;
  2736. function TgxMeshObject.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  2737. : TgxAffineVectorList;
  2738. begin
  2739. case mode of
  2740. momTriangles:
  2741. begin
  2742. Result := inherited ExtractTriangles;
  2743. if Assigned(texCoords) then
  2744. texCoords.Assign(Self.texCoords);
  2745. if Assigned(normals) then
  2746. normals.Assign(Self.normals);
  2747. end;
  2748. momTriangleStrip:
  2749. begin
  2750. Result := TgxAffineVectorList.Create;
  2751. ConvertStripToList(Vertices, Result);
  2752. if Assigned(texCoords) then
  2753. ConvertStripToList(Self.texCoords, texCoords);
  2754. if Assigned(normals) then
  2755. ConvertStripToList(Self.normals, normals);
  2756. end;
  2757. momFaceGroups:
  2758. begin
  2759. Result := TgxAffineVectorList.Create;
  2760. FaceGroups.AddToTriangles(Result, texCoords, normals);
  2761. end;
  2762. else
  2763. Result := nil;
  2764. Assert(False);
  2765. end;
  2766. end;
  2767. function TgxMeshObject.TriangleCount: Integer;
  2768. var
  2769. i: Integer;
  2770. begin
  2771. case mode of
  2772. momTriangles:
  2773. Result := (Vertices.Count div 3);
  2774. momTriangleStrip:
  2775. begin
  2776. Result := Vertices.Count - 2;
  2777. if Result < 0 then
  2778. Result := 0;
  2779. end;
  2780. momFaceGroups:
  2781. begin
  2782. Result := 0;
  2783. for i := 0 to FaceGroups.Count - 1 do
  2784. Result := Result + FaceGroups[i].TriangleCount;
  2785. end;
  2786. else
  2787. Result := 0;
  2788. Assert(False);
  2789. end;
  2790. end;
  2791. procedure TgxMeshObject.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  2792. begin
  2793. FaceGroups.PrepareMaterialLibraryCache(matLib);
  2794. end;
  2795. procedure TgxMeshObject.DropMaterialLibraryCache;
  2796. begin
  2797. FaceGroups.DropMaterialLibraryCache;
  2798. end;
  2799. procedure TgxMeshObject.GetExtents(out min, max: TAffineVector);
  2800. begin
  2801. if FVertices.Revision <> FExtentCacheRevision then
  2802. begin
  2803. FVertices.GetExtents(FExtentCache.min, FExtentCache.max);
  2804. FExtentCacheRevision := FVertices.Revision;
  2805. end;
  2806. min := FExtentCache.min;
  2807. max := FExtentCache.max;
  2808. end;
  2809. procedure TgxMeshObject.GetExtents(out aabb: TAABB);
  2810. begin
  2811. if FVertices.Revision <> FExtentCacheRevision then
  2812. begin
  2813. FVertices.GetExtents(FExtentCache.min, FExtentCache.max);
  2814. FExtentCacheRevision := FVertices.Revision;
  2815. end;
  2816. aabb := FExtentCache;
  2817. end;
  2818. function TgxMeshObject.GetBarycenter: TVector4f;
  2819. var
  2820. dMin, dMax: TAffineVector;
  2821. begin
  2822. GetExtents(dMin, dMax);
  2823. Result.X := (dMin.X + dMax.X) / 2;
  2824. Result.Y := (dMin.Y + dMax.Y) / 2;
  2825. Result.Z := (dMin.Z + dMax.Z) / 2;
  2826. Result.W := 0;
  2827. end;
  2828. procedure TgxMeshObject.Prepare;
  2829. var
  2830. i: Integer;
  2831. begin
  2832. ValidBuffers := [];
  2833. for i := 0 to FaceGroups.Count - 1 do
  2834. FaceGroups[i].Prepare;
  2835. end;
  2836. function TgxMeshObject.PointInObject(const aPoint: TAffineVector): Boolean;
  2837. var
  2838. min, max: TAffineVector;
  2839. begin
  2840. GetExtents(min, max);
  2841. Result := (aPoint.X >= min.X) and (aPoint.Y >= min.Y) and (aPoint.Z >= min.Z) and (aPoint.X <= max.X) and (aPoint.Y <= max.Y)
  2842. and (aPoint.Z <= max.Z);
  2843. end;
  2844. procedure TgxMeshObject.SetTexCoords(const val: TgxAffineVectorList);
  2845. begin
  2846. FTexCoords.Assign(val);
  2847. end;
  2848. procedure TgxMeshObject.SetLightmapTexCoords(const val: TgxAffineVectorList);
  2849. begin
  2850. FLightMapTexCoords.Assign(val);
  2851. end;
  2852. procedure TgxMeshObject.SetColors(const val: TgxVectorList);
  2853. begin
  2854. FColors.Assign(val);
  2855. end;
  2856. procedure TgxMeshObject.SetTexCoordsEx(Index: Integer; const val: TgxVectorList);
  2857. begin
  2858. TexCoordsEx[index].Assign(val);
  2859. end;
  2860. function TgxMeshObject.GetTexCoordsEx(Index: Integer): TgxVectorList;
  2861. var
  2862. i: Integer;
  2863. begin
  2864. if index > FTexCoordsEx.Count - 1 then
  2865. for i := FTexCoordsEx.Count - 1 to index do
  2866. FTexCoordsEx.Add(TgxVectorList.Create);
  2867. Result := TgxVectorList(FTexCoordsEx[index]);
  2868. end;
  2869. procedure TgxMeshObject.SetBinormals(const val: TgxVectorList);
  2870. begin
  2871. Binormals.Assign(val);
  2872. end;
  2873. function TgxMeshObject.GetBinormals: TgxVectorList;
  2874. begin
  2875. Result := TexCoordsEx[BinormalsTexCoordIndex];
  2876. end;
  2877. procedure TgxMeshObject.SetBinormalsTexCoordIndex(const val: Integer);
  2878. begin
  2879. Assert(val >= 0);
  2880. if val <> FBinormalsTexCoordIndex then
  2881. begin
  2882. FBinormalsTexCoordIndex := val;
  2883. end;
  2884. end;
  2885. procedure TgxMeshObject.SetTangents(const val: TgxVectorList);
  2886. begin
  2887. Tangents.Assign(val);
  2888. end;
  2889. function TgxMeshObject.GetTangents: TgxVectorList;
  2890. begin
  2891. Result := TexCoordsEx[TangentsTexCoordIndex];
  2892. end;
  2893. procedure TgxMeshObject.SetTangentsTexCoordIndex(const val: Integer);
  2894. begin
  2895. Assert(val >= 0);
  2896. if val <> FTangentsTexCoordIndex then
  2897. begin
  2898. FTangentsTexCoordIndex := val;
  2899. end;
  2900. end;
  2901. procedure TgxMeshObject.GetTriangleData(tri: Integer; list: TgxAffineVectorList; var v0, v1, v2: TAffineVector);
  2902. var
  2903. i, LastCount, Count: Integer;
  2904. fg: TfgxVertexIndexList;
  2905. begin
  2906. case mode of
  2907. momTriangles:
  2908. begin
  2909. v0 := list[3 * tri];
  2910. v1 := list[3 * tri + 1];
  2911. v2 := list[3 * tri + 2];
  2912. end;
  2913. momTriangleStrip:
  2914. begin
  2915. v0 := list[tri];
  2916. v1 := list[tri + 1];
  2917. v2 := list[tri + 2];
  2918. end;
  2919. momFaceGroups:
  2920. begin
  2921. Count := 0;
  2922. for i := 0 to FaceGroups.Count - 1 do
  2923. begin
  2924. LastCount := Count;
  2925. fg := TfgxVertexIndexList(FaceGroups[i]);
  2926. Count := Count + fg.TriangleCount;
  2927. if Count > tri then
  2928. begin
  2929. Count := tri - LastCount;
  2930. case fg.mode of
  2931. fgmmTriangles, fgmmFlatTriangles:
  2932. begin
  2933. v0 := list[fg.vertexIndices[3 * Count]];
  2934. v1 := list[fg.vertexIndices[3 * Count + 1]];
  2935. v2 := list[fg.vertexIndices[3 * Count + 2]];
  2936. end;
  2937. fgmmTriangleStrip:
  2938. begin
  2939. v0 := list[fg.vertexIndices[Count]];
  2940. v1 := list[fg.vertexIndices[Count + 1]];
  2941. v2 := list[fg.vertexIndices[Count + 2]];
  2942. end;
  2943. fgmmTriangleFan:
  2944. begin
  2945. v0 := list[fg.vertexIndices[0]];
  2946. v1 := list[fg.vertexIndices[Count + 1]];
  2947. v2 := list[fg.vertexIndices[Count + 2]];
  2948. end;
  2949. fgmmQuads:
  2950. begin
  2951. if Count mod 2 = 0 then
  2952. begin
  2953. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  2954. v1 := list[fg.vertexIndices[4 * (Count div 2) + 1]];
  2955. v2 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  2956. end
  2957. else
  2958. begin
  2959. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  2960. v1 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  2961. v2 := list[fg.vertexIndices[4 * (Count div 2) + 3]];
  2962. end;
  2963. end;
  2964. else
  2965. Assert(False);
  2966. end;
  2967. Break;
  2968. end;
  2969. end;
  2970. end;
  2971. else
  2972. Assert(False);
  2973. end;
  2974. end;
  2975. procedure TgxMeshObject.GetTriangleData(tri: Integer; list: TgxVectorList; var v0, v1, v2: TVector4f);
  2976. var
  2977. i, LastCount, Count: Integer;
  2978. fg: TfgxVertexIndexList;
  2979. begin
  2980. case mode of
  2981. momTriangles:
  2982. begin
  2983. v0 := list[3 * tri];
  2984. v1 := list[3 * tri + 1];
  2985. v2 := list[3 * tri + 2];
  2986. end;
  2987. momTriangleStrip:
  2988. begin
  2989. v0 := list[tri];
  2990. v1 := list[tri + 1];
  2991. v2 := list[tri + 2];
  2992. end;
  2993. momFaceGroups:
  2994. begin
  2995. Count := 0;
  2996. for i := 0 to FaceGroups.Count - 1 do
  2997. begin
  2998. LastCount := Count;
  2999. fg := TfgxVertexIndexList(FaceGroups[i]);
  3000. Count := Count + fg.TriangleCount;
  3001. if Count > tri then
  3002. begin
  3003. Count := tri - LastCount;
  3004. case fg.mode of
  3005. fgmmTriangles, fgmmFlatTriangles:
  3006. begin
  3007. v0 := list[fg.vertexIndices[3 * Count]];
  3008. v1 := list[fg.vertexIndices[3 * Count + 1]];
  3009. v2 := list[fg.vertexIndices[3 * Count + 2]];
  3010. end;
  3011. fgmmTriangleStrip:
  3012. begin
  3013. v0 := list[fg.vertexIndices[Count]];
  3014. v1 := list[fg.vertexIndices[Count + 1]];
  3015. v2 := list[fg.vertexIndices[Count + 2]];
  3016. end;
  3017. fgmmTriangleFan:
  3018. begin
  3019. v0 := list[fg.vertexIndices[0]];
  3020. v1 := list[fg.vertexIndices[Count + 1]];
  3021. v2 := list[fg.vertexIndices[Count + 2]];
  3022. end;
  3023. fgmmQuads:
  3024. begin
  3025. if Count mod 2 = 0 then
  3026. begin
  3027. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  3028. v1 := list[fg.vertexIndices[4 * (Count div 2) + 1]];
  3029. v2 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  3030. end
  3031. else
  3032. begin
  3033. v0 := list[fg.vertexIndices[4 * (Count div 2)]];
  3034. v1 := list[fg.vertexIndices[4 * (Count div 2) + 2]];
  3035. v2 := list[fg.vertexIndices[4 * (Count div 2) + 3]];
  3036. end;
  3037. end;
  3038. else
  3039. Assert(False);
  3040. end;
  3041. Break;
  3042. end;
  3043. end;
  3044. end;
  3045. else
  3046. Assert(False);
  3047. end;
  3048. end;
  3049. procedure TgxMeshObject.SetTriangleData(tri: Integer; list: TgxAffineVectorList; const v0, v1, v2: TAffineVector);
  3050. var
  3051. i, LastCount, Count: Integer;
  3052. fg: TfgxVertexIndexList;
  3053. begin
  3054. case mode of
  3055. momTriangles:
  3056. begin
  3057. list[3 * tri] := v0;
  3058. list[3 * tri + 1] := v1;
  3059. list[3 * tri + 2] := v2;
  3060. end;
  3061. momTriangleStrip:
  3062. begin
  3063. list[tri] := v0;
  3064. list[tri + 1] := v1;
  3065. list[tri + 2] := v2;
  3066. end;
  3067. momFaceGroups:
  3068. begin
  3069. Count := 0;
  3070. for i := 0 to FaceGroups.Count - 1 do
  3071. begin
  3072. LastCount := Count;
  3073. fg := TfgxVertexIndexList(FaceGroups[i]);
  3074. Count := Count + fg.TriangleCount;
  3075. if Count > tri then
  3076. begin
  3077. Count := tri - LastCount;
  3078. case fg.mode of
  3079. fgmmTriangles, fgmmFlatTriangles:
  3080. begin
  3081. list[fg.vertexIndices[3 * Count]] := v0;
  3082. list[fg.vertexIndices[3 * Count + 1]] := v1;
  3083. list[fg.vertexIndices[3 * Count + 2]] := v2;
  3084. end;
  3085. fgmmTriangleStrip:
  3086. begin
  3087. list[fg.vertexIndices[Count]] := v0;
  3088. list[fg.vertexIndices[Count + 1]] := v1;
  3089. list[fg.vertexIndices[Count + 2]] := v2;
  3090. end;
  3091. fgmmTriangleFan:
  3092. begin
  3093. list[fg.vertexIndices[0]] := v0;
  3094. list[fg.vertexIndices[Count + 1]] := v1;
  3095. list[fg.vertexIndices[Count + 2]] := v2;
  3096. end;
  3097. fgmmQuads:
  3098. begin
  3099. if Count mod 2 = 0 then
  3100. begin
  3101. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3102. list[fg.vertexIndices[4 * (Count div 2) + 1]] := v1;
  3103. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v2;
  3104. end
  3105. else
  3106. begin
  3107. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3108. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v1;
  3109. list[fg.vertexIndices[4 * (Count div 2) + 3]] := v2;
  3110. end;
  3111. end;
  3112. else
  3113. Assert(False);
  3114. end;
  3115. Break;
  3116. end;
  3117. end;
  3118. end;
  3119. else
  3120. Assert(False);
  3121. end;
  3122. end;
  3123. procedure TgxMeshObject.SetTriangleData(tri: Integer; list: TgxVectorList; const v0, v1, v2: TVector4f);
  3124. var
  3125. i, LastCount, Count: Integer;
  3126. fg: TfgxVertexIndexList;
  3127. begin
  3128. case mode of
  3129. momTriangles:
  3130. begin
  3131. list[3 * tri] := v0;
  3132. list[3 * tri + 1] := v1;
  3133. list[3 * tri + 2] := v2;
  3134. end;
  3135. momTriangleStrip:
  3136. begin
  3137. list[tri] := v0;
  3138. list[tri + 1] := v1;
  3139. list[tri + 2] := v2;
  3140. end;
  3141. momFaceGroups:
  3142. begin
  3143. Count := 0;
  3144. for i := 0 to FaceGroups.Count - 1 do
  3145. begin
  3146. LastCount := Count;
  3147. fg := TfgxVertexIndexList(FaceGroups[i]);
  3148. Count := Count + fg.TriangleCount;
  3149. if Count > tri then
  3150. begin
  3151. Count := tri - LastCount;
  3152. case fg.mode of
  3153. fgmmTriangles, fgmmFlatTriangles:
  3154. begin
  3155. list[fg.vertexIndices[3 * Count]] := v0;
  3156. list[fg.vertexIndices[3 * Count + 1]] := v1;
  3157. list[fg.vertexIndices[3 * Count + 2]] := v2;
  3158. end;
  3159. fgmmTriangleStrip:
  3160. begin
  3161. list[fg.vertexIndices[Count]] := v0;
  3162. list[fg.vertexIndices[Count + 1]] := v1;
  3163. list[fg.vertexIndices[Count + 2]] := v2;
  3164. end;
  3165. fgmmTriangleFan:
  3166. begin
  3167. list[fg.vertexIndices[0]] := v0;
  3168. list[fg.vertexIndices[Count + 1]] := v1;
  3169. list[fg.vertexIndices[Count + 2]] := v2;
  3170. end;
  3171. fgmmQuads:
  3172. begin
  3173. if Count mod 2 = 0 then
  3174. begin
  3175. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3176. list[fg.vertexIndices[4 * (Count div 2) + 1]] := v1;
  3177. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v2;
  3178. end
  3179. else
  3180. begin
  3181. list[fg.vertexIndices[4 * (Count div 2)]] := v0;
  3182. list[fg.vertexIndices[4 * (Count div 2) + 2]] := v1;
  3183. list[fg.vertexIndices[4 * (Count div 2) + 3]] := v2;
  3184. end;
  3185. end;
  3186. else
  3187. Assert(False);
  3188. end;
  3189. Break;
  3190. end;
  3191. end;
  3192. end;
  3193. else
  3194. Assert(False);
  3195. end;
  3196. end;
  3197. procedure TgxMeshObject.SetUseVBO(const Value: Boolean);
  3198. var
  3199. i: Integer;
  3200. begin
  3201. if Value = FUseVBO then
  3202. Exit;
  3203. if FUseVBO then
  3204. begin
  3205. FreeAndNil(FVerticesVBO);
  3206. FreeAndNil(FNormalsVBO);
  3207. FreeAndNil(FColorsVBO);
  3208. for i := 0 to high(FTexCoordsVBO) do
  3209. FreeAndNil(FTexCoordsVBO[i]);
  3210. FreeAndNil(FLightmapTexCoordsVBO);
  3211. end;
  3212. FValidBuffers := [];
  3213. FUseVBO := Value;
  3214. end;
  3215. procedure TgxMeshObject.SetValidBuffers(Value: TVBOBuffers);
  3216. var
  3217. i: Integer;
  3218. begin
  3219. if FValidBuffers <> Value then
  3220. begin
  3221. FValidBuffers := Value;
  3222. if Assigned(FVerticesVBO) then
  3223. FVerticesVBO.NotifyChangesOfData;
  3224. if Assigned(FNormalsVBO) then
  3225. FNormalsVBO.NotifyChangesOfData;
  3226. if Assigned(FColorsVBO) then
  3227. FColorsVBO.NotifyChangesOfData;
  3228. for i := 0 to high(FTexCoordsVBO) do
  3229. if Assigned(FTexCoordsVBO[i]) then
  3230. FTexCoordsVBO[i].NotifyChangesOfData;
  3231. if Assigned(FLightmapTexCoordsVBO) then
  3232. FLightmapTexCoordsVBO.NotifyChangesOfData;
  3233. end;
  3234. end;
  3235. procedure TgxMeshObject.BuildTangentSpace(buildBinormals: Boolean = True; buildTangents: Boolean = True);
  3236. var
  3237. i, j: Integer;
  3238. v, n, t: array [0 .. 2] of TAffineVector;
  3239. tangent, binormal: array [0 .. 2] of TVector4f;
  3240. vt, tt: TAffineVector;
  3241. interp, dot: Single;
  3242. procedure SortVertexData(sortidx: Integer);
  3243. begin
  3244. if t[0].v[sortidx] < t[1].v[sortidx] then
  3245. begin
  3246. vt := v[0];
  3247. tt := t[0];
  3248. v[0] := v[1];
  3249. t[0] := t[1];
  3250. v[1] := vt;
  3251. t[1] := tt;
  3252. end;
  3253. if t[0].v[sortidx] < t[2].v[sortidx] then
  3254. begin
  3255. vt := v[0];
  3256. tt := t[0];
  3257. v[0] := v[2];
  3258. t[0] := t[2];
  3259. v[2] := vt;
  3260. t[2] := tt;
  3261. end;
  3262. if t[1].v[sortidx] < t[2].v[sortidx] then
  3263. begin
  3264. vt := v[1];
  3265. tt := t[1];
  3266. v[1] := v[2];
  3267. t[1] := t[2];
  3268. v[2] := vt;
  3269. t[2] := tt;
  3270. end;
  3271. end;
  3272. begin
  3273. Tangents.Clear;
  3274. Binormals.Clear;
  3275. if buildTangents then
  3276. Tangents.Count := Vertices.Count;
  3277. if buildBinormals then
  3278. Binormals.Count := Vertices.Count;
  3279. for i := 0 to TriangleCount - 1 do
  3280. begin
  3281. // Get triangle data
  3282. GetTriangleData(i, Vertices, v[0], v[1], v[2]);
  3283. GetTriangleData(i, normals, n[0], n[1], n[2]);
  3284. GetTriangleData(i, texCoords, t[0], t[1], t[2]);
  3285. for j := 0 to 2 do
  3286. begin
  3287. // Compute tangent
  3288. if buildTangents then
  3289. begin
  3290. SortVertexData(1);
  3291. if (t[2].Y - t[0].Y) = 0 then
  3292. interp := 1
  3293. else
  3294. interp := (t[1].Y - t[0].Y) / (t[2].Y - t[0].Y);
  3295. vt := VectorLerp(v[0], v[2], interp);
  3296. interp := t[0].X + (t[2].X - t[0].X) * interp;
  3297. vt := VectorSubtract(vt, v[1]);
  3298. if t[1].X < interp then
  3299. vt := VectorNegate(vt);
  3300. dot := VectorDotProduct(vt, n[j]);
  3301. vt.X := vt.X - n[j].X * dot;
  3302. vt.Y := vt.Y - n[j].Y * dot;
  3303. vt.Z := vt.Z - n[j].Z * dot;
  3304. tangent[j] := VectorMake(VectorNormalize(vt), 0);
  3305. end;
  3306. // Compute Bi-Normal
  3307. if buildBinormals then
  3308. begin
  3309. SortVertexData(0);
  3310. if (t[2].X - t[0].X) = 0 then
  3311. interp := 1
  3312. else
  3313. interp := (t[1].X - t[0].X) / (t[2].X - t[0].X);
  3314. vt := VectorLerp(v[0], v[2], interp);
  3315. interp := t[0].Y + (t[2].Y - t[0].Y) * interp;
  3316. vt := VectorSubtract(vt, v[1]);
  3317. if t[1].Y < interp then
  3318. vt := VectorNegate(vt);
  3319. dot := VectorDotProduct(vt, n[j]);
  3320. vt.X := vt.X - n[j].X * dot;
  3321. vt.Y := vt.Y - n[j].Y * dot;
  3322. vt.Z := vt.Z - n[j].Z * dot;
  3323. binormal[j] := VectorMake(VectorNormalize(vt), 0);
  3324. end;
  3325. end;
  3326. if buildTangents then
  3327. SetTriangleData(i, Tangents, tangent[0], tangent[1], tangent[2]);
  3328. if buildBinormals then
  3329. SetTriangleData(i, Binormals, binormal[0], binormal[1], binormal[2]);
  3330. end;
  3331. end;
  3332. procedure TgxMeshObject.DeclareArraysToOpenGL(var mrci: TgxRenderContextInfo; evenIfAlreadyDeclared: Boolean = False);
  3333. var
  3334. i: Integer;
  3335. currentMapping: Cardinal;
  3336. lists: array [0 .. 4] of pointer;
  3337. tlists: array of pointer;
  3338. begin
  3339. if evenIfAlreadyDeclared or (not FArraysDeclared) then
  3340. begin
  3341. FillChar(lists, SizeOf(lists), 0);
  3342. SetLength(tlists, FTexCoordsEx.Count);
  3343. // workaround for ATI bug, disable element VBO if
  3344. // inside a display list
  3345. FUseVBO := FUseVBO and not mrci.gxStates.InsideList;
  3346. /// and GL_ARB_vertex_buffer_object
  3347. if not FUseVBO then
  3348. begin
  3349. lists[0] := Vertices.list;
  3350. lists[1] := normals.list;
  3351. lists[2] := Colors.list;
  3352. lists[3] := texCoords.list;
  3353. lists[4] := LightMapTexCoords.list;
  3354. for i := 0 to FTexCoordsEx.Count - 1 do
  3355. tlists[i] := TexCoordsEx[i].list;
  3356. end
  3357. else
  3358. begin
  3359. BufferArrays;
  3360. end;
  3361. if not mrci.ignoreMaterials then
  3362. begin
  3363. if normals.Count > 0 then
  3364. begin
  3365. if FUseVBO then
  3366. FNormalsVBO.Bind;
  3367. glEnableClientState(GL_NORMAL_ARRAY);
  3368. glNormalPointer(GL_FLOAT, 0, lists[1]);
  3369. end
  3370. else
  3371. glDisableClientState(GL_NORMAL_ARRAY);
  3372. if (Colors.Count > 0) and (not mrci.ignoreMaterials) then
  3373. begin
  3374. if FUseVBO then
  3375. FColorsVBO.Bind;
  3376. glEnableClientState(GL_COLOR_ARRAY);
  3377. glColorPointer(4, GL_FLOAT, 0, lists[2]);
  3378. end
  3379. else
  3380. glDisableClientState(GL_COLOR_ARRAY);
  3381. if texCoords.Count > 0 then
  3382. begin
  3383. if FUseVBO then
  3384. FTexCoordsVBO[0].Bind;
  3385. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3386. glTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), lists[3]);
  3387. end
  3388. else
  3389. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3390. /// if GL_ARB_multitexture then
  3391. begin
  3392. if LightMapTexCoords.Count > 0 then
  3393. begin
  3394. if FUseVBO then
  3395. FLightmapTexCoordsVBO.Bind;
  3396. glClientActiveTexture(GL_TEXTURE1);
  3397. glTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), lists[4]);
  3398. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3399. end;
  3400. for i := 0 to FTexCoordsEx.Count - 1 do
  3401. begin
  3402. if TexCoordsEx[i].Count > 0 then
  3403. begin
  3404. if FUseVBO then
  3405. FTexCoordsVBO[i].Bind;
  3406. glClientActiveTexture(GL_TEXTURE0 + i);
  3407. glTexCoordPointer(4, GL_FLOAT, SizeOf(TVector4f), tlists[i]);
  3408. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3409. end;
  3410. end;
  3411. glClientActiveTexture(GL_TEXTURE0);
  3412. end;
  3413. end
  3414. else
  3415. begin
  3416. glDisableClientState(GL_NORMAL_ARRAY);
  3417. glDisableClientState(GL_COLOR_ARRAY);
  3418. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3419. end;
  3420. if Vertices.Count > 0 then
  3421. begin
  3422. if FUseVBO then
  3423. FVerticesVBO.Bind;
  3424. glEnableClientState(GL_VERTEX_ARRAY);
  3425. glVertexPointer(3, GL_FLOAT, 0, lists[0]);
  3426. end
  3427. else
  3428. glDisableClientState(GL_VERTEX_ARRAY);
  3429. if (LightMapTexCoords.Count = 0) and not FUseVBO then
  3430. /// and GL_EXT_compiled_vertex_array
  3431. glLockArraysEXT(0, Vertices.Count);
  3432. FLastLightMapIndex := -1;
  3433. FArraysDeclared := True;
  3434. FLightMapArrayEnabled := False;
  3435. if mrci.drawState <> dsPicking then
  3436. FLastXOpenGLTexMapping := xglGetBitWiseMapping;
  3437. end
  3438. else
  3439. begin
  3440. if not mrci.ignoreMaterials and not(mrci.drawState = dsPicking) then
  3441. if texCoords.Count > 0 then
  3442. begin
  3443. currentMapping := xglGetBitWiseMapping;
  3444. if FLastXOpenGLTexMapping <> currentMapping then
  3445. begin
  3446. xglEnableClientState(GL_TEXTURE_COORD_ARRAY);
  3447. xglTexCoordPointer(2, GL_FLOAT, SizeOf(TAffineVector), texCoords.list);
  3448. FLastXOpenGLTexMapping := currentMapping;
  3449. end;
  3450. end;
  3451. end;
  3452. end;
  3453. procedure TgxMeshObject.DisableOpenGLArrays(var mrci: TgxRenderContextInfo);
  3454. var
  3455. i: Integer;
  3456. begin
  3457. if FArraysDeclared then
  3458. begin
  3459. DisableLightMapArray(mrci);
  3460. if (LightMapTexCoords.Count = 0) and not FUseVBO then
  3461. /// and GL_EXT_compiled_vertex_array
  3462. glUnlockArraysEXT;
  3463. if Vertices.Count > 0 then
  3464. glDisableClientState(GL_VERTEX_ARRAY);
  3465. if not mrci.ignoreMaterials then
  3466. begin
  3467. if normals.Count > 0 then
  3468. glDisableClientState(GL_NORMAL_ARRAY);
  3469. if (Colors.Count > 0) and (not mrci.ignoreMaterials) then
  3470. glDisableClientState(GL_COLOR_ARRAY);
  3471. if texCoords.Count > 0 then
  3472. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3473. /// if GL_ARB_multitexture then
  3474. begin
  3475. if LightMapTexCoords.Count > 0 then
  3476. begin
  3477. glClientActiveTexture(GL_TEXTURE1);
  3478. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3479. end;
  3480. for i := 0 to FTexCoordsEx.Count - 1 do
  3481. begin
  3482. if TexCoordsEx[i].Count > 0 then
  3483. begin
  3484. glClientActiveTexture(GL_TEXTURE0 + i);
  3485. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  3486. end;
  3487. end;
  3488. glClientActiveTexture(GL_TEXTURE0);
  3489. end;
  3490. end;
  3491. if FUseVBO then
  3492. begin
  3493. if Vertices.Count > 0 then
  3494. FVerticesVBO.UnBind;
  3495. if normals.Count > 0 then
  3496. FNormalsVBO.UnBind;
  3497. if Colors.Count > 0 then
  3498. FColorsVBO.UnBind;
  3499. if texCoords.Count > 0 then
  3500. FTexCoordsVBO[0].UnBind;
  3501. if LightMapTexCoords.Count > 0 then
  3502. FLightmapTexCoordsVBO.UnBind;
  3503. if FTexCoordsEx.Count > 0 then
  3504. begin
  3505. for i := 0 to FTexCoordsEx.Count - 1 do
  3506. begin
  3507. if TexCoordsEx[i].Count > 0 then
  3508. FTexCoordsVBO[i].UnBind;
  3509. end;
  3510. end;
  3511. end;
  3512. FArraysDeclared := False;
  3513. end;
  3514. end;
  3515. procedure TgxMeshObject.EnableLightMapArray(var mrci: TgxRenderContextInfo);
  3516. begin
  3517. if (not mrci.ignoreMaterials) then
  3518. /// and GL_ARB_multitexture
  3519. begin
  3520. Assert(FArraysDeclared);
  3521. if not FLightMapArrayEnabled then
  3522. begin
  3523. mrci.gxStates.ActiveTexture := 1;
  3524. mrci.gxStates.ActiveTextureEnabled[ttTexture2D] := True;
  3525. mrci.gxStates.ActiveTexture := 0;
  3526. FLightMapArrayEnabled := True;
  3527. end;
  3528. end;
  3529. end;
  3530. procedure TgxMeshObject.DisableLightMapArray(var mrci: TgxRenderContextInfo);
  3531. begin
  3532. if FLightMapArrayEnabled then
  3533. /// and GL_ARB_multitexture
  3534. begin
  3535. mrci.gxStates.ActiveTexture := 1;
  3536. mrci.gxStates.ActiveTextureEnabled[ttTexture2D] := False;
  3537. mrci.gxStates.ActiveTexture := 0;
  3538. FLightMapArrayEnabled := False;
  3539. end;
  3540. end;
  3541. procedure TgxMeshObject.PrepareBuildList(var mrci: TgxRenderContextInfo);
  3542. var
  3543. i: Integer;
  3544. begin
  3545. if (mode = momFaceGroups) and Assigned(mrci.MaterialLibrary) then
  3546. begin
  3547. for i := 0 to FaceGroups.Count - 1 do
  3548. with TgxFaceGroup(FaceGroups.list^[i]) do
  3549. begin
  3550. if MaterialCache <> nil then
  3551. MaterialCache.PrepareBuildList;
  3552. end;
  3553. end;
  3554. end;
  3555. procedure TgxMeshObject.BufferArrays;
  3556. const
  3557. BufferUsage = GL_DYNAMIC_DRAW;
  3558. var
  3559. i: Integer;
  3560. begin
  3561. if Vertices.Count > 0 then
  3562. begin
  3563. if not Assigned(FVerticesVBO) then
  3564. FVerticesVBO := TgxVBOArrayBufferHandle.Create;
  3565. FVerticesVBO.AllocateHandle;
  3566. if FVerticesVBO.IsDataNeedUpdate then
  3567. begin
  3568. FVerticesVBO.BindBufferData(Vertices.list, SizeOf(TAffineVector) * Vertices.Count, BufferUsage);
  3569. FVerticesVBO.NotifyDataUpdated;
  3570. FVerticesVBO.UnBind;
  3571. end;
  3572. Include(FValidBuffers, vbVertices);
  3573. end;
  3574. if normals.Count > 0 then
  3575. begin
  3576. if not Assigned(FNormalsVBO) then
  3577. FNormalsVBO := TgxVBOArrayBufferHandle.Create;
  3578. FNormalsVBO.AllocateHandle;
  3579. if FNormalsVBO.IsDataNeedUpdate then
  3580. begin
  3581. FNormalsVBO.BindBufferData(normals.list, SizeOf(TAffineVector) * normals.Count, BufferUsage);
  3582. FNormalsVBO.NotifyDataUpdated;
  3583. FNormalsVBO.UnBind;
  3584. end;
  3585. Include(FValidBuffers, vbNormals);
  3586. end;
  3587. if Colors.Count > 0 then
  3588. begin
  3589. if not Assigned(FColorsVBO) then
  3590. FColorsVBO := TgxVBOArrayBufferHandle.Create;
  3591. FColorsVBO.AllocateHandle;
  3592. if FColorsVBO.IsDataNeedUpdate then
  3593. begin
  3594. FColorsVBO.BindBufferData(Colors.list, SizeOf(TVector4f) * Colors.Count, BufferUsage);
  3595. FColorsVBO.NotifyDataUpdated;
  3596. FColorsVBO.UnBind;
  3597. end;
  3598. Include(FValidBuffers, vbColors);
  3599. end;
  3600. if texCoords.Count > 0 then
  3601. begin
  3602. if Length(FTexCoordsVBO) < 1 then
  3603. SetLength(FTexCoordsVBO, 1);
  3604. if not Assigned(FTexCoordsVBO[0]) then
  3605. FTexCoordsVBO[0] := TgxVBOArrayBufferHandle.Create;
  3606. FTexCoordsVBO[0].AllocateHandle;
  3607. if FTexCoordsVBO[0].IsDataNeedUpdate then
  3608. begin
  3609. FTexCoordsVBO[0].BindBufferData(texCoords.list, SizeOf(TAffineVector) * texCoords.Count, BufferUsage);
  3610. FTexCoordsVBO[0].NotifyDataUpdated;
  3611. FTexCoordsVBO[0].UnBind;
  3612. end;
  3613. Include(FValidBuffers, vbTexCoords);
  3614. end;
  3615. if LightMapTexCoords.Count > 0 then
  3616. begin
  3617. if not Assigned(FLightmapTexCoordsVBO) then
  3618. FLightmapTexCoordsVBO := TgxVBOArrayBufferHandle.Create;
  3619. FLightmapTexCoordsVBO.AllocateHandle;
  3620. FLightmapTexCoordsVBO.BindBufferData(LightMapTexCoords.list, SizeOf(TAffineVector) * LightMapTexCoords.Count, BufferUsage);
  3621. FLightmapTexCoordsVBO.NotifyDataUpdated;
  3622. FLightmapTexCoordsVBO.UnBind;
  3623. Include(FValidBuffers, vbLightMapTexCoords);
  3624. end;
  3625. if FTexCoordsEx.Count > 0 then
  3626. begin
  3627. if Length(FTexCoordsVBO) < FTexCoordsEx.Count then
  3628. SetLength(FTexCoordsVBO, FTexCoordsEx.Count);
  3629. for i := 0 to FTexCoordsEx.Count - 1 do
  3630. begin
  3631. if TexCoordsEx[i].Count <= 0 then
  3632. continue;
  3633. if not Assigned(FTexCoordsVBO[i]) then
  3634. FTexCoordsVBO[i] := TgxVBOArrayBufferHandle.Create;
  3635. FTexCoordsVBO[i].AllocateHandle;
  3636. if FTexCoordsVBO[i].IsDataNeedUpdate then
  3637. begin
  3638. FTexCoordsVBO[i].BindBufferData(TexCoordsEx[i].list, SizeOf(TVector4f) * TexCoordsEx[i].Count, BufferUsage);
  3639. FTexCoordsVBO[i].NotifyDataUpdated;
  3640. FTexCoordsVBO[i].UnBind;
  3641. end;
  3642. end;
  3643. Include(FValidBuffers, vbTexCoordsEx);
  3644. end;
  3645. /// CheckOpenGLError;
  3646. end;
  3647. procedure TgxMeshObject.BuildList(var mrci: TgxRenderContextInfo);
  3648. var
  3649. i, j, groupID, nbGroups: Integer;
  3650. gotNormals, gotTexCoords, gotColor: Boolean;
  3651. gotTexCoordsEx: array of Boolean;
  3652. libMat: TgxLibMaterial;
  3653. fg: TgxFaceGroup;
  3654. begin
  3655. // Make sure no VBO is bound and states enabled
  3656. FArraysDeclared := False;
  3657. FLastXOpenGLTexMapping := 0;
  3658. gotColor := (Vertices.Count = Colors.Count);
  3659. if gotColor then
  3660. begin
  3661. mrci.gxStates.Enable(stColorMaterial);
  3662. glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  3663. mrci.gxStates.SetMaterialColors(cmFront, clrBlack, clrGray20, clrGray80, clrBlack, 0);
  3664. mrci.gxStates.SetMaterialColors(cmBack, clrBlack, clrGray20, clrGray80, clrBlack, 0);
  3665. end;
  3666. case mode of
  3667. momTriangles, momTriangleStrip:
  3668. if Vertices.Count > 0 then
  3669. begin
  3670. DeclareArraysToOpenGL(mrci);
  3671. gotNormals := (Vertices.Count = normals.Count);
  3672. gotTexCoords := (Vertices.Count = texCoords.Count);
  3673. SetLength(gotTexCoordsEx, FTexCoordsEx.Count);
  3674. for i := 0 to FTexCoordsEx.Count - 1 do
  3675. gotTexCoordsEx[i] := (TexCoordsEx[i].Count > 0);
  3676. /// and GL_ARB_multitexture;
  3677. if mode = momTriangles then
  3678. glBegin(GL_TRIANGLES)
  3679. else
  3680. glBegin(GL_TRIANGLE_STRIP);
  3681. for i := 0 to Vertices.Count - 1 do
  3682. begin
  3683. if gotNormals then
  3684. glNormal3fv(@normals.list[i]);
  3685. if gotColor then
  3686. glColor4fv(@Colors.list[i]);
  3687. if FTexCoordsEx.Count > 0 then
  3688. begin
  3689. if gotTexCoordsEx[0] then
  3690. glMultiTexCoord4fv(GL_TEXTURE0, @TexCoordsEx[0].list[i])
  3691. else if gotTexCoords then
  3692. glTexCoord2fv(@texCoords.list[i]);
  3693. for j := 1 to FTexCoordsEx.Count - 1 do
  3694. if gotTexCoordsEx[j] then
  3695. glMultiTexCoord4fv(GL_TEXTURE0 + j, @TexCoordsEx[j].list[i]);
  3696. end
  3697. else
  3698. begin
  3699. if gotTexCoords then
  3700. glTexCoord2fv(@texCoords.list[i]);
  3701. end;
  3702. glVertex3fv(@Vertices.list[i]);
  3703. end;
  3704. glEnd;
  3705. end;
  3706. momFaceGroups:
  3707. begin
  3708. if Assigned(mrci.MaterialLibrary) then
  3709. begin
  3710. if moroGroupByMaterial in RenderingOptions then
  3711. begin
  3712. // group-by-material rendering, reduces material switches,
  3713. // but alters rendering order
  3714. groupID := vNextRenderGroupID;
  3715. Inc(vNextRenderGroupID);
  3716. for i := 0 to FaceGroups.Count - 1 do
  3717. begin
  3718. if FaceGroups[i].FRenderGroupID <> groupID then
  3719. begin
  3720. libMat := FaceGroups[i].FMaterialCache;
  3721. if Assigned(libMat) then
  3722. libMat.Apply(mrci);
  3723. repeat
  3724. for j := i to FaceGroups.Count - 1 do
  3725. with FaceGroups[j] do
  3726. begin
  3727. if (FRenderGroupID <> groupID) and (FMaterialCache = libMat) then
  3728. begin
  3729. FRenderGroupID := groupID;
  3730. BuildList(mrci);
  3731. end;
  3732. end;
  3733. until (not Assigned(libMat)) or (not libMat.UnApply(mrci));
  3734. end;
  3735. end;
  3736. end
  3737. else
  3738. begin
  3739. // canonical rendering (regroups only contiguous facegroups)
  3740. i := 0;
  3741. nbGroups := FaceGroups.Count;
  3742. while i < nbGroups do
  3743. begin
  3744. libMat := FaceGroups[i].FMaterialCache;
  3745. if Assigned(libMat) then
  3746. begin
  3747. libMat.Apply(mrci);
  3748. repeat
  3749. j := i;
  3750. while j < nbGroups do
  3751. begin
  3752. fg := FaceGroups[j];
  3753. if fg.MaterialCache <> libMat then
  3754. Break;
  3755. fg.BuildList(mrci);
  3756. Inc(j);
  3757. end;
  3758. until not libMat.UnApply(mrci);
  3759. i := j;
  3760. end
  3761. else
  3762. begin
  3763. FaceGroups[i].BuildList(mrci);
  3764. Inc(i);
  3765. end;
  3766. end;
  3767. end;
  3768. // restore faceculling
  3769. if (stCullFace in mrci.gxStates.States) then
  3770. begin
  3771. if not mrci.bufferFaceCull then
  3772. mrci.gxStates.Disable(stCullFace);
  3773. end
  3774. else
  3775. begin
  3776. if mrci.bufferFaceCull then
  3777. mrci.gxStates.Enable(stCullFace);
  3778. end;
  3779. end
  3780. else
  3781. for i := 0 to FaceGroups.Count - 1 do
  3782. FaceGroups[i].BuildList(mrci);
  3783. end;
  3784. else
  3785. Assert(False);
  3786. end;
  3787. DisableOpenGLArrays(mrci);
  3788. end;
  3789. // ------------------
  3790. // ------------------ TgxMeshObjectList ------------------
  3791. // ------------------
  3792. constructor TgxMeshObjectList.CreateOwned(aOwner: TgxBaseMesh);
  3793. begin
  3794. FOwner := aOwner;
  3795. Create;
  3796. end;
  3797. destructor TgxMeshObjectList.Destroy;
  3798. begin
  3799. Clear;
  3800. inherited;
  3801. end;
  3802. procedure TgxMeshObjectList.ReadFromFiler(reader: TgxVirtualReader);
  3803. var
  3804. i: Integer;
  3805. Mesh: TgxMeshObject;
  3806. begin
  3807. inherited;
  3808. for i := 0 to Count - 1 do
  3809. begin
  3810. Mesh := Items[i];
  3811. Mesh.FOwner := Self;
  3812. if Mesh is TgxSkeletonMeshObject then
  3813. TgxSkeletonMeshObject(Mesh).PrepareBoneMatrixInvertedMeshes;
  3814. end;
  3815. end;
  3816. procedure TgxMeshObjectList.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  3817. var
  3818. i: Integer;
  3819. begin
  3820. for i := 0 to Count - 1 do
  3821. TgxMeshObject(list^[i]).PrepareMaterialLibraryCache(matLib);
  3822. end;
  3823. procedure TgxMeshObjectList.DropMaterialLibraryCache;
  3824. var
  3825. i: Integer;
  3826. begin
  3827. for i := 0 to Count - 1 do
  3828. TgxMeshObject(list^[i]).DropMaterialLibraryCache;
  3829. end;
  3830. procedure TgxMeshObjectList.PrepareBuildList(var mrci: TgxRenderContextInfo);
  3831. var
  3832. i: Integer;
  3833. begin
  3834. for i := 0 to Count - 1 do
  3835. with Items[i] do
  3836. if Visible then
  3837. PrepareBuildList(mrci);
  3838. end;
  3839. procedure TgxMeshObjectList.BuildList(var mrci: TgxRenderContextInfo);
  3840. var
  3841. i: Integer;
  3842. begin
  3843. for i := 0 to Count - 1 do
  3844. with Items[i] do
  3845. if Visible then
  3846. BuildList(mrci);
  3847. end;
  3848. procedure TgxMeshObjectList.MorphTo(morphTargetIndex: Integer);
  3849. var
  3850. i: Integer;
  3851. begin
  3852. for i := 0 to Count - 1 do
  3853. if Items[i] is TgxMorphableMeshObject then
  3854. TgxMorphableMeshObject(Items[i]).MorphTo(morphTargetIndex);
  3855. end;
  3856. procedure TgxMeshObjectList.Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  3857. var
  3858. i: Integer;
  3859. begin
  3860. for i := 0 to Count - 1 do
  3861. if Items[i] is TgxMorphableMeshObject then
  3862. TgxMorphableMeshObject(Items[i]).Lerp(morphTargetIndex1, morphTargetIndex2, lerpFactor);
  3863. end;
  3864. function TgxMeshObjectList.MorphTargetCount: Integer;
  3865. var
  3866. i: Integer;
  3867. begin
  3868. Result := MaxInt;
  3869. for i := 0 to Count - 1 do
  3870. if Items[i] is TgxMorphableMeshObject then
  3871. with TgxMorphableMeshObject(Items[i]) do
  3872. if Result > MorphTargets.Count then
  3873. Result := MorphTargets.Count;
  3874. if Result = MaxInt then
  3875. Result := 0;
  3876. end;
  3877. procedure TgxMeshObjectList.Clear;
  3878. var
  3879. i: Integer;
  3880. begin
  3881. DropMaterialLibraryCache;
  3882. for i := 0 to Count - 1 do
  3883. with Items[i] do
  3884. begin
  3885. FOwner := nil;
  3886. Free;
  3887. end;
  3888. inherited;
  3889. end;
  3890. function TgxMeshObjectList.GetMeshObject(Index: Integer): TgxMeshObject;
  3891. begin
  3892. Result := TgxMeshObject(list^[Index]);
  3893. end;
  3894. procedure TgxMeshObjectList.GetExtents(out min, max: TAffineVector);
  3895. var
  3896. i, k: Integer;
  3897. lMin, lMax: TAffineVector;
  3898. const
  3899. cBigValue: Single = 1E30;
  3900. cSmallValue: Single = -1E30;
  3901. begin
  3902. SetVector(min, cBigValue, cBigValue, cBigValue);
  3903. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  3904. for i := 0 to Count - 1 do
  3905. begin
  3906. GetMeshObject(i).GetExtents(lMin, lMax);
  3907. for k := 0 to 2 do
  3908. begin
  3909. if lMin.v[k] < min.v[k] then
  3910. min.v[k] := lMin.v[k];
  3911. if lMax.v[k] > max.v[k] then
  3912. max.v[k] := lMax.v[k];
  3913. end;
  3914. end;
  3915. end;
  3916. procedure TgxMeshObjectList.Translate(const delta: TAffineVector);
  3917. var
  3918. i: Integer;
  3919. begin
  3920. for i := 0 to Count - 1 do
  3921. GetMeshObject(i).Translate(delta);
  3922. end;
  3923. function TgxMeshObjectList.ExtractTriangles(texCoords: TgxAffineVectorList = nil; normals: TgxAffineVectorList = nil)
  3924. : TgxAffineVectorList;
  3925. var
  3926. i: Integer;
  3927. obj: TgxMeshObject;
  3928. objTris: TgxAffineVectorList;
  3929. objTexCoords: TgxAffineVectorList;
  3930. objNormals: TgxAffineVectorList;
  3931. begin
  3932. Result := TgxAffineVectorList.Create;
  3933. if Assigned(texCoords) then
  3934. objTexCoords := TgxAffineVectorList.Create
  3935. else
  3936. objTexCoords := nil;
  3937. if Assigned(normals) then
  3938. objNormals := TgxAffineVectorList.Create
  3939. else
  3940. objNormals := nil;
  3941. try
  3942. for i := 0 to Count - 1 do
  3943. begin
  3944. obj := GetMeshObject(i);
  3945. if not obj.Visible then
  3946. continue;
  3947. objTris := obj.ExtractTriangles(objTexCoords, objNormals);
  3948. try
  3949. Result.Add(objTris);
  3950. if Assigned(texCoords) then
  3951. begin
  3952. texCoords.Add(objTexCoords);
  3953. objTexCoords.Count := 0;
  3954. end;
  3955. if Assigned(normals) then
  3956. begin
  3957. normals.Add(objNormals);
  3958. objNormals.Count := 0;
  3959. end;
  3960. finally
  3961. objTris.Free;
  3962. end;
  3963. end;
  3964. finally
  3965. objTexCoords.Free;
  3966. objNormals.Free;
  3967. end;
  3968. end;
  3969. function TgxMeshObjectList.TriangleCount: Integer;
  3970. var
  3971. i: Integer;
  3972. begin
  3973. Result := 0;
  3974. for i := 0 to Count - 1 do
  3975. Result := Result + Items[i].TriangleCount;
  3976. end;
  3977. procedure TgxMeshObjectList.Prepare;
  3978. var
  3979. i: Integer;
  3980. begin
  3981. for i := 0 to Count - 1 do
  3982. Items[i].Prepare;
  3983. end;
  3984. function TgxMeshObjectList.FindMeshByName(MeshName: string): TgxMeshObject;
  3985. var
  3986. i: Integer;
  3987. begin
  3988. Result := nil;
  3989. for i := 0 to Count - 1 do
  3990. if Items[i].Name = MeshName then
  3991. begin
  3992. Result := Items[i];
  3993. Break;
  3994. end;
  3995. end;
  3996. procedure TgxMeshObjectList.BuildTangentSpace(buildBinormals, buildTangents: Boolean);
  3997. var
  3998. i: Integer;
  3999. begin
  4000. if Count <> 0 then
  4001. for i := 0 to Count - 1 do
  4002. GetMeshObject(i).BuildTangentSpace(buildBinormals, buildTangents);
  4003. end;
  4004. function TgxMeshObjectList.GetUseVBO: Boolean;
  4005. var
  4006. i: Integer;
  4007. begin
  4008. Result := True;
  4009. if Count <> 0 then
  4010. for i := 0 to Count - 1 do
  4011. Result := Result and GetMeshObject(i).FUseVBO;
  4012. end;
  4013. procedure TgxMeshObjectList.SetUseVBO(const Value: Boolean);
  4014. var
  4015. i: Integer;
  4016. begin
  4017. if Count <> 0 then
  4018. for i := 0 to Count - 1 do
  4019. GetMeshObject(i).SetUseVBO(Value);
  4020. end;
  4021. // ------------------
  4022. // ------------------ TgxMeshMorphTarget ------------------
  4023. // ------------------
  4024. constructor TgxMeshMorphTarget.CreateOwned(aOwner: TgxMeshMorphTargetList);
  4025. begin
  4026. FOwner := aOwner;
  4027. Create;
  4028. if Assigned(FOwner) then
  4029. FOwner.Add(Self);
  4030. end;
  4031. destructor TgxMeshMorphTarget.Destroy;
  4032. begin
  4033. if Assigned(FOwner) then
  4034. FOwner.Remove(Self);
  4035. inherited;
  4036. end;
  4037. procedure TgxMeshMorphTarget.WriteToFiler(writer: TgxVirtualWriter);
  4038. begin
  4039. inherited WriteToFiler(writer);
  4040. with writer do
  4041. begin
  4042. WriteInteger(0); // Archive Version 0
  4043. // nothing
  4044. end;
  4045. end;
  4046. procedure TgxMeshMorphTarget.ReadFromFiler(reader: TgxVirtualReader);
  4047. var
  4048. archiveVersion: Integer;
  4049. begin
  4050. inherited ReadFromFiler(reader);
  4051. archiveVersion := reader.ReadInteger;
  4052. if archiveVersion = 0 then
  4053. with reader do
  4054. begin
  4055. // nothing
  4056. end
  4057. else
  4058. RaiseFilerException(archiveVersion);
  4059. end;
  4060. // ------------------
  4061. // ------------------ TgxMeshMorphTargetList ------------------
  4062. // ------------------
  4063. constructor TgxMeshMorphTargetList.CreateOwned(aOwner: TPersistent);
  4064. begin
  4065. FOwner := aOwner;
  4066. Create;
  4067. end;
  4068. destructor TgxMeshMorphTargetList.Destroy;
  4069. begin
  4070. Clear;
  4071. inherited;
  4072. end;
  4073. procedure TgxMeshMorphTargetList.ReadFromFiler(reader: TgxVirtualReader);
  4074. var
  4075. i: Integer;
  4076. begin
  4077. inherited;
  4078. for i := 0 to Count - 1 do
  4079. Items[i].FOwner := Self;
  4080. end;
  4081. procedure TgxMeshMorphTargetList.Translate(const delta: TAffineVector);
  4082. var
  4083. i: Integer;
  4084. begin
  4085. for i := 0 to Count - 1 do
  4086. Items[i].Translate(delta);
  4087. end;
  4088. procedure TgxMeshMorphTargetList.Clear;
  4089. var
  4090. i: Integer;
  4091. begin
  4092. for i := 0 to Count - 1 do
  4093. with Items[i] do
  4094. begin
  4095. FOwner := nil;
  4096. Free;
  4097. end;
  4098. inherited;
  4099. end;
  4100. function TgxMeshMorphTargetList.GetMeshMorphTarget(Index: Integer): TgxMeshMorphTarget;
  4101. begin
  4102. Result := TgxMeshMorphTarget(list^[Index]);
  4103. end;
  4104. // ------------------
  4105. // ------------------ TgxMorphableMeshObject ------------------
  4106. // ------------------
  4107. constructor TgxMorphableMeshObject.Create;
  4108. begin
  4109. inherited;
  4110. FMorphTargets := TgxMeshMorphTargetList.CreateOwned(Self);
  4111. end;
  4112. destructor TgxMorphableMeshObject.Destroy;
  4113. begin
  4114. FMorphTargets.Free;
  4115. inherited;
  4116. end;
  4117. procedure TgxMorphableMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  4118. begin
  4119. inherited WriteToFiler(writer);
  4120. with writer do
  4121. begin
  4122. WriteInteger(0); // Archive Version 0
  4123. FMorphTargets.WriteToFiler(writer);
  4124. end;
  4125. end;
  4126. procedure TgxMorphableMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  4127. var
  4128. archiveVersion: Integer;
  4129. begin
  4130. inherited ReadFromFiler(reader);
  4131. archiveVersion := reader.ReadInteger;
  4132. if archiveVersion = 0 then
  4133. with reader do
  4134. begin
  4135. FMorphTargets.ReadFromFiler(reader);
  4136. end
  4137. else
  4138. RaiseFilerException(archiveVersion);
  4139. end;
  4140. procedure TgxMorphableMeshObject.Clear;
  4141. begin
  4142. inherited;
  4143. FMorphTargets.Clear;
  4144. end;
  4145. procedure TgxMorphableMeshObject.Translate(const delta: TAffineVector);
  4146. begin
  4147. inherited;
  4148. MorphTargets.Translate(delta);
  4149. ValidBuffers := ValidBuffers - [vbVertices];
  4150. end;
  4151. procedure TgxMorphableMeshObject.MorphTo(morphTargetIndex: Integer);
  4152. begin
  4153. if (morphTargetIndex = 0) and (MorphTargets.Count = 0) then
  4154. Exit;
  4155. Assert(Cardinal(morphTargetIndex) < Cardinal(MorphTargets.Count));
  4156. with MorphTargets[morphTargetIndex] do
  4157. begin
  4158. if Vertices.Count > 0 then
  4159. begin
  4160. Self.Vertices.Assign(Vertices);
  4161. ValidBuffers := ValidBuffers - [vbVertices];
  4162. end;
  4163. if normals.Count > 0 then
  4164. begin
  4165. Self.normals.Assign(normals);
  4166. ValidBuffers := ValidBuffers - [vbNormals];
  4167. end;
  4168. end;
  4169. end;
  4170. procedure TgxMorphableMeshObject.Lerp(morphTargetIndex1, morphTargetIndex2: Integer; lerpFactor: Single);
  4171. var
  4172. mt1, mt2: TgxMeshMorphTarget;
  4173. begin
  4174. Assert((Cardinal(morphTargetIndex1) < Cardinal(MorphTargets.Count)) and
  4175. (Cardinal(morphTargetIndex2) < Cardinal(MorphTargets.Count)));
  4176. if lerpFactor = 0 then
  4177. MorphTo(morphTargetIndex1)
  4178. else if lerpFactor = 1 then
  4179. MorphTo(morphTargetIndex2)
  4180. else
  4181. begin
  4182. mt1 := MorphTargets[morphTargetIndex1];
  4183. mt2 := MorphTargets[morphTargetIndex2];
  4184. if mt1.Vertices.Count > 0 then
  4185. begin
  4186. Vertices.Lerp(mt1.Vertices, mt2.Vertices, lerpFactor);
  4187. ValidBuffers := ValidBuffers - [vbVertices];
  4188. end;
  4189. if mt1.normals.Count > 0 then
  4190. begin
  4191. normals.Lerp(mt1.normals, mt2.normals, lerpFactor);
  4192. normals.normalize;
  4193. ValidBuffers := ValidBuffers - [vbNormals];
  4194. end;
  4195. end;
  4196. end;
  4197. // ------------------
  4198. // ------------------ TgxSkeletonMeshObject ------------------
  4199. // ------------------
  4200. constructor TgxSkeletonMeshObject.Create;
  4201. begin
  4202. FBoneMatrixInvertedMeshes := TList.Create;
  4203. FBackupInvertedMeshes := TList.Create; // ragdoll
  4204. inherited Create;
  4205. end;
  4206. destructor TgxSkeletonMeshObject.Destroy;
  4207. begin
  4208. Clear;
  4209. FBoneMatrixInvertedMeshes.Free;
  4210. FBackupInvertedMeshes.Free;
  4211. inherited Destroy;
  4212. end;
  4213. procedure TgxSkeletonMeshObject.WriteToFiler(writer: TgxVirtualWriter);
  4214. var
  4215. i: Integer;
  4216. begin
  4217. inherited WriteToFiler(writer);
  4218. with writer do
  4219. begin
  4220. WriteInteger(0); // Archive Version 0
  4221. WriteInteger(FVerticeBoneWeightCount);
  4222. WriteInteger(FBonesPerVertex);
  4223. WriteInteger(FVerticeBoneWeightCapacity);
  4224. for i := 0 to FVerticeBoneWeightCount - 1 do
  4225. Write(FVerticesBonesWeights[i][0], FBonesPerVertex * SizeOf(TgxVertexBoneWeight));
  4226. end;
  4227. end;
  4228. procedure TgxSkeletonMeshObject.ReadFromFiler(reader: TgxVirtualReader);
  4229. var
  4230. archiveVersion, i: Integer;
  4231. begin
  4232. inherited ReadFromFiler(reader);
  4233. archiveVersion := reader.ReadInteger;
  4234. if archiveVersion = 0 then
  4235. with reader do
  4236. begin
  4237. FVerticeBoneWeightCount := ReadInteger;
  4238. FBonesPerVertex := ReadInteger;
  4239. FVerticeBoneWeightCapacity := ReadInteger;
  4240. ResizeVerticesBonesWeights;
  4241. for i := 0 to FVerticeBoneWeightCount - 1 do
  4242. Read(FVerticesBonesWeights[i][0], FBonesPerVertex * SizeOf(TgxVertexBoneWeight));
  4243. end
  4244. else
  4245. RaiseFilerException(archiveVersion);
  4246. end;
  4247. procedure TgxSkeletonMeshObject.Clear;
  4248. var
  4249. i: Integer;
  4250. begin
  4251. inherited;
  4252. FVerticeBoneWeightCount := 0;
  4253. FBonesPerVertex := 0;
  4254. ResizeVerticesBonesWeights;
  4255. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4256. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4257. FBoneMatrixInvertedMeshes.Clear;
  4258. end;
  4259. procedure TgxSkeletonMeshObject.SetVerticeBoneWeightCount(const val: Integer);
  4260. begin
  4261. if val <> FVerticeBoneWeightCount then
  4262. begin
  4263. FVerticeBoneWeightCount := val;
  4264. if FVerticeBoneWeightCount > FVerticeBoneWeightCapacity then
  4265. VerticeBoneWeightCapacity := FVerticeBoneWeightCount + 16;
  4266. FLastVerticeBoneWeightCount := FVerticeBoneWeightCount;
  4267. end;
  4268. end;
  4269. procedure TgxSkeletonMeshObject.SetVerticeBoneWeightCapacity(const val: Integer);
  4270. begin
  4271. if val <> FVerticeBoneWeightCapacity then
  4272. begin
  4273. FVerticeBoneWeightCapacity := val;
  4274. ResizeVerticesBonesWeights;
  4275. end;
  4276. end;
  4277. procedure TgxSkeletonMeshObject.SetBonesPerVertex(const val: Integer);
  4278. begin
  4279. if val <> FBonesPerVertex then
  4280. begin
  4281. FBonesPerVertex := val;
  4282. ResizeVerticesBonesWeights;
  4283. end;
  4284. end;
  4285. procedure TgxSkeletonMeshObject.ResizeVerticesBonesWeights;
  4286. var
  4287. n, m, i, j: Integer;
  4288. newArea: PgxVerticesBoneWeights;
  4289. begin
  4290. n := BonesPerVertex * VerticeBoneWeightCapacity;
  4291. if n = 0 then
  4292. begin
  4293. // release everything
  4294. if Assigned(FVerticesBonesWeights) then
  4295. begin
  4296. FreeMem(FVerticesBonesWeights[0]);
  4297. FreeMem(FVerticesBonesWeights);
  4298. FVerticesBonesWeights := nil;
  4299. end;
  4300. end
  4301. else
  4302. begin
  4303. // allocate new area
  4304. GetMem(newArea, VerticeBoneWeightCapacity * SizeOf(PgxVertexBoneWeightArray));
  4305. newArea[0] := AllocMem(n * SizeOf(TgxVertexBoneWeight));
  4306. for i := 1 to VerticeBoneWeightCapacity - 1 do
  4307. newArea[i] := PgxVertexBoneWeightArray(Cardinal(newArea[0]) + Cardinal(i * SizeOf(TgxVertexBoneWeight) * BonesPerVertex));
  4308. // transfer old data
  4309. if FLastVerticeBoneWeightCount < VerticeBoneWeightCount then
  4310. n := FLastVerticeBoneWeightCount
  4311. else
  4312. n := VerticeBoneWeightCount;
  4313. if FLastBonesPerVertex < BonesPerVertex then
  4314. m := FLastBonesPerVertex
  4315. else
  4316. m := BonesPerVertex;
  4317. for i := 0 to n - 1 do
  4318. for j := 0 to m - 1 do
  4319. newArea[i][j] := VerticesBonesWeights[i][j];
  4320. // release old area and switch to new
  4321. if Assigned(FVerticesBonesWeights) then
  4322. begin
  4323. FreeMem(FVerticesBonesWeights[0]);
  4324. FreeMem(FVerticesBonesWeights);
  4325. end;
  4326. FVerticesBonesWeights := newArea;
  4327. end;
  4328. FLastBonesPerVertex := FBonesPerVertex;
  4329. end;
  4330. procedure TgxSkeletonMeshObject.AddWeightedBone(aBoneID: Integer; aWeight: Single);
  4331. begin
  4332. if BonesPerVertex < 1 then
  4333. BonesPerVertex := 1;
  4334. VerticeBoneWeightCount := VerticeBoneWeightCount + 1;
  4335. with VerticesBonesWeights^[VerticeBoneWeightCount - 1]^[0] do
  4336. begin
  4337. BoneID := aBoneID;
  4338. weight := aWeight;
  4339. end;
  4340. end;
  4341. procedure TgxSkeletonMeshObject.AddWeightedBones(const boneIDs: TgxVertexBoneWeightDynArray);
  4342. var
  4343. i: Integer;
  4344. n: Integer;
  4345. begin
  4346. n := Length(boneIDs);
  4347. if BonesPerVertex < n then
  4348. BonesPerVertex := n;
  4349. VerticeBoneWeightCount := VerticeBoneWeightCount + 1;
  4350. for i := 0 to n - 1 do
  4351. begin
  4352. with VerticesBonesWeights^[VerticeBoneWeightCount - 1]^[i] do
  4353. begin
  4354. BoneID := boneIDs[i].BoneID;
  4355. weight := boneIDs[i].weight;
  4356. end;
  4357. end;
  4358. end;
  4359. function TgxSkeletonMeshObject.FindOrAdd(BoneID: Integer; const vertex, normal: TAffineVector): Integer;
  4360. var
  4361. i: Integer;
  4362. dynArray: TgxVertexBoneWeightDynArray;
  4363. begin
  4364. if BonesPerVertex > 1 then
  4365. begin
  4366. SetLength(dynArray, 1);
  4367. dynArray[0].BoneID := BoneID;
  4368. dynArray[0].weight := 1;
  4369. Result := FindOrAdd(dynArray, vertex, normal);
  4370. Exit;
  4371. end;
  4372. Result := -1;
  4373. for i := 0 to Vertices.Count - 1 do
  4374. if (VerticesBonesWeights^[i]^[0].BoneID = BoneID) and VectorEquals(Vertices.list^[i], vertex) and
  4375. VectorEquals(normals.list^[i], normal) then
  4376. begin
  4377. Result := i;
  4378. Break;
  4379. end;
  4380. if Result < 0 then
  4381. begin
  4382. AddWeightedBone(BoneID, 1);
  4383. Vertices.Add(vertex);
  4384. Result := normals.Add(normal);
  4385. end;
  4386. end;
  4387. function TgxSkeletonMeshObject.FindOrAdd(const boneIDs: TgxVertexBoneWeightDynArray; const vertex, normal: TAffineVector)
  4388. : Integer;
  4389. var
  4390. i, j: Integer;
  4391. bonesMatch: Boolean;
  4392. begin
  4393. Result := -1;
  4394. for i := 0 to Vertices.Count - 1 do
  4395. begin
  4396. bonesMatch := True;
  4397. for j := 0 to High(boneIDs) do
  4398. begin
  4399. if (boneIDs[j].BoneID <> VerticesBonesWeights^[i]^[j].BoneID) or (boneIDs[j].weight <> VerticesBonesWeights^[i]^[j].weight)
  4400. then
  4401. begin
  4402. bonesMatch := False;
  4403. Break;
  4404. end;
  4405. end;
  4406. if bonesMatch and VectorEquals(Vertices[i], vertex) and VectorEquals(normals[i], normal) then
  4407. begin
  4408. Result := i;
  4409. Break;
  4410. end;
  4411. end;
  4412. if Result < 0 then
  4413. begin
  4414. AddWeightedBones(boneIDs);
  4415. Vertices.Add(vertex);
  4416. Result := normals.Add(normal);
  4417. end;
  4418. end;
  4419. procedure TgxSkeletonMeshObject.PrepareBoneMatrixInvertedMeshes;
  4420. var
  4421. i, k, boneIndex: Integer;
  4422. invMesh: TgxBaseMeshObject;
  4423. invMat: TMatrix4f;
  4424. Bone: TgxSkeletonBone;
  4425. p: TVector4f;
  4426. begin
  4427. // cleanup existing stuff
  4428. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4429. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4430. FBoneMatrixInvertedMeshes.Clear;
  4431. // calculate
  4432. for k := 0 to BonesPerVertex - 1 do
  4433. begin
  4434. invMesh := TgxBaseMeshObject.Create;
  4435. FBoneMatrixInvertedMeshes.Add(invMesh);
  4436. invMesh.Vertices := Vertices;
  4437. invMesh.normals := normals;
  4438. for i := 0 to Vertices.Count - 1 do
  4439. begin
  4440. boneIndex := VerticesBonesWeights^[i]^[k].BoneID;
  4441. Bone := Owner.Owner.Skeleton.RootBones.BoneByID(boneIndex);
  4442. // transform point
  4443. MakePoint(p, Vertices[i]);
  4444. invMat := Bone.GlobalMatrix;
  4445. InvertMatrix(invMat);
  4446. p := VectorTransform(p, invMat);
  4447. invMesh.Vertices[i] := PAffineVector(@p)^;
  4448. // transform normal
  4449. SetVector(p, normals[i]);
  4450. invMat := Bone.GlobalMatrix;
  4451. invMat.W := NullHmgPoint;
  4452. InvertMatrix(invMat);
  4453. p := VectorTransform(p, invMat);
  4454. invMesh.normals[i] := PAffineVector(@p)^;
  4455. end;
  4456. end;
  4457. end;
  4458. procedure TgxSkeletonMeshObject.BackupBoneMatrixInvertedMeshes; // ragdoll
  4459. var
  4460. i: Integer;
  4461. bm: TgxBaseMeshObject;
  4462. begin
  4463. // cleanup existing stuff
  4464. for i := 0 to FBackupInvertedMeshes.Count - 1 do
  4465. TgxBaseMeshObject(FBackupInvertedMeshes[i]).Free;
  4466. FBackupInvertedMeshes.Clear;
  4467. // copy current stuff
  4468. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4469. begin
  4470. bm := TgxBaseMeshObject.Create;
  4471. bm.Assign(TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]));
  4472. FBackupInvertedMeshes.Add(bm);
  4473. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4474. end;
  4475. FBoneMatrixInvertedMeshes.Clear;
  4476. end;
  4477. procedure TgxSkeletonMeshObject.RestoreBoneMatrixInvertedMeshes; // ragdoll
  4478. var
  4479. i: Integer;
  4480. bm: TgxBaseMeshObject;
  4481. begin
  4482. // cleanup existing stuff
  4483. for i := 0 to FBoneMatrixInvertedMeshes.Count - 1 do
  4484. TgxBaseMeshObject(FBoneMatrixInvertedMeshes[i]).Free;
  4485. FBoneMatrixInvertedMeshes.Clear;
  4486. // restore the backup
  4487. for i := 0 to FBackupInvertedMeshes.Count - 1 do
  4488. begin
  4489. bm := TgxBaseMeshObject.Create;
  4490. bm.Assign(TgxBaseMeshObject(FBackupInvertedMeshes[i]));
  4491. FBoneMatrixInvertedMeshes.Add(bm);
  4492. TgxBaseMeshObject(FBackupInvertedMeshes[i]).Free;
  4493. end;
  4494. FBackupInvertedMeshes.Clear;
  4495. end;
  4496. procedure TgxSkeletonMeshObject.ApplyCurrentSkeletonFrame(normalize: Boolean);
  4497. var
  4498. i, j, BoneID: Integer;
  4499. refVertices, refNormals: TgxAffineVectorList;
  4500. n, nt: TVector4f;
  4501. Bone: TgxSkeletonBone;
  4502. Skeleton: TgxSkeleton;
  4503. tempvert, tempnorm: TAffineVector;
  4504. begin
  4505. with TgxBaseMeshObject(FBoneMatrixInvertedMeshes[0]) do
  4506. begin
  4507. refVertices := Vertices;
  4508. refNormals := normals;
  4509. end;
  4510. Skeleton := Owner.Owner.Skeleton;
  4511. n.W := 0;
  4512. if BonesPerVertex = 1 then
  4513. begin
  4514. // simple case, one bone per vertex
  4515. for i := 0 to refVertices.Count - 1 do
  4516. begin
  4517. BoneID := VerticesBonesWeights^[i]^[0].BoneID;
  4518. Bone := Skeleton.BoneByID(BoneID);
  4519. Vertices.list^[i] := VectorTransform(refVertices.list^[i], Bone.GlobalMatrix);
  4520. PAffineVector(@n)^ := refNormals.list^[i];
  4521. nt := VectorTransform(n, Bone.GlobalMatrix);
  4522. normals.list^[i] := PAffineVector(@nt)^;
  4523. end;
  4524. end
  4525. else
  4526. begin
  4527. // multiple bones per vertex
  4528. for i := 0 to refVertices.Count - 1 do
  4529. begin
  4530. Vertices.list^[i] := NullVector;
  4531. normals.list^[i] := NullVector;
  4532. for j := 0 to BonesPerVertex - 1 do
  4533. begin
  4534. with TgxBaseMeshObject(FBoneMatrixInvertedMeshes[j]) do
  4535. begin
  4536. refVertices := Vertices;
  4537. refNormals := normals;
  4538. end;
  4539. tempvert := NullVector;
  4540. tempnorm := NullVector;
  4541. if VerticesBonesWeights^[i]^[j].weight <> 0 then
  4542. begin
  4543. BoneID := VerticesBonesWeights^[i]^[j].BoneID;
  4544. Bone := Skeleton.BoneByID(BoneID);
  4545. CombineVector(tempvert, VectorTransform(refVertices.list^[i], Bone.GlobalMatrix),
  4546. VerticesBonesWeights^[i]^[j].weight);
  4547. PAffineVector(@n)^ := refNormals.list^[i];
  4548. n := VectorTransform(n, Bone.GlobalMatrix);
  4549. CombineVector(tempnorm, PAffineVector(@n)^, VerticesBonesWeights^[i]^[j].weight);
  4550. end;
  4551. AddVector(Vertices.list^[i], tempvert);
  4552. AddVector(normals.list^[i], tempnorm);
  4553. end;
  4554. end;
  4555. end;
  4556. if normalize then
  4557. normals.normalize;
  4558. end;
  4559. // ------------------
  4560. // ------------------ TgxFaceGroup ------------------
  4561. // ------------------
  4562. constructor TgxFaceGroup.CreateOwned(aOwner: TgxFaceGroups);
  4563. begin
  4564. FOwner := aOwner;
  4565. FLightMapIndex := -1;
  4566. Create;
  4567. if Assigned(FOwner) then
  4568. FOwner.Add(Self);
  4569. end;
  4570. destructor TgxFaceGroup.Destroy;
  4571. begin
  4572. if Assigned(FOwner) then
  4573. FOwner.Remove(Self);
  4574. inherited;
  4575. end;
  4576. procedure TgxFaceGroup.WriteToFiler(writer: TgxVirtualWriter);
  4577. begin
  4578. inherited WriteToFiler(writer);
  4579. with writer do
  4580. begin
  4581. if FLightMapIndex < 0 then
  4582. begin
  4583. WriteInteger(0); // Archive Version 0
  4584. WriteString(FMaterialName);
  4585. end
  4586. else
  4587. begin
  4588. WriteInteger(1); // Archive Version 1, added FLightMapIndex
  4589. WriteString(FMaterialName);
  4590. WriteInteger(FLightMapIndex);
  4591. end;
  4592. end;
  4593. end;
  4594. procedure TgxFaceGroup.ReadFromFiler(reader: TgxVirtualReader);
  4595. var
  4596. archiveVersion: Integer;
  4597. begin
  4598. inherited ReadFromFiler(reader);
  4599. archiveVersion := reader.ReadInteger;
  4600. if archiveVersion in [0 .. 1] then
  4601. with reader do
  4602. begin
  4603. FMaterialName := ReadString;
  4604. if archiveVersion >= 1 then
  4605. FLightMapIndex := ReadInteger
  4606. else
  4607. FLightMapIndex := -1;
  4608. end
  4609. else
  4610. RaiseFilerException(archiveVersion);
  4611. end;
  4612. procedure TgxFaceGroup.AttachLightmap(lightMap: TgxTexture; var mrci: TgxRenderContextInfo);
  4613. begin
  4614. /// if GL_ARB_multitexture then
  4615. with lightMap do
  4616. begin
  4617. Assert(Image.NativeTextureTarget = ttTexture2D);
  4618. mrci.gxStates.TextureBinding[1, ttTexture2D] := Handle;
  4619. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  4620. mrci.gxStates.ActiveTexture := 0;
  4621. end;
  4622. end;
  4623. procedure TgxFaceGroup.AttachOrDetachLightmap(var mrci: TgxRenderContextInfo);
  4624. var
  4625. libMat: TgxLibMaterial;
  4626. begin
  4627. /// if GL_ARB_multitexture then
  4628. if (not mrci.ignoreMaterials) and Assigned(mrci.LightmapLibrary) then
  4629. begin
  4630. if Owner.Owner.FLastLightMapIndex <> LightMapIndex then
  4631. begin
  4632. Owner.Owner.FLastLightMapIndex := LightMapIndex;
  4633. if LightMapIndex >= 0 then
  4634. begin
  4635. // attach and activate lightmap
  4636. Assert(LightMapIndex < TgxMaterialLibrary(mrci.LightmapLibrary).Materials.Count);
  4637. libMat := TgxMaterialLibrary(mrci.LightmapLibrary).Materials[LightMapIndex];
  4638. AttachLightmap(libMat.Material.Texture, mrci);
  4639. Owner.Owner.EnableLightMapArray(mrci);
  4640. end
  4641. else
  4642. begin
  4643. // desactivate lightmap
  4644. Owner.Owner.DisableLightMapArray(mrci);
  4645. end;
  4646. end;
  4647. end;
  4648. end;
  4649. procedure TgxFaceGroup.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  4650. begin
  4651. if (FMaterialName <> '') and (matLib <> nil) then
  4652. FMaterialCache := matLib.Materials.GetLibMaterialByName(FMaterialName)
  4653. else
  4654. FMaterialCache := nil;
  4655. end;
  4656. procedure TgxFaceGroup.DropMaterialLibraryCache;
  4657. begin
  4658. FMaterialCache := nil;
  4659. end;
  4660. procedure TgxFaceGroup.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  4661. aNormals: TgxAffineVectorList = nil);
  4662. begin
  4663. // nothing
  4664. end;
  4665. procedure TgxFaceGroup.Reverse;
  4666. begin
  4667. // nothing
  4668. end;
  4669. procedure TgxFaceGroup.Prepare;
  4670. begin
  4671. // nothing
  4672. end;
  4673. // ------------------
  4674. // ------------------ TfgxVertexIndexList ------------------
  4675. // ------------------
  4676. constructor TfgxVertexIndexList.Create;
  4677. begin
  4678. inherited;
  4679. FVertexIndices := TgxIntegerList.Create;
  4680. FMode := fgmmTriangles;
  4681. end;
  4682. destructor TfgxVertexIndexList.Destroy;
  4683. begin
  4684. FVertexIndices.Free;
  4685. FIndexVBO.Free;
  4686. inherited;
  4687. end;
  4688. procedure TfgxVertexIndexList.WriteToFiler(writer: TgxVirtualWriter);
  4689. begin
  4690. inherited WriteToFiler(writer);
  4691. with writer do
  4692. begin
  4693. WriteInteger(0); // Archive Version 0
  4694. FVertexIndices.WriteToFiler(writer);
  4695. WriteInteger(Integer(FMode));
  4696. end;
  4697. end;
  4698. procedure TfgxVertexIndexList.ReadFromFiler(reader: TgxVirtualReader);
  4699. var
  4700. archiveVersion: Integer;
  4701. begin
  4702. inherited ReadFromFiler(reader);
  4703. archiveVersion := reader.ReadInteger;
  4704. if archiveVersion = 0 then
  4705. with reader do
  4706. begin
  4707. FVertexIndices.ReadFromFiler(reader);
  4708. FMode := TgxFaceGroupMeshMode(ReadInteger);
  4709. InvalidateVBO;
  4710. end
  4711. else
  4712. RaiseFilerException(archiveVersion);
  4713. end;
  4714. procedure TfgxVertexIndexList.SetupVBO;
  4715. const
  4716. BufferUsage = GL_STATIC_DRAW;
  4717. begin
  4718. if not Assigned(FIndexVBO) then
  4719. FIndexVBO := TgxVBOElementArrayHandle.Create;
  4720. FIndexVBO.AllocateHandle;
  4721. if FIndexVBO.IsDataNeedUpdate then
  4722. begin
  4723. FIndexVBO.BindBufferData(vertexIndices.list, SizeOf(Integer) * vertexIndices.Count, BufferUsage);
  4724. FIndexVBO.NotifyDataUpdated;
  4725. end;
  4726. end;
  4727. procedure TfgxVertexIndexList.SetVertexIndices(const val: TgxIntegerList);
  4728. begin
  4729. FVertexIndices.Assign(val);
  4730. InvalidateVBO;
  4731. end;
  4732. procedure TfgxVertexIndexList.BuildList(var mrci: TgxRenderContextInfo);
  4733. const
  4734. cFaceGroupMeshModeToOpenGL: array [TgxFaceGroupMeshMode] of Integer = (GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLES,
  4735. GL_TRIANGLE_FAN, GL_QUADS);
  4736. begin
  4737. if vertexIndices.Count = 0 then
  4738. Exit;
  4739. Owner.Owner.DeclareArraysToOpenGL(mrci, False);
  4740. AttachOrDetachLightmap(mrci);
  4741. if Owner.Owner.UseVBO then
  4742. begin
  4743. SetupVBO;
  4744. FIndexVBO.Bind;
  4745. glDrawElements(cFaceGroupMeshModeToOpenGL[mode], vertexIndices.Count, GL_UNSIGNED_INT, nil);
  4746. FIndexVBO.UnBind;
  4747. end
  4748. else
  4749. begin
  4750. glDrawElements(cFaceGroupMeshModeToOpenGL[mode], vertexIndices.Count, GL_UNSIGNED_INT, vertexIndices.list);
  4751. end;
  4752. end;
  4753. procedure TfgxVertexIndexList.AddToList(Source, destination: TgxAffineVectorList; indices: TgxIntegerList);
  4754. var
  4755. i, n: Integer;
  4756. begin
  4757. if not Assigned(destination) then
  4758. Exit;
  4759. if indices.Count < 3 then
  4760. Exit;
  4761. case mode of
  4762. fgmmTriangles, fgmmFlatTriangles:
  4763. begin
  4764. n := (indices.Count div 3) * 3;
  4765. if Source.Count > 0 then
  4766. begin
  4767. destination.AdjustCapacityToAtLeast(destination.Count + n);
  4768. for i := 0 to n - 1 do
  4769. destination.Add(Source[indices.list^[i]]);
  4770. end
  4771. else
  4772. destination.AddNulls(destination.Count + n);
  4773. end;
  4774. fgmmTriangleStrip:
  4775. begin
  4776. if Source.Count > 0 then
  4777. ConvertStripToList(Source, indices, destination)
  4778. else
  4779. destination.AddNulls(destination.Count + (indices.Count - 2) * 3);
  4780. end;
  4781. fgmmTriangleFan:
  4782. begin
  4783. n := (indices.Count - 2) * 3;
  4784. if Source.Count > 0 then
  4785. begin
  4786. destination.AdjustCapacityToAtLeast(destination.Count + n);
  4787. for i := 2 to vertexIndices.Count - 1 do
  4788. begin
  4789. destination.Add(Source[indices.list^[0]], Source[indices.list^[i - 1]], Source[indices.list^[i]]);
  4790. end;
  4791. end
  4792. else
  4793. destination.AddNulls(destination.Count + n);
  4794. end;
  4795. fgmmQuads:
  4796. begin
  4797. n := indices.Count div 4;
  4798. if Source.Count > 0 then
  4799. begin
  4800. destination.AdjustCapacityToAtLeast(destination.Count + n * 6);
  4801. i := 0;
  4802. while n > 0 do
  4803. begin
  4804. destination.Add(Source[indices.list^[i]], Source[indices.list^[i + 1]], Source[indices.list^[i + 2]]);
  4805. destination.Add(Source[indices.list^[i]], Source[indices.list^[i + 2]], Source[indices.list^[i + 3]]);
  4806. Inc(i, 4);
  4807. Dec(n);
  4808. end;
  4809. end
  4810. else
  4811. destination.AddNulls(destination.Count + n * 6);
  4812. end;
  4813. else
  4814. Assert(False);
  4815. end;
  4816. end;
  4817. procedure TfgxVertexIndexList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  4818. aNormals: TgxAffineVectorList = nil);
  4819. var
  4820. mo: TgxMeshObject;
  4821. begin
  4822. mo := Owner.Owner;
  4823. AddToList(mo.Vertices, aList, vertexIndices);
  4824. AddToList(mo.texCoords, aTexCoords, vertexIndices);
  4825. AddToList(mo.normals, aNormals, vertexIndices);
  4826. InvalidateVBO;
  4827. end;
  4828. function TfgxVertexIndexList.TriangleCount: Integer;
  4829. begin
  4830. case mode of
  4831. fgmmTriangles, fgmmFlatTriangles:
  4832. Result := vertexIndices.Count div 3;
  4833. fgmmTriangleFan, fgmmTriangleStrip:
  4834. begin
  4835. Result := vertexIndices.Count - 2;
  4836. if Result < 0 then
  4837. Result := 0;
  4838. end;
  4839. fgmmQuads:
  4840. Result := vertexIndices.Count div 2;
  4841. else
  4842. Result := 0;
  4843. Assert(False);
  4844. end;
  4845. end;
  4846. procedure TfgxVertexIndexList.Reverse;
  4847. begin
  4848. vertexIndices.Reverse;
  4849. InvalidateVBO;
  4850. end;
  4851. procedure TfgxVertexIndexList.Add(idx: Integer);
  4852. begin
  4853. FVertexIndices.Add(idx);
  4854. InvalidateVBO;
  4855. end;
  4856. procedure TfgxVertexIndexList.GetExtents(var min, max: TAffineVector);
  4857. var
  4858. i, k: Integer;
  4859. f: Single;
  4860. ref: PFloatArray;
  4861. const
  4862. cBigValue: Single = 1E50;
  4863. cSmallValue: Single = -1E50;
  4864. begin
  4865. SetVector(min, cBigValue, cBigValue, cBigValue);
  4866. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  4867. for i := 0 to vertexIndices.Count - 1 do
  4868. begin
  4869. ref := Owner.Owner.Vertices.ItemAddress[vertexIndices[i]];
  4870. for k := 0 to 2 do
  4871. begin
  4872. f := ref^[k];
  4873. if f < min.v[k] then
  4874. min.v[k] := f;
  4875. if f > max.v[k] then
  4876. max.v[k] := f;
  4877. end;
  4878. end;
  4879. end;
  4880. procedure TfgxVertexIndexList.ConvertToList;
  4881. var
  4882. i: Integer;
  4883. bufList: TgxIntegerList;
  4884. begin
  4885. if vertexIndices.Count >= 3 then
  4886. begin
  4887. case mode of
  4888. fgmmTriangleStrip:
  4889. begin
  4890. bufList := TgxIntegerList.Create;
  4891. try
  4892. ConvertStripToList(vertexIndices, bufList);
  4893. vertexIndices := bufList;
  4894. finally
  4895. bufList.Free;
  4896. end;
  4897. FMode := fgmmTriangles;
  4898. end;
  4899. fgmmTriangleFan:
  4900. begin
  4901. bufList := TgxIntegerList.Create;
  4902. try
  4903. for i := 0 to vertexIndices.Count - 3 do
  4904. bufList.Add(vertexIndices[0], vertexIndices[i], vertexIndices[i + 1]);
  4905. vertexIndices := bufList;
  4906. finally
  4907. bufList.Free;
  4908. end;
  4909. FMode := fgmmTriangles;
  4910. end;
  4911. end;
  4912. InvalidateVBO;
  4913. end;
  4914. end;
  4915. function TfgxVertexIndexList.GetNormal: TAffineVector;
  4916. begin
  4917. if vertexIndices.Count < 3 then
  4918. Result := NullVector
  4919. else
  4920. with Owner.Owner.Vertices do
  4921. CalcPlaneNormal(Items[vertexIndices[0]], Items[vertexIndices[1]], Items[vertexIndices[2]], Result);
  4922. end;
  4923. procedure TfgxVertexIndexList.InvalidateVBO;
  4924. begin
  4925. if Assigned(FIndexVBO) then
  4926. FIndexVBO.NotifyChangesOfData;
  4927. end;
  4928. // ------------------
  4929. // ------------------ TFGVertexNormalTexIndexList ------------------
  4930. // ------------------
  4931. constructor TFGVertexNormalTexIndexList.Create;
  4932. begin
  4933. inherited;
  4934. FNormalIndices := TgxIntegerList.Create;
  4935. FTexCoordIndices := TgxIntegerList.Create;
  4936. end;
  4937. destructor TFGVertexNormalTexIndexList.Destroy;
  4938. begin
  4939. FTexCoordIndices.Free;
  4940. FNormalIndices.Free;
  4941. inherited;
  4942. end;
  4943. procedure TFGVertexNormalTexIndexList.WriteToFiler(writer: TgxVirtualWriter);
  4944. begin
  4945. inherited WriteToFiler(writer);
  4946. with writer do
  4947. begin
  4948. WriteInteger(0); // Archive Version 0
  4949. FNormalIndices.WriteToFiler(writer);
  4950. FTexCoordIndices.WriteToFiler(writer);
  4951. end;
  4952. end;
  4953. procedure TFGVertexNormalTexIndexList.ReadFromFiler(reader: TgxVirtualReader);
  4954. var
  4955. archiveVersion: Integer;
  4956. begin
  4957. inherited ReadFromFiler(reader);
  4958. archiveVersion := reader.ReadInteger;
  4959. if archiveVersion = 0 then
  4960. with reader do
  4961. begin
  4962. FNormalIndices.ReadFromFiler(reader);
  4963. FTexCoordIndices.ReadFromFiler(reader);
  4964. end
  4965. else
  4966. RaiseFilerException(archiveVersion);
  4967. end;
  4968. procedure TFGVertexNormalTexIndexList.SetNormalIndices(const val: TgxIntegerList);
  4969. begin
  4970. FNormalIndices.Assign(val);
  4971. end;
  4972. procedure TFGVertexNormalTexIndexList.SetTexCoordIndices(const val: TgxIntegerList);
  4973. begin
  4974. FTexCoordIndices.Assign(val);
  4975. end;
  4976. procedure TFGVertexNormalTexIndexList.BuildList(var mrci: TgxRenderContextInfo);
  4977. var
  4978. i: Integer;
  4979. vertexPool: PAffineVectorArray;
  4980. normalPool: PAffineVectorArray;
  4981. texCoordPool: PAffineVectorArray;
  4982. colorPool: PVectorArray;
  4983. normalIdxList, texCoordIdxList, vertexIdxList: PIntegerVector;
  4984. begin
  4985. Assert(((TexCoordIndices.Count = 0) or (vertexIndices.Count <= TexCoordIndices.Count)) and
  4986. ((normalIndices.Count = 0) or (vertexIndices.Count <= normalIndices.Count)));
  4987. vertexPool := Owner.Owner.Vertices.list;
  4988. normalPool := Owner.Owner.normals.list;
  4989. colorPool := Owner.Owner.Colors.list;
  4990. texCoordPool := Owner.Owner.texCoords.list;
  4991. case mode of
  4992. fgmmTriangles, fgmmFlatTriangles:
  4993. glBegin(GL_TRIANGLES);
  4994. fgmmTriangleStrip:
  4995. glBegin(GL_TRIANGLE_STRIP);
  4996. fgmmTriangleFan:
  4997. glBegin(GL_TRIANGLE_FAN);
  4998. else
  4999. Assert(False);
  5000. end;
  5001. vertexIdxList := vertexIndices.list;
  5002. if normalIndices.Count > 0 then
  5003. normalIdxList := normalIndices.list
  5004. else
  5005. normalIdxList := vertexIdxList;
  5006. if TexCoordIndices.Count > 0 then
  5007. texCoordIdxList := TexCoordIndices.list
  5008. else
  5009. texCoordIdxList := vertexIdxList;
  5010. for i := 0 to vertexIndices.Count - 1 do
  5011. begin
  5012. glNormal3fv(@normalPool[normalIdxList^[i]]);
  5013. if Assigned(colorPool) then
  5014. glColor4fv(@colorPool[vertexIdxList^[i]]);
  5015. if Assigned(texCoordPool) then
  5016. glTexCoord2fv(@texCoordPool[texCoordIdxList^[i]]);
  5017. glVertex3fv(@vertexPool[vertexIdxList^[i]]);
  5018. end;
  5019. glEnd;
  5020. end;
  5021. procedure TFGVertexNormalTexIndexList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5022. aNormals: TgxAffineVectorList = nil);
  5023. begin
  5024. AddToList(Owner.Owner.Vertices, aList, vertexIndices);
  5025. AddToList(Owner.Owner.texCoords, aTexCoords, TexCoordIndices);
  5026. AddToList(Owner.Owner.normals, aNormals, normalIndices);
  5027. end;
  5028. procedure TFGVertexNormalTexIndexList.Add(vertexIdx, normalIdx, texCoordIdx: Integer);
  5029. begin
  5030. inherited Add(vertexIdx);
  5031. FNormalIndices.Add(normalIdx);
  5032. FTexCoordIndices.Add(texCoordIdx);
  5033. end;
  5034. // ------------------
  5035. // ------------------ TFGIndexTexCoordList ------------------
  5036. // ------------------
  5037. constructor TFGIndexTexCoordList.Create;
  5038. begin
  5039. inherited;
  5040. FTexCoords := TgxAffineVectorList.Create;
  5041. end;
  5042. destructor TFGIndexTexCoordList.Destroy;
  5043. begin
  5044. FTexCoords.Free;
  5045. inherited;
  5046. end;
  5047. procedure TFGIndexTexCoordList.WriteToFiler(writer: TgxVirtualWriter);
  5048. begin
  5049. inherited WriteToFiler(writer);
  5050. with writer do
  5051. begin
  5052. WriteInteger(0); // Archive Version 0
  5053. FTexCoords.WriteToFiler(writer);
  5054. end;
  5055. end;
  5056. procedure TFGIndexTexCoordList.ReadFromFiler(reader: TgxVirtualReader);
  5057. var
  5058. archiveVersion: Integer;
  5059. begin
  5060. inherited ReadFromFiler(reader);
  5061. archiveVersion := reader.ReadInteger;
  5062. if archiveVersion = 0 then
  5063. with reader do
  5064. begin
  5065. FTexCoords.ReadFromFiler(reader);
  5066. end
  5067. else
  5068. RaiseFilerException(archiveVersion);
  5069. end;
  5070. procedure TFGIndexTexCoordList.SetTexCoords(const val: TgxAffineVectorList);
  5071. begin
  5072. FTexCoords.Assign(val);
  5073. end;
  5074. procedure TFGIndexTexCoordList.BuildList(var mrci: TgxRenderContextInfo);
  5075. var
  5076. i, k: Integer;
  5077. texCoordPool: PAffineVectorArray;
  5078. vertexPool: PAffineVectorArray;
  5079. normalPool: PAffineVectorArray;
  5080. indicesPool: PIntegerArray;
  5081. colorPool: PVectorArray;
  5082. gotColor: Boolean;
  5083. begin
  5084. Assert(vertexIndices.Count = texCoords.Count);
  5085. texCoordPool := texCoords.list;
  5086. vertexPool := Owner.Owner.Vertices.list;
  5087. indicesPool := @vertexIndices.list[0];
  5088. colorPool := @Owner.Owner.Colors.list[0];
  5089. gotColor := (Owner.Owner.Vertices.Count = Owner.Owner.Colors.Count);
  5090. case mode of
  5091. fgmmTriangles:
  5092. glBegin(GL_TRIANGLES);
  5093. fgmmFlatTriangles:
  5094. glBegin(GL_TRIANGLES);
  5095. fgmmTriangleStrip:
  5096. glBegin(GL_TRIANGLE_STRIP);
  5097. fgmmTriangleFan:
  5098. glBegin(GL_TRIANGLE_FAN);
  5099. fgmmQuads:
  5100. glBegin(GL_QUADS);
  5101. else
  5102. Assert(False);
  5103. end;
  5104. if Owner.Owner.normals.Count = Owner.Owner.Vertices.Count then
  5105. begin
  5106. normalPool := Owner.Owner.normals.list;
  5107. for i := 0 to vertexIndices.Count - 1 do
  5108. begin
  5109. glTexCoord2fv(@texCoordPool[i]);
  5110. k := indicesPool[i];
  5111. if gotColor then
  5112. glColor4fv(@colorPool[k]);
  5113. glNormal3fv(@normalPool[k]);
  5114. glVertex3fv(@vertexPool[k]);
  5115. end;
  5116. end
  5117. else
  5118. begin
  5119. for i := 0 to vertexIndices.Count - 1 do
  5120. begin
  5121. glTexCoord2fv(@texCoordPool[i]);
  5122. if gotColor then
  5123. glColor4fv(@colorPool[indicesPool[i]]);
  5124. glVertex3fv(@vertexPool[indicesPool[i]]);
  5125. end;
  5126. end;
  5127. glEnd;
  5128. /// CheckOpenGLError;
  5129. end;
  5130. procedure TFGIndexTexCoordList.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5131. aNormals: TgxAffineVectorList = nil);
  5132. var
  5133. i, n: Integer;
  5134. texCoordList: TgxAffineVectorList;
  5135. begin
  5136. AddToList(Owner.Owner.Vertices, aList, vertexIndices);
  5137. AddToList(Owner.Owner.normals, aNormals, vertexIndices);
  5138. texCoordList := Self.texCoords;
  5139. case mode of
  5140. fgmmTriangles, fgmmFlatTriangles:
  5141. begin
  5142. if Assigned(aTexCoords) then
  5143. begin
  5144. n := (vertexIndices.Count div 3) * 3;
  5145. aTexCoords.AdjustCapacityToAtLeast(aTexCoords.Count + n);
  5146. for i := 0 to n - 1 do
  5147. aTexCoords.Add(texCoordList[i]);
  5148. end;
  5149. end;
  5150. fgmmTriangleStrip:
  5151. begin
  5152. if Assigned(aTexCoords) then
  5153. ConvertStripToList(aTexCoords, texCoordList);
  5154. end;
  5155. fgmmTriangleFan:
  5156. begin
  5157. if Assigned(aTexCoords) then
  5158. begin
  5159. aTexCoords.AdjustCapacityToAtLeast(aTexCoords.Count + (vertexIndices.Count - 2) * 3);
  5160. for i := 2 to vertexIndices.Count - 1 do
  5161. begin
  5162. aTexCoords.Add(texCoordList[0], texCoordList[i - 1], texCoordList[i]);
  5163. end;
  5164. end;
  5165. end;
  5166. else
  5167. Assert(False);
  5168. end;
  5169. end;
  5170. procedure TFGIndexTexCoordList.Add(idx: Integer; const texCoord: TAffineVector);
  5171. begin
  5172. texCoords.Add(texCoord);
  5173. inherited Add(idx);
  5174. end;
  5175. procedure TFGIndexTexCoordList.Add(idx: Integer; const s, t: Single);
  5176. begin
  5177. texCoords.Add(s, t, 0);
  5178. inherited Add(idx);
  5179. end;
  5180. // ------------------
  5181. // ------------------ TgxFaceGroups ------------------
  5182. // ------------------
  5183. constructor TgxFaceGroups.CreateOwned(aOwner: TgxMeshObject);
  5184. begin
  5185. FOwner := aOwner;
  5186. Create;
  5187. end;
  5188. destructor TgxFaceGroups.Destroy;
  5189. begin
  5190. Clear;
  5191. inherited;
  5192. end;
  5193. procedure TgxFaceGroups.ReadFromFiler(reader: TgxVirtualReader);
  5194. var
  5195. i: Integer;
  5196. begin
  5197. inherited;
  5198. for i := 0 to Count - 1 do
  5199. Items[i].FOwner := Self;
  5200. end;
  5201. procedure TgxFaceGroups.Clear;
  5202. var
  5203. i: Integer;
  5204. fg: TgxFaceGroup;
  5205. begin
  5206. for i := 0 to Count - 1 do
  5207. begin
  5208. fg := GetFaceGroup(i);
  5209. if Assigned(fg) then
  5210. begin
  5211. fg.FOwner := nil;
  5212. fg.Free;
  5213. end;
  5214. end;
  5215. inherited;
  5216. end;
  5217. function TgxFaceGroups.GetFaceGroup(Index: Integer): TgxFaceGroup;
  5218. begin
  5219. Result := TgxFaceGroup(list^[Index]);
  5220. end;
  5221. procedure TgxFaceGroups.PrepareMaterialLibraryCache(matLib: TgxMaterialLibrary);
  5222. var
  5223. i: Integer;
  5224. begin
  5225. for i := 0 to Count - 1 do
  5226. TgxFaceGroup(list^[i]).PrepareMaterialLibraryCache(matLib);
  5227. end;
  5228. procedure TgxFaceGroups.DropMaterialLibraryCache;
  5229. var
  5230. i: Integer;
  5231. begin
  5232. for i := 0 to Count - 1 do
  5233. TgxFaceGroup(list^[i]).DropMaterialLibraryCache;
  5234. end;
  5235. procedure TgxFaceGroups.AddToTriangles(aList: TgxAffineVectorList; aTexCoords: TgxAffineVectorList = nil;
  5236. aNormals: TgxAffineVectorList = nil);
  5237. var
  5238. i: Integer;
  5239. begin
  5240. for i := 0 to Count - 1 do
  5241. Items[i].AddToTriangles(aList, aTexCoords, aNormals);
  5242. end;
  5243. function TgxFaceGroups.MaterialLibrary: TgxMaterialLibrary;
  5244. var
  5245. mol: TgxMeshObjectList;
  5246. bm: TgxBaseMesh;
  5247. begin
  5248. if Assigned(Owner) then
  5249. begin
  5250. mol := Owner.Owner;
  5251. if Assigned(mol) then
  5252. begin
  5253. bm := mol.Owner;
  5254. if Assigned(bm) then
  5255. begin
  5256. Result := bm.MaterialLibrary;;
  5257. Exit;
  5258. end;
  5259. end;
  5260. end;
  5261. Result := nil;
  5262. end;
  5263. function CompareMaterials(item1, item2: TObject): Integer;
  5264. function MaterialIsOpaque(fg: TgxFaceGroup): Boolean;
  5265. var
  5266. libMat: TgxLibMaterial;
  5267. begin
  5268. libMat := fg.MaterialCache;
  5269. Result := (not Assigned(libMat)) or (not libMat.Material.Blended);
  5270. end;
  5271. var
  5272. fg1, fg2: TgxFaceGroup;
  5273. opaque1, opaque2: Boolean;
  5274. begin
  5275. fg1 := TgxFaceGroup(item1);
  5276. opaque1 := MaterialIsOpaque(fg1);
  5277. fg2 := TgxFaceGroup(item2);
  5278. opaque2 := MaterialIsOpaque(fg2);
  5279. if opaque1 = opaque2 then
  5280. begin
  5281. Result := CompareStr(fg1.MaterialName, fg2.MaterialName);
  5282. if Result = 0 then
  5283. Result := fg1.LightMapIndex - fg2.LightMapIndex;
  5284. end
  5285. else if opaque1 then
  5286. Result := -1
  5287. else
  5288. Result := 1;
  5289. end;
  5290. procedure TgxFaceGroups.SortByMaterial;
  5291. begin
  5292. PrepareMaterialLibraryCache(Owner.Owner.Owner.MaterialLibrary);
  5293. Sort(@CompareMaterials);
  5294. end;
  5295. // ------------------
  5296. // ------------------ TgxVectorFile ------------------
  5297. // ------------------
  5298. constructor TgxVectorFile.Create(aOwner: TPersistent);
  5299. begin
  5300. Assert(aOwner is TgxBaseMesh);
  5301. inherited;
  5302. end;
  5303. function TgxVectorFile.Owner: TgxBaseMesh;
  5304. begin
  5305. Result := TgxBaseMesh(GetOwner);
  5306. end;
  5307. procedure TgxVectorFile.SetNormalsOrientation(const val: TMeshNormalsOrientation);
  5308. begin
  5309. FNormalsOrientation := val;
  5310. end;
  5311. // ------------------
  5312. // ------------------ TgxGLSMVectorFile ------------------
  5313. // ------------------
  5314. class function TgxGLSMVectorFile.Capabilities: TDataFileCapabilities;
  5315. begin
  5316. Result := [dfcRead, dfcWrite];
  5317. end;
  5318. procedure TgxGLSMVectorFile.LoadFromStream(aStream: TStream);
  5319. begin
  5320. Owner.MeshObjects.LoadFromStream(aStream);
  5321. end;
  5322. procedure TgxGLSMVectorFile.SaveToStream(aStream: TStream);
  5323. begin
  5324. Owner.MeshObjects.SaveToStream(aStream);
  5325. end;
  5326. // ------------------
  5327. // ------------------ TgxBaseMesh ------------------
  5328. // ------------------
  5329. constructor TgxBaseMesh.Create(aOwner: TComponent);
  5330. begin
  5331. inherited Create(aOwner);
  5332. if FMeshObjects = nil then
  5333. FMeshObjects := TgxMeshObjectList.CreateOwned(Self);
  5334. if FSkeleton = nil then
  5335. FSkeleton := TgxSkeleton.CreateOwned(Self);
  5336. FUseMeshMaterials := True;
  5337. FAutoCentering := [];
  5338. FAxisAlignedDimensionsCache.X := -1;
  5339. FBaryCenterOffsetChanged := True;
  5340. FAutoScaling := TgxCoordinates.CreateInitialized(Self, XYZWHmgVector, csPoint);
  5341. end;
  5342. destructor TgxBaseMesh.Destroy;
  5343. begin
  5344. FConnectivity.Free;
  5345. DropMaterialLibraryCache;
  5346. FSkeleton.Free;
  5347. FMeshObjects.Free;
  5348. FAutoScaling.Free;
  5349. inherited Destroy;
  5350. end;
  5351. procedure TgxBaseMesh.Assign(Source: TPersistent);
  5352. begin
  5353. if Source is TgxBaseMesh then
  5354. begin
  5355. FSkeleton.Clear;
  5356. FNormalsOrientation := TgxBaseMesh(Source).FNormalsOrientation;
  5357. FMaterialLibrary := TgxBaseMesh(Source).FMaterialLibrary;
  5358. FLightmapLibrary := TgxBaseMesh(Source).FLightmapLibrary;
  5359. FAxisAlignedDimensionsCache := TgxBaseMesh(Source).FAxisAlignedDimensionsCache;
  5360. FBaryCenterOffset := TgxBaseMesh(Source).FBaryCenterOffset;
  5361. FUseMeshMaterials := TgxBaseMesh(Source).FUseMeshMaterials;
  5362. FOverlaySkeleton := TgxBaseMesh(Source).FOverlaySkeleton;
  5363. FIgnoreMissingTextures := TgxBaseMesh(Source).FIgnoreMissingTextures;
  5364. FAutoCentering := TgxBaseMesh(Source).FAutoCentering;
  5365. FAutoScaling.Assign(TgxBaseMesh(Source).FAutoScaling);
  5366. FSkeleton.Assign(TgxBaseMesh(Source).FSkeleton);
  5367. FSkeleton.RootBones.PrepareGlobalMatrices;
  5368. FMeshObjects.Assign(TgxBaseMesh(Source).FMeshObjects);
  5369. end;
  5370. inherited Assign(Source);
  5371. end;
  5372. procedure TgxBaseMesh.LoadFromFile(const filename: string);
  5373. var
  5374. fs: TStream;
  5375. begin
  5376. FLastLoadedFilename := '';
  5377. if filename <> '' then
  5378. begin
  5379. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  5380. try
  5381. LoadFromStream(filename, fs);
  5382. FLastLoadedFilename := filename;
  5383. finally
  5384. fs.Free;
  5385. end;
  5386. end;
  5387. end;
  5388. procedure TgxBaseMesh.LoadFromStream(const filename: string; aStream: TStream);
  5389. var
  5390. newVectorFile: TgxVectorFile;
  5391. VectorFileClass: TgxVectorFileClass;
  5392. begin
  5393. FLastLoadedFilename := '';
  5394. if filename <> '' then
  5395. begin
  5396. MeshObjects.Clear;
  5397. Skeleton.Clear;
  5398. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5399. newVectorFile := VectorFileClass.Create(Self);
  5400. try
  5401. newVectorFile.ResourceName := filename;
  5402. PrepareVectorFile(newVectorFile);
  5403. if Assigned(Scene) then
  5404. Scene.BeginUpdate;
  5405. try
  5406. newVectorFile.LoadFromStream(aStream);
  5407. FLastLoadedFilename := filename;
  5408. finally
  5409. if Assigned(Scene) then
  5410. Scene.EndUpdate;
  5411. end;
  5412. finally
  5413. newVectorFile.Free;
  5414. end;
  5415. PerformAutoScaling;
  5416. PerformAutoCentering;
  5417. PrepareMesh;
  5418. end;
  5419. end;
  5420. procedure TgxBaseMesh.SaveToFile(const filename: string);
  5421. var
  5422. fs: TStream;
  5423. begin
  5424. if filename <> '' then
  5425. begin
  5426. fs := TFileStream.Create(filename, fmCreate);
  5427. try
  5428. SaveToStream(filename, fs);
  5429. finally
  5430. fs.Free;
  5431. end;
  5432. end;
  5433. end;
  5434. procedure TgxBaseMesh.SaveToStream(const filename: string; aStream: TStream);
  5435. var
  5436. newVectorFile: TgxVectorFile;
  5437. VectorFileClass: TgxVectorFileClass;
  5438. begin
  5439. if filename <> '' then
  5440. begin
  5441. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5442. newVectorFile := VectorFileClass.Create(Self);
  5443. try
  5444. newVectorFile.ResourceName := filename;
  5445. PrepareVectorFile(newVectorFile);
  5446. newVectorFile.SaveToStream(aStream);
  5447. finally
  5448. newVectorFile.Free;
  5449. end;
  5450. end;
  5451. end;
  5452. procedure TgxBaseMesh.AddDataFromFile(const filename: string);
  5453. var
  5454. fs: TStream;
  5455. begin
  5456. if filename <> '' then
  5457. begin
  5458. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  5459. try
  5460. AddDataFromStream(filename, fs);
  5461. finally
  5462. fs.Free;
  5463. end;
  5464. end;
  5465. end;
  5466. procedure TgxBaseMesh.AddDataFromStream(const filename: string; aStream: TStream);
  5467. var
  5468. newVectorFile: TgxVectorFile;
  5469. VectorFileClass: TgxVectorFileClass;
  5470. begin
  5471. if filename <> '' then
  5472. begin
  5473. VectorFileClass := GetVectorFileFormats.FindFromFileName(filename);
  5474. newVectorFile := VectorFileClass.Create(Self);
  5475. newVectorFile.ResourceName := filename;
  5476. PrepareVectorFile(newVectorFile);
  5477. try
  5478. if Assigned(Scene) then
  5479. Scene.BeginUpdate;
  5480. newVectorFile.LoadFromStream(aStream);
  5481. if Assigned(Scene) then
  5482. Scene.EndUpdate;
  5483. finally
  5484. newVectorFile.Free;
  5485. end;
  5486. PrepareMesh;
  5487. end;
  5488. end;
  5489. procedure TgxBaseMesh.GetExtents(out min, max: TAffineVector);
  5490. var
  5491. i, k: Integer;
  5492. lMin, lMax: TAffineVector;
  5493. const
  5494. cBigValue: Single = 1E50;
  5495. cSmallValue: Single = -1E50;
  5496. begin
  5497. SetVector(min, cBigValue, cBigValue, cBigValue);
  5498. SetVector(max, cSmallValue, cSmallValue, cSmallValue);
  5499. for i := 0 to MeshObjects.Count - 1 do
  5500. begin
  5501. TgxMeshObject(MeshObjects[i]).GetExtents(lMin, lMax);
  5502. for k := 0 to 2 do
  5503. begin
  5504. if lMin.v[k] < min.v[k] then
  5505. min.v[k] := lMin.v[k];
  5506. if lMax.v[k] > max.v[k] then
  5507. max.v[k] := lMax.v[k];
  5508. end;
  5509. end;
  5510. end;
  5511. function TgxBaseMesh.GetBarycenter: TAffineVector;
  5512. var
  5513. i, nb: Integer;
  5514. begin
  5515. Result := NullVector;
  5516. nb := 0;
  5517. for i := 0 to MeshObjects.Count - 1 do
  5518. TgxMeshObject(MeshObjects[i]).ContributeToBarycenter(Result, nb);
  5519. if nb > 0 then
  5520. ScaleVector(Result, 1 / nb);
  5521. end;
  5522. function TgxBaseMesh.LastLoadedFilename: string;
  5523. begin
  5524. Result := FLastLoadedFilename;
  5525. end;
  5526. procedure TgxBaseMesh.SetMaterialLibrary(const val: TgxMaterialLibrary);
  5527. begin
  5528. if FMaterialLibrary <> val then
  5529. begin
  5530. if FMaterialLibraryCachesPrepared then
  5531. DropMaterialLibraryCache;
  5532. if Assigned(FMaterialLibrary) then
  5533. begin
  5534. DestroyHandle;
  5535. FMaterialLibrary.RemoveFreeNotification(Self);
  5536. end;
  5537. FMaterialLibrary := val;
  5538. if Assigned(FMaterialLibrary) then
  5539. FMaterialLibrary.FreeNotification(Self);
  5540. StructureChanged;
  5541. end;
  5542. end;
  5543. procedure TgxBaseMesh.SetLightmapLibrary(const val: TgxMaterialLibrary);
  5544. begin
  5545. if FLightmapLibrary <> val then
  5546. begin
  5547. if Assigned(FLightmapLibrary) then
  5548. begin
  5549. DestroyHandle;
  5550. FLightmapLibrary.RemoveFreeNotification(Self);
  5551. end;
  5552. FLightmapLibrary := val;
  5553. if Assigned(FLightmapLibrary) then
  5554. FLightmapLibrary.FreeNotification(Self);
  5555. StructureChanged;
  5556. end;
  5557. end;
  5558. procedure TgxBaseMesh.SetNormalsOrientation(const val: TMeshNormalsOrientation);
  5559. begin
  5560. if val <> FNormalsOrientation then
  5561. begin
  5562. FNormalsOrientation := val;
  5563. StructureChanged;
  5564. end;
  5565. end;
  5566. procedure TgxBaseMesh.SetOverlaySkeleton(const val: Boolean);
  5567. begin
  5568. if FOverlaySkeleton <> val then
  5569. begin
  5570. FOverlaySkeleton := val;
  5571. NotifyChange(Self);
  5572. end;
  5573. end;
  5574. procedure TgxBaseMesh.SetAutoScaling(const Value: TgxCoordinates);
  5575. begin
  5576. FAutoScaling.SetPoint(Value.DirectX, Value.DirectY, Value.DirectZ);
  5577. end;
  5578. procedure TgxBaseMesh.Notification(AComponent: TComponent; Operation: TOperation);
  5579. begin
  5580. if Operation = opRemove then
  5581. begin
  5582. if AComponent = FMaterialLibrary then
  5583. MaterialLibrary := nil
  5584. else if AComponent = FLightmapLibrary then
  5585. LightmapLibrary := nil;
  5586. end;
  5587. inherited;
  5588. end;
  5589. function TgxBaseMesh.AxisAlignedDimensionsUnscaled: TVector4f;
  5590. var
  5591. dMin, dMax: TAffineVector;
  5592. begin
  5593. if FAxisAlignedDimensionsCache.X < 0 then
  5594. begin
  5595. MeshObjects.GetExtents(dMin, dMax);
  5596. FAxisAlignedDimensionsCache.X := (dMax.X - dMin.X) / 2;
  5597. FAxisAlignedDimensionsCache.Y := (dMax.Y - dMin.Y) / 2;
  5598. FAxisAlignedDimensionsCache.Z := (dMax.Z - dMin.Z) / 2;
  5599. FAxisAlignedDimensionsCache.W := 0;
  5600. end;
  5601. SetVector(Result, FAxisAlignedDimensionsCache);
  5602. end;
  5603. function TgxBaseMesh.BarycenterOffset: TVector4f;
  5604. var
  5605. dMin, dMax: TAffineVector;
  5606. begin
  5607. if FBaryCenterOffsetChanged then
  5608. begin
  5609. MeshObjects.GetExtents(dMin, dMax);
  5610. FBaryCenterOffset.X := (dMin.X + dMax.X) / 2;
  5611. FBaryCenterOffset.Y := (dMin.Y + dMax.Y) / 2;
  5612. FBaryCenterOffset.Z := (dMin.Z + dMax.Z) / 2;
  5613. FBaryCenterOffset.W := 0;
  5614. FBaryCenterOffsetChanged := False;
  5615. end;
  5616. Result := FBaryCenterOffset;
  5617. end;
  5618. function TgxBaseMesh.BarycenterPosition: TVector4f;
  5619. begin
  5620. Result := VectorAdd(Position.DirectVector, BarycenterOffset);
  5621. end;
  5622. function TgxBaseMesh.BarycenterAbsolutePosition: TVector4f;
  5623. begin
  5624. Result := LocalToAbsolute(BarycenterPosition);
  5625. end;
  5626. procedure TgxBaseMesh.DestroyHandle;
  5627. begin
  5628. if Assigned(FMaterialLibrary) then
  5629. MaterialLibrary.DestroyHandles;
  5630. if Assigned(FLightmapLibrary) then
  5631. LightmapLibrary.DestroyHandles;
  5632. inherited;
  5633. end;
  5634. procedure TgxBaseMesh.PrepareVectorFile(aFile: TgxVectorFile);
  5635. begin
  5636. aFile.NormalsOrientation := NormalsOrientation;
  5637. end;
  5638. procedure TgxBaseMesh.PerformAutoCentering;
  5639. var
  5640. delta, min, max: TAffineVector;
  5641. begin
  5642. if macUseBarycenter in AutoCentering then
  5643. begin
  5644. delta := VectorNegate(GetBarycenter);
  5645. end
  5646. else
  5647. begin
  5648. GetExtents(min, max);
  5649. if macCenterX in AutoCentering then
  5650. delta.X := -0.5 * (min.X + max.X)
  5651. else
  5652. delta.X := 0;
  5653. if macCenterY in AutoCentering then
  5654. delta.Y := -0.5 * (min.Y + max.Y)
  5655. else
  5656. delta.Y := 0;
  5657. if macCenterZ in AutoCentering then
  5658. delta.Z := -0.5 * (min.Z + max.Z)
  5659. else
  5660. delta.Z := 0;
  5661. end;
  5662. MeshObjects.Translate(delta);
  5663. if macRestorePosition in AutoCentering then
  5664. Position.Translate(VectorNegate(delta));
  5665. end;
  5666. procedure TgxBaseMesh.PerformAutoScaling;
  5667. var
  5668. i: Integer;
  5669. vScal: TAffineFltVector;
  5670. begin
  5671. if (FAutoScaling.DirectX <> 1) or (FAutoScaling.DirectY <> 1) or (FAutoScaling.DirectZ <> 1) then
  5672. begin
  5673. MakeVector(vScal, FAutoScaling.DirectX, FAutoScaling.DirectY, FAutoScaling.DirectZ);
  5674. for i := 0 to MeshObjects.Count - 1 do
  5675. begin
  5676. MeshObjects[i].Vertices.Scale(vScal);
  5677. end;
  5678. end;
  5679. end;
  5680. procedure TgxBaseMesh.PrepareMesh;
  5681. begin
  5682. StructureChanged;
  5683. end;
  5684. procedure TgxBaseMesh.PrepareMaterialLibraryCache;
  5685. begin
  5686. if FMaterialLibraryCachesPrepared then
  5687. DropMaterialLibraryCache;
  5688. MeshObjects.PrepareMaterialLibraryCache(FMaterialLibrary);
  5689. FMaterialLibraryCachesPrepared := True;
  5690. end;
  5691. procedure TgxBaseMesh.DropMaterialLibraryCache;
  5692. begin
  5693. if FMaterialLibraryCachesPrepared then
  5694. begin
  5695. MeshObjects.DropMaterialLibraryCache;
  5696. FMaterialLibraryCachesPrepared := False;
  5697. end;
  5698. end;
  5699. procedure TgxBaseMesh.PrepareBuildList(var mrci: TgxRenderContextInfo);
  5700. begin
  5701. MeshObjects.PrepareBuildList(mrci);
  5702. if LightmapLibrary <> nil then
  5703. LightmapLibrary.Materials.PrepareBuildList
  5704. end;
  5705. procedure TgxBaseMesh.SetUseMeshMaterials(const val: Boolean);
  5706. begin
  5707. if val <> FUseMeshMaterials then
  5708. begin
  5709. FUseMeshMaterials := val;
  5710. if FMaterialLibraryCachesPrepared and (not val) then
  5711. DropMaterialLibraryCache;
  5712. StructureChanged;
  5713. end;
  5714. end;
  5715. procedure TgxBaseMesh.BuildList(var rci: TgxRenderContextInfo);
  5716. begin
  5717. MeshObjects.BuildList(rci);
  5718. end;
  5719. procedure TgxBaseMesh.DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean);
  5720. begin
  5721. if Assigned(LightmapLibrary) then
  5722. xglForbidSecondTextureUnit;
  5723. if renderSelf then
  5724. begin
  5725. // set winding
  5726. case FNormalsOrientation of
  5727. mnoDefault:
  5728. ; // nothing
  5729. mnoInvert:
  5730. rci.gxStates.InvertFrontFace;
  5731. else
  5732. Assert(False);
  5733. end;
  5734. if not rci.ignoreMaterials then
  5735. begin
  5736. if UseMeshMaterials and Assigned(MaterialLibrary) then
  5737. begin
  5738. rci.MaterialLibrary := MaterialLibrary;
  5739. if not FMaterialLibraryCachesPrepared then
  5740. PrepareMaterialLibraryCache;
  5741. end
  5742. else
  5743. rci.MaterialLibrary := nil;
  5744. if Assigned(LightmapLibrary) then
  5745. rci.LightmapLibrary := LightmapLibrary
  5746. else
  5747. rci.LightmapLibrary := nil;
  5748. if rci.amalgamating or not(ListHandleAllocated or (osDirectDraw in ObjectStyle)) then
  5749. PrepareBuildList(rci);
  5750. Material.Apply(rci);
  5751. repeat
  5752. if (osDirectDraw in ObjectStyle) or rci.amalgamating or UseMeshMaterials then
  5753. BuildList(rci)
  5754. else
  5755. rci.gxStates.CallList(GetHandle(rci));
  5756. until not Material.UnApply(rci);
  5757. rci.MaterialLibrary := nil;
  5758. end
  5759. else
  5760. begin
  5761. if (osDirectDraw in ObjectStyle) or rci.amalgamating then
  5762. BuildList(rci)
  5763. else
  5764. rci.gxStates.CallList(GetHandle(rci));
  5765. end;
  5766. if FNormalsOrientation <> mnoDefault then
  5767. rci.gxStates.InvertFrontFace;
  5768. end;
  5769. if Assigned(LightmapLibrary) then
  5770. xglAllowSecondTextureUnit;
  5771. if renderChildren and (Count > 0) then
  5772. Self.renderChildren(0, Count - 1, rci);
  5773. end;
  5774. procedure TgxBaseMesh.StructureChanged;
  5775. begin
  5776. FAxisAlignedDimensionsCache.X := -1;
  5777. FBaryCenterOffsetChanged := True;
  5778. DropMaterialLibraryCache;
  5779. MeshObjects.Prepare;
  5780. inherited;
  5781. end;
  5782. procedure TgxBaseMesh.StructureChangedNoPrepare;
  5783. begin
  5784. inherited StructureChanged;
  5785. end;
  5786. function TgxBaseMesh.RayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  5787. intersectNormal: PVector4f = nil): Boolean;
  5788. var
  5789. i: Integer;
  5790. tris: TgxAffineVectorList;
  5791. locRayStart, locRayVector, iPoint, iNormal: TVector4f;
  5792. d, minD: Single;
  5793. begin
  5794. // BEWARE! Utterly inefficient implementation!
  5795. tris := MeshObjects.ExtractTriangles;
  5796. try
  5797. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5798. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5799. minD := -1;
  5800. i := 0;
  5801. while i < tris.Count do
  5802. begin
  5803. if RayCastTriangleIntersect(locRayStart, locRayVector, tris.list^[i], tris.list^[i + 1], tris.list^[i + 2], @iPoint,
  5804. @iNormal) then
  5805. begin
  5806. d := VectorDistance2(locRayStart, iPoint);
  5807. if (d < minD) or (minD < 0) then
  5808. begin
  5809. minD := d;
  5810. if intersectPoint <> nil then
  5811. intersectPoint^ := iPoint;
  5812. if intersectNormal <> nil then
  5813. intersectNormal^ := iNormal;
  5814. end;
  5815. end;
  5816. Inc(i, 3);
  5817. end;
  5818. finally
  5819. tris.Free;
  5820. end;
  5821. Result := (minD >= 0);
  5822. if Result then
  5823. begin
  5824. if intersectPoint <> nil then
  5825. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5826. if intersectNormal <> nil then
  5827. begin
  5828. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5829. if NormalsOrientation = mnoInvert then
  5830. NegateVector(intersectNormal^);
  5831. end;
  5832. end;
  5833. end;
  5834. function TgxBaseMesh.GenerateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters): TgxSilhouette;
  5835. var
  5836. mc: TgxBaseMeshConnectivity;
  5837. sil: TgxSilhouette;
  5838. begin
  5839. sil := nil;
  5840. if Assigned(FConnectivity) then
  5841. begin
  5842. mc := TgxBaseMeshConnectivity(FConnectivity);
  5843. mc.CreateSilhouette(silhouetteParameters, sil, True);
  5844. end
  5845. else
  5846. begin
  5847. mc := TgxBaseMeshConnectivity.CreateFromMesh(Self);
  5848. try
  5849. mc.CreateSilhouette(silhouetteParameters, sil, True);
  5850. finally
  5851. mc.Free;
  5852. end;
  5853. end;
  5854. Result := sil;
  5855. end;
  5856. procedure TgxBaseMesh.BuildSilhouetteConnectivityData;
  5857. var
  5858. i, j: Integer;
  5859. mo: TgxMeshObject;
  5860. begin
  5861. FreeAndNil(FConnectivity);
  5862. // connectivity data works only on facegroups of TfgxVertexIndexList class
  5863. for i := 0 to MeshObjects.Count - 1 do
  5864. begin
  5865. mo := (MeshObjects[i] as TgxMeshObject);
  5866. if mo.mode <> momFaceGroups then
  5867. Exit;
  5868. for j := 0 to mo.FaceGroups.Count - 1 do
  5869. if not mo.FaceGroups[j].InheritsFrom(TfgxVertexIndexList) then
  5870. Exit;
  5871. end;
  5872. FConnectivity := TgxBaseMeshConnectivity.CreateFromMesh(Self);
  5873. end;
  5874. // ------------------
  5875. // ------------------ TgxFreeForm ------------------
  5876. // ------------------
  5877. constructor TgxFreeForm.Create(aOwner: TComponent);
  5878. begin
  5879. inherited;
  5880. // ObjectStyle := [osDirectDraw];
  5881. FUseMeshMaterials := True;
  5882. end;
  5883. destructor TgxFreeForm.Destroy;
  5884. begin
  5885. FOctree.Free;
  5886. inherited Destroy;
  5887. end;
  5888. function TgxFreeForm.GetOctree: TgxOctree;
  5889. begin
  5890. // if not Assigned(FOctree) then //If auto-created, can never use "if Assigned(GLFreeform1.Octree)"
  5891. // FOctree:=TOctree.Create; //moved this code to BuildOctree
  5892. Result := FOctree;
  5893. end;
  5894. procedure TgxFreeForm.BuildOctree(TreeDepth: Integer = 3);
  5895. var
  5896. emin, emax: TAffineVector;
  5897. tl: TgxAffineVectorList;
  5898. begin
  5899. if not Assigned(FOctree) then // moved here from GetOctree
  5900. FOctree := TgxOctree.Create;
  5901. GetExtents(emin, emax);
  5902. tl := MeshObjects.ExtractTriangles;
  5903. try
  5904. with Octree do
  5905. begin
  5906. DisposeTree;
  5907. InitializeTree(emin, emax, tl, TreeDepth);
  5908. end;
  5909. finally
  5910. tl.Free;
  5911. end;
  5912. end;
  5913. function TgxFreeForm.OctreeRayCastIntersect(const rayStart, rayVector: TVector4f; intersectPoint: PVector4f = nil;
  5914. intersectNormal: PVector4f = nil): Boolean;
  5915. var
  5916. locRayStart, locRayVector: TVector4f;
  5917. begin
  5918. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5919. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5920. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5921. Result := Octree.RayCastIntersect(locRayStart, locRayVector, intersectPoint, intersectNormal);
  5922. if Result then
  5923. begin
  5924. if intersectPoint <> nil then
  5925. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5926. if intersectNormal <> nil then
  5927. begin
  5928. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5929. if NormalsOrientation = mnoInvert then
  5930. NegateVector(intersectNormal^);
  5931. end;
  5932. end;
  5933. end;
  5934. function TgxFreeForm.OctreePointInMesh(const Point: TVector4f): Boolean;
  5935. const
  5936. cPointRadiusStep = 10000;
  5937. var
  5938. rayStart, rayVector, hitPoint, hitNormal: TVector4f;
  5939. BRad: double;
  5940. HitCount: Integer;
  5941. hitDot: double;
  5942. begin
  5943. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5944. Result := False;
  5945. // Makes calculations sligthly faster by ignoring cases that are guaranteed
  5946. // to be outside the object
  5947. if not PointInObject(Point) then
  5948. Exit;
  5949. BRad := BoundingSphereRadius;
  5950. // This could be a fixed vector, but a fixed vector could have a systemic
  5951. // bug on an non-closed mesh, making it fail constantly for one or several
  5952. // faces.
  5953. rayVector := VectorMake(2 * random - 1, 2 * random - 1, 2 * random - 1);
  5954. rayStart := VectorAdd(VectorScale(rayVector, -BRad), Point);
  5955. HitCount := 0;
  5956. while OctreeRayCastIntersect(rayStart, rayVector, @hitPoint, @hitNormal) do
  5957. begin
  5958. // Are we past our taget?
  5959. if VectorDotProduct(rayVector, VectorSubtract(Point, hitPoint)) < 0 then
  5960. begin
  5961. Result := HitCount > 0;
  5962. Exit;
  5963. end;
  5964. hitDot := VectorDotProduct(hitNormal, rayVector);
  5965. if hitDot < 0 then
  5966. Inc(HitCount)
  5967. else if hitDot > 0 then
  5968. Dec(HitCount);
  5969. // ditDot = 0 is a tricky special case where the ray is just grazing the
  5970. // side of a face - this case means that it doesn't necessarily actually
  5971. // enter the mesh - but it _could_ enter the mesh. If this situation occurs,
  5972. // we should restart the run using a new rayVector - but this implementation
  5973. // currently doesn't.
  5974. // Restart the ray slightly beyond the point it hit the previous face. Note
  5975. // that this step introduces a possible issue with faces that are very close
  5976. rayStart := VectorAdd(hitPoint, VectorScale(rayVector, BRad / cPointRadiusStep));
  5977. end;
  5978. end;
  5979. function TgxFreeForm.OctreeSphereSweepIntersect(const rayStart, rayVector: TVector4f; const velocity, radius: Single;
  5980. intersectPoint: PVector4f = nil; intersectNormal: PVector4f = nil): Boolean;
  5981. var
  5982. locRayStart, locRayVector: TVector4f;
  5983. begin
  5984. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  5985. SetVector(locRayStart, AbsoluteToLocal(rayStart));
  5986. SetVector(locRayVector, AbsoluteToLocal(rayVector));
  5987. Result := Octree.SphereSweepIntersect(locRayStart, locRayVector, velocity, radius, intersectPoint, intersectNormal);
  5988. if Result then
  5989. begin
  5990. if intersectPoint <> nil then
  5991. SetVector(intersectPoint^, LocalToAbsolute(intersectPoint^));
  5992. if intersectNormal <> nil then
  5993. begin
  5994. SetVector(intersectNormal^, LocalToAbsolute(intersectNormal^));
  5995. if NormalsOrientation = mnoInvert then
  5996. NegateVector(intersectNormal^);
  5997. end;
  5998. end;
  5999. end;
  6000. function TgxFreeForm.OctreeTriangleIntersect(const v1, v2, v3: TAffineVector): Boolean;
  6001. var
  6002. t1, t2, t3: TAffineVector;
  6003. begin
  6004. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  6005. SetVector(t1, AbsoluteToLocal(v1));
  6006. SetVector(t2, AbsoluteToLocal(v2));
  6007. SetVector(t3, AbsoluteToLocal(v3));
  6008. Result := Octree.TriangleIntersect(t1, t2, t3);
  6009. end;
  6010. function TgxFreeForm.OctreeAABBIntersect(const aabb: TAABB; objMatrix, invObjMatrix: TMatrix4f;
  6011. triangles: TgxAffineVectorList = nil): Boolean;
  6012. var
  6013. m1to2, m2to1: TMatrix4f;
  6014. begin
  6015. Assert(Assigned(FOctree), 'Octree must have been prepared and setup before use.');
  6016. // get matrixes needed
  6017. // object to self
  6018. MatrixMultiply(objMatrix, InvAbsoluteMatrix, m1to2);
  6019. // self to object
  6020. MatrixMultiply(AbsoluteMatrix, invObjMatrix, m2to1);
  6021. Result := Octree.AABBIntersect(aabb, m1to2, m2to1, triangles);
  6022. end;
  6023. // ------------------
  6024. // ------------------ TgxActorAnimation ------------------
  6025. // ------------------
  6026. constructor TgxActorAnimation.Create(Collection: TCollection);
  6027. begin
  6028. inherited Create(Collection);
  6029. end;
  6030. destructor TgxActorAnimation.Destroy;
  6031. begin
  6032. with (Collection as TgxActorAnimations).FOwner do
  6033. if FTargetSmoothAnimation = Self then
  6034. FTargetSmoothAnimation := nil;
  6035. inherited Destroy;
  6036. end;
  6037. procedure TgxActorAnimation.Assign(Source: TPersistent);
  6038. begin
  6039. if Source is TgxActorAnimation then
  6040. begin
  6041. FName := TgxActorAnimation(Source).FName;
  6042. FStartFrame := TgxActorAnimation(Source).FStartFrame;
  6043. FEndFrame := TgxActorAnimation(Source).FEndFrame;
  6044. FReference := TgxActorAnimation(Source).FReference;
  6045. end
  6046. else
  6047. inherited;
  6048. end;
  6049. function TgxActorAnimation.GetDisplayName: string;
  6050. begin
  6051. Result := Format('%d - %s [%d - %d]', [Index, Name, startFrame, endFrame]);
  6052. end;
  6053. function TgxActorAnimation.FrameCount: Integer;
  6054. begin
  6055. case reference of
  6056. aarMorph:
  6057. Result := TgxActorAnimations(Collection).FOwner.MeshObjects.MorphTargetCount;
  6058. aarSkeleton:
  6059. Result := TgxActorAnimations(Collection).FOwner.Skeleton.Frames.Count;
  6060. else
  6061. Result := 0;
  6062. Assert(False);
  6063. end;
  6064. end;
  6065. procedure TgxActorAnimation.SetStartFrame(const val: Integer);
  6066. var
  6067. m: Integer;
  6068. begin
  6069. if val < 0 then
  6070. FStartFrame := 0
  6071. else
  6072. begin
  6073. m := FrameCount;
  6074. if val >= m then
  6075. FStartFrame := m - 1
  6076. else
  6077. FStartFrame := val;
  6078. end;
  6079. if FStartFrame > FEndFrame then
  6080. FEndFrame := FStartFrame;
  6081. end;
  6082. procedure TgxActorAnimation.SetEndFrame(const val: Integer);
  6083. var
  6084. m: Integer;
  6085. begin
  6086. if val < 0 then
  6087. FEndFrame := 0
  6088. else
  6089. begin
  6090. m := FrameCount;
  6091. if val >= m then
  6092. FEndFrame := m - 1
  6093. else
  6094. FEndFrame := val;
  6095. end;
  6096. if FStartFrame > FEndFrame then
  6097. FStartFrame := FEndFrame;
  6098. end;
  6099. procedure TgxActorAnimation.SetReference(val: TgxActorAnimationReference);
  6100. begin
  6101. if val <> FReference then
  6102. begin
  6103. FReference := val;
  6104. startFrame := startFrame;
  6105. endFrame := endFrame;
  6106. end;
  6107. end;
  6108. procedure TgxActorAnimation.SetAsString(const val: string);
  6109. var
  6110. sl: TStringList;
  6111. begin
  6112. sl := TStringList.Create;
  6113. try
  6114. sl.CommaText := val;
  6115. Assert(sl.Count >= 3);
  6116. FName := sl[0];
  6117. FStartFrame := StrToInt(sl[1]);
  6118. FEndFrame := StrToInt(sl[2]);
  6119. if sl.Count = 4 then
  6120. begin
  6121. if LowerCase(sl[3]) = 'morph' then
  6122. reference := aarMorph
  6123. else if LowerCase(sl[3]) = 'skeleton' then
  6124. reference := aarSkeleton
  6125. else
  6126. Assert(False);
  6127. end
  6128. else
  6129. reference := aarMorph;
  6130. finally
  6131. sl.Free;
  6132. end;
  6133. end;
  6134. function TgxActorAnimation.GetAsString: string;
  6135. const
  6136. cAARToString: array [aarMorph .. aarSkeleton] of string = ('morph', 'skeleton');
  6137. begin
  6138. Result := Format('"%s",%d,%d,%s', [FName, FStartFrame, FEndFrame, cAARToString[reference]]);
  6139. end;
  6140. function TgxActorAnimation.OwnerActor: TgxActor;
  6141. begin
  6142. Result := ((Collection as TgxActorAnimations).GetOwner as TgxActor);
  6143. end;
  6144. procedure TgxActorAnimation.MakeSkeletalTranslationStatic;
  6145. begin
  6146. OwnerActor.Skeleton.MakeSkeletalTranslationStatic(startFrame, endFrame);
  6147. end;
  6148. procedure TgxActorAnimation.MakeSkeletalRotationDelta;
  6149. begin
  6150. OwnerActor.Skeleton.MakeSkeletalRotationDelta(startFrame, endFrame);
  6151. end;
  6152. // ------------------
  6153. // ------------------ TgxActorAnimations ------------------
  6154. // ------------------
  6155. constructor TgxActorAnimations.Create(aOwner: TgxActor);
  6156. begin
  6157. FOwner := aOwner;
  6158. inherited Create(TgxActorAnimation);
  6159. end;
  6160. function TgxActorAnimations.GetOwner: TPersistent;
  6161. begin
  6162. Result := FOwner;
  6163. end;
  6164. procedure TgxActorAnimations.SetItems(Index: Integer; const val: TgxActorAnimation);
  6165. begin
  6166. inherited Items[index] := val;
  6167. end;
  6168. function TgxActorAnimations.GetItems(Index: Integer): TgxActorAnimation;
  6169. begin
  6170. Result := TgxActorAnimation(inherited Items[index]);
  6171. end;
  6172. function TgxActorAnimations.Last: TgxActorAnimation;
  6173. begin
  6174. if Count > 0 then
  6175. Result := TgxActorAnimation(inherited Items[Count - 1])
  6176. else
  6177. Result := nil;
  6178. end;
  6179. function TgxActorAnimations.Add: TgxActorAnimation;
  6180. begin
  6181. Result := (inherited Add) as TgxActorAnimation;
  6182. end;
  6183. function TgxActorAnimations.FindItemID(ID: Integer): TgxActorAnimation;
  6184. begin
  6185. Result := (inherited FindItemID(ID)) as TgxActorAnimation;
  6186. end;
  6187. function TgxActorAnimations.FindName(const aName: string): TgxActorAnimation;
  6188. var
  6189. i: Integer;
  6190. begin
  6191. Result := nil;
  6192. for i := 0 to Count - 1 do
  6193. if CompareText(Items[i].Name, aName) = 0 then
  6194. begin
  6195. Result := Items[i];
  6196. Break;
  6197. end;
  6198. end;
  6199. function TgxActorAnimations.FindFrame(aFrame: Integer; aReference: TgxActorAnimationReference): TgxActorAnimation;
  6200. var
  6201. i: Integer;
  6202. begin
  6203. Result := nil;
  6204. for i := 0 to Count - 1 do
  6205. with Items[i] do
  6206. if (startFrame <= aFrame) and (endFrame >= aFrame) and (reference = aReference) then
  6207. begin
  6208. Result := Items[i];
  6209. Break;
  6210. end;
  6211. end;
  6212. procedure TgxActorAnimations.SetToStrings(aStrings: TStrings);
  6213. var
  6214. i: Integer;
  6215. begin
  6216. with aStrings do
  6217. begin
  6218. BeginUpdate;
  6219. Clear;
  6220. for i := 0 to Self.Count - 1 do
  6221. Add(Self.Items[i].Name);
  6222. EndUpdate;
  6223. end;
  6224. end;
  6225. procedure TgxActorAnimations.SaveToStream(aStream: TStream);
  6226. var
  6227. i: Integer;
  6228. begin
  6229. WriteCRLFString(aStream, cAAFHeader);
  6230. WriteCRLFString(aStream, AnsiString(IntToStr(Count)));
  6231. for i := 0 to Count - 1 do
  6232. WriteCRLFString(aStream, AnsiString(Items[i].AsString));
  6233. end;
  6234. procedure TgxActorAnimations.LoadFromStream(aStream: TStream);
  6235. var
  6236. i, n: Integer;
  6237. begin
  6238. Clear;
  6239. if ReadCRLFString(aStream) <> cAAFHeader then
  6240. Assert(False);
  6241. n := StrToInt(string(ReadCRLFString(aStream)));
  6242. for i := 0 to n - 1 do
  6243. Add.AsString := string(ReadCRLFString(aStream));
  6244. end;
  6245. procedure TgxActorAnimations.SaveToFile(const filename: string);
  6246. var
  6247. fs: TStream;
  6248. begin
  6249. fs := TFileStream.Create(filename, fmCreate);
  6250. try
  6251. SaveToStream(fs);
  6252. finally
  6253. fs.Free;
  6254. end;
  6255. end;
  6256. procedure TgxActorAnimations.LoadFromFile(const filename: string);
  6257. var
  6258. fs: TStream;
  6259. begin
  6260. fs := TFileStream.Create(filename, fmOpenRead + fmShareDenyWrite);
  6261. try
  6262. LoadFromStream(fs);
  6263. finally
  6264. fs.Free;
  6265. end;
  6266. end;
  6267. // ------------------
  6268. // ------------------ TgxBaseAnimationControler ------------------
  6269. // ------------------
  6270. constructor TgxBaseAnimationControler.Create(aOwner: TComponent);
  6271. begin
  6272. inherited Create(aOwner);
  6273. FEnabled := True;
  6274. end;
  6275. destructor TgxBaseAnimationControler.Destroy;
  6276. begin
  6277. SetActor(nil);
  6278. inherited Destroy;
  6279. end;
  6280. procedure TgxBaseAnimationControler.Notification(AComponent: TComponent; Operation: TOperation);
  6281. begin
  6282. if (AComponent = FActor) and (Operation = opRemove) then
  6283. SetActor(nil);
  6284. inherited;
  6285. end;
  6286. procedure TgxBaseAnimationControler.DoChange;
  6287. begin
  6288. if Assigned(FActor) then
  6289. FActor.NotifyChange(Self);
  6290. end;
  6291. procedure TgxBaseAnimationControler.SetEnabled(const val: Boolean);
  6292. begin
  6293. if val <> FEnabled then
  6294. begin
  6295. FEnabled := val;
  6296. if Assigned(FActor) then
  6297. DoChange;
  6298. end;
  6299. end;
  6300. procedure TgxBaseAnimationControler.SetActor(const val: TgxActor);
  6301. begin
  6302. if FActor <> val then
  6303. begin
  6304. if Assigned(FActor) then
  6305. FActor.UnRegisterControler(Self);
  6306. FActor := val;
  6307. if Assigned(FActor) then
  6308. begin
  6309. FActor.RegisterControler(Self);
  6310. DoChange;
  6311. end;
  6312. end;
  6313. end;
  6314. function TgxBaseAnimationControler.Apply(var lerpInfo: TgxBlendedLerpInfo): Boolean;
  6315. begin
  6316. // virtual
  6317. Result := False;
  6318. end;
  6319. // ------------------
  6320. // ------------------ TgxAnimationControler ------------------
  6321. // ------------------
  6322. procedure TgxAnimationControler.DoChange;
  6323. begin
  6324. if AnimationName <> '' then
  6325. inherited;
  6326. end;
  6327. procedure TgxAnimationControler.SetAnimationName(const val: TgxActorAnimationName);
  6328. begin
  6329. if FAnimationName <> val then
  6330. begin
  6331. FAnimationName := val;
  6332. DoChange;
  6333. end;
  6334. end;
  6335. procedure TgxAnimationControler.SetRatio(const val: Single);
  6336. begin
  6337. if FRatio <> val then
  6338. begin
  6339. FRatio := ClampValue(val, 0, 1);
  6340. DoChange;
  6341. end;
  6342. end;
  6343. function TgxAnimationControler.Apply(var lerpInfo: TgxBlendedLerpInfo): Boolean;
  6344. var
  6345. anim: TgxActorAnimation;
  6346. baseDelta: Integer;
  6347. begin
  6348. if not Enabled then
  6349. begin
  6350. Result := False;
  6351. Exit;
  6352. end;
  6353. anim := Actor.Animations.FindName(AnimationName);
  6354. Result := (anim <> nil);
  6355. if not Result then
  6356. Exit;
  6357. with lerpInfo do
  6358. begin
  6359. if Ratio = 0 then
  6360. begin
  6361. frameIndex1 := anim.startFrame;
  6362. frameIndex2 := frameIndex1;
  6363. lerpFactor := 0;
  6364. end
  6365. else if Ratio = 1 then
  6366. begin
  6367. frameIndex1 := anim.endFrame;
  6368. frameIndex2 := frameIndex1;
  6369. lerpFactor := 0;
  6370. end
  6371. else
  6372. begin
  6373. baseDelta := anim.endFrame - anim.startFrame;
  6374. lerpFactor := anim.startFrame + baseDelta * Ratio;
  6375. frameIndex1 := Trunc(lerpFactor);
  6376. frameIndex2 := frameIndex1 + 1;
  6377. lerpFactor := Frac(lerpFactor);
  6378. end;
  6379. weight := 1;
  6380. externalRotations := nil;
  6381. externalQuaternions := nil;
  6382. end;
  6383. end;
  6384. // ------------------
  6385. // ------------------ TgxActor ------------------
  6386. // ------------------
  6387. constructor TgxActor.Create(aOwner: TComponent);
  6388. begin
  6389. inherited Create(aOwner);
  6390. ObjectStyle := ObjectStyle + [osDirectDraw];
  6391. FFrameInterpolation := afpLinear;
  6392. FAnimationMode := aamNone;
  6393. FInterval := 100; // 10 animation frames per second
  6394. FAnimations := TgxActorAnimations.Create(Self);
  6395. FControlers := nil; // created on request
  6396. FOptions := cDefaultActorOptions;
  6397. end;
  6398. destructor TgxActor.Destroy;
  6399. begin
  6400. inherited Destroy;
  6401. FControlers.Free;
  6402. FAnimations.Free;
  6403. end;
  6404. procedure TgxActor.Assign(Source: TPersistent);
  6405. begin
  6406. inherited Assign(Source);
  6407. if Source is TgxActor then
  6408. begin
  6409. FAnimations.Assign(TgxActor(Source).FAnimations);
  6410. FAnimationMode := TgxActor(Source).FAnimationMode;
  6411. Synchronize(TgxActor(Source));
  6412. end;
  6413. end;
  6414. procedure TgxActor.RegisterControler(aControler: TgxBaseAnimationControler);
  6415. begin
  6416. if not Assigned(FControlers) then
  6417. FControlers := TList.Create;
  6418. FControlers.Add(aControler);
  6419. FreeNotification(aControler);
  6420. end;
  6421. procedure TgxActor.UnRegisterControler(aControler: TgxBaseAnimationControler);
  6422. begin
  6423. Assert(Assigned(FControlers));
  6424. FControlers.Remove(aControler);
  6425. RemoveFreeNotification(aControler);
  6426. if FControlers.Count = 0 then
  6427. FreeAndNil(FControlers);
  6428. end;
  6429. procedure TgxActor.SetCurrentFrame(val: Integer);
  6430. begin
  6431. if val <> CurrentFrame then
  6432. begin
  6433. if val > FrameCount - 1 then
  6434. FCurrentFrame := FrameCount - 1
  6435. else if val < 0 then
  6436. FCurrentFrame := 0
  6437. else
  6438. FCurrentFrame := val;
  6439. FCurrentFrameDelta := 0;
  6440. case AnimationMode of
  6441. aamPlayOnce:
  6442. if (CurrentFrame = endFrame) and (FTargetSmoothAnimation = nil) then
  6443. FAnimationMode := aamNone;
  6444. aamBounceForward:
  6445. if CurrentFrame = endFrame then
  6446. FAnimationMode := aamBounceBackward;
  6447. aamBounceBackward:
  6448. if CurrentFrame = startFrame then
  6449. FAnimationMode := aamBounceForward;
  6450. end;
  6451. StructureChanged;
  6452. if Assigned(FOnFrameChanged) then
  6453. FOnFrameChanged(Self);
  6454. end;
  6455. end;
  6456. procedure TgxActor.SetCurrentFrameDirect(const Value: Integer);
  6457. begin
  6458. FCurrentFrame := Value;
  6459. end;
  6460. procedure TgxActor.SetStartFrame(val: Integer);
  6461. begin
  6462. if (val >= 0) and (val < FrameCount) and (val <> startFrame) then
  6463. FStartFrame := val;
  6464. if endFrame < startFrame then
  6465. FEndFrame := FStartFrame;
  6466. if CurrentFrame < startFrame then
  6467. CurrentFrame := FStartFrame;
  6468. end;
  6469. procedure TgxActor.SetEndFrame(val: Integer);
  6470. begin
  6471. if (val >= 0) and (val < FrameCount) and (val <> endFrame) then
  6472. FEndFrame := val;
  6473. if CurrentFrame > endFrame then
  6474. CurrentFrame := FEndFrame;
  6475. end;
  6476. procedure TgxActor.SetReference(val: TgxActorAnimationReference);
  6477. begin
  6478. if val <> reference then
  6479. begin
  6480. FReference := val;
  6481. startFrame := startFrame;
  6482. endFrame := endFrame;
  6483. CurrentFrame := CurrentFrame;
  6484. StructureChanged;
  6485. end;
  6486. end;
  6487. procedure TgxActor.SetAnimations(const val: TgxActorAnimations);
  6488. begin
  6489. FAnimations.Assign(val);
  6490. end;
  6491. function TgxActor.StoreAnimations: Boolean;
  6492. begin
  6493. Result := (FAnimations.Count > 0);
  6494. end;
  6495. procedure TgxActor.SetOptions(const val: TgxActorOptions);
  6496. begin
  6497. if val <> FOptions then
  6498. begin
  6499. FOptions := val;
  6500. StructureChanged;
  6501. end;
  6502. end;
  6503. function TgxActor.NextFrameIndex: Integer;
  6504. begin
  6505. case AnimationMode of
  6506. aamLoop, aamBounceForward:
  6507. begin
  6508. if FTargetSmoothAnimation <> nil then
  6509. Result := FTargetSmoothAnimation.startFrame
  6510. else
  6511. begin
  6512. Result := CurrentFrame + 1;
  6513. if Result > endFrame then
  6514. begin
  6515. Result := startFrame + (Result - endFrame - 1);
  6516. if Result > endFrame then
  6517. Result := endFrame;
  6518. end;
  6519. end;
  6520. end;
  6521. aamNone, aamPlayOnce:
  6522. begin
  6523. if FTargetSmoothAnimation <> nil then
  6524. Result := FTargetSmoothAnimation.startFrame
  6525. else
  6526. begin
  6527. Result := CurrentFrame + 1;
  6528. if Result > endFrame then
  6529. Result := endFrame;
  6530. end;
  6531. end;
  6532. aamBounceBackward, aamLoopBackward:
  6533. begin
  6534. if FTargetSmoothAnimation <> nil then
  6535. Result := FTargetSmoothAnimation.startFrame
  6536. else
  6537. begin
  6538. Result := CurrentFrame - 1;
  6539. if Result < startFrame then
  6540. begin
  6541. Result := endFrame - (startFrame - Result - 1);
  6542. if Result < startFrame then
  6543. Result := startFrame;
  6544. end;
  6545. end;
  6546. end;
  6547. aamExternal:
  6548. Result := CurrentFrame; // Do nothing
  6549. else
  6550. Result := CurrentFrame;
  6551. Assert(False);
  6552. end;
  6553. end;
  6554. procedure TgxActor.NextFrame(nbSteps: Integer = 1);
  6555. var
  6556. n: Integer;
  6557. begin
  6558. n := nbSteps;
  6559. while n > 0 do
  6560. begin
  6561. CurrentFrame := NextFrameIndex;
  6562. Dec(n);
  6563. if Assigned(FOnEndFrameReached) and (CurrentFrame = endFrame) then
  6564. FOnEndFrameReached(Self);
  6565. if Assigned(FOnStartFrameReached) and (CurrentFrame = startFrame) then
  6566. FOnStartFrameReached(Self);
  6567. end;
  6568. end;
  6569. procedure TgxActor.PrevFrame(nbSteps: Integer = 1);
  6570. var
  6571. Value: Integer;
  6572. begin
  6573. Value := FCurrentFrame - nbSteps;
  6574. if Value < FStartFrame then
  6575. begin
  6576. Value := FEndFrame - (FStartFrame - Value);
  6577. if Value < FStartFrame then
  6578. Value := FStartFrame;
  6579. end;
  6580. CurrentFrame := Value;
  6581. end;
  6582. procedure TgxActor.DoAnimate();
  6583. var
  6584. i, k: Integer;
  6585. nextFrameIdx: Integer;
  6586. lerpInfos: array of TgxBlendedLerpInfo;
  6587. begin
  6588. nextFrameIdx := NextFrameIndex;
  6589. case reference of
  6590. aarMorph:
  6591. if nextFrameIdx >= 0 then
  6592. begin
  6593. case FrameInterpolation of
  6594. afpLinear:
  6595. MeshObjects.Lerp(CurrentFrame, nextFrameIdx, CurrentFrameDelta)
  6596. else
  6597. MeshObjects.MorphTo(CurrentFrame);
  6598. end;
  6599. end;
  6600. aarSkeleton:
  6601. if Skeleton.Frames.Count > 0 then
  6602. begin
  6603. if Assigned(FControlers) and (AnimationMode <> aamExternal) then
  6604. begin
  6605. // Blended Skeletal Lerping
  6606. SetLength(lerpInfos, FControlers.Count + 1);
  6607. if nextFrameIdx >= 0 then
  6608. begin
  6609. case FrameInterpolation of
  6610. afpLinear:
  6611. with lerpInfos[0] do
  6612. begin
  6613. frameIndex1 := CurrentFrame;
  6614. frameIndex2 := nextFrameIdx;
  6615. lerpFactor := CurrentFrameDelta;
  6616. weight := 1;
  6617. end;
  6618. else
  6619. with lerpInfos[0] do
  6620. begin
  6621. frameIndex1 := CurrentFrame;
  6622. frameIndex2 := CurrentFrame;
  6623. lerpFactor := 0;
  6624. weight := 1;
  6625. end;
  6626. end;
  6627. end
  6628. else
  6629. begin
  6630. with lerpInfos[0] do
  6631. begin
  6632. frameIndex1 := CurrentFrame;
  6633. frameIndex2 := CurrentFrame;
  6634. lerpFactor := 0;
  6635. weight := 1;
  6636. end;
  6637. end;
  6638. k := 1;
  6639. for i := 0 to FControlers.Count - 1 do
  6640. if TgxBaseAnimationControler(FControlers[i]).Apply(lerpInfos[k]) then
  6641. Inc(k);
  6642. SetLength(lerpInfos, k);
  6643. Skeleton.BlendedLerps(lerpInfos);
  6644. end
  6645. else if (nextFrameIdx >= 0) and (AnimationMode <> aamExternal) then
  6646. begin
  6647. // Single Skeletal Lerp
  6648. case FrameInterpolation of
  6649. afpLinear:
  6650. Skeleton.Lerp(CurrentFrame, nextFrameIdx, CurrentFrameDelta);
  6651. else
  6652. Skeleton.SetCurrentFrame(Skeleton.Frames[CurrentFrame]);
  6653. end;
  6654. end;
  6655. Skeleton.MorphMesh(aoSkeletonNormalizeNormals in Options);
  6656. end;
  6657. aarNone:
  6658. ; // do nothing
  6659. end;
  6660. end;
  6661. procedure TgxActor.BuildList(var rci: TgxRenderContextInfo);
  6662. begin
  6663. DoAnimate;
  6664. inherited;
  6665. if OverlaySkeleton then
  6666. begin
  6667. rci.gxStates.Disable(stDepthTest);
  6668. Skeleton.RootBones.BuildList(rci);
  6669. end;
  6670. end;
  6671. procedure TgxActor.PrepareMesh;
  6672. begin
  6673. FStartFrame := 0;
  6674. FEndFrame := FrameCount - 1;
  6675. FCurrentFrame := 0;
  6676. if Assigned(FOnFrameChanged) then
  6677. FOnFrameChanged(Self);
  6678. inherited;
  6679. end;
  6680. procedure TgxActor.PrepareBuildList(var mrci: TgxRenderContextInfo);
  6681. begin
  6682. // no preparation needed for actors, they don't use buildlists
  6683. end;
  6684. function TgxActor.FrameCount: Integer;
  6685. begin
  6686. case reference of
  6687. aarMorph:
  6688. Result := MeshObjects.MorphTargetCount;
  6689. aarSkeleton:
  6690. Result := Skeleton.Frames.Count;
  6691. aarNone:
  6692. Result := 0;
  6693. else
  6694. Result := 0;
  6695. Assert(False);
  6696. end;
  6697. end;
  6698. procedure TgxActor.DoProgress(const progressTime: TgxProgressTimes);
  6699. var
  6700. fDelta: Single;
  6701. begin
  6702. inherited;
  6703. if (AnimationMode <> aamNone) and (Interval > 0) then
  6704. begin
  6705. if (startFrame <> endFrame) and (FrameCount > 1) then
  6706. begin
  6707. FCurrentFrameDelta := FCurrentFrameDelta + (progressTime.deltaTime * 1000) / FInterval;
  6708. if FCurrentFrameDelta > 1 then
  6709. begin
  6710. if Assigned(FTargetSmoothAnimation) then
  6711. begin
  6712. SwitchToAnimation(FTargetSmoothAnimation);
  6713. FTargetSmoothAnimation := nil;
  6714. end;
  6715. // we need to step on
  6716. fDelta := Frac(FCurrentFrameDelta);
  6717. NextFrame(Trunc(FCurrentFrameDelta));
  6718. FCurrentFrameDelta := fDelta;
  6719. StructureChanged;
  6720. end
  6721. else if FrameInterpolation <> afpNone then
  6722. StructureChanged;
  6723. end;
  6724. end;
  6725. end;
  6726. procedure TgxActor.LoadFromStream(const filename: string; aStream: TStream);
  6727. begin
  6728. if filename <> '' then
  6729. begin
  6730. Animations.Clear;
  6731. inherited LoadFromStream(filename, aStream);
  6732. end;
  6733. end;
  6734. procedure TgxActor.SwitchToAnimation(const AnimationName: string; smooth: Boolean = False);
  6735. begin
  6736. SwitchToAnimation(Animations.FindName(AnimationName), smooth);
  6737. end;
  6738. procedure TgxActor.SwitchToAnimation(animationIndex: Integer; smooth: Boolean = False);
  6739. begin
  6740. if (animationIndex >= 0) and (animationIndex < Animations.Count) then
  6741. SwitchToAnimation(Animations[animationIndex], smooth);
  6742. end;
  6743. procedure TgxActor.SwitchToAnimation(anAnimation: TgxActorAnimation; smooth: Boolean = False);
  6744. begin
  6745. if Assigned(anAnimation) then
  6746. begin
  6747. if smooth then
  6748. begin
  6749. FTargetSmoothAnimation := anAnimation;
  6750. FCurrentFrameDelta := 0;
  6751. end
  6752. else
  6753. begin
  6754. reference := anAnimation.reference;
  6755. startFrame := anAnimation.startFrame;
  6756. endFrame := anAnimation.endFrame;
  6757. CurrentFrame := startFrame;
  6758. end;
  6759. end;
  6760. end;
  6761. function TgxActor.CurrentAnimation: string;
  6762. var
  6763. aa: TgxActorAnimation;
  6764. begin
  6765. aa := Animations.FindFrame(CurrentFrame, reference);
  6766. if Assigned(aa) then
  6767. Result := aa.Name
  6768. else
  6769. Result := '';
  6770. end;
  6771. procedure TgxActor.Synchronize(referenceActor: TgxActor);
  6772. begin
  6773. if Assigned(referenceActor) then
  6774. begin
  6775. if referenceActor.startFrame < FrameCount then
  6776. FStartFrame := referenceActor.startFrame;
  6777. if referenceActor.endFrame < FrameCount then
  6778. FEndFrame := referenceActor.endFrame;
  6779. FReference := referenceActor.reference;
  6780. if referenceActor.CurrentFrame < FrameCount then
  6781. FCurrentFrame := referenceActor.CurrentFrame;
  6782. FCurrentFrameDelta := referenceActor.CurrentFrameDelta;
  6783. FAnimationMode := referenceActor.AnimationMode;
  6784. FFrameInterpolation := referenceActor.FrameInterpolation;
  6785. if referenceActor.FTargetSmoothAnimation <> nil then
  6786. FTargetSmoothAnimation := Animations.FindName(referenceActor.FTargetSmoothAnimation.Name)
  6787. else
  6788. FTargetSmoothAnimation := nil;
  6789. if (Skeleton.Frames.Count > 0) and (referenceActor.Skeleton.Frames.Count > 0) then
  6790. Skeleton.Synchronize(referenceActor.Skeleton);
  6791. end;
  6792. end;
  6793. function TgxActor.isSwitchingAnimation: Boolean;
  6794. begin
  6795. Result := FTargetSmoothAnimation <> nil;
  6796. end;
  6797. // ------------------------------------------------------------------
  6798. initialization
  6799. // ------------------------------------------------------------------
  6800. RegisterVectorFileFormat('glsm', 'GXScene Mesh', TgxGLSMVectorFile);
  6801. RegisterClasses([TgxFreeForm, TgxActor, TgxSkeleton, TgxSkeletonFrame, TgxSkeletonBone, TgxSkeletonMeshObject, TgxMeshObject,
  6802. TgxSkeletonFrameList, TgxMeshMorphTarget, TgxMorphableMeshObject, TgxFaceGroup, TfgxVertexIndexList,
  6803. TFGVertexNormalTexIndexList, TgxAnimationControler, TFGIndexTexCoordList, TgxSkeletonCollider, TgxSkeletonColliderList]);
  6804. finalization
  6805. FreeAndNil(vVectorFileFormats);
  6806. end.