// Copyright (C) 2002-2011 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by ZDimitor. //----------------------------------------------------------------------------- // This tool created by ZDimitor everyone can use it as wants //----------------------------------------------------------------------------- #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ #include "CMY3DMeshFileLoader.h" #include "SAnimatedMesh.h" #include "SMeshBuffer.h" #include "IReadFile.h" #include "IAttributes.h" #include "CImage.h" #include "CColorConverter.h" #include "CMY3DHelper.h" #include "os.h" // v3.15 - May 16, 2005 namespace irr { namespace scene { static const u32 MY3D_ID = 0x4d593344; static const u16 MY3D_VER = 0x0003; static const u16 MY3D_SCENE_HEADER_ID = 0x1000; static const u16 MY3D_MAT_LIST_ID = 0x2000; static const u16 MY3D_MAT_HEADER_ID = 0x2100; static const u16 MY3D_TEX_FNAME_ID = 0x2101; static const u16 MY3D_TEXDATA_HEADER_ID = 0x2501; static const u16 MY3D_TEXDATA_RLE_HEADER_ID = 0x2502; static const u16 MY3D_MESH_LIST_ID = 0x3000; static const u16 MY3D_MESH_HEADER_ID = 0x3100; static const u16 MY3D_VERTS_ID = 0x3101; static const u16 MY3D_FACES_ID = 0x3102; static const u16 MY3D_TVERTS_ID = 0x3103; static const u16 MY3D_TFACES_ID = 0x3104; static const u16 MY3D_FILE_END_ID = 0xFFFF; static const unsigned long MY3D_TEXDATA_COMPR_NONE_ID = 0x4e4f4e45; static const unsigned long MY3D_TEXDATA_COMPR_SIMPLE_ID = 0x53494d50; static const unsigned long MY3D_TEXDATA_COMPR_RLE_ID = 0x20524c45; static const unsigned long MY3D_PIXEL_FORMAT_24 = 0x5f32345f; static const unsigned long MY3D_PIXEL_FORMAT_16 = 0x5f31365f; CMY3DMeshFileLoader::CMY3DMeshFileLoader(ISceneManager* scmgr, io::IFileSystem* fs) : SceneManager(scmgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("CMY3DMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); } CMY3DMeshFileLoader::~CMY3DMeshFileLoader() { if (FileSystem) FileSystem->drop(); } bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "my3d" ); } IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) { MaterialEntry.clear(); MeshBufferEntry.clear(); ChildNodes.clear(); // working directory (from which we load the scene) core::stringc filepath = FileSystem->getFileDir(file->getFileName()); if (filepath==".") filepath=""; else filepath.append("/"); // read file into memory SMyFileHeader fileHeader; file->read(&fileHeader, sizeof(SMyFileHeader)); #ifdef __BIG_ENDIAN__ fileHeader.MyId = os::Byteswap::byteswap(fileHeader.MyId); fileHeader.Ver = os::Byteswap::byteswap(fileHeader.Ver); #endif if (fileHeader.MyId!=MY3D_ID || fileHeader.Ver!=MY3D_VER) { os::Printer::log("Bad MY3D file header, loading failed!", ELL_ERROR); return 0; } u16 id; file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_SCENE_HEADER_ID) { os::Printer::log("Cannot find MY3D_SCENE_HEADER_ID, loading failed!", ELL_ERROR); return 0; } SMySceneHeader sceneHeader; file->read(&sceneHeader, sizeof(SMySceneHeader)); #ifdef __BIG_ENDIAN__ sceneHeader.MaterialCount = os::Byteswap::byteswap(sceneHeader.MaterialCount); sceneHeader.MeshCount = os::Byteswap::byteswap(sceneHeader.MeshCount); #endif file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_MAT_LIST_ID) { os::Printer::log("Can not find MY3D_MAT_LIST_ID, loading failed!", ELL_ERROR); return 0; } core::stringc texturePath = SceneManager->getParameters()->getAttributeAsString(MY3D_TEXTURE_PATH); file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif c8 namebuf[256]; for (s32 m=0; m<sceneHeader.MaterialCount; ++m) { if (id != MY3D_MAT_HEADER_ID) { os::Printer::log("Cannot find MY3D_MAT_HEADER_ID, loading failed!", ELL_ERROR); return 0; } // read material header MaterialEntry.push_back(SMyMaterialEntry()); SMyMaterialEntry& me=MaterialEntry.getLast(); file->read(&(me.Header), sizeof(SMyMaterialHeader)); // read next identificator file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif bool gotLightMap=false, gotMainMap=false; for (u32 t=0; t<me.Header.TextureCount; ++t) { if (id==MY3D_TEX_FNAME_ID) file->read(namebuf, 256); else { me.Texture2 = readEmbeddedLightmap(file, namebuf); if (!me.Texture2) return 0; gotLightMap = true; } const core::stringc name = namebuf; const s32 pos = name.findLast('.'); const core::stringc LightingMapStr = "LightingMap"; const s32 ls = LightingMapStr.size(); const bool isSubString = (LightingMapStr == name.subString(core::max_(0, (pos - ls)), ls)); if ((isSubString || (name[pos-1]=='m' && name[pos-2]=='l' && name[pos-3]=='_')) && !gotLightMap) { const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); me.Texture2FileName = texturePath.size() ? texturePath : filepath; me.Texture2FileName.append("Lightmaps/"); me.Texture2FileName.append(name); if (name.size()) me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_LIGHTMAP_M2; gotLightMap = true; SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); } else if (!gotLightMap && gotMainMap) { me.Texture2FileName = texturePath.size() ? texturePath : filepath; me.Texture2FileName.append(name); if (name.size()) me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_REFLECTION_2_LAYER; } else if (!gotMainMap && !gotLightMap) { me.Texture1FileName = filepath; me.Texture1FileName.append(name); if (name.size()) me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName); gotMainMap = true; me.MaterialType = video::EMT_SOLID; } else if (gotLightMap) { me.MaterialType = video::EMT_LIGHTMAP_M2; } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif } // override material types based on their names if (!strncmp(me.Header.Name, "AlphaChannel-", 13)) me.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; else if (!strncmp(me.Header.Name, "SphereMap-", 10)) me.MaterialType = video::EMT_SPHERE_MAP; } // loading meshes if (id!=MY3D_MESH_LIST_ID) { os::Printer::log("Can not find MY3D_MESH_LIST_ID, loading failed!", ELL_ERROR); return 0; } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif for (s32 mesh_id=0; mesh_id<sceneHeader.MeshCount; mesh_id++) { // Warning!!! In some cases MY3D exporter uncorrectly calculates // MeshCount (it's a problem, has to be solved) thats why // i added this code line if (id!=MY3D_MESH_HEADER_ID) break; if (id!=MY3D_MESH_HEADER_ID) { os::Printer::log("Can not find MY3D_MESH_HEADER_ID, loading failed!", ELL_ERROR); return 0; } SMyMeshHeader meshHeader; file->read(&meshHeader, sizeof(SMyMeshHeader)); core::array <SMyVertex> Vertex; core::array <SMyFace> Face; core::array <SMyTVertex> TVertex1, TVertex2; core::array <SMyFace> TFace1, TFace2; s32 vertsNum=0; s32 facesNum=0; // vertices file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_VERTS_ID) { os::Printer::log("Can not find MY3D_VERTS_ID, loading failed!", ELL_ERROR); return 0; } file->read(&vertsNum, sizeof(vertsNum)); Vertex.set_used(vertsNum); file->read(Vertex.pointer(), sizeof(SMyVertex)*vertsNum); // faces file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_FACES_ID) { os::Printer::log("Can not find MY3D_FACES_ID, loading failed!", ELL_ERROR); return 0; } file->read(&facesNum, sizeof(facesNum)); Face.set_used(facesNum); file->read(Face.pointer(), sizeof(SMyFace)*facesNum); // reading texture channels for (s32 tex=0; tex<(s32)meshHeader.TChannelCnt; tex++) { // Max 2 texture channels allowed (but in format .my3d can be more) s32 tVertsNum=0, tFacesNum=0; // reading texture coords file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TVERTS_ID) { core::stringc msg="Can not find MY3D_TVERTS_ID ("; msg.append(core::stringc(tex)); msg.append("texture channel), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } file->read(&tVertsNum, sizeof(tVertsNum)); if (tex==0) { // 1st texture channel TVertex1.set_used(tVertsNum); file->read(TVertex1.pointer(), sizeof(SMyTVertex)*tVertsNum); } else if (tex==1) { // 2nd texture channel TVertex2.set_used(tVertsNum); file->read(TVertex2.pointer(), sizeof(SMyTVertex)*tVertsNum); } else { // skip other texture channels file->seek(file->getPos()+sizeof(SMyTVertex)*tVertsNum); } // reading texture faces file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TFACES_ID) { core::stringc msg="Can not find MY3D_TFACES_ID ("; msg.append(core::stringc(tex)); msg.append("texture channel), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } file->read(&tFacesNum, sizeof(tFacesNum)); if (tex==0) { // 1st texture channel TFace1.set_used(tFacesNum); file->read(TFace1.pointer(), sizeof(SMyFace)*tFacesNum); } else if (tex==1) { // 2nd texture channel TFace2.set_used(tFacesNum); file->read(TFace2.pointer(), sizeof(SMyFace)*tFacesNum); } else { // skip other texture channels file->seek(file->getPos()+sizeof(SMyFace)*tFacesNum); } } // trying to find material SMyMaterialEntry* matEnt = getMaterialEntryByIndex(meshHeader.MatIndex); // creating geometry for the mesh // trying to find mesh buffer for this material SMeshBufferLightMap* buffer = getMeshBufferByMaterialIndex(meshHeader.MatIndex); if (!buffer || (buffer->Vertices.size()+vertsNum) > SceneManager->getVideoDriver()->getMaximalPrimitiveCount()) { // creating new mesh buffer for this material buffer = new scene::SMeshBufferLightMap(); buffer->Material.MaterialType = video::EMT_LIGHTMAP_M2; // EMT_LIGHTMAP_M4 also possible buffer->Material.Wireframe = false; buffer->Material.Lighting = false; if (matEnt) { buffer->Material.MaterialType = matEnt->MaterialType; if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER) { buffer->Material.Lighting = true; buffer->Material.setTexture(1, matEnt->Texture1); buffer->Material.setTexture(0, matEnt->Texture2); } else { buffer->Material.setTexture(0, matEnt->Texture1); buffer->Material.setTexture(1, matEnt->Texture2); } if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { buffer->Material.BackfaceCulling = true; buffer->Material.Lighting = true; } else if (buffer->Material.MaterialType == video::EMT_SPHERE_MAP) { buffer->Material.Lighting = true; } buffer->Material.AmbientColor = video::SColor( matEnt->Header.AmbientColor.A, matEnt->Header.AmbientColor.R, matEnt->Header.AmbientColor.G, matEnt->Header.AmbientColor.B ); buffer->Material.DiffuseColor = video::SColor( matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R, matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B ); buffer->Material.EmissiveColor = video::SColor( matEnt->Header.EmissiveColor.A, matEnt->Header.EmissiveColor.R, matEnt->Header.EmissiveColor.G, matEnt->Header.EmissiveColor.B ); buffer->Material.SpecularColor = video::SColor( matEnt->Header.SpecularColor.A, matEnt->Header.SpecularColor.R, matEnt->Header.SpecularColor.G, matEnt->Header.SpecularColor.B ); } else { buffer->Material.setTexture(0, 0); buffer->Material.setTexture(1, 0); buffer->Material.AmbientColor = video::SColor(255, 255, 255, 255); buffer->Material.DiffuseColor = video::SColor(255, 255, 255, 255); buffer->Material.EmissiveColor = video::SColor(0, 0, 0, 0); buffer->Material.SpecularColor = video::SColor(0, 0, 0, 0); } if (matEnt && matEnt->Header.Transparency!=0) { if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER ) { buffer->Material.MaterialType = video::EMT_TRANSPARENT_REFLECTION_2_LAYER; buffer->Material.Lighting = true; buffer->Material.BackfaceCulling = true; } else { buffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; buffer->Material.Lighting = false; buffer->Material.BackfaceCulling = false; } } else if ( !buffer->Material.getTexture(1) && buffer->Material.MaterialType != video::EMT_TRANSPARENT_ALPHA_CHANNEL && buffer->Material.MaterialType != video::EMT_SPHERE_MAP) { buffer->Material.MaterialType = video::EMT_SOLID; buffer->Material.Lighting = true; } MeshBufferEntry.push_back( SMyMeshBufferEntry(meshHeader.MatIndex, buffer)); } video::S3DVertex2TCoords VertexA, VertexB, VertexC; // vertices (A, B, C) color video::SColor vert_color; if (matEnt && (buffer->Material.MaterialType == video::EMT_TRANSPARENT_VERTEX_ALPHA || buffer->Material.MaterialType == video::EMT_TRANSPARENT_REFLECTION_2_LAYER)) { video::SColor color( matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R, matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B); vert_color = color.getInterpolated(video::SColor(0,0,0,0), 1-matEnt->Header.Transparency); } else { vert_color = buffer->Material.DiffuseColor; } VertexA.Color = VertexB.Color = VertexC.Color = vert_color; if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { buffer->Indices.reallocate(buffer->Indices.size()+6*facesNum); buffer->Vertices.reallocate(buffer->Vertices.size()+6*facesNum); } else { buffer->Indices.reallocate(buffer->Indices.size()+3*facesNum); buffer->Vertices.reallocate(buffer->Vertices.size()+3*facesNum); } for (int f=0; f<facesNum; f++) { // vertex A VertexA.Pos.X = Vertex[Face[f].C].Coord.X; VertexA.Pos.Y = Vertex[Face[f].C].Coord.Y; VertexA.Pos.Z = Vertex[Face[f].C].Coord.Z; VertexA.Normal.X = Vertex[Face[f].C].Normal.X; VertexA.Normal.Y = Vertex[Face[f].C].Normal.Y; VertexA.Normal.Z = Vertex[Face[f].C].Normal.Z; if (meshHeader.TChannelCnt>0) { VertexA.TCoords.X = TVertex1[TFace1[f].C].TCoord.X; VertexA.TCoords.Y = TVertex1[TFace1[f].C].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexA.TCoords2.X = TVertex2[TFace2[f].C].TCoord.X; VertexA.TCoords2.Y = TVertex2[TFace2[f].C].TCoord.Y; } // vertex B VertexB.Pos.X = Vertex[Face[f].B].Coord.X; VertexB.Pos.Y = Vertex[Face[f].B].Coord.Y; VertexB.Pos.Z = Vertex[Face[f].B].Coord.Z; VertexB.Normal.X = Vertex[Face[f].B].Normal.X; VertexB.Normal.Y = Vertex[Face[f].B].Normal.Y; VertexB.Normal.Z = Vertex[Face[f].B].Normal.Z; if (meshHeader.TChannelCnt>0) { VertexB.TCoords.X = TVertex1[TFace1[f].B].TCoord.X; VertexB.TCoords.Y = TVertex1[TFace1[f].B].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexB.TCoords2.X = TVertex2[TFace2[f].B].TCoord.X; VertexB.TCoords2.Y = TVertex2[TFace2[f].B].TCoord.Y; } // vertex C VertexC.Pos.X = Vertex[Face[f].A].Coord.X; VertexC.Pos.Y = Vertex[Face[f].A].Coord.Y; VertexC.Pos.Z = Vertex[Face[f].A].Coord.Z; VertexC.Normal.X = Vertex[Face[f].A].Normal.X; VertexC.Normal.Y = Vertex[Face[f].A].Normal.Y; VertexC.Normal.Z = Vertex[Face[f].A].Normal.Z; if (meshHeader.TChannelCnt>0) { VertexC.TCoords.X = TVertex1[TFace1[f].A].TCoord.X; VertexC.TCoords.Y = TVertex1[TFace1[f].A].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexC.TCoords2.X = TVertex2[TFace2[f].A].TCoord.X; VertexC.TCoords2.Y = TVertex2[TFace2[f].A].TCoord.Y; } // store 3d data in mesh buffer buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexA); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexB); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexC); //***************************************************************** // !!!!!! W A R N I N G !!!!!!! //***************************************************************** // For materials with alpha channel we duplicate all faces. // This has be done for proper lighting calculation of the back faces. // So you must remember this while you creating your models !!!!! //***************************************************************** // !!!!!! W A R N I N G !!!!!!! //***************************************************************** if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { VertexA.Normal = core::vector3df(-VertexA.Normal.X, -VertexA.Normal.Y, -VertexA.Normal.Z); VertexB.Normal = core::vector3df(-VertexB.Normal.X, -VertexB.Normal.Y, -VertexB.Normal.Z); VertexC.Normal = core::vector3df(-VertexC.Normal.X, -VertexC.Normal.Y, -VertexC.Normal.Z); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexC); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexB); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexA); } } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif } // creating mesh SMesh* mesh = new SMesh(); for (u32 num=0; num<MeshBufferEntry.size(); ++num) { SMeshBufferLightMap* buffer = MeshBufferEntry[num].MeshBuffer; if (!buffer) continue; mesh->addMeshBuffer(buffer); buffer->recalculateBoundingBox(); buffer->drop(); } mesh->recalculateBoundingBox(); if (id != MY3D_FILE_END_ID) os::Printer::log("Loading finished, but can not find MY3D_FILE_END_ID token.", ELL_WARNING); SAnimatedMesh* am = new SAnimatedMesh(); am->addMesh(mesh); mesh->drop(); am->recalculateBoundingBox(); return am; } video::ITexture* CMY3DMeshFileLoader::readEmbeddedLightmap(io::IReadFile* file, char* namebuf) { static int LightMapIndex=0; u16 id; file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TEXDATA_HEADER_ID) { os::Printer::log("Can not find MY3D_TEXDATA_HEADER_ID, loading failed!", ELL_ERROR); return 0; } SMyTexDataHeader texDataHeader; file->read(&texDataHeader, sizeof(SMyTexDataHeader)); strcpy(texDataHeader.Name, namebuf); char LightMapName[255]; sprintf(LightMapName,"My3D.Lightmap.%d",++LightMapIndex); core::stringc pixFormatStr; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) pixFormatStr = "24bit,"; else if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_16) pixFormatStr = "16bit,"; else { core::stringc msg="Unknown format of image data ("; msg.append(LightMapName); msg.append("), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } if (texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_NONE_ID && texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_RLE_ID && texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_SIMPLE_ID ) { os::Printer::log("Unknown method of compression image data, loading failed!", ELL_ERROR); return 0; } const u32 num_pixels = texDataHeader.Width*texDataHeader.Height; void* data = 0; if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_NONE_ID) { // none compressed image data if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { data = (void*) new SMyPixelColor24[num_pixels]; file->read(data, sizeof(SMyPixelColor24)*num_pixels); } else { data = (void*) new SMyPixelColor16[num_pixels]; file->read(data, sizeof(SMyPixelColor16)*num_pixels); } } else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_RLE_ID) { // read RLE header identificator file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TEXDATA_RLE_HEADER_ID) { os::Printer::log("Can not find MY3D_TEXDATA_RLE_HEADER_ID, loading failed!", ELL_ERROR); return 0; } // read RLE header SMyRLEHeader rleHeader; file->read(&rleHeader, sizeof(SMyRLEHeader)); //allocate memory for input and output buffers void *input_buffer = (void*) new unsigned char[rleHeader.nEncodedBytes]; void *output_buffer = (void*) new unsigned char[rleHeader.nDecodedBytes]; // read encoded data file->read(input_buffer, rleHeader.nEncodedBytes); // decode data data = 0;//(void*) new unsigned char[rleHeader.nDecodedBytes]; s32 decodedBytes = core::rle_decode( (unsigned char*)input_buffer, rleHeader.nEncodedBytes, (unsigned char*)output_buffer, rleHeader.nDecodedBytes); if (decodedBytes!=(s32)rleHeader.nDecodedBytes) { os::Printer::log("Error extracting data from RLE compression, loading failed!", ELL_ERROR); return 0; } // free input buffer delete [] (unsigned char*)input_buffer; // here decoded data data = output_buffer; } else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_SIMPLE_ID) { // simple compressed image data if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) data = (void*) new SMyPixelColor24[num_pixels]; else data = (void*) new SMyPixelColor16[num_pixels]; u32 nReadedPixels=0, nToRead=0; while (true) { file->read(&nToRead, sizeof(nToRead)); if ((nReadedPixels+nToRead) > num_pixels) break; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { SMyPixelColor24 col24; file->read(&col24, sizeof(SMyPixelColor24)); for (u32 p=0; p<nToRead; p++) { ((SMyPixelColor24*)data)[nReadedPixels+p] = SMyPixelColor24(col24.r, col24.g, col24.b); } } else { SMyPixelColor16 col16; file->read(&col16, sizeof(SMyPixelColor16)); for (u32 p=0; p<nToRead; p++) ((SMyPixelColor16*)data)[nReadedPixels+p].argb = col16.argb; } nReadedPixels+=nToRead; if (nReadedPixels >= num_pixels) break; } if (nReadedPixels != num_pixels) { os::Printer::log("Image data seems to be corrupted, loading failed!", ELL_ERROR); return 0; } } //! Creates a software image from a byte array. video::IImage* light_img = 0; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { // 24 bit lightmap format light_img = SceneManager->getVideoDriver()->createImageFromData( video::ECF_R8G8B8, core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height), data, true); } else { // 16 bit lightmap format light_img = SceneManager->getVideoDriver()->createImageFromData( video::ECF_A1R5G5B5, core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height), data, true); } const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); video::ITexture* lmtex = SceneManager->getVideoDriver()->addTexture(LightMapName, light_img); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); light_img->drop(); return lmtex; } CMY3DMeshFileLoader::SMyMaterialEntry* CMY3DMeshFileLoader::getMaterialEntryByIndex(u32 matInd) { for (u32 m=0; m<MaterialEntry.size(); ++m) if (MaterialEntry[m].Header.Index == matInd) return &MaterialEntry[m]; return 0; } SMeshBufferLightMap* CMY3DMeshFileLoader::getMeshBufferByMaterialIndex(u32 matInd) { for (u32 m=0; m<MeshBufferEntry.size(); ++m) { if (MeshBufferEntry[m].MaterialIndex == (s32)matInd) return MeshBufferEntry[m].MeshBuffer; } return 0; } const core::array<ISceneNode*>& CMY3DMeshFileLoader::getChildNodes() const { return ChildNodes; } } // end namespace scnene } // end namespace irr #endif // _IRR_COMPILE_WITH_MY3D_LOADER_
Options | Liens officiels | Caractéristiques | Statistiques | Communauté |
---|---|---|---|---|
Corrections |
|
xhtml 1.0 css 2.1 Propulsé par FluxBB Traduit par FluxBB.fr |
882 membres 1429 sujets 11119 messages |
Dernier membre inscrit: LiseBuisson96 44 invités en ligne Aucun membre connecté RSS Feed |