aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/camera.cpp293
-rw-r--r--src/camera.h9
-rw-r--r--src/content_cao.cpp13
-rw-r--r--src/mesh.cpp362
-rw-r--r--src/mesh.h66
-rw-r--r--src/tile.cpp38
-rw-r--r--src/utility.cpp21
-rw-r--r--src/utility.h5
9 files changed, 474 insertions, 334 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a0e063465..61a0b1be8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -161,6 +161,7 @@ set(minetest_SRCS
MyBillboardSceneNode.cpp
content_mapblock.cpp
content_cao.cpp
+ mesh.cpp
mapblock_mesh.cpp
farmesh.cpp
keycode.cpp
diff --git a/src/camera.cpp b/src/camera.cpp
index 8f421e691..c0e171468 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -22,21 +22,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client.h"
#include "main.h" // for g_settings
#include "map.h"
+#include "mesh.h"
#include "player.h"
#include "tile.h"
#include <cmath>
-#include <SAnimatedMesh.h>
#include "settings.h"
#include "nodedef.h" // For wield visualization
-// 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
-
Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
m_smgr(smgr),
m_playernode(NULL),
@@ -480,7 +472,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
case NDT_ALLFACES:
case NDT_ALLFACES_OPTIONAL:
m_wieldnode->setCube(ndef->get(content).tiles);
- m_wieldnode->setScale(v3f(30));
isCube = true;
break;
default:
@@ -492,7 +483,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
if (!isCube)
{
m_wieldnode->setSprite(item->getImageRaw());
- m_wieldnode->setScale(v3f(40));
}
m_wieldnode->setVisible(true);
@@ -501,7 +491,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
{
// Bare hands
m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png"));
- m_wieldnode->setScale(v3f(40));
m_wieldnode->setVisible(true);
}
}
@@ -536,7 +525,6 @@ ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
ISceneNode(parent, mgr, id, position, rotation, scale)
{
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
- m_thickness = 0.1;
m_cubemesh = NULL;
m_is_cube = false;
m_light = LIGHT_MAX;
@@ -551,6 +539,8 @@ ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
{
+ const v3f sprite_scale(40.0, 40.0, 4.0); // width, height, thickness
+
if (texture == NULL)
{
m_meshnode->setVisible(false);
@@ -568,7 +558,9 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
else
{
// Texture was not yet extruded, do it now and save in cache
- mesh = extrude(texture);
+ mesh = createExtrudedMesh(texture,
+ SceneManager->getVideoDriver(),
+ sprite_scale);
if (mesh == NULL)
{
dstream << "Warning: failed to extrude sprite" << std::endl;
@@ -580,7 +572,6 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
mesh->drop();
}
- m_meshnode->setScale(v3f(1, 1, m_thickness));
m_meshnode->getMaterial(0).setTexture(0, texture);
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
@@ -592,11 +583,14 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
{
+ const v3f cube_scale(30.0, 30.0, 30.0);
+
if (m_cubemesh == NULL)
- m_cubemesh = createCubeMesh();
+ {
+ m_cubemesh = createCubeMesh(cube_scale);
+ }
m_meshnode->setMesh(m_cubemesh);
- m_meshnode->setScale(v3f(1));
for (int i = 0; i < 6; ++i)
{
// Get the tile texture and atlas transformation
@@ -626,7 +620,7 @@ void ExtrudedSpriteSceneNode::updateLight(u8 light)
// Set brightness one lower than incoming light
diminish_light(li);
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_meshnode->getMesh(), color);
+ setMeshColor(m_meshnode->getMesh(), color);
}
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
@@ -637,13 +631,6 @@ void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
cache->removeMesh(mesh);
}
-void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
-{
- m_thickness = thickness;
- if (!m_is_cube)
- m_meshnode->setScale(v3f(1, 1, thickness));
-}
-
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
{
return m_meshnode->getBoundingBox();
@@ -667,259 +654,3 @@ io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
path.append("/[extruded]");
return path;
}
-
-scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrudeARGB(u32 width, u32 height, u8* data)
-{
- const s32 argb_wstep = 4 * width;
- 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[(width+2) * (height+2)];
- u32 wstep = width + 2;
- for (u32 y = 0; y < height + 2; ++y)
- {
- u8* scanline = solidity + y * wstep;
- if (y == 0 || y == height + 1)
- {
- for (u32 x = 0; x < width + 2; ++x)
- scanline[x] = 0;
- }
- else
- {
- scanline[0] = 0;
- u8* argb_scanline = data + (y - 1) * argb_wstep;
- for (u32 x = 0; x < width; ++x)
- scanline[x+1] = (argb_scanline[x*4+3] >= alpha_threshold);
- scanline[width + 1] = 0;
- }
- }
-
- // without this, there would be occasional "holes" in the mesh
- f32 eps = 0.01;
-
- for (u32 y = 0; y <= height; ++y)
- {
- u8* scanline = solidity + y * wstep + 1;
- for (u32 x = 0; x <= width; ++x)
- {
- if (scanline[x] && !scanline[x + wstep])
- {
- u32 xx = x + 1;
- while (scanline[xx] && !scanline[xx + wstep])
- ++xx;
- f32 vx1 = (x - eps) / (f32) width - 0.5;
- f32 vx2 = (xx + eps) / (f32) width - 0.5;
- f32 vy = 0.5 - (y - eps) / (f32) height;
- f32 tx1 = x / (f32) width;
- f32 tx2 = xx / (f32) width;
- f32 ty = (y - 0.5) / (f32) height;
- video::S3DVertex vertices[8] =
- {
- video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
- video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
- video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
- video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
- };
- u16 indices[6] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
- x = xx - 1;
- }
- if (!scanline[x] && scanline[x + wstep])
- {
- u32 xx = x + 1;
- while (!scanline[xx] && scanline[xx + wstep])
- ++xx;
- f32 vx1 = (x - eps) / (f32) width - 0.5;
- f32 vx2 = (xx + eps) / (f32) width - 0.5;
- f32 vy = 0.5 - (y + eps) / (f32) height;
- f32 tx1 = x / (f32) width;
- f32 tx2 = xx / (f32) width;
- f32 ty = (y + 0.5) / (f32) height;
- video::S3DVertex vertices[8] =
- {
- video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
- video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
- video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
- video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
- };
- u16 indices[6] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
- x = xx - 1;
- }
- }
- }
-
- for (u32 x = 0; x <= width; ++x)
- {
- u8* scancol = solidity + x + wstep;
- for (u32 y = 0; y <= height; ++y)
- {
- if (scancol[y * wstep] && !scancol[y * wstep + 1])
- {
- u32 yy = y + 1;
- while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
- ++yy;
- f32 vx = (x - eps) / (f32) width - 0.5;
- f32 vy1 = 0.5 - (y - eps) / (f32) height;
- f32 vy2 = 0.5 - (yy + eps) / (f32) height;
- f32 tx = (x - 0.5) / (f32) width;
- f32 ty1 = y / (f32) height;
- f32 ty2 = yy / (f32) height;
- video::S3DVertex vertices[8] =
- {
- video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
- video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
- video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
- video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
- };
- u16 indices[6] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
- y = yy - 1;
- }
- if (!scancol[y * wstep] && scancol[y * wstep + 1])
- {
- u32 yy = y + 1;
- while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
- ++yy;
- f32 vx = (x + eps) / (f32) width - 0.5;
- f32 vy1 = 0.5 - (y - eps) / (f32) height;
- f32 vy2 = 0.5 - (yy + eps) / (f32) height;
- f32 tx = (x + 0.5) / (f32) width;
- f32 ty1 = y / (f32) height;
- f32 ty2 = yy / (f32) height;
- video::S3DVertex vertices[8] =
- {
- video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
- video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
- video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
- video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
- };
- u16 indices[6] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
- y = yy - 1;
- }
- }
- }
-
- // Add to mesh
- scene::SMesh* mesh = new scene::SMesh();
- buf->recalculateBoundingBox();
- mesh->addMeshBuffer(buf);
- buf->drop();
- mesh->recalculateBoundingBox();
- scene::SAnimatedMesh* anim_mesh = new scene::SAnimatedMesh(mesh);
- mesh->drop();
- return anim_mesh;
-}
-
-scene::IAnimatedMesh* ExtrudedSpriteSceneNode::extrude(video::ITexture* texture)
-{
- scene::IAnimatedMesh* mesh = NULL;
- core::dimension2d<u32> size = texture->getSize();
- video::ECOLOR_FORMAT format = texture->getColorFormat();
- if (format == video::ECF_A8R8G8B8)
- {
- // Texture is in the correct color format, we can pass it
- // to extrudeARGB right away.
- void* data = texture->lock(MY_ETLM_READ_ONLY);
- if (data == NULL)
- return NULL;
- mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
- texture->unlock();
- }
- else
- {
- video::IVideoDriver* driver = SceneManager->getVideoDriver();
-
- video::IImage* img1 = driver->createImageFromData(format, size, texture->lock(MY_ETLM_READ_ONLY));
- if (img1 == NULL)
- return NULL;
-
- // 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)
- {
- img1->copyTo(img2);
- img1->drop();
-
- mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
- img2->unlock();
- img2->drop();
- }
- img1->drop();
- }
- return mesh;
-}
-
-scene::IMesh* ExtrudedSpriteSceneNode::createCubeMesh()
-{
- 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);
- buf->recalculateBoundingBox();
- mesh->addMeshBuffer(buf);
- buf->drop();
- }
- mesh->recalculateBoundingBox();
- return mesh;
-}
diff --git a/src/camera.h b/src/camera.h
index 973ae3f31..d5789d807 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h"
#include "inventory.h"
+#include "mesh.h"
#include "tile.h"
#include "utility.h"
#include <ICameraSceneNode.h>
@@ -206,9 +207,6 @@ public:
void setSprite(video::ITexture* texture);
void setCube(const TileSpec tiles[6]);
- f32 getSpriteThickness() const { return m_thickness; }
- void setSpriteThickness(f32 thickness);
-
void updateLight(u8 light);
void removeSpriteFromCache(video::ITexture* texture);
@@ -219,16 +217,11 @@ public:
private:
scene::IMeshSceneNode* m_meshnode;
- f32 m_thickness;
scene::IMesh* m_cubemesh;
bool m_is_cube;
u8 m_light;
- // internal extrusion helper methods
io::path getExtrudedName(video::ITexture* texture);
- scene::IAnimatedMesh* extrudeARGB(u32 width, u32 height, u8* data);
- scene::IAnimatedMesh* extrude(video::ITexture* texture);
- scene::IMesh* createCubeMesh();
};
#endif
diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index b9dc91e63..da68004ce 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h"
#include "clientobject.h"
#include "content_object.h"
+#include "mesh.h"
#include "utility.h" // For IntervalLimiter
class Settings;
#include "MyBillboardSceneNode.h"
@@ -630,7 +631,7 @@ void ItemCAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_node->getMesh(), color);
+ setMeshColor(m_node->getMesh(), color);
}
v3s16 ItemCAO::getLightPosition()
@@ -778,7 +779,7 @@ void RatCAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_node->getMesh(), color);
+ setMeshColor(m_node->getMesh(), color);
}
v3s16 RatCAO::getLightPosition()
@@ -934,7 +935,7 @@ void Oerkki1CAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_node->getMesh(), color);
+ setMeshColor(m_node->getMesh(), color);
}
v3s16 Oerkki1CAO::getLightPosition()
@@ -1165,7 +1166,7 @@ void FireflyCAO::updateLight(u8 light_at_pos)
u8 li = 255;
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_node->getMesh(), color);
+ setMeshColor(m_node->getMesh(), color);
}
v3s16 FireflyCAO::getLightPosition()
@@ -1866,7 +1867,7 @@ public:
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
if(m_meshnode){
- setMeshVerticesColor(m_meshnode->getMesh(), color);
+ setMeshColor(m_meshnode->getMesh(), color);
m_meshnode->setVisible(true);
}
if(m_spritenode){
@@ -2250,7 +2251,7 @@ public:
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
- setMeshVerticesColor(m_node->getMesh(), color);
+ setMeshColor(m_node->getMesh(), color);
}
v3s16 getLightPosition()
diff --git a/src/mesh.cpp b/src/mesh.cpp
new file mode 100644
index 000000000..1d347a09f
--- /dev/null
+++ b/src/mesh.cpp
@@ -0,0 +1,362 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 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
+(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.
+
+You should have received a copy of the GNU 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 <IAnimatedMesh.h>
+#include <SAnimatedMesh.h>
+
+// 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);
+ 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.01;
+
+ for (u32 y = 0; y <= theight; ++y)
+ {
+ u8 *scanline = solidity + y * wstep + 1;
+ for (u32 x = 0; x <= twidth; ++x)
+ {
+ if (scanline[x] && !scanline[x + wstep])
+ {
+ u32 xx = x + 1;
+ while (scanline[xx] && !scanline[xx + wstep])
+ ++xx;
+ f32 vx1 = (x - eps) / (f32) twidth - 0.5;
+ f32 vx2 = (xx + eps) / (f32) twidth - 0.5;
+ f32 vy = 0.5 - (y - eps) / (f32) theight;
+ f32 tx1 = x / (f32) twidth;
+ f32 tx2 = xx / (f32) twidth;
+ f32 ty = (y - 0.5) / (f32) theight;
+ video::S3DVertex vertices[8] =
+ {
+ video::S3DVertex(vx1,vy,-0.5, 0,-1,0, c, tx1,ty),
+ video::S3DVertex(vx2,vy,-0.5, 0,-1,0, c, tx2,ty),
+ video::S3DVertex(vx2,vy,+0.5, 0,-1,0, c, tx2,ty),
+ video::S3DVertex(vx1,vy,+0.5, 0,-1,0, c, tx1,ty),
+ };
+ u16 indices[6] = {0,1,2,2,3,0};
+ buf->append(vertices, 4, indices, 6);
+ x = xx - 1;
+ }
+ if (!scanline[x] && scanline[x + wstep])
+ {
+ u32 xx = x + 1;
+ while (!scanline[xx] && scanline[xx + wstep])
+ ++xx;
+ f32 vx1 = (x - eps) / (f32) twidth - 0.5;
+ f32 vx2 = (xx + eps) / (f32) twidth - 0.5;
+ f32 vy = 0.5 - (y + eps) / (f32) theight;
+ f32 tx1 = x / (f32) twidth;
+ f32 tx2 = xx / (f32) twidth;
+ f32 ty = (y + 0.5) / (f32) theight;
+ video::S3DVertex vertices[8] =
+ {
+ video::S3DVertex(vx1,vy,-0.5, 0,1,0, c, tx1,ty),
+ video::S3DVertex(vx1,vy,+0.5, 0,1,0, c, tx1,ty),
+ video::S3DVertex(vx2,vy,+0.5, 0,1,0, c, tx2,ty),
+ video::S3DVertex(vx2,vy,-0.5, 0,1,0, c, tx2,ty),
+ };
+ u16 indices[6] = {0,1,2,2,3,0};
+ buf->append(vertices, 4, indices, 6);
+ x = xx - 1;
+ }
+ }
+ }
+
+ for (u32 x = 0; x <= twidth; ++x)
+ {
+ u8 *scancol = solidity + x + wstep;
+ for (u32 y = 0; y <= theight; ++y)
+ {
+ if (scancol[y * wstep] && !scancol[y * wstep + 1])
+ {
+ u32 yy = y + 1;
+ while (scancol[yy * wstep] && !scancol[yy * wstep + 1])
+ ++yy;
+ f32 vx = (x - eps) / (f32) twidth - 0.5;
+ f32 vy1 = 0.5 - (y - eps) / (f32) theight;
+ f32 vy2 = 0.5 - (yy + eps) / (f32) theight;
+ f32 tx = (x - 0.5) / (f32) twidth;
+ f32 ty1 = y / (f32) theight;
+ f32 ty2 = yy / (f32) theight;
+ video::S3DVertex vertices[8] =
+ {
+ video::S3DVertex(vx,vy1,-0.5, 1,0,0, c, tx,ty1),
+ video::S3DVertex(vx,vy1,+0.5, 1,0,0, c, tx,ty1),
+ video::S3DVertex(vx,vy2,+0.5, 1,0,0, c, tx,ty2),
+ video::S3DVertex(vx,vy2,-0.5, 1,0,0, c, tx,ty2),
+ };
+ u16 indices[6] = {0,1,2,2,3,0};
+ buf->append(vertices, 4, indices, 6);
+ y = yy - 1;
+ }
+ if (!scancol[y * wstep] && scancol[y * wstep + 1])
+ {
+ u32 yy = y + 1;
+ while (!scancol[yy * wstep] && scancol[yy * wstep + 1])
+ ++yy;
+ f32 vx = (x + eps) / (f32) twidth - 0.5;
+ f32 vy1 = 0.5 - (y - eps) / (f32) theight;
+ f32 vy2 = 0.5 - (yy + eps) / (f32) theight;
+ f32 tx = (x + 0.5) / (f32) twidth;
+ f32 ty1 = y / (f32) theight;
+ f32 ty2 = yy / (f32) theight;
+ video::S3DVertex vertices[8] =
+ {
+ video::S3DVertex(vx,vy1,-0.5, -1,0,0, c, tx,ty1),
+ video::S3DVertex(vx,vy2,-0.5, -1,0,0, c, tx,ty2),
+ video::S3DVertex(vx,vy2,+0.5, -1,0,0, c, tx,ty2),
+ video::S3DVertex(vx,vy1,+0.5, -1,0,0, c, tx,ty1),
+ };
+ u16 indices[6] = {0,1,2,2,3,0};
+ buf->append(vertices, 4, indices, 6);
+ y = yy - 1;
+ }
+ }
+ }
+
+ // Add to mesh
+ scene::SMesh *mesh = new scene::SMesh();
+ mesh->addMeshBuffer(buf);
+ buf->drop();
+ scene::SAnimatedMesh *anim_mesh = new scene::SAnimatedMesh(mesh);
+ mesh->drop();
+ return anim_mesh;
+}
+
+scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
+ video::IVideoDriver *driver, v3f scale)
+{
+ scene::IAnimatedMesh *mesh = NULL;
+ core::dimension2d<u32> size = texture->getSize();
+ video::ECOLOR_FORMAT format = texture->getColorFormat();
+ if (format == video::ECF_A8R8G8B8)
+ {
+ // Texture is in the correct color format, we can pass it
+ // to extrudeARGB right away.
+ void *data = texture->lock(MY_ETLM_READ_ONLY);
+ if (data == NULL)
+ return NULL;
+ mesh = extrudeARGB(size.Width, size.Height, (u8*) data);
+ texture->unlock();
+ }
+ else
+ {
+ video::IImage *img1 = driver->createImageFromData(format, size, texture->lock(MY_ETLM_READ_ONLY));
+ if (img1 == NULL)
+ return NULL;
+
+ // 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)
+ {
+ img1->copyTo(img2);
+ img1->drop();
+
+ mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock());
+ img2->unlock();
+ img2->drop();
+ }
+ img1->drop();
+ }
+ scaleMesh(mesh, scale); // also recalculates bounding box
+ return mesh;
+}
+
+void scaleMesh(scene::IMesh *mesh, v3f scale)
+{
+ if(mesh == NULL)
+ return;
+
+ core::aabbox3d<f32> bbox;
+ bbox.reset(0,0,0);
+
+ 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<vc; i++)
+ {
+ vertices[i].Pos *= scale;
+ }
+ buf->recalculateBoundingBox();
+
+ // 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; 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;
+ }
+ }
+}
+
+void setMeshColorByNormalXYZ(scene::IMesh *mesh,
+ const video::SColor &colorX,
+ const video::SColor &colorY,
+ const video::SColor &colorZ)
+{
+ if(mesh == NULL)
+ return;
+
+ 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<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;
+ else
+ vertices[i].Color = colorZ;
+
+ }
+ }
+}
diff --git a/src/mesh.h b/src/mesh.h
new file mode 100644
index 000000000..33e072927
--- /dev/null
+++ b/src/mesh.h
@@ -0,0 +1,66 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 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
+(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.
+
+You should have received a copy of the GNU 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 MESH_HEADER
+#define MESH_HEADER
+
+#include "common_irrlicht.h"
+
+/*
+ Create a new cube mesh.
+ Vertices are at (+-scale.X/2, +-scale.Y/2, +-scale.Z/2).
+
+ The resulting mesh has 6 materials (up, down, right, left, back, front)
+ which must be defined by the caller.
+*/
+scene::IAnimatedMesh* createCubeMesh(v3f scale);
+
+/*
+ Create a new extruded mesh from a texture.
+ Maximum bounding box is (+-scale.X/2, +-scale.Y/2, +-scale.Z).
+ Thickness is in Z direction.
+
+ The resulting mesh has 1 material which must be defined by the caller.
+*/
+scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture,
+ video::IVideoDriver *driver, v3f scale);
+
+/*
+ Multiplies each vertex coordinate by the specified scaling factors
+ (componentwise vector multiplication).
+*/
+void scaleMesh(scene::IMesh *mesh, v3f scale);
+
+/*
+ Set a constant color for all vertices in the mesh
+*/
+void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
+
+/*
+ Set the color of all vertices in the mesh.
+ For each vertex, determine the largest absolute entry in
+ the normal vector, and choose one of colorX, colorY or
+ colorZ accordingly.
+*/
+void setMeshColorByNormalXYZ(scene::IMesh *mesh,
+ const video::SColor &colorX,
+ const video::SColor &colorY,
+ const video::SColor &colorZ);
+
+#endif
diff --git a/src/tile.cpp b/src/tile.cpp
index 27454c321..89f345197 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "utility.h"
#include "settings.h"
+#include "mesh.h"
#include <ICameraSceneNode.h>
#include "log.h"
#include "mapnode.h" // For texture atlas making
@@ -1468,11 +1469,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
assert(img_top && img_left && img_right);
// Create textures from images
- // TODO: Use them all
video::ITexture *texture_top = driver->addTexture(
(imagename_top + "__temp__").c_str(), img_top);
- assert(texture_top);
-
+ video::ITexture *texture_left = driver->addTexture(
+ (imagename_left + "__temp__").c_str(), img_left);
+ video::ITexture *texture_right = driver->addTexture(
+ (imagename_right + "__temp__").c_str(), img_right);
+ assert(texture_top && texture_left && texture_right);
+
// Drop images
img_top->drop();
img_left->drop();
@@ -1499,17 +1503,24 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
Create scene:
- An unit cube is centered at 0,0,0
- Camera looks at cube from Y+, Z- towards Y-, Z+
- NOTE: Cube has to be changed to something else because
- the textures cannot be set individually (or can they?)
*/
- scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1,
- v3f(0,0,0), v3f(0, 45, 0));
+ scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1));
+ setMeshColor(cube, video::SColor(255, 255, 255, 255));
+
+ scene::IMeshSceneNode* cubenode = smgr->addMeshSceneNode(cube, NULL, -1, v3f(0,0,0), v3f(0,45,0), v3f(1,1,1), true);
+ cube->drop();
+
// Set texture of cube
- cube->setMaterialTexture(0, texture_top);
- //cube->setMaterialFlag(video::EMF_LIGHTING, false);
- cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
- cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
+ cubenode->getMaterial(0).setTexture(0, texture_top);
+ cubenode->getMaterial(1).setTexture(0, texture_top);
+ cubenode->getMaterial(2).setTexture(0, texture_right);
+ cubenode->getMaterial(3).setTexture(0, texture_right);
+ cubenode->getMaterial(4).setTexture(0, texture_left);
+ cubenode->getMaterial(5).setTexture(0, texture_left);
+ cubenode->setMaterialFlag(video::EMF_LIGHTING, true);
+ cubenode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
+ cubenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
v3f(0, 1.0, -1.5), v3f(0, 0, 0));
@@ -1519,7 +1530,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
camera->setProjectionMatrix(pm, true);
/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
- v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
+ v3f(-50, 100, -75), video::SColorf(0.5,0.5,0.5), 1000);
smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));
@@ -1540,8 +1551,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
driver->setRenderTarget(0, true, true, 0);
// Free textures of images
- // TODO: When all are used, free them all
driver->removeTexture(texture_top);
+ driver->removeTexture(texture_left);
+ driver->removeTexture(texture_right);
// Create image of render target
video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);
diff --git a/src/utility.cpp b/src/utility.cpp
index 87c81cb2a..4e9f307d8 100644
--- a/src/utility.cpp
+++ b/src/utility.cpp
@@ -172,27 +172,6 @@ int myrand_range(int min, int max)
return (myrand()%(max-min+1))+min;
}
-#ifndef SERVER
-// Sets the color of all vertices in the mesh
-void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color)
-{
- if(mesh == NULL)
- return;
-
- 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<vc; i++)
- {
- vertices[i].Color = color;
- }
- }
-}
-#endif
-
/*
blockpos: position of block in block coordinates
camera_pos: position of camera in nodes
diff --git a/src/utility.h b/src/utility.h
index 47696cbf8..14b49772b 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -694,11 +694,6 @@ private:
u32 *m_result;
};
-#ifndef SERVER
-// Sets the color of all vertices in the mesh
-void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
-#endif
-
// Calculates the borders of a "d-radius" cube
inline void getFacePositions(core::list<v3s16> &list, u16 d)
{