1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456 |
- /******************************************************************************
- @File PVRTModelPOD.cpp
- @Title PVRTModelPOD
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform ANSI compatible
- @Description Code to load POD files - models exported from MAX.
- ******************************************************************************/
- #include <math.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "PVRTGlobal.h"
- #include "PVRTContext.h"
- #include "PVRTFixedPoint.h"
- #include "PVRTMatrix.h"
- #include "PVRTQuaternion.h"
- #include "PVRTVertex.h"
- #include "PVRTBoneBatch.h"
- #include "PVRTModelPOD.h"
- #include "PVRTMisc.h"
- #include "PVRTResourceFile.h"
- #include "PVRTTrans.h"
- /****************************************************************************
- ** Defines
- ****************************************************************************/
- #define PVRTMODELPOD_TAG_MASK (0x80000000)
- #define PVRTMODELPOD_TAG_START (0x00000000)
- #define PVRTMODELPOD_TAG_END (0x80000000)
- #define CFAH (1024)
- /****************************************************************************
- ** Enumerations
- ****************************************************************************/
- /*!****************************************************************************
- @Struct EPODFileName
- @Brief Enum for the binary pod blocks
- ******************************************************************************/
- enum EPODFileName
- {
- ePODFileVersion = 1000,
- ePODFileScene,
- ePODFileExpOpt,
- ePODFileHistory,
- ePODFileEndiannessMisMatch = -402456576,
- ePODFileColourBackground = 2000,
- ePODFileColourAmbient,
- ePODFileNumCamera,
- ePODFileNumLight,
- ePODFileNumMesh,
- ePODFileNumNode,
- ePODFileNumMeshNode,
- ePODFileNumTexture,
- ePODFileNumMaterial,
- ePODFileNumFrame,
- ePODFileCamera, // Will come multiple times
- ePODFileLight, // Will come multiple times
- ePODFileMesh, // Will come multiple times
- ePODFileNode, // Will come multiple times
- ePODFileTexture, // Will come multiple times
- ePODFileMaterial, // Will come multiple times
- ePODFileFlags,
- ePODFileFPS,
- ePODFileMatName = 3000,
- ePODFileMatIdxTexDiffuse,
- ePODFileMatOpacity,
- ePODFileMatAmbient,
- ePODFileMatDiffuse,
- ePODFileMatSpecular,
- ePODFileMatShininess,
- ePODFileMatEffectFile,
- ePODFileMatEffectName,
- ePODFileMatIdxTexAmbient,
- ePODFileMatIdxTexSpecularColour,
- ePODFileMatIdxTexSpecularLevel,
- ePODFileMatIdxTexBump,
- ePODFileMatIdxTexEmissive,
- ePODFileMatIdxTexGlossiness,
- ePODFileMatIdxTexOpacity,
- ePODFileMatIdxTexReflection,
- ePODFileMatIdxTexRefraction,
- ePODFileMatBlendSrcRGB,
- ePODFileMatBlendSrcA,
- ePODFileMatBlendDstRGB,
- ePODFileMatBlendDstA,
- ePODFileMatBlendOpRGB,
- ePODFileMatBlendOpA,
- ePODFileMatBlendColour,
- ePODFileMatBlendFactor,
- ePODFileMatFlags,
- ePODFileTexName = 4000,
- ePODFileNodeIdx = 5000,
- ePODFileNodeName,
- ePODFileNodeIdxMat,
- ePODFileNodeIdxParent,
- ePODFileNodePos,
- ePODFileNodeRot,
- ePODFileNodeScale,
- ePODFileNodeAnimPos,
- ePODFileNodeAnimRot,
- ePODFileNodeAnimScale,
- ePODFileNodeMatrix,
- ePODFileNodeAnimMatrix,
- ePODFileNodeAnimFlags,
- ePODFileNodeAnimPosIdx,
- ePODFileNodeAnimRotIdx,
- ePODFileNodeAnimScaleIdx,
- ePODFileNodeAnimMatrixIdx,
- ePODFileMeshNumVtx = 6000,
- ePODFileMeshNumFaces,
- ePODFileMeshNumUVW,
- ePODFileMeshFaces,
- ePODFileMeshStripLength,
- ePODFileMeshNumStrips,
- ePODFileMeshVtx,
- ePODFileMeshNor,
- ePODFileMeshTan,
- ePODFileMeshBin,
- ePODFileMeshUVW, // Will come multiple times
- ePODFileMeshVtxCol,
- ePODFileMeshBoneIdx,
- ePODFileMeshBoneWeight,
- ePODFileMeshInterleaved,
- ePODFileMeshBoneBatches,
- ePODFileMeshBoneBatchBoneCnts,
- ePODFileMeshBoneBatchOffsets,
- ePODFileMeshBoneBatchBoneMax,
- ePODFileMeshBoneBatchCnt,
- ePODFileMeshUnpackMatrix,
- ePODFileLightIdxTgt = 7000,
- ePODFileLightColour,
- ePODFileLightType,
- ePODFileLightConstantAttenuation,
- ePODFileLightLinearAttenuation,
- ePODFileLightQuadraticAttenuation,
- ePODFileLightFalloffAngle,
- ePODFileLightFalloffExponent,
- ePODFileCamIdxTgt = 8000,
- ePODFileCamFOV,
- ePODFileCamFar,
- ePODFileCamNear,
- ePODFileCamAnimFOV,
- ePODFileDataType = 9000,
- ePODFileN,
- ePODFileStride,
- ePODFileData
- };
- /****************************************************************************
- ** Structures
- ****************************************************************************/
- struct SPVRTPODImpl
- {
- VERTTYPE fFrame; /*!< Frame number */
- VERTTYPE fBlend; /*!< Frame blend (AKA fractional part of animation frame number) */
- int nFrame; /*!< Frame number (AKA integer part of animation frame number) */
- VERTTYPE *pfCache; /*!< Cache indicating the frames at which the matrix cache was filled */
- PVRTMATRIX *pWmCache; /*!< Cache of world matrices */
- PVRTMATRIX *pWmZeroCache; /*!< Pre-calculated frame 0 matrices */
- bool bFromMemory; /*!< Was the mesh data loaded from memory? */
- #ifdef _DEBUG
- PVRTint64 nWmTotal, nWmCacheHit, nWmZeroCacheHit;
- float fHitPerc, fHitPercZero;
- #endif
- };
- /****************************************************************************
- ** Local code: Memory allocation
- ****************************************************************************/
- /*!***************************************************************************
- @Function SafeAlloc
- @Input cnt
- @Output ptr
- @Return false if memory allocation failed
- @Description Allocates a block of memory.
- *****************************************************************************/
- template <typename T>
- bool SafeAlloc(T* &ptr, size_t cnt)
- {
- _ASSERT(!ptr);
- if(cnt)
- {
- ptr = (T*)calloc(cnt, sizeof(T));
- _ASSERT(ptr);
- if(!ptr)
- return false;
- }
- return true;
- }
- #ifdef _UITRON_
- template bool SafeAlloc<unsigned int>(unsigned int*&,size_t);
- template bool SafeAlloc<SPODTexture>(SPODTexture*&,size_t);
- template bool SafeAlloc<SPODLight>(SPODLight*&,size_t);
- template bool SafeAlloc<SPODNode>(SPODNode*&,size_t);
- template bool SafeAlloc<unsigned char>(unsigned char*&,size_t);
- template bool SafeAlloc<int>(int*&,size_t);
- template bool SafeAlloc<float>(float*&,size_t);
- template bool SafeAlloc<CPODData>(CPODData*&,size_t);
- template bool SafeAlloc<char>(char*&,size_t);
- template bool SafeAlloc<SPODCamera>(SPODCamera*&,size_t);
- template bool SafeAlloc<SPODMesh>(SPODMesh*&,size_t);
- template bool SafeAlloc<SPODMaterial>(SPODMaterial*&,size_t);
- template bool SafeAlloc<PVRTMATRIX>(PVRTMATRIX*&,size_t);
- template bool SafeAlloc<bool>(bool*&,size_t);
- template bool SafeAlloc<unsigned short>(unsigned short*&,size_t);
- #endif
- /*!***************************************************************************
- @Function SafeRealloc
- @Modified ptr
- @Input cnt
- @Description Changes the size of a memory allocation.
- *****************************************************************************/
- template <typename T>
- void SafeRealloc(T* &ptr, size_t cnt)
- {
- ptr = (T*)realloc(ptr, cnt * sizeof(T));
- _ASSERT(ptr);
- }
- #ifdef _UITRON_
- template void SafeRealloc<unsigned char>(unsigned char*&,size_t);
- #endif
- /****************************************************************************
- ** Class: CPODData
- ****************************************************************************/
- /*!***************************************************************************
- @Function Reset
- @Description Resets the POD Data to NULL
- *****************************************************************************/
- void CPODData::Reset()
- {
- eType = EPODDataFloat;
- n = 0;
- nStride = 0;
- FREE(pData);
- }
- // check32BitType and check16BitType are structs where only the specialisations have a standard declaration (complete type)
- // if this struct is instantiated with a different type then the compiler will choke on it
- // Place a line like: " check32BitType<channelType>(); " in a template function
- // to ensure it won't be called using a type of the wrong size.
- template<class T> struct check32BitType;
- template<> struct check32BitType<unsigned int> {};
- template<> struct check32BitType<int> {};
- template<> struct check32BitType<float> {};
- template<class T> struct check16BitType;
- template<> struct check16BitType<unsigned short> {};
- template<> struct check16BitType<short> {};
- /*!***************************************************************************
- Class: CSource
- *****************************************************************************/
- class CSource
- {
- public:
- /*!***************************************************************************
- @Function ~CSource
- @Description Destructor
- *****************************************************************************/
- virtual ~CSource() {};
- virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead) = 0;
- virtual bool Skip(const unsigned int nBytes) = 0;
- template <typename T>
- bool Read(T &n)
- {
- return Read(&n, sizeof(T));
- }
- template <typename T>
- bool Read32(T &n)
- {
- unsigned char ub[4];
- if(Read(&ub, 4))
- {
- unsigned int *pn = (unsigned int*) &n;
- *pn = (unsigned int) ((ub[3] << 24) | (ub[2] << 16) | (ub[1] << 8) | ub[0]);
- return true;
- }
- return false;
- }
- template <typename T>
- bool Read16(T &n)
- {
- unsigned char ub[2];
- if(Read(&ub, 2))
- {
- unsigned short *pn = (unsigned short*) &n;
- *pn = (unsigned short) ((ub[1] << 8) | ub[0]);
- return true;
- }
- return false;
- }
- bool ReadMarker(unsigned int &nName, unsigned int &nLen);
- template <typename T>
- bool ReadAfterAlloc(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
- {
- if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead))
- return false;
- return Read(lpBuffer, dwNumberOfBytesToRead);
- }
- template <typename T>
- bool ReadAfterAlloc32(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
- {
- check32BitType<T>();
- if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead/4))
- return false;
- return ReadArray32((unsigned int*) lpBuffer, dwNumberOfBytesToRead / 4);
- }
- bool ReadArray32(unsigned int *pn, unsigned int i32Size)
- {
- bool bRet = true;
- for(unsigned int i = 0; i < i32Size; ++i)
- bRet &= Read32(pn[i]);
- return bRet;
- }
- template <typename T>
- bool ReadAfterAlloc16(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
- {
- check16BitType<T>();
- if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead/2 ))
- return false;
- return ReadArray16((unsigned short*) lpBuffer, dwNumberOfBytesToRead / 2);
- }
- bool ReadArray16(unsigned short* pn, unsigned int i32Size)
- {
- bool bRet = true;
- for(unsigned int i = 0; i < i32Size; ++i)
- bRet &= Read16(pn[i]);
- return bRet;
- }
- };
- bool CSource::ReadMarker(unsigned int &nName, unsigned int &nLen)
- {
- if(!Read32(nName))
- return false;
- if(!Read32(nLen))
- return false;
- return true;
- }
- /*!***************************************************************************
- Class: CSourceStream
- *****************************************************************************/
- class CSourceStream : public CSource
- {
- protected:
- CPVRTResourceFile* m_pFile;
- size_t m_BytesReadCount;
- public:
- /*!***************************************************************************
- @Function CSourceStream
- @Description Constructor
- *****************************************************************************/
- CSourceStream() : m_pFile(0), m_BytesReadCount(0) {}
- /*!***************************************************************************
- @Function ~CSourceStream
- @Description Destructor
- *****************************************************************************/
- virtual ~CSourceStream();
- bool Init(const char * const pszFileName);
- bool Init(const char * const pData, const size_t i32Size);
- virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead);
- virtual bool Skip(const unsigned int nBytes);
- };
- /*!***************************************************************************
- @Function ~CSourceStream
- @Description Destructor
- *****************************************************************************/
- CSourceStream::~CSourceStream()
- {
- delete m_pFile;
- }
- /*!***************************************************************************
- @Function Init
- @Input pszFileName Source file
- @Description Initialises the source stream with a file at the specified
- directory.
- *****************************************************************************/
- bool CSourceStream::Init(const char * const pszFileName)
- {
- m_BytesReadCount = 0;
- if (m_pFile) delete m_pFile;
- m_pFile = new CPVRTResourceFile(pszFileName);
- if (!m_pFile->IsOpen())
- {
- delete m_pFile;
- m_pFile = 0;
- return false;
- }
- return true;
- }
- /*!***************************************************************************
- @Function Init
- @Input pData Address of the source data
- @Input i32Size Size of the data (in bytes)
- @Description Initialises the source stream with the data at the specified
- directory.
- *****************************************************************************/
- bool CSourceStream::Init(const char * pData, size_t i32Size)
- {
- m_BytesReadCount = 0;
- if (m_pFile) delete m_pFile;
- m_pFile = new CPVRTResourceFile(pData, i32Size);
- if (!m_pFile->IsOpen())
- {
- delete m_pFile;
- m_pFile = 0;
- return false;
- }
- return true;
- }
- /*!***************************************************************************
- @Function Read
- @Modified lpBuffer Buffer to write the data into
- @Input dwNumberOfBytesToRead Number of bytes to read
- @Description Reads specified number of bytes from the source stream
- into the output buffer.
- *****************************************************************************/
- bool CSourceStream::Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead)
- {
- _ASSERT(lpBuffer);
- _ASSERT(m_pFile);
- if (m_BytesReadCount + dwNumberOfBytesToRead > m_pFile->Size()) return false;
- memcpy(lpBuffer, &(m_pFile->StringPtr())[m_BytesReadCount], dwNumberOfBytesToRead);
- m_BytesReadCount += dwNumberOfBytesToRead;
- return true;
- }
- /*!***************************************************************************
- @Function Skip
- @Input nBytes The number of bytes to skip
- @Description Skips the specified number of bytes of the source stream.
- *****************************************************************************/
- bool CSourceStream::Skip(const unsigned int nBytes)
- {
- if (m_BytesReadCount + nBytes > m_pFile->Size()) return false;
- m_BytesReadCount += nBytes;
- return true;
- }
- #if defined(WIN32) && !defined(__BADA__)
- /*!***************************************************************************
- Class: CSourceResource
- *****************************************************************************/
- class CSourceResource : public CSource
- {
- protected:
- const unsigned char *m_pData;
- unsigned int m_nSize, m_nReadPos;
- public:
- bool Init(const TCHAR * const pszName);
- virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead);
- virtual bool Skip(const unsigned int nBytes);
- };
- /*!***************************************************************************
- @Function Init
- @Input pszName The file extension of the resource file
- @Description Initialises the source resource from the data at the
- specified file extension.
- *****************************************************************************/
- bool CSourceResource::Init(const TCHAR * const pszName)
- {
- HRSRC hR;
- HGLOBAL hG;
- // Find the resource
- hR = FindResource(GetModuleHandle(NULL), pszName, RT_RCDATA);
- if(!hR)
- return false;
- // How big is the resource?
- m_nSize = SizeofResource(NULL, hR);
- if(!m_nSize)
- return false;
- // Get a pointer to the resource data
- hG = LoadResource(NULL, hR);
- if(!hG)
- return false;
- m_pData = (unsigned char*)LockResource(hG);
- if(!m_pData)
- return false;
- m_nReadPos = 0;
- return true;
- }
- /*!***************************************************************************
- @Function Read
- @Modified lpBuffer The buffer to write to
- @Input dwNumberOfBytesToRead The number of bytes to read
- @Description Reads data from the resource to the specified output buffer.
- *****************************************************************************/
- bool CSourceResource::Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead)
- {
- if(m_nReadPos + dwNumberOfBytesToRead > m_nSize)
- return false;
- _ASSERT(lpBuffer);
- memcpy(lpBuffer, &m_pData[m_nReadPos], dwNumberOfBytesToRead);
- m_nReadPos += dwNumberOfBytesToRead;
- return true;
- }
- bool CSourceResource::Skip(const unsigned int nBytes)
- {
- if(m_nReadPos + nBytes > m_nSize)
- return false;
- m_nReadPos += nBytes;
- return true;
- }
- #endif /* WIN32 */
- /****************************************************************************
- ** Local code: File writing
- ****************************************************************************/
- /*!***************************************************************************
- @Function WriteFileSafe
- @Input pFile
- @Input lpBuffer
- @Input nNumberOfBytesToWrite
- @Return true if successful
- @Description Writes data to a file, checking return codes.
- *****************************************************************************/
- static bool WriteFileSafe(FILE *pFile, const void * const lpBuffer, const unsigned int nNumberOfBytesToWrite)
- {
- if(nNumberOfBytesToWrite)
- {
- size_t count = fwrite(lpBuffer, nNumberOfBytesToWrite, 1, pFile);
- return count == 1;
- }
- return true;
- }
- static bool WriteFileSafe16(FILE *pFile, const unsigned short * const lpBuffer, const unsigned int nSize)
- {
- if(nSize)
- {
- unsigned char ub[2];
- bool bRet = true;
- for(unsigned int i = 0; i < nSize; ++i)
- {
- ub[0] = (unsigned char) lpBuffer[i];
- ub[1] = lpBuffer[i] >> 8;
- bRet &= (fwrite(ub, 2, 1, pFile) == 1);
- }
- return bRet;
- }
- return true;
- }
- static bool WriteFileSafe32(FILE *pFile, const unsigned int * const lpBuffer, const unsigned int nSize)
- {
- if(nSize)
- {
- unsigned char ub[4];
- bool bRet = true;
- for(unsigned int i = 0; i < nSize; ++i)
- {
- ub[0] = (unsigned char) (lpBuffer[i]);
- ub[1] = (unsigned char) (lpBuffer[i] >> 8);
- ub[2] = (unsigned char) (lpBuffer[i] >> 16);
- ub[3] = (unsigned char) (lpBuffer[i] >> 24);
- bRet &= (fwrite(ub, 4, 1, pFile) == 1);
- }
- return bRet;
- }
- return true;
- }
- /*!***************************************************************************
- @Function WriteMarker
- @Input pFile
- @Input nName
- @Input bEnd
- @Input nLen
- Return true if successful
- @Description Write a marker to a POD file. If bEnd if false, it's a
- beginning marker, otherwise it's an end marker.
- *****************************************************************************/
- static bool WriteMarker(
- FILE * const pFile,
- const unsigned int nName,
- const bool bEnd,
- const unsigned int nLen = 0)
- {
- unsigned int nMarker;
- bool bRet;
- _ASSERT((nName & ~PVRTMODELPOD_TAG_MASK) == nName);
- nMarker = nName | (bEnd ? PVRTMODELPOD_TAG_END : PVRTMODELPOD_TAG_START);
- bRet = WriteFileSafe32(pFile, &nMarker, 1);
- bRet &= WriteFileSafe32(pFile, &nLen, 1);
- return bRet;
- }
- /*!***************************************************************************
- @Function WriteData
- @Input pFile
- @Input nName
- @Input pData
- @Input nLen
- @Return true if successful
- @Description Write nLen bytes of data from pData, bracketed by an nName
- begin/end markers.
- *****************************************************************************/
- static bool WriteData(
- FILE * const pFile,
- const unsigned int nName,
- const void * const pData,
- const unsigned int nLen)
- {
- if(pData)
- {
- _ASSERT(nLen);
- if(!WriteMarker(pFile, nName, false, nLen)) return false;
- if(!WriteFileSafe(pFile, pData, nLen)) return false;
- if(!WriteMarker(pFile, nName, true)) return false;
- }
- return true;
- }
- /*!***************************************************************************
- @Function WriteData16
- @Input pFile
- @Input nName
- @Input pData
- @Input i32Size
- @Return true if successful
- @Description Write i32Size no. of unsigned shorts from pData, bracketed by
- an nName begin/end markers.
- *****************************************************************************/
- template <typename T>
- static bool WriteData16(
- FILE * const pFile,
- const unsigned int nName,
- const T * const pData,
- int i32Size = 1)
- {
- if(pData)
- {
- if(!WriteMarker(pFile, nName, false, 2 * i32Size)) return false;
- if(!WriteFileSafe16(pFile, (unsigned short*) pData, i32Size)) return false;
- if(!WriteMarker(pFile, nName, true)) return false;
- }
- return true;
- }
- /*!***************************************************************************
- @Function WriteData32
- @Input pFile
- @Input nName
- @Input pData
- @Input i32Size
- @Return true if successful
- @Description Write i32Size no. of unsigned ints from pData, bracketed by
- an nName begin/end markers.
- *****************************************************************************/
- template <typename T>
- static bool WriteData32(
- FILE * const pFile,
- const unsigned int nName,
- const T * const pData,
- int i32Size = 1)
- {
- if(pData)
- {
- if(!WriteMarker(pFile, nName, false, 4 * i32Size)) return false;
- if(!WriteFileSafe32(pFile, (unsigned int*) pData, i32Size)) return false;
- if(!WriteMarker(pFile, nName, true)) return false;
- }
- return true;
- }
- /*!***************************************************************************
- @Function WriteData
- @Input pFile
- @Input nName
- @Input n
- @Return true if successful
- @Description Write the value n, bracketed by an nName begin/end markers.
- *****************************************************************************/
- template <typename T>
- static bool WriteData(
- FILE * const pFile,
- const unsigned int nName,
- const T &n)
- {
- unsigned int nSize = sizeof(T);
- bool bRet = WriteData(pFile, nName, (void*)&n, nSize);
- return bRet;
- }
- /*!***************************************************************************
- @Function WriteCPODData
- @Input pFile
- @Input nName
- @Input n
- @Input nEntries
- @Input bValidData
- @Return true if successful
- @Description Write the value n, bracketed by an nName begin/end markers.
- *****************************************************************************/
- static bool WriteCPODData(
- FILE * const pFile,
- const unsigned int nName,
- const CPODData &n,
- const unsigned int nEntries,
- const bool bValidData)
- {
- if(!WriteMarker(pFile, nName, false)) return false;
- if(!WriteData32(pFile, ePODFileDataType, &n.eType)) return false;
- if(!WriteData32(pFile, ePODFileN, &n.n)) return false;
- if(!WriteData32(pFile, ePODFileStride, &n.nStride)) return false;
- if(bValidData)
- {
- switch(PVRTModelPODDataTypeSize(n.eType))
- {
- case 1: if(!WriteData(pFile, ePODFileData, n.pData, nEntries * n.nStride)) return false; break;
- case 2: if(!WriteData16(pFile, ePODFileData, n.pData, nEntries * (n.nStride / 2))) return false; break;
- case 4: if(!WriteData32(pFile, ePODFileData, n.pData, nEntries * (n.nStride / 4))) return false; break;
- default: { _ASSERT(false); }
- };
- }
- else
- {
- unsigned int offset = (unsigned int) (size_t) n.pData;
- if(!WriteData32(pFile, ePODFileData, &offset)) return false;
- }
- if(!WriteMarker(pFile, nName, true)) return false;
- return true;
- }
- /*!***************************************************************************
- @Function WriteInterleaved
- @Input pFile
- @Input mesh
- @Return true if successful
- @Description Write out the interleaved data to file.
- *****************************************************************************/
- static bool WriteInterleaved(FILE * const pFile, SPODMesh &mesh)
- {
- if(!mesh.pInterleaved)
- return true;
- unsigned int i;
- unsigned int ui32CPODDataSize = 0;
- CPODData **pCPODData = new CPODData*[7 + mesh.nNumUVW];
- if(mesh.sVertex.n) pCPODData[ui32CPODDataSize++] = &mesh.sVertex;
- if(mesh.sNormals.n) pCPODData[ui32CPODDataSize++] = &mesh.sNormals;
- if(mesh.sTangents.n) pCPODData[ui32CPODDataSize++] = &mesh.sTangents;
- if(mesh.sBinormals.n) pCPODData[ui32CPODDataSize++] = &mesh.sBinormals;
- if(mesh.sVtxColours.n) pCPODData[ui32CPODDataSize++] = &mesh.sVtxColours;
- if(mesh.sBoneIdx.n) pCPODData[ui32CPODDataSize++] = &mesh.sBoneIdx;
- if(mesh.sBoneWeight.n) pCPODData[ui32CPODDataSize++] = &mesh.sBoneWeight;
- for(i = 0; i < mesh.nNumUVW; ++i)
- if(mesh.psUVW[i].n) pCPODData[ui32CPODDataSize++] = &mesh.psUVW[i];
- // Bubble sort pCPODData based on the vertex element offsets
- bool bSwap = true;
- unsigned int ui32Size = ui32CPODDataSize;
- while(bSwap)
- {
- bSwap = false;
- for(i = 0; i < ui32Size - 1; ++i)
- {
- if(pCPODData[i]->pData > pCPODData[i + 1]->pData)
- {
- PVRTswap(pCPODData[i], pCPODData[i + 1]);
- bSwap = true;
- }
- }
- --ui32Size;
- }
- // Do we need padding? If so how much? We calc this by comparing the actual stride with the one stored
- unsigned int ui32ActualStride = 0;
- for(i = 0; i < ui32CPODDataSize; ++i)
- ui32ActualStride += (unsigned int) PVRTModelPODDataStride(*pCPODData[i]);
- unsigned int ui32Pad = mesh.sVertex.nStride - ui32ActualStride;
- // Write out the data
- if(!WriteMarker(pFile, ePODFileMeshInterleaved, false, mesh.nNumVertex * mesh.sVertex.nStride)) return false;
- for(i = 0; i < mesh.nNumVertex; ++i)
- {
- unsigned char* pVtxStart = mesh.pInterleaved + (i * mesh.sVertex.nStride);
- for(unsigned int j = 0; j < ui32CPODDataSize; ++j)
- {
- unsigned char* pData = pVtxStart + (size_t) pCPODData[j]->pData;
- switch(PVRTModelPODDataTypeSize(pCPODData[j]->eType))
- {
- case 1: if(!WriteFileSafe(pFile, pData, pCPODData[j]->n)) return false; break;
- case 2: if(!WriteFileSafe16(pFile, (unsigned short*) pData, pCPODData[j]->n)) return false; break;
- case 4: if(!WriteFileSafe32(pFile, (unsigned int*) pData, pCPODData[j]->n)) return false; break;
- default: { _ASSERT(false); }
- };
- }
- // Write out the padding
- fwrite("\0\0\0\0", ui32Pad, 1, pFile);
- }
- if(!WriteMarker(pFile, ePODFileMeshInterleaved, true)) return false;
- // Tidy up
- delete[] pCPODData;
- return true;
- }
- /*!***************************************************************************
- @Function PVRTModelPODGetAnimArraySize
- @Input pAnimDataIdx
- @Input ui32Frames
- @Input ui32Components
- @Return Size of the animation array
- @Description Calculates the size of an animation array
- *****************************************************************************/
- unsigned int PVRTModelPODGetAnimArraySize(unsigned int *pAnimDataIdx, unsigned int ui32Frames, unsigned int ui32Components)
- {
- if(pAnimDataIdx)
- {
- // Find the largest index value
- unsigned int ui32Max = 0;
- for(unsigned int i = 0; i < ui32Frames; ++i)
- {
- if(ui32Max < pAnimDataIdx[i])
- ui32Max = pAnimDataIdx[i];
- }
- return ui32Max + ui32Components;
- }
- return ui32Frames * ui32Components;
- }
- /*!***************************************************************************
- @Function WritePOD
- @Output The file referenced by pFile
- @Input s The POD Scene to write
- @Input pszExpOpt Exporter options
- @Return true if successful
- @Description Write a POD file
- *****************************************************************************/
- static bool WritePOD(
- FILE * const pFile,
- const char * const pszExpOpt,
- const char * const pszHistory,
- const SPODScene &s)
- {
- unsigned int i, j;
- // Save: file version
- {
- char *pszVersion = (char*)PVRTMODELPOD_VERSION;
- if(!WriteData(pFile, ePODFileVersion, pszVersion, (unsigned int)strlen(pszVersion) + 1)) return false;
- }
- // Save: exporter options
- if(pszExpOpt && *pszExpOpt)
- {
- if(!WriteData(pFile, ePODFileExpOpt, pszExpOpt, (unsigned int)strlen(pszExpOpt) + 1)) return false;
- }
- // Save: .pod file history
- if(pszHistory && *pszHistory)
- {
- if(!WriteData(pFile, ePODFileHistory, pszHistory, (unsigned int)strlen(pszHistory) + 1)) return false;
- }
- // Save: scene descriptor
- if(!WriteMarker(pFile, ePODFileScene, false)) return false;
- {
- if(!WriteData32(pFile, ePODFileColourBackground, s.pfColourBackground, sizeof(s.pfColourBackground) / sizeof(*s.pfColourBackground))) return false;
- if(!WriteData32(pFile, ePODFileColourAmbient, s.pfColourAmbient, sizeof(s.pfColourAmbient) / sizeof(*s.pfColourAmbient))) return false;
- if(!WriteData32(pFile, ePODFileNumCamera, &s.nNumCamera)) return false;
- if(!WriteData32(pFile, ePODFileNumLight, &s.nNumLight)) return false;
- if(!WriteData32(pFile, ePODFileNumMesh, &s.nNumMesh)) return false;
- if(!WriteData32(pFile, ePODFileNumNode, &s.nNumNode)) return false;
- if(!WriteData32(pFile, ePODFileNumMeshNode, &s.nNumMeshNode)) return false;
- if(!WriteData32(pFile, ePODFileNumTexture, &s.nNumTexture)) return false;
- if(!WriteData32(pFile, ePODFileNumMaterial, &s.nNumMaterial)) return false;
- if(!WriteData32(pFile, ePODFileNumFrame, &s.nNumFrame)) return false;
- if(!WriteData32(pFile, ePODFileFPS, &s.nFPS)) return false;
- if(!WriteData32(pFile, ePODFileFlags, &s.nFlags)) return false;
- // Save: cameras
- for(i = 0; i < s.nNumCamera; ++i)
- {
- if(!WriteMarker(pFile, ePODFileCamera, false)) return false;
- if(!WriteData32(pFile, ePODFileCamIdxTgt, &s.pCamera[i].nIdxTarget)) return false;
- if(!WriteData32(pFile, ePODFileCamFOV, &s.pCamera[i].fFOV)) return false;
- if(!WriteData32(pFile, ePODFileCamFar, &s.pCamera[i].fFar)) return false;
- if(!WriteData32(pFile, ePODFileCamNear, &s.pCamera[i].fNear)) return false;
- if(!WriteData32(pFile, ePODFileCamAnimFOV, s.pCamera[i].pfAnimFOV, s.nNumFrame)) return false;
- if(!WriteMarker(pFile, ePODFileCamera, true)) return false;
- }
- // Save: lights
- for(i = 0; i < s.nNumLight; ++i)
- {
- if(!WriteMarker(pFile, ePODFileLight, false)) return false;
- if(!WriteData32(pFile, ePODFileLightIdxTgt, &s.pLight[i].nIdxTarget)) return false;
- if(!WriteData32(pFile, ePODFileLightColour, s.pLight[i].pfColour, sizeof(s.pLight[i].pfColour) / sizeof(*s.pLight[i].pfColour))) return false;
- if(!WriteData32(pFile, ePODFileLightType, &s.pLight[i].eType)) return false;
- if(s.pLight[i].eType != ePODDirectional)
- {
- if(!WriteData32(pFile, ePODFileLightConstantAttenuation, &s.pLight[i].fConstantAttenuation)) return false;
- if(!WriteData32(pFile, ePODFileLightLinearAttenuation, &s.pLight[i].fLinearAttenuation)) return false;
- if(!WriteData32(pFile, ePODFileLightQuadraticAttenuation, &s.pLight[i].fQuadraticAttenuation)) return false;
- }
- if(s.pLight[i].eType == ePODSpot)
- {
- if(!WriteData32(pFile, ePODFileLightFalloffAngle, &s.pLight[i].fFalloffAngle)) return false;
- if(!WriteData32(pFile, ePODFileLightFalloffExponent, &s.pLight[i].fFalloffExponent)) return false;
- }
- if(!WriteMarker(pFile, ePODFileLight, true)) return false;
- }
- // Save: materials
- for(i = 0; i < s.nNumMaterial; ++i)
- {
- if(!WriteMarker(pFile, ePODFileMaterial, false)) return false;
- if(!WriteData32(pFile, ePODFileMatFlags, &s.pMaterial[i].nFlags)) return false;
- if(!WriteData(pFile, ePODFileMatName, s.pMaterial[i].pszName, (unsigned int)strlen(s.pMaterial[i].pszName)+1)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexDiffuse, &s.pMaterial[i].nIdxTexDiffuse)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexAmbient, &s.pMaterial[i].nIdxTexAmbient)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexSpecularColour, &s.pMaterial[i].nIdxTexSpecularColour)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexSpecularLevel, &s.pMaterial[i].nIdxTexSpecularLevel)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexBump, &s.pMaterial[i].nIdxTexBump)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexEmissive, &s.pMaterial[i].nIdxTexEmissive)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexGlossiness, &s.pMaterial[i].nIdxTexGlossiness)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexOpacity, &s.pMaterial[i].nIdxTexOpacity)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexReflection, &s.pMaterial[i].nIdxTexReflection)) return false;
- if(!WriteData32(pFile, ePODFileMatIdxTexRefraction, &s.pMaterial[i].nIdxTexRefraction)) return false;
- if(!WriteData32(pFile, ePODFileMatOpacity, &s.pMaterial[i].fMatOpacity)) return false;
- if(!WriteData32(pFile, ePODFileMatAmbient, s.pMaterial[i].pfMatAmbient, sizeof(s.pMaterial[i].pfMatAmbient) / sizeof(*s.pMaterial[i].pfMatAmbient))) return false;
- if(!WriteData32(pFile, ePODFileMatDiffuse, s.pMaterial[i].pfMatDiffuse, sizeof(s.pMaterial[i].pfMatDiffuse) / sizeof(*s.pMaterial[i].pfMatDiffuse))) return false;
- if(!WriteData32(pFile, ePODFileMatSpecular, s.pMaterial[i].pfMatSpecular, sizeof(s.pMaterial[i].pfMatSpecular) / sizeof(*s.pMaterial[i].pfMatSpecular))) return false;
- if(!WriteData32(pFile, ePODFileMatShininess, &s.pMaterial[i].fMatShininess)) return false;
- if(!WriteData(pFile, ePODFileMatEffectFile, s.pMaterial[i].pszEffectFile, s.pMaterial[i].pszEffectFile ? ((unsigned int)strlen(s.pMaterial[i].pszEffectFile)+1) : 0)) return false;
- if(!WriteData(pFile, ePODFileMatEffectName, s.pMaterial[i].pszEffectName, s.pMaterial[i].pszEffectName ? ((unsigned int)strlen(s.pMaterial[i].pszEffectName)+1) : 0)) return false;
- if(!WriteData32(pFile, ePODFileMatBlendSrcRGB, &s.pMaterial[i].eBlendSrcRGB))return false;
- if(!WriteData32(pFile, ePODFileMatBlendSrcA, &s.pMaterial[i].eBlendSrcA)) return false;
- if(!WriteData32(pFile, ePODFileMatBlendDstRGB, &s.pMaterial[i].eBlendDstRGB))return false;
- if(!WriteData32(pFile, ePODFileMatBlendDstA, &s.pMaterial[i].eBlendDstA)) return false;
- if(!WriteData32(pFile, ePODFileMatBlendOpRGB, &s.pMaterial[i].eBlendOpRGB)) return false;
- if(!WriteData32(pFile, ePODFileMatBlendOpA, &s.pMaterial[i].eBlendOpA)) return false;
- if(!WriteData32(pFile, ePODFileMatBlendColour, s.pMaterial[i].pfBlendColour, sizeof(s.pMaterial[i].pfBlendColour) / sizeof(*s.pMaterial[i].pfBlendColour))) return false;
- if(!WriteData32(pFile, ePODFileMatBlendFactor, s.pMaterial[i].pfBlendFactor, sizeof(s.pMaterial[i].pfBlendFactor) / sizeof(*s.pMaterial[i].pfBlendFactor))) return false;
- if(!WriteMarker(pFile, ePODFileMaterial, true)) return false;
- }
- // Save: meshes
- for(i = 0; i < s.nNumMesh; ++i)
- {
- if(!WriteMarker(pFile, ePODFileMesh, false)) return false;
- if(!WriteData32(pFile, ePODFileMeshNumVtx, &s.pMesh[i].nNumVertex)) return false;
- if(!WriteData32(pFile, ePODFileMeshNumFaces, &s.pMesh[i].nNumFaces)) return false;
- if(!WriteData32(pFile, ePODFileMeshNumUVW, &s.pMesh[i].nNumUVW)) return false;
- if(!WriteData32(pFile, ePODFileMeshStripLength, s.pMesh[i].pnStripLength, s.pMesh[i].nNumStrips)) return false;
- if(!WriteData32(pFile, ePODFileMeshNumStrips, &s.pMesh[i].nNumStrips)) return false;
- if(!WriteInterleaved(pFile, s.pMesh[i])) return false;
- if(!WriteData32(pFile, ePODFileMeshBoneBatchBoneMax,&s.pMesh[i].sBoneBatches.nBatchBoneMax)) return false;
- if(!WriteData32(pFile, ePODFileMeshBoneBatchCnt, &s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
- if(!WriteData32(pFile, ePODFileMeshBoneBatches, s.pMesh[i].sBoneBatches.pnBatches, s.pMesh[i].sBoneBatches.nBatchBoneMax * s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
- if(!WriteData32(pFile, ePODFileMeshBoneBatchBoneCnts, s.pMesh[i].sBoneBatches.pnBatchBoneCnt, s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
- if(!WriteData32(pFile, ePODFileMeshBoneBatchOffsets, s.pMesh[i].sBoneBatches.pnBatchOffset,s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
- if(!WriteData32(pFile, ePODFileMeshUnpackMatrix, s.pMesh[i].mUnpackMatrix.f, 16)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshFaces, s.pMesh[i].sFaces, PVRTModelPODCountIndices(s.pMesh[i]), true)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshVtx, s.pMesh[i].sVertex, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshNor, s.pMesh[i].sNormals, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshTan, s.pMesh[i].sTangents, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshBin, s.pMesh[i].sBinormals, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- for(j = 0; j < s.pMesh[i].nNumUVW; ++j)
- if(!WriteCPODData(pFile, ePODFileMeshUVW, s.pMesh[i].psUVW[j], s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshVtxCol, s.pMesh[i].sVtxColours, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshBoneIdx, s.pMesh[i].sBoneIdx, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteCPODData(pFile, ePODFileMeshBoneWeight, s.pMesh[i].sBoneWeight, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
- if(!WriteMarker(pFile, ePODFileMesh, true)) return false;
- }
- int iTransformationNo;
- // Save: node
- for(i = 0; i < s.nNumNode; ++i)
- {
- if(!WriteMarker(pFile, ePODFileNode, false)) return false;
- {
- if(!WriteData32(pFile, ePODFileNodeIdx, &s.pNode[i].nIdx)) return false;
- if(!WriteData(pFile, ePODFileNodeName, s.pNode[i].pszName, (unsigned int)strlen(s.pNode[i].pszName)+1)) return false;
- if(!WriteData32(pFile, ePODFileNodeIdxMat, &s.pNode[i].nIdxMaterial)) return false;
- if(!WriteData32(pFile, ePODFileNodeIdxParent, &s.pNode[i].nIdxParent)) return false;
- if(!WriteData32(pFile, ePODFileNodeAnimFlags, &s.pNode[i].nAnimFlags)) return false;
- if(s.pNode[i].pnAnimPositionIdx)
- {
- if(!WriteData32(pFile, ePODFileNodeAnimPosIdx, s.pNode[i].pnAnimPositionIdx, s.nNumFrame)) return false;
- }
- iTransformationNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
- if(!WriteData32(pFile, ePODFileNodeAnimPos, s.pNode[i].pfAnimPosition, iTransformationNo)) return false;
- if(s.pNode[i].pnAnimRotationIdx)
- {
- if(!WriteData32(pFile, ePODFileNodeAnimRotIdx, s.pNode[i].pnAnimRotationIdx, s.nNumFrame)) return false;
- }
- iTransformationNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
- if(!WriteData32(pFile, ePODFileNodeAnimRot, s.pNode[i].pfAnimRotation, iTransformationNo)) return false;
- if(s.pNode[i].pnAnimScaleIdx)
- {
- if(!WriteData32(pFile, ePODFileNodeAnimScaleIdx, s.pNode[i].pnAnimScaleIdx, s.nNumFrame)) return false;
- }
- iTransformationNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
- if(!WriteData32(pFile, ePODFileNodeAnimScale, s.pNode[i].pfAnimScale, iTransformationNo)) return false;
- if(s.pNode[i].pnAnimMatrixIdx)
- {
- if(!WriteData32(pFile, ePODFileNodeAnimMatrixIdx, s.pNode[i].pnAnimMatrixIdx, s.nNumFrame)) return false;
- }
- iTransformationNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
- if(!WriteData32(pFile, ePODFileNodeAnimMatrix,s.pNode[i].pfAnimMatrix, iTransformationNo)) return false;
- }
- if(!WriteMarker(pFile, ePODFileNode, true)) return false;
- }
- // Save: texture
- for(i = 0; i < s.nNumTexture; ++i)
- {
- if(!WriteMarker(pFile, ePODFileTexture, false)) return false;
- if(!WriteData(pFile, ePODFileTexName, s.pTexture[i].pszName, (unsigned int)strlen(s.pTexture[i].pszName)+1)) return false;
- if(!WriteMarker(pFile, ePODFileTexture, true)) return false;
- }
- }
- if(!WriteMarker(pFile, ePODFileScene, true)) return false;
- return true;
- }
- /****************************************************************************
- ** Local code: File reading
- ****************************************************************************/
- /*!***************************************************************************
- @Function ReadCPODData
- @Modified s The CPODData to read into
- @Input src CSource object to read data from.
- @Input nSpec
- @Input bValidData
- @Return true if successful
- @Description Read a CPODData block in from a pod file
- *****************************************************************************/
- static bool ReadCPODData(
- CPODData &s,
- CSource &src,
- const unsigned int nSpec,
- const bool bValidData)
- {
- unsigned int nName, nLen, nBuff;
- while(src.ReadMarker(nName, nLen))
- {
- if(nName == (nSpec | PVRTMODELPOD_TAG_END))
- return true;
- switch(nName)
- {
- case ePODFileDataType: if(!src.Read32(s.eType)) return false; break;
- case ePODFileN: if(!src.Read32(s.n)) return false; break;
- case ePODFileStride: if(!src.Read32(s.nStride)) return false; break;
- case ePODFileData:
- if(bValidData)
- {
- switch(PVRTModelPODDataTypeSize(s.eType))
- {
- case 1: if(!src.ReadAfterAlloc(s.pData, nLen)) return false; break;
- case 2:
- { // reading 16bit data but have 8bit pointer
- PVRTuint16 *p16Pointer=NULL;
- if(!src.ReadAfterAlloc16(p16Pointer, nLen)) return false;
- s.pData = (unsigned char*)p16Pointer;
- break;
- }
- case 4:
- { // reading 32bit data but have 8bit pointer
- PVRTuint32 *p32Pointer=NULL;
- if(!src.ReadAfterAlloc32(p32Pointer, nLen)) return false;
- s.pData = (unsigned char*)p32Pointer;
- break;
- }
- default:
- { _ASSERT(false);}
- }
- }
- else
- {
- if(src.Read32(nBuff))
- {
- s.pData = (unsigned char*) (size_t) nBuff;
- }
- else
- {
- return false;
- }
- }
- break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadCamera
- @Modified s The SPODCamera to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a camera block in from a pod file
- *****************************************************************************/
- static bool ReadCamera(
- SPODCamera &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- s.pfAnimFOV = 0;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileCamera | PVRTMODELPOD_TAG_END: return true;
- case ePODFileCamIdxTgt: if(!src.Read32(s.nIdxTarget)) return false; break;
- case ePODFileCamFOV: if(!src.Read32(s.fFOV)) return false; break;
- case ePODFileCamFar: if(!src.Read32(s.fFar)) return false; break;
- case ePODFileCamNear: if(!src.Read32(s.fNear)) return false; break;
- case ePODFileCamAnimFOV: if(!src.ReadAfterAlloc32(s.pfAnimFOV, nLen)) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadLight
- @Modified s The SPODLight to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a light block in from a pod file
- *****************************************************************************/
- static bool ReadLight(
- SPODLight &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileLight | PVRTMODELPOD_TAG_END: return true;
- case ePODFileLightIdxTgt: if(!src.Read32(s.nIdxTarget)) return false; break;
- case ePODFileLightColour: if(!src.ReadArray32((unsigned int*) s.pfColour, 3)) return false; break;
- case ePODFileLightType: if(!src.Read32(s.eType)) return false; break;
- case ePODFileLightConstantAttenuation: if(!src.Read32(s.fConstantAttenuation)) return false; break;
- case ePODFileLightLinearAttenuation: if(!src.Read32(s.fLinearAttenuation)) return false; break;
- case ePODFileLightQuadraticAttenuation: if(!src.Read32(s.fQuadraticAttenuation)) return false; break;
- case ePODFileLightFalloffAngle: if(!src.Read32(s.fFalloffAngle)) return false; break;
- case ePODFileLightFalloffExponent: if(!src.Read32(s.fFalloffExponent)) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadMaterial
- @Modified s The SPODMaterial to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a material block in from a pod file
- *****************************************************************************/
- static bool ReadMaterial(
- SPODMaterial &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- // Set texture IDs to -1
- s.nIdxTexDiffuse = -1;
- s.nIdxTexAmbient = -1;
- s.nIdxTexSpecularColour = -1;
- s.nIdxTexSpecularLevel = -1;
- s.nIdxTexBump = -1;
- s.nIdxTexEmissive = -1;
- s.nIdxTexGlossiness = -1;
- s.nIdxTexOpacity = -1;
- s.nIdxTexReflection = -1;
- s.nIdxTexRefraction = -1;
- // Set defaults for blend modes
- s.eBlendSrcRGB = s.eBlendSrcA = ePODBlendFunc_ONE;
- s.eBlendDstRGB = s.eBlendDstA = ePODBlendFunc_ZERO;
- s.eBlendOpRGB = s.eBlendOpA = ePODBlendOp_ADD;
- memset(s.pfBlendColour, 0, sizeof(s.pfBlendColour));
- memset(s.pfBlendFactor, 0, sizeof(s.pfBlendFactor));
- // Set default for material flags
- s.nFlags = 0;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileMaterial | PVRTMODELPOD_TAG_END: return true;
- case ePODFileMatFlags: if(!src.Read32(s.nFlags)) return false; break;
- case ePODFileMatName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
- case ePODFileMatIdxTexDiffuse: if(!src.Read32(s.nIdxTexDiffuse)) return false; break;
- case ePODFileMatIdxTexAmbient: if(!src.Read32(s.nIdxTexAmbient)) return false; break;
- case ePODFileMatIdxTexSpecularColour: if(!src.Read32(s.nIdxTexSpecularColour)) return false; break;
- case ePODFileMatIdxTexSpecularLevel: if(!src.Read32(s.nIdxTexSpecularLevel)) return false; break;
- case ePODFileMatIdxTexBump: if(!src.Read32(s.nIdxTexBump)) return false; break;
- case ePODFileMatIdxTexEmissive: if(!src.Read32(s.nIdxTexEmissive)) return false; break;
- case ePODFileMatIdxTexGlossiness: if(!src.Read32(s.nIdxTexGlossiness)) return false; break;
- case ePODFileMatIdxTexOpacity: if(!src.Read32(s.nIdxTexOpacity)) return false; break;
- case ePODFileMatIdxTexReflection: if(!src.Read32(s.nIdxTexReflection)) return false; break;
- case ePODFileMatIdxTexRefraction: if(!src.Read32(s.nIdxTexRefraction)) return false; break;
- case ePODFileMatOpacity: if(!src.Read32(s.fMatOpacity)) return false; break;
- case ePODFileMatAmbient: if(!src.ReadArray32((unsigned int*) s.pfMatAmbient, sizeof(s.pfMatAmbient) / sizeof(*s.pfMatAmbient))) return false; break;
- case ePODFileMatDiffuse: if(!src.ReadArray32((unsigned int*) s.pfMatDiffuse, sizeof(s.pfMatDiffuse) / sizeof(*s.pfMatDiffuse))) return false; break;
- case ePODFileMatSpecular: if(!src.ReadArray32((unsigned int*) s.pfMatSpecular, sizeof(s.pfMatSpecular) / sizeof(*s.pfMatSpecular))) return false; break;
- case ePODFileMatShininess: if(!src.Read32(s.fMatShininess)) return false; break;
- case ePODFileMatEffectFile: if(!src.ReadAfterAlloc(s.pszEffectFile, nLen)) return false; break;
- case ePODFileMatEffectName: if(!src.ReadAfterAlloc(s.pszEffectName, nLen)) return false; break;
- case ePODFileMatBlendSrcRGB: if(!src.Read32(s.eBlendSrcRGB)) return false; break;
- case ePODFileMatBlendSrcA: if(!src.Read32(s.eBlendSrcA)) return false; break;
- case ePODFileMatBlendDstRGB: if(!src.Read32(s.eBlendDstRGB)) return false; break;
- case ePODFileMatBlendDstA: if(!src.Read32(s.eBlendDstA)) return false; break;
- case ePODFileMatBlendOpRGB: if(!src.Read32(s.eBlendOpRGB)) return false; break;
- case ePODFileMatBlendOpA: if(!src.Read32(s.eBlendOpA)) return false; break;
- case ePODFileMatBlendColour: if(!src.ReadArray32((unsigned int*) s.pfBlendColour, sizeof(s.pfBlendColour) / sizeof(*s.pfBlendColour))) return false; break;
- case ePODFileMatBlendFactor: if(!src.ReadArray32((unsigned int*) s.pfBlendFactor, sizeof(s.pfBlendFactor) / sizeof(*s.pfBlendFactor))) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function PVRTFixInterleavedEndiannessUsingCPODData
- @Modified pInterleaved - The interleaved data
- @Input data - The CPODData.
- @Return ui32Size - Number of elements in pInterleaved
- @Description Called multiple times and goes through the interleaved data
- correcting the endianness.
- *****************************************************************************/
- void PVRTFixInterleavedEndiannessUsingCPODData(unsigned char* pInterleaved, CPODData &data, unsigned int ui32Size)
- {
- if(!data.n)
- return;
- size_t ui32TypeSize = PVRTModelPODDataTypeSize(data.eType);
- unsigned char ub[4];
- unsigned char *pData = pInterleaved + (size_t) data.pData;
- switch(ui32TypeSize)
- {
- case 1: return;
- case 2:
- {
- for(unsigned int i = 0; i < ui32Size; ++i)
- {
- for(unsigned int j = 0; j < data.n; ++j)
- {
- ub[0] = pData[ui32TypeSize * j + 0];
- ub[1] = pData[ui32TypeSize * j + 1];
- ((unsigned short*) pData)[j] = (unsigned short) ((ub[1] << 8) | ub[0]);
- }
- pData += data.nStride;
- }
- }
- break;
- case 4:
- {
- for(unsigned int i = 0; i < ui32Size; ++i)
- {
- for(unsigned int j = 0; j < data.n; ++j)
- {
- ub[0] = pData[ui32TypeSize * j + 0];
- ub[1] = pData[ui32TypeSize * j + 1];
- ub[2] = pData[ui32TypeSize * j + 2];
- ub[3] = pData[ui32TypeSize * j + 3];
- ((unsigned int*) pData)[j] = (unsigned int) ((ub[3] << 24) | (ub[2] << 16) | (ub[1] << 8) | ub[0]);
- }
- pData += data.nStride;
- }
- }
- break;
- default: { _ASSERT(false); }
- };
- }
- void PVRTFixInterleavedEndianness(SPODMesh &s)
- {
- if(!s.pInterleaved || PVRTIsLittleEndian())
- return;
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sVertex, s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sNormals, s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sTangents, s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBinormals, s.nNumVertex);
- for(unsigned int i = 0; i < s.nNumUVW; ++i)
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.psUVW[i], s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sVtxColours, s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBoneIdx, s.nNumVertex);
- PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBoneWeight, s.nNumVertex);
- }
- /*!***************************************************************************
- @Function ReadMesh
- @Modified s The SPODMesh to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a mesh block in from a pod file
- *****************************************************************************/
- static bool ReadMesh(
- SPODMesh &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- unsigned int nUVWs=0;
- PVRTMatrixIdentity(s.mUnpackMatrix);
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileMesh | PVRTMODELPOD_TAG_END:
- if(nUVWs != s.nNumUVW)
- return false;
- PVRTFixInterleavedEndianness(s);
- return true;
- case ePODFileMeshNumVtx: if(!src.Read32(s.nNumVertex)) return false; break;
- case ePODFileMeshNumFaces: if(!src.Read32(s.nNumFaces)) return false; break;
- case ePODFileMeshNumUVW: if(!src.Read32(s.nNumUVW)) return false; if(!SafeAlloc(s.psUVW, s.nNumUVW)) return false; break;
- case ePODFileMeshStripLength: if(!src.ReadAfterAlloc32(s.pnStripLength, nLen)) return false; break;
- case ePODFileMeshNumStrips: if(!src.Read32(s.nNumStrips)) return false; break;
- case ePODFileMeshInterleaved: if(!src.ReadAfterAlloc(s.pInterleaved, nLen)) return false; break;
- case ePODFileMeshBoneBatches: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatches, nLen)) return false; break;
- case ePODFileMeshBoneBatchBoneCnts: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatchBoneCnt, nLen)) return false; break;
- case ePODFileMeshBoneBatchOffsets: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatchOffset, nLen)) return false; break;
- case ePODFileMeshBoneBatchBoneMax: if(!src.Read32(s.sBoneBatches.nBatchBoneMax)) return false; break;
- case ePODFileMeshBoneBatchCnt: if(!src.Read32(s.sBoneBatches.nBatchCnt)) return false; break;
- case ePODFileMeshUnpackMatrix: if(!src.ReadArray32((unsigned int*)&s.mUnpackMatrix.f[0], 16)) return false; break;
- case ePODFileMeshFaces: if(!ReadCPODData(s.sFaces, src, ePODFileMeshFaces, true)) return false; break;
- case ePODFileMeshVtx: if(!ReadCPODData(s.sVertex, src, ePODFileMeshVtx, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshNor: if(!ReadCPODData(s.sNormals, src, ePODFileMeshNor, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshTan: if(!ReadCPODData(s.sTangents, src, ePODFileMeshTan, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshBin: if(!ReadCPODData(s.sBinormals, src, ePODFileMeshBin, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshUVW: if(!ReadCPODData(s.psUVW[nUVWs++], src, ePODFileMeshUVW, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshVtxCol: if(!ReadCPODData(s.sVtxColours, src, ePODFileMeshVtxCol, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshBoneIdx: if(!ReadCPODData(s.sBoneIdx, src, ePODFileMeshBoneIdx, s.pInterleaved == 0)) return false; break;
- case ePODFileMeshBoneWeight: if(!ReadCPODData(s.sBoneWeight, src, ePODFileMeshBoneWeight, s.pInterleaved == 0)) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadNode
- @Modified s The SPODNode to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a node block in from a pod file
- *****************************************************************************/
- static bool ReadNode(
- SPODNode &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- bool bOldNodeFormat = false;
- VERTTYPE fPos[3] = {0,0,0};
- VERTTYPE fQuat[4] = {0,0,0,f2vt(1)};
- VERTTYPE fScale[7] = {f2vt(1),f2vt(1),f2vt(1),0,0,0,0};
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileNode | PVRTMODELPOD_TAG_END:
- if(bOldNodeFormat)
- {
- if(s.pfAnimPosition)
- s.nAnimFlags |= ePODHasPositionAni;
- else
- {
- s.pfAnimPosition = (VERTTYPE*) malloc(sizeof(fPos));
- memcpy(s.pfAnimPosition, fPos, sizeof(fPos));
- }
- if(s.pfAnimRotation)
- s.nAnimFlags |= ePODHasRotationAni;
- else
- {
- s.pfAnimRotation = (VERTTYPE*) malloc(sizeof(fQuat));
- memcpy(s.pfAnimRotation, fQuat, sizeof(fQuat));
- }
- if(s.pfAnimScale)
- s.nAnimFlags |= ePODHasScaleAni;
- else
- {
- s.pfAnimScale = (VERTTYPE*) malloc(sizeof(fScale));
- memcpy(s.pfAnimScale, fScale, sizeof(fScale));
- }
- }
- return true;
- case ePODFileNodeIdx: if(!src.Read32(s.nIdx)) return false; break;
- case ePODFileNodeName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
- case ePODFileNodeIdxMat: if(!src.Read32(s.nIdxMaterial)) return false; break;
- case ePODFileNodeIdxParent: if(!src.Read32(s.nIdxParent)) return false; break;
- case ePODFileNodeAnimFlags:if(!src.Read32(s.nAnimFlags))return false; break;
- case ePODFileNodeAnimPosIdx: if(!src.ReadAfterAlloc32(s.pnAnimPositionIdx, nLen)) return false; break;
- case ePODFileNodeAnimPos: if(!src.ReadAfterAlloc32(s.pfAnimPosition, nLen)) return false; break;
- case ePODFileNodeAnimRotIdx: if(!src.ReadAfterAlloc32(s.pnAnimRotationIdx, nLen)) return false; break;
- case ePODFileNodeAnimRot: if(!src.ReadAfterAlloc32(s.pfAnimRotation, nLen)) return false; break;
- case ePODFileNodeAnimScaleIdx: if(!src.ReadAfterAlloc32(s.pnAnimScaleIdx, nLen)) return false; break;
- case ePODFileNodeAnimScale: if(!src.ReadAfterAlloc32(s.pfAnimScale, nLen)) return false; break;
- case ePODFileNodeAnimMatrixIdx: if(!src.ReadAfterAlloc32(s.pnAnimMatrixIdx, nLen)) return false; break;
- case ePODFileNodeAnimMatrix:if(!src.ReadAfterAlloc32(s.pfAnimMatrix, nLen)) return false; break;
- // Parameters from the older pod format
- case ePODFileNodePos: if(!src.ReadArray32((unsigned int*) fPos, 3)) return false; bOldNodeFormat = true; break;
- case ePODFileNodeRot: if(!src.ReadArray32((unsigned int*) fQuat, 4)) return false; bOldNodeFormat = true; break;
- case ePODFileNodeScale: if(!src.ReadArray32((unsigned int*) fScale,3)) return false; bOldNodeFormat = true; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadTexture
- @Modified s The SPODTexture to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a texture block in from a pod file
- *****************************************************************************/
- static bool ReadTexture(
- SPODTexture &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileTexture | PVRTMODELPOD_TAG_END: return true;
- case ePODFileTexName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function ReadScene
- @Modified s The SPODScene to read into
- @Input src CSource object to read data from.
- @Return true if successful
- @Description Read a scene block in from a pod file
- *****************************************************************************/
- static bool ReadScene(
- SPODScene &s,
- CSource &src)
- {
- unsigned int nName, nLen;
- unsigned int nCameras=0, nLights=0, nMaterials=0, nMeshes=0, nTextures=0, nNodes=0;
- s.nFPS = 30;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileScene | PVRTMODELPOD_TAG_END:
- if(nCameras != s.nNumCamera) return false;
- if(nLights != s.nNumLight) return false;
- if(nMaterials != s.nNumMaterial) return false;
- if(nMeshes != s.nNumMesh) return false;
- if(nTextures != s.nNumTexture) return false;
- if(nNodes != s.nNumNode) return false;
- return true;
- case ePODFileColourBackground: if(!src.ReadArray32((unsigned int*) s.pfColourBackground, sizeof(s.pfColourBackground) / sizeof(*s.pfColourBackground))) return false; break;
- case ePODFileColourAmbient: if(!src.ReadArray32((unsigned int*) s.pfColourAmbient, sizeof(s.pfColourAmbient) / sizeof(*s.pfColourAmbient))) return false; break;
- case ePODFileNumCamera: if(!src.Read32(s.nNumCamera)) return false; if(!SafeAlloc(s.pCamera, s.nNumCamera)) return false; break;
- case ePODFileNumLight: if(!src.Read32(s.nNumLight)) return false; if(!SafeAlloc(s.pLight, s.nNumLight)) return false; break;
- case ePODFileNumMesh: if(!src.Read32(s.nNumMesh)) return false; if(!SafeAlloc(s.pMesh, s.nNumMesh)) return false; break;
- case ePODFileNumNode: if(!src.Read32(s.nNumNode)) return false; if(!SafeAlloc(s.pNode, s.nNumNode)) return false; break;
- case ePODFileNumMeshNode: if(!src.Read32(s.nNumMeshNode)) return false; break;
- case ePODFileNumTexture: if(!src.Read32(s.nNumTexture)) return false; if(!SafeAlloc(s.pTexture, s.nNumTexture)) return false; break;
- case ePODFileNumMaterial: if(!src.Read32(s.nNumMaterial)) return false; if(!SafeAlloc(s.pMaterial, s.nNumMaterial)) return false; break;
- case ePODFileNumFrame: if(!src.Read32(s.nNumFrame)) return false; break;
- case ePODFileFPS: if(!src.Read32(s.nFPS)) return false; break;
- case ePODFileFlags: if(!src.Read32(s.nFlags)) return false; break;
- case ePODFileCamera: if(!ReadCamera(s.pCamera[nCameras++], src)) return false; break;
- case ePODFileLight: if(!ReadLight(s.pLight[nLights++], src)) return false; break;
- case ePODFileMaterial: if(!ReadMaterial(s.pMaterial[nMaterials++], src)) return false; break;
- case ePODFileMesh: if(!ReadMesh(s.pMesh[nMeshes++], src)) return false; break;
- case ePODFileNode: if(!ReadNode(s.pNode[nNodes++], src)) return false; break;
- case ePODFileTexture: if(!ReadTexture(s.pTexture[nTextures++], src)) return false; break;
- default:
- if(!src.Skip(nLen)) return false;
- }
- }
- return false;
- }
- /*!***************************************************************************
- @Function Read
- @Output pS SPODScene data. May be NULL.
- @Input src CSource object to read data from.
- @Output pszExpOpt Export options.
- @Input count Data size.
- @Output pszHistory Export history.
- @Input historyCount History data size.
- @Description Loads the specified ".POD" file; returns the scene in
- pScene. This structure must later be destroyed with
- PVRTModelPODDestroy() to prevent memory leaks.
- ".POD" files are exported from 3D Studio MAX using a
- PowerVR plugin. pS may be NULL if only the export options
- are required.
- *****************************************************************************/
- static bool Read(
- SPODScene * const pS,
- CSource &src,
- char * const pszExpOpt,
- const size_t count,
- char * const pszHistory,
- const size_t historyCount)
- {
- unsigned int nName, nLen;
- bool bVersionOK = false, bDone = false;
- bool bNeedOptions = pszExpOpt != 0;
- bool bNeedHistory = pszHistory != 0;
- bool bLoadingOptionsOrHistory = bNeedOptions || bNeedHistory;
- while(src.ReadMarker(nName, nLen))
- {
- switch(nName)
- {
- case ePODFileVersion:
- {
- char *pszVersion = NULL;
- if(nLen != strlen(PVRTMODELPOD_VERSION)+1) return false;
- if(!SafeAlloc(pszVersion, nLen)) return false;
- if(!src.Read(pszVersion, nLen)) return false;
- if(strcmp(pszVersion, PVRTMODELPOD_VERSION) != 0) return false;
- bVersionOK = true;
- FREE(pszVersion);
- }
- continue;
- case ePODFileScene:
- if(pS)
- {
- if(!ReadScene(*pS, src))
- return false;
- bDone = true;
- }
- continue;
- case ePODFileExpOpt:
- if(bNeedOptions)
- {
- if(!src.Read(pszExpOpt, PVRT_MIN(nLen, (unsigned int) count)))
- return false;
- bNeedOptions = false;
- if(count < nLen)
- nLen -= (unsigned int) count ; // Adjust nLen as the read has moved our position
- else
- nLen = 0;
- }
- break;
- case ePODFileHistory:
- if(bNeedHistory)
- {
- if(!src.Read(pszHistory, PVRT_MIN(nLen, (unsigned int) historyCount)))
- return false;
- bNeedHistory = false;
- if(count < nLen)
- nLen -= (unsigned int) historyCount; // Adjust nLen as the read has moved our position
- else
- nLen = 0;
- }
- break;
- case ePODFileScene | PVRTMODELPOD_TAG_END:
- return bVersionOK == true && bDone == true;
- case (unsigned int) ePODFileEndiannessMisMatch:
- PVRTErrorOutputDebug("Error: Endianness mismatch between the .pod file and the platform.\n");
- return false;
- }
- if(bLoadingOptionsOrHistory && !bNeedOptions && !bNeedHistory)
- return true; // The options and/or history has been loaded
- // Unhandled data, skip it
- if(!src.Skip(nLen))
- return false;
- }
- if(bLoadingOptionsOrHistory)
- return true;
- /*
- Convert data to fixed or float point as this build desires
- */
- #ifdef PVRT_FIXED_POINT_ENABLE
- if(!(pS->nFlags & PVRTMODELPODSF_FIXED))
- PVRTModelPODToggleFixedPoint(*pS);
- #else
- if(pS->nFlags & PVRTMODELPODSF_FIXED)
- PVRTModelPODToggleFixedPoint(*pS);
- #endif
- return bVersionOK == true && bDone == true;
- }
- /*!***************************************************************************
- @Function ReadFromSourceStream
- @Output pS CPVRTModelPOD data. May not be NULL.
- @Input src CSource object to read data from.
- @Output pszExpOpt Export options.
- @Input count Data size.
- @Output pszHistory Export history.
- @Input historyCount History data size.
- @Description Loads the ".POD" data from the source stream; returns the scene
- in pS.
- *****************************************************************************/
- static EPVRTError ReadFromSourceStream(
- CPVRTModelPOD * const pS,
- CSourceStream &src,
- char * const pszExpOpt,
- const size_t count,
- char * const pszHistory,
- const size_t historyCount)
- {
- memset(pS, 0, sizeof(*pS));
- if(!Read(pszExpOpt || pszHistory ? NULL : pS, src, pszExpOpt, count, pszHistory, historyCount))
- return PVR_FAIL;
- if(pS->InitImpl() != PVR_SUCCESS)
- return PVR_FAIL;
- return PVR_SUCCESS;
- }
- /****************************************************************************
- ** Class: CPVRTModelPOD
- ****************************************************************************/
- /*!***************************************************************************
- @Function ReadFromFile
- @Input pszFileName Filename to load
- @Output pszExpOpt String in which to place exporter options
- @Input count Maximum number of characters to store.
- @Output pszHistory String in which to place the pod file history
- @Input historyCount Maximum number of characters to store.
- @Return PVR_SUCCESS if successful, PVR_FAIL if not
- @Description Loads the specified ".POD" file; returns the scene in
- pScene. This structure must later be destroyed with
- PVRTModelPODDestroy() to prevent memory leaks.
- ".POD" files are exported using the PVRGeoPOD exporters.
- If pszExpOpt is NULL, the scene is loaded; otherwise the
- scene is not loaded and pszExpOpt is filled in. The same
- is true for pszHistory.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::ReadFromFile(
- const char * const pszFileName,
- char * const pszExpOpt,
- const size_t count,
- char * const pszHistory,
- const size_t historyCount)
- {
- CSourceStream src;
- if(!src.Init(pszFileName))
- return PVR_FAIL;
- return ReadFromSourceStream(this, src, pszExpOpt, count, pszHistory, historyCount);
- }
- /*!***************************************************************************
- @Function ReadFromMemory
- @Input pData Data to load
- @Input i32Size Size of data
- @Output pszExpOpt String in which to place exporter options
- @Input count Maximum number of characters to store.
- @Output pszHistory String in which to place the pod file history
- @Input historyCount Maximum number of characters to store.
- @Return PVR_SUCCESS if successful, PVR_FAIL if not
- @Description Loads the supplied pod data. This data can be exported
- directly to a header using one of the pod exporters.
- If pszExpOpt is NULL, the scene is loaded; otherwise the
- scene is not loaded and pszExpOpt is filled in. The same
- is true for pszHistory.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::ReadFromMemory(
- const char * pData,
- const size_t i32Size,
- char * const pszExpOpt,
- const size_t count,
- char * const pszHistory,
- const size_t historyCount)
- {
- CSourceStream src;
- if(!src.Init(pData, i32Size))
- return PVR_FAIL;
- return ReadFromSourceStream(this, src, pszExpOpt, count, pszHistory, historyCount);
- }
- /*!***************************************************************************
- @Function ReadFromMemory
- @Input scene Scene data from the header file
- @Return PVR_SUCCESS if successful, PVR_FAIL if not
- @Description Sets the scene data from the supplied data structure. Use
- when loading from .H files.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::ReadFromMemory(
- const SPODScene &scene)
- {
- Destroy();
- memset(this, 0, sizeof(*this));
- *(SPODScene*)this = scene;
- if(InitImpl() != PVR_SUCCESS)
- return PVR_FAIL;
- m_pImpl->bFromMemory = true;
- return PVR_SUCCESS;
- }
- /*!***************************************************************************
- @Function CopyFromMemory
- @Input scene Scene data
- @Return PVR_SUCCESS if successful, PVR_FAIL if not
- @Description Sets the scene data from the supplied data structure.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::CopyFromMemory(const SPODScene &scene)
- {
- Destroy();
- unsigned int i;
- // SPODScene
- nNumFrame = scene.nNumFrame;
- nFPS = scene.nFPS;
- nFlags = scene.nFlags;
- for(i = 0; i < 3; ++i)
- {
- pfColourBackground[i] = scene.pfColourBackground[i];
- pfColourAmbient[i] = scene.pfColourAmbient[i];
- }
- // Nodes
- if(scene.nNumNode && SafeAlloc(pNode, sizeof(SPODNode) * scene.nNumNode))
- {
- nNumNode = scene.nNumNode;
- nNumMeshNode = scene.nNumMeshNode;
- for(i = 0; i < nNumNode; ++i)
- PVRTModelPODCopyNode(scene.pNode[i], pNode[i], scene.nNumFrame);
- }
- // Meshes
- if(scene.nNumMesh && SafeAlloc(pMesh, sizeof(SPODMesh) * scene.nNumMesh))
- {
- nNumMesh = scene.nNumMesh;
- for(i = 0; i < nNumMesh; ++i)
- PVRTModelPODCopyMesh(scene.pMesh[i], pMesh[i]);
- }
- // Cameras
- if(scene.nNumCamera && SafeAlloc(pCamera, sizeof(SPODCamera) * scene.nNumCamera))
- {
- nNumCamera = scene.nNumCamera;
- for(i = 0; i < nNumCamera; ++i)
- PVRTModelPODCopyCamera(scene.pCamera[i], pCamera[i], scene.nNumFrame);
- }
- // Lights
- if(scene.nNumLight && SafeAlloc(pLight, sizeof(SPODLight) * scene.nNumLight))
- {
- nNumLight = scene.nNumLight;
- for(i = 0; i < nNumLight; ++i)
- PVRTModelPODCopyLight(scene.pLight[i], pLight[i]);
- }
- // Textures
- if(scene.nNumTexture && SafeAlloc(pTexture, sizeof(SPODTexture) * scene.nNumTexture))
- {
- nNumTexture = scene.nNumTexture;
- for(i = 0; i < nNumTexture; ++i)
- PVRTModelPODCopyTexture(scene.pTexture[i], pTexture[i]);
- }
- // Materials
- if(scene.nNumMaterial && SafeAlloc(pMaterial, sizeof(SPODMaterial) * scene.nNumMaterial))
- {
- nNumMaterial = scene.nNumMaterial;
- for(i = 0; i < nNumMaterial; ++i)
- PVRTModelPODCopyMaterial(scene.pMaterial[i], pMaterial[i]);
- }
- if(InitImpl() != PVR_SUCCESS)
- return PVR_FAIL;
- return PVR_SUCCESS;
- }
- #if defined(WIN32) && !defined(__BADA__)
- /*!***************************************************************************
- @Function ReadFromResource
- @Input pszName Name of the resource to load from
- @Return PVR_SUCCESS if successful, PVR_FAIL if not
- @Description Loads the specified ".POD" file; returns the scene in
- pScene. This structure must later be destroyed with
- PVRTModelPODDestroy() to prevent memory leaks.
- ".POD" files are exported from 3D Studio MAX using a
- PowerVR plugin.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::ReadFromResource(
- const TCHAR * const pszName)
- {
- CSourceResource src;
- if(!src.Init(pszName))
- return PVR_FAIL;
- memset(this, 0, sizeof(*this));
- if(!Read(this, src, NULL, 0, NULL, 0))
- return PVR_FAIL;
- if(InitImpl() != PVR_SUCCESS)
- return PVR_FAIL;
- return PVR_SUCCESS;
- }
- #endif /* WIN32 */
- /*!***********************************************************************
- @Function InitImpl
- @Description Used by the Read*() fns to initialise implementation
- details. Should also be called by applications which
- manually build data in the POD structures for rendering;
- in this case call it after the data has been created.
- Otherwise, do not call this function.
- *************************************************************************/
- EPVRTError CPVRTModelPOD::InitImpl()
- {
- // Allocate space for implementation data
- delete m_pImpl;
- m_pImpl = new SPVRTPODImpl;
- if(!m_pImpl)
- return PVR_FAIL;
- // Zero implementation data
- memset(m_pImpl, 0, sizeof(*m_pImpl));
- #ifdef _DEBUG
- m_pImpl->nWmTotal = 0;
- #endif
- // Allocate world-matrix cache
- m_pImpl->pfCache = new VERTTYPE[nNumNode];
- m_pImpl->pWmCache = new PVRTMATRIX[nNumNode];
- m_pImpl->pWmZeroCache = new PVRTMATRIX[nNumNode];
- FlushCache();
- return PVR_SUCCESS;
- }
- /*!***********************************************************************
- @Function DestroyImpl
- @Description Used to free memory allocated by the implementation.
- *************************************************************************/
- void CPVRTModelPOD::DestroyImpl()
- {
- if(m_pImpl)
- {
- if(m_pImpl->pfCache) delete [] m_pImpl->pfCache;
- if(m_pImpl->pWmCache) delete [] m_pImpl->pWmCache;
- if(m_pImpl->pWmZeroCache) delete [] m_pImpl->pWmZeroCache;
- delete m_pImpl;
- m_pImpl = 0;
- }
- }
- /*!***********************************************************************
- @Function FlushCache
- @Description Clears the matrix cache; use this if necessary when you
- edit the position or animation of a node.
- *************************************************************************/
- void CPVRTModelPOD::FlushCache()
- {
- // Pre-calc frame zero matrices
- SetFrame(0);
- for(unsigned int i = 0; i < nNumNode; ++i)
- GetWorldMatrixNoCache(m_pImpl->pWmZeroCache[i], pNode[i]);
- // Load cache with frame-zero data
- memcpy(m_pImpl->pWmCache, m_pImpl->pWmZeroCache, nNumNode * sizeof(*m_pImpl->pWmCache));
- memset(m_pImpl->pfCache, 0, nNumNode * sizeof(*m_pImpl->pfCache));
- }
- /*!***************************************************************************
- @Function Constructor
- @Description Initializes the pointer to scene data to NULL
- *****************************************************************************/
- CPVRTModelPOD::CPVRTModelPOD() : m_pImpl(NULL)
- {}
- /*!***************************************************************************
- @Function Destructor
- @Description Frees the memory allocated to store the scene in pScene.
- *****************************************************************************/
- CPVRTModelPOD::~CPVRTModelPOD()
- {
- Destroy();
- }
- /*!***************************************************************************
- @Function Destroy
- @Description Frees the memory allocated to store the scene in pScene.
- *****************************************************************************/
- void CPVRTModelPOD::Destroy()
- {
- unsigned int i;
- if(m_pImpl != NULL)
- {
- /*
- Only attempt to free this memory if it was actually allocated at
- run-time, as opposed to compiled into the app.
- */
- if(!m_pImpl->bFromMemory)
- {
- for(i = 0; i < nNumCamera; ++i)
- FREE(pCamera[i].pfAnimFOV);
- FREE(pCamera);
- FREE(pLight);
- for(i = 0; i < nNumMaterial; ++i)
- {
- FREE(pMaterial[i].pszName);
- FREE(pMaterial[i].pszEffectFile);
- FREE(pMaterial[i].pszEffectName);
- }
- FREE(pMaterial);
- for(i = 0; i < nNumMesh; ++i) {
- FREE(pMesh[i].sFaces.pData);
- FREE(pMesh[i].pnStripLength);
- if(pMesh[i].pInterleaved)
- {
- FREE(pMesh[i].pInterleaved);
- }
- else
- {
- FREE(pMesh[i].sVertex.pData);
- FREE(pMesh[i].sNormals.pData);
- FREE(pMesh[i].sTangents.pData);
- FREE(pMesh[i].sBinormals.pData);
- for(unsigned int j = 0; j < pMesh[i].nNumUVW; ++j)
- FREE(pMesh[i].psUVW[j].pData);
- FREE(pMesh[i].sVtxColours.pData);
- FREE(pMesh[i].sBoneIdx.pData);
- FREE(pMesh[i].sBoneWeight.pData);
- }
- FREE(pMesh[i].psUVW);
- pMesh[i].sBoneBatches.Release();
- }
- FREE(pMesh);
- for(i = 0; i < nNumNode; ++i) {
- FREE(pNode[i].pszName);
- FREE(pNode[i].pfAnimPosition);
- FREE(pNode[i].pnAnimPositionIdx);
- FREE(pNode[i].pfAnimRotation);
- FREE(pNode[i].pnAnimRotationIdx);
- FREE(pNode[i].pfAnimScale);
- FREE(pNode[i].pnAnimScaleIdx);
- FREE(pNode[i].pfAnimMatrix);
- FREE(pNode[i].pnAnimMatrixIdx);
- pNode[i].nAnimFlags = 0;
- }
- FREE(pNode);
- for(i = 0; i < nNumTexture; ++i)
- FREE(pTexture[i].pszName);
- FREE(pTexture);
- }
- // Free the working space used by the implementation
- DestroyImpl();
- }
- memset(this, 0, sizeof(*this));
- }
- /*!***************************************************************************
- @Function SetFrame
- @Input fFrame Frame number
- @Description Set the animation frame for which subsequent Get*() calls
- should return data.
- *****************************************************************************/
- void CPVRTModelPOD::SetFrame(const VERTTYPE fFrame)
- {
- if(nNumFrame) {
- /*
- Limit animation frames.
- Example: If there are 100 frames of animation, the highest frame
- number allowed is 98, since that will blend between frames 98 and
- 99. (99 being of course the 100th frame.)
- */
- _ASSERT(fFrame <= f2vt((float)(nNumFrame-1)));
- m_pImpl->nFrame = (int)vt2f(fFrame);
- m_pImpl->fBlend = fFrame - f2vt(m_pImpl->nFrame);
- }
- else
- {
- m_pImpl->fBlend = 0;
- m_pImpl->nFrame = 0;
- }
- m_pImpl->fFrame = fFrame;
- }
- /*!***************************************************************************
- @Function GetRotationMatrix
- @Output mOut Rotation matrix
- @Input node Node to get the rotation matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetRotationMatrix(
- PVRTMATRIX &mOut,
- const SPODNode &node) const
- {
- PVRTQUATERNION q;
- if(node.pfAnimRotation)
- {
- if(node.nAnimFlags & ePODHasRotationAni)
- {
- if(node.pnAnimRotationIdx)
- {
- PVRTMatrixQuaternionSlerp(
- q,
- (PVRTQUATERNION&)node.pfAnimRotation[node.pnAnimRotationIdx[m_pImpl->nFrame]],
- (PVRTQUATERNION&)node.pfAnimRotation[node.pnAnimRotationIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
- }
- else
- {
- PVRTMatrixQuaternionSlerp(
- q,
- (PVRTQUATERNION&)node.pfAnimRotation[4*m_pImpl->nFrame],
- (PVRTQUATERNION&)node.pfAnimRotation[4*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
- }
- PVRTMatrixRotationQuaternion(mOut, q);
- }
- else
- {
- PVRTMatrixRotationQuaternion(mOut, *(PVRTQUATERNION*)node.pfAnimRotation);
- }
- }
- else
- {
- PVRTMatrixIdentity(mOut);
- }
- }
- /*!***************************************************************************
- @Function GetRotationMatrix
- @Input node Node to get the rotation matrix from
- @Returns Rotation matrix
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetRotationMatrix(const SPODNode &node) const
- {
- PVRTMat4 mOut;
- GetRotationMatrix(mOut,node);
- return mOut;
- }
- /*!***************************************************************************
- @Function GetScalingMatrix
- @Output mOut Scaling matrix
- @Input node Node to get the rotation matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetScalingMatrix(
- PVRTMATRIX &mOut,
- const SPODNode &node) const
- {
- PVRTVECTOR3 v;
- if(node.pfAnimScale)
- {
- if(node.nAnimFlags & ePODHasScaleAni)
- {
- if(node.pnAnimScaleIdx)
- {
- PVRTMatrixVec3Lerp(
- v,
- (PVRTVECTOR3&)node.pfAnimScale[node.pnAnimScaleIdx[m_pImpl->nFrame+0]],
- (PVRTVECTOR3&)node.pfAnimScale[node.pnAnimScaleIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
- }
- else
- {
- PVRTMatrixVec3Lerp(
- v,
- (PVRTVECTOR3&)node.pfAnimScale[7*(m_pImpl->nFrame+0)],
- (PVRTVECTOR3&)node.pfAnimScale[7*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
- }
- PVRTMatrixScaling(mOut, v.x, v.y, v.z);
- }
- else
- {
- PVRTMatrixScaling(mOut, node.pfAnimScale[0], node.pfAnimScale[1], node.pfAnimScale[2]);
- }
- }
- else
- {
- PVRTMatrixIdentity(mOut);
- }
- }
- /*!***************************************************************************
- @Function GetScalingMatrix
- @Input node Node to get the rotation matrix from
- @Returns Scaling matrix
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetScalingMatrix(const SPODNode &node) const
- {
- PVRTMat4 mOut;
- GetScalingMatrix(mOut, node);
- return mOut;
- }
- /*!***************************************************************************
- @Function GetTranslation
- @Output V Translation vector
- @Input node Node to get the translation vector from
- @Description Generates the translation vector for the given Mesh
- Instance. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetTranslation(
- PVRTVECTOR3 &V,
- const SPODNode &node) const
- {
- if(node.pfAnimPosition)
- {
- if(node.nAnimFlags & ePODHasPositionAni)
- {
- if(node.pnAnimPositionIdx)
- {
- PVRTMatrixVec3Lerp(V,
- (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+0]],
- (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
- }
- else
- {
- PVRTMatrixVec3Lerp(V,
- (PVRTVECTOR3&)node.pfAnimPosition[3 * (m_pImpl->nFrame+0)],
- (PVRTVECTOR3&)node.pfAnimPosition[3 * (m_pImpl->nFrame+1)], m_pImpl->fBlend);
- }
- }
- else
- {
- V = *(PVRTVECTOR3*) node.pfAnimPosition;
- }
- }
- else
- {
- _ASSERT(false);
- }
- }
- /*!***************************************************************************
- @Function GetTranslation
- @Input node Node to get the translation vector from
- @Returns Translation vector
- @Description Generates the translation vector for the given Mesh
- Instance. Uses animation data.
- *****************************************************************************/
- PVRTVec3 CPVRTModelPOD::GetTranslation(const SPODNode &node) const
- {
- PVRTVec3 vOut;
- GetTranslation(vOut, node);
- return vOut;
- }
- /*!***************************************************************************
- @Function GetTranslationMatrix
- @Output mOut Translation matrix
- @Input node Node to get the translation matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetTranslationMatrix(
- PVRTMATRIX &mOut,
- const SPODNode &node) const
- {
- PVRTVECTOR3 v;
- if(node.pfAnimPosition)
- {
- if(node.nAnimFlags & ePODHasPositionAni)
- {
- if(node.pnAnimPositionIdx)
- {
- PVRTMatrixVec3Lerp(v,
- (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+0]],
- (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
- }
- else
- {
- PVRTMatrixVec3Lerp(v,
- (PVRTVECTOR3&)node.pfAnimPosition[3*(m_pImpl->nFrame+0)],
- (PVRTVECTOR3&)node.pfAnimPosition[3*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
- }
- PVRTMatrixTranslation(mOut, v.x, v.y, v.z);
- }
- else
- {
- PVRTMatrixTranslation(mOut, node.pfAnimPosition[0], node.pfAnimPosition[1], node.pfAnimPosition[2]);
- }
- }
- else
- {
- PVRTMatrixIdentity(mOut);
- }
- }
- /*!***************************************************************************
- @Function GetTranslationMatrix
- @Input node Node to get the translation matrix from
- @Returns Translation matrix
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetTranslationMatrix(const SPODNode &node) const
- {
- PVRTMat4 mOut;
- GetTranslationMatrix(mOut, node);
- return mOut;
- }
- /*!***************************************************************************
- @Function GetTransformationMatrix
- @Output mOut Transformation matrix
- @Input node Node to get the transformation matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetTransformationMatrix(PVRTMATRIX &mOut, const SPODNode &node) const
- {
- if(node.pfAnimMatrix)
- {
- if(node.nAnimFlags & ePODHasMatrixAni)
- {
- if(node.pnAnimMatrixIdx)
- mOut = *((PVRTMATRIX*) &node.pfAnimMatrix[node.pnAnimMatrixIdx[m_pImpl->nFrame]]);
- else
- mOut = *((PVRTMATRIX*) &node.pfAnimMatrix[16*m_pImpl->nFrame]);
- }
- else
- {
- mOut = *((PVRTMATRIX*) node.pfAnimMatrix);
- }
- }
- else
- {
- PVRTMatrixIdentity(mOut);
- }
- }
- /*!***************************************************************************
- @Function GetWorldMatrixNoCache
- @Output mOut World matrix
- @Input node Node to get the world matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetWorldMatrixNoCache(
- PVRTMATRIX &mOut,
- const SPODNode &node) const
- {
- PVRTMATRIX mTmp;
- if(node.pfAnimMatrix) // The transformations are stored as matrices
- GetTransformationMatrix(mOut, node);
- else
- {
- // Scale
- GetScalingMatrix(mOut, node);
- // Rotation
- GetRotationMatrix(mTmp, node);
- PVRTMatrixMultiply(mOut, mOut, mTmp);
- // Translation
- GetTranslationMatrix(mTmp, node);
- PVRTMatrixMultiply(mOut, mOut, mTmp);
- }
- // Do we have to worry about a parent?
- if(node.nIdxParent < 0)
- return;
- // Apply parent's transform too.
- GetWorldMatrixNoCache(mTmp, pNode[node.nIdxParent]);
- PVRTMatrixMultiply(mOut, mOut, mTmp);
- }
- /*!***************************************************************************
- @Function GetWorldMatrixNoCache
- @Input node Node to get the world matrix from
- @Returns World matrix
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetWorldMatrixNoCache(const SPODNode& node) const
- {
- PVRTMat4 mWorld;
- GetWorldMatrixNoCache(mWorld,node);
- return mWorld;
- }
- /*!***************************************************************************
- @Function GetWorldMatrix
- @Output mOut World matrix
- @Input node Node to get the world matrix from
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetWorldMatrix(
- PVRTMATRIX &mOut,
- const SPODNode &node) const
- {
- unsigned int nIdx;
- #ifdef _DEBUG
- ++m_pImpl->nWmTotal;
- m_pImpl->fHitPerc = (float)m_pImpl->nWmCacheHit / (float)m_pImpl->nWmTotal;
- m_pImpl->fHitPercZero = (float)m_pImpl->nWmZeroCacheHit / (float)m_pImpl->nWmTotal;
- #endif
- // Calculate a node index
- nIdx = (unsigned int)(&node - pNode);
- // There is a dedicated cache for frame 0 data
- if(m_pImpl->fFrame == 0)
- {
- mOut = m_pImpl->pWmZeroCache[nIdx];
- #ifdef _DEBUG
- ++m_pImpl->nWmZeroCacheHit;
- #endif
- return;
- }
- // Has this matrix been calculated & cached?
- if(m_pImpl->fFrame == m_pImpl->pfCache[nIdx])
- {
- mOut = m_pImpl->pWmCache[nIdx];
- #ifdef _DEBUG
- ++m_pImpl->nWmCacheHit;
- #endif
- return;
- }
- GetWorldMatrixNoCache(mOut, node);
- // Cache the matrix
- m_pImpl->pfCache[nIdx] = m_pImpl->fFrame;
- m_pImpl->pWmCache[nIdx] = mOut;
- }
- /*!***************************************************************************
- @Function GetWorldMatrix
- @Input node Node to get the world matrix from
- @Returns World matrix
- @Description Generates the world matrix for the given Mesh Instance;
- applies the parent's transform too. Uses animation data.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetWorldMatrix(const SPODNode& node) const
- {
- PVRTMat4 mWorld;
- GetWorldMatrix(mWorld,node);
- return mWorld;
- }
- /*!***************************************************************************
- @Function GetBoneWorldMatrix
- @Output mOut Bone world matrix
- @Input NodeMesh Mesh to take the bone matrix from
- @Input NodeBone Bone to take the matrix from
- @Description Generates the world matrix for the given bone.
- *****************************************************************************/
- void CPVRTModelPOD::GetBoneWorldMatrix(
- PVRTMATRIX &mOut,
- const SPODNode &NodeMesh,
- const SPODNode &NodeBone)
- {
- PVRTMATRIX mTmp;
- VERTTYPE fFrame;
- fFrame = m_pImpl->fFrame;
- SetFrame(0);
- // Transform by object matrix
- GetWorldMatrix(mOut, NodeMesh);
- // Back transform bone from frame 0 position
- GetWorldMatrix(mTmp, NodeBone);
- PVRTMatrixInverse(mTmp, mTmp);
- PVRTMatrixMultiply(mOut, mOut, mTmp);
- // The bone origin should now be at the origin
- SetFrame(fFrame);
- // Transform bone into frame fFrame position
- GetWorldMatrix(mTmp, NodeBone);
- PVRTMatrixMultiply(mOut, mOut, mTmp);
- }
- /*!***************************************************************************
- @Function GetBoneWorldMatrix
- @Input NodeMesh Mesh to take the bone matrix from
- @Input NodeBone Bone to take the matrix from
- @Returns Bone world matrix
- @Description Generates the world matrix for the given bone.
- *****************************************************************************/
- PVRTMat4 CPVRTModelPOD::GetBoneWorldMatrix(
- const SPODNode &NodeMesh,
- const SPODNode &NodeBone)
- {
- PVRTMat4 mOut;
- GetBoneWorldMatrix(mOut,NodeMesh,NodeBone);
- return mOut;
- }
- /*!***************************************************************************
- @Function GetCamera
- @Output vFrom Position of the camera
- @Output vTo Target of the camera
- @Output vUp Up direction of the camera
- @Input nIdx Camera number
- @Return Camera horizontal FOV
- @Description Calculate the From, To and Up vectors for the given
- camera. Uses animation data.
- Note that even if the camera has a target, *pvTo is not
- the position of that target. *pvTo is a position in the
- correct direction of the target, one unit away from the
- camera.
- *****************************************************************************/
- VERTTYPE CPVRTModelPOD::GetCamera(
- PVRTVECTOR3 &vFrom,
- PVRTVECTOR3 &vTo,
- PVRTVECTOR3 &vUp,
- const unsigned int nIdx) const
- {
- PVRTMATRIX mTmp;
- VERTTYPE *pfData;
- SPODCamera *pCam;
- const SPODNode *pNd;
- _ASSERT(nIdx < nNumCamera);
- // Camera nodes are after the mesh and light nodes in the array
- pNd = &pNode[nNumMeshNode + nNumLight + nIdx];
- pCam = &pCamera[pNd->nIdx];
- GetWorldMatrix(mTmp, *pNd);
- // View position is 0,0,0,1 transformed by world matrix
- vFrom.x = mTmp.f[12];
- vFrom.y = mTmp.f[13];
- vFrom.z = mTmp.f[14];
- // View direction is 0,-1,0,1 transformed by world matrix
- vTo.x = -mTmp.f[4] + mTmp.f[12];
- vTo.y = -mTmp.f[5] + mTmp.f[13];
- vTo.z = -mTmp.f[6] + mTmp.f[14];
- #if defined(BUILD_DX9) || defined(BUILD_DX10)
- /*
- When you rotate the camera from "straight forward" to "straight down", in
- D3D the UP vector will be [0, 0, 1]
- */
- vUp.x = mTmp.f[ 8];
- vUp.y = mTmp.f[ 9];
- vUp.z = mTmp.f[10];
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- /*
- When you rotate the camera from "straight forward" to "straight down", in
- OpenGL the UP vector will be [0, 0, -1]
- */
- vUp.x = -mTmp.f[ 8];
- vUp.y = -mTmp.f[ 9];
- vUp.z = -mTmp.f[10];
- #endif
- /*
- Find & calculate FOV value
- */
- if(pCam->pfAnimFOV) {
- pfData = &pCam->pfAnimFOV[m_pImpl->nFrame];
- return pfData[0] + m_pImpl->fBlend * (pfData[1] - pfData[0]);
- } else {
- return pCam->fFOV;
- }
- }
- /*!***************************************************************************
- @Function GetCameraPos
- @Output vFrom Position of the camera
- @Output vTo Target of the camera
- @Input nIdx Camera number
- @Return Camera horizontal FOV
- @Description Calculate the position of the camera and its target. Uses
- animation data.
- If the queried camera does not have a target, *pvTo is
- not changed.
- *****************************************************************************/
- VERTTYPE CPVRTModelPOD::GetCameraPos(
- PVRTVECTOR3 &vFrom,
- PVRTVECTOR3 &vTo,
- const unsigned int nIdx) const
- {
- PVRTMATRIX mTmp;
- VERTTYPE *pfData;
- SPODCamera *pCam;
- const SPODNode *pNd;
- _ASSERT(nIdx < nNumCamera);
- // Camera nodes are after the mesh and light nodes in the array
- pNd = &pNode[nNumMeshNode + nNumLight + nIdx];
- // View position is 0,0,0,1 transformed by world matrix
- GetWorldMatrix(mTmp, *pNd);
- vFrom.x = mTmp.f[12];
- vFrom.y = mTmp.f[13];
- vFrom.z = mTmp.f[14];
- pCam = &pCamera[pNd->nIdx];
- if(pCam->nIdxTarget >= 0)
- {
- // View position is 0,0,0,1 transformed by world matrix
- GetWorldMatrix(mTmp, pNode[pCam->nIdxTarget]);
- vTo.x = mTmp.f[12];
- vTo.y = mTmp.f[13];
- vTo.z = mTmp.f[14];
- }
- /*
- Find & calculate FOV value
- */
- if(pCam->pfAnimFOV) {
- pfData = &pCam->pfAnimFOV[m_pImpl->nFrame];
- return pfData[0] + m_pImpl->fBlend * (pfData[1] - pfData[0]);
- } else {
- return pCam->fFOV;
- }
- }
- /*!***************************************************************************
- @Function GetLight
- @Output vPos Position of the light
- @Output vDir Direction of the light
- @Input nIdx Light number
- @Description Calculate the position and direction of the given Light.
- Uses animation data.
- *****************************************************************************/
- void CPVRTModelPOD::GetLight(
- PVRTVECTOR3 &vPos,
- PVRTVECTOR3 &vDir,
- const unsigned int nIdx) const
- {
- PVRTMATRIX mTmp;
- const SPODNode *pNd;
- _ASSERT(nIdx < nNumLight);
- // Light nodes are after the mesh nodes in the array
- pNd = &pNode[nNumMeshNode + nIdx];
- GetWorldMatrix(mTmp, *pNd);
- // View position is 0,0,0,1 transformed by world matrix
- vPos.x = mTmp.f[12];
- vPos.y = mTmp.f[13];
- vPos.z = mTmp.f[14];
- // View direction is 0,-1,0,0 transformed by world matrix
- vDir.x = -mTmp.f[4];
- vDir.y = -mTmp.f[5];
- vDir.z = -mTmp.f[6];
- }
- /*!***************************************************************************
- @Function GetLightPositon
- @Input u32Idx Light number
- @Return PVRTVec4 position of light with w set correctly
- @Description Calculates the position of the given light. Uses animation data
- *****************************************************************************/
- PVRTVec4 CPVRTModelPOD::GetLightPosition(const unsigned int u32Idx) const
- { // TODO: make this a real function instead of just wrapping GetLight()
- PVRTVec3 vPos, vDir;
- GetLight(vPos,vDir,u32Idx);
- _ASSERT(u32Idx < nNumLight);
- _ASSERT(pLight[u32Idx].eType!=ePODDirectional);
- return PVRTVec4(vPos,1);
- }
- /*!***************************************************************************
- @Function GetLightDirection
- @Input u32Idx Light number
- @Return PVRTVec4 direction of light with w set correctly
- @Description Calculate the direction of the given Light. Uses animation data.
- *****************************************************************************/
- PVRTVec4 CPVRTModelPOD::GetLightDirection(const unsigned int u32Idx) const
- { // TODO: make this a real function instead of just wrapping GetLight()
- PVRTVec3 vPos, vDir;
- GetLight(vPos,vDir,u32Idx);
- _ASSERT(u32Idx < nNumLight);
- _ASSERT(pLight[u32Idx].eType!=ePODPoint);
- return PVRTVec4(vDir,0);
- }
- /*!***************************************************************************
- @Function CreateSkinIdxWeight
- @Output pIdx Four bytes containing matrix indices for vertex (0..255) (D3D: use UBYTE4)
- @Output pWeight Four bytes containing blend weights for vertex (0.0 .. 1.0) (D3D: use D3DCOLOR)
- @Input nVertexBones Number of bones this vertex uses
- @Input pnBoneIdx Pointer to 'nVertexBones' indices
- @Input pfBoneWeight Pointer to 'nVertexBones' blend weights
- @Description Creates the matrix indices and blend weights for a boned
- vertex. Call once per vertex of a boned mesh.
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::CreateSkinIdxWeight(
- char * const pIdx, // Four bytes containing matrix indices for vertex (0..255) (D3D: use UBYTE4)
- char * const pWeight, // Four bytes containing blend weights for vertex (0.0 .. 1.0) (D3D: use D3DCOLOR)
- const int nVertexBones, // Number of bones this vertex uses
- const int * const pnBoneIdx, // Pointer to 'nVertexBones' indices
- const VERTTYPE * const pfBoneWeight) // Pointer to 'nVertexBones' blend weights
- {
- int i, nSum;
- int nIdx[4];
- int nWeight[4];
- for(i = 0; i < nVertexBones; ++i)
- {
- nIdx[i] = pnBoneIdx[i];
- nWeight[i] = (int)vt2f((VERTTYPEMUL(f2vt(255.0f), pfBoneWeight[i])));
- if(nIdx[i] > 255)
- {
- PVRTErrorOutputDebug("Too many bones (highest index is 255).\n");
- return PVR_FAIL;
- }
- nWeight[i] = PVRT_MAX(nWeight[i], 0);
- nWeight[i] = PVRT_MIN(nWeight[i], 255);
- }
- for(; i < 4; ++i)
- {
- nIdx[i] = 0;
- nWeight[i] = 0;
- }
- if(nVertexBones)
- {
- // It's important the weights sum to 1
- nSum = 0;
- for(i = 0; i < 4; ++i)
- nSum += nWeight[i];
- if(!nSum)
- return PVR_FAIL;
- _ASSERT(nSum <= 255);
- i = 0;
- while(nSum < 255)
- {
- if(nWeight[i]) {
- ++nWeight[i];
- ++nSum;
- }
- if(++i > 3)
- i = 0;
- }
- _ASSERT(nSum == 255);
- }
- #if defined(BUILD_DX9)
- *(unsigned int*)pIdx = D3DCOLOR_ARGB(nIdx[3], nIdx[2], nIdx[1], nIdx[0]); // UBYTE4 is WZYX
- *(unsigned int*)pWeight = D3DCOLOR_RGBA(nWeight[0], nWeight[1], nWeight[2], nWeight[3]); // D3DCOLORs are WXYZ
- #endif
- #if defined(BUILD_DX10)
- *(unsigned int*)pIdx = D3DXCOLOR((float)nIdx[3], (float)nIdx[2],(float) nIdx[1], (float)nIdx[0]); //
- *(unsigned int*)pWeight = D3DXCOLOR((float)nWeight[0], (float)nWeight[1], (float)nWeight[2], (float)nWeight[3]); //
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- // Return indices and weights as bytes
- for(i = 0; i < 4; ++i)
- {
- pIdx[i] = (char) nIdx[i];
- pWeight[i] = (char) nWeight[i];
- }
- #endif
- return PVR_SUCCESS;
- }
- /*!***************************************************************************
- @Function SavePOD
- @Input pszFilename Filename to save to
- @Input pszExpOpt A string containing the options used by the exporter
- @Description Save a binary POD file (.POD).
- *****************************************************************************/
- EPVRTError CPVRTModelPOD::SavePOD(const char * const pszFilename, const char * const pszExpOpt, const char * const pszHistory)
- {
- FILE *pFile;
- bool bRet;
- pFile = fopen(pszFilename, "wb+");
- if(!pFile)
- return PVR_FAIL;
- bRet = WritePOD(pFile, pszExpOpt, pszHistory, *this);
- // Done
- fclose(pFile);
- return bRet ? PVR_SUCCESS : PVR_FAIL;
- }
- /*!***************************************************************************
- @Function PVRTModelPODDataTypeSize
- @Input type Type to get the size of
- @Return Size of the data element
- @Description Returns the size of each data element.
- *****************************************************************************/
- size_t PVRTModelPODDataTypeSize(const EPVRTDataType type)
- {
- switch(type)
- {
- default:
- _ASSERT(false);
- return 0;
- case EPODDataFloat:
- return sizeof(float);
- case EPODDataInt:
- case EPODDataUnsignedInt:
- return sizeof(int);
- case EPODDataShort:
- case EPODDataShortNorm:
- case EPODDataUnsignedShort:
- case EPODDataUnsignedShortNorm:
- return sizeof(unsigned short);
- case EPODDataRGBA:
- return sizeof(unsigned int);
- case EPODDataARGB:
- return sizeof(unsigned int);
- case EPODDataD3DCOLOR:
- return sizeof(unsigned int);
- case EPODDataUBYTE4:
- return sizeof(unsigned int);
- case EPODDataDEC3N:
- return sizeof(unsigned int);
- case EPODDataFixed16_16:
- return sizeof(unsigned int);
- case EPODDataUnsignedByte:
- case EPODDataUnsignedByteNorm:
- case EPODDataByte:
- case EPODDataByteNorm:
- return sizeof(unsigned char);
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODDataTypeComponentCount
- @Input type Type to get the number of components from
- @Return number of components in the data element
- @Description Returns the number of components in a data element.
- *****************************************************************************/
- size_t PVRTModelPODDataTypeComponentCount(const EPVRTDataType type)
- {
- switch(type)
- {
- default:
- _ASSERT(false);
- return 0;
- case EPODDataFloat:
- case EPODDataInt:
- case EPODDataUnsignedInt:
- case EPODDataShort:
- case EPODDataShortNorm:
- case EPODDataUnsignedShort:
- case EPODDataUnsignedShortNorm:
- case EPODDataFixed16_16:
- case EPODDataByte:
- case EPODDataByteNorm:
- case EPODDataUnsignedByte:
- case EPODDataUnsignedByteNorm:
- return 1;
- case EPODDataDEC3N:
- return 3;
- case EPODDataRGBA:
- case EPODDataARGB:
- case EPODDataD3DCOLOR:
- case EPODDataUBYTE4:
- return 4;
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODDataStride
- @Input data Data elements
- @Return Size of the vector elements
- @Description Returns the size of the vector of data elements.
- *****************************************************************************/
- size_t PVRTModelPODDataStride(const CPODData &data)
- {
- return PVRTModelPODDataTypeSize(data.eType) * data.n;
- }
- /*!***************************************************************************
- @Function PVRTModelPODDataConvert
- @Modified data Data elements to convert
- @Input eNewType New type of elements
- @Input nCnt Number of elements
- @Description Convert the format of the array of vectors.
- *****************************************************************************/
- void PVRTModelPODDataConvert(CPODData &data, const unsigned int nCnt, const EPVRTDataType eNewType)
- {
- PVRTVECTOR4f v;
- unsigned int i;
- CPODData old;
- if(!data.pData || data.eType == eNewType)
- return;
- old = data;
- switch(eNewType)
- {
- case EPODDataFloat:
- case EPODDataInt:
- case EPODDataUnsignedInt:
- case EPODDataUnsignedShort:
- case EPODDataUnsignedShortNorm:
- case EPODDataFixed16_16:
- case EPODDataUnsignedByte:
- case EPODDataUnsignedByteNorm:
- case EPODDataShort:
- case EPODDataShortNorm:
- case EPODDataByte:
- case EPODDataByteNorm:
- data.n = old.n * PVRTModelPODDataTypeComponentCount(old.eType);
- break;
- case EPODDataRGBA:
- case EPODDataARGB:
- case EPODDataD3DCOLOR:
- case EPODDataUBYTE4:
- case EPODDataDEC3N:
- data.n = 1;
- break;
- default:
- _ASSERT(false); // unrecognised type
- break;
- }
- data.eType = eNewType;
- data.nStride = (unsigned int)PVRTModelPODDataStride(data);
- // If the old & new strides are identical, we can convert it in place
- if(old.nStride != data.nStride)
- {
- data.pData = (unsigned char*)malloc(data.nStride * nCnt);
- }
- for(i = 0; i < nCnt; ++i)
- {
- PVRTVertexRead(&v, old.pData + i * old.nStride, old.eType, old.n);
- PVRTVertexWrite(data.pData + i * data.nStride, eNewType, data.n * PVRTModelPODDataTypeComponentCount(data.eType), &v);
- }
- if(old.nStride != data.nStride)
- {
- FREE(old.pData);
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODScaleAndConvertVtxData
- @Modified mesh POD mesh to scale and convert the mesh data
- @Input eNewType The data type to scale and convert the vertex data to
- @Return PVR_SUCCESS on success and PVR_FAIL on failure.
- @Description Scales the vertex data to fit within the range of the requested
- data type and then converts the data to that type. This function
- isn't currently compiled in for fixed point builds of the tools.
- *****************************************************************************/
- #if !defined(PVRT_FIXED_POINT_ENABLE)
- EPVRTError PVRTModelPODScaleAndConvertVtxData(SPODMesh &mesh, const EPVRTDataType eNewType)
- {
- // Initialise the matrix to identity
- PVRTMatrixIdentity(mesh.mUnpackMatrix);
- // No vertices to process
- if(!mesh.nNumVertex)
- return PVR_SUCCESS;
- // This function expects the data to be floats and not interleaved
- if(mesh.sVertex.eType != EPODDataFloat && mesh.pInterleaved != 0)
- return PVR_FAIL;
- if(eNewType == EPODDataFloat) // Nothing to do
- return PVR_FAIL;
- // A few variables
- float fLower = 0.0f, fUpper = 0.0f;
- PVRTBOUNDINGBOX BoundingBox;
- PVRTMATRIX mOffset, mScale;
- PVRTVECTOR4 v,o;
- // Set the w component of o as it is needed for later
- o.w = 1.0f;
- // Calc bounding box
- PVRTBoundingBoxComputeInterleaved(&BoundingBox, mesh.sVertex.pData, mesh.nNumVertex, 0, mesh.sVertex.nStride);
- // Get new type data range that we wish to scale the data to
- // Due to a hardware bug in early MBXs in some cases we clamp the data to the minimum possible value +1
- switch(eNewType)
- {
- case EPODDataInt:
- fUpper = 1 << 30;
- fLower = -fUpper;
- break;
- case EPODDataUnsignedInt:
- fUpper = 1 << 30;
- break;
- case EPODDataShort:
- case EPODDataFixed16_16:
- fUpper = 32767.0f;
- fLower = -fUpper;
- break;
- case EPODDataUnsignedShort:
- fUpper = 0x0ffff;
- break;
- case EPODDataRGBA:
- case EPODDataARGB:
- case EPODDataD3DCOLOR:
- fUpper = 1.0f;
- break;
- case EPODDataUBYTE4:
- case EPODDataUnsignedByte:
- fUpper = 0x0ff;
- break;
- case EPODDataShortNorm:
- case EPODDataUnsignedShortNorm:
- case EPODDataByteNorm:
- case EPODDataUnsignedByteNorm:
- fUpper = 1.0f;
- fLower = -fUpper;
- break;
- case EPODDataDEC3N:
- fUpper = 511.0f;
- fLower = -fUpper;
- break;
- case EPODDataByte:
- fUpper = 127.0f;
- fLower = -fUpper;
- break;
- default:
- _ASSERT(false);
- return PVR_FAIL; // Unsupported format specified
- }
- PVRTVECTOR3f vScale, vOffset;
- float fRange = fUpper - fLower;
- vScale.x = fRange / (BoundingBox.Point[7].x - BoundingBox.Point[0].x);
- vScale.y = fRange / (BoundingBox.Point[7].y - BoundingBox.Point[0].y);
- vScale.z = fRange / (BoundingBox.Point[7].z - BoundingBox.Point[0].z);
- vOffset.x = -BoundingBox.Point[0].x;
- vOffset.y = -BoundingBox.Point[0].y;
- vOffset.z = -BoundingBox.Point[0].z;
- PVRTMatrixTranslation(mOffset, -fLower, -fLower, -fLower);
- PVRTMatrixScaling(mScale, 1.0f / vScale.x, 1.0f / vScale.y, 1.0f / vScale.z);
- PVRTMatrixMultiply(mesh.mUnpackMatrix, mOffset, mScale);
- PVRTMatrixTranslation(mOffset, -vOffset.x, -vOffset.y, -vOffset.z);
- PVRTMatrixMultiply(mesh.mUnpackMatrix, mesh.mUnpackMatrix, mOffset);
- // Transform vertex data
- for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
- {
- PVRTVertexRead(&v, mesh.sVertex.pData + i * mesh.sVertex.nStride, mesh.sVertex.eType, mesh.sVertex.n);
- o.x = (v.x + vOffset.x) * vScale.x + fLower;
- o.y = (v.y + vOffset.y) * vScale.y + fLower;
- o.z = (v.z + vOffset.z) * vScale.z + fLower;
- _ASSERT((o.x >= fLower && o.x <= fUpper) || fabs(1.0f - o.x / fLower) < 0.01f || fabs(1.0f - o.x / fUpper) < 0.01f);
- _ASSERT((o.y >= fLower && o.y <= fUpper) || fabs(1.0f - o.y / fLower) < 0.01f || fabs(1.0f - o.y / fUpper) < 0.01f);
- _ASSERT((o.z >= fLower && o.z <= fUpper) || fabs(1.0f - o.z / fLower) < 0.01f || fabs(1.0f - o.z / fUpper) < 0.01f);
- #if defined(_DEBUG)
- PVRTVECTOR4 res;
- PVRTTransform(&res, &o, &mesh.mUnpackMatrix);
- _ASSERT(fabs(res.x - v.x) <= 0.02);
- _ASSERT(fabs(res.y - v.y) <= 0.02);
- _ASSERT(fabs(res.z - v.z) <= 0.02);
- _ASSERT(fabs(res.w - 1.0) <= 0.02);
- #endif
- PVRTVertexWrite(mesh.sVertex.pData + i * mesh.sVertex.nStride, mesh.sVertex.eType, mesh.sVertex.n * PVRTModelPODDataTypeComponentCount(mesh.sVertex.eType), &o);
- }
- // Convert the data to the chosen format
- PVRTModelPODDataConvert(mesh.sVertex, mesh.nNumVertex, eNewType);
- return PVR_SUCCESS;
- }
- #endif
- /*!***************************************************************************
- @Function PVRTModelPODDataShred
- @Modified data Data elements to modify
- @Input nCnt Number of elements
- @Input pChannels A list of the wanted channels, e.g. {'x', 'y', 0}
- @Description Reduce the number of dimensions in 'data' using the requested
- channel array. The array should have a maximum length of 4
- or be null terminated if less channels are wanted. It is also
- possible to negate an element, e.g. {'x','y', -'z'}.
- *****************************************************************************/
- void PVRTModelPODDataShred(CPODData &data, const unsigned int nCnt, const int * pChannels)
- {
- CPODData old;
- PVRTVECTOR4f v,o;
- float * const pv = &v.x;
- float * const po = &o.x;
- unsigned int i, nCh;
- int i32Map[4];
- bool bNegate[4];
- if(!data.pData || !pChannels)
- return;
- old = data;
- // Count the number of output channels while setting up cMap and bNegate
- for(data.n = 0; data.n < 4 && pChannels[data.n]; ++data.n)
- {
- i32Map[data.n] = abs(pChannels[data.n]) == 'w' ? 3 : abs(pChannels[data.n]) - 'x';
- bNegate[data.n] = pChannels[data.n] < 0;
- }
- if(data.n > old.n)
- data.n = old.n;
- // Allocate output memory
- data.nStride = (unsigned int)PVRTModelPODDataStride(data);
- if(data.nStride == 0)
- {
- FREE(data.pData);
- return;
- }
- data.pData = (unsigned char*)malloc(data.nStride * nCnt);
- for(i = 0; i < nCnt; ++i)
- {
- // Read the vector
- PVRTVertexRead(&v, old.pData + i * old.nStride, old.eType, old.n);
- // Shred the vector
- for(nCh = 0; nCh < 4 && pChannels[nCh]; ++nCh)
- po[nCh] = bNegate[nCh] ? -pv[i32Map[nCh]] : pv[i32Map[nCh]];
- for(; nCh < 4; ++nCh)
- po[nCh] = 0;
- // Write the vector
- PVRTVertexWrite((char*)data.pData + i * data.nStride, data.eType, data.n * PVRTModelPODDataTypeComponentCount(data.eType), &o);
- }
- FREE(old.pData);
- }
- /*!***************************************************************************
- @Function PVRTModelPODReorderFaces
- @Modified mesh The mesh to re-order the faces of
- @Input i32El1 The first index to be written out
- @Input i32El2 The second index to be written out
- @Input i32El3 The third index to be written out
- @Description Reorders the face indices of a mesh.
- *****************************************************************************/
- void PVRTModelPODReorderFaces(SPODMesh &mesh, const int i32El1, const int i32El2, const int i32El3)
- {
- if(!mesh.sFaces.pData)
- return;
- unsigned int ui32V[3];
- for(unsigned int i = 0; i < mesh.nNumFaces * 3; i += 3)
- {
- unsigned char *pData = mesh.sFaces.pData + i * mesh.sFaces.nStride;
- // Read
- PVRTVertexRead(&ui32V[0], pData, mesh.sFaces.eType);
- PVRTVertexRead(&ui32V[1], pData + mesh.sFaces.nStride, mesh.sFaces.eType);
- PVRTVertexRead(&ui32V[2], pData + 2 * mesh.sFaces.nStride, mesh.sFaces.eType);
- // Write in place the new order
- PVRTVertexWrite(pData, mesh.sFaces.eType, ui32V[i32El1]);
- PVRTVertexWrite(pData + mesh.sFaces.nStride, mesh.sFaces.eType, ui32V[i32El2]);
- PVRTVertexWrite(pData + 2 * mesh.sFaces.nStride, mesh.sFaces.eType, ui32V[i32El3]);
- }
- }
- /*!***************************************************************************
- @Function InterleaveArray
- @Modified pInterleaved
- @Modified data
- @Input nNumVertex
- @Input nStride
- @Input nOffset
- @Description Interleaves the pod data
- *****************************************************************************/
- static void InterleaveArray(
- char * const pInterleaved,
- CPODData &data,
- const int nNumVertex,
- const size_t nStride,
- size_t &nOffset)
- {
- if(!data.nStride)
- return;
- for(int i = 0; i < nNumVertex; ++i)
- memcpy(pInterleaved + i * nStride + nOffset, (char*)data.pData + i * data.nStride, data.nStride);
- FREE(data.pData);
- data.nStride = (unsigned int)nStride;
- data.pData = (unsigned char*)nOffset;
- nOffset += (int)PVRTModelPODDataStride(data);
- }
- /*!***************************************************************************
- @Function DeinterleaveArray
- @Input data
- @Input pInter
- @Input nNumVertex
- @Description DeInterleaves the pod data
- *****************************************************************************/
- static void DeinterleaveArray(
- CPODData &data,
- const void * const pInter,
- const int nNumVertex)
- {
- unsigned int nSrcStride = data.nStride;
- unsigned int nDestStride = (unsigned int)PVRTModelPODDataStride(data);
- const char *pSrc = (char*)pInter + (size_t)data.pData;
- if(!nSrcStride)
- return;
- data.pData = 0;
- SafeAlloc(data.pData, nDestStride * nNumVertex);
- data.nStride = nDestStride;
- for(int i = 0; i < nNumVertex; ++i)
- memcpy((char*)data.pData + i * nDestStride, pSrc + i * nSrcStride, nDestStride);
- }
- /*!***************************************************************************
- @Function PVRTModelPODToggleInterleaved
- @Modified mesh Mesh to modify
- @Input ui32AlignToNBytes Align the interleaved data to this no. of bytes.
- @Description Switches the supplied mesh to or from interleaved data format.
- *****************************************************************************/
- void PVRTModelPODToggleInterleaved(SPODMesh &mesh, unsigned int ui32AlignToNBytes)
- {
- unsigned int i;
- if(!mesh.nNumVertex)
- return;
- if(mesh.pInterleaved)
- {
- /*
- De-interleave
- */
- DeinterleaveArray(mesh.sVertex, mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sNormals, mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sTangents, mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sBinormals, mesh.pInterleaved, mesh.nNumVertex);
- for(i = 0; i < mesh.nNumUVW; ++i)
- DeinterleaveArray(mesh.psUVW[i], mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sVtxColours, mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sBoneIdx, mesh.pInterleaved, mesh.nNumVertex);
- DeinterleaveArray(mesh.sBoneWeight, mesh.pInterleaved, mesh.nNumVertex);
- FREE(mesh.pInterleaved);
- }
- else
- {
- size_t nStride, nOffset, nBytes;
- /*
- Interleave
- */
- // Calculate how much data the interleaved array must store
- nStride = PVRTModelPODDataStride(mesh.sVertex);
- nStride += PVRTModelPODDataStride(mesh.sNormals);
- nStride += PVRTModelPODDataStride(mesh.sTangents);
- nStride += PVRTModelPODDataStride(mesh.sBinormals);
- for(i = 0; i < mesh.nNumUVW; ++i)
- nStride += PVRTModelPODDataStride(mesh.psUVW[i]);
- nStride += PVRTModelPODDataStride(mesh.sVtxColours);
- nStride += PVRTModelPODDataStride(mesh.sBoneIdx);
- nStride += PVRTModelPODDataStride(mesh.sBoneWeight);
- // Pad out the vertex stride to align the vertices to our
- // requested bytes boundry
- if(ui32AlignToNBytes > 1)
- nStride += (ui32AlignToNBytes - (nStride % ui32AlignToNBytes)) % ui32AlignToNBytes;
- // Allocate interleaved array
- SafeAlloc(mesh.pInterleaved, mesh.nNumVertex * nStride);
- // Interleave the data
- nOffset = 0;
- for(nBytes = 4; nBytes > 0; nBytes >>= 1)
- {
- if(PVRTModelPODDataTypeSize(mesh.sVertex.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sVertex, mesh.nNumVertex, nStride, nOffset);
- if(PVRTModelPODDataTypeSize(mesh.sNormals.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sNormals, mesh.nNumVertex, nStride, nOffset);
- if(PVRTModelPODDataTypeSize(mesh.sTangents.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sTangents, mesh.nNumVertex, nStride, nOffset);
- if(PVRTModelPODDataTypeSize(mesh.sBinormals.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sBinormals, mesh.nNumVertex, nStride, nOffset);
- if(PVRTModelPODDataTypeSize(mesh.sVtxColours.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sVtxColours, mesh.nNumVertex, nStride, nOffset);
- for(i = 0; i < mesh.nNumUVW; ++i)
- {
- if(PVRTModelPODDataTypeSize(mesh.psUVW[i].eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.psUVW[i], mesh.nNumVertex, nStride, nOffset);
- }
- if(PVRTModelPODDataTypeSize(mesh.sBoneIdx.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sBoneIdx, mesh.nNumVertex, nStride, nOffset);
- if(PVRTModelPODDataTypeSize(mesh.sBoneWeight.eType) == nBytes)
- InterleaveArray((char*)mesh.pInterleaved, mesh.sBoneWeight, mesh.nNumVertex, nStride, nOffset);
- }
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODDeIndex
- @Modified mesh Mesh to modify
- @Description De-indexes the supplied mesh. The mesh must be
- Interleaved before calling this function.
- *****************************************************************************/
- void PVRTModelPODDeIndex(SPODMesh &mesh)
- {
- unsigned char *pNew = 0;
- if(!mesh.pInterleaved || !mesh.nNumVertex)
- return;
- _ASSERT(mesh.nNumVertex && mesh.nNumFaces);
- // Create a new vertex list
- mesh.nNumVertex = PVRTModelPODCountIndices(mesh);
- SafeAlloc(pNew, mesh.sVertex.nStride * mesh.nNumVertex);
- // Deindex the vertices
- if(mesh.sFaces.eType == EPODDataUnsignedShort)
- {
- for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
- memcpy(pNew + i * mesh.sVertex.nStride, (char*)mesh.pInterleaved + ((unsigned short*)mesh.sFaces.pData)[i] * mesh.sVertex.nStride, mesh.sVertex.nStride);
- }
- else
- {
- _ASSERT(mesh.sFaces.eType == EPODDataUnsignedInt);
- for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
- memcpy(pNew + i * mesh.sVertex.nStride, (char*)mesh.pInterleaved + ((unsigned int*)mesh.sFaces.pData)[i] * mesh.sVertex.nStride, mesh.sVertex.nStride);
- }
- // Replace the old vertex list
- FREE(mesh.pInterleaved);
- mesh.pInterleaved = pNew;
- // Get rid of the index list
- FREE(mesh.sFaces.pData);
- mesh.sFaces.n = 0;
- mesh.sFaces.nStride = 0;
- }
- /*!***************************************************************************
- @Function PVRTModelPODToggleStrips
- @Modified mesh Mesh to modify
- @Description Converts the supplied mesh to or from strips.
- *****************************************************************************/
- void PVRTModelPODToggleStrips(SPODMesh &mesh)
- {
- CPODData old;
- size_t nIdxSize, nTriStride;
- if(!mesh.nNumFaces)
- return;
- _ASSERT(mesh.sFaces.n == 1);
- nIdxSize = PVRTModelPODDataTypeSize(mesh.sFaces.eType);
- nTriStride = PVRTModelPODDataStride(mesh.sFaces) * 3;
- old = mesh.sFaces;
- mesh.sFaces.pData = 0;
- SafeAlloc(mesh.sFaces.pData, nTriStride * mesh.nNumFaces);
- if(mesh.nNumStrips)
- {
- unsigned int nListIdxCnt, nStripIdxCnt;
- // Convert to list
- nListIdxCnt = 0;
- nStripIdxCnt = 0;
- for(unsigned int i = 0; i < mesh.nNumStrips; ++i)
- {
- for(unsigned int j = 0; j < mesh.pnStripLength[i]; ++j)
- {
- if(j)
- {
- _ASSERT(j == 1); // Because this will surely break with any other number
- memcpy(
- (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
- (char*)old.pData + nIdxSize * (nStripIdxCnt - 1),
- nIdxSize);
- nListIdxCnt += 1;
- memcpy(
- (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
- (char*)old.pData + nIdxSize * (nStripIdxCnt - 2),
- nIdxSize);
- nListIdxCnt += 1;
- memcpy(
- (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
- (char*)old.pData + nIdxSize * nStripIdxCnt,
- nIdxSize);
- nListIdxCnt += 1;
- nStripIdxCnt += 1;
- }
- else
- {
- memcpy(
- (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
- (char*)old.pData + nIdxSize * nStripIdxCnt,
- nTriStride);
- nStripIdxCnt += 3;
- nListIdxCnt += 3;
- }
- }
- }
- _ASSERT(nListIdxCnt == mesh.nNumFaces*3);
- FREE(mesh.pnStripLength);
- mesh.nNumStrips = 0;
- }
- else
- {
- int nIdxCnt;
- int nBatchCnt;
- unsigned int n0, n1, n2;
- unsigned int p0, p1, p2, nFaces;
- unsigned char* pFaces;
- // Convert to strips
- mesh.pnStripLength = (unsigned int*)calloc(mesh.nNumFaces, sizeof(*mesh.pnStripLength));
- mesh.nNumStrips = 0;
- nIdxCnt = 0;
- nBatchCnt = mesh.sBoneBatches.nBatchCnt ? mesh.sBoneBatches.nBatchCnt : 1;
- for(int h = 0; h < nBatchCnt; ++h)
- {
- n0 = 0;
- n1 = 0;
- n2 = 0;
- if(!mesh.sBoneBatches.nBatchCnt)
- {
- nFaces = mesh.nNumFaces;
- pFaces = old.pData;
- }
- else
- {
- if(h + 1 < mesh.sBoneBatches.nBatchCnt)
- nFaces = mesh.sBoneBatches.pnBatchOffset[h+1] - mesh.sBoneBatches.pnBatchOffset[h];
- else
- nFaces = mesh.nNumFaces - mesh.sBoneBatches.pnBatchOffset[h];
- pFaces = &old.pData[3 * mesh.sBoneBatches.pnBatchOffset[h] * old.nStride];
- }
- for(unsigned int i = 0; i < nFaces; ++i)
- {
- p0 = n0;
- p1 = n1;
- p2 = n2;
- PVRTVertexRead(&n0, (char*)pFaces + (3 * i + 0) * old.nStride, old.eType);
- PVRTVertexRead(&n1, (char*)pFaces + (3 * i + 1) * old.nStride, old.eType);
- PVRTVertexRead(&n2, (char*)pFaces + (3 * i + 2) * old.nStride, old.eType);
- if(mesh.pnStripLength[mesh.nNumStrips])
- {
- if(mesh.pnStripLength[mesh.nNumStrips] & 0x01)
- {
- if(p1 == n1 && p2 == n0)
- {
- PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
- ++nIdxCnt;
- mesh.pnStripLength[mesh.nNumStrips] += 1;
- continue;
- }
- }
- else
- {
- if(p2 == n1 && p0 == n0)
- {
- PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
- ++nIdxCnt;
- mesh.pnStripLength[mesh.nNumStrips] += 1;
- continue;
- }
- }
- ++mesh.nNumStrips;
- }
- // Start of strip, copy entire triangle
- PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n0);
- ++nIdxCnt;
- PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n1);
- ++nIdxCnt;
- PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
- ++nIdxCnt;
- mesh.pnStripLength[mesh.nNumStrips] += 1;
- }
- }
- if(mesh.pnStripLength[mesh.nNumStrips])
- ++mesh.nNumStrips;
- SafeRealloc(mesh.sFaces.pData, nIdxCnt * nIdxSize);
- mesh.pnStripLength = (unsigned int*)realloc(mesh.pnStripLength, sizeof(*mesh.pnStripLength) * mesh.nNumStrips);
- }
- FREE(old.pData);
- }
- /*!***************************************************************************
- @Function PVRTModelPODCountIndices
- @Input mesh Mesh
- @Return Number of indices used by mesh
- @Description Counts the number of indices of a mesh
- *****************************************************************************/
- unsigned int PVRTModelPODCountIndices(const SPODMesh &mesh)
- {
- if(mesh.nNumStrips)
- {
- unsigned int i, n = 0;
- for(i = 0; i < mesh.nNumStrips; ++i)
- n += mesh.pnStripLength[i] + 2;
- return n;
- }
- return mesh.nNumFaces * 3;
- }
- static void FloatToFixed(int * const pn, const float * const pf, unsigned int n)
- {
- if(!pn || !pf) return;
- while(n)
- {
- --n;
- pn[n] = (int)(pf[n] * (float)(1<<16));
- }
- }
- static void FixedToFloat(float * const pf, const int * const pn, unsigned int n)
- {
- if(!pn || !pf) return;
- while(n)
- {
- --n;
- pf[n] = (float)pn[n] / (float)(1<<16);
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODToggleFixedPoint
- @Modified s Scene to modify
- @Description Switch all non-vertex data between fixed-point and
- floating-point.
- *****************************************************************************/
- void PVRTModelPODToggleFixedPoint(SPODScene &s)
- {
- unsigned int i;
- int i32TransformNo;
- if(s.nFlags & PVRTMODELPODSF_FIXED)
- {
- /*
- Convert to floating-point
- */
- for(i = 0; i < s.nNumCamera; ++i)
- {
- FixedToFloat((float*)&s.pCamera[i].fFOV, (int*)&s.pCamera[i].fFOV, 1);
- FixedToFloat((float*)&s.pCamera[i].fFar, (int*)&s.pCamera[i].fFar, 1);
- FixedToFloat((float*)&s.pCamera[i].fNear, (int*)&s.pCamera[i].fNear, 1);
- FixedToFloat((float*)s.pCamera[i].pfAnimFOV, (int*)s.pCamera[i].pfAnimFOV, s.nNumFrame);
- }
- for(i = 0; i < s.nNumLight; ++i)
- {
- FixedToFloat((float*)&s.pLight[i].pfColour, (int*)&s.pLight[i].pfColour, 3);
- FixedToFloat((float*)&s.pLight[i].fConstantAttenuation, (int*)&s.pLight[i].fConstantAttenuation, 1);
- FixedToFloat((float*)&s.pLight[i].fLinearAttenuation, (int*)&s.pLight[i].fLinearAttenuation, 1);
- FixedToFloat((float*)&s.pLight[i].fQuadraticAttenuation,(int*)&s.pLight[i].fQuadraticAttenuation, 1);
- FixedToFloat((float*)&s.pLight[i].fFalloffAngle, (int*)&s.pLight[i].fFalloffAngle, 1);
- FixedToFloat((float*)&s.pLight[i].fFalloffExponent, (int*)&s.pLight[i].fFalloffExponent, 1);
- }
- for(i = 0; i < s.nNumNode; ++i)
- {
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
- FixedToFloat((float*)s.pNode[i].pfAnimPosition, (int*)s.pNode[i].pfAnimPosition, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
- FixedToFloat((float*)s.pNode[i].pfAnimRotation, (int*)s.pNode[i].pfAnimRotation, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
- FixedToFloat((float*)s.pNode[i].pfAnimScale, (int*)s.pNode[i].pfAnimScale, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
- FixedToFloat((float*)s.pNode[i].pfAnimMatrix, (int*)s.pNode[i].pfAnimMatrix, i32TransformNo);
- }
- for(i = 0; i < s.nNumMaterial; ++i)
- {
- FixedToFloat((float*)&s.pMaterial[i].fMatOpacity, (int*)&s.pMaterial[i].fMatOpacity, 1);
- FixedToFloat((float*)s.pMaterial[i].pfMatAmbient, (int*)s.pMaterial[i].pfMatAmbient, 3);
- FixedToFloat((float*)s.pMaterial[i].pfMatDiffuse, (int*)s.pMaterial[i].pfMatDiffuse, 3);
- FixedToFloat((float*)s.pMaterial[i].pfMatSpecular, (int*)s.pMaterial[i].pfMatSpecular, 3);
- FixedToFloat((float*)&s.pMaterial[i].fMatShininess, (int*)&s.pMaterial[i].fMatShininess, 1);
- }
- for(i = 0; i < s.nNumMesh; ++i)
- {
- FixedToFloat((float*)&s.pMesh[i].mUnpackMatrix.f[0], (int*)&s.pMesh[i].mUnpackMatrix.f[0], 16);
- }
- FixedToFloat((float*)s.pfColourBackground, (int*)s.pfColourBackground, 3);
- FixedToFloat((float*)s.pfColourAmbient, (int*)s.pfColourAmbient, 3);
- }
- else
- {
- /*
- Convert to Fixed-point
- */
- for(i = 0; i < s.nNumCamera; ++i)
- {
- FloatToFixed((int*)&s.pCamera[i].fFOV, (float*)&s.pCamera[i].fFOV, 1);
- FloatToFixed((int*)&s.pCamera[i].fFar, (float*)&s.pCamera[i].fFar, 1);
- FloatToFixed((int*)&s.pCamera[i].fNear, (float*)&s.pCamera[i].fNear, 1);
- FloatToFixed((int*)s.pCamera[i].pfAnimFOV, (float*)s.pCamera[i].pfAnimFOV, s.nNumFrame);
- }
- for(i = 0; i < s.nNumLight; ++i)
- {
- FloatToFixed((int*)&s.pLight[i].pfColour, (float*)&s.pLight[i].pfColour, 3);
- FloatToFixed((int*)&s.pLight[i].fConstantAttenuation, (float*)&s.pLight[i].fConstantAttenuation, 1);
- FloatToFixed((int*)&s.pLight[i].fLinearAttenuation, (float*)&s.pLight[i].fLinearAttenuation, 1);
- FloatToFixed((int*)&s.pLight[i].fQuadraticAttenuation,(float*)&s.pLight[i].fQuadraticAttenuation, 1);
- FloatToFixed((int*)&s.pLight[i].fFalloffAngle, (float*)&s.pLight[i].fFalloffAngle, 1);
- FloatToFixed((int*)&s.pLight[i].fFalloffExponent, (float*)&s.pLight[i].fFalloffExponent, 1);
- }
- for(i = 0; i < s.nNumNode; ++i)
- {
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
- FloatToFixed((int*)s.pNode[i].pfAnimPosition, (float*)s.pNode[i].pfAnimPosition, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
- FloatToFixed((int*)s.pNode[i].pfAnimRotation, (float*)s.pNode[i].pfAnimRotation, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
- FloatToFixed((int*)s.pNode[i].pfAnimScale, (float*)s.pNode[i].pfAnimScale, i32TransformNo);
- i32TransformNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
- FloatToFixed((int*)s.pNode[i].pfAnimMatrix, (float*)s.pNode[i].pfAnimMatrix, i32TransformNo);
- }
- for(i = 0; i < s.nNumMaterial; ++i)
- {
- FloatToFixed((int*)&s.pMaterial[i].fMatOpacity, (float*)&s.pMaterial[i].fMatOpacity, 1);
- FloatToFixed((int*)s.pMaterial[i].pfMatAmbient, (float*)s.pMaterial[i].pfMatAmbient, 3);
- FloatToFixed((int*)s.pMaterial[i].pfMatDiffuse, (float*)s.pMaterial[i].pfMatDiffuse, 3);
- FloatToFixed((int*)s.pMaterial[i].pfMatSpecular, (float*)s.pMaterial[i].pfMatSpecular, 3);
- FloatToFixed((int*)&s.pMaterial[i].fMatShininess, (float*)&s.pMaterial[i].fMatShininess, 1);
- }
- for(i = 0; i < s.nNumMesh; ++i)
- {
- FloatToFixed((int*)&s.pMesh[i].mUnpackMatrix.f[0], (float*)&s.pMesh[i].mUnpackMatrix.f[0], 16);
- }
- FloatToFixed((int*)s.pfColourBackground, (float*)s.pfColourBackground, 3);
- FloatToFixed((int*)s.pfColourAmbient, (float*)s.pfColourAmbient, 3);
- }
- // Done
- s.nFlags ^= PVRTMODELPODSF_FIXED;
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyCPODData
- @Input in
- @Output out
- @Input ui32No
- @Input bInterleaved
- @Description Used to copy a CPODData of a mesh
- *****************************************************************************/
- void PVRTModelPODCopyCPODData(const CPODData &in, CPODData &out, unsigned int ui32No, bool bInterleaved)
- {
- FREE(out.pData);
- out.eType = in.eType;
- out.n = in.n;
- out.nStride = in.nStride;
- if(bInterleaved)
- {
- out.pData = in.pData;
- }
- else if(in.pData)
- {
- size_t ui32Size = PVRTModelPODDataStride(out) * ui32No;
- if(SafeAlloc(out.pData, ui32Size))
- memcpy(out.pData, in.pData, ui32Size);
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyNode
- @Input in
- @Output out
- @Input nNumFrames
- @Description Used to copy a pod node
- *****************************************************************************/
- void PVRTModelPODCopyNode(const SPODNode &in, SPODNode &out, int nNumFrames)
- {
- out.nIdx = in.nIdx;
- out.nIdxMaterial = in.nIdxMaterial;
- out.nIdxParent = in.nIdxParent;
- out.nAnimFlags = in.nAnimFlags;
- if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
- memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
- int i32Size;
- // Position
- i32Size = in.nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(in.pnAnimPositionIdx, nNumFrames, 3) : 3;
- if(in.pnAnimPositionIdx && SafeAlloc(out.pnAnimPositionIdx, sizeof(*out.pnAnimPositionIdx) * nNumFrames))
- memcpy(out.pnAnimPositionIdx, in.pnAnimPositionIdx, sizeof(*out.pnAnimPositionIdx) * nNumFrames);
- if(in.pfAnimPosition && SafeAlloc(out.pfAnimPosition, sizeof(*out.pfAnimPosition) * i32Size))
- memcpy(out.pfAnimPosition, in.pfAnimPosition, sizeof(*out.pfAnimPosition) * i32Size);
- // Rotation
- i32Size = in.nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(in.pnAnimRotationIdx, nNumFrames, 4) : 4;
- if(in.pnAnimRotationIdx && SafeAlloc(out.pnAnimRotationIdx, sizeof(*out.pnAnimRotationIdx) * nNumFrames))
- memcpy(out.pnAnimRotationIdx, in.pnAnimRotationIdx, sizeof(*out.pnAnimRotationIdx) * nNumFrames);
- if(in.pfAnimRotation && SafeAlloc(out.pfAnimRotation, sizeof(*out.pfAnimRotation) * i32Size))
- memcpy(out.pfAnimRotation, in.pfAnimRotation, sizeof(*out.pfAnimRotation) * i32Size);
- // Scale
- i32Size = in.nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(in.pnAnimScaleIdx, nNumFrames, 7) : 7;
- if(in.pnAnimScaleIdx && SafeAlloc(out.pnAnimScaleIdx, sizeof(*out.pnAnimScaleIdx) * nNumFrames))
- memcpy(out.pnAnimScaleIdx, in.pnAnimScaleIdx, sizeof(*out.pnAnimScaleIdx) * nNumFrames);
- if(in.pfAnimScale && SafeAlloc(out.pfAnimScale, sizeof(*out.pfAnimScale) * i32Size))
- memcpy(out.pfAnimScale, in.pfAnimScale, sizeof(*out.pfAnimScale) * i32Size);
- // Matrix
- i32Size = in.nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(in.pnAnimMatrixIdx, nNumFrames, 16) : 16;
- if(in.pnAnimMatrixIdx && SafeAlloc(out.pnAnimMatrixIdx, sizeof(*out.pnAnimMatrixIdx) * nNumFrames))
- memcpy(out.pnAnimMatrixIdx, in.pnAnimMatrixIdx, sizeof(*out.pnAnimMatrixIdx) * nNumFrames);
- if(in.pfAnimMatrix && SafeAlloc(out.pfAnimMatrix, sizeof(*out.pfAnimMatrix) * i32Size))
- memcpy(out.pfAnimMatrix, in.pfAnimMatrix, sizeof(*out.pfAnimMatrix) * i32Size);
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyMesh
- @Input in
- @Output out
- @Description Used to copy a pod mesh
- *****************************************************************************/
- void PVRTModelPODCopyMesh(const SPODMesh &in, SPODMesh &out)
- {
- unsigned int i;
- size_t i32Stride = 0;
- bool bInterleaved = in.pInterleaved != 0;
- out.nNumVertex = in.nNumVertex;
- out.nNumFaces = in.nNumFaces;
- // Face data
- PVRTModelPODCopyCPODData(in.sFaces , out.sFaces , out.nNumFaces * 3, false);
- // Vertex data
- PVRTModelPODCopyCPODData(in.sVertex , out.sVertex , out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sVertex);
- PVRTModelPODCopyCPODData(in.sNormals , out.sNormals , out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sNormals);
- PVRTModelPODCopyCPODData(in.sTangents , out.sTangents , out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sTangents);
- PVRTModelPODCopyCPODData(in.sBinormals , out.sBinormals , out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sBinormals);
- PVRTModelPODCopyCPODData(in.sVtxColours, out.sVtxColours, out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sVtxColours);
- PVRTModelPODCopyCPODData(in.sBoneIdx , out.sBoneIdx , out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sBoneIdx);
- PVRTModelPODCopyCPODData(in.sBoneWeight, out.sBoneWeight, out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.sBoneWeight);
- if(in.nNumUVW && SafeAlloc(out.psUVW, sizeof(CPODData) * in.nNumUVW))
- {
- out.nNumUVW = in.nNumUVW;
- for(i = 0; i < out.nNumUVW; ++i)
- {
- PVRTModelPODCopyCPODData(in.psUVW[i], out.psUVW[i], out.nNumVertex, bInterleaved);
- i32Stride += PVRTModelPODDataStride(out.psUVW[i]);
- }
- }
- // Allocate and copy interleaved array
- if(bInterleaved && SafeAlloc(out.pInterleaved, out.nNumVertex * i32Stride))
- memcpy(out.pInterleaved, in.pInterleaved, out.nNumVertex * i32Stride);
- if(in.pnStripLength && SafeAlloc(out.pnStripLength, sizeof(*out.pnStripLength) * out.nNumFaces))
- {
- memcpy(out.pnStripLength, in.pnStripLength, sizeof(*out.pnStripLength) * out.nNumFaces);
- out.nNumStrips = in.nNumStrips;
- }
- if(in.sBoneBatches.nBatchCnt)
- {
- out.sBoneBatches.Release();
- out.sBoneBatches.nBatchBoneMax = in.sBoneBatches.nBatchBoneMax;
- out.sBoneBatches.nBatchCnt = in.sBoneBatches.nBatchCnt;
- if(in.sBoneBatches.pnBatches)
- {
- out.sBoneBatches.pnBatches = new int[out.sBoneBatches.nBatchCnt * out.sBoneBatches.nBatchBoneMax];
- if(out.sBoneBatches.pnBatches)
- memcpy(out.sBoneBatches.pnBatches, in.sBoneBatches.pnBatches, out.sBoneBatches.nBatchCnt * out.sBoneBatches.nBatchBoneMax * sizeof(*out.sBoneBatches.pnBatches));
- }
- if(in.sBoneBatches.pnBatchBoneCnt)
- {
- out.sBoneBatches.pnBatchBoneCnt = new int[out.sBoneBatches.nBatchCnt];
- if(out.sBoneBatches.pnBatchBoneCnt)
- memcpy(out.sBoneBatches.pnBatchBoneCnt, in.sBoneBatches.pnBatchBoneCnt, out.sBoneBatches.nBatchCnt * sizeof(*out.sBoneBatches.pnBatchBoneCnt));
- }
- if(in.sBoneBatches.pnBatchOffset)
- {
- out.sBoneBatches.pnBatchOffset = new int[out.sBoneBatches.nBatchCnt];
- if(out.sBoneBatches.pnBatchOffset)
- memcpy(out.sBoneBatches.pnBatchOffset, in.sBoneBatches.pnBatchOffset, out.sBoneBatches.nBatchCnt * sizeof(*out.sBoneBatches.pnBatchOffset));
- }
- }
- memcpy(out.mUnpackMatrix.f, in.mUnpackMatrix.f, sizeof(in.mUnpackMatrix.f[0]) * 16);
- out.ePrimitiveType = in.ePrimitiveType;
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyTexture
- @Input in
- @Output out
- @Description Used to copy a pod texture
- *****************************************************************************/
- void PVRTModelPODCopyTexture(const SPODTexture &in, SPODTexture &out)
- {
- if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
- memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyMaterial
- @Input in
- @Output out
- @Description Used to copy a pod material
- *****************************************************************************/
- void PVRTModelPODCopyMaterial(const SPODMaterial &in, SPODMaterial &out)
- {
- memcpy(&out, &in, sizeof(SPODMaterial));
- out.pszName = 0;
- out.pszEffectFile = 0;
- out.pszEffectName = 0;
- if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
- memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
- if(in.pszEffectFile && SafeAlloc(out.pszEffectFile, strlen(in.pszEffectFile) + 1))
- memcpy(out.pszEffectFile, in.pszEffectFile, strlen(in.pszEffectFile) + 1);
- if(in.pszEffectName && SafeAlloc(out.pszEffectName, strlen(in.pszEffectName) + 1))
- memcpy(out.pszEffectName, in.pszEffectName, strlen(in.pszEffectName) + 1);
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyCamera
- @Input in
- @Output out
- @Input nNumFrames The number of animation frames
- @Description Used to copy a pod camera
- *****************************************************************************/
- void PVRTModelPODCopyCamera(const SPODCamera &in, SPODCamera &out, int nNumFrames)
- {
- memcpy(&out, &in, sizeof(SPODCamera));
- out.pfAnimFOV = 0;
- if(in.pfAnimFOV && SafeAlloc(out.pfAnimFOV, sizeof(*out.pfAnimFOV) * nNumFrames))
- memcpy(out.pfAnimFOV, in.pfAnimFOV, sizeof(*out.pfAnimFOV) * nNumFrames);
- }
- /*!***************************************************************************
- @Function PVRTModelPODCopyLight
- @Input in
- @Output out
- @Description Used to copy a pod light
- *****************************************************************************/
- void PVRTModelPODCopyLight(const SPODLight &in, SPODLight &out)
- {
- memcpy(&out, &in, sizeof(SPODLight));
- }
- /*!***************************************************************************
- @Function TransformCPODData
- @Input in
- @Output out
- @Input idx Value to transform
- @Input pPalette Palette of matrices to transform with
- @Input pBoneIdx Array of indices into pPalette
- @Input pBoneWeight Array of weights to weight the influence of the matrices of pPalette with
- @Input i32BoneCnt Size of pBoneIdx and pBoneWeight
- @Description Used to transform a particular value in a CPODData
- *****************************************************************************/
- inline void TransformCPODData(CPODData &in, CPODData &out, int idx, PVRTMATRIX *pPalette, float *pBoneIdx, float *pBoneW, int i32BoneCnt, bool bNormalise)
- {
- PVRTVECTOR4f fResult, fOrig, fTmp;
- if(in.n)
- {
- PVRTVertexRead(&fOrig, in.pData + (idx * in.nStride), in.eType, in.n);
- memset(&fResult.x, 0, sizeof(fResult));
- if(i32BoneCnt)
- {
- for(int i = 0; i < i32BoneCnt; ++i)
- {
- int i32BoneIdx = (int) pBoneIdx[i];
- fTmp.x = vt2f(pPalette[i32BoneIdx].f[0]) * fOrig.x + vt2f(pPalette[i32BoneIdx].f[4]) * fOrig.y + vt2f(pPalette[i32BoneIdx].f[8]) * fOrig.z + vt2f(pPalette[i32BoneIdx].f[12]) * fOrig.w;
- fTmp.y = vt2f(pPalette[i32BoneIdx].f[1]) * fOrig.x + vt2f(pPalette[i32BoneIdx].f[5]) * fOrig.y + vt2f(pPalette[i32BoneIdx].f[9]) * fOrig.z + vt2f(pPalette[i32BoneIdx].f[13]) * fOrig.w;
- fTmp.z = vt2f(pPalette[i32BoneIdx].f[2]) * fOrig.x + vt2f(pPalette[i32BoneIdx].f[6]) * fOrig.y + vt2f(pPalette[i32BoneIdx].f[10])* fOrig.z + vt2f(pPalette[i32BoneIdx].f[14]) * fOrig.w;
- fTmp.w = vt2f(pPalette[i32BoneIdx].f[3]) * fOrig.x + vt2f(pPalette[i32BoneIdx].f[7]) * fOrig.y + vt2f(pPalette[i32BoneIdx].f[11])* fOrig.z + vt2f(pPalette[i32BoneIdx].f[15]) * fOrig.w;
- fResult.x += fTmp.x * pBoneW[i];
- fResult.y += fTmp.y * pBoneW[i];
- fResult.z += fTmp.z * pBoneW[i];
- fResult.w += fTmp.w * pBoneW[i];
- }
- }
- else
- {
- fResult.x = vt2f(pPalette[0].f[0]) * fOrig.x + vt2f(pPalette[0].f[4]) * fOrig.y + vt2f(pPalette[0].f[8]) * fOrig.z + vt2f(pPalette[0].f[12]) * fOrig.w;
- fResult.y = vt2f(pPalette[0].f[1]) * fOrig.x + vt2f(pPalette[0].f[5]) * fOrig.y + vt2f(pPalette[0].f[9]) * fOrig.z + vt2f(pPalette[0].f[13]) * fOrig.w;
- fResult.z = vt2f(pPalette[0].f[2]) * fOrig.x + vt2f(pPalette[0].f[6]) * fOrig.y + vt2f(pPalette[0].f[10])* fOrig.z + vt2f(pPalette[0].f[14]) * fOrig.w;
- fResult.w = vt2f(pPalette[0].f[3]) * fOrig.x + vt2f(pPalette[0].f[7]) * fOrig.y + vt2f(pPalette[0].f[11])* fOrig.z + vt2f(pPalette[0].f[15]) * fOrig.w;
- }
- if(bNormalise)
- {
- double temp = (double)(fResult.x * fResult.x + fResult.y * fResult.y + fResult.z * fResult.z);
- temp = 1.0 / sqrt(temp);
- float f = (float)temp;
- fResult.x = fResult.x * f;
- fResult.y = fResult.y * f;
- fResult.z = fResult.z * f;
- }
- PVRTVertexWrite(out.pData + (idx * out.nStride), out.eType, in.n, &fResult);
- }
- }
- /*!***************************************************************************
- @Function PVRTModelPODFlattenToWorldSpace
- @Input in - Source scene. All meshes must not be interleaved.
- @Output out
- @Description Used to flatten a pod scene to world space. All animation
- and skinning information will be removed. The returned
- position, normal, binormals and tangent data if present
- will be returned as floats regardless of the input data
- type.
- *****************************************************************************/
- EPVRTError PVRTModelPODFlattenToWorldSpace(CPVRTModelPOD &in, CPVRTModelPOD &out)
- {
- unsigned int i, j, k, l;
- PVRTMATRIX mWorld;
- // Destroy the out pod scene to make sure it is clean
- out.Destroy();
- // Init mesh and node arrays
- SafeAlloc(out.pNode, sizeof(SPODNode) * in.nNumNode);
- SafeAlloc(out.pMesh, sizeof(SPODMesh) * in.nNumMeshNode);
- out.nNumNode = in.nNumNode;
- out.nNumMesh = out.nNumMeshNode = in.nNumMeshNode;
- // Init scene values
- out.nNumFrame = 0;
- out.nFlags = in.nFlags;
- for(i = 0; i < 3; ++i)
- {
- out.pfColourBackground[i] = in.pfColourBackground[i];
- out.pfColourAmbient[i] = in.pfColourAmbient[i];
- }
- // flatten meshes to world space
- for(i = 0; i < in.nNumMeshNode; ++i)
- {
- SPODNode& inNode = in.pNode[i];
- SPODNode& outNode = out.pNode[i];
- // Get the meshes
- SPODMesh& inMesh = in.pMesh[inNode.nIdx];
- SPODMesh& outMesh = out.pMesh[i];
- if(inMesh.pInterleaved != 0) // This function requires all the meshes to be de-interleaved
- {
- _ASSERT(inMesh.pInterleaved == 0);
- out.Destroy(); // Tidy up
- return PVR_FAIL;
- }
- // Copy the node
- PVRTModelPODCopyNode(inNode, outNode, in.nNumFrame);
- // Strip out animation and parenting
- outNode.nIdxParent = -1;
- outNode.nAnimFlags = 0;
- FREE(outNode.pfAnimMatrix);
- FREE(outNode.pfAnimPosition);
- FREE(outNode.pfAnimRotation);
- FREE(outNode.pfAnimScale);
- // Update the mesh ID. The rest of the IDs should remain correct
- outNode.nIdx = i;
- // Copy the mesh
- PVRTModelPODCopyMesh(inMesh, outMesh);
- // Strip out skinning information as that is no longer needed
- outMesh.sBoneBatches.Release();
- outMesh.sBoneIdx.Reset();
- outMesh.sBoneWeight.Reset();
- // Set the data type to float and resize the arrays as this function outputs transformed data as float only
- if(inMesh.sVertex.n)
- {
- outMesh.sVertex.eType = EPODDataFloat;
- outMesh.sVertex.pData = (unsigned char*) realloc(outMesh.sVertex.pData, PVRTModelPODDataStride(outMesh.sVertex) * inMesh.nNumVertex);
- }
- if(inMesh.sNormals.n)
- {
- outMesh.sNormals.eType = EPODDataFloat;
- outMesh.sNormals.pData = (unsigned char*) realloc(outMesh.sNormals.pData, PVRTModelPODDataStride(outMesh.sNormals) * inMesh.nNumVertex);
- }
- if(inMesh.sTangents.n)
- {
- outMesh.sTangents.eType = EPODDataFloat;
- outMesh.sTangents.pData = (unsigned char*) realloc(outMesh.sTangents.pData, PVRTModelPODDataStride(outMesh.sTangents) * inMesh.nNumVertex);
- }
- if(inMesh.sBinormals.n)
- {
- outMesh.sBinormals.eType = EPODDataFloat;
- outMesh.sBinormals.pData = (unsigned char*) realloc(outMesh.sBinormals.pData, PVRTModelPODDataStride(outMesh.sBinormals) * inMesh.nNumVertex);
- }
- if(inMesh.sBoneBatches.nBatchCnt)
- {
- unsigned int ui32BatchPaletteSize = 0;
- PVRTMATRIX *pPalette = 0;
- PVRTMATRIX *pPaletteInvTrans = 0;
- unsigned int ui32Offset = 0, ui32Strip = 0;
- bool *pbTransformed = 0;
- SafeAlloc(pPalette, sizeof(PVRTMATRIX) * inMesh.sBoneBatches.nBatchBoneMax);
- SafeAlloc(pPaletteInvTrans, sizeof(PVRTMATRIX) * inMesh.sBoneBatches.nBatchBoneMax);
- SafeAlloc(pbTransformed, sizeof(bool) * inMesh.nNumVertex);
- for(j = 0; j < (unsigned int) inMesh.sBoneBatches.nBatchCnt; ++j)
- {
- ui32BatchPaletteSize = (unsigned int) inMesh.sBoneBatches.pnBatchBoneCnt[j];
- for(k = 0; k < ui32BatchPaletteSize; ++k)
- {
- // Get the Node of the bone
- int i32NodeID = inMesh.sBoneBatches.pnBatches[j * inMesh.sBoneBatches.nBatchBoneMax + k];
- // Get the World transformation matrix for this bone
- in.GetBoneWorldMatrix(pPalette[k], inNode, in.pNode[i32NodeID]);
- // Get the inverse transpose of the 3x3
- if(inMesh.sNormals.n || inMesh.sTangents.n || inMesh.sBinormals.n)
- {
- pPaletteInvTrans[k] = pPalette[k];
- pPaletteInvTrans[k].f[3] = pPaletteInvTrans[k].f[7] = pPaletteInvTrans[k].f[11] = 0;
- pPaletteInvTrans[k].f[12] = pPaletteInvTrans[k].f[13] = pPaletteInvTrans[k].f[14] = 0;
- PVRTMatrixInverse(pPaletteInvTrans[k], pPaletteInvTrans[k]);
- PVRTMatrixTranspose(pPaletteInvTrans[k], pPaletteInvTrans[k]);
- }
- }
- // Calculate the number of triangles in the current batch
- unsigned int ui32Tris;
- if(j + 1 < (unsigned int) inMesh.sBoneBatches.nBatchCnt)
- ui32Tris = inMesh.sBoneBatches.pnBatchOffset[j + 1] - inMesh.sBoneBatches.pnBatchOffset[j];
- else
- ui32Tris = inMesh.nNumFaces - inMesh.sBoneBatches.pnBatchOffset[j];
- unsigned int idx;
- float fBoneIdx[4], fBoneWeights[4];
- if(inMesh.nNumStrips == 0)
- {
- ui32Offset = 3 * inMesh.sBoneBatches.pnBatchOffset[j];
- for(l = ui32Offset; l < ui32Offset + (ui32Tris * 3); ++l)
- {
- if(inMesh.sFaces.pData) // Indexed Triangle Lists
- PVRTVertexRead(&idx, inMesh.sFaces.pData + (l * inMesh.sFaces.nStride), inMesh.sFaces.eType);
- else // Indexed Triangle Lists
- idx = l;
- if(!pbTransformed[idx])
- {
- PVRTVertexRead((PVRTVECTOR4f*) &fBoneIdx[0], inMesh.sBoneIdx.pData + (idx * inMesh.sBoneIdx.nStride), inMesh.sBoneIdx.eType, inMesh.sBoneIdx.n);
- PVRTVertexRead((PVRTVECTOR4f*) &fBoneWeights[0], inMesh.sBoneWeight.pData + (idx * inMesh.sBoneWeight.nStride), inMesh.sBoneWeight.eType, inMesh.sBoneWeight.n);
- TransformCPODData(inMesh.sVertex, outMesh.sVertex, idx, pPalette, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, false);
- TransformCPODData(inMesh.sNormals, outMesh.sNormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- TransformCPODData(inMesh.sTangents, outMesh.sTangents, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- pbTransformed[idx] = true;
- }
- }
- }
- else
- {
- unsigned int ui32TrisDrawn = 0;
- while(ui32TrisDrawn < ui32Tris)
- {
- for(l = ui32Offset; l < ui32Offset + (inMesh.pnStripLength[ui32Strip]+2); ++l)
- {
- if(inMesh.sFaces.pData) // Indexed Triangle Strips
- PVRTVertexRead(&idx, inMesh.sFaces.pData + (l * inMesh.sFaces.nStride), inMesh.sFaces.eType);
- else // Triangle Strips
- idx = l;
- if(!pbTransformed[idx])
- {
- PVRTVertexRead((PVRTVECTOR4f*) &fBoneIdx[0], inMesh.sBoneIdx.pData + (idx * inMesh.sBoneIdx.nStride), inMesh.sBoneIdx.eType, inMesh.sBoneIdx.n);
- PVRTVertexRead((PVRTVECTOR4f*) &fBoneWeights[0], inMesh.sBoneWeight.pData + (idx * inMesh.sBoneWeight.nStride), inMesh.sBoneWeight.eType, inMesh.sBoneWeight.n);
- TransformCPODData(inMesh.sVertex, outMesh.sVertex, idx, pPalette, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, false);
- TransformCPODData(inMesh.sNormals, outMesh.sNormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- TransformCPODData(inMesh.sTangents, outMesh.sTangents, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
- pbTransformed[idx] = true;
- }
- }
- ui32Offset += inMesh.pnStripLength[ui32Strip] + 2;
- ui32TrisDrawn += inMesh.pnStripLength[ui32Strip];
- ++ui32Strip;
- }
- }
- }
- FREE(pPalette);
- FREE(pPaletteInvTrans);
- FREE(pbTransformed);
- }
- else
- {
- // Get transformation matrix
- in.GetWorldMatrix(mWorld, inNode);
- PVRTMATRIX mWorldInvTrans;
- // Get the inverse transpose of the 3x3
- if(inMesh.sNormals.n || inMesh.sTangents.n || inMesh.sBinormals.n)
- {
- mWorldInvTrans = mWorld;
- mWorldInvTrans.f[3] = mWorldInvTrans.f[7] = mWorldInvTrans.f[11] = 0;
- mWorldInvTrans.f[12] = mWorldInvTrans.f[13] = mWorldInvTrans.f[14] = 0;
- PVRTMatrixInverse(mWorldInvTrans, mWorldInvTrans);
- PVRTMatrixTranspose(mWorldInvTrans, mWorldInvTrans);
- }
- // Transform the vertices
- for(j = 0; j < inMesh.nNumVertex; ++j)
- {
- TransformCPODData(inMesh.sVertex, outMesh.sVertex, j, &mWorld, 0, 0, 0, false);
- TransformCPODData(inMesh.sNormals, outMesh.sNormals, j, &mWorldInvTrans, 0, 0, 0, true);
- TransformCPODData(inMesh.sTangents, outMesh.sTangents, j, &mWorldInvTrans, 0, 0, 0, true);
- TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, j, &mWorldInvTrans, 0, 0, 0, true);
- }
- }
- }
- // Copy the rest of the nodes
- for(i = in.nNumMeshNode; i < in.nNumNode; ++i)
- {
- PVRTModelPODCopyNode(in.pNode[i], out.pNode[i], in.nNumFrame);
- // Strip out animation and parenting
- out.pNode[i].nIdxParent = -1;
- out.pNode[i].nAnimFlags = 0;
- FREE(out.pNode[i].pfAnimMatrix);
- FREE(out.pNode[i].pnAnimMatrixIdx);
- FREE(out.pNode[i].pfAnimPosition);
- FREE(out.pNode[i].pnAnimPositionIdx);
- FREE(out.pNode[i].pfAnimRotation);
- FREE(out.pNode[i].pnAnimRotationIdx);
- FREE(out.pNode[i].pfAnimScale);
- FREE(out.pNode[i].pnAnimScaleIdx);
- // Get world transformation matrix....
- in.GetWorldMatrix(mWorld, in.pNode[i]);
- // ...set the out node transformation matrix
- if(SafeAlloc(out.pNode[i].pfAnimMatrix, sizeof(PVRTMATRIX)))
- memcpy(out.pNode[i].pfAnimMatrix, mWorld.f, sizeof(PVRTMATRIX));
- }
- // Copy camera, lights
- if(in.nNumCamera && SafeAlloc(out.pCamera, sizeof(SPODCamera) * in.nNumCamera))
- {
- out.nNumCamera = in.nNumCamera;
- for(i = 0; i < in.nNumCamera; ++i)
- PVRTModelPODCopyCamera(in.pCamera[i], out.pCamera[i], in.nNumFrame);
- }
- if(in.nNumLight && SafeAlloc(out.pLight, sizeof(SPODLight) * in.nNumLight))
- {
- out.nNumLight = in.nNumLight;
- for(i = 0; i < out.nNumLight; ++i)
- PVRTModelPODCopyLight(in.pLight[i], out.pLight[i]);
- }
- // Copy textures
- if(in.nNumTexture && SafeAlloc(out.pTexture, sizeof(SPODTexture) * in.nNumTexture))
- {
- out.nNumTexture = in.nNumTexture;
- for(i = 0; i < out.nNumTexture; ++i)
- PVRTModelPODCopyTexture(in.pTexture[i], out.pTexture[i]);
- }
- // Copy materials
- if(in.nNumMaterial && SafeAlloc(out.pMaterial, sizeof(SPODMaterial) * in.nNumMaterial))
- {
- out.nNumMaterial = in.nNumMaterial;
- for(i = 0; i < in.nNumMaterial; ++i)
- PVRTModelPODCopyMaterial(in.pMaterial[i], out.pMaterial[i]);
- }
- out.InitImpl();
- return PVR_SUCCESS;
- }
- /*****************************************************************************
- End of file (PVRTModelPOD.cpp)
- *****************************************************************************/
|