inventorycube: use all three specified textures; also moved mesh creation / modification functions to mesh.cpp; in lua, inventorycube is now called minetest.inventorycube

This commit is contained in:
Kahrl 2011-12-03 08:40:32 +01:00 committed by Perttu Ahola
parent 275a348b75
commit 392485aa45
12 changed files with 517 additions and 375 deletions

View File

@ -303,6 +303,19 @@ function test_stackstring()
end end
test_stackstring() test_stackstring()
--
-- nodeitem helpers
--
minetest.inventorycube = function(img1, img2, img3)
img2 = img2 or img1
img3 = img3 or img1
return "[inventorycube"
.. "{" .. img1:gsub("%^", "&")
.. "{" .. img2:gsub("%^", "&")
.. "{" .. img3:gsub("%^", "&")
end
-- --
-- craftitem helpers -- craftitem helpers
-- --

View File

@ -824,20 +824,11 @@ function digprop_glasslike(toughness)
} }
end end
function inventorycube(img1, img2, img3)
img2 = img2 or img1
img3 = img3 or img1
return "[inventorycube"
.. "{" .. img1:gsub("%^", "&")
.. "{" .. img2:gsub("%^", "&")
.. "{" .. img3:gsub("%^", "&")
end
-- Legacy nodes -- Legacy nodes
minetest.register_node(":stone", { minetest.register_node(":stone", {
tile_images = {"stone.png"}, tile_images = {"stone.png"},
inventory_image = inventorycube("stone.png"), inventory_image = minetest.inventorycube("stone.png"),
paramtype = "mineral", paramtype = "mineral",
is_ground_content = true, is_ground_content = true,
often_contains_mineral = true, -- Texture atlas hint often_contains_mineral = true, -- Texture atlas hint
@ -847,7 +838,7 @@ minetest.register_node(":stone", {
minetest.register_node(":dirt_with_grass", { minetest.register_node(":dirt_with_grass", {
tile_images = {"grass.png", "mud.png", "mud.png^grass_side.png"}, tile_images = {"grass.png", "mud.png", "mud.png^grass_side.png"},
inventory_image = inventorycube("mud.png^grass_side.png"), inventory_image = minetest.inventorycube("mud.png^grass_side.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_dirtlike(1.0), material = digprop_dirtlike(1.0),
dug_item = 'node "dirt" 1', dug_item = 'node "dirt" 1',
@ -863,14 +854,14 @@ minetest.register_node(":dirt_with_grass_footsteps", {
minetest.register_node(":dirt", { minetest.register_node(":dirt", {
tile_images = {"mud.png"}, tile_images = {"mud.png"},
inventory_image = inventorycube("mud.png"), inventory_image = minetest.inventorycube("mud.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_dirtlike(1.0), material = digprop_dirtlike(1.0),
}) })
minetest.register_node(":sand", { minetest.register_node(":sand", {
tile_images = {"sand.png"}, tile_images = {"sand.png"},
inventory_image = inventorycube("sand.png"), inventory_image = minetest.inventorycube("sand.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_dirtlike(1.0), material = digprop_dirtlike(1.0),
cookresult_item = 'node "glass" 1', cookresult_item = 'node "glass" 1',
@ -878,14 +869,14 @@ minetest.register_node(":sand", {
minetest.register_node(":gravel", { minetest.register_node(":gravel", {
tile_images = {"gravel.png"}, tile_images = {"gravel.png"},
inventory_image = inventorycube("gravel.png"), inventory_image = minetest.inventorycube("gravel.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_gravellike(1.0), material = digprop_gravellike(1.0),
}) })
minetest.register_node(":sandstone", { minetest.register_node(":sandstone", {
tile_images = {"sandstone.png"}, tile_images = {"sandstone.png"},
inventory_image = inventorycube("sandstone.png"), inventory_image = minetest.inventorycube("sandstone.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_dirtlike(1.0), -- FIXME should this be stonelike? material = digprop_dirtlike(1.0), -- FIXME should this be stonelike?
dug_item = 'node "sand" 1', -- FIXME is this intentional? dug_item = 'node "sand" 1', -- FIXME is this intentional?
@ -893,7 +884,7 @@ minetest.register_node(":sandstone", {
minetest.register_node(":clay", { minetest.register_node(":clay", {
tile_images = {"clay.png"}, tile_images = {"clay.png"},
inventory_image = inventorycube("clay.png"), inventory_image = minetest.inventorycube("clay.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_dirtlike(1.0), material = digprop_dirtlike(1.0),
dug_item = 'craft "lump_of_clay" 4', dug_item = 'craft "lump_of_clay" 4',
@ -901,7 +892,7 @@ minetest.register_node(":clay", {
minetest.register_node(":brick", { minetest.register_node(":brick", {
tile_images = {"brick.png"}, tile_images = {"brick.png"},
inventory_image = inventorycube("brick.png"), inventory_image = minetest.inventorycube("brick.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_stonelike(1.0), material = digprop_stonelike(1.0),
dug_item = 'craft "clay_brick" 4', dug_item = 'craft "clay_brick" 4',
@ -909,7 +900,7 @@ minetest.register_node(":brick", {
minetest.register_node(":tree", { minetest.register_node(":tree", {
tile_images = {"tree_top.png", "tree_top.png", "tree.png"}, tile_images = {"tree_top.png", "tree_top.png", "tree.png"},
inventory_image = inventorycube("tree_top.png", "tree.png", "tree.png"), inventory_image = minetest.inventorycube("tree_top.png", "tree.png", "tree.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_woodlike(1.0), material = digprop_woodlike(1.0),
cookresult_item = 'craft "lump_of_coal" 1', cookresult_item = 'craft "lump_of_coal" 1',
@ -918,7 +909,7 @@ minetest.register_node(":tree", {
minetest.register_node(":jungletree", { minetest.register_node(":jungletree", {
tile_images = {"jungletree_top.png", "jungletree_top.png", "jungletree.png"}, tile_images = {"jungletree_top.png", "jungletree_top.png", "jungletree.png"},
inventory_image = inventorycube("jungletree_top.png", "jungletree.png", "jungletree.png"), inventory_image = minetest.inventorycube("jungletree_top.png", "jungletree.png", "jungletree.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_woodlike(1.0), material = digprop_woodlike(1.0),
cookresult_item = 'craft "lump_of_coal" 1', cookresult_item = 'craft "lump_of_coal" 1',
@ -941,7 +932,7 @@ minetest.register_node(":leaves", {
drawtype = "allfaces_optional", drawtype = "allfaces_optional",
visual_scale = 1.3, visual_scale = 1.3,
tile_images = {"leaves.png"}, tile_images = {"leaves.png"},
inventory_image = "leaves.png", inventory_image = minetest.inventorycube("leaves.png"),
light_propagates = true, light_propagates = true,
paramtype = "light", paramtype = "light",
material = digprop_leaveslike(1.0), material = digprop_leaveslike(1.0),
@ -952,7 +943,7 @@ minetest.register_node(":leaves", {
minetest.register_node(":cactus", { minetest.register_node(":cactus", {
tile_images = {"cactus_top.png", "cactus_top.png", "cactus_side.png"}, tile_images = {"cactus_top.png", "cactus_top.png", "cactus_side.png"},
inventory_image = inventorycube("cactus_top.png", "cactus_side.png", "cactus_side.png"), inventory_image = minetest.inventorycube("cactus_top.png", "cactus_side.png", "cactus_side.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_woodlike(0.75), material = digprop_woodlike(0.75),
furnace_burntime = 15, furnace_burntime = 15,
@ -972,9 +963,7 @@ minetest.register_node(":papyrus", {
minetest.register_node(":bookshelf", { minetest.register_node(":bookshelf", {
tile_images = {"wood.png", "wood.png", "bookshelf.png"}, tile_images = {"wood.png", "wood.png", "bookshelf.png"},
-- FIXME: inventorycube only cares for the first texture inventory_image = minetest.inventorycube("wood.png", "bookshelf.png", "bookshelf.png"),
--inventory_image = inventorycube("wood.png", "bookshelf.png", "bookshelf.png")
inventory_image = inventorycube("bookshelf.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_woodlike(0.75), material = digprop_woodlike(0.75),
furnace_burntime = 30, furnace_burntime = 30,
@ -983,7 +972,7 @@ minetest.register_node(":bookshelf", {
minetest.register_node(":glass", { minetest.register_node(":glass", {
drawtype = "glasslike", drawtype = "glasslike",
tile_images = {"glass.png"}, tile_images = {"glass.png"},
inventory_image = inventorycube("glass.png"), inventory_image = minetest.inventorycube("glass.png"),
light_propagates = true, light_propagates = true,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
@ -1050,7 +1039,7 @@ minetest.register_node(":coalstone", {
minetest.register_node(":wood", { minetest.register_node(":wood", {
tile_images = {"wood.png"}, tile_images = {"wood.png"},
inventory_image = inventorycube("wood.png"), inventory_image = minetest.inventorycube("wood.png"),
is_ground_content = true, is_ground_content = true,
furnace_burntime = 7, furnace_burntime = 7,
material = digprop_woodlike(0.75), material = digprop_woodlike(0.75),
@ -1058,7 +1047,7 @@ minetest.register_node(":wood", {
minetest.register_node(":mese", { minetest.register_node(":mese", {
tile_images = {"mese.png"}, tile_images = {"mese.png"},
inventory_image = inventorycube("mese.png"), inventory_image = minetest.inventorycube("mese.png"),
is_ground_content = true, is_ground_content = true,
furnace_burntime = 30, furnace_burntime = 30,
material = digprop_stonelike(0.5), material = digprop_stonelike(0.5),
@ -1066,7 +1055,7 @@ minetest.register_node(":mese", {
minetest.register_node(":cloud", { minetest.register_node(":cloud", {
tile_images = {"cloud.png"}, tile_images = {"cloud.png"},
inventory_image = inventorycube("cloud.png"), inventory_image = minetest.inventorycube("cloud.png"),
is_ground_content = true, is_ground_content = true,
}) })
@ -1074,7 +1063,7 @@ minetest.register_node(":water_flowing", {
drawtype = "flowingliquid", drawtype = "flowingliquid",
tile_images = {"water.png"}, tile_images = {"water.png"},
alpha = WATER_ALPHA, alpha = WATER_ALPHA,
inventory_image = inventorycube("water.png"), inventory_image = minetest.inventorycube("water.png"),
paramtype = "light", paramtype = "light",
light_propagates = true, light_propagates = true,
walkable = false, walkable = false,
@ -1096,7 +1085,7 @@ minetest.register_node(":water_source", {
drawtype = "liquid", drawtype = "liquid",
tile_images = {"water.png"}, tile_images = {"water.png"},
alpha = WATER_ALPHA, alpha = WATER_ALPHA,
inventory_image = inventorycube("water.png"), inventory_image = minetest.inventorycube("water.png"),
paramtype = "light", paramtype = "light",
light_propagates = true, light_propagates = true,
walkable = false, walkable = false,
@ -1117,7 +1106,7 @@ minetest.register_node(":water_source", {
minetest.register_node(":lava_flowing", { minetest.register_node(":lava_flowing", {
drawtype = "flowingliquid", drawtype = "flowingliquid",
tile_images = {"lava.png"}, tile_images = {"lava.png"},
inventory_image = inventorycube("lava.png"), inventory_image = minetest.inventorycube("lava.png"),
paramtype = "light", paramtype = "light",
light_propagates = false, light_propagates = false,
light_source = LIGHT_MAX - 1, light_source = LIGHT_MAX - 1,
@ -1140,7 +1129,7 @@ minetest.register_node(":lava_flowing", {
minetest.register_node(":lava_source", { minetest.register_node(":lava_source", {
drawtype = "liquid", drawtype = "liquid",
tile_images = {"lava.png"}, tile_images = {"lava.png"},
inventory_image = inventorycube("lava.png"), inventory_image = minetest.inventorycube("lava.png"),
paramtype = "light", paramtype = "light",
light_propagates = false, light_propagates = false,
light_source = LIGHT_MAX - 1, light_source = LIGHT_MAX - 1,
@ -1204,8 +1193,7 @@ minetest.register_node(":sign_wall", {
minetest.register_node(":chest", { minetest.register_node(":chest", {
tile_images = {"chest_top.png", "chest_top.png", "chest_side.png", tile_images = {"chest_top.png", "chest_top.png", "chest_side.png",
"chest_side.png", "chest_side.png", "chest_front.png"}, "chest_side.png", "chest_side.png", "chest_front.png"},
inventory_image = "chest_top.png", inventory_image = minetest.inventorycube("chest_top.png", "chest_front.png", "chest_side.png"),
--inventory_image = inventorycube("chest_top.png", "chest_side.png", "chest_front.png"),
paramtype = "facedir_simple", paramtype = "facedir_simple",
metadata_name = "chest", metadata_name = "chest",
material = digprop_woodlike(1.0), material = digprop_woodlike(1.0),
@ -1215,7 +1203,7 @@ minetest.register_node(":chest", {
minetest.register_node(":locked_chest", { minetest.register_node(":locked_chest", {
tile_images = {"chest_top.png", "chest_top.png", "chest_side.png", tile_images = {"chest_top.png", "chest_top.png", "chest_side.png",
"chest_side.png", "chest_side.png", "chest_lock.png"}, "chest_side.png", "chest_side.png", "chest_lock.png"},
inventory_image = "chest_lock.png", inventory_image = minetest.inventorycube("chest_top.png", "chest_lock.png", "chest_side.png"),
paramtype = "facedir_simple", paramtype = "facedir_simple",
metadata_name = "locked_chest", metadata_name = "locked_chest",
material = digprop_woodlike(1.0), material = digprop_woodlike(1.0),
@ -1225,7 +1213,7 @@ minetest.register_node(":locked_chest", {
minetest.register_node(":furnace", { minetest.register_node(":furnace", {
tile_images = {"furnace_side.png", "furnace_side.png", "furnace_side.png", tile_images = {"furnace_side.png", "furnace_side.png", "furnace_side.png",
"furnace_side.png", "furnace_side.png", "furnace_front.png"}, "furnace_side.png", "furnace_side.png", "furnace_front.png"},
inventory_image = "furnace_front.png", inventory_image = minetest.inventorycube("furnace_side.png", "furnace_front.png", "furnace_side.png"),
paramtype = "facedir_simple", paramtype = "facedir_simple",
metadata_name = "furnace", metadata_name = "furnace",
material = digprop_stonelike(3.0), material = digprop_stonelike(3.0),
@ -1233,7 +1221,7 @@ minetest.register_node(":furnace", {
minetest.register_node(":cobble", { minetest.register_node(":cobble", {
tile_images = {"cobble.png"}, tile_images = {"cobble.png"},
inventory_image = inventorycube("cobble.png"), inventory_image = minetest.inventorycube("cobble.png"),
is_ground_content = true, is_ground_content = true,
cookresult_item = 'node "stone" 1', cookresult_item = 'node "stone" 1',
material = digprop_stonelike(0.9), material = digprop_stonelike(0.9),
@ -1241,14 +1229,14 @@ minetest.register_node(":cobble", {
minetest.register_node(":mossycobble", { minetest.register_node(":mossycobble", {
tile_images = {"mossycobble.png"}, tile_images = {"mossycobble.png"},
inventory_image = inventorycube("mossycobble.png"), inventory_image = minetest.inventorycube("mossycobble.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_stonelike(0.8), material = digprop_stonelike(0.8),
}) })
minetest.register_node(":steelblock", { minetest.register_node(":steelblock", {
tile_images = {"steel_block.png"}, tile_images = {"steel_block.png"},
inventory_image = inventorycube("steel_block.png"), inventory_image = minetest.inventorycube("steel_block.png"),
is_ground_content = true, is_ground_content = true,
material = digprop_stonelike(5.0), material = digprop_stonelike(5.0),
}) })

View File

@ -8,7 +8,7 @@ minetest.register_node("experimental:luafurnace", {
tile_images = {"lava.png", "furnace_side.png", "furnace_side.png", tile_images = {"lava.png", "furnace_side.png", "furnace_side.png",
"furnace_side.png", "furnace_side.png", "furnace_front.png"}, "furnace_side.png", "furnace_side.png", "furnace_front.png"},
--inventory_image = "furnace_front.png", --inventory_image = "furnace_front.png",
inventory_image = inventorycube("furnace_front.png"), inventory_image = minetest.inventorycube("furnace_front.png"),
paramtype = "facedir_simple", paramtype = "facedir_simple",
metadata_name = "generic", metadata_name = "generic",
material = digprop_stonelike(3.0), material = digprop_stonelike(3.0),
@ -134,7 +134,8 @@ minetest.register_craft({
minetest.register_node("experimental:somenode", { minetest.register_node("experimental:somenode", {
tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"}, tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
inventory_image = "treeprop.png", inventory_image = minetest.inventorycube("lava.png", "mese.png", "stone.png"),
--inventory_image = "treeprop.png",
material = { material = {
diggability = "normal", diggability = "normal",
weight = 0, weight = 0,

View File

@ -161,6 +161,7 @@ set(minetest_SRCS
MyBillboardSceneNode.cpp MyBillboardSceneNode.cpp
content_mapblock.cpp content_mapblock.cpp
content_cao.cpp content_cao.cpp
mesh.cpp
mapblock_mesh.cpp mapblock_mesh.cpp
farmesh.cpp farmesh.cpp
keycode.cpp keycode.cpp

View File

@ -22,21 +22,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client.h" #include "client.h"
#include "main.h" // for g_settings #include "main.h" // for g_settings
#include "map.h" #include "map.h"
#include "mesh.h"
#include "player.h" #include "player.h"
#include "tile.h" #include "tile.h"
#include <cmath> #include <cmath>
#include <SAnimatedMesh.h>
#include "settings.h" #include "settings.h"
#include "nodedef.h" // For wield visualization #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): Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
m_smgr(smgr), m_smgr(smgr),
m_playernode(NULL), m_playernode(NULL),
@ -480,7 +472,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
case NDT_ALLFACES: case NDT_ALLFACES:
case NDT_ALLFACES_OPTIONAL: case NDT_ALLFACES_OPTIONAL:
m_wieldnode->setCube(ndef->get(content).tiles); m_wieldnode->setCube(ndef->get(content).tiles);
m_wieldnode->setScale(v3f(30));
isCube = true; isCube = true;
break; break;
default: default:
@ -492,7 +483,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
if (!isCube) if (!isCube)
{ {
m_wieldnode->setSprite(item->getImageRaw()); m_wieldnode->setSprite(item->getImageRaw());
m_wieldnode->setScale(v3f(40));
} }
m_wieldnode->setVisible(true); m_wieldnode->setVisible(true);
@ -501,7 +491,6 @@ void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
{ {
// Bare hands // Bare hands
m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png")); m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png"));
m_wieldnode->setScale(v3f(40));
m_wieldnode->setVisible(true); m_wieldnode->setVisible(true);
} }
} }
@ -536,7 +525,6 @@ ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
ISceneNode(parent, mgr, id, position, rotation, scale) 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_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_cubemesh = NULL;
m_is_cube = false; m_is_cube = false;
m_light = LIGHT_MAX; m_light = LIGHT_MAX;
@ -551,6 +539,8 @@ ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture) void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
{ {
const v3f sprite_scale(40.0, 40.0, 4.0); // width, height, thickness
if (texture == NULL) if (texture == NULL)
{ {
m_meshnode->setVisible(false); m_meshnode->setVisible(false);
@ -568,7 +558,9 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
else else
{ {
// Texture was not yet extruded, do it now and save in cache // 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) if (mesh == NULL)
{ {
dstream << "Warning: failed to extrude sprite" << std::endl; dstream << "Warning: failed to extrude sprite" << std::endl;
@ -580,7 +572,6 @@ void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
mesh->drop(); mesh->drop();
} }
m_meshnode->setScale(v3f(1, 1, m_thickness));
m_meshnode->getMaterial(0).setTexture(0, texture); m_meshnode->getMaterial(0).setTexture(0, texture);
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false); m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, 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]) void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
{ {
const v3f cube_scale(30.0, 30.0, 30.0);
if (m_cubemesh == NULL) if (m_cubemesh == NULL)
m_cubemesh = createCubeMesh(); {
m_cubemesh = createCubeMesh(cube_scale);
}
m_meshnode->setMesh(m_cubemesh); m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
{ {
// Get the tile texture and atlas transformation // Get the tile texture and atlas transformation
@ -626,7 +620,7 @@ void ExtrudedSpriteSceneNode::updateLight(u8 light)
// Set brightness one lower than incoming light // Set brightness one lower than incoming light
diminish_light(li); diminish_light(li);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_meshnode->getMesh(), color); setMeshColor(m_meshnode->getMesh(), color);
} }
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture) void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
@ -637,13 +631,6 @@ void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
cache->removeMesh(mesh); 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 const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
{ {
return m_meshnode->getBoundingBox(); return m_meshnode->getBoundingBox();
@ -667,259 +654,3 @@ io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
path.append("/[extruded]"); path.append("/[extruded]");
return path; 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;
}

View File

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include "inventory.h" #include "inventory.h"
#include "mesh.h"
#include "tile.h" #include "tile.h"
#include "utility.h" #include "utility.h"
#include <ICameraSceneNode.h> #include <ICameraSceneNode.h>
@ -206,9 +207,6 @@ public:
void setSprite(video::ITexture* texture); void setSprite(video::ITexture* texture);
void setCube(const TileSpec tiles[6]); void setCube(const TileSpec tiles[6]);
f32 getSpriteThickness() const { return m_thickness; }
void setSpriteThickness(f32 thickness);
void updateLight(u8 light); void updateLight(u8 light);
void removeSpriteFromCache(video::ITexture* texture); void removeSpriteFromCache(video::ITexture* texture);
@ -219,16 +217,11 @@ public:
private: private:
scene::IMeshSceneNode* m_meshnode; scene::IMeshSceneNode* m_meshnode;
f32 m_thickness;
scene::IMesh* m_cubemesh; scene::IMesh* m_cubemesh;
bool m_is_cube; bool m_is_cube;
u8 m_light; u8 m_light;
// internal extrusion helper methods
io::path getExtrudedName(video::ITexture* texture); 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 #endif

View File

@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gamedef.h" #include "gamedef.h"
#include "clientobject.h" #include "clientobject.h"
#include "content_object.h" #include "content_object.h"
#include "mesh.h"
#include "utility.h" // For IntervalLimiter #include "utility.h" // For IntervalLimiter
class Settings; class Settings;
#include "MyBillboardSceneNode.h" #include "MyBillboardSceneNode.h"
@ -630,7 +631,7 @@ void ItemCAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color); setMeshColor(m_node->getMesh(), color);
} }
v3s16 ItemCAO::getLightPosition() v3s16 ItemCAO::getLightPosition()
@ -778,7 +779,7 @@ void RatCAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color); setMeshColor(m_node->getMesh(), color);
} }
v3s16 RatCAO::getLightPosition() v3s16 RatCAO::getLightPosition()
@ -934,7 +935,7 @@ void Oerkki1CAO::updateLight(u8 light_at_pos)
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color); setMeshColor(m_node->getMesh(), color);
} }
v3s16 Oerkki1CAO::getLightPosition() v3s16 Oerkki1CAO::getLightPosition()
@ -1165,7 +1166,7 @@ void FireflyCAO::updateLight(u8 light_at_pos)
u8 li = 255; u8 li = 255;
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color); setMeshColor(m_node->getMesh(), color);
} }
v3s16 FireflyCAO::getLightPosition() v3s16 FireflyCAO::getLightPosition()
@ -1866,7 +1867,7 @@ public:
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
if(m_meshnode){ if(m_meshnode){
setMeshVerticesColor(m_meshnode->getMesh(), color); setMeshColor(m_meshnode->getMesh(), color);
m_meshnode->setVisible(true); m_meshnode->setVisible(true);
} }
if(m_spritenode){ if(m_spritenode){
@ -2250,7 +2251,7 @@ public:
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color); setMeshColor(m_node->getMesh(), color);
} }
v3s16 getLightPosition() v3s16 getLightPosition()

362
src/mesh.cpp Normal file
View File

@ -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;
}
}
}

66
src/mesh.h Normal file
View File

@ -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

View File

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h" #include "filesys.h"
#include "utility.h" #include "utility.h"
#include "settings.h" #include "settings.h"
#include "mesh.h"
#include <ICameraSceneNode.h> #include <ICameraSceneNode.h>
#include "log.h" #include "log.h"
#include "mapnode.h" // For texture atlas making #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); assert(img_top && img_left && img_right);
// Create textures from images // Create textures from images
// TODO: Use them all
video::ITexture *texture_top = driver->addTexture( video::ITexture *texture_top = driver->addTexture(
(imagename_top + "__temp__").c_str(), img_top); (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 // Drop images
img_top->drop(); img_top->drop();
img_left->drop(); img_left->drop();
@ -1499,17 +1503,24 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
Create scene: Create scene:
- An unit cube is centered at 0,0,0 - An unit cube is centered at 0,0,0
- Camera looks at cube from Y+, Z- towards Y-, Z+ - 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, scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1));
v3f(0,0,0), v3f(0, 45, 0)); 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 // Set texture of cube
cube->setMaterialTexture(0, texture_top); cubenode->getMaterial(0).setTexture(0, texture_top);
//cube->setMaterialFlag(video::EMF_LIGHTING, false); cubenode->getMaterial(1).setTexture(0, texture_top);
cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false); cubenode->getMaterial(2).setTexture(0, texture_right);
cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); 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, scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
v3f(0, 1.0, -1.5), v3f(0, 0, 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); camera->setProjectionMatrix(pm, true);
/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0, /*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)); 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); driver->setRenderTarget(0, true, true, 0);
// Free textures of images // Free textures of images
// TODO: When all are used, free them all
driver->removeTexture(texture_top); driver->removeTexture(texture_top);
driver->removeTexture(texture_left);
driver->removeTexture(texture_right);
// Create image of render target // Create image of render target
video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim); video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);

View File

@ -172,27 +172,6 @@ int myrand_range(int min, int max)
return (myrand()%(max-min+1))+min; 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 blockpos: position of block in block coordinates
camera_pos: position of camera in nodes camera_pos: position of camera in nodes

View File

@ -694,11 +694,6 @@ private:
u32 *m_result; 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 // Calculates the borders of a "d-radius" cube
inline void getFacePositions(core::list<v3s16> &list, u16 d) inline void getFacePositions(core::list<v3s16> &list, u16 d)
{ {