//! looks if file is in the same directory of path. returns offset of directory. //! 0 means in same directory. 1 means file is direct child of path s32 ioutils::isInSameDirectory(const core::stringc& path, const core::stringc& file) { s32 subA = 0; s32 subB = 0; s32 pos; if (path.size() && !path.equalsn(file, path.size())) return -1; pos = 0; while ((pos = path.findFirst('/', pos)) >= 0) { subA += 1; pos += 1; } pos = 0; while ((pos = file.findFirst('/', pos)) >= 0) { subB += 1; pos += 1; } return subB - subA; }
//! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); // get number of chars after last dot s32 end = 0; if (!keepExtension) { // take care to search only after last slash to check only for // dots in the filename end = filename.findLast('.', lastSlash); if (end == -1) end=0; else end = filename.size()-end; } if ((u32)lastSlash < filename.size()) return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); else if (end != 0) return filename.subString(0, filename.size()-end); else return filename; }
bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; }
bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); for (u32 j=0; j<indexCount; j+=3) { writeFace(file, buffer->getPosition(buffer->getIndices()[j]), buffer->getPosition(buffer->getIndices()[j+1]), buffer->getPosition(buffer->getIndices()[j+2])); } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; }
bool FileSceneNode::isimg(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".bmp")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".jpg")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".tga")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".pcx")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".png")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".psd"))) return true; return false; }
bool FileSceneNode::isanimesh(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".md2")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".md3")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".obj")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".bsp")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".my3d")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".lmts")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".csm")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".oct"))) return true; return false; }
bool FileSceneNode::isvid(core::stringc name) { if ((name.subString(name.size() - 4, 4).equals_ignore_case(".avi")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".wmv")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mpg")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".mpeg")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mp4")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".mkv")) || (name.subString(name.size() - 4, 4).equals_ignore_case(".ogm")) || (name.subString(name.size() - 3, 3).equals_ignore_case(".rm")) || (name.subString(name.size() - 5, 5).equals_ignore_case(".divx"))) return true; return false; }
core::stringc CFileSystem::getAbsolutePath(const core::stringc& filename) const { c8 *p=0; #ifdef _IRR_WINDOWS_API_ #if !defined ( _WIN32_WCE ) c8 fpath[_MAX_PATH]; p = _fullpath( fpath, filename.c_str(), _MAX_PATH); #endif #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) c8 fpath[4096]; fpath[0]=0; p = realpath(filename.c_str(), fpath); if (!p) { // content in fpath is undefined at this point if ('0'==fpath[0]) // seems like fpath wasn't altered { // at least remove a ./ prefix if ('.'==filename[0] && '/'==filename[1]) return filename.subString(2, filename.size()-2); else return filename; } else return core::stringc(fpath); } #endif return core::stringc(p); }
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; j<mesh->getMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { const core::vector3df& v1 = buffer->getPosition(buffer->getIndices()[j]); const core::vector3df& v2 = buffer->getPosition(buffer->getIndices()[j+1]); const core::vector3df& v3 = buffer->getPosition(buffer->getIndices()[j+2]); const core::plane3df tmpplane(v1,v2,v3); file->write(&tmpplane.Normal, 12); file->write(&v1, 12); file->write(&v2, 12); file->write(&v3, 12); file->write(&attributes, 2); } } } return true; }
core::stringc GetContextPathFromFilename( const core::stringc& filename ) { core::stringc path; s32 i=filename.size()-1; while ( i >= 0 && filename[i] != '/' ) { i--; } path = filename.subString( 0, i+1 ); return path; }
//! returns the directory part of a filename, i.e. all until the first //! slash or backslash, excluding it. If no directory path is prefixed, a '.' //! is returned. core::stringc CFileSystem::getFileDir(const core::stringc& filename) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; if ((u32)lastSlash < filename.size()) return filename.subString(0, lastSlash); else return "."; }
//! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); s32 end = 0; if (!keepExtension) { end = filename.findLast('.'); if (end == -1) end=0; else end = filename.size()-end; } if ((u32)lastSlash < filename.size()) return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); else if (end != 0) return filename.subString(0, filename.size()-end); else return filename; }
//! deletes the path from a filename void CPakReader::deletePathFromFilename(core::stringc& filename) { // delete path from filename const c8* p = filename.c_str() + filename.size(); // search for path separator or beginning while (*p!='/' && *p!='\\' && p!=filename.c_str()) --p; if (p != filename.c_str()) { ++p; filename = p; } }
//! deletes the path from a filename void CPakReader::deletePathFromFilename(core::stringc& filename) { // delete path from filename const c8* p = filename.c_str() + filename.size(); // suche ein slash oder den anfang. while (*p!='/' && *p!='\\' && p!=filename.c_str()) --p; core::stringc newName; if (p != filename.c_str()) { ++p; filename = p; } }
core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const { s32 slashIndex=inString.findLast('/'); // forward slash s32 backSlash=inString.findLast('\\'); // back slash if (backSlash>slashIndex) slashIndex=backSlash; if (slashIndex==-1)//no slashes found { if (returnPath) return core::stringc(); //no path to return else return inString; } if (returnPath) return inString.subString(0, slashIndex + 1); else return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); }
core::stringc CHashMD5::quickHash(core::stringc str) { hash_start(); hash_append((u8*)str.c_str(), str.size()); u8 digest[16]; hash_finish(digest, 16); c8 retstr[33]; memset(retstr, 0, 33); c8* temp = retstr; for(int i = 0; i < 16; i++) { if((digest[i] & 0xff) > 0xf){ sprintf(temp, "%x", (digest[i] & 0xff)); }else{ sprintf(temp, "0%x", (digest[i] & 0xff)); } temp += 2; } core::stringc ret(retstr); return ret; };
core::array<SDefineExp> grabDefineExpressions(core::stringc &shaderProgram) { s32 CurrentSearchPos = 1; s32 FindHelper = 1; s32 FindHelper2 = 1; core::array<SDefineExp> DefineArray; // Dont bother stripping comments if theres no defines. if((CurrentSearchPos = shaderProgram.find("##ifdef")) == -1) return DefineArray; // Strip all comments, they get in the way. while((CurrentSearchPos = shaderProgram.find("//")) > -1) { FindHelper = shaderProgram.findNext('\n',CurrentSearchPos); if(FindHelper != -1) for(u32 i = CurrentSearchPos;i < (u32)FindHelper;++i) shaderProgram[i] = ' '; else for(u32 i = CurrentSearchPos;i < shaderProgram.size();++i) shaderProgram[i] = ' '; } while((CurrentSearchPos = shaderProgram.find("/*")) > -1) { FindHelper = shaderProgram.find("*/"); if(FindHelper > CurrentSearchPos) for(u32 i = CurrentSearchPos;i <= (u32)(FindHelper + 1);++i) shaderProgram[i] = ' '; else for(u32 i = CurrentSearchPos;i < shaderProgram.size();++i) shaderProgram[i] = ' '; } while((CurrentSearchPos = shaderProgram.find("##ifdef")) > -1) { SDefineExp DExp; DExp.IfPos = CurrentSearchPos; // Comment out the ##ifdef so that we do not find it again, and so that the compiler ignores it. shaderProgram[CurrentSearchPos] = '/'; shaderProgram[CurrentSearchPos + 1] = '/'; FindHelper = shaderProgram.findNext(' ',CurrentSearchPos); FindHelper2 = shaderProgram.findNext('\n',FindHelper); if(FindHelper == -1 || FindHelper2 == -1) { std::cerr << "Shader preprocessor encountered invalid if statement." << std::endl; return DefineArray; } // Find the appropriate expression and trim all white space. DExp.IfExp = shaderProgram.subString(FindHelper,FindHelper2 - FindHelper); DExp.IfExp.trim(); // Record if its inverse and remove ! sign from expression. if(DExp.IfExp[0] == '!') { DExp.IfExp[0] = ' '; DExp.IfExp.trim(); DExp.Inverse = true; } bool EndIfFound = false; FindHelper2 = CurrentSearchPos; s32 IfEndScope = 0; while(!EndIfFound) { FindHelper = shaderProgram.findNext('#',FindHelper2); if(FindHelper == -1 || FindHelper >= (s32)(shaderProgram.size() - 3)) { std::cerr << "Shader preprocessor encountered unmatched if statement." << std::endl; return DefineArray; } if(IfEndScope < 0) { std::cerr << "Shader preprocessor encountered unmatched endif statement." << std::endl; return DefineArray; } if(shaderProgram[FindHelper + 1] != '#') { FindHelper2 = FindHelper + 1; continue; } else if(shaderProgram[FindHelper + 2] == 'i') { IfEndScope++; } else if(shaderProgram[FindHelper + 2] == 'e' && shaderProgram[FindHelper + 3] == 'n') { if(IfEndScope == 0) break; IfEndScope--; } else if(shaderProgram[FindHelper + 2] == 'e' && shaderProgram[FindHelper + 3] == 'l') { if(IfEndScope == 0) { if(DExp.ElsePos != -1) { std::cerr << "Shader preprocessor encountered duplicate else statements per if statement." << std::endl; return DefineArray; } // Comment out the ##else so that we do not find it again, and so that the compiler ignores it. shaderProgram[FindHelper] = '/'; shaderProgram[FindHelper + 1] = '/'; DExp.ElsePos = FindHelper; } } FindHelper2 = FindHelper + 2; } // Comment out the ##endif so that we do not find it again, and so that the compiler ignores it. shaderProgram[FindHelper] = '/'; shaderProgram[FindHelper + 1] = '/'; DExp.EndPos = FindHelper; // Add the define expression to the array. DefineArray.push_back(DExp); } return DefineArray; }
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 CMeshBuffer<video::S3DVertex2TCoords>* buffer = getMeshBufferByMaterialIndex(meshHeader.MatIndex); if (!buffer || (buffer->getVertexBuffer()->getVertexCount()+vertsNum) > SceneManager->getVideoDriver()->getMaximalPrimitiveCount()) { // creating new mesh buffer for this material buffer = new CMeshBuffer<video::S3DVertex2TCoords>(SceneManager->getVideoDriver()->getVertexDescriptor(1)); 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->getIndexBuffer()->reallocate(buffer->getIndexBuffer()->getIndexCount()+6*facesNum); buffer->getVertexBuffer()->reallocate(buffer->getVertexBuffer()->getVertexCount()+6*facesNum); } else { buffer->getIndexBuffer()->reallocate(buffer->getIndexBuffer()->getIndexCount()+3*facesNum); buffer->getVertexBuffer()->reallocate(buffer->getVertexBuffer()->getVertexCount()+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->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&VertexA); buffer->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&VertexB); buffer->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&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->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&VertexC); buffer->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&VertexB); buffer->getIndexBuffer()->addIndex(buffer->getVertexBuffer()->getVertexCount()); buffer->getVertexBuffer()->addVertex(&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) { CMeshBuffer<video::S3DVertex2TCoords>* 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; }
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; j<mesh->getMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; } } } return true; }
//! PreProcesses a shader using Irrlicht's built-in shader preprocessor. core::stringc CShaderPreprocessor::ppShader(core::stringc shaderProgram) { core::array<SDefineExp> DefineArray = grabDefineExpressions(shaderProgram); // No need for this as its already inited at startup. //// If DefineMap is empty then initialize it. //if(DefineMap.isEmpty()) // initDefineMap(); for(u32 i = 0; i < DefineArray.size();++i) { if(DefineArray[i].IfPos == -1) break; // Either it is true and not inversed, or it is false, but inversed. // (Wish C++ had a built-in (logical) XOR operator sometimes. :P) if((DefineMap.find(DefineArray[i].IfExp) && !DefineArray[i].Inverse) || (!DefineMap.find(DefineArray[i].IfExp) && DefineArray[i].Inverse)) { if(DefineArray[i].ElsePos > -1) { // If there is an else statement then clear the else section. if(DefineArray[i].EndPos != -1) { for(int z = DefineArray[i].ElsePos;z <= DefineArray[i].EndPos + 6;++z) shaderProgram[z] = ' '; } } } else if(DefineArray[i].ElsePos != -1) { // If there is an else statement then clear the if section. for(int z = DefineArray[i].IfPos;z <= DefineArray[i].ElsePos + 5;++z) shaderProgram[z] = ' '; } else { // Else just clear the whole block. if(DefineArray[i].EndPos != -1) { for(int z = DefineArray[i].IfPos;z <= DefineArray[i].EndPos + 6;++z) shaderProgram[z] = ' '; } } } core::map<core::stringc,core::stringc>::ParentFirstIterator DefIter; s32 DefFinder = 1; // Replace all shader defines. for(DefIter = DefineMap.getParentFirstIterator();!DefIter.atEnd();DefIter++) { if(DefIter->getValue().size() == 0) continue; // Replace all occurances. while((DefFinder = shaderProgram.find(DefIter->getKey().c_str())) > -1) { // Clear the define from the code. for(u32 z = DefFinder;z < DefFinder + DefIter->getKey().size();++z) shaderProgram[z] = ' '; // Stitch value and shader program together. (Is there a faster way?) shaderProgram = shaderProgram.subString(0,DefFinder) + DefIter->getValue() + shaderProgram.subString(DefFinder,shaderProgram.size() - 1); } } return shaderProgram; }
effectHandler::effectHandler(IrrlichtDevice* dev, dimension2d<u32> mapSize, core::stringc shaderFolder, irr::core::dimension2d<irr::u32> screenRTTSize) : device(dev), smgr(dev->getSceneManager()), driver(dev->getVideoDriver()), ScreenRTTSize((screenRTTSize == dimension2d<u32>(0,0)) ? dev->getVideoDriver()->getScreenSize() : screenRTTSize), ClearColour(0x0), shadowsUnsupported(false), DepthRTT(0), DepthPass(false), depthMC(0), shadowMC(0), AmbientColour(0x0) { CShaderPreprocessor sPP(driver); sPP.addShaderDefine("MAPRES", core::stringc(mapSize.Height)); bool tempTexFlagMipMaps = driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); bool tempTexFlag32 = driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT); ShadowMapTex = driver->addRenderTargetTexture(mapSize); ScreenRTT = driver->addRenderTargetTexture(ScreenRTTSize); ScreenQuad.rt[0] = driver->addRenderTargetTexture(ScreenRTTSize); ScreenQuad.rt[1] = driver->addRenderTargetTexture(ScreenRTTSize); driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, tempTexFlagMipMaps); driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT, tempTexFlag32); stringc platformExt = (driver->getDriverType() == EDT_DIRECT3D9) ? ".hlsl" : ".glsl"; if(shaderFolder.size() > 0 && shaderFolder[shaderFolder.size() - 1] != '/') shaderFolder += "/"; // For shadows stringc DFNV = shaderFolder + stringc("ShadowPass1V") + platformExt; stringc DFNP = shaderFolder + stringc("ShadowPass1P") + platformExt; stringc WFNP = shaderFolder + stringc("WhiteWashP") + platformExt; stringc SDFNV = shaderFolder + stringc("ShadowPass2V") + platformExt; stringc SDFNP = shaderFolder + stringc("ShadowPass2P") + platformExt; stringc GOOCHV = shaderFolder + stringc("ShaderGoochPtV") + platformExt; stringc WIGGLEV = shaderFolder + stringc("ShaderMrWiggleV") + platformExt; stringc DEPTHWIGGLEV = shaderFolder + stringc("ShaderDepthWiggleV") + platformExt; stringc ANISOV = shaderFolder + stringc("ShaderAnisoV") + platformExt; stringc PHONGV = shaderFolder + stringc("ShaderPhongV") + platformExt; stringc BRDFV = shaderFolder + stringc("ShaderBRDFV") + platformExt; stringc GOOCHP = shaderFolder + stringc("ShaderGoochPtP") + platformExt; stringc WIGGLEP = shaderFolder + stringc("ShaderMrWiggleP") + platformExt; stringc ANISOP = shaderFolder + stringc("ShaderAnisoP") + platformExt; stringc PHONGP = shaderFolder + stringc("ShaderPhongP") + platformExt; stringc BRDFP = shaderFolder + stringc("ShaderBRDFP") + platformExt; video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); if(gpu && ((driver->getDriverType() == EDT_OPENGL && driver->queryFeature(EVDF_ARB_GLSL)) || (driver->getDriverType() == EDT_DIRECT3D9 && driver->queryFeature(EVDF_PIXEL_SHADER_1_4)))) { BRDFShaderCB* mc4 = new BRDFShaderCB(this); LightShaderCB* mc5 = new LightShaderCB(this); WiggleShaderCB* mc6 = new WiggleShaderCB(this); AnisoShaderCB* mc8 = new AnisoShaderCB(this); PhongShaderCB* mc9 = new PhongShaderCB(this); Effects[EET_BRDF] = gpu->addHighLevelShaderMaterialFromFiles( BRDFV.c_str(), "vertexMain", video::EVST_VS_1_1, BRDFP.c_str(), "pixelMain", video::EPST_PS_1_4, mc4, video::EMT_SOLID); Effects[EET_GOOCH] = gpu->addHighLevelShaderMaterialFromFiles( GOOCHV.c_str(), "vertexMain", video::EVST_VS_1_1, GOOCHP.c_str(), "pixelMain", video::EPST_PS_1_4, mc5, video::EMT_SOLID); Effects[EET_MRWIGGLE] = gpu->addHighLevelShaderMaterialFromFiles( WIGGLEV.c_str(), "vertexMain", video::EVST_VS_1_1, WIGGLEP.c_str(), "pixelMain", video::EPST_PS_1_4, mc6, video::EMT_SOLID); Effects[EET_ANISO] = gpu->addHighLevelShaderMaterialFromFiles( ANISOV.c_str(), "vertexMain", video::EVST_VS_1_1, ANISOP.c_str(), "pixelMain", video::EPST_PS_1_4, mc8, video::EMT_SOLID); Effects[EET_PHONG] = gpu->addHighLevelShaderMaterialFromFiles( PHONGV.c_str(), "vertexMain", video::EVST_VS_1_1, PHONGP.c_str(), "pixelMain", video::EPST_PS_1_4, mc9, video::EMT_SOLID); if(driver->queryFeature(EVDF_PIXEL_SHADER_2_0) || driver->getDriverType() == EDT_OPENGL) { depthMC = new DepthShaderCB(this); shadowMC = new ShadowShaderCB(this); Depth = gpu->addHighLevelShaderMaterialFromFiles( DFNV.c_str(), "vertexMain", video::EVST_VS_2_0, DFNP.c_str(), "pixelMain", video::EPST_PS_2_0, depthMC, video::EMT_SOLID); DepthWiggle = gpu->addHighLevelShaderMaterialFromFiles( DEPTHWIGGLEV.c_str(), "vertexMain", video::EVST_VS_2_0, DFNP.c_str(), "pixelMain", video::EPST_PS_2_0, depthMC, video::EMT_SOLID); WhiteWash = gpu->addHighLevelShaderMaterialFromFiles( DFNV.c_str(), "vertexMain", video::EVST_VS_2_0, WFNP.c_str(), "pixelMain", video::EPST_PS_2_0, depthMC, video::EMT_SOLID); sPP.addShaderDefine("SAMPLE_AMOUNT", core::stringc(1)); Solid[EFT_NONE] = gpu->addHighLevelShaderMaterial( sPP.ppShaderFF(SDFNV).c_str(), "vertexMain", video::EVST_VS_2_0, sPP.ppShaderFF(SDFNP).c_str(), "pixelMain", video::EPST_PS_2_0, shadowMC, video::EMT_SOLID); sPP.addShaderDefine("SAMPLE_AMOUNT", core::stringc(4)); Solid[EFT_4PCF] = gpu->addHighLevelShaderMaterial( sPP.ppShaderFF(SDFNV).c_str(), "vertexMain", video::EVST_VS_2_0, sPP.ppShaderFF(SDFNP).c_str(), "pixelMain", video::EPST_PS_2_0, shadowMC, video::EMT_SOLID); sPP.addShaderDefine("SAMPLE_AMOUNT", core::stringc(8)); Solid[EFT_8PCF] = gpu->addHighLevelShaderMaterial( sPP.ppShaderFF(SDFNV).c_str(), "vertexMain", video::EVST_VS_2_0, sPP.ppShaderFF(SDFNP).c_str(), "pixelMain", video::EPST_PS_2_0, shadowMC, video::EMT_SOLID); sPP.addShaderDefine("SAMPLE_AMOUNT", core::stringc(12)); if(driver->queryFeature(EVDF_PIXEL_SHADER_3_0) || driver->getDriverType() == EDT_OPENGL) Solid[EFT_12PCF] = gpu->addHighLevelShaderMaterial( sPP.ppShaderFF(SDFNV).c_str(), "vertexMain", video::EVST_VS_3_0, sPP.ppShaderFF(SDFNP).c_str(), "pixelMain", video::EPST_PS_3_0, shadowMC, video::EMT_SOLID); else Solid[EFT_12PCF] = Solid[EFT_8PCF]; sPP.addShaderDefine("SAMPLE_AMOUNT", core::stringc(16)); if(driver->queryFeature(EVDF_PIXEL_SHADER_3_0) || driver->getDriverType() == EDT_OPENGL) Solid[EFT_16PCF] = gpu->addHighLevelShaderMaterial( sPP.ppShaderFF(SDFNV).c_str(), "vertexMain", video::EVST_VS_3_0, sPP.ppShaderFF(SDFNP).c_str(), "pixelMain", video::EPST_PS_3_0, shadowMC, video::EMT_SOLID); else Solid[EFT_16PCF] = Solid[EFT_8PCF]; // Light modulate. LightModulate = obtainScreenQuadMaterialFromFile( shaderFolder + stringc("LightModulate") + platformExt); // Simple present. Simple = obtainScreenQuadMaterialFromFile( shaderFolder + stringc("SimpleP") + platformExt, EMT_TRANSPARENT_ADD_COLOR); } else { Depth = EMT_SOLID; DepthWiggle = EMT_SOLID; WhiteWash = EMT_SOLID; for(u32 i = 0;i < EFT_COUNT;++i) Solid[i] = EMT_SOLID; device->getLogger()->log("XEffects: Shadow maps not supported on this system."); shadowsUnsupported = true; } mc4->drop(); mc5->drop(); mc6->drop(); mc8->drop(); mc9->drop(); } else { Depth = EMT_SOLID; DepthWiggle = EMT_SOLID; WhiteWash = EMT_SOLID; for(u32 i = 0;i < EFT_COUNT;++i) Solid[i] = EMT_SOLID; for(u32 i = 0;i < EET_COUNT;++i) Effects[i] = EMT_SOLID; device->getLogger()->log("XEffects: Shadow maps not supported on this system."); device->getLogger()->log("XEffects: Effects not supported on this system."); } }
//! writes a mesh bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; os::Printer::log("Writing mesh", file->getFileName()); // write OBJ MESH header const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshName(mesh), false)+".mtl"); file->write("# exported by Irrlicht\n",23); file->write("mtllib ",7); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers core::array<video::SMaterial*> mat; u32 allVertexCount=1; // count vertices over the whole file for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { core::stringc num(i+1); IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer && buffer->getVertexCount()) { file->write("g grp", 5); file->write(num.c_str(), num.size()); file->write("\n",1); u32 j; const u32 vertexCount = buffer->getVertexCount(); for (j=0; j<vertexCount; ++j) { file->write("v ",2); getVectorAsStringLine(buffer->getPosition(j), num); file->write(num.c_str(), num.size()); } for (j=0; j<vertexCount; ++j) { file->write("vt ",3); getVectorAsStringLine(buffer->getTCoords(j), num); file->write(num.c_str(), num.size()); } for (j=0; j<vertexCount; ++j) { file->write("vn ",3); getVectorAsStringLine(buffer->getNormal(j), num); file->write(num.c_str(), num.size()); } file->write("usemtl mat",10); num = ""; for (j=0; j<mat.size(); ++j) { if (*mat[j]==buffer->getMaterial()) { num = core::stringc(j); break; } } if (num == "") { num = core::stringc(mat.size()); mat.push_back(&buffer->getMaterial()); } file->write(num.c_str(), num.size()); file->write("\n",1); const u32 indexCount = buffer->getIndexCount(); for (j=0; j<indexCount; j+=3) { file->write("f ",2); num = core::stringc(buffer->getIndices()[j+2]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+1]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+0]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); file->write("\n",1); } file->write("\n",1); allVertexCount += vertexCount; } } if (mat.size() == 0) return true; file = FileSystem->createAndWriteFile( name ); if (file) { os::Printer::log("Writing material", file->getFileName()); file->write("# exported by Irrlicht\n\n",24); for (u32 i=0; i<mat.size(); ++i) { core::stringc num(i); file->write("newmtl mat",10); file->write(num.c_str(),num.size()); file->write("\n",1); getColorAsStringLine(mat[i]->AmbientColor, "Ka", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->DiffuseColor, "Kd", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->SpecularColor, "Ks", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->EmissiveColor, "Ke", num); file->write(num.c_str(),num.size()); num = core::stringc(mat[i]->Shininess/0.128f); file->write("Ns ", 3); file->write(num.c_str(),num.size()); file->write("\n", 1); if (mat[i]->getTexture(0)) { file->write("map_Kd ", 7); file->write(mat[i]->getTexture(0)->getName().getPath().c_str(), mat[i]->getTexture(0)->getName().getPath().size()); file->write("\n",1); } file->write("\n",1); } file->drop(); } return true; }