]> git.lizzy.rs Git - minetest.git/blobdiff - src/mesh.cpp
Add '/clearobjects quick'
[minetest.git] / src / mesh.cpp
index e021e4c923718d8e16ef4a075e408663e8bdf11b..d79f545f3cca8c9040f5767e849594dd9a7211af 100644 (file)
@@ -33,6 +33,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
 #endif
 
+static void applyFacesShading(video::SColor& color, float factor)
+{
+       color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
+       color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
+       color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
+}
+
 scene::IAnimatedMesh* createCubeMesh(v3f scale)
 {
        video::SColor c(255,255,255,255);
@@ -94,26 +101,25 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
 
 void scaleMesh(scene::IMesh *mesh, v3f scale)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
 
        core::aabbox3d<f32> bbox;
-       bbox.reset(0,0,0);
+       bbox.reset(0, 0, 0);
 
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 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<vc; i++)
-               {
-                       vertices[i].Pos *= scale;
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
+
                buf->recalculateBoundingBox();
 
                // calculate total bounding box
-               if(j == 0)
+               if (j == 0)
                        bbox = buf->getBoundingBox();
                else
                        bbox.addInternalBox(buf->getBoundingBox());
@@ -123,26 +129,25 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
 
 void translateMesh(scene::IMesh *mesh, v3f vec)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
 
        core::aabbox3d<f32> bbox;
-       bbox.reset(0,0,0);
+       bbox.reset(0, 0, 0);
 
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 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<vc; i++)
-               {
-                       vertices[i].Pos += vec;
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
+
                buf->recalculateBoundingBox();
 
                // calculate total bounding box
-               if(j == 0)
+               if (j == 0)
                        bbox = buf->getBoundingBox();
                else
                        bbox.addInternalBox(buf->getBoundingBox());
@@ -150,20 +155,48 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
        mesh->setBoundingBox(bbox);
 }
 
+
 void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
-       
-       u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 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<vc; i++)
-               {
-                       vertices[i].Color = color;
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Color = color;
+       }
+}
+
+void shadeMeshFaces(scene::IMesh *mesh)
+{
+       if (mesh == NULL)
+               return;
+
+       u32 mc = mesh->getMeshBufferCount();
+       for (u32 j = 0; j < mc; j++) {
+               scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) {
+                       video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+                       video::SColor &vc = vertex->Color;
+                       if (vertex->Normal.Y < -0.5) {
+                               applyFacesShading (vc, 0.447213);
+                       } else if (vertex->Normal.Z > 0.5) {
+                               applyFacesShading (vc, 0.670820);
+                       } else if (vertex->Normal.Z < -0.5) {
+                               applyFacesShading (vc, 0.670820);
+                       } else if (vertex->Normal.X > 0.5) {
+                               applyFacesShading (vc, 0.836660);
+                       } else if (vertex->Normal.X < -0.5) {
+                               applyFacesShading (vc, 0.836660);
+                       }
                }
        }
 }
@@ -173,146 +206,139 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
                const video::SColor &colorY,
                const video::SColor &colorZ)
 {
-       if(mesh == NULL)
+       if (mesh == NULL)
                return;
-       
+
        u16 mc = mesh->getMeshBufferCount();
-       for(u16 j=0; j<mc; j++)
-       {
+       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<vc; i++)
-               {
-                       f32 x = fabs(vertices[i].Normal.X);
-                       f32 y = fabs(vertices[i].Normal.Y);
-                       f32 z = fabs(vertices[i].Normal.Z);
-                       if(x >= y && x >= z)
-                               vertices[i].Color = colorX;
-                       else if(y >= z)
-                               vertices[i].Color = colorY;
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) {
+                       video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+                       f32 x = fabs(vertex->Normal.X);
+                       f32 y = fabs(vertex->Normal.Y);
+                       f32 z = fabs(vertex->Normal.Z);
+                       if (x >= y && x >= z)
+                               vertex->Color = colorX;
+                       else if (y >= z)
+                               vertex->Color = colorY;
                        else
-                               vertices[i].Color = colorZ;
+                               vertex->Color = colorZ;
 
                }
        }
 }
 
-void rotateMeshXYby (scene::IMesh *mesh, f64 degrees) 
-{      
+void rotateMeshXYby(scene::IMesh *mesh, f64 degrees)
+{
        u16 mc = mesh->getMeshBufferCount();
-       for(u16 j = 0; j < mc; j++)
-       {
+       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 < vc; i++)
-               {
-                       vertices[i].Pos.rotateXYBy(degrees);
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXYBy(degrees);
        }
 }
 
-void rotateMeshXZby (scene::IMesh *mesh, f64 degrees) 
-{      
+void rotateMeshXZby(scene::IMesh *mesh, f64 degrees)
+{
        u16 mc = mesh->getMeshBufferCount();
-       for(u16 j = 0; j < mc; j++)
-       {
+       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 < vc; i++)
-               {
-                       vertices[i].Pos.rotateXZBy(degrees);
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXZBy(degrees);
        }
 }
 
-void rotateMeshYZby (scene::IMesh *mesh, f64 degrees) 
-{      
+void rotateMeshYZby(scene::IMesh *mesh, f64 degrees)
+{
        u16 mc = mesh->getMeshBufferCount();
-       for(u16 j = 0; j < mc; j++)
-       {
+       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 < vc; i++)
-               {
-                       vertices[i].Pos.rotateYZBy(degrees);
-               }
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++)
+                       ((video::S3DVertex *)(vertices + i * stride))->Pos.rotateYZBy(degrees);
        }
 }
 
 void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
-{              
-       int axisdir = facedir>>2;
+{
+       int axisdir = facedir >> 2;
        facedir &= 0x03;
 
        u16 mc = mesh->getMeshBufferCount();
-       for(u16 j = 0; j < mc; j++)
-       {
+       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<vc; i++)
-               {
-                       switch (axisdir)
-                       {
-                       case 0:
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateXZBy(-90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateXZBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateXZBy(90);
-                               break;
-                       case 1: // z+
-                               vertices[i].Pos.rotateYZBy(90);
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateXYBy(90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateXYBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateXYBy(-90);
-                               break;
-                       case 2: //z-
-                               vertices[i].Pos.rotateYZBy(-90);
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateXYBy(-90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateXYBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateXYBy(90);
-                               break;
-                       case 3:  //x+
-                               vertices[i].Pos.rotateXYBy(-90);
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateYZBy(90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateYZBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateYZBy(-90);
-                               break;
-                       case 4:  //x-
-                               vertices[i].Pos.rotateXYBy(90);
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateYZBy(-90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateYZBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateYZBy(90);
-                               break;
-                       case 5:
-                               vertices[i].Pos.rotateXYBy(-180);
-                               if(facedir == 1)
-                                       vertices[i].Pos.rotateXZBy(90);
-                               else if(facedir == 2)
-                                       vertices[i].Pos.rotateXZBy(180);
-                               else if(facedir == 3)
-                                       vertices[i].Pos.rotateXZBy(-90);
-                               break;
-                       default:
-                               break;
+               const u32 stride = getVertexPitchFromType(buf->getVertexType());
+               u32 vertex_count = buf->getVertexCount();
+               u8 *vertices = (u8 *)buf->getVertices();
+               for (u32 i = 0; i < vertex_count; i++) {
+                       video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+                       switch (axisdir) {
+                               case 0:
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateXZBy(-90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateXZBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateXZBy(90);
+                                       break;
+                               case 1: // z+
+                                       vertex->Pos.rotateYZBy(90);
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateXYBy(90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateXYBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateXYBy(-90);
+                                       break;
+                               case 2: //z-
+                                       vertex->Pos.rotateYZBy(-90);
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateXYBy(-90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateXYBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateXYBy(90);
+                                       break;
+                               case 3:  //x+
+                                       vertex->Pos.rotateXYBy(-90);
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateYZBy(90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateYZBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateYZBy(-90);
+                                       break;
+                               case 4:  //x-
+                                       vertex->Pos.rotateXYBy(90);
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateYZBy(-90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateYZBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateYZBy(90);
+                                       break;
+                               case 5:
+                                       vertex->Pos.rotateXYBy(-180);
+                                       if (facedir == 1)
+                                               vertex->Pos.rotateXZBy(90);
+                                       else if (facedir == 2)
+                                               vertex->Pos.rotateXZBy(180);
+                                       else if (facedir == 3)
+                                               vertex->Pos.rotateXZBy(-90);
+                                       break;
+                               default:
+                                       break;
                        }
                }
        }
@@ -322,11 +348,10 @@ void recalculateBoundingBox(scene::IMesh *src_mesh)
 {
        core::aabbox3d<f32> bbox;
        bbox.reset(0,0,0);
-       for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
-       {
+       for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
                scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
                buf->recalculateBoundingBox();
-               if(j == 0)
+               if (j == 0)
                        bbox = buf->getBoundingBox();
                else
                        bbox.addInternalBox(buf->getBoundingBox());
@@ -337,23 +362,54 @@ void recalculateBoundingBox(scene::IMesh *src_mesh)
 scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
 {
        scene::SMesh* dst_mesh = new scene::SMesh();
-       for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
-       {
+       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();
+               switch (buf->getVertexType()) {
+                       case video::EVT_STANDARD: {
+                               video::S3DVertex *v =
+                                       (video::S3DVertex *) buf->getVertices();
+                               u16 *indices = (u16*)buf->getIndices();
+                               scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
+                               temp_buf->append(v, buf->getVertexCount(),
+                                       indices, buf->getIndexCount());
+                               dst_mesh->addMeshBuffer(temp_buf);
+                               temp_buf->drop();
+                               break;
+                       }
+                       case video::EVT_2TCOORDS: {
+                               video::S3DVertex2TCoords *v =
+                                       (video::S3DVertex2TCoords *) buf->getVertices();
+                               u16 *indices = (u16*)buf->getIndices();
+                               scene::SMeshBufferTangents *temp_buf =
+                                       new scene::SMeshBufferTangents();
+                               temp_buf->append(v, buf->getVertexCount(),
+                                       indices, buf->getIndexCount());
+                               dst_mesh->addMeshBuffer(temp_buf);
+                               temp_buf->drop();
+                               break;
+                       }
+                       case video::EVT_TANGENTS: {
+                               video::S3DVertexTangents *v =
+                                       (video::S3DVertexTangents *) buf->getVertices();
+                               u16 *indices = (u16*)buf->getIndices();
+                               scene::SMeshBufferTangents *temp_buf =
+                                       new scene::SMeshBufferTangents();
+                               temp_buf->append(v, buf->getVertexCount(),
+                                       indices, buf->getIndexCount());
+                               dst_mesh->addMeshBuffer(temp_buf);
+                               temp_buf->drop();
+                               break;
+                       }
+               }
        }
-       return dst_mesh;                                        
+       return dst_mesh;
 }
 
-scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
+scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
+               const f32 *uv_coords)
 {
        scene::SMesh* dst_mesh = new scene::SMesh();
+
        for (u16 j = 0; j < 6; j++)
        {
                scene::IMeshBuffer *buf = new scene::SMeshBuffer();
@@ -362,14 +418,12 @@ scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
                dst_mesh->addMeshBuffer(buf);
                buf->drop();
        }
-       
+
        video::SColor c(255,255,255,255);       
 
-       std::vector<aabb3f> boxes = f->node_box.fixed;
-               
-       for(std::vector<aabb3f>::iterator
+       for(std::vector<aabb3f>::const_iterator
                        i = boxes.begin();
-                       i != boxes.end(); i++)
+                       i != boxes.end(); ++i)
        {
                aabb3f box = *i;
 
@@ -392,27 +446,33 @@ scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
                                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] = {
+
+               // Compute texture UV 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_default[24] = {
                        // up
-                       tx1, 1-tz2, tx2, 1-tz1,
+                       tx1, 1 - tz2, tx2, 1 - tz1,
                        // down
                        tx1, tz1, tx2, tz2,
                        // right
-                       tz1, 1-ty2, tz2, 1-ty1,
+                       tz1, 1 - ty2, tz2, 1 - ty1,
                        // left
-                       1-tz2, 1-ty2, 1-tz1, 1-ty1,
+                       1 - tz2, 1 - ty2, 1 - tz1, 1 - ty1,
                        // back
-                       1-tx2, 1-ty2, 1-tx1, 1-ty1,
+                       1 - tx2, 1 - ty2, 1 - tx1, 1 - ty1,
                        // front
-                       tx1, 1-ty2, tx2, 1-ty1,
+                       tx1, 1 - ty2, tx2, 1 - ty1,
                };
+
+               // use default texture UV mapping if not provided
+               const f32 *txc = uv_coords ? uv_coords : txc_default;
+
                v3f min = box.MinEdge;
                v3f max = box.MaxEdge;