]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/mesh.cpp
Cleanup and (mostly) document util/string.h and (very) minor refactoring
[dragonfireclient.git] / src / mesh.cpp
index d0d8b0a6ed83133b81d8a0648e1c63bb95ab06fb..19d75f9f5e7c3480a868b91e426351f4bf853488 100644 (file)
@@ -1,29 +1,28 @@
 /*
-Minetest-c55
-Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+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 General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
+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 <cassert>
 #include <iostream>
 #include <IAnimatedMesh.h>
 #include <SAnimatedMesh.h>
-#include <ICameraSceneNode.h>
 
 // In Irrlicht 1.8 the signature of ITexture::lock was changed from
 // (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
@@ -246,6 +245,8 @@ static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data)
                }
        }
 
+       delete[] solidity;
+
        // Add to mesh
        scene::SMesh *mesh = new scene::SMesh();
        mesh->addMeshBuffer(buf);
@@ -259,7 +260,7 @@ scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
                video::IVideoDriver *driver, v3f scale)
 {
        scene::IAnimatedMesh *mesh = NULL;
-       core::dimension2d<u32> size = texture->getSize();
+       core::dimension2d<u32> size = texture->getOriginalSize();
        video::ECOLOR_FORMAT format = texture->getColorFormat();
        if (format == video::ECF_A8R8G8B8)
        {
@@ -279,16 +280,17 @@ scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
 
                // img1 is in the texture's color format, convert to 8-bit ARGB
                video::IImage *img2 = driver->createImage(video::ECF_A8R8G8B8, size);
-               if (img2 != NULL)
+               if (img2 == NULL)
                {
-                       img1->copyTo(img2);
                        img1->drop();
-
-                       mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
-                       img2->unlock();
-                       img2->drop();
+                       return NULL;
                }
+
+               img1->copyTo(img2);
                img1->drop();
+               mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
+               img2->unlock();
+               img2->drop();
        }
 
        // Set default material
@@ -407,78 +409,218 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
        }
 }
 
-video::ITexture *generateTextureFromMesh(scene::IMesh *mesh,
-               IrrlichtDevice *device,
-               core::dimension2d<u32> dim,
-               std::string texture_name,
-               v3f camera_position,
-               v3f camera_lookat,
-               core::CMatrix4<f32> camera_projection_matrix,
-               video::SColorf ambient_light,
-               v3f light_position,
-               video::SColorf light_color,
-               f32 light_radius)
-{
-       video::IVideoDriver *driver = device->getVideoDriver();
-       if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
+void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
+{              
+       int axisdir = facedir>>2;
+       facedir &= 0x03;
+
+       u16 mc = mesh->getMeshBufferCount();
+       for(u16 j = 0; j < mc; j++)
        {
-               static bool warned = false;
-               if(!warned)
+               scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+               video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+               u16 vc = buf->getVertexCount();
+               for(u16 i=0; i<vc; i++)
                {
-                       errorstream<<"generateTextureFromMesh(): EVDF_RENDER_TO_TARGET"
-                                       " not supported."<<std::endl;
-                       warned = true;
+                       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;
+                       }
                }
-               return NULL;
        }
+}
 
-       // Create render target texture
-       video::ITexture *rtt = driver->addRenderTargetTexture(
-                       dim, texture_name.c_str(), video::ECF_A8R8G8B8);
-       if(rtt == NULL)
+void recalculateBoundingBox(scene::IMesh *src_mesh)
+{
+       core::aabbox3d<f32> bbox;
+       bbox.reset(0,0,0);
+       for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
        {
-               errorstream<<"generateTextureFromMesh(): addRenderTargetTexture"
-                               " returned NULL."<<std::endl;
-               return NULL;
+               scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
+               buf->recalculateBoundingBox();
+               if(j == 0)
+                       bbox = buf->getBoundingBox();
+               else
+                       bbox.addInternalBox(buf->getBoundingBox());
        }
+       src_mesh->setBoundingBox(bbox);
+}
 
-       // Set render target
-       driver->setRenderTarget(rtt, true, true, video::SColor(0,0,0,0));
-
-       // Get a scene manager
-       scene::ISceneManager *smgr_main = device->getSceneManager();
-       assert(smgr_main);
-       scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
-       assert(smgr);
-
-       scene::IMeshSceneNode* meshnode = smgr->addMeshSceneNode(mesh, NULL, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
-       meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
-       meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
-       meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
-
-       scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
-                       camera_position, camera_lookat);
-       // second parameter of setProjectionMatrix (isOrthogonal) is ignored
-       camera->setProjectionMatrix(camera_projection_matrix, false);
-
-       smgr->setAmbientLight(ambient_light);
-       smgr->addLightSceneNode(0, light_position, light_color, light_radius);
-
-       // Render scene
-       driver->beginScene(true, true, video::SColor(0,0,0,0));
-       smgr->drawAll();
-       driver->endScene();
-
-       // NOTE: The scene nodes should not be dropped, otherwise
-       //       smgr->drop() segfaults
-       /*cube->drop();
-       camera->drop();
-       light->drop();*/
-       // Drop scene manager
-       smgr->drop();
-
-       // Unset render target
-       driver->setRenderTarget(0, true, true, 0);
-
-       return rtt;
+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();
+               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
+                       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;                                        
 }