GLVectorFileObjects.pas 228 KB

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