GLS.VectorFileObjects.pas 222 KB

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