GLS.VectorFileObjects.pas 222 KB

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