PVRTModelPOD.cpp 152 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456
  1. /******************************************************************************
  2. @File PVRTModelPOD.cpp
  3. @Title PVRTModelPOD
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description Code to load POD files - models exported from MAX.
  8. ******************************************************************************/
  9. #include <math.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "PVRTGlobal.h"
  14. #include "PVRTContext.h"
  15. #include "PVRTFixedPoint.h"
  16. #include "PVRTMatrix.h"
  17. #include "PVRTQuaternion.h"
  18. #include "PVRTVertex.h"
  19. #include "PVRTBoneBatch.h"
  20. #include "PVRTModelPOD.h"
  21. #include "PVRTMisc.h"
  22. #include "PVRTResourceFile.h"
  23. #include "PVRTTrans.h"
  24. /****************************************************************************
  25. ** Defines
  26. ****************************************************************************/
  27. #define PVRTMODELPOD_TAG_MASK (0x80000000)
  28. #define PVRTMODELPOD_TAG_START (0x00000000)
  29. #define PVRTMODELPOD_TAG_END (0x80000000)
  30. #define CFAH (1024)
  31. /****************************************************************************
  32. ** Enumerations
  33. ****************************************************************************/
  34. /*!****************************************************************************
  35. @Struct EPODFileName
  36. @Brief Enum for the binary pod blocks
  37. ******************************************************************************/
  38. enum EPODFileName
  39. {
  40. ePODFileVersion = 1000,
  41. ePODFileScene,
  42. ePODFileExpOpt,
  43. ePODFileHistory,
  44. ePODFileEndiannessMisMatch = -402456576,
  45. ePODFileColourBackground = 2000,
  46. ePODFileColourAmbient,
  47. ePODFileNumCamera,
  48. ePODFileNumLight,
  49. ePODFileNumMesh,
  50. ePODFileNumNode,
  51. ePODFileNumMeshNode,
  52. ePODFileNumTexture,
  53. ePODFileNumMaterial,
  54. ePODFileNumFrame,
  55. ePODFileCamera, // Will come multiple times
  56. ePODFileLight, // Will come multiple times
  57. ePODFileMesh, // Will come multiple times
  58. ePODFileNode, // Will come multiple times
  59. ePODFileTexture, // Will come multiple times
  60. ePODFileMaterial, // Will come multiple times
  61. ePODFileFlags,
  62. ePODFileFPS,
  63. ePODFileMatName = 3000,
  64. ePODFileMatIdxTexDiffuse,
  65. ePODFileMatOpacity,
  66. ePODFileMatAmbient,
  67. ePODFileMatDiffuse,
  68. ePODFileMatSpecular,
  69. ePODFileMatShininess,
  70. ePODFileMatEffectFile,
  71. ePODFileMatEffectName,
  72. ePODFileMatIdxTexAmbient,
  73. ePODFileMatIdxTexSpecularColour,
  74. ePODFileMatIdxTexSpecularLevel,
  75. ePODFileMatIdxTexBump,
  76. ePODFileMatIdxTexEmissive,
  77. ePODFileMatIdxTexGlossiness,
  78. ePODFileMatIdxTexOpacity,
  79. ePODFileMatIdxTexReflection,
  80. ePODFileMatIdxTexRefraction,
  81. ePODFileMatBlendSrcRGB,
  82. ePODFileMatBlendSrcA,
  83. ePODFileMatBlendDstRGB,
  84. ePODFileMatBlendDstA,
  85. ePODFileMatBlendOpRGB,
  86. ePODFileMatBlendOpA,
  87. ePODFileMatBlendColour,
  88. ePODFileMatBlendFactor,
  89. ePODFileMatFlags,
  90. ePODFileTexName = 4000,
  91. ePODFileNodeIdx = 5000,
  92. ePODFileNodeName,
  93. ePODFileNodeIdxMat,
  94. ePODFileNodeIdxParent,
  95. ePODFileNodePos,
  96. ePODFileNodeRot,
  97. ePODFileNodeScale,
  98. ePODFileNodeAnimPos,
  99. ePODFileNodeAnimRot,
  100. ePODFileNodeAnimScale,
  101. ePODFileNodeMatrix,
  102. ePODFileNodeAnimMatrix,
  103. ePODFileNodeAnimFlags,
  104. ePODFileNodeAnimPosIdx,
  105. ePODFileNodeAnimRotIdx,
  106. ePODFileNodeAnimScaleIdx,
  107. ePODFileNodeAnimMatrixIdx,
  108. ePODFileMeshNumVtx = 6000,
  109. ePODFileMeshNumFaces,
  110. ePODFileMeshNumUVW,
  111. ePODFileMeshFaces,
  112. ePODFileMeshStripLength,
  113. ePODFileMeshNumStrips,
  114. ePODFileMeshVtx,
  115. ePODFileMeshNor,
  116. ePODFileMeshTan,
  117. ePODFileMeshBin,
  118. ePODFileMeshUVW, // Will come multiple times
  119. ePODFileMeshVtxCol,
  120. ePODFileMeshBoneIdx,
  121. ePODFileMeshBoneWeight,
  122. ePODFileMeshInterleaved,
  123. ePODFileMeshBoneBatches,
  124. ePODFileMeshBoneBatchBoneCnts,
  125. ePODFileMeshBoneBatchOffsets,
  126. ePODFileMeshBoneBatchBoneMax,
  127. ePODFileMeshBoneBatchCnt,
  128. ePODFileMeshUnpackMatrix,
  129. ePODFileLightIdxTgt = 7000,
  130. ePODFileLightColour,
  131. ePODFileLightType,
  132. ePODFileLightConstantAttenuation,
  133. ePODFileLightLinearAttenuation,
  134. ePODFileLightQuadraticAttenuation,
  135. ePODFileLightFalloffAngle,
  136. ePODFileLightFalloffExponent,
  137. ePODFileCamIdxTgt = 8000,
  138. ePODFileCamFOV,
  139. ePODFileCamFar,
  140. ePODFileCamNear,
  141. ePODFileCamAnimFOV,
  142. ePODFileDataType = 9000,
  143. ePODFileN,
  144. ePODFileStride,
  145. ePODFileData
  146. };
  147. /****************************************************************************
  148. ** Structures
  149. ****************************************************************************/
  150. struct SPVRTPODImpl
  151. {
  152. VERTTYPE fFrame; /*!< Frame number */
  153. VERTTYPE fBlend; /*!< Frame blend (AKA fractional part of animation frame number) */
  154. int nFrame; /*!< Frame number (AKA integer part of animation frame number) */
  155. VERTTYPE *pfCache; /*!< Cache indicating the frames at which the matrix cache was filled */
  156. PVRTMATRIX *pWmCache; /*!< Cache of world matrices */
  157. PVRTMATRIX *pWmZeroCache; /*!< Pre-calculated frame 0 matrices */
  158. bool bFromMemory; /*!< Was the mesh data loaded from memory? */
  159. #ifdef _DEBUG
  160. PVRTint64 nWmTotal, nWmCacheHit, nWmZeroCacheHit;
  161. float fHitPerc, fHitPercZero;
  162. #endif
  163. };
  164. /****************************************************************************
  165. ** Local code: Memory allocation
  166. ****************************************************************************/
  167. /*!***************************************************************************
  168. @Function SafeAlloc
  169. @Input cnt
  170. @Output ptr
  171. @Return false if memory allocation failed
  172. @Description Allocates a block of memory.
  173. *****************************************************************************/
  174. template <typename T>
  175. bool SafeAlloc(T* &ptr, size_t cnt)
  176. {
  177. _ASSERT(!ptr);
  178. if(cnt)
  179. {
  180. ptr = (T*)calloc(cnt, sizeof(T));
  181. _ASSERT(ptr);
  182. if(!ptr)
  183. return false;
  184. }
  185. return true;
  186. }
  187. #ifdef _UITRON_
  188. template bool SafeAlloc<unsigned int>(unsigned int*&,size_t);
  189. template bool SafeAlloc<SPODTexture>(SPODTexture*&,size_t);
  190. template bool SafeAlloc<SPODLight>(SPODLight*&,size_t);
  191. template bool SafeAlloc<SPODNode>(SPODNode*&,size_t);
  192. template bool SafeAlloc<unsigned char>(unsigned char*&,size_t);
  193. template bool SafeAlloc<int>(int*&,size_t);
  194. template bool SafeAlloc<float>(float*&,size_t);
  195. template bool SafeAlloc<CPODData>(CPODData*&,size_t);
  196. template bool SafeAlloc<char>(char*&,size_t);
  197. template bool SafeAlloc<SPODCamera>(SPODCamera*&,size_t);
  198. template bool SafeAlloc<SPODMesh>(SPODMesh*&,size_t);
  199. template bool SafeAlloc<SPODMaterial>(SPODMaterial*&,size_t);
  200. template bool SafeAlloc<PVRTMATRIX>(PVRTMATRIX*&,size_t);
  201. template bool SafeAlloc<bool>(bool*&,size_t);
  202. template bool SafeAlloc<unsigned short>(unsigned short*&,size_t);
  203. #endif
  204. /*!***************************************************************************
  205. @Function SafeRealloc
  206. @Modified ptr
  207. @Input cnt
  208. @Description Changes the size of a memory allocation.
  209. *****************************************************************************/
  210. template <typename T>
  211. void SafeRealloc(T* &ptr, size_t cnt)
  212. {
  213. ptr = (T*)realloc(ptr, cnt * sizeof(T));
  214. _ASSERT(ptr);
  215. }
  216. #ifdef _UITRON_
  217. template void SafeRealloc<unsigned char>(unsigned char*&,size_t);
  218. #endif
  219. /****************************************************************************
  220. ** Class: CPODData
  221. ****************************************************************************/
  222. /*!***************************************************************************
  223. @Function Reset
  224. @Description Resets the POD Data to NULL
  225. *****************************************************************************/
  226. void CPODData::Reset()
  227. {
  228. eType = EPODDataFloat;
  229. n = 0;
  230. nStride = 0;
  231. FREE(pData);
  232. }
  233. // check32BitType and check16BitType are structs where only the specialisations have a standard declaration (complete type)
  234. // if this struct is instantiated with a different type then the compiler will choke on it
  235. // Place a line like: " check32BitType<channelType>(); " in a template function
  236. // to ensure it won't be called using a type of the wrong size.
  237. template<class T> struct check32BitType;
  238. template<> struct check32BitType<unsigned int> {};
  239. template<> struct check32BitType<int> {};
  240. template<> struct check32BitType<float> {};
  241. template<class T> struct check16BitType;
  242. template<> struct check16BitType<unsigned short> {};
  243. template<> struct check16BitType<short> {};
  244. /*!***************************************************************************
  245. Class: CSource
  246. *****************************************************************************/
  247. class CSource
  248. {
  249. public:
  250. /*!***************************************************************************
  251. @Function ~CSource
  252. @Description Destructor
  253. *****************************************************************************/
  254. virtual ~CSource() {};
  255. virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead) = 0;
  256. virtual bool Skip(const unsigned int nBytes) = 0;
  257. template <typename T>
  258. bool Read(T &n)
  259. {
  260. return Read(&n, sizeof(T));
  261. }
  262. template <typename T>
  263. bool Read32(T &n)
  264. {
  265. unsigned char ub[4];
  266. if(Read(&ub, 4))
  267. {
  268. unsigned int *pn = (unsigned int*) &n;
  269. *pn = (unsigned int) ((ub[3] << 24) | (ub[2] << 16) | (ub[1] << 8) | ub[0]);
  270. return true;
  271. }
  272. return false;
  273. }
  274. template <typename T>
  275. bool Read16(T &n)
  276. {
  277. unsigned char ub[2];
  278. if(Read(&ub, 2))
  279. {
  280. unsigned short *pn = (unsigned short*) &n;
  281. *pn = (unsigned short) ((ub[1] << 8) | ub[0]);
  282. return true;
  283. }
  284. return false;
  285. }
  286. bool ReadMarker(unsigned int &nName, unsigned int &nLen);
  287. template <typename T>
  288. bool ReadAfterAlloc(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
  289. {
  290. if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead))
  291. return false;
  292. return Read(lpBuffer, dwNumberOfBytesToRead);
  293. }
  294. template <typename T>
  295. bool ReadAfterAlloc32(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
  296. {
  297. check32BitType<T>();
  298. if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead/4))
  299. return false;
  300. return ReadArray32((unsigned int*) lpBuffer, dwNumberOfBytesToRead / 4);
  301. }
  302. bool ReadArray32(unsigned int *pn, unsigned int i32Size)
  303. {
  304. bool bRet = true;
  305. for(unsigned int i = 0; i < i32Size; ++i)
  306. bRet &= Read32(pn[i]);
  307. return bRet;
  308. }
  309. template <typename T>
  310. bool ReadAfterAlloc16(T* &lpBuffer, const unsigned int dwNumberOfBytesToRead)
  311. {
  312. check16BitType<T>();
  313. if(!SafeAlloc(lpBuffer, dwNumberOfBytesToRead/2 ))
  314. return false;
  315. return ReadArray16((unsigned short*) lpBuffer, dwNumberOfBytesToRead / 2);
  316. }
  317. bool ReadArray16(unsigned short* pn, unsigned int i32Size)
  318. {
  319. bool bRet = true;
  320. for(unsigned int i = 0; i < i32Size; ++i)
  321. bRet &= Read16(pn[i]);
  322. return bRet;
  323. }
  324. };
  325. bool CSource::ReadMarker(unsigned int &nName, unsigned int &nLen)
  326. {
  327. if(!Read32(nName))
  328. return false;
  329. if(!Read32(nLen))
  330. return false;
  331. return true;
  332. }
  333. /*!***************************************************************************
  334. Class: CSourceStream
  335. *****************************************************************************/
  336. class CSourceStream : public CSource
  337. {
  338. protected:
  339. CPVRTResourceFile* m_pFile;
  340. size_t m_BytesReadCount;
  341. public:
  342. /*!***************************************************************************
  343. @Function CSourceStream
  344. @Description Constructor
  345. *****************************************************************************/
  346. CSourceStream() : m_pFile(0), m_BytesReadCount(0) {}
  347. /*!***************************************************************************
  348. @Function ~CSourceStream
  349. @Description Destructor
  350. *****************************************************************************/
  351. virtual ~CSourceStream();
  352. bool Init(const char * const pszFileName);
  353. bool Init(const char * const pData, const size_t i32Size);
  354. virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead);
  355. virtual bool Skip(const unsigned int nBytes);
  356. };
  357. /*!***************************************************************************
  358. @Function ~CSourceStream
  359. @Description Destructor
  360. *****************************************************************************/
  361. CSourceStream::~CSourceStream()
  362. {
  363. delete m_pFile;
  364. }
  365. /*!***************************************************************************
  366. @Function Init
  367. @Input pszFileName Source file
  368. @Description Initialises the source stream with a file at the specified
  369. directory.
  370. *****************************************************************************/
  371. bool CSourceStream::Init(const char * const pszFileName)
  372. {
  373. m_BytesReadCount = 0;
  374. if (m_pFile) delete m_pFile;
  375. m_pFile = new CPVRTResourceFile(pszFileName);
  376. if (!m_pFile->IsOpen())
  377. {
  378. delete m_pFile;
  379. m_pFile = 0;
  380. return false;
  381. }
  382. return true;
  383. }
  384. /*!***************************************************************************
  385. @Function Init
  386. @Input pData Address of the source data
  387. @Input i32Size Size of the data (in bytes)
  388. @Description Initialises the source stream with the data at the specified
  389. directory.
  390. *****************************************************************************/
  391. bool CSourceStream::Init(const char * pData, size_t i32Size)
  392. {
  393. m_BytesReadCount = 0;
  394. if (m_pFile) delete m_pFile;
  395. m_pFile = new CPVRTResourceFile(pData, i32Size);
  396. if (!m_pFile->IsOpen())
  397. {
  398. delete m_pFile;
  399. m_pFile = 0;
  400. return false;
  401. }
  402. return true;
  403. }
  404. /*!***************************************************************************
  405. @Function Read
  406. @Modified lpBuffer Buffer to write the data into
  407. @Input dwNumberOfBytesToRead Number of bytes to read
  408. @Description Reads specified number of bytes from the source stream
  409. into the output buffer.
  410. *****************************************************************************/
  411. bool CSourceStream::Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead)
  412. {
  413. _ASSERT(lpBuffer);
  414. _ASSERT(m_pFile);
  415. if (m_BytesReadCount + dwNumberOfBytesToRead > m_pFile->Size()) return false;
  416. memcpy(lpBuffer, &(m_pFile->StringPtr())[m_BytesReadCount], dwNumberOfBytesToRead);
  417. m_BytesReadCount += dwNumberOfBytesToRead;
  418. return true;
  419. }
  420. /*!***************************************************************************
  421. @Function Skip
  422. @Input nBytes The number of bytes to skip
  423. @Description Skips the specified number of bytes of the source stream.
  424. *****************************************************************************/
  425. bool CSourceStream::Skip(const unsigned int nBytes)
  426. {
  427. if (m_BytesReadCount + nBytes > m_pFile->Size()) return false;
  428. m_BytesReadCount += nBytes;
  429. return true;
  430. }
  431. #if defined(WIN32) && !defined(__BADA__)
  432. /*!***************************************************************************
  433. Class: CSourceResource
  434. *****************************************************************************/
  435. class CSourceResource : public CSource
  436. {
  437. protected:
  438. const unsigned char *m_pData;
  439. unsigned int m_nSize, m_nReadPos;
  440. public:
  441. bool Init(const TCHAR * const pszName);
  442. virtual bool Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead);
  443. virtual bool Skip(const unsigned int nBytes);
  444. };
  445. /*!***************************************************************************
  446. @Function Init
  447. @Input pszName The file extension of the resource file
  448. @Description Initialises the source resource from the data at the
  449. specified file extension.
  450. *****************************************************************************/
  451. bool CSourceResource::Init(const TCHAR * const pszName)
  452. {
  453. HRSRC hR;
  454. HGLOBAL hG;
  455. // Find the resource
  456. hR = FindResource(GetModuleHandle(NULL), pszName, RT_RCDATA);
  457. if(!hR)
  458. return false;
  459. // How big is the resource?
  460. m_nSize = SizeofResource(NULL, hR);
  461. if(!m_nSize)
  462. return false;
  463. // Get a pointer to the resource data
  464. hG = LoadResource(NULL, hR);
  465. if(!hG)
  466. return false;
  467. m_pData = (unsigned char*)LockResource(hG);
  468. if(!m_pData)
  469. return false;
  470. m_nReadPos = 0;
  471. return true;
  472. }
  473. /*!***************************************************************************
  474. @Function Read
  475. @Modified lpBuffer The buffer to write to
  476. @Input dwNumberOfBytesToRead The number of bytes to read
  477. @Description Reads data from the resource to the specified output buffer.
  478. *****************************************************************************/
  479. bool CSourceResource::Read(void* lpBuffer, const unsigned int dwNumberOfBytesToRead)
  480. {
  481. if(m_nReadPos + dwNumberOfBytesToRead > m_nSize)
  482. return false;
  483. _ASSERT(lpBuffer);
  484. memcpy(lpBuffer, &m_pData[m_nReadPos], dwNumberOfBytesToRead);
  485. m_nReadPos += dwNumberOfBytesToRead;
  486. return true;
  487. }
  488. bool CSourceResource::Skip(const unsigned int nBytes)
  489. {
  490. if(m_nReadPos + nBytes > m_nSize)
  491. return false;
  492. m_nReadPos += nBytes;
  493. return true;
  494. }
  495. #endif /* WIN32 */
  496. /****************************************************************************
  497. ** Local code: File writing
  498. ****************************************************************************/
  499. /*!***************************************************************************
  500. @Function WriteFileSafe
  501. @Input pFile
  502. @Input lpBuffer
  503. @Input nNumberOfBytesToWrite
  504. @Return true if successful
  505. @Description Writes data to a file, checking return codes.
  506. *****************************************************************************/
  507. static bool WriteFileSafe(FILE *pFile, const void * const lpBuffer, const unsigned int nNumberOfBytesToWrite)
  508. {
  509. if(nNumberOfBytesToWrite)
  510. {
  511. size_t count = fwrite(lpBuffer, nNumberOfBytesToWrite, 1, pFile);
  512. return count == 1;
  513. }
  514. return true;
  515. }
  516. static bool WriteFileSafe16(FILE *pFile, const unsigned short * const lpBuffer, const unsigned int nSize)
  517. {
  518. if(nSize)
  519. {
  520. unsigned char ub[2];
  521. bool bRet = true;
  522. for(unsigned int i = 0; i < nSize; ++i)
  523. {
  524. ub[0] = (unsigned char) lpBuffer[i];
  525. ub[1] = lpBuffer[i] >> 8;
  526. bRet &= (fwrite(ub, 2, 1, pFile) == 1);
  527. }
  528. return bRet;
  529. }
  530. return true;
  531. }
  532. static bool WriteFileSafe32(FILE *pFile, const unsigned int * const lpBuffer, const unsigned int nSize)
  533. {
  534. if(nSize)
  535. {
  536. unsigned char ub[4];
  537. bool bRet = true;
  538. for(unsigned int i = 0; i < nSize; ++i)
  539. {
  540. ub[0] = (unsigned char) (lpBuffer[i]);
  541. ub[1] = (unsigned char) (lpBuffer[i] >> 8);
  542. ub[2] = (unsigned char) (lpBuffer[i] >> 16);
  543. ub[3] = (unsigned char) (lpBuffer[i] >> 24);
  544. bRet &= (fwrite(ub, 4, 1, pFile) == 1);
  545. }
  546. return bRet;
  547. }
  548. return true;
  549. }
  550. /*!***************************************************************************
  551. @Function WriteMarker
  552. @Input pFile
  553. @Input nName
  554. @Input bEnd
  555. @Input nLen
  556. Return true if successful
  557. @Description Write a marker to a POD file. If bEnd if false, it's a
  558. beginning marker, otherwise it's an end marker.
  559. *****************************************************************************/
  560. static bool WriteMarker(
  561. FILE * const pFile,
  562. const unsigned int nName,
  563. const bool bEnd,
  564. const unsigned int nLen = 0)
  565. {
  566. unsigned int nMarker;
  567. bool bRet;
  568. _ASSERT((nName & ~PVRTMODELPOD_TAG_MASK) == nName);
  569. nMarker = nName | (bEnd ? PVRTMODELPOD_TAG_END : PVRTMODELPOD_TAG_START);
  570. bRet = WriteFileSafe32(pFile, &nMarker, 1);
  571. bRet &= WriteFileSafe32(pFile, &nLen, 1);
  572. return bRet;
  573. }
  574. /*!***************************************************************************
  575. @Function WriteData
  576. @Input pFile
  577. @Input nName
  578. @Input pData
  579. @Input nLen
  580. @Return true if successful
  581. @Description Write nLen bytes of data from pData, bracketed by an nName
  582. begin/end markers.
  583. *****************************************************************************/
  584. static bool WriteData(
  585. FILE * const pFile,
  586. const unsigned int nName,
  587. const void * const pData,
  588. const unsigned int nLen)
  589. {
  590. if(pData)
  591. {
  592. _ASSERT(nLen);
  593. if(!WriteMarker(pFile, nName, false, nLen)) return false;
  594. if(!WriteFileSafe(pFile, pData, nLen)) return false;
  595. if(!WriteMarker(pFile, nName, true)) return false;
  596. }
  597. return true;
  598. }
  599. /*!***************************************************************************
  600. @Function WriteData16
  601. @Input pFile
  602. @Input nName
  603. @Input pData
  604. @Input i32Size
  605. @Return true if successful
  606. @Description Write i32Size no. of unsigned shorts from pData, bracketed by
  607. an nName begin/end markers.
  608. *****************************************************************************/
  609. template <typename T>
  610. static bool WriteData16(
  611. FILE * const pFile,
  612. const unsigned int nName,
  613. const T * const pData,
  614. int i32Size = 1)
  615. {
  616. if(pData)
  617. {
  618. if(!WriteMarker(pFile, nName, false, 2 * i32Size)) return false;
  619. if(!WriteFileSafe16(pFile, (unsigned short*) pData, i32Size)) return false;
  620. if(!WriteMarker(pFile, nName, true)) return false;
  621. }
  622. return true;
  623. }
  624. /*!***************************************************************************
  625. @Function WriteData32
  626. @Input pFile
  627. @Input nName
  628. @Input pData
  629. @Input i32Size
  630. @Return true if successful
  631. @Description Write i32Size no. of unsigned ints from pData, bracketed by
  632. an nName begin/end markers.
  633. *****************************************************************************/
  634. template <typename T>
  635. static bool WriteData32(
  636. FILE * const pFile,
  637. const unsigned int nName,
  638. const T * const pData,
  639. int i32Size = 1)
  640. {
  641. if(pData)
  642. {
  643. if(!WriteMarker(pFile, nName, false, 4 * i32Size)) return false;
  644. if(!WriteFileSafe32(pFile, (unsigned int*) pData, i32Size)) return false;
  645. if(!WriteMarker(pFile, nName, true)) return false;
  646. }
  647. return true;
  648. }
  649. /*!***************************************************************************
  650. @Function WriteData
  651. @Input pFile
  652. @Input nName
  653. @Input n
  654. @Return true if successful
  655. @Description Write the value n, bracketed by an nName begin/end markers.
  656. *****************************************************************************/
  657. template <typename T>
  658. static bool WriteData(
  659. FILE * const pFile,
  660. const unsigned int nName,
  661. const T &n)
  662. {
  663. unsigned int nSize = sizeof(T);
  664. bool bRet = WriteData(pFile, nName, (void*)&n, nSize);
  665. return bRet;
  666. }
  667. /*!***************************************************************************
  668. @Function WriteCPODData
  669. @Input pFile
  670. @Input nName
  671. @Input n
  672. @Input nEntries
  673. @Input bValidData
  674. @Return true if successful
  675. @Description Write the value n, bracketed by an nName begin/end markers.
  676. *****************************************************************************/
  677. static bool WriteCPODData(
  678. FILE * const pFile,
  679. const unsigned int nName,
  680. const CPODData &n,
  681. const unsigned int nEntries,
  682. const bool bValidData)
  683. {
  684. if(!WriteMarker(pFile, nName, false)) return false;
  685. if(!WriteData32(pFile, ePODFileDataType, &n.eType)) return false;
  686. if(!WriteData32(pFile, ePODFileN, &n.n)) return false;
  687. if(!WriteData32(pFile, ePODFileStride, &n.nStride)) return false;
  688. if(bValidData)
  689. {
  690. switch(PVRTModelPODDataTypeSize(n.eType))
  691. {
  692. case 1: if(!WriteData(pFile, ePODFileData, n.pData, nEntries * n.nStride)) return false; break;
  693. case 2: if(!WriteData16(pFile, ePODFileData, n.pData, nEntries * (n.nStride / 2))) return false; break;
  694. case 4: if(!WriteData32(pFile, ePODFileData, n.pData, nEntries * (n.nStride / 4))) return false; break;
  695. default: { _ASSERT(false); }
  696. };
  697. }
  698. else
  699. {
  700. unsigned int offset = (unsigned int) (size_t) n.pData;
  701. if(!WriteData32(pFile, ePODFileData, &offset)) return false;
  702. }
  703. if(!WriteMarker(pFile, nName, true)) return false;
  704. return true;
  705. }
  706. /*!***************************************************************************
  707. @Function WriteInterleaved
  708. @Input pFile
  709. @Input mesh
  710. @Return true if successful
  711. @Description Write out the interleaved data to file.
  712. *****************************************************************************/
  713. static bool WriteInterleaved(FILE * const pFile, SPODMesh &mesh)
  714. {
  715. if(!mesh.pInterleaved)
  716. return true;
  717. unsigned int i;
  718. unsigned int ui32CPODDataSize = 0;
  719. CPODData **pCPODData = new CPODData*[7 + mesh.nNumUVW];
  720. if(mesh.sVertex.n) pCPODData[ui32CPODDataSize++] = &mesh.sVertex;
  721. if(mesh.sNormals.n) pCPODData[ui32CPODDataSize++] = &mesh.sNormals;
  722. if(mesh.sTangents.n) pCPODData[ui32CPODDataSize++] = &mesh.sTangents;
  723. if(mesh.sBinormals.n) pCPODData[ui32CPODDataSize++] = &mesh.sBinormals;
  724. if(mesh.sVtxColours.n) pCPODData[ui32CPODDataSize++] = &mesh.sVtxColours;
  725. if(mesh.sBoneIdx.n) pCPODData[ui32CPODDataSize++] = &mesh.sBoneIdx;
  726. if(mesh.sBoneWeight.n) pCPODData[ui32CPODDataSize++] = &mesh.sBoneWeight;
  727. for(i = 0; i < mesh.nNumUVW; ++i)
  728. if(mesh.psUVW[i].n) pCPODData[ui32CPODDataSize++] = &mesh.psUVW[i];
  729. // Bubble sort pCPODData based on the vertex element offsets
  730. bool bSwap = true;
  731. unsigned int ui32Size = ui32CPODDataSize;
  732. while(bSwap)
  733. {
  734. bSwap = false;
  735. for(i = 0; i < ui32Size - 1; ++i)
  736. {
  737. if(pCPODData[i]->pData > pCPODData[i + 1]->pData)
  738. {
  739. PVRTswap(pCPODData[i], pCPODData[i + 1]);
  740. bSwap = true;
  741. }
  742. }
  743. --ui32Size;
  744. }
  745. // Do we need padding? If so how much? We calc this by comparing the actual stride with the one stored
  746. unsigned int ui32ActualStride = 0;
  747. for(i = 0; i < ui32CPODDataSize; ++i)
  748. ui32ActualStride += (unsigned int) PVRTModelPODDataStride(*pCPODData[i]);
  749. unsigned int ui32Pad = mesh.sVertex.nStride - ui32ActualStride;
  750. // Write out the data
  751. if(!WriteMarker(pFile, ePODFileMeshInterleaved, false, mesh.nNumVertex * mesh.sVertex.nStride)) return false;
  752. for(i = 0; i < mesh.nNumVertex; ++i)
  753. {
  754. unsigned char* pVtxStart = mesh.pInterleaved + (i * mesh.sVertex.nStride);
  755. for(unsigned int j = 0; j < ui32CPODDataSize; ++j)
  756. {
  757. unsigned char* pData = pVtxStart + (size_t) pCPODData[j]->pData;
  758. switch(PVRTModelPODDataTypeSize(pCPODData[j]->eType))
  759. {
  760. case 1: if(!WriteFileSafe(pFile, pData, pCPODData[j]->n)) return false; break;
  761. case 2: if(!WriteFileSafe16(pFile, (unsigned short*) pData, pCPODData[j]->n)) return false; break;
  762. case 4: if(!WriteFileSafe32(pFile, (unsigned int*) pData, pCPODData[j]->n)) return false; break;
  763. default: { _ASSERT(false); }
  764. };
  765. }
  766. // Write out the padding
  767. fwrite("\0\0\0\0", ui32Pad, 1, pFile);
  768. }
  769. if(!WriteMarker(pFile, ePODFileMeshInterleaved, true)) return false;
  770. // Tidy up
  771. delete[] pCPODData;
  772. return true;
  773. }
  774. /*!***************************************************************************
  775. @Function PVRTModelPODGetAnimArraySize
  776. @Input pAnimDataIdx
  777. @Input ui32Frames
  778. @Input ui32Components
  779. @Return Size of the animation array
  780. @Description Calculates the size of an animation array
  781. *****************************************************************************/
  782. unsigned int PVRTModelPODGetAnimArraySize(unsigned int *pAnimDataIdx, unsigned int ui32Frames, unsigned int ui32Components)
  783. {
  784. if(pAnimDataIdx)
  785. {
  786. // Find the largest index value
  787. unsigned int ui32Max = 0;
  788. for(unsigned int i = 0; i < ui32Frames; ++i)
  789. {
  790. if(ui32Max < pAnimDataIdx[i])
  791. ui32Max = pAnimDataIdx[i];
  792. }
  793. return ui32Max + ui32Components;
  794. }
  795. return ui32Frames * ui32Components;
  796. }
  797. /*!***************************************************************************
  798. @Function WritePOD
  799. @Output The file referenced by pFile
  800. @Input s The POD Scene to write
  801. @Input pszExpOpt Exporter options
  802. @Return true if successful
  803. @Description Write a POD file
  804. *****************************************************************************/
  805. static bool WritePOD(
  806. FILE * const pFile,
  807. const char * const pszExpOpt,
  808. const char * const pszHistory,
  809. const SPODScene &s)
  810. {
  811. unsigned int i, j;
  812. // Save: file version
  813. {
  814. char *pszVersion = (char*)PVRTMODELPOD_VERSION;
  815. if(!WriteData(pFile, ePODFileVersion, pszVersion, (unsigned int)strlen(pszVersion) + 1)) return false;
  816. }
  817. // Save: exporter options
  818. if(pszExpOpt && *pszExpOpt)
  819. {
  820. if(!WriteData(pFile, ePODFileExpOpt, pszExpOpt, (unsigned int)strlen(pszExpOpt) + 1)) return false;
  821. }
  822. // Save: .pod file history
  823. if(pszHistory && *pszHistory)
  824. {
  825. if(!WriteData(pFile, ePODFileHistory, pszHistory, (unsigned int)strlen(pszHistory) + 1)) return false;
  826. }
  827. // Save: scene descriptor
  828. if(!WriteMarker(pFile, ePODFileScene, false)) return false;
  829. {
  830. if(!WriteData32(pFile, ePODFileColourBackground, s.pfColourBackground, sizeof(s.pfColourBackground) / sizeof(*s.pfColourBackground))) return false;
  831. if(!WriteData32(pFile, ePODFileColourAmbient, s.pfColourAmbient, sizeof(s.pfColourAmbient) / sizeof(*s.pfColourAmbient))) return false;
  832. if(!WriteData32(pFile, ePODFileNumCamera, &s.nNumCamera)) return false;
  833. if(!WriteData32(pFile, ePODFileNumLight, &s.nNumLight)) return false;
  834. if(!WriteData32(pFile, ePODFileNumMesh, &s.nNumMesh)) return false;
  835. if(!WriteData32(pFile, ePODFileNumNode, &s.nNumNode)) return false;
  836. if(!WriteData32(pFile, ePODFileNumMeshNode, &s.nNumMeshNode)) return false;
  837. if(!WriteData32(pFile, ePODFileNumTexture, &s.nNumTexture)) return false;
  838. if(!WriteData32(pFile, ePODFileNumMaterial, &s.nNumMaterial)) return false;
  839. if(!WriteData32(pFile, ePODFileNumFrame, &s.nNumFrame)) return false;
  840. if(!WriteData32(pFile, ePODFileFPS, &s.nFPS)) return false;
  841. if(!WriteData32(pFile, ePODFileFlags, &s.nFlags)) return false;
  842. // Save: cameras
  843. for(i = 0; i < s.nNumCamera; ++i)
  844. {
  845. if(!WriteMarker(pFile, ePODFileCamera, false)) return false;
  846. if(!WriteData32(pFile, ePODFileCamIdxTgt, &s.pCamera[i].nIdxTarget)) return false;
  847. if(!WriteData32(pFile, ePODFileCamFOV, &s.pCamera[i].fFOV)) return false;
  848. if(!WriteData32(pFile, ePODFileCamFar, &s.pCamera[i].fFar)) return false;
  849. if(!WriteData32(pFile, ePODFileCamNear, &s.pCamera[i].fNear)) return false;
  850. if(!WriteData32(pFile, ePODFileCamAnimFOV, s.pCamera[i].pfAnimFOV, s.nNumFrame)) return false;
  851. if(!WriteMarker(pFile, ePODFileCamera, true)) return false;
  852. }
  853. // Save: lights
  854. for(i = 0; i < s.nNumLight; ++i)
  855. {
  856. if(!WriteMarker(pFile, ePODFileLight, false)) return false;
  857. if(!WriteData32(pFile, ePODFileLightIdxTgt, &s.pLight[i].nIdxTarget)) return false;
  858. if(!WriteData32(pFile, ePODFileLightColour, s.pLight[i].pfColour, sizeof(s.pLight[i].pfColour) / sizeof(*s.pLight[i].pfColour))) return false;
  859. if(!WriteData32(pFile, ePODFileLightType, &s.pLight[i].eType)) return false;
  860. if(s.pLight[i].eType != ePODDirectional)
  861. {
  862. if(!WriteData32(pFile, ePODFileLightConstantAttenuation, &s.pLight[i].fConstantAttenuation)) return false;
  863. if(!WriteData32(pFile, ePODFileLightLinearAttenuation, &s.pLight[i].fLinearAttenuation)) return false;
  864. if(!WriteData32(pFile, ePODFileLightQuadraticAttenuation, &s.pLight[i].fQuadraticAttenuation)) return false;
  865. }
  866. if(s.pLight[i].eType == ePODSpot)
  867. {
  868. if(!WriteData32(pFile, ePODFileLightFalloffAngle, &s.pLight[i].fFalloffAngle)) return false;
  869. if(!WriteData32(pFile, ePODFileLightFalloffExponent, &s.pLight[i].fFalloffExponent)) return false;
  870. }
  871. if(!WriteMarker(pFile, ePODFileLight, true)) return false;
  872. }
  873. // Save: materials
  874. for(i = 0; i < s.nNumMaterial; ++i)
  875. {
  876. if(!WriteMarker(pFile, ePODFileMaterial, false)) return false;
  877. if(!WriteData32(pFile, ePODFileMatFlags, &s.pMaterial[i].nFlags)) return false;
  878. if(!WriteData(pFile, ePODFileMatName, s.pMaterial[i].pszName, (unsigned int)strlen(s.pMaterial[i].pszName)+1)) return false;
  879. if(!WriteData32(pFile, ePODFileMatIdxTexDiffuse, &s.pMaterial[i].nIdxTexDiffuse)) return false;
  880. if(!WriteData32(pFile, ePODFileMatIdxTexAmbient, &s.pMaterial[i].nIdxTexAmbient)) return false;
  881. if(!WriteData32(pFile, ePODFileMatIdxTexSpecularColour, &s.pMaterial[i].nIdxTexSpecularColour)) return false;
  882. if(!WriteData32(pFile, ePODFileMatIdxTexSpecularLevel, &s.pMaterial[i].nIdxTexSpecularLevel)) return false;
  883. if(!WriteData32(pFile, ePODFileMatIdxTexBump, &s.pMaterial[i].nIdxTexBump)) return false;
  884. if(!WriteData32(pFile, ePODFileMatIdxTexEmissive, &s.pMaterial[i].nIdxTexEmissive)) return false;
  885. if(!WriteData32(pFile, ePODFileMatIdxTexGlossiness, &s.pMaterial[i].nIdxTexGlossiness)) return false;
  886. if(!WriteData32(pFile, ePODFileMatIdxTexOpacity, &s.pMaterial[i].nIdxTexOpacity)) return false;
  887. if(!WriteData32(pFile, ePODFileMatIdxTexReflection, &s.pMaterial[i].nIdxTexReflection)) return false;
  888. if(!WriteData32(pFile, ePODFileMatIdxTexRefraction, &s.pMaterial[i].nIdxTexRefraction)) return false;
  889. if(!WriteData32(pFile, ePODFileMatOpacity, &s.pMaterial[i].fMatOpacity)) return false;
  890. if(!WriteData32(pFile, ePODFileMatAmbient, s.pMaterial[i].pfMatAmbient, sizeof(s.pMaterial[i].pfMatAmbient) / sizeof(*s.pMaterial[i].pfMatAmbient))) return false;
  891. if(!WriteData32(pFile, ePODFileMatDiffuse, s.pMaterial[i].pfMatDiffuse, sizeof(s.pMaterial[i].pfMatDiffuse) / sizeof(*s.pMaterial[i].pfMatDiffuse))) return false;
  892. if(!WriteData32(pFile, ePODFileMatSpecular, s.pMaterial[i].pfMatSpecular, sizeof(s.pMaterial[i].pfMatSpecular) / sizeof(*s.pMaterial[i].pfMatSpecular))) return false;
  893. if(!WriteData32(pFile, ePODFileMatShininess, &s.pMaterial[i].fMatShininess)) return false;
  894. if(!WriteData(pFile, ePODFileMatEffectFile, s.pMaterial[i].pszEffectFile, s.pMaterial[i].pszEffectFile ? ((unsigned int)strlen(s.pMaterial[i].pszEffectFile)+1) : 0)) return false;
  895. if(!WriteData(pFile, ePODFileMatEffectName, s.pMaterial[i].pszEffectName, s.pMaterial[i].pszEffectName ? ((unsigned int)strlen(s.pMaterial[i].pszEffectName)+1) : 0)) return false;
  896. if(!WriteData32(pFile, ePODFileMatBlendSrcRGB, &s.pMaterial[i].eBlendSrcRGB))return false;
  897. if(!WriteData32(pFile, ePODFileMatBlendSrcA, &s.pMaterial[i].eBlendSrcA)) return false;
  898. if(!WriteData32(pFile, ePODFileMatBlendDstRGB, &s.pMaterial[i].eBlendDstRGB))return false;
  899. if(!WriteData32(pFile, ePODFileMatBlendDstA, &s.pMaterial[i].eBlendDstA)) return false;
  900. if(!WriteData32(pFile, ePODFileMatBlendOpRGB, &s.pMaterial[i].eBlendOpRGB)) return false;
  901. if(!WriteData32(pFile, ePODFileMatBlendOpA, &s.pMaterial[i].eBlendOpA)) return false;
  902. if(!WriteData32(pFile, ePODFileMatBlendColour, s.pMaterial[i].pfBlendColour, sizeof(s.pMaterial[i].pfBlendColour) / sizeof(*s.pMaterial[i].pfBlendColour))) return false;
  903. if(!WriteData32(pFile, ePODFileMatBlendFactor, s.pMaterial[i].pfBlendFactor, sizeof(s.pMaterial[i].pfBlendFactor) / sizeof(*s.pMaterial[i].pfBlendFactor))) return false;
  904. if(!WriteMarker(pFile, ePODFileMaterial, true)) return false;
  905. }
  906. // Save: meshes
  907. for(i = 0; i < s.nNumMesh; ++i)
  908. {
  909. if(!WriteMarker(pFile, ePODFileMesh, false)) return false;
  910. if(!WriteData32(pFile, ePODFileMeshNumVtx, &s.pMesh[i].nNumVertex)) return false;
  911. if(!WriteData32(pFile, ePODFileMeshNumFaces, &s.pMesh[i].nNumFaces)) return false;
  912. if(!WriteData32(pFile, ePODFileMeshNumUVW, &s.pMesh[i].nNumUVW)) return false;
  913. if(!WriteData32(pFile, ePODFileMeshStripLength, s.pMesh[i].pnStripLength, s.pMesh[i].nNumStrips)) return false;
  914. if(!WriteData32(pFile, ePODFileMeshNumStrips, &s.pMesh[i].nNumStrips)) return false;
  915. if(!WriteInterleaved(pFile, s.pMesh[i])) return false;
  916. if(!WriteData32(pFile, ePODFileMeshBoneBatchBoneMax,&s.pMesh[i].sBoneBatches.nBatchBoneMax)) return false;
  917. if(!WriteData32(pFile, ePODFileMeshBoneBatchCnt, &s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
  918. if(!WriteData32(pFile, ePODFileMeshBoneBatches, s.pMesh[i].sBoneBatches.pnBatches, s.pMesh[i].sBoneBatches.nBatchBoneMax * s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
  919. if(!WriteData32(pFile, ePODFileMeshBoneBatchBoneCnts, s.pMesh[i].sBoneBatches.pnBatchBoneCnt, s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
  920. if(!WriteData32(pFile, ePODFileMeshBoneBatchOffsets, s.pMesh[i].sBoneBatches.pnBatchOffset,s.pMesh[i].sBoneBatches.nBatchCnt)) return false;
  921. if(!WriteData32(pFile, ePODFileMeshUnpackMatrix, s.pMesh[i].mUnpackMatrix.f, 16)) return false;
  922. if(!WriteCPODData(pFile, ePODFileMeshFaces, s.pMesh[i].sFaces, PVRTModelPODCountIndices(s.pMesh[i]), true)) return false;
  923. if(!WriteCPODData(pFile, ePODFileMeshVtx, s.pMesh[i].sVertex, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  924. if(!WriteCPODData(pFile, ePODFileMeshNor, s.pMesh[i].sNormals, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  925. if(!WriteCPODData(pFile, ePODFileMeshTan, s.pMesh[i].sTangents, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  926. if(!WriteCPODData(pFile, ePODFileMeshBin, s.pMesh[i].sBinormals, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  927. for(j = 0; j < s.pMesh[i].nNumUVW; ++j)
  928. if(!WriteCPODData(pFile, ePODFileMeshUVW, s.pMesh[i].psUVW[j], s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  929. if(!WriteCPODData(pFile, ePODFileMeshVtxCol, s.pMesh[i].sVtxColours, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  930. if(!WriteCPODData(pFile, ePODFileMeshBoneIdx, s.pMesh[i].sBoneIdx, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  931. if(!WriteCPODData(pFile, ePODFileMeshBoneWeight, s.pMesh[i].sBoneWeight, s.pMesh[i].nNumVertex, s.pMesh[i].pInterleaved == 0)) return false;
  932. if(!WriteMarker(pFile, ePODFileMesh, true)) return false;
  933. }
  934. int iTransformationNo;
  935. // Save: node
  936. for(i = 0; i < s.nNumNode; ++i)
  937. {
  938. if(!WriteMarker(pFile, ePODFileNode, false)) return false;
  939. {
  940. if(!WriteData32(pFile, ePODFileNodeIdx, &s.pNode[i].nIdx)) return false;
  941. if(!WriteData(pFile, ePODFileNodeName, s.pNode[i].pszName, (unsigned int)strlen(s.pNode[i].pszName)+1)) return false;
  942. if(!WriteData32(pFile, ePODFileNodeIdxMat, &s.pNode[i].nIdxMaterial)) return false;
  943. if(!WriteData32(pFile, ePODFileNodeIdxParent, &s.pNode[i].nIdxParent)) return false;
  944. if(!WriteData32(pFile, ePODFileNodeAnimFlags, &s.pNode[i].nAnimFlags)) return false;
  945. if(s.pNode[i].pnAnimPositionIdx)
  946. {
  947. if(!WriteData32(pFile, ePODFileNodeAnimPosIdx, s.pNode[i].pnAnimPositionIdx, s.nNumFrame)) return false;
  948. }
  949. iTransformationNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
  950. if(!WriteData32(pFile, ePODFileNodeAnimPos, s.pNode[i].pfAnimPosition, iTransformationNo)) return false;
  951. if(s.pNode[i].pnAnimRotationIdx)
  952. {
  953. if(!WriteData32(pFile, ePODFileNodeAnimRotIdx, s.pNode[i].pnAnimRotationIdx, s.nNumFrame)) return false;
  954. }
  955. iTransformationNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
  956. if(!WriteData32(pFile, ePODFileNodeAnimRot, s.pNode[i].pfAnimRotation, iTransformationNo)) return false;
  957. if(s.pNode[i].pnAnimScaleIdx)
  958. {
  959. if(!WriteData32(pFile, ePODFileNodeAnimScaleIdx, s.pNode[i].pnAnimScaleIdx, s.nNumFrame)) return false;
  960. }
  961. iTransformationNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
  962. if(!WriteData32(pFile, ePODFileNodeAnimScale, s.pNode[i].pfAnimScale, iTransformationNo)) return false;
  963. if(s.pNode[i].pnAnimMatrixIdx)
  964. {
  965. if(!WriteData32(pFile, ePODFileNodeAnimMatrixIdx, s.pNode[i].pnAnimMatrixIdx, s.nNumFrame)) return false;
  966. }
  967. iTransformationNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
  968. if(!WriteData32(pFile, ePODFileNodeAnimMatrix,s.pNode[i].pfAnimMatrix, iTransformationNo)) return false;
  969. }
  970. if(!WriteMarker(pFile, ePODFileNode, true)) return false;
  971. }
  972. // Save: texture
  973. for(i = 0; i < s.nNumTexture; ++i)
  974. {
  975. if(!WriteMarker(pFile, ePODFileTexture, false)) return false;
  976. if(!WriteData(pFile, ePODFileTexName, s.pTexture[i].pszName, (unsigned int)strlen(s.pTexture[i].pszName)+1)) return false;
  977. if(!WriteMarker(pFile, ePODFileTexture, true)) return false;
  978. }
  979. }
  980. if(!WriteMarker(pFile, ePODFileScene, true)) return false;
  981. return true;
  982. }
  983. /****************************************************************************
  984. ** Local code: File reading
  985. ****************************************************************************/
  986. /*!***************************************************************************
  987. @Function ReadCPODData
  988. @Modified s The CPODData to read into
  989. @Input src CSource object to read data from.
  990. @Input nSpec
  991. @Input bValidData
  992. @Return true if successful
  993. @Description Read a CPODData block in from a pod file
  994. *****************************************************************************/
  995. static bool ReadCPODData(
  996. CPODData &s,
  997. CSource &src,
  998. const unsigned int nSpec,
  999. const bool bValidData)
  1000. {
  1001. unsigned int nName, nLen, nBuff;
  1002. while(src.ReadMarker(nName, nLen))
  1003. {
  1004. if(nName == (nSpec | PVRTMODELPOD_TAG_END))
  1005. return true;
  1006. switch(nName)
  1007. {
  1008. case ePODFileDataType: if(!src.Read32(s.eType)) return false; break;
  1009. case ePODFileN: if(!src.Read32(s.n)) return false; break;
  1010. case ePODFileStride: if(!src.Read32(s.nStride)) return false; break;
  1011. case ePODFileData:
  1012. if(bValidData)
  1013. {
  1014. switch(PVRTModelPODDataTypeSize(s.eType))
  1015. {
  1016. case 1: if(!src.ReadAfterAlloc(s.pData, nLen)) return false; break;
  1017. case 2:
  1018. { // reading 16bit data but have 8bit pointer
  1019. PVRTuint16 *p16Pointer=NULL;
  1020. if(!src.ReadAfterAlloc16(p16Pointer, nLen)) return false;
  1021. s.pData = (unsigned char*)p16Pointer;
  1022. break;
  1023. }
  1024. case 4:
  1025. { // reading 32bit data but have 8bit pointer
  1026. PVRTuint32 *p32Pointer=NULL;
  1027. if(!src.ReadAfterAlloc32(p32Pointer, nLen)) return false;
  1028. s.pData = (unsigned char*)p32Pointer;
  1029. break;
  1030. }
  1031. default:
  1032. { _ASSERT(false);}
  1033. }
  1034. }
  1035. else
  1036. {
  1037. if(src.Read32(nBuff))
  1038. {
  1039. s.pData = (unsigned char*) (size_t) nBuff;
  1040. }
  1041. else
  1042. {
  1043. return false;
  1044. }
  1045. }
  1046. break;
  1047. default:
  1048. if(!src.Skip(nLen)) return false;
  1049. }
  1050. }
  1051. return false;
  1052. }
  1053. /*!***************************************************************************
  1054. @Function ReadCamera
  1055. @Modified s The SPODCamera to read into
  1056. @Input src CSource object to read data from.
  1057. @Return true if successful
  1058. @Description Read a camera block in from a pod file
  1059. *****************************************************************************/
  1060. static bool ReadCamera(
  1061. SPODCamera &s,
  1062. CSource &src)
  1063. {
  1064. unsigned int nName, nLen;
  1065. s.pfAnimFOV = 0;
  1066. while(src.ReadMarker(nName, nLen))
  1067. {
  1068. switch(nName)
  1069. {
  1070. case ePODFileCamera | PVRTMODELPOD_TAG_END: return true;
  1071. case ePODFileCamIdxTgt: if(!src.Read32(s.nIdxTarget)) return false; break;
  1072. case ePODFileCamFOV: if(!src.Read32(s.fFOV)) return false; break;
  1073. case ePODFileCamFar: if(!src.Read32(s.fFar)) return false; break;
  1074. case ePODFileCamNear: if(!src.Read32(s.fNear)) return false; break;
  1075. case ePODFileCamAnimFOV: if(!src.ReadAfterAlloc32(s.pfAnimFOV, nLen)) return false; break;
  1076. default:
  1077. if(!src.Skip(nLen)) return false;
  1078. }
  1079. }
  1080. return false;
  1081. }
  1082. /*!***************************************************************************
  1083. @Function ReadLight
  1084. @Modified s The SPODLight to read into
  1085. @Input src CSource object to read data from.
  1086. @Return true if successful
  1087. @Description Read a light block in from a pod file
  1088. *****************************************************************************/
  1089. static bool ReadLight(
  1090. SPODLight &s,
  1091. CSource &src)
  1092. {
  1093. unsigned int nName, nLen;
  1094. while(src.ReadMarker(nName, nLen))
  1095. {
  1096. switch(nName)
  1097. {
  1098. case ePODFileLight | PVRTMODELPOD_TAG_END: return true;
  1099. case ePODFileLightIdxTgt: if(!src.Read32(s.nIdxTarget)) return false; break;
  1100. case ePODFileLightColour: if(!src.ReadArray32((unsigned int*) s.pfColour, 3)) return false; break;
  1101. case ePODFileLightType: if(!src.Read32(s.eType)) return false; break;
  1102. case ePODFileLightConstantAttenuation: if(!src.Read32(s.fConstantAttenuation)) return false; break;
  1103. case ePODFileLightLinearAttenuation: if(!src.Read32(s.fLinearAttenuation)) return false; break;
  1104. case ePODFileLightQuadraticAttenuation: if(!src.Read32(s.fQuadraticAttenuation)) return false; break;
  1105. case ePODFileLightFalloffAngle: if(!src.Read32(s.fFalloffAngle)) return false; break;
  1106. case ePODFileLightFalloffExponent: if(!src.Read32(s.fFalloffExponent)) return false; break;
  1107. default:
  1108. if(!src.Skip(nLen)) return false;
  1109. }
  1110. }
  1111. return false;
  1112. }
  1113. /*!***************************************************************************
  1114. @Function ReadMaterial
  1115. @Modified s The SPODMaterial to read into
  1116. @Input src CSource object to read data from.
  1117. @Return true if successful
  1118. @Description Read a material block in from a pod file
  1119. *****************************************************************************/
  1120. static bool ReadMaterial(
  1121. SPODMaterial &s,
  1122. CSource &src)
  1123. {
  1124. unsigned int nName, nLen;
  1125. // Set texture IDs to -1
  1126. s.nIdxTexDiffuse = -1;
  1127. s.nIdxTexAmbient = -1;
  1128. s.nIdxTexSpecularColour = -1;
  1129. s.nIdxTexSpecularLevel = -1;
  1130. s.nIdxTexBump = -1;
  1131. s.nIdxTexEmissive = -1;
  1132. s.nIdxTexGlossiness = -1;
  1133. s.nIdxTexOpacity = -1;
  1134. s.nIdxTexReflection = -1;
  1135. s.nIdxTexRefraction = -1;
  1136. // Set defaults for blend modes
  1137. s.eBlendSrcRGB = s.eBlendSrcA = ePODBlendFunc_ONE;
  1138. s.eBlendDstRGB = s.eBlendDstA = ePODBlendFunc_ZERO;
  1139. s.eBlendOpRGB = s.eBlendOpA = ePODBlendOp_ADD;
  1140. memset(s.pfBlendColour, 0, sizeof(s.pfBlendColour));
  1141. memset(s.pfBlendFactor, 0, sizeof(s.pfBlendFactor));
  1142. // Set default for material flags
  1143. s.nFlags = 0;
  1144. while(src.ReadMarker(nName, nLen))
  1145. {
  1146. switch(nName)
  1147. {
  1148. case ePODFileMaterial | PVRTMODELPOD_TAG_END: return true;
  1149. case ePODFileMatFlags: if(!src.Read32(s.nFlags)) return false; break;
  1150. case ePODFileMatName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
  1151. case ePODFileMatIdxTexDiffuse: if(!src.Read32(s.nIdxTexDiffuse)) return false; break;
  1152. case ePODFileMatIdxTexAmbient: if(!src.Read32(s.nIdxTexAmbient)) return false; break;
  1153. case ePODFileMatIdxTexSpecularColour: if(!src.Read32(s.nIdxTexSpecularColour)) return false; break;
  1154. case ePODFileMatIdxTexSpecularLevel: if(!src.Read32(s.nIdxTexSpecularLevel)) return false; break;
  1155. case ePODFileMatIdxTexBump: if(!src.Read32(s.nIdxTexBump)) return false; break;
  1156. case ePODFileMatIdxTexEmissive: if(!src.Read32(s.nIdxTexEmissive)) return false; break;
  1157. case ePODFileMatIdxTexGlossiness: if(!src.Read32(s.nIdxTexGlossiness)) return false; break;
  1158. case ePODFileMatIdxTexOpacity: if(!src.Read32(s.nIdxTexOpacity)) return false; break;
  1159. case ePODFileMatIdxTexReflection: if(!src.Read32(s.nIdxTexReflection)) return false; break;
  1160. case ePODFileMatIdxTexRefraction: if(!src.Read32(s.nIdxTexRefraction)) return false; break;
  1161. case ePODFileMatOpacity: if(!src.Read32(s.fMatOpacity)) return false; break;
  1162. case ePODFileMatAmbient: if(!src.ReadArray32((unsigned int*) s.pfMatAmbient, sizeof(s.pfMatAmbient) / sizeof(*s.pfMatAmbient))) return false; break;
  1163. case ePODFileMatDiffuse: if(!src.ReadArray32((unsigned int*) s.pfMatDiffuse, sizeof(s.pfMatDiffuse) / sizeof(*s.pfMatDiffuse))) return false; break;
  1164. case ePODFileMatSpecular: if(!src.ReadArray32((unsigned int*) s.pfMatSpecular, sizeof(s.pfMatSpecular) / sizeof(*s.pfMatSpecular))) return false; break;
  1165. case ePODFileMatShininess: if(!src.Read32(s.fMatShininess)) return false; break;
  1166. case ePODFileMatEffectFile: if(!src.ReadAfterAlloc(s.pszEffectFile, nLen)) return false; break;
  1167. case ePODFileMatEffectName: if(!src.ReadAfterAlloc(s.pszEffectName, nLen)) return false; break;
  1168. case ePODFileMatBlendSrcRGB: if(!src.Read32(s.eBlendSrcRGB)) return false; break;
  1169. case ePODFileMatBlendSrcA: if(!src.Read32(s.eBlendSrcA)) return false; break;
  1170. case ePODFileMatBlendDstRGB: if(!src.Read32(s.eBlendDstRGB)) return false; break;
  1171. case ePODFileMatBlendDstA: if(!src.Read32(s.eBlendDstA)) return false; break;
  1172. case ePODFileMatBlendOpRGB: if(!src.Read32(s.eBlendOpRGB)) return false; break;
  1173. case ePODFileMatBlendOpA: if(!src.Read32(s.eBlendOpA)) return false; break;
  1174. case ePODFileMatBlendColour: if(!src.ReadArray32((unsigned int*) s.pfBlendColour, sizeof(s.pfBlendColour) / sizeof(*s.pfBlendColour))) return false; break;
  1175. case ePODFileMatBlendFactor: if(!src.ReadArray32((unsigned int*) s.pfBlendFactor, sizeof(s.pfBlendFactor) / sizeof(*s.pfBlendFactor))) return false; break;
  1176. default:
  1177. if(!src.Skip(nLen)) return false;
  1178. }
  1179. }
  1180. return false;
  1181. }
  1182. /*!***************************************************************************
  1183. @Function PVRTFixInterleavedEndiannessUsingCPODData
  1184. @Modified pInterleaved - The interleaved data
  1185. @Input data - The CPODData.
  1186. @Return ui32Size - Number of elements in pInterleaved
  1187. @Description Called multiple times and goes through the interleaved data
  1188. correcting the endianness.
  1189. *****************************************************************************/
  1190. void PVRTFixInterleavedEndiannessUsingCPODData(unsigned char* pInterleaved, CPODData &data, unsigned int ui32Size)
  1191. {
  1192. if(!data.n)
  1193. return;
  1194. size_t ui32TypeSize = PVRTModelPODDataTypeSize(data.eType);
  1195. unsigned char ub[4];
  1196. unsigned char *pData = pInterleaved + (size_t) data.pData;
  1197. switch(ui32TypeSize)
  1198. {
  1199. case 1: return;
  1200. case 2:
  1201. {
  1202. for(unsigned int i = 0; i < ui32Size; ++i)
  1203. {
  1204. for(unsigned int j = 0; j < data.n; ++j)
  1205. {
  1206. ub[0] = pData[ui32TypeSize * j + 0];
  1207. ub[1] = pData[ui32TypeSize * j + 1];
  1208. ((unsigned short*) pData)[j] = (unsigned short) ((ub[1] << 8) | ub[0]);
  1209. }
  1210. pData += data.nStride;
  1211. }
  1212. }
  1213. break;
  1214. case 4:
  1215. {
  1216. for(unsigned int i = 0; i < ui32Size; ++i)
  1217. {
  1218. for(unsigned int j = 0; j < data.n; ++j)
  1219. {
  1220. ub[0] = pData[ui32TypeSize * j + 0];
  1221. ub[1] = pData[ui32TypeSize * j + 1];
  1222. ub[2] = pData[ui32TypeSize * j + 2];
  1223. ub[3] = pData[ui32TypeSize * j + 3];
  1224. ((unsigned int*) pData)[j] = (unsigned int) ((ub[3] << 24) | (ub[2] << 16) | (ub[1] << 8) | ub[0]);
  1225. }
  1226. pData += data.nStride;
  1227. }
  1228. }
  1229. break;
  1230. default: { _ASSERT(false); }
  1231. };
  1232. }
  1233. void PVRTFixInterleavedEndianness(SPODMesh &s)
  1234. {
  1235. if(!s.pInterleaved || PVRTIsLittleEndian())
  1236. return;
  1237. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sVertex, s.nNumVertex);
  1238. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sNormals, s.nNumVertex);
  1239. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sTangents, s.nNumVertex);
  1240. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBinormals, s.nNumVertex);
  1241. for(unsigned int i = 0; i < s.nNumUVW; ++i)
  1242. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.psUVW[i], s.nNumVertex);
  1243. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sVtxColours, s.nNumVertex);
  1244. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBoneIdx, s.nNumVertex);
  1245. PVRTFixInterleavedEndiannessUsingCPODData(s.pInterleaved, s.sBoneWeight, s.nNumVertex);
  1246. }
  1247. /*!***************************************************************************
  1248. @Function ReadMesh
  1249. @Modified s The SPODMesh to read into
  1250. @Input src CSource object to read data from.
  1251. @Return true if successful
  1252. @Description Read a mesh block in from a pod file
  1253. *****************************************************************************/
  1254. static bool ReadMesh(
  1255. SPODMesh &s,
  1256. CSource &src)
  1257. {
  1258. unsigned int nName, nLen;
  1259. unsigned int nUVWs=0;
  1260. PVRTMatrixIdentity(s.mUnpackMatrix);
  1261. while(src.ReadMarker(nName, nLen))
  1262. {
  1263. switch(nName)
  1264. {
  1265. case ePODFileMesh | PVRTMODELPOD_TAG_END:
  1266. if(nUVWs != s.nNumUVW)
  1267. return false;
  1268. PVRTFixInterleavedEndianness(s);
  1269. return true;
  1270. case ePODFileMeshNumVtx: if(!src.Read32(s.nNumVertex)) return false; break;
  1271. case ePODFileMeshNumFaces: if(!src.Read32(s.nNumFaces)) return false; break;
  1272. case ePODFileMeshNumUVW: if(!src.Read32(s.nNumUVW)) return false; if(!SafeAlloc(s.psUVW, s.nNumUVW)) return false; break;
  1273. case ePODFileMeshStripLength: if(!src.ReadAfterAlloc32(s.pnStripLength, nLen)) return false; break;
  1274. case ePODFileMeshNumStrips: if(!src.Read32(s.nNumStrips)) return false; break;
  1275. case ePODFileMeshInterleaved: if(!src.ReadAfterAlloc(s.pInterleaved, nLen)) return false; break;
  1276. case ePODFileMeshBoneBatches: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatches, nLen)) return false; break;
  1277. case ePODFileMeshBoneBatchBoneCnts: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatchBoneCnt, nLen)) return false; break;
  1278. case ePODFileMeshBoneBatchOffsets: if(!src.ReadAfterAlloc32(s.sBoneBatches.pnBatchOffset, nLen)) return false; break;
  1279. case ePODFileMeshBoneBatchBoneMax: if(!src.Read32(s.sBoneBatches.nBatchBoneMax)) return false; break;
  1280. case ePODFileMeshBoneBatchCnt: if(!src.Read32(s.sBoneBatches.nBatchCnt)) return false; break;
  1281. case ePODFileMeshUnpackMatrix: if(!src.ReadArray32((unsigned int*)&s.mUnpackMatrix.f[0], 16)) return false; break;
  1282. case ePODFileMeshFaces: if(!ReadCPODData(s.sFaces, src, ePODFileMeshFaces, true)) return false; break;
  1283. case ePODFileMeshVtx: if(!ReadCPODData(s.sVertex, src, ePODFileMeshVtx, s.pInterleaved == 0)) return false; break;
  1284. case ePODFileMeshNor: if(!ReadCPODData(s.sNormals, src, ePODFileMeshNor, s.pInterleaved == 0)) return false; break;
  1285. case ePODFileMeshTan: if(!ReadCPODData(s.sTangents, src, ePODFileMeshTan, s.pInterleaved == 0)) return false; break;
  1286. case ePODFileMeshBin: if(!ReadCPODData(s.sBinormals, src, ePODFileMeshBin, s.pInterleaved == 0)) return false; break;
  1287. case ePODFileMeshUVW: if(!ReadCPODData(s.psUVW[nUVWs++], src, ePODFileMeshUVW, s.pInterleaved == 0)) return false; break;
  1288. case ePODFileMeshVtxCol: if(!ReadCPODData(s.sVtxColours, src, ePODFileMeshVtxCol, s.pInterleaved == 0)) return false; break;
  1289. case ePODFileMeshBoneIdx: if(!ReadCPODData(s.sBoneIdx, src, ePODFileMeshBoneIdx, s.pInterleaved == 0)) return false; break;
  1290. case ePODFileMeshBoneWeight: if(!ReadCPODData(s.sBoneWeight, src, ePODFileMeshBoneWeight, s.pInterleaved == 0)) return false; break;
  1291. default:
  1292. if(!src.Skip(nLen)) return false;
  1293. }
  1294. }
  1295. return false;
  1296. }
  1297. /*!***************************************************************************
  1298. @Function ReadNode
  1299. @Modified s The SPODNode to read into
  1300. @Input src CSource object to read data from.
  1301. @Return true if successful
  1302. @Description Read a node block in from a pod file
  1303. *****************************************************************************/
  1304. static bool ReadNode(
  1305. SPODNode &s,
  1306. CSource &src)
  1307. {
  1308. unsigned int nName, nLen;
  1309. bool bOldNodeFormat = false;
  1310. VERTTYPE fPos[3] = {0,0,0};
  1311. VERTTYPE fQuat[4] = {0,0,0,f2vt(1)};
  1312. VERTTYPE fScale[7] = {f2vt(1),f2vt(1),f2vt(1),0,0,0,0};
  1313. while(src.ReadMarker(nName, nLen))
  1314. {
  1315. switch(nName)
  1316. {
  1317. case ePODFileNode | PVRTMODELPOD_TAG_END:
  1318. if(bOldNodeFormat)
  1319. {
  1320. if(s.pfAnimPosition)
  1321. s.nAnimFlags |= ePODHasPositionAni;
  1322. else
  1323. {
  1324. s.pfAnimPosition = (VERTTYPE*) malloc(sizeof(fPos));
  1325. memcpy(s.pfAnimPosition, fPos, sizeof(fPos));
  1326. }
  1327. if(s.pfAnimRotation)
  1328. s.nAnimFlags |= ePODHasRotationAni;
  1329. else
  1330. {
  1331. s.pfAnimRotation = (VERTTYPE*) malloc(sizeof(fQuat));
  1332. memcpy(s.pfAnimRotation, fQuat, sizeof(fQuat));
  1333. }
  1334. if(s.pfAnimScale)
  1335. s.nAnimFlags |= ePODHasScaleAni;
  1336. else
  1337. {
  1338. s.pfAnimScale = (VERTTYPE*) malloc(sizeof(fScale));
  1339. memcpy(s.pfAnimScale, fScale, sizeof(fScale));
  1340. }
  1341. }
  1342. return true;
  1343. case ePODFileNodeIdx: if(!src.Read32(s.nIdx)) return false; break;
  1344. case ePODFileNodeName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
  1345. case ePODFileNodeIdxMat: if(!src.Read32(s.nIdxMaterial)) return false; break;
  1346. case ePODFileNodeIdxParent: if(!src.Read32(s.nIdxParent)) return false; break;
  1347. case ePODFileNodeAnimFlags:if(!src.Read32(s.nAnimFlags))return false; break;
  1348. case ePODFileNodeAnimPosIdx: if(!src.ReadAfterAlloc32(s.pnAnimPositionIdx, nLen)) return false; break;
  1349. case ePODFileNodeAnimPos: if(!src.ReadAfterAlloc32(s.pfAnimPosition, nLen)) return false; break;
  1350. case ePODFileNodeAnimRotIdx: if(!src.ReadAfterAlloc32(s.pnAnimRotationIdx, nLen)) return false; break;
  1351. case ePODFileNodeAnimRot: if(!src.ReadAfterAlloc32(s.pfAnimRotation, nLen)) return false; break;
  1352. case ePODFileNodeAnimScaleIdx: if(!src.ReadAfterAlloc32(s.pnAnimScaleIdx, nLen)) return false; break;
  1353. case ePODFileNodeAnimScale: if(!src.ReadAfterAlloc32(s.pfAnimScale, nLen)) return false; break;
  1354. case ePODFileNodeAnimMatrixIdx: if(!src.ReadAfterAlloc32(s.pnAnimMatrixIdx, nLen)) return false; break;
  1355. case ePODFileNodeAnimMatrix:if(!src.ReadAfterAlloc32(s.pfAnimMatrix, nLen)) return false; break;
  1356. // Parameters from the older pod format
  1357. case ePODFileNodePos: if(!src.ReadArray32((unsigned int*) fPos, 3)) return false; bOldNodeFormat = true; break;
  1358. case ePODFileNodeRot: if(!src.ReadArray32((unsigned int*) fQuat, 4)) return false; bOldNodeFormat = true; break;
  1359. case ePODFileNodeScale: if(!src.ReadArray32((unsigned int*) fScale,3)) return false; bOldNodeFormat = true; break;
  1360. default:
  1361. if(!src.Skip(nLen)) return false;
  1362. }
  1363. }
  1364. return false;
  1365. }
  1366. /*!***************************************************************************
  1367. @Function ReadTexture
  1368. @Modified s The SPODTexture to read into
  1369. @Input src CSource object to read data from.
  1370. @Return true if successful
  1371. @Description Read a texture block in from a pod file
  1372. *****************************************************************************/
  1373. static bool ReadTexture(
  1374. SPODTexture &s,
  1375. CSource &src)
  1376. {
  1377. unsigned int nName, nLen;
  1378. while(src.ReadMarker(nName, nLen))
  1379. {
  1380. switch(nName)
  1381. {
  1382. case ePODFileTexture | PVRTMODELPOD_TAG_END: return true;
  1383. case ePODFileTexName: if(!src.ReadAfterAlloc(s.pszName, nLen)) return false; break;
  1384. default:
  1385. if(!src.Skip(nLen)) return false;
  1386. }
  1387. }
  1388. return false;
  1389. }
  1390. /*!***************************************************************************
  1391. @Function ReadScene
  1392. @Modified s The SPODScene to read into
  1393. @Input src CSource object to read data from.
  1394. @Return true if successful
  1395. @Description Read a scene block in from a pod file
  1396. *****************************************************************************/
  1397. static bool ReadScene(
  1398. SPODScene &s,
  1399. CSource &src)
  1400. {
  1401. unsigned int nName, nLen;
  1402. unsigned int nCameras=0, nLights=0, nMaterials=0, nMeshes=0, nTextures=0, nNodes=0;
  1403. s.nFPS = 30;
  1404. while(src.ReadMarker(nName, nLen))
  1405. {
  1406. switch(nName)
  1407. {
  1408. case ePODFileScene | PVRTMODELPOD_TAG_END:
  1409. if(nCameras != s.nNumCamera) return false;
  1410. if(nLights != s.nNumLight) return false;
  1411. if(nMaterials != s.nNumMaterial) return false;
  1412. if(nMeshes != s.nNumMesh) return false;
  1413. if(nTextures != s.nNumTexture) return false;
  1414. if(nNodes != s.nNumNode) return false;
  1415. return true;
  1416. case ePODFileColourBackground: if(!src.ReadArray32((unsigned int*) s.pfColourBackground, sizeof(s.pfColourBackground) / sizeof(*s.pfColourBackground))) return false; break;
  1417. case ePODFileColourAmbient: if(!src.ReadArray32((unsigned int*) s.pfColourAmbient, sizeof(s.pfColourAmbient) / sizeof(*s.pfColourAmbient))) return false; break;
  1418. case ePODFileNumCamera: if(!src.Read32(s.nNumCamera)) return false; if(!SafeAlloc(s.pCamera, s.nNumCamera)) return false; break;
  1419. case ePODFileNumLight: if(!src.Read32(s.nNumLight)) return false; if(!SafeAlloc(s.pLight, s.nNumLight)) return false; break;
  1420. case ePODFileNumMesh: if(!src.Read32(s.nNumMesh)) return false; if(!SafeAlloc(s.pMesh, s.nNumMesh)) return false; break;
  1421. case ePODFileNumNode: if(!src.Read32(s.nNumNode)) return false; if(!SafeAlloc(s.pNode, s.nNumNode)) return false; break;
  1422. case ePODFileNumMeshNode: if(!src.Read32(s.nNumMeshNode)) return false; break;
  1423. case ePODFileNumTexture: if(!src.Read32(s.nNumTexture)) return false; if(!SafeAlloc(s.pTexture, s.nNumTexture)) return false; break;
  1424. case ePODFileNumMaterial: if(!src.Read32(s.nNumMaterial)) return false; if(!SafeAlloc(s.pMaterial, s.nNumMaterial)) return false; break;
  1425. case ePODFileNumFrame: if(!src.Read32(s.nNumFrame)) return false; break;
  1426. case ePODFileFPS: if(!src.Read32(s.nFPS)) return false; break;
  1427. case ePODFileFlags: if(!src.Read32(s.nFlags)) return false; break;
  1428. case ePODFileCamera: if(!ReadCamera(s.pCamera[nCameras++], src)) return false; break;
  1429. case ePODFileLight: if(!ReadLight(s.pLight[nLights++], src)) return false; break;
  1430. case ePODFileMaterial: if(!ReadMaterial(s.pMaterial[nMaterials++], src)) return false; break;
  1431. case ePODFileMesh: if(!ReadMesh(s.pMesh[nMeshes++], src)) return false; break;
  1432. case ePODFileNode: if(!ReadNode(s.pNode[nNodes++], src)) return false; break;
  1433. case ePODFileTexture: if(!ReadTexture(s.pTexture[nTextures++], src)) return false; break;
  1434. default:
  1435. if(!src.Skip(nLen)) return false;
  1436. }
  1437. }
  1438. return false;
  1439. }
  1440. /*!***************************************************************************
  1441. @Function Read
  1442. @Output pS SPODScene data. May be NULL.
  1443. @Input src CSource object to read data from.
  1444. @Output pszExpOpt Export options.
  1445. @Input count Data size.
  1446. @Output pszHistory Export history.
  1447. @Input historyCount History data size.
  1448. @Description Loads the specified ".POD" file; returns the scene in
  1449. pScene. This structure must later be destroyed with
  1450. PVRTModelPODDestroy() to prevent memory leaks.
  1451. ".POD" files are exported from 3D Studio MAX using a
  1452. PowerVR plugin. pS may be NULL if only the export options
  1453. are required.
  1454. *****************************************************************************/
  1455. static bool Read(
  1456. SPODScene * const pS,
  1457. CSource &src,
  1458. char * const pszExpOpt,
  1459. const size_t count,
  1460. char * const pszHistory,
  1461. const size_t historyCount)
  1462. {
  1463. unsigned int nName, nLen;
  1464. bool bVersionOK = false, bDone = false;
  1465. bool bNeedOptions = pszExpOpt != 0;
  1466. bool bNeedHistory = pszHistory != 0;
  1467. bool bLoadingOptionsOrHistory = bNeedOptions || bNeedHistory;
  1468. while(src.ReadMarker(nName, nLen))
  1469. {
  1470. switch(nName)
  1471. {
  1472. case ePODFileVersion:
  1473. {
  1474. char *pszVersion = NULL;
  1475. if(nLen != strlen(PVRTMODELPOD_VERSION)+1) return false;
  1476. if(!SafeAlloc(pszVersion, nLen)) return false;
  1477. if(!src.Read(pszVersion, nLen)) return false;
  1478. if(strcmp(pszVersion, PVRTMODELPOD_VERSION) != 0) return false;
  1479. bVersionOK = true;
  1480. FREE(pszVersion);
  1481. }
  1482. continue;
  1483. case ePODFileScene:
  1484. if(pS)
  1485. {
  1486. if(!ReadScene(*pS, src))
  1487. return false;
  1488. bDone = true;
  1489. }
  1490. continue;
  1491. case ePODFileExpOpt:
  1492. if(bNeedOptions)
  1493. {
  1494. if(!src.Read(pszExpOpt, PVRT_MIN(nLen, (unsigned int) count)))
  1495. return false;
  1496. bNeedOptions = false;
  1497. if(count < nLen)
  1498. nLen -= (unsigned int) count ; // Adjust nLen as the read has moved our position
  1499. else
  1500. nLen = 0;
  1501. }
  1502. break;
  1503. case ePODFileHistory:
  1504. if(bNeedHistory)
  1505. {
  1506. if(!src.Read(pszHistory, PVRT_MIN(nLen, (unsigned int) historyCount)))
  1507. return false;
  1508. bNeedHistory = false;
  1509. if(count < nLen)
  1510. nLen -= (unsigned int) historyCount; // Adjust nLen as the read has moved our position
  1511. else
  1512. nLen = 0;
  1513. }
  1514. break;
  1515. case ePODFileScene | PVRTMODELPOD_TAG_END:
  1516. return bVersionOK == true && bDone == true;
  1517. case (unsigned int) ePODFileEndiannessMisMatch:
  1518. PVRTErrorOutputDebug("Error: Endianness mismatch between the .pod file and the platform.\n");
  1519. return false;
  1520. }
  1521. if(bLoadingOptionsOrHistory && !bNeedOptions && !bNeedHistory)
  1522. return true; // The options and/or history has been loaded
  1523. // Unhandled data, skip it
  1524. if(!src.Skip(nLen))
  1525. return false;
  1526. }
  1527. if(bLoadingOptionsOrHistory)
  1528. return true;
  1529. /*
  1530. Convert data to fixed or float point as this build desires
  1531. */
  1532. #ifdef PVRT_FIXED_POINT_ENABLE
  1533. if(!(pS->nFlags & PVRTMODELPODSF_FIXED))
  1534. PVRTModelPODToggleFixedPoint(*pS);
  1535. #else
  1536. if(pS->nFlags & PVRTMODELPODSF_FIXED)
  1537. PVRTModelPODToggleFixedPoint(*pS);
  1538. #endif
  1539. return bVersionOK == true && bDone == true;
  1540. }
  1541. /*!***************************************************************************
  1542. @Function ReadFromSourceStream
  1543. @Output pS CPVRTModelPOD data. May not be NULL.
  1544. @Input src CSource object to read data from.
  1545. @Output pszExpOpt Export options.
  1546. @Input count Data size.
  1547. @Output pszHistory Export history.
  1548. @Input historyCount History data size.
  1549. @Description Loads the ".POD" data from the source stream; returns the scene
  1550. in pS.
  1551. *****************************************************************************/
  1552. static EPVRTError ReadFromSourceStream(
  1553. CPVRTModelPOD * const pS,
  1554. CSourceStream &src,
  1555. char * const pszExpOpt,
  1556. const size_t count,
  1557. char * const pszHistory,
  1558. const size_t historyCount)
  1559. {
  1560. memset(pS, 0, sizeof(*pS));
  1561. if(!Read(pszExpOpt || pszHistory ? NULL : pS, src, pszExpOpt, count, pszHistory, historyCount))
  1562. return PVR_FAIL;
  1563. if(pS->InitImpl() != PVR_SUCCESS)
  1564. return PVR_FAIL;
  1565. return PVR_SUCCESS;
  1566. }
  1567. /****************************************************************************
  1568. ** Class: CPVRTModelPOD
  1569. ****************************************************************************/
  1570. /*!***************************************************************************
  1571. @Function ReadFromFile
  1572. @Input pszFileName Filename to load
  1573. @Output pszExpOpt String in which to place exporter options
  1574. @Input count Maximum number of characters to store.
  1575. @Output pszHistory String in which to place the pod file history
  1576. @Input historyCount Maximum number of characters to store.
  1577. @Return PVR_SUCCESS if successful, PVR_FAIL if not
  1578. @Description Loads the specified ".POD" file; returns the scene in
  1579. pScene. This structure must later be destroyed with
  1580. PVRTModelPODDestroy() to prevent memory leaks.
  1581. ".POD" files are exported using the PVRGeoPOD exporters.
  1582. If pszExpOpt is NULL, the scene is loaded; otherwise the
  1583. scene is not loaded and pszExpOpt is filled in. The same
  1584. is true for pszHistory.
  1585. *****************************************************************************/
  1586. EPVRTError CPVRTModelPOD::ReadFromFile(
  1587. const char * const pszFileName,
  1588. char * const pszExpOpt,
  1589. const size_t count,
  1590. char * const pszHistory,
  1591. const size_t historyCount)
  1592. {
  1593. CSourceStream src;
  1594. if(!src.Init(pszFileName))
  1595. return PVR_FAIL;
  1596. return ReadFromSourceStream(this, src, pszExpOpt, count, pszHistory, historyCount);
  1597. }
  1598. /*!***************************************************************************
  1599. @Function ReadFromMemory
  1600. @Input pData Data to load
  1601. @Input i32Size Size of data
  1602. @Output pszExpOpt String in which to place exporter options
  1603. @Input count Maximum number of characters to store.
  1604. @Output pszHistory String in which to place the pod file history
  1605. @Input historyCount Maximum number of characters to store.
  1606. @Return PVR_SUCCESS if successful, PVR_FAIL if not
  1607. @Description Loads the supplied pod data. This data can be exported
  1608. directly to a header using one of the pod exporters.
  1609. If pszExpOpt is NULL, the scene is loaded; otherwise the
  1610. scene is not loaded and pszExpOpt is filled in. The same
  1611. is true for pszHistory.
  1612. *****************************************************************************/
  1613. EPVRTError CPVRTModelPOD::ReadFromMemory(
  1614. const char * pData,
  1615. const size_t i32Size,
  1616. char * const pszExpOpt,
  1617. const size_t count,
  1618. char * const pszHistory,
  1619. const size_t historyCount)
  1620. {
  1621. CSourceStream src;
  1622. if(!src.Init(pData, i32Size))
  1623. return PVR_FAIL;
  1624. return ReadFromSourceStream(this, src, pszExpOpt, count, pszHistory, historyCount);
  1625. }
  1626. /*!***************************************************************************
  1627. @Function ReadFromMemory
  1628. @Input scene Scene data from the header file
  1629. @Return PVR_SUCCESS if successful, PVR_FAIL if not
  1630. @Description Sets the scene data from the supplied data structure. Use
  1631. when loading from .H files.
  1632. *****************************************************************************/
  1633. EPVRTError CPVRTModelPOD::ReadFromMemory(
  1634. const SPODScene &scene)
  1635. {
  1636. Destroy();
  1637. memset(this, 0, sizeof(*this));
  1638. *(SPODScene*)this = scene;
  1639. if(InitImpl() != PVR_SUCCESS)
  1640. return PVR_FAIL;
  1641. m_pImpl->bFromMemory = true;
  1642. return PVR_SUCCESS;
  1643. }
  1644. /*!***************************************************************************
  1645. @Function CopyFromMemory
  1646. @Input scene Scene data
  1647. @Return PVR_SUCCESS if successful, PVR_FAIL if not
  1648. @Description Sets the scene data from the supplied data structure.
  1649. *****************************************************************************/
  1650. EPVRTError CPVRTModelPOD::CopyFromMemory(const SPODScene &scene)
  1651. {
  1652. Destroy();
  1653. unsigned int i;
  1654. // SPODScene
  1655. nNumFrame = scene.nNumFrame;
  1656. nFPS = scene.nFPS;
  1657. nFlags = scene.nFlags;
  1658. for(i = 0; i < 3; ++i)
  1659. {
  1660. pfColourBackground[i] = scene.pfColourBackground[i];
  1661. pfColourAmbient[i] = scene.pfColourAmbient[i];
  1662. }
  1663. // Nodes
  1664. if(scene.nNumNode && SafeAlloc(pNode, sizeof(SPODNode) * scene.nNumNode))
  1665. {
  1666. nNumNode = scene.nNumNode;
  1667. nNumMeshNode = scene.nNumMeshNode;
  1668. for(i = 0; i < nNumNode; ++i)
  1669. PVRTModelPODCopyNode(scene.pNode[i], pNode[i], scene.nNumFrame);
  1670. }
  1671. // Meshes
  1672. if(scene.nNumMesh && SafeAlloc(pMesh, sizeof(SPODMesh) * scene.nNumMesh))
  1673. {
  1674. nNumMesh = scene.nNumMesh;
  1675. for(i = 0; i < nNumMesh; ++i)
  1676. PVRTModelPODCopyMesh(scene.pMesh[i], pMesh[i]);
  1677. }
  1678. // Cameras
  1679. if(scene.nNumCamera && SafeAlloc(pCamera, sizeof(SPODCamera) * scene.nNumCamera))
  1680. {
  1681. nNumCamera = scene.nNumCamera;
  1682. for(i = 0; i < nNumCamera; ++i)
  1683. PVRTModelPODCopyCamera(scene.pCamera[i], pCamera[i], scene.nNumFrame);
  1684. }
  1685. // Lights
  1686. if(scene.nNumLight && SafeAlloc(pLight, sizeof(SPODLight) * scene.nNumLight))
  1687. {
  1688. nNumLight = scene.nNumLight;
  1689. for(i = 0; i < nNumLight; ++i)
  1690. PVRTModelPODCopyLight(scene.pLight[i], pLight[i]);
  1691. }
  1692. // Textures
  1693. if(scene.nNumTexture && SafeAlloc(pTexture, sizeof(SPODTexture) * scene.nNumTexture))
  1694. {
  1695. nNumTexture = scene.nNumTexture;
  1696. for(i = 0; i < nNumTexture; ++i)
  1697. PVRTModelPODCopyTexture(scene.pTexture[i], pTexture[i]);
  1698. }
  1699. // Materials
  1700. if(scene.nNumMaterial && SafeAlloc(pMaterial, sizeof(SPODMaterial) * scene.nNumMaterial))
  1701. {
  1702. nNumMaterial = scene.nNumMaterial;
  1703. for(i = 0; i < nNumMaterial; ++i)
  1704. PVRTModelPODCopyMaterial(scene.pMaterial[i], pMaterial[i]);
  1705. }
  1706. if(InitImpl() != PVR_SUCCESS)
  1707. return PVR_FAIL;
  1708. return PVR_SUCCESS;
  1709. }
  1710. #if defined(WIN32) && !defined(__BADA__)
  1711. /*!***************************************************************************
  1712. @Function ReadFromResource
  1713. @Input pszName Name of the resource to load from
  1714. @Return PVR_SUCCESS if successful, PVR_FAIL if not
  1715. @Description Loads the specified ".POD" file; returns the scene in
  1716. pScene. This structure must later be destroyed with
  1717. PVRTModelPODDestroy() to prevent memory leaks.
  1718. ".POD" files are exported from 3D Studio MAX using a
  1719. PowerVR plugin.
  1720. *****************************************************************************/
  1721. EPVRTError CPVRTModelPOD::ReadFromResource(
  1722. const TCHAR * const pszName)
  1723. {
  1724. CSourceResource src;
  1725. if(!src.Init(pszName))
  1726. return PVR_FAIL;
  1727. memset(this, 0, sizeof(*this));
  1728. if(!Read(this, src, NULL, 0, NULL, 0))
  1729. return PVR_FAIL;
  1730. if(InitImpl() != PVR_SUCCESS)
  1731. return PVR_FAIL;
  1732. return PVR_SUCCESS;
  1733. }
  1734. #endif /* WIN32 */
  1735. /*!***********************************************************************
  1736. @Function InitImpl
  1737. @Description Used by the Read*() fns to initialise implementation
  1738. details. Should also be called by applications which
  1739. manually build data in the POD structures for rendering;
  1740. in this case call it after the data has been created.
  1741. Otherwise, do not call this function.
  1742. *************************************************************************/
  1743. EPVRTError CPVRTModelPOD::InitImpl()
  1744. {
  1745. // Allocate space for implementation data
  1746. delete m_pImpl;
  1747. m_pImpl = new SPVRTPODImpl;
  1748. if(!m_pImpl)
  1749. return PVR_FAIL;
  1750. // Zero implementation data
  1751. memset(m_pImpl, 0, sizeof(*m_pImpl));
  1752. #ifdef _DEBUG
  1753. m_pImpl->nWmTotal = 0;
  1754. #endif
  1755. // Allocate world-matrix cache
  1756. m_pImpl->pfCache = new VERTTYPE[nNumNode];
  1757. m_pImpl->pWmCache = new PVRTMATRIX[nNumNode];
  1758. m_pImpl->pWmZeroCache = new PVRTMATRIX[nNumNode];
  1759. FlushCache();
  1760. return PVR_SUCCESS;
  1761. }
  1762. /*!***********************************************************************
  1763. @Function DestroyImpl
  1764. @Description Used to free memory allocated by the implementation.
  1765. *************************************************************************/
  1766. void CPVRTModelPOD::DestroyImpl()
  1767. {
  1768. if(m_pImpl)
  1769. {
  1770. if(m_pImpl->pfCache) delete [] m_pImpl->pfCache;
  1771. if(m_pImpl->pWmCache) delete [] m_pImpl->pWmCache;
  1772. if(m_pImpl->pWmZeroCache) delete [] m_pImpl->pWmZeroCache;
  1773. delete m_pImpl;
  1774. m_pImpl = 0;
  1775. }
  1776. }
  1777. /*!***********************************************************************
  1778. @Function FlushCache
  1779. @Description Clears the matrix cache; use this if necessary when you
  1780. edit the position or animation of a node.
  1781. *************************************************************************/
  1782. void CPVRTModelPOD::FlushCache()
  1783. {
  1784. // Pre-calc frame zero matrices
  1785. SetFrame(0);
  1786. for(unsigned int i = 0; i < nNumNode; ++i)
  1787. GetWorldMatrixNoCache(m_pImpl->pWmZeroCache[i], pNode[i]);
  1788. // Load cache with frame-zero data
  1789. memcpy(m_pImpl->pWmCache, m_pImpl->pWmZeroCache, nNumNode * sizeof(*m_pImpl->pWmCache));
  1790. memset(m_pImpl->pfCache, 0, nNumNode * sizeof(*m_pImpl->pfCache));
  1791. }
  1792. /*!***************************************************************************
  1793. @Function Constructor
  1794. @Description Initializes the pointer to scene data to NULL
  1795. *****************************************************************************/
  1796. CPVRTModelPOD::CPVRTModelPOD() : m_pImpl(NULL)
  1797. {}
  1798. /*!***************************************************************************
  1799. @Function Destructor
  1800. @Description Frees the memory allocated to store the scene in pScene.
  1801. *****************************************************************************/
  1802. CPVRTModelPOD::~CPVRTModelPOD()
  1803. {
  1804. Destroy();
  1805. }
  1806. /*!***************************************************************************
  1807. @Function Destroy
  1808. @Description Frees the memory allocated to store the scene in pScene.
  1809. *****************************************************************************/
  1810. void CPVRTModelPOD::Destroy()
  1811. {
  1812. unsigned int i;
  1813. if(m_pImpl != NULL)
  1814. {
  1815. /*
  1816. Only attempt to free this memory if it was actually allocated at
  1817. run-time, as opposed to compiled into the app.
  1818. */
  1819. if(!m_pImpl->bFromMemory)
  1820. {
  1821. for(i = 0; i < nNumCamera; ++i)
  1822. FREE(pCamera[i].pfAnimFOV);
  1823. FREE(pCamera);
  1824. FREE(pLight);
  1825. for(i = 0; i < nNumMaterial; ++i)
  1826. {
  1827. FREE(pMaterial[i].pszName);
  1828. FREE(pMaterial[i].pszEffectFile);
  1829. FREE(pMaterial[i].pszEffectName);
  1830. }
  1831. FREE(pMaterial);
  1832. for(i = 0; i < nNumMesh; ++i) {
  1833. FREE(pMesh[i].sFaces.pData);
  1834. FREE(pMesh[i].pnStripLength);
  1835. if(pMesh[i].pInterleaved)
  1836. {
  1837. FREE(pMesh[i].pInterleaved);
  1838. }
  1839. else
  1840. {
  1841. FREE(pMesh[i].sVertex.pData);
  1842. FREE(pMesh[i].sNormals.pData);
  1843. FREE(pMesh[i].sTangents.pData);
  1844. FREE(pMesh[i].sBinormals.pData);
  1845. for(unsigned int j = 0; j < pMesh[i].nNumUVW; ++j)
  1846. FREE(pMesh[i].psUVW[j].pData);
  1847. FREE(pMesh[i].sVtxColours.pData);
  1848. FREE(pMesh[i].sBoneIdx.pData);
  1849. FREE(pMesh[i].sBoneWeight.pData);
  1850. }
  1851. FREE(pMesh[i].psUVW);
  1852. pMesh[i].sBoneBatches.Release();
  1853. }
  1854. FREE(pMesh);
  1855. for(i = 0; i < nNumNode; ++i) {
  1856. FREE(pNode[i].pszName);
  1857. FREE(pNode[i].pfAnimPosition);
  1858. FREE(pNode[i].pnAnimPositionIdx);
  1859. FREE(pNode[i].pfAnimRotation);
  1860. FREE(pNode[i].pnAnimRotationIdx);
  1861. FREE(pNode[i].pfAnimScale);
  1862. FREE(pNode[i].pnAnimScaleIdx);
  1863. FREE(pNode[i].pfAnimMatrix);
  1864. FREE(pNode[i].pnAnimMatrixIdx);
  1865. pNode[i].nAnimFlags = 0;
  1866. }
  1867. FREE(pNode);
  1868. for(i = 0; i < nNumTexture; ++i)
  1869. FREE(pTexture[i].pszName);
  1870. FREE(pTexture);
  1871. }
  1872. // Free the working space used by the implementation
  1873. DestroyImpl();
  1874. }
  1875. memset(this, 0, sizeof(*this));
  1876. }
  1877. /*!***************************************************************************
  1878. @Function SetFrame
  1879. @Input fFrame Frame number
  1880. @Description Set the animation frame for which subsequent Get*() calls
  1881. should return data.
  1882. *****************************************************************************/
  1883. void CPVRTModelPOD::SetFrame(const VERTTYPE fFrame)
  1884. {
  1885. if(nNumFrame) {
  1886. /*
  1887. Limit animation frames.
  1888. Example: If there are 100 frames of animation, the highest frame
  1889. number allowed is 98, since that will blend between frames 98 and
  1890. 99. (99 being of course the 100th frame.)
  1891. */
  1892. _ASSERT(fFrame <= f2vt((float)(nNumFrame-1)));
  1893. m_pImpl->nFrame = (int)vt2f(fFrame);
  1894. m_pImpl->fBlend = fFrame - f2vt(m_pImpl->nFrame);
  1895. }
  1896. else
  1897. {
  1898. m_pImpl->fBlend = 0;
  1899. m_pImpl->nFrame = 0;
  1900. }
  1901. m_pImpl->fFrame = fFrame;
  1902. }
  1903. /*!***************************************************************************
  1904. @Function GetRotationMatrix
  1905. @Output mOut Rotation matrix
  1906. @Input node Node to get the rotation matrix from
  1907. @Description Generates the world matrix for the given Mesh Instance;
  1908. applies the parent's transform too. Uses animation data.
  1909. *****************************************************************************/
  1910. void CPVRTModelPOD::GetRotationMatrix(
  1911. PVRTMATRIX &mOut,
  1912. const SPODNode &node) const
  1913. {
  1914. PVRTQUATERNION q;
  1915. if(node.pfAnimRotation)
  1916. {
  1917. if(node.nAnimFlags & ePODHasRotationAni)
  1918. {
  1919. if(node.pnAnimRotationIdx)
  1920. {
  1921. PVRTMatrixQuaternionSlerp(
  1922. q,
  1923. (PVRTQUATERNION&)node.pfAnimRotation[node.pnAnimRotationIdx[m_pImpl->nFrame]],
  1924. (PVRTQUATERNION&)node.pfAnimRotation[node.pnAnimRotationIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
  1925. }
  1926. else
  1927. {
  1928. PVRTMatrixQuaternionSlerp(
  1929. q,
  1930. (PVRTQUATERNION&)node.pfAnimRotation[4*m_pImpl->nFrame],
  1931. (PVRTQUATERNION&)node.pfAnimRotation[4*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
  1932. }
  1933. PVRTMatrixRotationQuaternion(mOut, q);
  1934. }
  1935. else
  1936. {
  1937. PVRTMatrixRotationQuaternion(mOut, *(PVRTQUATERNION*)node.pfAnimRotation);
  1938. }
  1939. }
  1940. else
  1941. {
  1942. PVRTMatrixIdentity(mOut);
  1943. }
  1944. }
  1945. /*!***************************************************************************
  1946. @Function GetRotationMatrix
  1947. @Input node Node to get the rotation matrix from
  1948. @Returns Rotation matrix
  1949. @Description Generates the world matrix for the given Mesh Instance;
  1950. applies the parent's transform too. Uses animation data.
  1951. *****************************************************************************/
  1952. PVRTMat4 CPVRTModelPOD::GetRotationMatrix(const SPODNode &node) const
  1953. {
  1954. PVRTMat4 mOut;
  1955. GetRotationMatrix(mOut,node);
  1956. return mOut;
  1957. }
  1958. /*!***************************************************************************
  1959. @Function GetScalingMatrix
  1960. @Output mOut Scaling matrix
  1961. @Input node Node to get the rotation matrix from
  1962. @Description Generates the world matrix for the given Mesh Instance;
  1963. applies the parent's transform too. Uses animation data.
  1964. *****************************************************************************/
  1965. void CPVRTModelPOD::GetScalingMatrix(
  1966. PVRTMATRIX &mOut,
  1967. const SPODNode &node) const
  1968. {
  1969. PVRTVECTOR3 v;
  1970. if(node.pfAnimScale)
  1971. {
  1972. if(node.nAnimFlags & ePODHasScaleAni)
  1973. {
  1974. if(node.pnAnimScaleIdx)
  1975. {
  1976. PVRTMatrixVec3Lerp(
  1977. v,
  1978. (PVRTVECTOR3&)node.pfAnimScale[node.pnAnimScaleIdx[m_pImpl->nFrame+0]],
  1979. (PVRTVECTOR3&)node.pfAnimScale[node.pnAnimScaleIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
  1980. }
  1981. else
  1982. {
  1983. PVRTMatrixVec3Lerp(
  1984. v,
  1985. (PVRTVECTOR3&)node.pfAnimScale[7*(m_pImpl->nFrame+0)],
  1986. (PVRTVECTOR3&)node.pfAnimScale[7*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
  1987. }
  1988. PVRTMatrixScaling(mOut, v.x, v.y, v.z);
  1989. }
  1990. else
  1991. {
  1992. PVRTMatrixScaling(mOut, node.pfAnimScale[0], node.pfAnimScale[1], node.pfAnimScale[2]);
  1993. }
  1994. }
  1995. else
  1996. {
  1997. PVRTMatrixIdentity(mOut);
  1998. }
  1999. }
  2000. /*!***************************************************************************
  2001. @Function GetScalingMatrix
  2002. @Input node Node to get the rotation matrix from
  2003. @Returns Scaling matrix
  2004. @Description Generates the world matrix for the given Mesh Instance;
  2005. applies the parent's transform too. Uses animation data.
  2006. *****************************************************************************/
  2007. PVRTMat4 CPVRTModelPOD::GetScalingMatrix(const SPODNode &node) const
  2008. {
  2009. PVRTMat4 mOut;
  2010. GetScalingMatrix(mOut, node);
  2011. return mOut;
  2012. }
  2013. /*!***************************************************************************
  2014. @Function GetTranslation
  2015. @Output V Translation vector
  2016. @Input node Node to get the translation vector from
  2017. @Description Generates the translation vector for the given Mesh
  2018. Instance. Uses animation data.
  2019. *****************************************************************************/
  2020. void CPVRTModelPOD::GetTranslation(
  2021. PVRTVECTOR3 &V,
  2022. const SPODNode &node) const
  2023. {
  2024. if(node.pfAnimPosition)
  2025. {
  2026. if(node.nAnimFlags & ePODHasPositionAni)
  2027. {
  2028. if(node.pnAnimPositionIdx)
  2029. {
  2030. PVRTMatrixVec3Lerp(V,
  2031. (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+0]],
  2032. (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
  2033. }
  2034. else
  2035. {
  2036. PVRTMatrixVec3Lerp(V,
  2037. (PVRTVECTOR3&)node.pfAnimPosition[3 * (m_pImpl->nFrame+0)],
  2038. (PVRTVECTOR3&)node.pfAnimPosition[3 * (m_pImpl->nFrame+1)], m_pImpl->fBlend);
  2039. }
  2040. }
  2041. else
  2042. {
  2043. V = *(PVRTVECTOR3*) node.pfAnimPosition;
  2044. }
  2045. }
  2046. else
  2047. {
  2048. _ASSERT(false);
  2049. }
  2050. }
  2051. /*!***************************************************************************
  2052. @Function GetTranslation
  2053. @Input node Node to get the translation vector from
  2054. @Returns Translation vector
  2055. @Description Generates the translation vector for the given Mesh
  2056. Instance. Uses animation data.
  2057. *****************************************************************************/
  2058. PVRTVec3 CPVRTModelPOD::GetTranslation(const SPODNode &node) const
  2059. {
  2060. PVRTVec3 vOut;
  2061. GetTranslation(vOut, node);
  2062. return vOut;
  2063. }
  2064. /*!***************************************************************************
  2065. @Function GetTranslationMatrix
  2066. @Output mOut Translation matrix
  2067. @Input node Node to get the translation matrix from
  2068. @Description Generates the world matrix for the given Mesh Instance;
  2069. applies the parent's transform too. Uses animation data.
  2070. *****************************************************************************/
  2071. void CPVRTModelPOD::GetTranslationMatrix(
  2072. PVRTMATRIX &mOut,
  2073. const SPODNode &node) const
  2074. {
  2075. PVRTVECTOR3 v;
  2076. if(node.pfAnimPosition)
  2077. {
  2078. if(node.nAnimFlags & ePODHasPositionAni)
  2079. {
  2080. if(node.pnAnimPositionIdx)
  2081. {
  2082. PVRTMatrixVec3Lerp(v,
  2083. (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+0]],
  2084. (PVRTVECTOR3&)node.pfAnimPosition[node.pnAnimPositionIdx[m_pImpl->nFrame+1]], m_pImpl->fBlend);
  2085. }
  2086. else
  2087. {
  2088. PVRTMatrixVec3Lerp(v,
  2089. (PVRTVECTOR3&)node.pfAnimPosition[3*(m_pImpl->nFrame+0)],
  2090. (PVRTVECTOR3&)node.pfAnimPosition[3*(m_pImpl->nFrame+1)], m_pImpl->fBlend);
  2091. }
  2092. PVRTMatrixTranslation(mOut, v.x, v.y, v.z);
  2093. }
  2094. else
  2095. {
  2096. PVRTMatrixTranslation(mOut, node.pfAnimPosition[0], node.pfAnimPosition[1], node.pfAnimPosition[2]);
  2097. }
  2098. }
  2099. else
  2100. {
  2101. PVRTMatrixIdentity(mOut);
  2102. }
  2103. }
  2104. /*!***************************************************************************
  2105. @Function GetTranslationMatrix
  2106. @Input node Node to get the translation matrix from
  2107. @Returns Translation matrix
  2108. @Description Generates the world matrix for the given Mesh Instance;
  2109. applies the parent's transform too. Uses animation data.
  2110. *****************************************************************************/
  2111. PVRTMat4 CPVRTModelPOD::GetTranslationMatrix(const SPODNode &node) const
  2112. {
  2113. PVRTMat4 mOut;
  2114. GetTranslationMatrix(mOut, node);
  2115. return mOut;
  2116. }
  2117. /*!***************************************************************************
  2118. @Function GetTransformationMatrix
  2119. @Output mOut Transformation matrix
  2120. @Input node Node to get the transformation matrix from
  2121. @Description Generates the world matrix for the given Mesh Instance;
  2122. applies the parent's transform too. Uses animation data.
  2123. *****************************************************************************/
  2124. void CPVRTModelPOD::GetTransformationMatrix(PVRTMATRIX &mOut, const SPODNode &node) const
  2125. {
  2126. if(node.pfAnimMatrix)
  2127. {
  2128. if(node.nAnimFlags & ePODHasMatrixAni)
  2129. {
  2130. if(node.pnAnimMatrixIdx)
  2131. mOut = *((PVRTMATRIX*) &node.pfAnimMatrix[node.pnAnimMatrixIdx[m_pImpl->nFrame]]);
  2132. else
  2133. mOut = *((PVRTMATRIX*) &node.pfAnimMatrix[16*m_pImpl->nFrame]);
  2134. }
  2135. else
  2136. {
  2137. mOut = *((PVRTMATRIX*) node.pfAnimMatrix);
  2138. }
  2139. }
  2140. else
  2141. {
  2142. PVRTMatrixIdentity(mOut);
  2143. }
  2144. }
  2145. /*!***************************************************************************
  2146. @Function GetWorldMatrixNoCache
  2147. @Output mOut World matrix
  2148. @Input node Node to get the world matrix from
  2149. @Description Generates the world matrix for the given Mesh Instance;
  2150. applies the parent's transform too. Uses animation data.
  2151. *****************************************************************************/
  2152. void CPVRTModelPOD::GetWorldMatrixNoCache(
  2153. PVRTMATRIX &mOut,
  2154. const SPODNode &node) const
  2155. {
  2156. PVRTMATRIX mTmp;
  2157. if(node.pfAnimMatrix) // The transformations are stored as matrices
  2158. GetTransformationMatrix(mOut, node);
  2159. else
  2160. {
  2161. // Scale
  2162. GetScalingMatrix(mOut, node);
  2163. // Rotation
  2164. GetRotationMatrix(mTmp, node);
  2165. PVRTMatrixMultiply(mOut, mOut, mTmp);
  2166. // Translation
  2167. GetTranslationMatrix(mTmp, node);
  2168. PVRTMatrixMultiply(mOut, mOut, mTmp);
  2169. }
  2170. // Do we have to worry about a parent?
  2171. if(node.nIdxParent < 0)
  2172. return;
  2173. // Apply parent's transform too.
  2174. GetWorldMatrixNoCache(mTmp, pNode[node.nIdxParent]);
  2175. PVRTMatrixMultiply(mOut, mOut, mTmp);
  2176. }
  2177. /*!***************************************************************************
  2178. @Function GetWorldMatrixNoCache
  2179. @Input node Node to get the world matrix from
  2180. @Returns World matrix
  2181. @Description Generates the world matrix for the given Mesh Instance;
  2182. applies the parent's transform too. Uses animation data.
  2183. *****************************************************************************/
  2184. PVRTMat4 CPVRTModelPOD::GetWorldMatrixNoCache(const SPODNode& node) const
  2185. {
  2186. PVRTMat4 mWorld;
  2187. GetWorldMatrixNoCache(mWorld,node);
  2188. return mWorld;
  2189. }
  2190. /*!***************************************************************************
  2191. @Function GetWorldMatrix
  2192. @Output mOut World matrix
  2193. @Input node Node to get the world matrix from
  2194. @Description Generates the world matrix for the given Mesh Instance;
  2195. applies the parent's transform too. Uses animation data.
  2196. *****************************************************************************/
  2197. void CPVRTModelPOD::GetWorldMatrix(
  2198. PVRTMATRIX &mOut,
  2199. const SPODNode &node) const
  2200. {
  2201. unsigned int nIdx;
  2202. #ifdef _DEBUG
  2203. ++m_pImpl->nWmTotal;
  2204. m_pImpl->fHitPerc = (float)m_pImpl->nWmCacheHit / (float)m_pImpl->nWmTotal;
  2205. m_pImpl->fHitPercZero = (float)m_pImpl->nWmZeroCacheHit / (float)m_pImpl->nWmTotal;
  2206. #endif
  2207. // Calculate a node index
  2208. nIdx = (unsigned int)(&node - pNode);
  2209. // There is a dedicated cache for frame 0 data
  2210. if(m_pImpl->fFrame == 0)
  2211. {
  2212. mOut = m_pImpl->pWmZeroCache[nIdx];
  2213. #ifdef _DEBUG
  2214. ++m_pImpl->nWmZeroCacheHit;
  2215. #endif
  2216. return;
  2217. }
  2218. // Has this matrix been calculated & cached?
  2219. if(m_pImpl->fFrame == m_pImpl->pfCache[nIdx])
  2220. {
  2221. mOut = m_pImpl->pWmCache[nIdx];
  2222. #ifdef _DEBUG
  2223. ++m_pImpl->nWmCacheHit;
  2224. #endif
  2225. return;
  2226. }
  2227. GetWorldMatrixNoCache(mOut, node);
  2228. // Cache the matrix
  2229. m_pImpl->pfCache[nIdx] = m_pImpl->fFrame;
  2230. m_pImpl->pWmCache[nIdx] = mOut;
  2231. }
  2232. /*!***************************************************************************
  2233. @Function GetWorldMatrix
  2234. @Input node Node to get the world matrix from
  2235. @Returns World matrix
  2236. @Description Generates the world matrix for the given Mesh Instance;
  2237. applies the parent's transform too. Uses animation data.
  2238. *****************************************************************************/
  2239. PVRTMat4 CPVRTModelPOD::GetWorldMatrix(const SPODNode& node) const
  2240. {
  2241. PVRTMat4 mWorld;
  2242. GetWorldMatrix(mWorld,node);
  2243. return mWorld;
  2244. }
  2245. /*!***************************************************************************
  2246. @Function GetBoneWorldMatrix
  2247. @Output mOut Bone world matrix
  2248. @Input NodeMesh Mesh to take the bone matrix from
  2249. @Input NodeBone Bone to take the matrix from
  2250. @Description Generates the world matrix for the given bone.
  2251. *****************************************************************************/
  2252. void CPVRTModelPOD::GetBoneWorldMatrix(
  2253. PVRTMATRIX &mOut,
  2254. const SPODNode &NodeMesh,
  2255. const SPODNode &NodeBone)
  2256. {
  2257. PVRTMATRIX mTmp;
  2258. VERTTYPE fFrame;
  2259. fFrame = m_pImpl->fFrame;
  2260. SetFrame(0);
  2261. // Transform by object matrix
  2262. GetWorldMatrix(mOut, NodeMesh);
  2263. // Back transform bone from frame 0 position
  2264. GetWorldMatrix(mTmp, NodeBone);
  2265. PVRTMatrixInverse(mTmp, mTmp);
  2266. PVRTMatrixMultiply(mOut, mOut, mTmp);
  2267. // The bone origin should now be at the origin
  2268. SetFrame(fFrame);
  2269. // Transform bone into frame fFrame position
  2270. GetWorldMatrix(mTmp, NodeBone);
  2271. PVRTMatrixMultiply(mOut, mOut, mTmp);
  2272. }
  2273. /*!***************************************************************************
  2274. @Function GetBoneWorldMatrix
  2275. @Input NodeMesh Mesh to take the bone matrix from
  2276. @Input NodeBone Bone to take the matrix from
  2277. @Returns Bone world matrix
  2278. @Description Generates the world matrix for the given bone.
  2279. *****************************************************************************/
  2280. PVRTMat4 CPVRTModelPOD::GetBoneWorldMatrix(
  2281. const SPODNode &NodeMesh,
  2282. const SPODNode &NodeBone)
  2283. {
  2284. PVRTMat4 mOut;
  2285. GetBoneWorldMatrix(mOut,NodeMesh,NodeBone);
  2286. return mOut;
  2287. }
  2288. /*!***************************************************************************
  2289. @Function GetCamera
  2290. @Output vFrom Position of the camera
  2291. @Output vTo Target of the camera
  2292. @Output vUp Up direction of the camera
  2293. @Input nIdx Camera number
  2294. @Return Camera horizontal FOV
  2295. @Description Calculate the From, To and Up vectors for the given
  2296. camera. Uses animation data.
  2297. Note that even if the camera has a target, *pvTo is not
  2298. the position of that target. *pvTo is a position in the
  2299. correct direction of the target, one unit away from the
  2300. camera.
  2301. *****************************************************************************/
  2302. VERTTYPE CPVRTModelPOD::GetCamera(
  2303. PVRTVECTOR3 &vFrom,
  2304. PVRTVECTOR3 &vTo,
  2305. PVRTVECTOR3 &vUp,
  2306. const unsigned int nIdx) const
  2307. {
  2308. PVRTMATRIX mTmp;
  2309. VERTTYPE *pfData;
  2310. SPODCamera *pCam;
  2311. const SPODNode *pNd;
  2312. _ASSERT(nIdx < nNumCamera);
  2313. // Camera nodes are after the mesh and light nodes in the array
  2314. pNd = &pNode[nNumMeshNode + nNumLight + nIdx];
  2315. pCam = &pCamera[pNd->nIdx];
  2316. GetWorldMatrix(mTmp, *pNd);
  2317. // View position is 0,0,0,1 transformed by world matrix
  2318. vFrom.x = mTmp.f[12];
  2319. vFrom.y = mTmp.f[13];
  2320. vFrom.z = mTmp.f[14];
  2321. // View direction is 0,-1,0,1 transformed by world matrix
  2322. vTo.x = -mTmp.f[4] + mTmp.f[12];
  2323. vTo.y = -mTmp.f[5] + mTmp.f[13];
  2324. vTo.z = -mTmp.f[6] + mTmp.f[14];
  2325. #if defined(BUILD_DX9) || defined(BUILD_DX10)
  2326. /*
  2327. When you rotate the camera from "straight forward" to "straight down", in
  2328. D3D the UP vector will be [0, 0, 1]
  2329. */
  2330. vUp.x = mTmp.f[ 8];
  2331. vUp.y = mTmp.f[ 9];
  2332. vUp.z = mTmp.f[10];
  2333. #endif
  2334. #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
  2335. /*
  2336. When you rotate the camera from "straight forward" to "straight down", in
  2337. OpenGL the UP vector will be [0, 0, -1]
  2338. */
  2339. vUp.x = -mTmp.f[ 8];
  2340. vUp.y = -mTmp.f[ 9];
  2341. vUp.z = -mTmp.f[10];
  2342. #endif
  2343. /*
  2344. Find & calculate FOV value
  2345. */
  2346. if(pCam->pfAnimFOV) {
  2347. pfData = &pCam->pfAnimFOV[m_pImpl->nFrame];
  2348. return pfData[0] + m_pImpl->fBlend * (pfData[1] - pfData[0]);
  2349. } else {
  2350. return pCam->fFOV;
  2351. }
  2352. }
  2353. /*!***************************************************************************
  2354. @Function GetCameraPos
  2355. @Output vFrom Position of the camera
  2356. @Output vTo Target of the camera
  2357. @Input nIdx Camera number
  2358. @Return Camera horizontal FOV
  2359. @Description Calculate the position of the camera and its target. Uses
  2360. animation data.
  2361. If the queried camera does not have a target, *pvTo is
  2362. not changed.
  2363. *****************************************************************************/
  2364. VERTTYPE CPVRTModelPOD::GetCameraPos(
  2365. PVRTVECTOR3 &vFrom,
  2366. PVRTVECTOR3 &vTo,
  2367. const unsigned int nIdx) const
  2368. {
  2369. PVRTMATRIX mTmp;
  2370. VERTTYPE *pfData;
  2371. SPODCamera *pCam;
  2372. const SPODNode *pNd;
  2373. _ASSERT(nIdx < nNumCamera);
  2374. // Camera nodes are after the mesh and light nodes in the array
  2375. pNd = &pNode[nNumMeshNode + nNumLight + nIdx];
  2376. // View position is 0,0,0,1 transformed by world matrix
  2377. GetWorldMatrix(mTmp, *pNd);
  2378. vFrom.x = mTmp.f[12];
  2379. vFrom.y = mTmp.f[13];
  2380. vFrom.z = mTmp.f[14];
  2381. pCam = &pCamera[pNd->nIdx];
  2382. if(pCam->nIdxTarget >= 0)
  2383. {
  2384. // View position is 0,0,0,1 transformed by world matrix
  2385. GetWorldMatrix(mTmp, pNode[pCam->nIdxTarget]);
  2386. vTo.x = mTmp.f[12];
  2387. vTo.y = mTmp.f[13];
  2388. vTo.z = mTmp.f[14];
  2389. }
  2390. /*
  2391. Find & calculate FOV value
  2392. */
  2393. if(pCam->pfAnimFOV) {
  2394. pfData = &pCam->pfAnimFOV[m_pImpl->nFrame];
  2395. return pfData[0] + m_pImpl->fBlend * (pfData[1] - pfData[0]);
  2396. } else {
  2397. return pCam->fFOV;
  2398. }
  2399. }
  2400. /*!***************************************************************************
  2401. @Function GetLight
  2402. @Output vPos Position of the light
  2403. @Output vDir Direction of the light
  2404. @Input nIdx Light number
  2405. @Description Calculate the position and direction of the given Light.
  2406. Uses animation data.
  2407. *****************************************************************************/
  2408. void CPVRTModelPOD::GetLight(
  2409. PVRTVECTOR3 &vPos,
  2410. PVRTVECTOR3 &vDir,
  2411. const unsigned int nIdx) const
  2412. {
  2413. PVRTMATRIX mTmp;
  2414. const SPODNode *pNd;
  2415. _ASSERT(nIdx < nNumLight);
  2416. // Light nodes are after the mesh nodes in the array
  2417. pNd = &pNode[nNumMeshNode + nIdx];
  2418. GetWorldMatrix(mTmp, *pNd);
  2419. // View position is 0,0,0,1 transformed by world matrix
  2420. vPos.x = mTmp.f[12];
  2421. vPos.y = mTmp.f[13];
  2422. vPos.z = mTmp.f[14];
  2423. // View direction is 0,-1,0,0 transformed by world matrix
  2424. vDir.x = -mTmp.f[4];
  2425. vDir.y = -mTmp.f[5];
  2426. vDir.z = -mTmp.f[6];
  2427. }
  2428. /*!***************************************************************************
  2429. @Function GetLightPositon
  2430. @Input u32Idx Light number
  2431. @Return PVRTVec4 position of light with w set correctly
  2432. @Description Calculates the position of the given light. Uses animation data
  2433. *****************************************************************************/
  2434. PVRTVec4 CPVRTModelPOD::GetLightPosition(const unsigned int u32Idx) const
  2435. { // TODO: make this a real function instead of just wrapping GetLight()
  2436. PVRTVec3 vPos, vDir;
  2437. GetLight(vPos,vDir,u32Idx);
  2438. _ASSERT(u32Idx < nNumLight);
  2439. _ASSERT(pLight[u32Idx].eType!=ePODDirectional);
  2440. return PVRTVec4(vPos,1);
  2441. }
  2442. /*!***************************************************************************
  2443. @Function GetLightDirection
  2444. @Input u32Idx Light number
  2445. @Return PVRTVec4 direction of light with w set correctly
  2446. @Description Calculate the direction of the given Light. Uses animation data.
  2447. *****************************************************************************/
  2448. PVRTVec4 CPVRTModelPOD::GetLightDirection(const unsigned int u32Idx) const
  2449. { // TODO: make this a real function instead of just wrapping GetLight()
  2450. PVRTVec3 vPos, vDir;
  2451. GetLight(vPos,vDir,u32Idx);
  2452. _ASSERT(u32Idx < nNumLight);
  2453. _ASSERT(pLight[u32Idx].eType!=ePODPoint);
  2454. return PVRTVec4(vDir,0);
  2455. }
  2456. /*!***************************************************************************
  2457. @Function CreateSkinIdxWeight
  2458. @Output pIdx Four bytes containing matrix indices for vertex (0..255) (D3D: use UBYTE4)
  2459. @Output pWeight Four bytes containing blend weights for vertex (0.0 .. 1.0) (D3D: use D3DCOLOR)
  2460. @Input nVertexBones Number of bones this vertex uses
  2461. @Input pnBoneIdx Pointer to 'nVertexBones' indices
  2462. @Input pfBoneWeight Pointer to 'nVertexBones' blend weights
  2463. @Description Creates the matrix indices and blend weights for a boned
  2464. vertex. Call once per vertex of a boned mesh.
  2465. *****************************************************************************/
  2466. EPVRTError CPVRTModelPOD::CreateSkinIdxWeight(
  2467. char * const pIdx, // Four bytes containing matrix indices for vertex (0..255) (D3D: use UBYTE4)
  2468. char * const pWeight, // Four bytes containing blend weights for vertex (0.0 .. 1.0) (D3D: use D3DCOLOR)
  2469. const int nVertexBones, // Number of bones this vertex uses
  2470. const int * const pnBoneIdx, // Pointer to 'nVertexBones' indices
  2471. const VERTTYPE * const pfBoneWeight) // Pointer to 'nVertexBones' blend weights
  2472. {
  2473. int i, nSum;
  2474. int nIdx[4];
  2475. int nWeight[4];
  2476. for(i = 0; i < nVertexBones; ++i)
  2477. {
  2478. nIdx[i] = pnBoneIdx[i];
  2479. nWeight[i] = (int)vt2f((VERTTYPEMUL(f2vt(255.0f), pfBoneWeight[i])));
  2480. if(nIdx[i] > 255)
  2481. {
  2482. PVRTErrorOutputDebug("Too many bones (highest index is 255).\n");
  2483. return PVR_FAIL;
  2484. }
  2485. nWeight[i] = PVRT_MAX(nWeight[i], 0);
  2486. nWeight[i] = PVRT_MIN(nWeight[i], 255);
  2487. }
  2488. for(; i < 4; ++i)
  2489. {
  2490. nIdx[i] = 0;
  2491. nWeight[i] = 0;
  2492. }
  2493. if(nVertexBones)
  2494. {
  2495. // It's important the weights sum to 1
  2496. nSum = 0;
  2497. for(i = 0; i < 4; ++i)
  2498. nSum += nWeight[i];
  2499. if(!nSum)
  2500. return PVR_FAIL;
  2501. _ASSERT(nSum <= 255);
  2502. i = 0;
  2503. while(nSum < 255)
  2504. {
  2505. if(nWeight[i]) {
  2506. ++nWeight[i];
  2507. ++nSum;
  2508. }
  2509. if(++i > 3)
  2510. i = 0;
  2511. }
  2512. _ASSERT(nSum == 255);
  2513. }
  2514. #if defined(BUILD_DX9)
  2515. *(unsigned int*)pIdx = D3DCOLOR_ARGB(nIdx[3], nIdx[2], nIdx[1], nIdx[0]); // UBYTE4 is WZYX
  2516. *(unsigned int*)pWeight = D3DCOLOR_RGBA(nWeight[0], nWeight[1], nWeight[2], nWeight[3]); // D3DCOLORs are WXYZ
  2517. #endif
  2518. #if defined(BUILD_DX10)
  2519. *(unsigned int*)pIdx = D3DXCOLOR((float)nIdx[3], (float)nIdx[2],(float) nIdx[1], (float)nIdx[0]); //
  2520. *(unsigned int*)pWeight = D3DXCOLOR((float)nWeight[0], (float)nWeight[1], (float)nWeight[2], (float)nWeight[3]); //
  2521. #endif
  2522. #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
  2523. // Return indices and weights as bytes
  2524. for(i = 0; i < 4; ++i)
  2525. {
  2526. pIdx[i] = (char) nIdx[i];
  2527. pWeight[i] = (char) nWeight[i];
  2528. }
  2529. #endif
  2530. return PVR_SUCCESS;
  2531. }
  2532. /*!***************************************************************************
  2533. @Function SavePOD
  2534. @Input pszFilename Filename to save to
  2535. @Input pszExpOpt A string containing the options used by the exporter
  2536. @Description Save a binary POD file (.POD).
  2537. *****************************************************************************/
  2538. EPVRTError CPVRTModelPOD::SavePOD(const char * const pszFilename, const char * const pszExpOpt, const char * const pszHistory)
  2539. {
  2540. FILE *pFile;
  2541. bool bRet;
  2542. pFile = fopen(pszFilename, "wb+");
  2543. if(!pFile)
  2544. return PVR_FAIL;
  2545. bRet = WritePOD(pFile, pszExpOpt, pszHistory, *this);
  2546. // Done
  2547. fclose(pFile);
  2548. return bRet ? PVR_SUCCESS : PVR_FAIL;
  2549. }
  2550. /*!***************************************************************************
  2551. @Function PVRTModelPODDataTypeSize
  2552. @Input type Type to get the size of
  2553. @Return Size of the data element
  2554. @Description Returns the size of each data element.
  2555. *****************************************************************************/
  2556. size_t PVRTModelPODDataTypeSize(const EPVRTDataType type)
  2557. {
  2558. switch(type)
  2559. {
  2560. default:
  2561. _ASSERT(false);
  2562. return 0;
  2563. case EPODDataFloat:
  2564. return sizeof(float);
  2565. case EPODDataInt:
  2566. case EPODDataUnsignedInt:
  2567. return sizeof(int);
  2568. case EPODDataShort:
  2569. case EPODDataShortNorm:
  2570. case EPODDataUnsignedShort:
  2571. case EPODDataUnsignedShortNorm:
  2572. return sizeof(unsigned short);
  2573. case EPODDataRGBA:
  2574. return sizeof(unsigned int);
  2575. case EPODDataARGB:
  2576. return sizeof(unsigned int);
  2577. case EPODDataD3DCOLOR:
  2578. return sizeof(unsigned int);
  2579. case EPODDataUBYTE4:
  2580. return sizeof(unsigned int);
  2581. case EPODDataDEC3N:
  2582. return sizeof(unsigned int);
  2583. case EPODDataFixed16_16:
  2584. return sizeof(unsigned int);
  2585. case EPODDataUnsignedByte:
  2586. case EPODDataUnsignedByteNorm:
  2587. case EPODDataByte:
  2588. case EPODDataByteNorm:
  2589. return sizeof(unsigned char);
  2590. }
  2591. }
  2592. /*!***************************************************************************
  2593. @Function PVRTModelPODDataTypeComponentCount
  2594. @Input type Type to get the number of components from
  2595. @Return number of components in the data element
  2596. @Description Returns the number of components in a data element.
  2597. *****************************************************************************/
  2598. size_t PVRTModelPODDataTypeComponentCount(const EPVRTDataType type)
  2599. {
  2600. switch(type)
  2601. {
  2602. default:
  2603. _ASSERT(false);
  2604. return 0;
  2605. case EPODDataFloat:
  2606. case EPODDataInt:
  2607. case EPODDataUnsignedInt:
  2608. case EPODDataShort:
  2609. case EPODDataShortNorm:
  2610. case EPODDataUnsignedShort:
  2611. case EPODDataUnsignedShortNorm:
  2612. case EPODDataFixed16_16:
  2613. case EPODDataByte:
  2614. case EPODDataByteNorm:
  2615. case EPODDataUnsignedByte:
  2616. case EPODDataUnsignedByteNorm:
  2617. return 1;
  2618. case EPODDataDEC3N:
  2619. return 3;
  2620. case EPODDataRGBA:
  2621. case EPODDataARGB:
  2622. case EPODDataD3DCOLOR:
  2623. case EPODDataUBYTE4:
  2624. return 4;
  2625. }
  2626. }
  2627. /*!***************************************************************************
  2628. @Function PVRTModelPODDataStride
  2629. @Input data Data elements
  2630. @Return Size of the vector elements
  2631. @Description Returns the size of the vector of data elements.
  2632. *****************************************************************************/
  2633. size_t PVRTModelPODDataStride(const CPODData &data)
  2634. {
  2635. return PVRTModelPODDataTypeSize(data.eType) * data.n;
  2636. }
  2637. /*!***************************************************************************
  2638. @Function PVRTModelPODDataConvert
  2639. @Modified data Data elements to convert
  2640. @Input eNewType New type of elements
  2641. @Input nCnt Number of elements
  2642. @Description Convert the format of the array of vectors.
  2643. *****************************************************************************/
  2644. void PVRTModelPODDataConvert(CPODData &data, const unsigned int nCnt, const EPVRTDataType eNewType)
  2645. {
  2646. PVRTVECTOR4f v;
  2647. unsigned int i;
  2648. CPODData old;
  2649. if(!data.pData || data.eType == eNewType)
  2650. return;
  2651. old = data;
  2652. switch(eNewType)
  2653. {
  2654. case EPODDataFloat:
  2655. case EPODDataInt:
  2656. case EPODDataUnsignedInt:
  2657. case EPODDataUnsignedShort:
  2658. case EPODDataUnsignedShortNorm:
  2659. case EPODDataFixed16_16:
  2660. case EPODDataUnsignedByte:
  2661. case EPODDataUnsignedByteNorm:
  2662. case EPODDataShort:
  2663. case EPODDataShortNorm:
  2664. case EPODDataByte:
  2665. case EPODDataByteNorm:
  2666. data.n = old.n * PVRTModelPODDataTypeComponentCount(old.eType);
  2667. break;
  2668. case EPODDataRGBA:
  2669. case EPODDataARGB:
  2670. case EPODDataD3DCOLOR:
  2671. case EPODDataUBYTE4:
  2672. case EPODDataDEC3N:
  2673. data.n = 1;
  2674. break;
  2675. default:
  2676. _ASSERT(false); // unrecognised type
  2677. break;
  2678. }
  2679. data.eType = eNewType;
  2680. data.nStride = (unsigned int)PVRTModelPODDataStride(data);
  2681. // If the old & new strides are identical, we can convert it in place
  2682. if(old.nStride != data.nStride)
  2683. {
  2684. data.pData = (unsigned char*)malloc(data.nStride * nCnt);
  2685. }
  2686. for(i = 0; i < nCnt; ++i)
  2687. {
  2688. PVRTVertexRead(&v, old.pData + i * old.nStride, old.eType, old.n);
  2689. PVRTVertexWrite(data.pData + i * data.nStride, eNewType, data.n * PVRTModelPODDataTypeComponentCount(data.eType), &v);
  2690. }
  2691. if(old.nStride != data.nStride)
  2692. {
  2693. FREE(old.pData);
  2694. }
  2695. }
  2696. /*!***************************************************************************
  2697. @Function PVRTModelPODScaleAndConvertVtxData
  2698. @Modified mesh POD mesh to scale and convert the mesh data
  2699. @Input eNewType The data type to scale and convert the vertex data to
  2700. @Return PVR_SUCCESS on success and PVR_FAIL on failure.
  2701. @Description Scales the vertex data to fit within the range of the requested
  2702. data type and then converts the data to that type. This function
  2703. isn't currently compiled in for fixed point builds of the tools.
  2704. *****************************************************************************/
  2705. #if !defined(PVRT_FIXED_POINT_ENABLE)
  2706. EPVRTError PVRTModelPODScaleAndConvertVtxData(SPODMesh &mesh, const EPVRTDataType eNewType)
  2707. {
  2708. // Initialise the matrix to identity
  2709. PVRTMatrixIdentity(mesh.mUnpackMatrix);
  2710. // No vertices to process
  2711. if(!mesh.nNumVertex)
  2712. return PVR_SUCCESS;
  2713. // This function expects the data to be floats and not interleaved
  2714. if(mesh.sVertex.eType != EPODDataFloat && mesh.pInterleaved != 0)
  2715. return PVR_FAIL;
  2716. if(eNewType == EPODDataFloat) // Nothing to do
  2717. return PVR_FAIL;
  2718. // A few variables
  2719. float fLower = 0.0f, fUpper = 0.0f;
  2720. PVRTBOUNDINGBOX BoundingBox;
  2721. PVRTMATRIX mOffset, mScale;
  2722. PVRTVECTOR4 v,o;
  2723. // Set the w component of o as it is needed for later
  2724. o.w = 1.0f;
  2725. // Calc bounding box
  2726. PVRTBoundingBoxComputeInterleaved(&BoundingBox, mesh.sVertex.pData, mesh.nNumVertex, 0, mesh.sVertex.nStride);
  2727. // Get new type data range that we wish to scale the data to
  2728. // Due to a hardware bug in early MBXs in some cases we clamp the data to the minimum possible value +1
  2729. switch(eNewType)
  2730. {
  2731. case EPODDataInt:
  2732. fUpper = 1 << 30;
  2733. fLower = -fUpper;
  2734. break;
  2735. case EPODDataUnsignedInt:
  2736. fUpper = 1 << 30;
  2737. break;
  2738. case EPODDataShort:
  2739. case EPODDataFixed16_16:
  2740. fUpper = 32767.0f;
  2741. fLower = -fUpper;
  2742. break;
  2743. case EPODDataUnsignedShort:
  2744. fUpper = 0x0ffff;
  2745. break;
  2746. case EPODDataRGBA:
  2747. case EPODDataARGB:
  2748. case EPODDataD3DCOLOR:
  2749. fUpper = 1.0f;
  2750. break;
  2751. case EPODDataUBYTE4:
  2752. case EPODDataUnsignedByte:
  2753. fUpper = 0x0ff;
  2754. break;
  2755. case EPODDataShortNorm:
  2756. case EPODDataUnsignedShortNorm:
  2757. case EPODDataByteNorm:
  2758. case EPODDataUnsignedByteNorm:
  2759. fUpper = 1.0f;
  2760. fLower = -fUpper;
  2761. break;
  2762. case EPODDataDEC3N:
  2763. fUpper = 511.0f;
  2764. fLower = -fUpper;
  2765. break;
  2766. case EPODDataByte:
  2767. fUpper = 127.0f;
  2768. fLower = -fUpper;
  2769. break;
  2770. default:
  2771. _ASSERT(false);
  2772. return PVR_FAIL; // Unsupported format specified
  2773. }
  2774. PVRTVECTOR3f vScale, vOffset;
  2775. float fRange = fUpper - fLower;
  2776. vScale.x = fRange / (BoundingBox.Point[7].x - BoundingBox.Point[0].x);
  2777. vScale.y = fRange / (BoundingBox.Point[7].y - BoundingBox.Point[0].y);
  2778. vScale.z = fRange / (BoundingBox.Point[7].z - BoundingBox.Point[0].z);
  2779. vOffset.x = -BoundingBox.Point[0].x;
  2780. vOffset.y = -BoundingBox.Point[0].y;
  2781. vOffset.z = -BoundingBox.Point[0].z;
  2782. PVRTMatrixTranslation(mOffset, -fLower, -fLower, -fLower);
  2783. PVRTMatrixScaling(mScale, 1.0f / vScale.x, 1.0f / vScale.y, 1.0f / vScale.z);
  2784. PVRTMatrixMultiply(mesh.mUnpackMatrix, mOffset, mScale);
  2785. PVRTMatrixTranslation(mOffset, -vOffset.x, -vOffset.y, -vOffset.z);
  2786. PVRTMatrixMultiply(mesh.mUnpackMatrix, mesh.mUnpackMatrix, mOffset);
  2787. // Transform vertex data
  2788. for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
  2789. {
  2790. PVRTVertexRead(&v, mesh.sVertex.pData + i * mesh.sVertex.nStride, mesh.sVertex.eType, mesh.sVertex.n);
  2791. o.x = (v.x + vOffset.x) * vScale.x + fLower;
  2792. o.y = (v.y + vOffset.y) * vScale.y + fLower;
  2793. o.z = (v.z + vOffset.z) * vScale.z + fLower;
  2794. _ASSERT((o.x >= fLower && o.x <= fUpper) || fabs(1.0f - o.x / fLower) < 0.01f || fabs(1.0f - o.x / fUpper) < 0.01f);
  2795. _ASSERT((o.y >= fLower && o.y <= fUpper) || fabs(1.0f - o.y / fLower) < 0.01f || fabs(1.0f - o.y / fUpper) < 0.01f);
  2796. _ASSERT((o.z >= fLower && o.z <= fUpper) || fabs(1.0f - o.z / fLower) < 0.01f || fabs(1.0f - o.z / fUpper) < 0.01f);
  2797. #if defined(_DEBUG)
  2798. PVRTVECTOR4 res;
  2799. PVRTTransform(&res, &o, &mesh.mUnpackMatrix);
  2800. _ASSERT(fabs(res.x - v.x) <= 0.02);
  2801. _ASSERT(fabs(res.y - v.y) <= 0.02);
  2802. _ASSERT(fabs(res.z - v.z) <= 0.02);
  2803. _ASSERT(fabs(res.w - 1.0) <= 0.02);
  2804. #endif
  2805. PVRTVertexWrite(mesh.sVertex.pData + i * mesh.sVertex.nStride, mesh.sVertex.eType, mesh.sVertex.n * PVRTModelPODDataTypeComponentCount(mesh.sVertex.eType), &o);
  2806. }
  2807. // Convert the data to the chosen format
  2808. PVRTModelPODDataConvert(mesh.sVertex, mesh.nNumVertex, eNewType);
  2809. return PVR_SUCCESS;
  2810. }
  2811. #endif
  2812. /*!***************************************************************************
  2813. @Function PVRTModelPODDataShred
  2814. @Modified data Data elements to modify
  2815. @Input nCnt Number of elements
  2816. @Input pChannels A list of the wanted channels, e.g. {'x', 'y', 0}
  2817. @Description Reduce the number of dimensions in 'data' using the requested
  2818. channel array. The array should have a maximum length of 4
  2819. or be null terminated if less channels are wanted. It is also
  2820. possible to negate an element, e.g. {'x','y', -'z'}.
  2821. *****************************************************************************/
  2822. void PVRTModelPODDataShred(CPODData &data, const unsigned int nCnt, const int * pChannels)
  2823. {
  2824. CPODData old;
  2825. PVRTVECTOR4f v,o;
  2826. float * const pv = &v.x;
  2827. float * const po = &o.x;
  2828. unsigned int i, nCh;
  2829. int i32Map[4];
  2830. bool bNegate[4];
  2831. if(!data.pData || !pChannels)
  2832. return;
  2833. old = data;
  2834. // Count the number of output channels while setting up cMap and bNegate
  2835. for(data.n = 0; data.n < 4 && pChannels[data.n]; ++data.n)
  2836. {
  2837. i32Map[data.n] = abs(pChannels[data.n]) == 'w' ? 3 : abs(pChannels[data.n]) - 'x';
  2838. bNegate[data.n] = pChannels[data.n] < 0;
  2839. }
  2840. if(data.n > old.n)
  2841. data.n = old.n;
  2842. // Allocate output memory
  2843. data.nStride = (unsigned int)PVRTModelPODDataStride(data);
  2844. if(data.nStride == 0)
  2845. {
  2846. FREE(data.pData);
  2847. return;
  2848. }
  2849. data.pData = (unsigned char*)malloc(data.nStride * nCnt);
  2850. for(i = 0; i < nCnt; ++i)
  2851. {
  2852. // Read the vector
  2853. PVRTVertexRead(&v, old.pData + i * old.nStride, old.eType, old.n);
  2854. // Shred the vector
  2855. for(nCh = 0; nCh < 4 && pChannels[nCh]; ++nCh)
  2856. po[nCh] = bNegate[nCh] ? -pv[i32Map[nCh]] : pv[i32Map[nCh]];
  2857. for(; nCh < 4; ++nCh)
  2858. po[nCh] = 0;
  2859. // Write the vector
  2860. PVRTVertexWrite((char*)data.pData + i * data.nStride, data.eType, data.n * PVRTModelPODDataTypeComponentCount(data.eType), &o);
  2861. }
  2862. FREE(old.pData);
  2863. }
  2864. /*!***************************************************************************
  2865. @Function PVRTModelPODReorderFaces
  2866. @Modified mesh The mesh to re-order the faces of
  2867. @Input i32El1 The first index to be written out
  2868. @Input i32El2 The second index to be written out
  2869. @Input i32El3 The third index to be written out
  2870. @Description Reorders the face indices of a mesh.
  2871. *****************************************************************************/
  2872. void PVRTModelPODReorderFaces(SPODMesh &mesh, const int i32El1, const int i32El2, const int i32El3)
  2873. {
  2874. if(!mesh.sFaces.pData)
  2875. return;
  2876. unsigned int ui32V[3];
  2877. for(unsigned int i = 0; i < mesh.nNumFaces * 3; i += 3)
  2878. {
  2879. unsigned char *pData = mesh.sFaces.pData + i * mesh.sFaces.nStride;
  2880. // Read
  2881. PVRTVertexRead(&ui32V[0], pData, mesh.sFaces.eType);
  2882. PVRTVertexRead(&ui32V[1], pData + mesh.sFaces.nStride, mesh.sFaces.eType);
  2883. PVRTVertexRead(&ui32V[2], pData + 2 * mesh.sFaces.nStride, mesh.sFaces.eType);
  2884. // Write in place the new order
  2885. PVRTVertexWrite(pData, mesh.sFaces.eType, ui32V[i32El1]);
  2886. PVRTVertexWrite(pData + mesh.sFaces.nStride, mesh.sFaces.eType, ui32V[i32El2]);
  2887. PVRTVertexWrite(pData + 2 * mesh.sFaces.nStride, mesh.sFaces.eType, ui32V[i32El3]);
  2888. }
  2889. }
  2890. /*!***************************************************************************
  2891. @Function InterleaveArray
  2892. @Modified pInterleaved
  2893. @Modified data
  2894. @Input nNumVertex
  2895. @Input nStride
  2896. @Input nOffset
  2897. @Description Interleaves the pod data
  2898. *****************************************************************************/
  2899. static void InterleaveArray(
  2900. char * const pInterleaved,
  2901. CPODData &data,
  2902. const int nNumVertex,
  2903. const size_t nStride,
  2904. size_t &nOffset)
  2905. {
  2906. if(!data.nStride)
  2907. return;
  2908. for(int i = 0; i < nNumVertex; ++i)
  2909. memcpy(pInterleaved + i * nStride + nOffset, (char*)data.pData + i * data.nStride, data.nStride);
  2910. FREE(data.pData);
  2911. data.nStride = (unsigned int)nStride;
  2912. data.pData = (unsigned char*)nOffset;
  2913. nOffset += (int)PVRTModelPODDataStride(data);
  2914. }
  2915. /*!***************************************************************************
  2916. @Function DeinterleaveArray
  2917. @Input data
  2918. @Input pInter
  2919. @Input nNumVertex
  2920. @Description DeInterleaves the pod data
  2921. *****************************************************************************/
  2922. static void DeinterleaveArray(
  2923. CPODData &data,
  2924. const void * const pInter,
  2925. const int nNumVertex)
  2926. {
  2927. unsigned int nSrcStride = data.nStride;
  2928. unsigned int nDestStride = (unsigned int)PVRTModelPODDataStride(data);
  2929. const char *pSrc = (char*)pInter + (size_t)data.pData;
  2930. if(!nSrcStride)
  2931. return;
  2932. data.pData = 0;
  2933. SafeAlloc(data.pData, nDestStride * nNumVertex);
  2934. data.nStride = nDestStride;
  2935. for(int i = 0; i < nNumVertex; ++i)
  2936. memcpy((char*)data.pData + i * nDestStride, pSrc + i * nSrcStride, nDestStride);
  2937. }
  2938. /*!***************************************************************************
  2939. @Function PVRTModelPODToggleInterleaved
  2940. @Modified mesh Mesh to modify
  2941. @Input ui32AlignToNBytes Align the interleaved data to this no. of bytes.
  2942. @Description Switches the supplied mesh to or from interleaved data format.
  2943. *****************************************************************************/
  2944. void PVRTModelPODToggleInterleaved(SPODMesh &mesh, unsigned int ui32AlignToNBytes)
  2945. {
  2946. unsigned int i;
  2947. if(!mesh.nNumVertex)
  2948. return;
  2949. if(mesh.pInterleaved)
  2950. {
  2951. /*
  2952. De-interleave
  2953. */
  2954. DeinterleaveArray(mesh.sVertex, mesh.pInterleaved, mesh.nNumVertex);
  2955. DeinterleaveArray(mesh.sNormals, mesh.pInterleaved, mesh.nNumVertex);
  2956. DeinterleaveArray(mesh.sTangents, mesh.pInterleaved, mesh.nNumVertex);
  2957. DeinterleaveArray(mesh.sBinormals, mesh.pInterleaved, mesh.nNumVertex);
  2958. for(i = 0; i < mesh.nNumUVW; ++i)
  2959. DeinterleaveArray(mesh.psUVW[i], mesh.pInterleaved, mesh.nNumVertex);
  2960. DeinterleaveArray(mesh.sVtxColours, mesh.pInterleaved, mesh.nNumVertex);
  2961. DeinterleaveArray(mesh.sBoneIdx, mesh.pInterleaved, mesh.nNumVertex);
  2962. DeinterleaveArray(mesh.sBoneWeight, mesh.pInterleaved, mesh.nNumVertex);
  2963. FREE(mesh.pInterleaved);
  2964. }
  2965. else
  2966. {
  2967. size_t nStride, nOffset, nBytes;
  2968. /*
  2969. Interleave
  2970. */
  2971. // Calculate how much data the interleaved array must store
  2972. nStride = PVRTModelPODDataStride(mesh.sVertex);
  2973. nStride += PVRTModelPODDataStride(mesh.sNormals);
  2974. nStride += PVRTModelPODDataStride(mesh.sTangents);
  2975. nStride += PVRTModelPODDataStride(mesh.sBinormals);
  2976. for(i = 0; i < mesh.nNumUVW; ++i)
  2977. nStride += PVRTModelPODDataStride(mesh.psUVW[i]);
  2978. nStride += PVRTModelPODDataStride(mesh.sVtxColours);
  2979. nStride += PVRTModelPODDataStride(mesh.sBoneIdx);
  2980. nStride += PVRTModelPODDataStride(mesh.sBoneWeight);
  2981. // Pad out the vertex stride to align the vertices to our
  2982. // requested bytes boundry
  2983. if(ui32AlignToNBytes > 1)
  2984. nStride += (ui32AlignToNBytes - (nStride % ui32AlignToNBytes)) % ui32AlignToNBytes;
  2985. // Allocate interleaved array
  2986. SafeAlloc(mesh.pInterleaved, mesh.nNumVertex * nStride);
  2987. // Interleave the data
  2988. nOffset = 0;
  2989. for(nBytes = 4; nBytes > 0; nBytes >>= 1)
  2990. {
  2991. if(PVRTModelPODDataTypeSize(mesh.sVertex.eType) == nBytes)
  2992. InterleaveArray((char*)mesh.pInterleaved, mesh.sVertex, mesh.nNumVertex, nStride, nOffset);
  2993. if(PVRTModelPODDataTypeSize(mesh.sNormals.eType) == nBytes)
  2994. InterleaveArray((char*)mesh.pInterleaved, mesh.sNormals, mesh.nNumVertex, nStride, nOffset);
  2995. if(PVRTModelPODDataTypeSize(mesh.sTangents.eType) == nBytes)
  2996. InterleaveArray((char*)mesh.pInterleaved, mesh.sTangents, mesh.nNumVertex, nStride, nOffset);
  2997. if(PVRTModelPODDataTypeSize(mesh.sBinormals.eType) == nBytes)
  2998. InterleaveArray((char*)mesh.pInterleaved, mesh.sBinormals, mesh.nNumVertex, nStride, nOffset);
  2999. if(PVRTModelPODDataTypeSize(mesh.sVtxColours.eType) == nBytes)
  3000. InterleaveArray((char*)mesh.pInterleaved, mesh.sVtxColours, mesh.nNumVertex, nStride, nOffset);
  3001. for(i = 0; i < mesh.nNumUVW; ++i)
  3002. {
  3003. if(PVRTModelPODDataTypeSize(mesh.psUVW[i].eType) == nBytes)
  3004. InterleaveArray((char*)mesh.pInterleaved, mesh.psUVW[i], mesh.nNumVertex, nStride, nOffset);
  3005. }
  3006. if(PVRTModelPODDataTypeSize(mesh.sBoneIdx.eType) == nBytes)
  3007. InterleaveArray((char*)mesh.pInterleaved, mesh.sBoneIdx, mesh.nNumVertex, nStride, nOffset);
  3008. if(PVRTModelPODDataTypeSize(mesh.sBoneWeight.eType) == nBytes)
  3009. InterleaveArray((char*)mesh.pInterleaved, mesh.sBoneWeight, mesh.nNumVertex, nStride, nOffset);
  3010. }
  3011. }
  3012. }
  3013. /*!***************************************************************************
  3014. @Function PVRTModelPODDeIndex
  3015. @Modified mesh Mesh to modify
  3016. @Description De-indexes the supplied mesh. The mesh must be
  3017. Interleaved before calling this function.
  3018. *****************************************************************************/
  3019. void PVRTModelPODDeIndex(SPODMesh &mesh)
  3020. {
  3021. unsigned char *pNew = 0;
  3022. if(!mesh.pInterleaved || !mesh.nNumVertex)
  3023. return;
  3024. _ASSERT(mesh.nNumVertex && mesh.nNumFaces);
  3025. // Create a new vertex list
  3026. mesh.nNumVertex = PVRTModelPODCountIndices(mesh);
  3027. SafeAlloc(pNew, mesh.sVertex.nStride * mesh.nNumVertex);
  3028. // Deindex the vertices
  3029. if(mesh.sFaces.eType == EPODDataUnsignedShort)
  3030. {
  3031. for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
  3032. memcpy(pNew + i * mesh.sVertex.nStride, (char*)mesh.pInterleaved + ((unsigned short*)mesh.sFaces.pData)[i] * mesh.sVertex.nStride, mesh.sVertex.nStride);
  3033. }
  3034. else
  3035. {
  3036. _ASSERT(mesh.sFaces.eType == EPODDataUnsignedInt);
  3037. for(unsigned int i = 0; i < mesh.nNumVertex; ++i)
  3038. memcpy(pNew + i * mesh.sVertex.nStride, (char*)mesh.pInterleaved + ((unsigned int*)mesh.sFaces.pData)[i] * mesh.sVertex.nStride, mesh.sVertex.nStride);
  3039. }
  3040. // Replace the old vertex list
  3041. FREE(mesh.pInterleaved);
  3042. mesh.pInterleaved = pNew;
  3043. // Get rid of the index list
  3044. FREE(mesh.sFaces.pData);
  3045. mesh.sFaces.n = 0;
  3046. mesh.sFaces.nStride = 0;
  3047. }
  3048. /*!***************************************************************************
  3049. @Function PVRTModelPODToggleStrips
  3050. @Modified mesh Mesh to modify
  3051. @Description Converts the supplied mesh to or from strips.
  3052. *****************************************************************************/
  3053. void PVRTModelPODToggleStrips(SPODMesh &mesh)
  3054. {
  3055. CPODData old;
  3056. size_t nIdxSize, nTriStride;
  3057. if(!mesh.nNumFaces)
  3058. return;
  3059. _ASSERT(mesh.sFaces.n == 1);
  3060. nIdxSize = PVRTModelPODDataTypeSize(mesh.sFaces.eType);
  3061. nTriStride = PVRTModelPODDataStride(mesh.sFaces) * 3;
  3062. old = mesh.sFaces;
  3063. mesh.sFaces.pData = 0;
  3064. SafeAlloc(mesh.sFaces.pData, nTriStride * mesh.nNumFaces);
  3065. if(mesh.nNumStrips)
  3066. {
  3067. unsigned int nListIdxCnt, nStripIdxCnt;
  3068. // Convert to list
  3069. nListIdxCnt = 0;
  3070. nStripIdxCnt = 0;
  3071. for(unsigned int i = 0; i < mesh.nNumStrips; ++i)
  3072. {
  3073. for(unsigned int j = 0; j < mesh.pnStripLength[i]; ++j)
  3074. {
  3075. if(j)
  3076. {
  3077. _ASSERT(j == 1); // Because this will surely break with any other number
  3078. memcpy(
  3079. (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
  3080. (char*)old.pData + nIdxSize * (nStripIdxCnt - 1),
  3081. nIdxSize);
  3082. nListIdxCnt += 1;
  3083. memcpy(
  3084. (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
  3085. (char*)old.pData + nIdxSize * (nStripIdxCnt - 2),
  3086. nIdxSize);
  3087. nListIdxCnt += 1;
  3088. memcpy(
  3089. (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
  3090. (char*)old.pData + nIdxSize * nStripIdxCnt,
  3091. nIdxSize);
  3092. nListIdxCnt += 1;
  3093. nStripIdxCnt += 1;
  3094. }
  3095. else
  3096. {
  3097. memcpy(
  3098. (char*)mesh.sFaces.pData + nIdxSize * nListIdxCnt,
  3099. (char*)old.pData + nIdxSize * nStripIdxCnt,
  3100. nTriStride);
  3101. nStripIdxCnt += 3;
  3102. nListIdxCnt += 3;
  3103. }
  3104. }
  3105. }
  3106. _ASSERT(nListIdxCnt == mesh.nNumFaces*3);
  3107. FREE(mesh.pnStripLength);
  3108. mesh.nNumStrips = 0;
  3109. }
  3110. else
  3111. {
  3112. int nIdxCnt;
  3113. int nBatchCnt;
  3114. unsigned int n0, n1, n2;
  3115. unsigned int p0, p1, p2, nFaces;
  3116. unsigned char* pFaces;
  3117. // Convert to strips
  3118. mesh.pnStripLength = (unsigned int*)calloc(mesh.nNumFaces, sizeof(*mesh.pnStripLength));
  3119. mesh.nNumStrips = 0;
  3120. nIdxCnt = 0;
  3121. nBatchCnt = mesh.sBoneBatches.nBatchCnt ? mesh.sBoneBatches.nBatchCnt : 1;
  3122. for(int h = 0; h < nBatchCnt; ++h)
  3123. {
  3124. n0 = 0;
  3125. n1 = 0;
  3126. n2 = 0;
  3127. if(!mesh.sBoneBatches.nBatchCnt)
  3128. {
  3129. nFaces = mesh.nNumFaces;
  3130. pFaces = old.pData;
  3131. }
  3132. else
  3133. {
  3134. if(h + 1 < mesh.sBoneBatches.nBatchCnt)
  3135. nFaces = mesh.sBoneBatches.pnBatchOffset[h+1] - mesh.sBoneBatches.pnBatchOffset[h];
  3136. else
  3137. nFaces = mesh.nNumFaces - mesh.sBoneBatches.pnBatchOffset[h];
  3138. pFaces = &old.pData[3 * mesh.sBoneBatches.pnBatchOffset[h] * old.nStride];
  3139. }
  3140. for(unsigned int i = 0; i < nFaces; ++i)
  3141. {
  3142. p0 = n0;
  3143. p1 = n1;
  3144. p2 = n2;
  3145. PVRTVertexRead(&n0, (char*)pFaces + (3 * i + 0) * old.nStride, old.eType);
  3146. PVRTVertexRead(&n1, (char*)pFaces + (3 * i + 1) * old.nStride, old.eType);
  3147. PVRTVertexRead(&n2, (char*)pFaces + (3 * i + 2) * old.nStride, old.eType);
  3148. if(mesh.pnStripLength[mesh.nNumStrips])
  3149. {
  3150. if(mesh.pnStripLength[mesh.nNumStrips] & 0x01)
  3151. {
  3152. if(p1 == n1 && p2 == n0)
  3153. {
  3154. PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
  3155. ++nIdxCnt;
  3156. mesh.pnStripLength[mesh.nNumStrips] += 1;
  3157. continue;
  3158. }
  3159. }
  3160. else
  3161. {
  3162. if(p2 == n1 && p0 == n0)
  3163. {
  3164. PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
  3165. ++nIdxCnt;
  3166. mesh.pnStripLength[mesh.nNumStrips] += 1;
  3167. continue;
  3168. }
  3169. }
  3170. ++mesh.nNumStrips;
  3171. }
  3172. // Start of strip, copy entire triangle
  3173. PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n0);
  3174. ++nIdxCnt;
  3175. PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n1);
  3176. ++nIdxCnt;
  3177. PVRTVertexWrite((char*)mesh.sFaces.pData + nIdxCnt * mesh.sFaces.nStride, mesh.sFaces.eType, n2);
  3178. ++nIdxCnt;
  3179. mesh.pnStripLength[mesh.nNumStrips] += 1;
  3180. }
  3181. }
  3182. if(mesh.pnStripLength[mesh.nNumStrips])
  3183. ++mesh.nNumStrips;
  3184. SafeRealloc(mesh.sFaces.pData, nIdxCnt * nIdxSize);
  3185. mesh.pnStripLength = (unsigned int*)realloc(mesh.pnStripLength, sizeof(*mesh.pnStripLength) * mesh.nNumStrips);
  3186. }
  3187. FREE(old.pData);
  3188. }
  3189. /*!***************************************************************************
  3190. @Function PVRTModelPODCountIndices
  3191. @Input mesh Mesh
  3192. @Return Number of indices used by mesh
  3193. @Description Counts the number of indices of a mesh
  3194. *****************************************************************************/
  3195. unsigned int PVRTModelPODCountIndices(const SPODMesh &mesh)
  3196. {
  3197. if(mesh.nNumStrips)
  3198. {
  3199. unsigned int i, n = 0;
  3200. for(i = 0; i < mesh.nNumStrips; ++i)
  3201. n += mesh.pnStripLength[i] + 2;
  3202. return n;
  3203. }
  3204. return mesh.nNumFaces * 3;
  3205. }
  3206. static void FloatToFixed(int * const pn, const float * const pf, unsigned int n)
  3207. {
  3208. if(!pn || !pf) return;
  3209. while(n)
  3210. {
  3211. --n;
  3212. pn[n] = (int)(pf[n] * (float)(1<<16));
  3213. }
  3214. }
  3215. static void FixedToFloat(float * const pf, const int * const pn, unsigned int n)
  3216. {
  3217. if(!pn || !pf) return;
  3218. while(n)
  3219. {
  3220. --n;
  3221. pf[n] = (float)pn[n] / (float)(1<<16);
  3222. }
  3223. }
  3224. /*!***************************************************************************
  3225. @Function PVRTModelPODToggleFixedPoint
  3226. @Modified s Scene to modify
  3227. @Description Switch all non-vertex data between fixed-point and
  3228. floating-point.
  3229. *****************************************************************************/
  3230. void PVRTModelPODToggleFixedPoint(SPODScene &s)
  3231. {
  3232. unsigned int i;
  3233. int i32TransformNo;
  3234. if(s.nFlags & PVRTMODELPODSF_FIXED)
  3235. {
  3236. /*
  3237. Convert to floating-point
  3238. */
  3239. for(i = 0; i < s.nNumCamera; ++i)
  3240. {
  3241. FixedToFloat((float*)&s.pCamera[i].fFOV, (int*)&s.pCamera[i].fFOV, 1);
  3242. FixedToFloat((float*)&s.pCamera[i].fFar, (int*)&s.pCamera[i].fFar, 1);
  3243. FixedToFloat((float*)&s.pCamera[i].fNear, (int*)&s.pCamera[i].fNear, 1);
  3244. FixedToFloat((float*)s.pCamera[i].pfAnimFOV, (int*)s.pCamera[i].pfAnimFOV, s.nNumFrame);
  3245. }
  3246. for(i = 0; i < s.nNumLight; ++i)
  3247. {
  3248. FixedToFloat((float*)&s.pLight[i].pfColour, (int*)&s.pLight[i].pfColour, 3);
  3249. FixedToFloat((float*)&s.pLight[i].fConstantAttenuation, (int*)&s.pLight[i].fConstantAttenuation, 1);
  3250. FixedToFloat((float*)&s.pLight[i].fLinearAttenuation, (int*)&s.pLight[i].fLinearAttenuation, 1);
  3251. FixedToFloat((float*)&s.pLight[i].fQuadraticAttenuation,(int*)&s.pLight[i].fQuadraticAttenuation, 1);
  3252. FixedToFloat((float*)&s.pLight[i].fFalloffAngle, (int*)&s.pLight[i].fFalloffAngle, 1);
  3253. FixedToFloat((float*)&s.pLight[i].fFalloffExponent, (int*)&s.pLight[i].fFalloffExponent, 1);
  3254. }
  3255. for(i = 0; i < s.nNumNode; ++i)
  3256. {
  3257. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
  3258. FixedToFloat((float*)s.pNode[i].pfAnimPosition, (int*)s.pNode[i].pfAnimPosition, i32TransformNo);
  3259. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
  3260. FixedToFloat((float*)s.pNode[i].pfAnimRotation, (int*)s.pNode[i].pfAnimRotation, i32TransformNo);
  3261. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
  3262. FixedToFloat((float*)s.pNode[i].pfAnimScale, (int*)s.pNode[i].pfAnimScale, i32TransformNo);
  3263. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
  3264. FixedToFloat((float*)s.pNode[i].pfAnimMatrix, (int*)s.pNode[i].pfAnimMatrix, i32TransformNo);
  3265. }
  3266. for(i = 0; i < s.nNumMaterial; ++i)
  3267. {
  3268. FixedToFloat((float*)&s.pMaterial[i].fMatOpacity, (int*)&s.pMaterial[i].fMatOpacity, 1);
  3269. FixedToFloat((float*)s.pMaterial[i].pfMatAmbient, (int*)s.pMaterial[i].pfMatAmbient, 3);
  3270. FixedToFloat((float*)s.pMaterial[i].pfMatDiffuse, (int*)s.pMaterial[i].pfMatDiffuse, 3);
  3271. FixedToFloat((float*)s.pMaterial[i].pfMatSpecular, (int*)s.pMaterial[i].pfMatSpecular, 3);
  3272. FixedToFloat((float*)&s.pMaterial[i].fMatShininess, (int*)&s.pMaterial[i].fMatShininess, 1);
  3273. }
  3274. for(i = 0; i < s.nNumMesh; ++i)
  3275. {
  3276. FixedToFloat((float*)&s.pMesh[i].mUnpackMatrix.f[0], (int*)&s.pMesh[i].mUnpackMatrix.f[0], 16);
  3277. }
  3278. FixedToFloat((float*)s.pfColourBackground, (int*)s.pfColourBackground, 3);
  3279. FixedToFloat((float*)s.pfColourAmbient, (int*)s.pfColourAmbient, 3);
  3280. }
  3281. else
  3282. {
  3283. /*
  3284. Convert to Fixed-point
  3285. */
  3286. for(i = 0; i < s.nNumCamera; ++i)
  3287. {
  3288. FloatToFixed((int*)&s.pCamera[i].fFOV, (float*)&s.pCamera[i].fFOV, 1);
  3289. FloatToFixed((int*)&s.pCamera[i].fFar, (float*)&s.pCamera[i].fFar, 1);
  3290. FloatToFixed((int*)&s.pCamera[i].fNear, (float*)&s.pCamera[i].fNear, 1);
  3291. FloatToFixed((int*)s.pCamera[i].pfAnimFOV, (float*)s.pCamera[i].pfAnimFOV, s.nNumFrame);
  3292. }
  3293. for(i = 0; i < s.nNumLight; ++i)
  3294. {
  3295. FloatToFixed((int*)&s.pLight[i].pfColour, (float*)&s.pLight[i].pfColour, 3);
  3296. FloatToFixed((int*)&s.pLight[i].fConstantAttenuation, (float*)&s.pLight[i].fConstantAttenuation, 1);
  3297. FloatToFixed((int*)&s.pLight[i].fLinearAttenuation, (float*)&s.pLight[i].fLinearAttenuation, 1);
  3298. FloatToFixed((int*)&s.pLight[i].fQuadraticAttenuation,(float*)&s.pLight[i].fQuadraticAttenuation, 1);
  3299. FloatToFixed((int*)&s.pLight[i].fFalloffAngle, (float*)&s.pLight[i].fFalloffAngle, 1);
  3300. FloatToFixed((int*)&s.pLight[i].fFalloffExponent, (float*)&s.pLight[i].fFalloffExponent, 1);
  3301. }
  3302. for(i = 0; i < s.nNumNode; ++i)
  3303. {
  3304. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimPositionIdx, s.nNumFrame, 3) : 3;
  3305. FloatToFixed((int*)s.pNode[i].pfAnimPosition, (float*)s.pNode[i].pfAnimPosition, i32TransformNo);
  3306. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimRotationIdx, s.nNumFrame, 4) : 4;
  3307. FloatToFixed((int*)s.pNode[i].pfAnimRotation, (float*)s.pNode[i].pfAnimRotation, i32TransformNo);
  3308. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimScaleIdx, s.nNumFrame, 7) : 7;
  3309. FloatToFixed((int*)s.pNode[i].pfAnimScale, (float*)s.pNode[i].pfAnimScale, i32TransformNo);
  3310. i32TransformNo = s.pNode[i].nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(s.pNode[i].pnAnimMatrixIdx, s.nNumFrame, 16) : 16;
  3311. FloatToFixed((int*)s.pNode[i].pfAnimMatrix, (float*)s.pNode[i].pfAnimMatrix, i32TransformNo);
  3312. }
  3313. for(i = 0; i < s.nNumMaterial; ++i)
  3314. {
  3315. FloatToFixed((int*)&s.pMaterial[i].fMatOpacity, (float*)&s.pMaterial[i].fMatOpacity, 1);
  3316. FloatToFixed((int*)s.pMaterial[i].pfMatAmbient, (float*)s.pMaterial[i].pfMatAmbient, 3);
  3317. FloatToFixed((int*)s.pMaterial[i].pfMatDiffuse, (float*)s.pMaterial[i].pfMatDiffuse, 3);
  3318. FloatToFixed((int*)s.pMaterial[i].pfMatSpecular, (float*)s.pMaterial[i].pfMatSpecular, 3);
  3319. FloatToFixed((int*)&s.pMaterial[i].fMatShininess, (float*)&s.pMaterial[i].fMatShininess, 1);
  3320. }
  3321. for(i = 0; i < s.nNumMesh; ++i)
  3322. {
  3323. FloatToFixed((int*)&s.pMesh[i].mUnpackMatrix.f[0], (float*)&s.pMesh[i].mUnpackMatrix.f[0], 16);
  3324. }
  3325. FloatToFixed((int*)s.pfColourBackground, (float*)s.pfColourBackground, 3);
  3326. FloatToFixed((int*)s.pfColourAmbient, (float*)s.pfColourAmbient, 3);
  3327. }
  3328. // Done
  3329. s.nFlags ^= PVRTMODELPODSF_FIXED;
  3330. }
  3331. /*!***************************************************************************
  3332. @Function PVRTModelPODCopyCPODData
  3333. @Input in
  3334. @Output out
  3335. @Input ui32No
  3336. @Input bInterleaved
  3337. @Description Used to copy a CPODData of a mesh
  3338. *****************************************************************************/
  3339. void PVRTModelPODCopyCPODData(const CPODData &in, CPODData &out, unsigned int ui32No, bool bInterleaved)
  3340. {
  3341. FREE(out.pData);
  3342. out.eType = in.eType;
  3343. out.n = in.n;
  3344. out.nStride = in.nStride;
  3345. if(bInterleaved)
  3346. {
  3347. out.pData = in.pData;
  3348. }
  3349. else if(in.pData)
  3350. {
  3351. size_t ui32Size = PVRTModelPODDataStride(out) * ui32No;
  3352. if(SafeAlloc(out.pData, ui32Size))
  3353. memcpy(out.pData, in.pData, ui32Size);
  3354. }
  3355. }
  3356. /*!***************************************************************************
  3357. @Function PVRTModelPODCopyNode
  3358. @Input in
  3359. @Output out
  3360. @Input nNumFrames
  3361. @Description Used to copy a pod node
  3362. *****************************************************************************/
  3363. void PVRTModelPODCopyNode(const SPODNode &in, SPODNode &out, int nNumFrames)
  3364. {
  3365. out.nIdx = in.nIdx;
  3366. out.nIdxMaterial = in.nIdxMaterial;
  3367. out.nIdxParent = in.nIdxParent;
  3368. out.nAnimFlags = in.nAnimFlags;
  3369. if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
  3370. memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
  3371. int i32Size;
  3372. // Position
  3373. i32Size = in.nAnimFlags & ePODHasPositionAni ? PVRTModelPODGetAnimArraySize(in.pnAnimPositionIdx, nNumFrames, 3) : 3;
  3374. if(in.pnAnimPositionIdx && SafeAlloc(out.pnAnimPositionIdx, sizeof(*out.pnAnimPositionIdx) * nNumFrames))
  3375. memcpy(out.pnAnimPositionIdx, in.pnAnimPositionIdx, sizeof(*out.pnAnimPositionIdx) * nNumFrames);
  3376. if(in.pfAnimPosition && SafeAlloc(out.pfAnimPosition, sizeof(*out.pfAnimPosition) * i32Size))
  3377. memcpy(out.pfAnimPosition, in.pfAnimPosition, sizeof(*out.pfAnimPosition) * i32Size);
  3378. // Rotation
  3379. i32Size = in.nAnimFlags & ePODHasRotationAni ? PVRTModelPODGetAnimArraySize(in.pnAnimRotationIdx, nNumFrames, 4) : 4;
  3380. if(in.pnAnimRotationIdx && SafeAlloc(out.pnAnimRotationIdx, sizeof(*out.pnAnimRotationIdx) * nNumFrames))
  3381. memcpy(out.pnAnimRotationIdx, in.pnAnimRotationIdx, sizeof(*out.pnAnimRotationIdx) * nNumFrames);
  3382. if(in.pfAnimRotation && SafeAlloc(out.pfAnimRotation, sizeof(*out.pfAnimRotation) * i32Size))
  3383. memcpy(out.pfAnimRotation, in.pfAnimRotation, sizeof(*out.pfAnimRotation) * i32Size);
  3384. // Scale
  3385. i32Size = in.nAnimFlags & ePODHasScaleAni ? PVRTModelPODGetAnimArraySize(in.pnAnimScaleIdx, nNumFrames, 7) : 7;
  3386. if(in.pnAnimScaleIdx && SafeAlloc(out.pnAnimScaleIdx, sizeof(*out.pnAnimScaleIdx) * nNumFrames))
  3387. memcpy(out.pnAnimScaleIdx, in.pnAnimScaleIdx, sizeof(*out.pnAnimScaleIdx) * nNumFrames);
  3388. if(in.pfAnimScale && SafeAlloc(out.pfAnimScale, sizeof(*out.pfAnimScale) * i32Size))
  3389. memcpy(out.pfAnimScale, in.pfAnimScale, sizeof(*out.pfAnimScale) * i32Size);
  3390. // Matrix
  3391. i32Size = in.nAnimFlags & ePODHasMatrixAni ? PVRTModelPODGetAnimArraySize(in.pnAnimMatrixIdx, nNumFrames, 16) : 16;
  3392. if(in.pnAnimMatrixIdx && SafeAlloc(out.pnAnimMatrixIdx, sizeof(*out.pnAnimMatrixIdx) * nNumFrames))
  3393. memcpy(out.pnAnimMatrixIdx, in.pnAnimMatrixIdx, sizeof(*out.pnAnimMatrixIdx) * nNumFrames);
  3394. if(in.pfAnimMatrix && SafeAlloc(out.pfAnimMatrix, sizeof(*out.pfAnimMatrix) * i32Size))
  3395. memcpy(out.pfAnimMatrix, in.pfAnimMatrix, sizeof(*out.pfAnimMatrix) * i32Size);
  3396. }
  3397. /*!***************************************************************************
  3398. @Function PVRTModelPODCopyMesh
  3399. @Input in
  3400. @Output out
  3401. @Description Used to copy a pod mesh
  3402. *****************************************************************************/
  3403. void PVRTModelPODCopyMesh(const SPODMesh &in, SPODMesh &out)
  3404. {
  3405. unsigned int i;
  3406. size_t i32Stride = 0;
  3407. bool bInterleaved = in.pInterleaved != 0;
  3408. out.nNumVertex = in.nNumVertex;
  3409. out.nNumFaces = in.nNumFaces;
  3410. // Face data
  3411. PVRTModelPODCopyCPODData(in.sFaces , out.sFaces , out.nNumFaces * 3, false);
  3412. // Vertex data
  3413. PVRTModelPODCopyCPODData(in.sVertex , out.sVertex , out.nNumVertex, bInterleaved);
  3414. i32Stride += PVRTModelPODDataStride(out.sVertex);
  3415. PVRTModelPODCopyCPODData(in.sNormals , out.sNormals , out.nNumVertex, bInterleaved);
  3416. i32Stride += PVRTModelPODDataStride(out.sNormals);
  3417. PVRTModelPODCopyCPODData(in.sTangents , out.sTangents , out.nNumVertex, bInterleaved);
  3418. i32Stride += PVRTModelPODDataStride(out.sTangents);
  3419. PVRTModelPODCopyCPODData(in.sBinormals , out.sBinormals , out.nNumVertex, bInterleaved);
  3420. i32Stride += PVRTModelPODDataStride(out.sBinormals);
  3421. PVRTModelPODCopyCPODData(in.sVtxColours, out.sVtxColours, out.nNumVertex, bInterleaved);
  3422. i32Stride += PVRTModelPODDataStride(out.sVtxColours);
  3423. PVRTModelPODCopyCPODData(in.sBoneIdx , out.sBoneIdx , out.nNumVertex, bInterleaved);
  3424. i32Stride += PVRTModelPODDataStride(out.sBoneIdx);
  3425. PVRTModelPODCopyCPODData(in.sBoneWeight, out.sBoneWeight, out.nNumVertex, bInterleaved);
  3426. i32Stride += PVRTModelPODDataStride(out.sBoneWeight);
  3427. if(in.nNumUVW && SafeAlloc(out.psUVW, sizeof(CPODData) * in.nNumUVW))
  3428. {
  3429. out.nNumUVW = in.nNumUVW;
  3430. for(i = 0; i < out.nNumUVW; ++i)
  3431. {
  3432. PVRTModelPODCopyCPODData(in.psUVW[i], out.psUVW[i], out.nNumVertex, bInterleaved);
  3433. i32Stride += PVRTModelPODDataStride(out.psUVW[i]);
  3434. }
  3435. }
  3436. // Allocate and copy interleaved array
  3437. if(bInterleaved && SafeAlloc(out.pInterleaved, out.nNumVertex * i32Stride))
  3438. memcpy(out.pInterleaved, in.pInterleaved, out.nNumVertex * i32Stride);
  3439. if(in.pnStripLength && SafeAlloc(out.pnStripLength, sizeof(*out.pnStripLength) * out.nNumFaces))
  3440. {
  3441. memcpy(out.pnStripLength, in.pnStripLength, sizeof(*out.pnStripLength) * out.nNumFaces);
  3442. out.nNumStrips = in.nNumStrips;
  3443. }
  3444. if(in.sBoneBatches.nBatchCnt)
  3445. {
  3446. out.sBoneBatches.Release();
  3447. out.sBoneBatches.nBatchBoneMax = in.sBoneBatches.nBatchBoneMax;
  3448. out.sBoneBatches.nBatchCnt = in.sBoneBatches.nBatchCnt;
  3449. if(in.sBoneBatches.pnBatches)
  3450. {
  3451. out.sBoneBatches.pnBatches = new int[out.sBoneBatches.nBatchCnt * out.sBoneBatches.nBatchBoneMax];
  3452. if(out.sBoneBatches.pnBatches)
  3453. memcpy(out.sBoneBatches.pnBatches, in.sBoneBatches.pnBatches, out.sBoneBatches.nBatchCnt * out.sBoneBatches.nBatchBoneMax * sizeof(*out.sBoneBatches.pnBatches));
  3454. }
  3455. if(in.sBoneBatches.pnBatchBoneCnt)
  3456. {
  3457. out.sBoneBatches.pnBatchBoneCnt = new int[out.sBoneBatches.nBatchCnt];
  3458. if(out.sBoneBatches.pnBatchBoneCnt)
  3459. memcpy(out.sBoneBatches.pnBatchBoneCnt, in.sBoneBatches.pnBatchBoneCnt, out.sBoneBatches.nBatchCnt * sizeof(*out.sBoneBatches.pnBatchBoneCnt));
  3460. }
  3461. if(in.sBoneBatches.pnBatchOffset)
  3462. {
  3463. out.sBoneBatches.pnBatchOffset = new int[out.sBoneBatches.nBatchCnt];
  3464. if(out.sBoneBatches.pnBatchOffset)
  3465. memcpy(out.sBoneBatches.pnBatchOffset, in.sBoneBatches.pnBatchOffset, out.sBoneBatches.nBatchCnt * sizeof(*out.sBoneBatches.pnBatchOffset));
  3466. }
  3467. }
  3468. memcpy(out.mUnpackMatrix.f, in.mUnpackMatrix.f, sizeof(in.mUnpackMatrix.f[0]) * 16);
  3469. out.ePrimitiveType = in.ePrimitiveType;
  3470. }
  3471. /*!***************************************************************************
  3472. @Function PVRTModelPODCopyTexture
  3473. @Input in
  3474. @Output out
  3475. @Description Used to copy a pod texture
  3476. *****************************************************************************/
  3477. void PVRTModelPODCopyTexture(const SPODTexture &in, SPODTexture &out)
  3478. {
  3479. if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
  3480. memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
  3481. }
  3482. /*!***************************************************************************
  3483. @Function PVRTModelPODCopyMaterial
  3484. @Input in
  3485. @Output out
  3486. @Description Used to copy a pod material
  3487. *****************************************************************************/
  3488. void PVRTModelPODCopyMaterial(const SPODMaterial &in, SPODMaterial &out)
  3489. {
  3490. memcpy(&out, &in, sizeof(SPODMaterial));
  3491. out.pszName = 0;
  3492. out.pszEffectFile = 0;
  3493. out.pszEffectName = 0;
  3494. if(in.pszName && SafeAlloc(out.pszName, strlen(in.pszName) + 1))
  3495. memcpy(out.pszName, in.pszName, strlen(in.pszName) + 1);
  3496. if(in.pszEffectFile && SafeAlloc(out.pszEffectFile, strlen(in.pszEffectFile) + 1))
  3497. memcpy(out.pszEffectFile, in.pszEffectFile, strlen(in.pszEffectFile) + 1);
  3498. if(in.pszEffectName && SafeAlloc(out.pszEffectName, strlen(in.pszEffectName) + 1))
  3499. memcpy(out.pszEffectName, in.pszEffectName, strlen(in.pszEffectName) + 1);
  3500. }
  3501. /*!***************************************************************************
  3502. @Function PVRTModelPODCopyCamera
  3503. @Input in
  3504. @Output out
  3505. @Input nNumFrames The number of animation frames
  3506. @Description Used to copy a pod camera
  3507. *****************************************************************************/
  3508. void PVRTModelPODCopyCamera(const SPODCamera &in, SPODCamera &out, int nNumFrames)
  3509. {
  3510. memcpy(&out, &in, sizeof(SPODCamera));
  3511. out.pfAnimFOV = 0;
  3512. if(in.pfAnimFOV && SafeAlloc(out.pfAnimFOV, sizeof(*out.pfAnimFOV) * nNumFrames))
  3513. memcpy(out.pfAnimFOV, in.pfAnimFOV, sizeof(*out.pfAnimFOV) * nNumFrames);
  3514. }
  3515. /*!***************************************************************************
  3516. @Function PVRTModelPODCopyLight
  3517. @Input in
  3518. @Output out
  3519. @Description Used to copy a pod light
  3520. *****************************************************************************/
  3521. void PVRTModelPODCopyLight(const SPODLight &in, SPODLight &out)
  3522. {
  3523. memcpy(&out, &in, sizeof(SPODLight));
  3524. }
  3525. /*!***************************************************************************
  3526. @Function TransformCPODData
  3527. @Input in
  3528. @Output out
  3529. @Input idx Value to transform
  3530. @Input pPalette Palette of matrices to transform with
  3531. @Input pBoneIdx Array of indices into pPalette
  3532. @Input pBoneWeight Array of weights to weight the influence of the matrices of pPalette with
  3533. @Input i32BoneCnt Size of pBoneIdx and pBoneWeight
  3534. @Description Used to transform a particular value in a CPODData
  3535. *****************************************************************************/
  3536. inline void TransformCPODData(CPODData &in, CPODData &out, int idx, PVRTMATRIX *pPalette, float *pBoneIdx, float *pBoneW, int i32BoneCnt, bool bNormalise)
  3537. {
  3538. PVRTVECTOR4f fResult, fOrig, fTmp;
  3539. if(in.n)
  3540. {
  3541. PVRTVertexRead(&fOrig, in.pData + (idx * in.nStride), in.eType, in.n);
  3542. memset(&fResult.x, 0, sizeof(fResult));
  3543. if(i32BoneCnt)
  3544. {
  3545. for(int i = 0; i < i32BoneCnt; ++i)
  3546. {
  3547. int i32BoneIdx = (int) pBoneIdx[i];
  3548. 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;
  3549. 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;
  3550. 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;
  3551. 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;
  3552. fResult.x += fTmp.x * pBoneW[i];
  3553. fResult.y += fTmp.y * pBoneW[i];
  3554. fResult.z += fTmp.z * pBoneW[i];
  3555. fResult.w += fTmp.w * pBoneW[i];
  3556. }
  3557. }
  3558. else
  3559. {
  3560. 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;
  3561. 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;
  3562. 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;
  3563. 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;
  3564. }
  3565. if(bNormalise)
  3566. {
  3567. double temp = (double)(fResult.x * fResult.x + fResult.y * fResult.y + fResult.z * fResult.z);
  3568. temp = 1.0 / sqrt(temp);
  3569. float f = (float)temp;
  3570. fResult.x = fResult.x * f;
  3571. fResult.y = fResult.y * f;
  3572. fResult.z = fResult.z * f;
  3573. }
  3574. PVRTVertexWrite(out.pData + (idx * out.nStride), out.eType, in.n, &fResult);
  3575. }
  3576. }
  3577. /*!***************************************************************************
  3578. @Function PVRTModelPODFlattenToWorldSpace
  3579. @Input in - Source scene. All meshes must not be interleaved.
  3580. @Output out
  3581. @Description Used to flatten a pod scene to world space. All animation
  3582. and skinning information will be removed. The returned
  3583. position, normal, binormals and tangent data if present
  3584. will be returned as floats regardless of the input data
  3585. type.
  3586. *****************************************************************************/
  3587. EPVRTError PVRTModelPODFlattenToWorldSpace(CPVRTModelPOD &in, CPVRTModelPOD &out)
  3588. {
  3589. unsigned int i, j, k, l;
  3590. PVRTMATRIX mWorld;
  3591. // Destroy the out pod scene to make sure it is clean
  3592. out.Destroy();
  3593. // Init mesh and node arrays
  3594. SafeAlloc(out.pNode, sizeof(SPODNode) * in.nNumNode);
  3595. SafeAlloc(out.pMesh, sizeof(SPODMesh) * in.nNumMeshNode);
  3596. out.nNumNode = in.nNumNode;
  3597. out.nNumMesh = out.nNumMeshNode = in.nNumMeshNode;
  3598. // Init scene values
  3599. out.nNumFrame = 0;
  3600. out.nFlags = in.nFlags;
  3601. for(i = 0; i < 3; ++i)
  3602. {
  3603. out.pfColourBackground[i] = in.pfColourBackground[i];
  3604. out.pfColourAmbient[i] = in.pfColourAmbient[i];
  3605. }
  3606. // flatten meshes to world space
  3607. for(i = 0; i < in.nNumMeshNode; ++i)
  3608. {
  3609. SPODNode& inNode = in.pNode[i];
  3610. SPODNode& outNode = out.pNode[i];
  3611. // Get the meshes
  3612. SPODMesh& inMesh = in.pMesh[inNode.nIdx];
  3613. SPODMesh& outMesh = out.pMesh[i];
  3614. if(inMesh.pInterleaved != 0) // This function requires all the meshes to be de-interleaved
  3615. {
  3616. _ASSERT(inMesh.pInterleaved == 0);
  3617. out.Destroy(); // Tidy up
  3618. return PVR_FAIL;
  3619. }
  3620. // Copy the node
  3621. PVRTModelPODCopyNode(inNode, outNode, in.nNumFrame);
  3622. // Strip out animation and parenting
  3623. outNode.nIdxParent = -1;
  3624. outNode.nAnimFlags = 0;
  3625. FREE(outNode.pfAnimMatrix);
  3626. FREE(outNode.pfAnimPosition);
  3627. FREE(outNode.pfAnimRotation);
  3628. FREE(outNode.pfAnimScale);
  3629. // Update the mesh ID. The rest of the IDs should remain correct
  3630. outNode.nIdx = i;
  3631. // Copy the mesh
  3632. PVRTModelPODCopyMesh(inMesh, outMesh);
  3633. // Strip out skinning information as that is no longer needed
  3634. outMesh.sBoneBatches.Release();
  3635. outMesh.sBoneIdx.Reset();
  3636. outMesh.sBoneWeight.Reset();
  3637. // Set the data type to float and resize the arrays as this function outputs transformed data as float only
  3638. if(inMesh.sVertex.n)
  3639. {
  3640. outMesh.sVertex.eType = EPODDataFloat;
  3641. outMesh.sVertex.pData = (unsigned char*) realloc(outMesh.sVertex.pData, PVRTModelPODDataStride(outMesh.sVertex) * inMesh.nNumVertex);
  3642. }
  3643. if(inMesh.sNormals.n)
  3644. {
  3645. outMesh.sNormals.eType = EPODDataFloat;
  3646. outMesh.sNormals.pData = (unsigned char*) realloc(outMesh.sNormals.pData, PVRTModelPODDataStride(outMesh.sNormals) * inMesh.nNumVertex);
  3647. }
  3648. if(inMesh.sTangents.n)
  3649. {
  3650. outMesh.sTangents.eType = EPODDataFloat;
  3651. outMesh.sTangents.pData = (unsigned char*) realloc(outMesh.sTangents.pData, PVRTModelPODDataStride(outMesh.sTangents) * inMesh.nNumVertex);
  3652. }
  3653. if(inMesh.sBinormals.n)
  3654. {
  3655. outMesh.sBinormals.eType = EPODDataFloat;
  3656. outMesh.sBinormals.pData = (unsigned char*) realloc(outMesh.sBinormals.pData, PVRTModelPODDataStride(outMesh.sBinormals) * inMesh.nNumVertex);
  3657. }
  3658. if(inMesh.sBoneBatches.nBatchCnt)
  3659. {
  3660. unsigned int ui32BatchPaletteSize = 0;
  3661. PVRTMATRIX *pPalette = 0;
  3662. PVRTMATRIX *pPaletteInvTrans = 0;
  3663. unsigned int ui32Offset = 0, ui32Strip = 0;
  3664. bool *pbTransformed = 0;
  3665. SafeAlloc(pPalette, sizeof(PVRTMATRIX) * inMesh.sBoneBatches.nBatchBoneMax);
  3666. SafeAlloc(pPaletteInvTrans, sizeof(PVRTMATRIX) * inMesh.sBoneBatches.nBatchBoneMax);
  3667. SafeAlloc(pbTransformed, sizeof(bool) * inMesh.nNumVertex);
  3668. for(j = 0; j < (unsigned int) inMesh.sBoneBatches.nBatchCnt; ++j)
  3669. {
  3670. ui32BatchPaletteSize = (unsigned int) inMesh.sBoneBatches.pnBatchBoneCnt[j];
  3671. for(k = 0; k < ui32BatchPaletteSize; ++k)
  3672. {
  3673. // Get the Node of the bone
  3674. int i32NodeID = inMesh.sBoneBatches.pnBatches[j * inMesh.sBoneBatches.nBatchBoneMax + k];
  3675. // Get the World transformation matrix for this bone
  3676. in.GetBoneWorldMatrix(pPalette[k], inNode, in.pNode[i32NodeID]);
  3677. // Get the inverse transpose of the 3x3
  3678. if(inMesh.sNormals.n || inMesh.sTangents.n || inMesh.sBinormals.n)
  3679. {
  3680. pPaletteInvTrans[k] = pPalette[k];
  3681. pPaletteInvTrans[k].f[3] = pPaletteInvTrans[k].f[7] = pPaletteInvTrans[k].f[11] = 0;
  3682. pPaletteInvTrans[k].f[12] = pPaletteInvTrans[k].f[13] = pPaletteInvTrans[k].f[14] = 0;
  3683. PVRTMatrixInverse(pPaletteInvTrans[k], pPaletteInvTrans[k]);
  3684. PVRTMatrixTranspose(pPaletteInvTrans[k], pPaletteInvTrans[k]);
  3685. }
  3686. }
  3687. // Calculate the number of triangles in the current batch
  3688. unsigned int ui32Tris;
  3689. if(j + 1 < (unsigned int) inMesh.sBoneBatches.nBatchCnt)
  3690. ui32Tris = inMesh.sBoneBatches.pnBatchOffset[j + 1] - inMesh.sBoneBatches.pnBatchOffset[j];
  3691. else
  3692. ui32Tris = inMesh.nNumFaces - inMesh.sBoneBatches.pnBatchOffset[j];
  3693. unsigned int idx;
  3694. float fBoneIdx[4], fBoneWeights[4];
  3695. if(inMesh.nNumStrips == 0)
  3696. {
  3697. ui32Offset = 3 * inMesh.sBoneBatches.pnBatchOffset[j];
  3698. for(l = ui32Offset; l < ui32Offset + (ui32Tris * 3); ++l)
  3699. {
  3700. if(inMesh.sFaces.pData) // Indexed Triangle Lists
  3701. PVRTVertexRead(&idx, inMesh.sFaces.pData + (l * inMesh.sFaces.nStride), inMesh.sFaces.eType);
  3702. else // Indexed Triangle Lists
  3703. idx = l;
  3704. if(!pbTransformed[idx])
  3705. {
  3706. PVRTVertexRead((PVRTVECTOR4f*) &fBoneIdx[0], inMesh.sBoneIdx.pData + (idx * inMesh.sBoneIdx.nStride), inMesh.sBoneIdx.eType, inMesh.sBoneIdx.n);
  3707. PVRTVertexRead((PVRTVECTOR4f*) &fBoneWeights[0], inMesh.sBoneWeight.pData + (idx * inMesh.sBoneWeight.nStride), inMesh.sBoneWeight.eType, inMesh.sBoneWeight.n);
  3708. TransformCPODData(inMesh.sVertex, outMesh.sVertex, idx, pPalette, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, false);
  3709. TransformCPODData(inMesh.sNormals, outMesh.sNormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3710. TransformCPODData(inMesh.sTangents, outMesh.sTangents, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3711. TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3712. pbTransformed[idx] = true;
  3713. }
  3714. }
  3715. }
  3716. else
  3717. {
  3718. unsigned int ui32TrisDrawn = 0;
  3719. while(ui32TrisDrawn < ui32Tris)
  3720. {
  3721. for(l = ui32Offset; l < ui32Offset + (inMesh.pnStripLength[ui32Strip]+2); ++l)
  3722. {
  3723. if(inMesh.sFaces.pData) // Indexed Triangle Strips
  3724. PVRTVertexRead(&idx, inMesh.sFaces.pData + (l * inMesh.sFaces.nStride), inMesh.sFaces.eType);
  3725. else // Triangle Strips
  3726. idx = l;
  3727. if(!pbTransformed[idx])
  3728. {
  3729. PVRTVertexRead((PVRTVECTOR4f*) &fBoneIdx[0], inMesh.sBoneIdx.pData + (idx * inMesh.sBoneIdx.nStride), inMesh.sBoneIdx.eType, inMesh.sBoneIdx.n);
  3730. PVRTVertexRead((PVRTVECTOR4f*) &fBoneWeights[0], inMesh.sBoneWeight.pData + (idx * inMesh.sBoneWeight.nStride), inMesh.sBoneWeight.eType, inMesh.sBoneWeight.n);
  3731. TransformCPODData(inMesh.sVertex, outMesh.sVertex, idx, pPalette, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, false);
  3732. TransformCPODData(inMesh.sNormals, outMesh.sNormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3733. TransformCPODData(inMesh.sTangents, outMesh.sTangents, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3734. TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, idx, pPaletteInvTrans, &fBoneIdx[0], &fBoneWeights[0], inMesh.sBoneIdx.n, true);
  3735. pbTransformed[idx] = true;
  3736. }
  3737. }
  3738. ui32Offset += inMesh.pnStripLength[ui32Strip] + 2;
  3739. ui32TrisDrawn += inMesh.pnStripLength[ui32Strip];
  3740. ++ui32Strip;
  3741. }
  3742. }
  3743. }
  3744. FREE(pPalette);
  3745. FREE(pPaletteInvTrans);
  3746. FREE(pbTransformed);
  3747. }
  3748. else
  3749. {
  3750. // Get transformation matrix
  3751. in.GetWorldMatrix(mWorld, inNode);
  3752. PVRTMATRIX mWorldInvTrans;
  3753. // Get the inverse transpose of the 3x3
  3754. if(inMesh.sNormals.n || inMesh.sTangents.n || inMesh.sBinormals.n)
  3755. {
  3756. mWorldInvTrans = mWorld;
  3757. mWorldInvTrans.f[3] = mWorldInvTrans.f[7] = mWorldInvTrans.f[11] = 0;
  3758. mWorldInvTrans.f[12] = mWorldInvTrans.f[13] = mWorldInvTrans.f[14] = 0;
  3759. PVRTMatrixInverse(mWorldInvTrans, mWorldInvTrans);
  3760. PVRTMatrixTranspose(mWorldInvTrans, mWorldInvTrans);
  3761. }
  3762. // Transform the vertices
  3763. for(j = 0; j < inMesh.nNumVertex; ++j)
  3764. {
  3765. TransformCPODData(inMesh.sVertex, outMesh.sVertex, j, &mWorld, 0, 0, 0, false);
  3766. TransformCPODData(inMesh.sNormals, outMesh.sNormals, j, &mWorldInvTrans, 0, 0, 0, true);
  3767. TransformCPODData(inMesh.sTangents, outMesh.sTangents, j, &mWorldInvTrans, 0, 0, 0, true);
  3768. TransformCPODData(inMesh.sBinormals, outMesh.sBinormals, j, &mWorldInvTrans, 0, 0, 0, true);
  3769. }
  3770. }
  3771. }
  3772. // Copy the rest of the nodes
  3773. for(i = in.nNumMeshNode; i < in.nNumNode; ++i)
  3774. {
  3775. PVRTModelPODCopyNode(in.pNode[i], out.pNode[i], in.nNumFrame);
  3776. // Strip out animation and parenting
  3777. out.pNode[i].nIdxParent = -1;
  3778. out.pNode[i].nAnimFlags = 0;
  3779. FREE(out.pNode[i].pfAnimMatrix);
  3780. FREE(out.pNode[i].pnAnimMatrixIdx);
  3781. FREE(out.pNode[i].pfAnimPosition);
  3782. FREE(out.pNode[i].pnAnimPositionIdx);
  3783. FREE(out.pNode[i].pfAnimRotation);
  3784. FREE(out.pNode[i].pnAnimRotationIdx);
  3785. FREE(out.pNode[i].pfAnimScale);
  3786. FREE(out.pNode[i].pnAnimScaleIdx);
  3787. // Get world transformation matrix....
  3788. in.GetWorldMatrix(mWorld, in.pNode[i]);
  3789. // ...set the out node transformation matrix
  3790. if(SafeAlloc(out.pNode[i].pfAnimMatrix, sizeof(PVRTMATRIX)))
  3791. memcpy(out.pNode[i].pfAnimMatrix, mWorld.f, sizeof(PVRTMATRIX));
  3792. }
  3793. // Copy camera, lights
  3794. if(in.nNumCamera && SafeAlloc(out.pCamera, sizeof(SPODCamera) * in.nNumCamera))
  3795. {
  3796. out.nNumCamera = in.nNumCamera;
  3797. for(i = 0; i < in.nNumCamera; ++i)
  3798. PVRTModelPODCopyCamera(in.pCamera[i], out.pCamera[i], in.nNumFrame);
  3799. }
  3800. if(in.nNumLight && SafeAlloc(out.pLight, sizeof(SPODLight) * in.nNumLight))
  3801. {
  3802. out.nNumLight = in.nNumLight;
  3803. for(i = 0; i < out.nNumLight; ++i)
  3804. PVRTModelPODCopyLight(in.pLight[i], out.pLight[i]);
  3805. }
  3806. // Copy textures
  3807. if(in.nNumTexture && SafeAlloc(out.pTexture, sizeof(SPODTexture) * in.nNumTexture))
  3808. {
  3809. out.nNumTexture = in.nNumTexture;
  3810. for(i = 0; i < out.nNumTexture; ++i)
  3811. PVRTModelPODCopyTexture(in.pTexture[i], out.pTexture[i]);
  3812. }
  3813. // Copy materials
  3814. if(in.nNumMaterial && SafeAlloc(out.pMaterial, sizeof(SPODMaterial) * in.nNumMaterial))
  3815. {
  3816. out.nNumMaterial = in.nNumMaterial;
  3817. for(i = 0; i < in.nNumMaterial; ++i)
  3818. PVRTModelPODCopyMaterial(in.pMaterial[i], out.pMaterial[i]);
  3819. }
  3820. out.InitImpl();
  3821. return PVR_SUCCESS;
  3822. }
  3823. /*****************************************************************************
  3824. End of file (PVRTModelPOD.cpp)
  3825. *****************************************************************************/