GLS.VectorFileObjects.pas 222 KB

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