/* 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 "log.h" #include #include #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; } static scene::IAnimatedMesh* extrudeARGB(u32 twidth, u32 theight, u8 *data) { const s32 argb_wstep = 4 * twidth; const s32 alpha_threshold = 1; scene::IMeshBuffer *buf = new scene::SMeshBuffer(); video::SColor c(255,255,255,255); // Front and back { video::S3DVertex vertices[8] = { 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), 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, 1,0), 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, 0,1), }; u16 indices[12] = {0,1,2,2,3,0,4,5,6,6,7,4}; buf->append(vertices, 8, indices, 12); } // "Interior" // (add faces where a solid pixel is next to a transparent one) u8 *solidity = new u8[(twidth+2) * (theight+2)]; u32 wstep = twidth + 2; for (u32 y = 0; y < theight + 2; ++y) { u8 *scanline = solidity + y * wstep; if (y == 0 || y == theight + 1) { for (u32 x = 0; x < twidth + 2; ++x) scanline[x] = 0; } else { scanline[0] = 0; u8 *argb_scanline = data + (y - 1) * argb_wstep; for (u32 x = 0; x < twidth; ++x) scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold); scanline[twidth + 1] = 0; } } // without this, there would be occasional "holes" in the mesh f32 eps = 0.0/* Minetest Copyright (C) 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 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. */ #ifndef GETTEXT_HEADER #define GETTEXT_HEADER #include "config.h" // for USE_GETTEXT #if USE_GETTEXT #include <libintl.h> #else // In certain environments, some standard headers like <iomanip> // and <locale> include libintl.h. If libintl.h is included after // we define our gettext macro below, this causes a syntax error // at the declaration of the gettext function in libintl.h. // Fix this by including such a header before defining the macro. // See issue #4446. // Note that we can't include libintl.h directly since we're in // the USE_GETTEXT=0 case and can't assume that gettext is installed. #include <locale> #define gettext(String) String #endif #define _(String) gettext(String) #define gettext_noop(String) (String) #define N_(String) gettext_noop((String)) void init_gettext(const char *path, const std::string &configured_language, int argc, char *argv[]); extern wchar_t *utf8_to_wide_c(const char *str); // You must free the returned string! // The returned string is allocated using new inline const wchar_t *wgettext(const char *str) { return utf8_to_wide_c(gettext(str)); } inline std::string strgettext(const std::string &text) { return gettext(text.c_str()); } #endif ertex*)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; } } } video::ITexture *generateTextureFromMesh(scene::IMesh *mesh, IrrlichtDevice *device, core::dimension2d dim, std::string texture_name, v3f camera_position, v3f camera_lookat, core::CMatrix4 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) { static bool warned = false; if(!warned) { errorstream<<"generateTextureFromMesh(): EVDF_RENDER_TO_TARGET" " not supported."<addRenderTargetTexture( dim, texture_name.c_str(), video::ECF_A8R8G8B8); if(rtt == NULL) { errorstream<<"generateTextureFromMesh(): addRenderTargetTexture" " returned NULL."<setRenderTarget(rtt, false, 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, false, true, 0); return rtt; }