GLX.VectorFileObjects.pas 218 KB

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