/* Minetest Copyright (C) 2010-2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mesh.h" #include "debug.h" #include "log.h" #include #include #include // In Irrlicht 1.8 the signature of ITexture::lock was changed from // (bool, u32) to (E_TEXTURE_LOCK_MODE, u32). #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 #define MY_ETLM_READ_ONLY true #else #define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY #endif scene::IAnimatedMesh* createCubeMesh(v3f scale) { video::SColor c(255,255,255,255); video::S3DVertex vertices[24] = { // Up video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1), video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0), video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0), video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1), // Down video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0), video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0), video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1), video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1), // Right video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1), video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0), video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0), video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1), // Left video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1), video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1), video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0), video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0), // Back video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1), video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1), video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0), video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0), // Front video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1), video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0), video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0), video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1), }; u16 indices[6] = {0,1,2,2,3,0}; scene::SMesh *mesh = new scene::SMesh(); for (u32 i=0; i<6; ++i) { scene::IMeshBuffer *buf = new scene::SMeshBuffer(); buf->append(vertices + 4 * i, 4, indices, 6); // Set default material buf->getMaterial().setFlag(video::EMF_LIGHTING, false); buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; // Add mesh buffer to mesh mesh->addMeshBuffer(buf); buf->drop(); } scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh); mesh->drop(); scaleMesh(anim_mesh, scale); // also recalculates bounding box return anim_mesh; } void scaleMesh(scene::IMesh *mesh, v3f scale) { if(mesh == NULL) return; core::aabbox3d bbox; bbox.reset(0,0,0); u16 mc = mesh->getMeshBufferCount(); for(u16 j=0; jgetMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 vc = buf->getVertexCount(); for(u16 i=0; irecalculateBoundingBox(); // calculate total bounding box if(j == 0) bbox = buf->getBoundingBox(); else bbox.addInternalBox(buf->getBoundingBox()); } mesh->setBoundingBox(bbox); } void translateMesh(scene::IMesh *mesh, v3f vec) { if(mesh == NULL) return; core::aabbox3d bbox; bbox.reset(0,0,0); u16 mc = mesh->getMeshBufferCount(); for(u16 j=0; jgetMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 vc = buf->getVertexCount(); for(u16 i=0; irecalculateBoundingBox(); // calculate total bounding box if(j == 0) bbox = buf->getBoundingBox(); else bbox.addInternalBox(buf->getBoundingBox()); } mesh->setBoundingBox(bbox); } void setMeshColor(scene::IMesh *mesh, const video::SColor &color) { if(mesh == NULL) return; u16 mc = mesh->getMeshBufferCount(); for(u16 j=0; jgetMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 vc = buf->getVertexCount(); for(u16 i=0; igetMeshBufferCount(); for(u16 j=0; jgetMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 vc = buf->getVertexCount(); for(u16 i=0; i= y && x >= z) vertices[i].Color = colorX; else if(y >= z) vertices[i].Color = colorY; else vertices[i].Color = colorZ; } } } void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir) { int axisdir = facedir>>2; facedir &= 0x03; u16 mc = mesh->getMeshBufferCount(); for(u16 j = 0; j < mc; j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 vc = buf->getVertexCount(); for(u16 i=0; i bbox; bbox.reset(0,0,0); for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) { scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j); buf->recalculateBoundingBox(); if(j == 0) bbox = buf->getBoundingBox(); else bbox.addInternalBox(buf->getBoundingBox()); } src_mesh->setBoundingBox(bbox); } scene::IMesh* cloneMesh(scene::IMesh *src_mesh) { scene::SMesh* dst_mesh = new scene::SMesh(); for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) { scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); u16 *indices = (u16*)buf->getIndices(); scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer(); temp_buf->append(vertices, buf->getVertexCount(), indices, buf->getIndexCount()); dst_mesh->addMeshBuffer(temp_buf); temp_buf->drop(); } return dst_mesh; } scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f) { scene::SMesh* dst_mesh = new scene::SMesh(); for (u16 j = 0; j < 6; j++) { scene::IMeshBuffer *buf = new scene::SMeshBuffer(); buf->getMaterial().setFlag(video::EMF_LIGHTING, false); buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); dst_mesh->addMeshBuffer(buf); buf->drop(); } video::SColor c(255,255,255,255); std::vector boxes = f->node_box.fixed; for(std::vector::iterator i = boxes.begin(); i != boxes.end(); i++) { aabb3f box = *i; f32 temp; if (box.MinEdge.X > box.MaxEdge.X) { temp=box.MinEdge.X; box.MinEdge.X=box.MaxEdge.X; box.MaxEdge.X=temp; } if (box.MinEdge.Y > box.MaxEdge.Y) { temp=box.MinEdge.Y; box.MinEdge.Y=box.MaxEdge.Y; box.MaxEdge.Y=temp; } if (box.MinEdge.Z > box.MaxEdge.Z) { temp=box.MinEdge.Z; box.MinEdge.Z=box.MaxEdge.Z; box.MaxEdge.Z=temp; } // Compute texture coords f32 tx1 = (box.MinEdge.X/BS)+0.5; f32 ty1 = (box.MinEdge.Y/BS)+0.5; f32 tz1 = (box.MinEdge.Z/BS)+0.5; f32 tx2 = (box.MaxEdge.X/BS)+0.5; f32 ty2 = (box.MaxEdge.Y/BS)+0.5; f32 tz2 = (box.MaxEdge.Z/BS)+0.5; f32 txc[24] = { // up tx1, 1-tz2, tx2, 1-tz1, // down tx1, tz1, tx2, tz2, // right tz1, 1-ty2, tz2, 1-ty1, // left 1-tz2, 1-ty2, 1-tz1, 1-ty1, // back 1-tx2, 1-ty2, 1-tx1, 1-ty1, // front tx1, 1-ty2, tx2, 1-ty1, }; v3f min = box.MinEdge; v3f max = box.MaxEdge; video::S3DVertex vertices[24] = { // up video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]), video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]), video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]), video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]), // down video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]), video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]), video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]), video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]), // right video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]), video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]), video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]), video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]), // left video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]), video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]), video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]), video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]), // back video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[16],txc[17]), video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[18],txc[17]), video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[18],txc[19]), video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[16],txc[19]), // front video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[20],txc[21]), video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[22],txc[21]), video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[22],txc[23]), video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]), }; u16 indices[] = {0,1,2,2,3,0}; for(u16 j = 0; j < 24; j += 4) { scene::IMeshBuffer *buf = dst_mesh->getMeshBuffer(j / 4); buf->append(vertices + j, 4, indices, 6); } } return dst_mesh; }