void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) { Scale = scale; const u32 mp = driver -> getMaximalPrimitiveCount(); Width = hm.width(); Height = hm.height(); const u32 sw = mp / (6 * Height); // the width of each piece u32 i=0; for(u32 y0 = 0; y0 < Height; y0 += sw) { u16 y1 = y0 + sw; if (y1 >= Height) y1 = Height - 1; // the last one might be narrower addstrip(hm, cf, y0, y1, i); ++i; } if (i<Mesh->getMeshBufferCount()) { // clear the rest for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j) { Mesh->getMeshBuffer(j)->drop(); } Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); } // set dirty flag to make sure that hardware copies of this // buffer are also updated, see IMesh::setHardwareMappingHint Mesh->setDirty(); Mesh->recalculateBoundingBox(); }
void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) { Scale = scale; const u32 mp = driver -> getMaximalPrimitiveCount(); Width = hm.width(); Height = hm.height(); const u32 sw = mp / (6 * Height); // the width of each piece u32 i=0; for(u32 y0 = 0; y0 < Height; y0 += sw) { u16 y1 = y0 + sw; if (y1 >= Height) y1 = Height - 1; // the last one might be narrower addstrip(hm, cf, y0, y1, i); ++i; } if (i<Mesh->getMeshBufferCount()) { // clear the rest for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j) { Mesh->getMeshBuffer(j)->drop(); } Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); } Mesh->recalculateBoundingBox(); }
//! Creates/loads an animated mesh from the file. IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file) { // create empty mesh SMesh *mesh = new SMesh(); // load file u16 version; u8 flags; s32 limbCount; s32 i; io::BinaryFile::read(file, version); io::BinaryFile::read(file, flags); io::BinaryFile::read(file, limbCount); // load mesh data core::matrix4 identity; for (i=0; i < limbCount; ++i) loadLimb(file, mesh, identity); // recalculate buffer bounding boxes for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i) mesh->getMeshBuffer(i)->recalculateBoundingBox(); mesh->recalculateBoundingBox(); SAnimatedMesh *am = new SAnimatedMesh(); am->addMesh(mesh); mesh->drop(); am->recalculateBoundingBox(); return am; }
void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum) { SMeshBuffer *buf = 0; if (bufNum<Mesh->getMeshBufferCount()) { buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum); } else { // create new buffer buf = new SMeshBuffer(); Mesh->addMeshBuffer(buf); // to simplify things we drop here but continue using buf buf->drop(); } buf->Vertices.set_used((1 + y1 - y0) * Width); u32 i=0; for (u16 y = y0; y <= y1; ++y) { for (u16 x = 0; x < Width; ++x) { const f32 z = hm.get(x, y); const f32 xx = (f32)x/(f32)Width; const f32 yy = (f32)y/(f32)Height; S3DVertex& v = buf->Vertices[i++]; v.Pos.set(x, Scale * z, y); v.Normal.set(hm.getnormal(x, y, Scale)); v.Color=cf(xx, yy, z); v.TCoords.set(xx, yy); } } buf->Indices.set_used(6 * (Width - 1) * (y1 - y0)); i=0; for(u16 y = y0; y < y1; ++y) { for(u16 x = 0; x < Width - 1; ++x) { const u16 n = (y-y0) * Width + x; buf->Indices[i]=n; buf->Indices[++i]=n + Width; buf->Indices[++i]=n + Width + 1; buf->Indices[++i]=n + Width + 1; buf->Indices[++i]=n + 1; buf->Indices[++i]=n; ++i; } } buf->recalculateBoundingBox(); }
//! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) { const long filesize = file->getSize(); if (filesize < 6) // we need a header return 0; const u32 WORD_BUFFER_LENGTH = 512; SMesh* mesh = new SMesh(); SMeshBuffer* meshBuffer = new SMeshBuffer(); mesh->addMeshBuffer(meshBuffer); meshBuffer->drop(); core::vector3df vertex[3]; core::vector3df normal; c8 buffer[WORD_BUFFER_LENGTH]; bool binary = false; file->read(buffer, 5); if (strncmp("solid", buffer, 5)) binary = true; // read/skip header u32 binFaceCount = 0; if (binary) { file->seek(80); file->read(&binFaceCount, 4); #ifdef __BIG_ENDIAN__ binFaceCount = os::Byteswap::byteswap(binFaceCount); #endif } else goNextLine(file); u16 attrib=0; core::stringc token; token.reserve(32); while (file->getPos() < filesize) { if (!binary) { if (getNextToken(file, token) != "facet") { if (token=="endsolid") break; mesh->drop(); return 0; } if (getNextToken(file, token) != "normal") { mesh->drop(); return 0; } } getNextVector(file, normal, binary); if (!binary) { if (getNextToken(file, token) != "outer") { mesh->drop(); return 0; } if (getNextToken(file, token) != "loop") { mesh->drop(); return 0; } } for (u32 i=0; i<3; ++i) { if (!binary) { if (getNextToken(file, token) != "vertex") { mesh->drop(); return 0; } } getNextVector(file, vertex[i], binary); } if (!binary) { if (getNextToken(file, token) != "endloop") { mesh->drop(); return 0; } if (getNextToken(file, token) != "endfacet") { mesh->drop(); return 0; } } else { file->read(&attrib, 2); #ifdef __BIG_ENDIAN__ attrib = os::Byteswap::byteswap(attrib); #endif } SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1)); u32 vCount = mb->getVertexCount(); video::SColor color(0xffffffff); if (attrib & 0x8000) color = video::A1R5G5B5toA8R8G8B8(attrib); if (normal==core::vector3df()) normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal; mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df())); mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); mb->Indices.push_back(vCount); mb->Indices.push_back(vCount+1); mb->Indices.push_back(vCount+2); } // end while (file->getPos() < filesize) mesh->getMeshBuffer(0)->recalculateBoundingBox(); // Create the Animated mesh if there's anything in the mesh SAnimatedMesh* pAM = 0; if ( 0 != mesh->getMeshBufferCount() ) { mesh->recalculateBoundingBox(); pAM = new SAnimatedMesh(); pAM->Type = EAMT_OBJ; pAM->addMesh(mesh); pAM->recalculateBoundingBox(); } mesh->drop(); return pAM; }
GLlink(ISceneNode *i_parent, ISceneManager *i_mgr, s32 i_id, const LinkInfo &i_li, BodyInfo_var i_binfo) : ISceneNode(i_parent, i_mgr, i_id), m_jointId(i_li.jointId) { setAutomaticCulling(scene::EAC_OFF); setPosition(vector3df( i_li.translation[0], -i_li.translation[1], i_li.translation[2])); Vector3 axis(i_li.rotation[0], i_li.rotation[1], i_li.rotation[2]); Matrix33 R; hrp::calcRodrigues(R, axis, i_li.rotation[3]); Vector3 rpy(rpyFromRot(R)); //std::cout << "rpy:" << rpy << std::endl; setRotation(vector3df(-180/M_PI*rpy[0], 180/M_PI*rpy[1], -180/M_PI*rpy[2])); m_axis << i_li.jointAxis[0], i_li.jointAxis[1], i_li.jointAxis[2]; ShapeInfoSequence_var sis = i_binfo->shapes(); AppearanceInfoSequence_var ais = i_binfo->appearances(); MaterialInfoSequence_var mis = i_binfo->materials(); TextureInfoSequence_var txs = i_binfo->textures(); const TransformedShapeIndexSequence& tsis = i_li.shapeIndices; core::vector3df vertex; core::vector3df normal; for (unsigned int l=0; l<tsis.length(); l++) { SMesh* mesh = new SMesh(); SMeshBuffer* meshBuffer = new SMeshBuffer(); mesh->addMeshBuffer(meshBuffer); meshBuffer->drop(); const TransformedShapeIndex &tsi = tsis[l]; short index = tsi.shapeIndex; ShapeInfo& si = sis[index]; const float *vertices = si.vertices.get_buffer(); const LongSequence& triangles = si.triangles; const AppearanceInfo& ai = ais[si.appearanceIndex]; const float *normals = ai.normals.get_buffer(); //std::cout << "length of normals = " << ai.normals.length() << std::endl; const LongSequence& normalIndices = ai.normalIndices; //std::cout << "length of normalIndices = " << normalIndices.length() << std::endl; const int numTriangles = triangles.length() / 3; //std::cout << "numTriangles = " << numTriangles << std::endl; video::SColor color(0xffffffff); if (ai.colors.length()) { color.set(0xff, 0xff*ai.colors[0], 0xff*ai.colors[1], 0xff*ai.colors[2]); } else if (ai.materialIndex >= 0) { const MaterialInfo& mi = mis[ai.materialIndex]; color.set(0xff, 0xff*mi.diffuseColor[0], 0xff*mi.diffuseColor[1], 0xff*mi.diffuseColor[2]); } else { std::cout << "no material" << std::endl; } SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1)); u32 vCount = mb->getVertexCount(); const DblArray12& tfm = tsi.transformMatrix; CMatrix4<f32> cmat; for (int i=0; i<3; i++) { for (int j=0; j<4; j++) { cmat[j*4+i] = tfm[i*4+j]; } } cmat[3] = cmat[7] = cmat[11] = 0.0; cmat[15] = 1.0; vector3df pos = cmat.getTranslation(); pos.Y *= -1; vector3df rpy = cmat.getRotationDegrees(); rpy.X *= -1; rpy.Z *= -1; vector3df scale = cmat.getScale(); const float *textureCoordinate = NULL; if (ai.textureIndex >= 0) { textureCoordinate = ai.textureCoordinate.get_buffer(); //std::cout << "length of textureCoordinate:" << ai.textureCoordinate.length() << std::endl; //std::cout << "length of vertices:" << si.vertices.length() << std::endl; } for(int j=0; j < numTriangles; ++j) { if (!ai.normalPerVertex) { int p; if (normalIndices.length() == 0) { p = j*3; } else { p = normalIndices[j]*3; } if ( normals != NULL ) { normal.X = normals[p]; normal.Y = -normals[p+1]; //left-handed->right-handed normal.Z = normals[p+2]; } else { normal.X = 0; normal.Y = 0; normal.Z = 1; } } for(int k=0; k < 3; ++k) { long orgVertexIndex = si.triangles[j * 3 + k]; if (ai.normalPerVertex) { int p; if (normalIndices.length()) { p = normalIndices[j*3+k]*3; } else { p = orgVertexIndex*3; } normal.X = normals[p]; normal.Y = -normals[p+1]; //left-handed -> right-handed normal.Z = normals[p+2]; } int p = orgVertexIndex * 3; vertex.X = scale.X*vertices[p]; vertex.Y = -scale.Y*vertices[p+1]; // left-handed -> right-handed vertex.Z = scale.Z*vertices[p+2]; //std::cout << vertices[p] <<"," << vertices[p+1] << "," << vertices[p+2] << std::endl; vector2df texc; if (textureCoordinate) { texc.X = textureCoordinate[ai.textureCoordIndices[j*3+k]*2]; texc.Y = textureCoordinate[ai.textureCoordIndices[j*3+k]*2+1]; } // redundant vertices mb->Vertices.push_back(video::S3DVertex(vertex,normal,color, texc)); } mb->Indices.push_back(vCount); mb->Indices.push_back(vCount+2); mb->Indices.push_back(vCount+1); vCount += 3; } mesh->getMeshBuffer(0)->recalculateBoundingBox(); // Create the Animated mesh if there's anything in the mesh SAnimatedMesh* pAM = 0; if ( 0 != mesh->getMeshBufferCount() ) { mesh->recalculateBoundingBox(); pAM = new SAnimatedMesh(); pAM->Type = EAMT_OBJ; pAM->addMesh(mesh); pAM->recalculateBoundingBox(); } mesh->drop(); vector3df noscale(1,1,1); IMeshSceneNode *node = i_mgr->addMeshSceneNode(mesh, this, -1, pos, rpy, noscale); if (ai.textureIndex >= 0) { const TextureInfo& ti = txs[ai.textureIndex]; //std::cout << "url:" << ti.url << std::endl; video::IVideoDriver* driver = i_mgr->getVideoDriver(); const char *path = ti.url; SMaterial& mat = node->getMaterial(0); ITexture *texture = driver->getTexture(path); mat.setTexture( 0, texture); } } const SensorInfoSequence& sensors = i_li.sensors; for (unsigned int i=0; i<sensors.length(); i++) { const SensorInfo& si = sensors[i]; std::string type(si.type); if (type == "Vision") { //std::cout << si.name << std::endl; ISceneNode *camera = i_mgr->addEmptySceneNode(this); camera->setName(si.name); camera->setPosition(vector3df( si.translation[0], -si.translation[1], si.translation[2])); Vector3 axis(si.rotation[0], si.rotation[1], si.rotation[2]); Matrix33 R; hrp::calcRodrigues(R, axis, si.rotation[3]); Vector3 rpy(rpyFromRot(R)); camera->setRotation(vector3df(-180/M_PI*rpy[0], 180/M_PI*rpy[1], -180/M_PI*rpy[2])); m_cameraInfos.push_back(new GLcamera(si, camera)); } } }
/**Creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information.*/ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) { if (!file) return 0; video::IVideoDriver* driver = SceneMgr->getVideoDriver(); //Load stringlist StringList dmfRawFile; LoadFromFile(file, dmfRawFile); if (dmfRawFile.size()==0) return 0; SMesh * mesh = new SMesh(); u32 i; dmfHeader header; //load header core::array<dmfMaterial> materiali; if (GetDMFHeader(dmfRawFile, header)) { //let's set ambient light SceneMgr->setAmbientLight(header.dmfAmbient); //let's create the correct number of materials, vertices and faces dmfVert *verts=new dmfVert[header.numVertices]; dmfFace *faces=new dmfFace[header.numFaces]; //let's get the materials #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str()); #endif GetDMFMaterials(dmfRawFile, materiali, header.numMaterials); //let's get vertices and faces #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading geometry"); #endif GetDMFVerticesFaces(dmfRawFile, verts, faces); //create a meshbuffer for each material, then we'll remove empty ones #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Creating meshbuffers."); #endif for (i=0; i<header.numMaterials; i++) { //create a new SMeshBufferLightMap for each material SSkinMeshBuffer* buffer = new SSkinMeshBuffer(); buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING; buffer->Material.Wireframe = false; buffer->Material.Lighting = true; mesh->addMeshBuffer(buffer); buffer->drop(); } // Build the mesh buffers #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Adding geometry to mesh."); #endif for (i = 0; i < header.numFaces; i++) { #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str()); #endif if (faces[i].numVerts < 3) continue; const core::vector3df normal = core::triangle3df(verts[faces[i].firstVert].pos, verts[faces[i].firstVert+1].pos, verts[faces[i].firstVert+2].pos).getNormal().normalize(); SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer( faces[i].materialID); const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() || materiali[faces[i].materialID].lightmapName.size(); if (use2TCoords && meshBuffer->Vertices_Standard.size()) meshBuffer->convertTo2TCoords(); const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size(); // Add this face's verts if (use2TCoords) { // make sure we have the proper type set meshBuffer->VertexType=video::EVT_2TCOORDS; for (u32 v = 0; v < faces[i].numVerts; v++) { const dmfVert& vv = verts[faces[i].firstVert + v]; video::S3DVertex2TCoords vert(vv.pos, normal, video::SColor(255,255,255,255), vv.tc, vv.lc); if (materiali[faces[i].materialID].textureBlend==4 && SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) { vert.TCoords.set(vv.tc.X,-vv.tc.Y); } meshBuffer->Vertices_2TCoords.push_back(vert); } } else { for (u32 v = 0; v < faces[i].numVerts; v++) { const dmfVert& vv = verts[faces[i].firstVert + v]; video::S3DVertex vert(vv.pos, normal, video::SColor(255,255,255,255), vv.tc); if (materiali[faces[i].materialID].textureBlend==4 && SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) { vert.TCoords.set(vv.tc.X,-vv.tc.Y); } meshBuffer->Vertices_Standard.push_back(vert); } } // Now add the indices // This weird loop turns convex polygons into triangle strips. // I do it this way instead of a simple fan because it usually // looks a lot better in wireframe, for example. u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center for (u32 v = 0; v < faces[i].numVerts - 2; v++) { if (v & 1) // odd c = h - 1; else // even c = l + 1; meshBuffer->Indices.push_back(base + h); meshBuffer->Indices.push_back(base + l); meshBuffer->Indices.push_back(base + c); if (v & 1) // odd h--; else // even l++; } } delete [] verts; delete [] faces; } // delete all buffers without geometry in it. #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Cleaning meshbuffers."); #endif i = 0; while(i < mesh->MeshBuffers.size()) { if (mesh->MeshBuffers[i]->getVertexCount() == 0 || mesh->MeshBuffers[i]->getIndexCount() == 0) { // Meshbuffer is empty -- drop it mesh->MeshBuffers[i]->drop(); mesh->MeshBuffers.erase(i); materiali.erase(i); } else { i++; } } { //load textures and lightmaps in materials. //don't worry if you receive a could not load texture, cause if you don't need //a particular material in your scene it will be loaded and then destroyed. #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading textures."); #endif const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS); core::stringc path; if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) ) path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH); else path = FileSystem->getFileDir(file->getFileName()); path += ('/'); for (i=0; i<mesh->getMeshBufferCount(); i++) { //texture and lightmap video::ITexture *tex = 0; video::ITexture *lig = 0; //current buffer to apply material video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial(); //Primary texture is normal if (materiali[i].textureFlag==0) { if (materiali[i].textureBlend==4) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName); tex = driver->getTexture(materiali[i].textureName); } //Primary texture is just a colour else if(materiali[i].textureFlag==1) { video::SColor color(axtoi(materiali[i].textureName.c_str())); //just for compatibility with older Irrlicht versions //to support transparent materials if (color.getAlpha()!=255 && materiali[i].textureBlend==4) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8, core::dimension2d<u32>(8,8)); immagine->fill(color); tex = driver->addTexture("", immagine); immagine->drop(); //to support transparent materials if (color.getAlpha()!=255 && materiali[i].textureBlend==4) { mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f); } } //Lightmap is present if (materiali[i].lightmapFlag == 0) { findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName); lig = driver->getTexture(materiali[i].lightmapName); } else //no lightmap { mat.MaterialType = video::EMT_SOLID; const f32 mult = 100.0f - header.dmfShadow; mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f); } if (materiali[i].textureBlend==4) { mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; mat.MaterialTypeParam = SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF); } //if texture is present mirror vertically owing to DeleD representation if (tex && header.dmfVersion<1.1) { const core::dimension2d<u32> texsize = tex->getSize(); void* pp = tex->lock(); if (pp) { const video::ECOLOR_FORMAT format = tex->getColorFormat(); if (format == video::ECF_A1R5G5B5) { s16* p = (s16*)pp; s16 tmp=0; for (u32 x=0; x<texsize.Width; x++) for (u32 y=0; y<texsize.Height/2; y++) { tmp=p[y*texsize.Width + x]; p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x]; p[(texsize.Height-y-1)*texsize.Width + x]=tmp; } } else if (format == video::ECF_A8R8G8B8) { s32* p = (s32*)pp; s32 tmp=0; for (u32 x=0; x<texsize.Width; x++) for (u32 y=0; y<texsize.Height/2; y++) { tmp=p[y*texsize.Width + x]; p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x]; p[(texsize.Height-y-1)*texsize.Width + x]=tmp; } } } tex->unlock(); tex->regenerateMipMapLevels(); } //if lightmap is present mirror vertically owing to DeleD rapresentation if (lig && header.dmfVersion<1.1) { const core::dimension2d<u32> ligsize=lig->getSize(); void* pp = lig->lock(); if (pp) { video::ECOLOR_FORMAT format = lig->getColorFormat(); if (format == video::ECF_A1R5G5B5) { s16* p = (s16*)pp; s16 tmp=0; for (u32 x=0; x<ligsize.Width; x++) { for (u32 y=0; y<ligsize.Height/2; y++) { tmp=p[y*ligsize.Width + x]; p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x]; p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp; } } } else if (format == video::ECF_A8R8G8B8) { s32* p = (s32*)pp; s32 tmp=0; for (u32 x=0; x<ligsize.Width; x++) { for (u32 y=0; y<ligsize.Height/2; y++) { tmp=p[y*ligsize.Width + x]; p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x]; p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp; } } } } lig->unlock(); lig->regenerateMipMapLevels(); } mat.setTexture(0, tex); mat.setTexture(1, lig); } } // create bounding box for (i = 0; i < mesh->MeshBuffers.size(); ++i) { mesh->MeshBuffers[i]->recalculateBoundingBox(); } mesh->recalculateBoundingBox(); // Set up an animated mesh to hold the mesh SAnimatedMesh* AMesh = new SAnimatedMesh(); AMesh->Type = EAMT_UNKNOWN; AMesh->addMesh(mesh); AMesh->recalculateBoundingBox(); mesh->drop(); return AMesh; }
IAnimatedMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d<f32>& stretchSize, f32 maxHeight, video::IVideoDriver* driver, const core::dimension2d<s32> maxVtxBlockSize, bool debugBorders) { u32 tm = os::Timer::getRealTime()/1000; if (!texture || !heightmap) return 0; video::SMaterial material; c8 textureName[64]; c8 tmp[255]; // debug border s32 borderSkip = debugBorders ? 0 : 1; video::S3DVertex vtx; vtx.Color.set(255,255,255,255); SMesh* mesh = new SMesh(); core::dimension2d<s32> hMapSize= heightmap->getDimension(); core::dimension2d<s32> tMapSize= texture->getDimension(); core::position2d<f32> thRel((f32)tMapSize.Width / (s32)hMapSize.Width, (f32)tMapSize.Height / (s32)hMapSize.Height); core::position2d<s32> processed(0,0); while (processed.Y<hMapSize.Height) { while(processed.X<hMapSize.Width) { core::dimension2d<s32> blockSize = maxVtxBlockSize; if (processed.X + blockSize.Width > hMapSize.Width) blockSize.Width = hMapSize.Width - processed.X; if (processed.Y + blockSize.Height > hMapSize.Height) blockSize.Height = hMapSize.Height - processed.Y; SMeshBuffer* buffer = new SMeshBuffer(); s32 x,y; // add vertices of vertex block for (y=0; y<blockSize.Height; ++y) for (x=0; x<blockSize.Width; ++x) { video::SColor clr = heightmap->getPixel(x+processed.X, y+processed.Y); f32 height = ((clr.getRed() + clr.getGreen() + clr.getBlue()) / 3.0f)/255.0f * maxHeight; vtx.Pos.set((f32)(x+processed.X) * stretchSize.Width, height, (f32)(y+processed.Y) * stretchSize.Height); vtx.TCoords.set((f32)(x+0.5f) / ((f32)blockSize.Width), (f32)(y+0.5f) / ((f32)blockSize.Height)); buffer->Vertices.push_back(vtx); } // add indices of vertex block for (y=0; y<blockSize.Height-1; ++y) for (x=0; x<blockSize.Width-1; ++x) { s32 c = (y*blockSize.Width) + x; buffer->Indices.push_back(c); buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + 1); buffer->Indices.push_back(c + 1); buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + 1 + blockSize.Width); } // recalculate normals for (s32 i=0; i<(s32)buffer->Indices.size(); i+=3) { core::plane3d<f32> p( buffer->Vertices[buffer->Indices[i+0]].Pos, buffer->Vertices[buffer->Indices[i+1]].Pos, buffer->Vertices[buffer->Indices[i+2]].Pos); p.Normal.normalize(); buffer->Vertices[buffer->Indices[i+0]].Normal = p.Normal; buffer->Vertices[buffer->Indices[i+1]].Normal = p.Normal; buffer->Vertices[buffer->Indices[i+2]].Normal = p.Normal; } if (buffer->Vertices.size()) { // create texture for this block video::IImage* img = new video::CImage(texture, core::position2d<s32>((s32)(processed.X*thRel.X), (s32)(processed.Y*thRel.Y)), core::dimension2d<s32>((s32)(blockSize.Width*thRel.X), (s32)(blockSize.Height*thRel.Y))); sprintf(textureName, "terrain%d_%d", tm, mesh->getMeshBufferCount()); material.Texture1 = driver->addTexture(textureName, img); if (material.Texture1) { sprintf(tmp, "Generated terrain texture (%dx%d): %s", material.Texture1->getSize().Width, material.Texture1->getSize().Height, textureName); os::Printer::log(tmp); } else os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR); buffer->Material = material; img->drop(); } buffer->recalculateBoundingBox(); mesh->addMeshBuffer(buffer); buffer->drop(); // keep on processing processed.X += maxVtxBlockSize.Width - borderSkip; } // keep on processing processed.X = 0; processed.Y += maxVtxBlockSize.Height - borderSkip; } SAnimatedMesh* animatedMesh = new SAnimatedMesh(); mesh->recalculateBoundingBox(); animatedMesh->addMesh(mesh); animatedMesh->recalculateBoundingBox(); mesh->drop(); return animatedMesh; }