GLVectorFileObjects.pas 228 KB

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