#ifndef _CGRAPHICSMODEL #define _CGRAPHICSMODEL #include "CAABox.bt" #include "CEvalSystem.bt" #include "CVector4i.bt" #include "CColor4f.bt" #include "CRenderOctree.bt" #include "NGraphicsMaterial.bt" #include "CMaterialInstanceResource.bt" struct SModelAnimatedUVData { CEvalSystem evalSystem; uint evalIdCount; CEvalId evalId[evalIdCount]; uint vec4iCount; CVector4i vec4is[vec4iCount]; uint unkCount; char unk[unkCount]; if (!isDKCTF) { uchar unk2; } }; struct SModelWindData { uint32 windSets; struct WindSet { CVector3f WindMin; CVector3f WindMax; float unk; } windset[windSets]; // uint32 unkD; // byte unkData[unkD]; }; struct SCausticData { uint32 unkD; uint32 unkData[unkD]; }; // CModelDataSource struct DataSourceLoader { if (ReadByte() == 0) //Type for WiiU is an I32 { uint32 tmpFormatI32; switch (tmpFormatI32) { case 0: local FourCC type = "ANUV"; break; case 1: local FourCC type = "WIND"; break; case 2: local FourCC type = "CAUS"; break; } } else { FourCC type; } switch (type) { case "ANUV": // NModelCustomData::sAnimUvDataSourceLoader SModelAnimatedUVData animatedUvs; break; case "WIND": // NModelCustomData::sWindModelDataSourceLoader SModelWindData wind; break; case "CAUS": // NModelCustomData::sCausticDataSourceLoader SCausticData caustic; break; } // NModelCustomData::sSkinnedModelAnimUvDataSourceLoader // NModelCustomData::sVertAnimModelDataSourceLoader }; struct CustomDataLoader { FourCC type; // CModelCustomDataMPT // byte b; // if (b) CModelSurfaceMetaDataMPT }; struct ModelHeader { if (isDKCTF == 1) { uint opaqueMeshes; uint onePassTransMeshes; uint TwoPassTransMeshes; uint oneBitMeshes; uint additiveMeshes; } else { uint unk1; } CAABox bounds; uint dataSourceCount; local int i; for (i = 0; i < dataSourceCount; ++i) { DataSourceLoader dataSource; } if (isDKCTF == 0) { uchar unk2; if (unk2) { CustomDataLoader customData; } } }; typedef struct(int readerVersion, int writerVersion) { FourCC id ; FourCC type ; } MaterialType ; struct STextureUsageInfo { uint flags; uint filter; uint wrapX; uint wrapY; uint wrapZ; }; struct SSkinnedModelHeader { uint unk; if (!isDKCTF) { uint unk; uint unk; uint unk; uint uintsCount; uint uints[uintsCount]; uint dataCount; char data[dataCount]; } }; struct SWorldModelHeader { uchar unk; }; enum ECachedGraphicsTransform { XF_MODEL_TO_WORLD_MTX = 0, // uc_modelToWorldMatrix XF_WORLD_TO_MODEL_MTX = 1, // uc_worldToModelMatrix XF_WORLD_TO_VIEW_MTX = 2, // uc_worldToViewMatrix XF_PROJECTION_MTX = 3, // uc_projectionMatrix XF_MODEL_VIEW_MTX = 4, // uc_modelViewMatrix XF_MODEL_VIEW_PROJECTION_MTX = 5, // uc_modelViewProjectionMatrix XF_PROJECTION_INVERSE_MTX = 6, // uc_projectionInverseMatrix XF_NORMAL_MTX = 7, // uc_normalMatrix XF_CUSTOM_MTX_0 = 8, // uc_customMatrix0 }; enum EVertexComponent { VTX_POSITION = 0, // in_position VTX_NORMAL = 1, // in_normal VTX_TANGENT0 = 2, // in_tangent[0] VTX_TANGENT1 = 3, // in_tangent[1] VTX_TANGENT2 = 4, // in_tangent[2] VTX_TEXCOORD0 = 5, // in_texCoord[0] VTX_TEXCOORD1 = 6, // in_texCoord[1] VTX_TEXCOORD2 = 7, // in_texCoord[2] VTX_TEXCOORD3 = 8, // in_texCoord[3] VTX_COLOR = 9, // in_color VTX_BONE_INDICES = 10, // in_boneIndices VTX_BONE_WEIGHTS = 11, // in_boneWeights VTX_BAKED_LIGHTING_COORD = 12, // in_bakedLightingCoord VTX_BAKED_LIGHTING_TANGENT = 13, // in_bakedLightingTangent VTX_VERT_INSTANCE_PARAMS = 14, // in_vertInstanceParams VTX_VERT_INSTANCE_COLOR = 15, // in_vertInstanceColor VTX_VERT_TRANSFORM0 = 16, // in_vertTransform[0] VTX_VERT_TRANSFORM1 = 17, // in_vertTransform[1] VTX_VERT_TRANSFORM2 = 18, // in_vertTransform[2] VTX_CURRENT_POSITION = 19, // in_currentPosition VTX_VERT_INSTANCE_OPACITY_PARAMS = 20, // in_vertInstanceOpacityParams VTX_VERT_INSTANCE_COLOR_INDEXING_PARAMS = 21, // in_vertInstanceColorIndexingParams VTX_VERT_INSTANCE_OPACITY_INDEXING_PARAMS = 22, // in_vertInstanceOpacityIndexingParams VTX_VERT_INSTANCE_PAINT_PARAMS = 23, // in_vertInstancePaintParams VTX_BAKED_LIGHTING_LOOKUP = 24, // in_bakedLightingLookup VTX_MATERIAL_CHOICE0 = 25, // in_materialChoice[0] VTX_MATERIAL_CHOICE1 = 26, // in_materialChoice[1] VTX_MATERIAL_CHOICE2 = 27, // in_materialChoice[2] VTX_MATERIAL_CHOICE3 = 28, // in_materialChoice[3] }; enum EMaterialDataType { DATA_TYPE_NONE = 0, DATA_TYPE_TEXTURE = 1, // TXTR DATA_TYPE_COLOR = 2, // COLR DATA_TYPE_SCALAR = 3, // SCLR DATA_TYPE_INT1 = 4, // INT1 DATA_TYPE_COMPLEX = 5, // CPLX DATA_TYPE_INT4 = 6, // INT4 DATA_TYPE_MAT4 = 7, // MAT4 }; EMaterialDataType MapMaterialDataType(FourCC value) { switch (value) { case "TXTR": return DATA_TYPE_TEXTURE; case "COLR": return DATA_TYPE_COLOR; case "SCLR": return DATA_TYPE_SCALAR; case "INT1": return DATA_TYPE_INT1; case "CPLX": return DATA_TYPE_COMPLEX; case "INT4": return DATA_TYPE_INT4; case "MAT4": return DATA_TYPE_MAT4; default: return DATA_TYPE_NONE; } } string ReadMaterialDataType(FourCC value) { EMaterialDataType type = MapMaterialDataType(value); return EnumToString(type); } typedef struct { GUID id; if (id != GUIDZero || isDKCTF) { STextureUsageInfo usage; } //Detect isDKCTF to force it on NS models } CMaterialTextureTokenData ; enum EBlendControl { // TODO }; struct SBlendRegs { CColor4f colors[3]; }; struct CLayeredTextureBaseData { EBlendControl blendControl; SBlendRegs regs; byte flags; }; struct CLayeredTextureData { CLayeredTextureBaseData base; CMaterialTextureTokenData textures[3]; }; typedef struct(int readerVersion, int writerVersion) { FourCC id ; if (ReadByte() == 0) //Fix DKCTF WiiU models { uint32 tmpFormatI32; //Do this so we can get the fancy struct names switch (tmpFormatI32) { case 0: local FourCC type = "TXTR"; CMaterialTextureTokenData texture; break; case 1: local FourCC type = "COLR"; float color[4]; break; case 2: local FourCC type = "SCLR"; float scalar; break; case 3: local FourCC type = "INT1"; //Not sure if in DKCTF but need to dcheck int int1; break; case 4: local FourCC type = "CPLX"; byte unk[141]; break; case 5: local FourCC type = "INT4"; int int4[4]; break; case 6: local FourCC type = "MAT4"; //Not sure if in DKCTF but need to dcheck float mtx[16]; break; } } else { FourCC type ; switch (MapMaterialDataType(type)) { case DATA_TYPE_TEXTURE: CMaterialTextureTokenData texture; break; case DATA_TYPE_COLOR: CColor4f color; break; case DATA_TYPE_SCALAR: float scalar; break; case DATA_TYPE_INT1: int int1; break; case DATA_TYPE_INT4: CVector4i int4; break; case DATA_TYPE_MAT4: float mtx[16]; // CMatrix4f break; case DATA_TYPE_COMPLEX: if (isDKCTF) { byte unk[141]; } else { local EMaterialDataId dataId = MapMaterialDataId(id); if (IsTextureLayeredMaterialDataId(dataId)) { CLayeredTextureData data; } else if (IsTextureMaterialDataId(dataId)) { // TODO } else if (dataId == DATA_ID_XCH0) { byte unk[56]; } } break; } } } CMaterialData ; string CMaterialDataRead(CMaterialData &mat) { switch (MapMaterialDataType(mat.type)) { case DATA_TYPE_TEXTURE: return Str("Texture %s = %s", mat.id, GUIDToString(mat.texture.id)); case DATA_TYPE_COLOR: return Str("Color %s = %s", mat.id, ColorToString(mat.color)); case DATA_TYPE_SCALAR: return Str("Scalar %s = %f", mat.id, mat.scalar); case DATA_TYPE_INT1: return Str("Int %s = %f", mat.id, mat.int1); case DATA_TYPE_INT4: return Str("Int4 %s = %s", mat.id, Vec4iToString(mat.int4)); case DATA_TYPE_COMPLEX: return Str("Complex %s", mat.id); } return ""; } typedef struct(int readerVersion, int writerVersion) { if (ReadByte() == 0 || !isDKCTF) //NS, use anti isDKCTF so MP1R models don't break { local uint useMaterialTypeChunk = 1; CStringFixed name; } else { local uint useMaterialTypeChunk = 0; CString name; } GUID shaderID; if (isDKCTF) { local uint traitCount = 1; //Hack it to 1 } else { GUID guid2; //unsure uint unk1; uint unk2; uint traitCount; } if (traitCount != 0) { struct { FourCC value; } traits[traitCount] ; } if (isDKCTF == 1) { uint flags; } else { uint variableDescCount; if (variableDescCount != 0) { CVariableDesc variableDescs[variableDescCount]; } } //material data types if (readerVersion != 163) { // Metroid Prime remastered and earlier uint dataCount; if (useMaterialTypeChunk || !isDKCTF) { MaterialType dataTypes(readerVersion, writerVersion)[dataCount]; } } else { uint dataCount; } // data parse CMaterialData materialData(readerVersion, writerVersion)[dataCount] ; } CMaterialCache ; typedef struct { if (isDKCTF) { uint32 PrimitiveMode; } ushort MaterialIndex; byte VertexBufferIndex; byte IndexBufferIndex; uint IndexStart; uint IndexCount; uint Flags; if (isDKCTF) { byte unk; } } CRenderMesh; struct SMeshLoadInformation { uint meshCount; CRenderMesh meshes[meshCount] ; byte unk[(meshCount + 3) / 4]; byte unk2[(meshCount + 7) / 8]; uint shortCount; if (shortCount > 0) { uint16 shorts[shortCount]; } byte lodCount; struct { struct { uint32 a; uint32 b; } inner[5]; } outer[lodCount]; uint32 hasLodRule; if (hasLodRule == 1) { float lodRule[lodCount]; } }; enum EVertexDataFormat { FMT_R8_UNORM = 0, FMT_R8_UINT = 1, FMT_R8_SNORM = 2, FMT_R8_SINT = 3, FMT_R16_UNORM = 4, FMT_R16_UINT = 5, FMT_R16_SNORM = 6, FMT_R16_SINT = 7, FMT_R16_FLOAT = 8, FMT_RG8_UNORM = 9, FMT_RG8_UINT = 10, FMT_RG8_SNORM = 11, FMT_RG8_SINT = 12, FMT_R32_UINT = 13, FMT_R32_SINT = 14, FMT_R32_FLOAT = 15, FMT_RG16_UNORM = 16, FMT_RG16_UINT = 17, FMT_RG16_SNORM = 18, FMT_RG16_SINT = 19, FMT_RG16_FLOAT = 20, FMT_RGBA8_UNORM = 21, FMT_RGBA8_UINT = 22, FMT_RGBA8_SNORM = 23, FMT_RGBA8_SINT = 24, FMT_RGB10A2_UNORM = 25, FMT_RGB10A2_UINT = 26, FMT_RG32_UINT = 27, FMT_RG32_SINT = 28, FMT_RG32_FLOAT = 29, FMT_RGBA16_UNORM = 30, FMT_RGBA16_UINT = 31, FMT_RGBA16_SNORM = 32, FMT_RGBA16_SINT = 33, FMT_RGBA16_FLOAT = 34, FMT_RGB32_UINT = 35, FMT_RGB32_SINT = 36, FMT_RGB32_FLOAT = 37, FMT_RGBA32_UINT = 38, FMT_RGBA32_SINT = 39, FMT_RGBA32_FLOAT = 40, }; struct SVertexDataComponent { uint32 bufferIndex; uint32 offset; uint32 stride; EVertexDataFormat format; EVertexComponent component; }; struct SVertexBufferInfo { // uint32 vertexCount; uint32 numAttributes; SVertexDataComponent component[numAttributes]; if (!isDKCTF) { uint32 unk2; byte unk; } }; struct CGraphicsVertexBufferToken { uint32 count; SVertexBufferInfo info[count] ; }; enum EBufferType { INDEX_U8 = 0, // ? INDEX_U16 = 1, INDEX_U32 = 2, }; struct CGraphicsIndexBufferToken { uint32 count; EBufferType type[count]; }; typedef struct(int readerVersion, int writerVersion) { ChunkDescriptor chunk; local uint pos