framework for modifying textures

This commit is contained in:
Perttu Ahola 2010-12-20 22:03:49 +02:00
parent 6350c5d7a6
commit 123e8fdf53
19 changed files with 425 additions and 246 deletions

@ -2,9 +2,9 @@
# It's usually sufficient to change just the target name and source file list # It's usually sufficient to change just the target name and source file list
# and be sure that CXX is set to a valid compiler # and be sure that CXX is set to a valid compiler
TARGET = test TARGET = test
SOURCE_FILES = guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp SOURCE_FILES = irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp
SOURCES = $(addprefix src/, $(SOURCE_FILES)) SOURCES = $(addprefix src/, $(SOURCE_FILES))
BUILD_DIR = build/ BUILD_DIR = build
OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))
#OBJECTS = $(SOURCES:.cpp=.o) #OBJECTS = $(SOURCES:.cpp=.o)
@ -13,7 +13,7 @@ FAST_TARGET = fasttest
SERVER_TARGET = server SERVER_TARGET = server
SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp
SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES)) SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))
SERVER_BUILD_DIR = serverbuild/ SERVER_BUILD_DIR = serverbuild
SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o)) SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))
#SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o) #SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o)

@ -13,8 +13,8 @@
#fps_max = 60 #fps_max = 60
#viewing_range_nodes_max = 300 #viewing_range_nodes_max = 300
#viewing_range_nodes_min = 50 #viewing_range_nodes_min = 50
#screenW = #screenW = 800
#screenH = #screenH = 600
#host_game = #host_game =
#port = 30000 #port = 30000
#address = kray.dy.fi #address = kray.dy.fi

@ -62,8 +62,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// Viewing range stuff // Viewing range stuff
//#define FREETIME_RATIO 0.2 //#define FREETIME_RATIO 0.15
#define FREETIME_RATIO 0.15 #define FREETIME_RATIO 0.0
// Sectors are split to SECTOR_HEIGHTMAP_SPLIT^2 heightmaps // Sectors are split to SECTOR_HEIGHTMAP_SPLIT^2 heightmaps
#define SECTOR_HEIGHTMAP_SPLIT 2 #define SECTOR_HEIGHTMAP_SPLIT 2

@ -30,29 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <jmutexautolock.h> #include <jmutexautolock.h>
#include <iostream> #include <iostream>
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include "threads.h"
/*
Compatibility stuff
*/
#if (defined(WIN32) || defined(_WIN32_WCE))
typedef DWORD threadid_t;
#define __NORETURN __declspec(noreturn)
#define __FUNCTION_NAME __FUNCTION__
#else
typedef pthread_t threadid_t;
#define __NORETURN __attribute__ ((__noreturn__))
#define __FUNCTION_NAME __PRETTY_FUNCTION__
#endif
inline threadid_t get_current_thread_id()
{
#if (defined(WIN32) || defined(_WIN32_WCE))
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
/* /*
Debug output Debug output

@ -28,8 +28,8 @@ void set_default_settings()
g_settings.setDefault("fps_max", "60"); g_settings.setDefault("fps_max", "60");
g_settings.setDefault("viewing_range_nodes_max", "300"); g_settings.setDefault("viewing_range_nodes_max", "300");
g_settings.setDefault("viewing_range_nodes_min", "35"); g_settings.setDefault("viewing_range_nodes_min", "35");
g_settings.setDefault("screenW", ""); g_settings.setDefault("screenW", "800");
g_settings.setDefault("screenH", ""); g_settings.setDefault("screenH", "600");
g_settings.setDefault("host_game", ""); g_settings.setDefault("host_game", "");
g_settings.setDefault("port", ""); g_settings.setDefault("port", "");
g_settings.setDefault("address", ""); g_settings.setDefault("address", "");

@ -132,6 +132,14 @@ public:
{} {}
}; };
class ItemNotFoundException : public BaseException
{
public:
ItemNotFoundException(const char *s):
BaseException(s)
{}
};
/* /*
Some "old-style" interrupts: Some "old-style" interrupts:
*/ */

@ -80,10 +80,12 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
video::ITexture * MapBlockObjectItem::getImage() video::ITexture * MapBlockObjectItem::getImage()
{ {
if(m_inventorystring.substr(0,3) == "Rat") if(m_inventorystring.substr(0,3) == "Rat")
return g_device->getVideoDriver()->getTexture("../data/rat.png"); //return g_device->getVideoDriver()->getTexture("../data/rat.png");
return g_irrlicht->getTexture("../data/rat.png");
if(m_inventorystring.substr(0,4) == "Sign") if(m_inventorystring.substr(0,4) == "Sign")
return g_device->getVideoDriver()->getTexture("../data/sign.png"); //return g_device->getVideoDriver()->getTexture("../data/sign.png");
return g_irrlicht->getTexture("../data/sign.png");
return NULL; return NULL;
} }

@ -96,7 +96,7 @@ public:
if(m_content >= USEFUL_CONTENT_COUNT) if(m_content >= USEFUL_CONTENT_COUNT)
return NULL; return NULL;
return g_texturecache.get(g_content_inventory_textures[m_content]); return g_irrlicht->getTexture(g_content_inventory_textures[m_content]);
} }
#endif #endif
std::string getText() std::string getText()

@ -183,6 +183,9 @@ TODO: Node cracking animation when digging
- TODO: A way to generate new textures by combining textures - TODO: A way to generate new textures by combining textures
- TODO: Mesh update to fetch cracked faces from the former - TODO: Mesh update to fetch cracked faces from the former
TODO: A thread-safe wrapper for irrlicht for threads, to get rid of
g_device
====================================================================== ======================================================================
*/ */
@ -247,28 +250,7 @@ TODO: Node cracking animation when digging
#include "porting.h" #include "porting.h"
#include "guiPauseMenu.h" #include "guiPauseMenu.h"
IrrlichtDevice *g_device = NULL; IrrlichtWrapper *g_irrlicht;
/*const char *g_content_filenames[MATERIALS_COUNT] =
{
"../data/stone.png",
"../data/grass.png",
"../data/water.png",
"../data/torch_on_floor.png",
"../data/tree.png",
"../data/leaves.png",
"../data/grass_footsteps.png",
"../data/mese.png",
"../data/mud.png",
"../data/water.png", // CONTENT_OCEAN
};
// Material cache
video::SMaterial g_materials[MATERIALS_COUNT];*/
// Texture cache
TextureCache g_texturecache;
// All range-related stuff below is locked behind this // All range-related stuff below is locked behind this
JMutex g_range_mutex; JMutex g_range_mutex;
@ -852,9 +834,10 @@ void updateViewingRange(f32 frametime, Client *client)
static bool fraction_is_good = false; static bool fraction_is_good = false;
float fraction_good_threshold = 0.1; //float fraction_good_threshold = 0.1;
//float fraction_bad_threshold = 0.25; //float fraction_bad_threshold = 0.25;
float fraction_bad_threshold = 0.1; float fraction_good_threshold = 0.075;
float fraction_bad_threshold = 0.125;
float fraction_limit; float fraction_limit;
// Use high limit if fraction is good AND the fraction would // Use high limit if fraction is good AND the fraction would
// lower the range. We want to keep the range fairly high. // lower the range. We want to keep the range fairly high.
@ -1283,7 +1266,12 @@ int main(int argc, char *argv[])
/* /*
Resolution selection Resolution selection
*/ */
bool fullscreen = false;
u16 screenW = atoi(g_settings.get("screenW").c_str());
u16 screenH = atoi(g_settings.get("screenH").c_str());
#if 0
u16 screenW; u16 screenW;
u16 screenH; u16 screenH;
bool fullscreen = false; bool fullscreen = false;
@ -1345,6 +1333,7 @@ int main(int argc, char *argv[])
screenH = resolutions[r0-1][1]; screenH = resolutions[r0-1][1];
fullscreen = resolutions[r0-1][2]; fullscreen = resolutions[r0-1][2];
} }
#endif
// //
@ -1372,8 +1361,10 @@ int main(int argc, char *argv[])
if (device == 0) if (device == 0)
return 1; // could not create selected driver. return 1; // could not create selected driver.
g_irrlicht = new IrrlichtWrapper(device);
g_device = device; //g_device = device;
device->setResizable(true); device->setResizable(true);
@ -1432,10 +1423,11 @@ int main(int argc, char *argv[])
/* /*
Preload some random textures that are used in threads Preload some random textures that are used in threads
*/ */
#if 0
g_texturecache.set("torch", driver->getTexture("../data/torch.png")); g_texturecache.set("torch", driver->getTexture("../data/torch.png"));
g_texturecache.set("torch_on_floor", driver->getTexture("../data/torch_on_floor.png")); g_texturecache.set("torch_on_floor", driver->getTexture("../data/torch_on_floor.png"));
g_texturecache.set("torch_on_ceiling", driver->getTexture("../data/torch_on_ceiling.png")); g_texturecache.set("torch_on_ceiling", driver->getTexture("../data/torch_on_ceiling.png"));
g_texturecache.set("crack", driver->getTexture("../data/crack.png"));
/* /*
Load tile textures Load tile textures
@ -1452,7 +1444,11 @@ int main(int argc, char *argv[])
g_texturecache.set(name, driver->getTexture(filename.c_str())); g_texturecache.set(name, driver->getTexture(filename.c_str()));
} }
tile_materials_preload(g_texturecache); #endif
//tile_materials_preload(g_texturecache);
tile_materials_preload(g_irrlicht);
//tile_materials_init();
/* /*
Make a scope here for the client so that it gets removed Make a scope here for the client so that it gets removed
@ -1641,6 +1637,11 @@ int main(int argc, char *argv[])
while(device->run()) while(device->run())
{ {
/*
Run global IrrlichtWrapper's main thread processing stuff
*/
g_irrlicht->Run();
/* /*
Random calculations Random calculations
*/ */
@ -1653,7 +1654,7 @@ int main(int argc, char *argv[])
// Info text // Info text
std::wstring infotext; std::wstring infotext;
//TimeTaker //timer1("//timer1", device); //TimeTaker //timer1("//timer1", g_irrlicht);
// Time of frame without fps limit // Time of frame without fps limit
float busytime; float busytime;
@ -1843,20 +1844,20 @@ int main(int argc, char *argv[])
*/ */
{ {
//TimeTaker timer("client.step(dtime)", device); //TimeTaker timer("client.step(dtime)", g_irrlicht);
client.step(dtime); client.step(dtime);
//client.step(dtime_avg1); //client.step(dtime_avg1);
} }
if(server != NULL) if(server != NULL)
{ {
//TimeTaker timer("server->step(dtime)", device); //TimeTaker timer("server->step(dtime)", g_irrlicht);
server->step(dtime); server->step(dtime);
} }
v3f player_position = client.getPlayerPosition(); v3f player_position = client.getPlayerPosition();
//TimeTaker //timer2("//timer2", device); //TimeTaker //timer2("//timer2", g_irrlicht);
/* /*
Mouse and camera control Mouse and camera control
@ -1910,12 +1911,12 @@ int main(int argc, char *argv[])
} }
else{ else{
//client.m_env.getMap().updateCamera(camera_position, camera_direction); //client.m_env.getMap().updateCamera(camera_position, camera_direction);
//TimeTaker timer("client.updateCamera", device); //TimeTaker timer("client.updateCamera", g_irrlicht);
client.updateCamera(camera_position, camera_direction); client.updateCamera(camera_position, camera_direction);
} }
//timer2.stop(); //timer2.stop();
//TimeTaker //timer3("//timer3", device); //TimeTaker //timer3("//timer3", g_irrlicht);
/* /*
Calculate what block is the crosshair pointing to Calculate what block is the crosshair pointing to
@ -2266,7 +2267,7 @@ int main(int argc, char *argv[])
Update gui stuff (0ms) Update gui stuff (0ms)
*/ */
//TimeTaker guiupdatetimer("Gui updating", device); //TimeTaker guiupdatetimer("Gui updating", g_irrlicht);
{ {
wchar_t temptext[150]; wchar_t temptext[150];
@ -2376,14 +2377,14 @@ int main(int argc, char *argv[])
Drawing begins Drawing begins
*/ */
TimeTaker drawtimer("Drawing", device); TimeTaker drawtimer("Drawing", g_irrlicht);
{ {
TimeTaker timer("beginScene", device); TimeTaker timer("beginScene", g_irrlicht);
driver->beginScene(true, true, bgcolor); driver->beginScene(true, true, bgcolor);
//driver->beginScene(false, true, bgcolor); //driver->beginScene(false, true, bgcolor);
beginscenetime = timer.stop(true); beginscenetime = timer.stop(true);
} }
//timer3.stop(); //timer3.stop();
@ -2391,13 +2392,13 @@ int main(int argc, char *argv[])
//std::cout<<DTIME<<"smgr->drawAll()"<<std::endl; //std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;
{ {
TimeTaker timer("smgr", device); TimeTaker timer("smgr", g_irrlicht);
smgr->drawAll(); smgr->drawAll();
scenetime = timer.stop(true); scenetime = timer.stop(true);
} }
{ {
//TimeTaker timer9("auxiliary drawings", device); //TimeTaker timer9("auxiliary drawings", g_irrlicht);
// 0ms // 0ms
driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0), driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),
@ -2408,7 +2409,7 @@ int main(int argc, char *argv[])
video::SColor(255,255,255,255)); video::SColor(255,255,255,255));
//timer9.stop(); //timer9.stop();
//TimeTaker //timer10("//timer10", device); //TimeTaker //timer10("//timer10", g_irrlicht);
video::SMaterial m; video::SMaterial m;
m.Thickness = 10; m.Thickness = 10;
@ -2431,7 +2432,7 @@ int main(int argc, char *argv[])
} }
//timer10.stop(); //timer10.stop();
//TimeTaker //timer11("//timer11", device); //TimeTaker //timer11("//timer11", g_irrlicht);
/* /*
Draw gui Draw gui
@ -2441,9 +2442,9 @@ int main(int argc, char *argv[])
// End drawing // End drawing
{ {
TimeTaker timer("endScene", device); TimeTaker timer("endScene", g_irrlicht);
driver->endScene(); driver->endScene();
endscenetime = timer.stop(true); endscenetime = timer.stop(true);
} }
drawtime = drawtimer.stop(true); drawtime = drawtimer.stop(true);

@ -46,12 +46,14 @@ extern std::ostream *derr_server_ptr;
#define dout_server (*dout_server_ptr) #define dout_server (*dout_server_ptr)
#define derr_server (*derr_server_ptr) #define derr_server (*derr_server_ptr)
#ifndef SERVER /*#ifndef SERVER
#include "utility.h" #include "utility.h"
extern TextureCache g_texturecache; extern TextureCache g_texturecache;
#endif #endif*/
extern IrrlichtDevice *g_device; #include "irrlichtwrapper.h"
//extern IrrlichtDevice *g_device;
extern IrrlichtWrapper *g_irrlicht;
#endif #endif

@ -740,7 +740,7 @@ void Map::updateLighting(enum LightBank bank,
} }
{ {
//TimeTaker timer("unspreadLight", g_device); //TimeTaker timer("unspreadLight", g_irrlicht);
unspreadLight(bank, unlight_from, light_sources, modified_blocks); unspreadLight(bank, unlight_from, light_sources, modified_blocks);
} }
@ -759,7 +759,7 @@ void Map::updateLighting(enum LightBank bank,
// - Find out why it works // - Find out why it works
{ {
//TimeTaker timer("spreadLight", g_device); //TimeTaker timer("spreadLight", g_irrlicht);
spreadLight(bank, light_sources, modified_blocks); spreadLight(bank, light_sources, modified_blocks);
} }
@ -1065,7 +1065,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
#ifndef SERVER #ifndef SERVER
void Map::expireMeshes(bool only_daynight_diffed) void Map::expireMeshes(bool only_daynight_diffed)
{ {
TimeTaker timer("expireMeshes()", g_device); TimeTaker timer("expireMeshes()", g_irrlicht);
core::map<v2s16, MapSector*>::Iterator si; core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator(); si = m_sectors.getIterator();
@ -3017,7 +3017,7 @@ MapVoxelManipulator::~MapVoxelManipulator()
#if 1 #if 1
void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id) void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
{ {
TimeTaker timer1("emerge", g_device, &emerge_time); TimeTaker timer1("emerge", g_irrlicht, &emerge_time);
// Units of these are MapBlocks // Units of these are MapBlocks
v3s16 p_min = getNodeBlockPos(a.MinEdge); v3s16 p_min = getNodeBlockPos(a.MinEdge);
@ -3041,7 +3041,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
bool block_data_inexistent = false; bool block_data_inexistent = false;
try try
{ {
TimeTaker timer1("emerge load", g_device, &emerge_load_time); TimeTaker timer1("emerge load", g_irrlicht, &emerge_load_time);
/*dstream<<"Loading block (caller_id="<<caller_id<<")" /*dstream<<"Loading block (caller_id="<<caller_id<<")"
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")" <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
@ -3082,7 +3082,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
#if 0 #if 0
void MapVoxelManipulator::emerge(VoxelArea a) void MapVoxelManipulator::emerge(VoxelArea a)
{ {
TimeTaker timer1("emerge", g_device, &emerge_time); TimeTaker timer1("emerge", g_irrlicht, &emerge_time);
v3s16 size = a.getExtent(); v3s16 size = a.getExtent();
@ -3101,7 +3101,7 @@ void MapVoxelManipulator::emerge(VoxelArea a)
continue; continue;
try try
{ {
TimeTaker timer1("emerge load", g_device, &emerge_load_time); TimeTaker timer1("emerge load", g_irrlicht, &emerge_load_time);
MapNode n = m_map->getNode(a.MinEdge + p); MapNode n = m_map->getNode(a.MinEdge + p);
m_data[i] = n; m_data[i] = n;
m_flags[i] = 0; m_flags[i] = 0;
@ -3126,7 +3126,7 @@ void MapVoxelManipulator::blitBack
if(m_area.getExtent() == v3s16(0,0,0)) if(m_area.getExtent() == v3s16(0,0,0))
return; return;
//TimeTaker timer1("blitBack", g_device); //TimeTaker timer1("blitBack", g_irrlicht);
/* /*
Initialize block cache Initialize block cache

@ -646,7 +646,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
if(f.tile.feature == TILEFEAT_NONE) if(f.tile.feature == TILEFEAT_NONE)
{ {
collector.append(g_tile_materials[f.tile.id], f.vertices, 4, /*collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
indices, 6);*/
collector.append(tile_material_get(f.tile.id), f.vertices, 4,
indices, 6); indices, 6);
} }
else else
@ -748,16 +750,21 @@ void MapBlock::updateMesh(u32 daynight_ratio)
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
if(dir == v3s16(0,-1,0)) if(dir == v3s16(0,-1,0))
buf->getMaterial().setTexture(0, buf->getMaterial().setTexture(0,
g_texturecache.get("torch_on_floor")); g_irrlicht->getTexture("../data/torch_on_floor.png"));
//g_texturecache.get("torch_on_floor"));
else if(dir == v3s16(0,1,0)) else if(dir == v3s16(0,1,0))
buf->getMaterial().setTexture(0, buf->getMaterial().setTexture(0,
g_texturecache.get("torch_on_ceiling")); g_irrlicht->getTexture("../data/torch_on_ceiling.png"));
//g_texturecache.get("torch_on_ceiling"));
// For backwards compatibility // For backwards compatibility
else if(dir == v3s16(0,0,0)) else if(dir == v3s16(0,0,0))
buf->getMaterial().setTexture(0, buf->getMaterial().setTexture(0,
g_texturecache.get("torch_on_floor")); g_irrlicht->getTexture("../data/torch_on_floor.png"));
//g_texturecache.get("torch_on_floor"));
else else
buf->getMaterial().setTexture(0, g_texturecache.get("torch")); buf->getMaterial().setTexture(0,
g_irrlicht->getTexture("../data/torch.png"));
//buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
// Add to mesh // Add to mesh
mesh_new->addMeshBuffer(buf); mesh_new->addMeshBuffer(buf);

@ -46,16 +46,16 @@ u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] =
const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] = const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
{ {
"stone", "../data/stone.png",
"grass", "../data/grass.png",
"water", "../data/water.png",
"torch_on_floor", "../data/torch_on_floor.png",
"tree_top", "../data/tree_top.png",
"leaves", "../data/leaves.png",
"grass_footsteps", "../data/grass_footsteps.png",
"mese", "../data/mese.png",
"mud", "../data/mud.png",
"water", "../data/water.png",
"cloud", "../data/cloud.png",
}; };

@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
/* /*
(c) 2010 Perttu Ahola <celeron55@gmail.com> Random portability stuff
*/ */
#ifndef PORTING_HEADER #ifndef PORTING_HEADER

@ -18,36 +18,40 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "tile.h" #include "tile.h"
#include "irrlichtwrapper.h"
const char * g_tile_texture_names[TILES_COUNT] = // A mapping from tiles to paths of textures
const char * g_tile_texture_paths[TILES_COUNT] =
{ {
NULL, NULL,
"stone", "../data/stone.png",
"water", "../data/water.png",
"grass", "../data/grass.png",
"tree", "../data/tree.png",
"leaves", "../data/leaves.png",
"grass_footsteps", "../data/grass_footsteps.png",
"mese", "../data/mese.png",
"mud", "../data/mud.png",
"tree_top", "../data/tree_top.png",
"mud_with_grass", "../data/mud_with_grass.png",
"cloud", "../data/cloud.png",
}; };
// A mapping from tiles to materials
// Initialized at run-time.
video::SMaterial g_tile_materials[TILES_COUNT]; video::SMaterial g_tile_materials[TILES_COUNT];
void tile_materials_preload(TextureCache &cache) void tile_materials_preload(IrrlichtWrapper *irrlicht)
{ {
for(s32 i=0; i<TILES_COUNT; i++) for(s32 i=0; i<TILES_COUNT; i++)
{ {
const char *name = g_tile_texture_names[i]; const char *path = g_tile_texture_paths[i];
video::ITexture *t = NULL; video::ITexture *t = NULL;
if(name != NULL) if(path != NULL)
{ {
t = cache.get(name); t = irrlicht->getTexture(path);
assert(t != NULL); assert(t != NULL);
} }
@ -68,3 +72,10 @@ void tile_materials_preload(TextureCache &cache)
//g_tile_materials[TILE_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; //g_tile_materials[TILE_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
} }
video::SMaterial & tile_material_get(u32 i)
{
assert(i < TILES_COUNT);
return g_tile_materials[i];
}

@ -93,18 +93,16 @@ struct TileSpec
} param; } param;
}; };
// A mapping from tiles to names of cached textures /*extern const char * g_tile_texture_paths[TILES_COUNT];
extern const char * g_tile_texture_names[TILES_COUNT]; extern video::SMaterial g_tile_materials[TILES_COUNT];*/
// A mapping from tiles to materials
// Initialized at run-time.
extern video::SMaterial g_tile_materials[TILES_COUNT];
/* /*
Functions Functions
*/ */
// Initializes g_tile_materials // Initializes g_tile_materials
void tile_materials_preload(TextureCache &cache); void tile_materials_preload(IrrlichtWrapper *irrlicht);
video::SMaterial & tile_material_get(u32 i);
#endif #endif

@ -22,6 +22,49 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/ */
#include "utility.h" #include "utility.h"
#include "irrlichtwrapper.h"
TimeTaker::TimeTaker(const char *name, IrrlichtWrapper *irrlicht, u32 *result)
{
m_name = name;
m_irrlicht = irrlicht;
m_result = result;
m_running = true;
if(irrlicht == NULL)
{
m_time1 = 0;
return;
}
m_time1 = m_irrlicht->getTime();
}
u32 TimeTaker::stop(bool quiet)
{
if(m_running)
{
if(m_irrlicht == NULL)
{
/*if(quiet == false)
std::cout<<"Couldn't measure time for "<<m_name
<<": irrlicht==NULL"<<std::endl;*/
return 0;
}
u32 time2 = m_irrlicht->getTime();
u32 dtime = time2 - m_time1;
if(m_result != NULL)
{
(*m_result) += dtime;
}
else
{
if(quiet == false)
std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
}
m_running = false;
return dtime;
}
return 0;
}
const v3s16 g_26dirs[26] = const v3s16 g_26dirs[26] =
{ {

@ -17,10 +17,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
/*
(c) 2010 Perttu Ahola <celeron55@gmail.com>
*/
#ifndef UTILITY_HEADER #ifndef UTILITY_HEADER
#define UTILITY_HEADER #define UTILITY_HEADER
@ -403,56 +399,23 @@ private:
TimeTaker TimeTaker
*/ */
class IrrlichtWrapper;
class TimeTaker class TimeTaker
{ {
public: public:
TimeTaker(const char *name, IrrlichtDevice *dev, u32 *result=NULL) TimeTaker(const char *name, IrrlichtWrapper *irrlicht, u32 *result=NULL);
{
m_name = name;
m_dev = dev;
m_result = result;
m_running = true;
if(dev == NULL)
{
m_time1 = 0;
return;
}
m_time1 = m_dev->getTimer()->getRealTime();
}
~TimeTaker() ~TimeTaker()
{ {
stop(); stop();
} }
u32 stop(bool quiet=false)
{ u32 stop(bool quiet=false);
if(m_running)
{
if(m_dev == NULL)
{
/*if(quiet == false)
std::cout<<"Couldn't measure time for "<<m_name
<<": dev==NULL"<<std::endl;*/
return 0;
}
u32 time2 = m_dev->getTimer()->getRealTime();
u32 dtime = time2 - m_time1;
if(m_result != NULL)
{
(*m_result) += dtime;
}
else
{
if(quiet == false)
std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
}
m_running = false;
return dtime;
}
return 0;
}
private: private:
const char *m_name; const char *m_name;
IrrlichtDevice *m_dev; IrrlichtWrapper *m_irrlicht;
u32 m_time1; u32 m_time1;
bool m_running; bool m_running;
u32 *m_result; u32 *m_result;
@ -673,6 +636,48 @@ inline s32 stoi(std::string s)
return atoi(s.c_str()); return atoi(s.c_str());
} }
/*
A base class for simple background thread implementation
*/
class SimpleThread : public JThread
{
bool run;
JMutex run_mutex;
public:
SimpleThread():
JThread(),
run(true)
{
run_mutex.Init();
}
virtual ~SimpleThread()
{}
virtual void * Thread() = 0;
bool getRun()
{
JMutexAutoLock lock(run_mutex);
return run;
}
void setRun(bool a_run)
{
JMutexAutoLock lock(run_mutex);
run = a_run;
}
void stop()
{
setRun(false);
while(IsRunning())
sleep_ms(100);
}
};
/* /*
Config stuff Config stuff
*/ */
@ -1070,81 +1075,205 @@ private:
}; };
/* /*
A thread-safe texture cache. A thread-safe queue
This is used so that irrlicht doesn't get called from many threads
*/ */
class TextureCache template<typename T>
class MutexedQueue
{ {
public: public:
TextureCache() MutexedQueue()
{ {
m_mutex.Init(); m_mutex.Init();
assert(m_mutex.IsInitialized()); m_is_empty_mutex.Init();
} }
u32 size()
void set(std::string name, video::ITexture *texture) {
return m_list.size();
}
void push_back(T t)
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
m_list.push_back(t);
if(m_list.size() == 1)
m_is_empty_mutex.Unlock();
}
T pop_front(bool wait_if_empty=false)
{
for(;;)
{
{
JMutexAutoLock lock(m_mutex);
m_textures[name] = texture; if(m_list.size() > 0)
{
if(m_list.size() == 1)
m_is_empty_mutex.Lock();
typename core::list<T>::Iterator begin = m_list.begin();
T t = *begin;
m_list.erase(begin);
return t;
}
if(wait_if_empty == false)
throw ItemNotFoundException("MutexedQueue: item not found");
}
// To wait for an empty list, we're gonna hang on this mutex
m_is_empty_mutex.Lock();
m_is_empty_mutex.Unlock();
// Then loop to the beginning and hopefully return something
}
}
JMutex & getMutex()
{
return m_mutex;
}
JMutex & getIsEmptyMutex()
{
return m_is_empty_mutex;
} }
video::ITexture* get(std::string name) core::list<T> & getList()
{ {
JMutexAutoLock lock(m_mutex); return m_list;
}
core::map<std::string, video::ITexture*>::Node *n; protected:
n = m_textures.find(name); JMutex m_mutex;
// This is locked always when the list is empty
JMutex m_is_empty_mutex;
core::list<T> m_list;
};
if(n != NULL) template<typename Caller, typename Data>
return n->getValue(); class CallerInfo
{
public:
Caller caller;
Data data;
};
return NULL; template<typename Key, typename T, typename Caller, typename CallerData>
class GetResult
{
public:
Key key;
T item;
core::list<CallerInfo<Caller, CallerData> > callers;
};
template<typename Key, typename T, typename Caller, typename CallerData>
class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
{
};
template<typename Key, typename T, typename Caller, typename CallerData>
class GetRequest
{
public:
GetRequest()
{
dest = NULL;
}
GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
{
dest = a_dest;
}
GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
Key a_key)
{
dest = a_dest;
key = a_key;
}
~GetRequest()
{
}
Key key;
ResultQueue<Key, T, Caller, CallerData> *dest;
core::list<CallerInfo<Caller, CallerData> > callers;
};
/*
Quickhands for typical request-result queues.
Used for distributing work between threads.
*/
template<typename Key, typename T, typename Caller, typename CallerData>
class RequestQueue
{
public:
u32 size()
{
return m_queue.size();
}
void add(Key key, Caller caller, CallerData callerdata,
ResultQueue<Key, T, Caller, CallerData> *dest)
{
JMutexAutoLock lock(m_queue.getMutex());
/*
If the caller is already on the list, only update CallerData
*/
for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
i = m_queue.getList().begin();
i != m_queue.getList().end(); i++)
{
GetRequest<Key, T, Caller, CallerData> &request = *i;
if(request.key == key)
{
for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
i = request.callers.begin();
i != request.callers.end(); i++)
{
CallerInfo<Caller, CallerData> &ca = *i;
if(ca.caller == caller)
{
ca.data = callerdata;
return;
}
}
CallerInfo<Caller, CallerData> ca;
ca.caller = caller;
ca.data = callerdata;
request.callers.push_back(ca);
return;
}
}
/*
Else add a new request to the queue
*/
GetRequest<Key, T, Caller, CallerData> request;
request.key = key;
CallerInfo<Caller, CallerData> ca;
ca.caller = caller;
ca.data = callerdata;
request.callers.push_back(ca);
request.dest = dest;
m_queue.getList().push_back(request);
if(m_queue.getList().size() == 1)
m_queue.getIsEmptyMutex().Unlock();
}
GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
{
return m_queue.pop_front(wait_if_empty);
} }
private: private:
core::map<std::string, video::ITexture*> m_textures; MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
JMutex m_mutex;
};
class SimpleThread : public JThread
{
bool run;
JMutex run_mutex;
public:
SimpleThread():
JThread(),
run(true)
{
run_mutex.Init();
}
virtual ~SimpleThread()
{}
virtual void * Thread() = 0;
bool getRun()
{
JMutexAutoLock lock(run_mutex);
return run;
}
void setRun(bool a_run)
{
JMutexAutoLock lock(run_mutex);
run = a_run;
}
void stop()
{
setRun(false);
while(IsRunning())
sleep_ms(100);
}
}; };
#endif #endif

@ -138,7 +138,7 @@ void VoxelManipulator::addArea(VoxelArea area)
if(m_area.contains(area)) if(m_area.contains(area))
return; return;
TimeTaker timer("addArea", g_device, &addarea_time); TimeTaker timer("addArea", g_irrlicht, &addarea_time);
// Calculate new area // Calculate new area
VoxelArea new_area; VoxelArea new_area;
@ -290,7 +290,7 @@ void VoxelManipulator::interpolate(VoxelArea area)
void VoxelManipulator::clearFlag(u8 flags) void VoxelManipulator::clearFlag(u8 flags)
{ {
// 0-1ms on moderate area // 0-1ms on moderate area
TimeTaker timer("clearFlag", g_device, &clearflag_time); TimeTaker timer("clearFlag", g_irrlicht, &clearflag_time);
v3s16 s = m_area.getExtent(); v3s16 s = m_area.getExtent();
@ -539,7 +539,7 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a,
core::map<v3s16, u8> &active_nodes, core::map<v3s16, u8> &active_nodes,
bool checked3_is_clear) bool checked3_is_clear)
{ {
TimeTaker timer("updateAreaWaterPressure", g_device, TimeTaker timer("updateAreaWaterPressure", g_irrlicht,
&updateareawaterpressure_time); &updateareawaterpressure_time);
emerge(a, 3); emerge(a, 3);
@ -585,7 +585,7 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a,
try try
{ {
// 0-1ms @ recur_count <= 100 // 0-1ms @ recur_count <= 100
//TimeTaker timer("getWaterPressure", g_device); //TimeTaker timer("getWaterPressure", g_irrlicht);
pr = getWaterPressure(p, highest_y, recur_count); pr = getWaterPressure(p, highest_y, recur_count);
} }
catch(ProcessingLimitException &e) catch(ProcessingLimitException &e)
@ -613,7 +613,7 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a,
try try
{ {
// 0ms // 0ms
//TimeTaker timer("spreadWaterPressure", g_device); //TimeTaker timer("spreadWaterPressure", g_irrlicht);
spreadWaterPressure(p, pr, a, active_nodes, 0); spreadWaterPressure(p, pr, a, active_nodes, 0);
} }
catch(ProcessingLimitException &e) catch(ProcessingLimitException &e)
@ -653,7 +653,7 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
//dstream<<"s1="<<s1<<", s2="<<s2<<std::endl; //dstream<<"s1="<<s1<<", s2="<<s2<<std::endl;
{ {
TimeTaker timer1("flowWater pre", g_device, &flowwater_pre_time); TimeTaker timer1("flowWater pre", g_irrlicht, &flowwater_pre_time);
// Load neighboring nodes // Load neighboring nodes
emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)), 4); emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)), 4);
@ -802,9 +802,9 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos,
debugprint, stoptime); debugprint, stoptime);
} }
if(stoptime != 0 && g_device != NULL) if(stoptime != 0 && g_irrlicht != NULL)
{ {
u32 timenow = g_device->getTimer()->getRealTime(); u32 timenow = g_irrlicht->getTime();
if(timenow >= stoptime || if(timenow >= stoptime ||
(stoptime < 0x80000000 && timenow > 0x80000000)) (stoptime < 0x80000000 && timenow > 0x80000000))
{ {
@ -870,15 +870,15 @@ void VoxelManipulator::flowWater(
return; return;
} }
//TimeTaker timer1("flowWater (active_nodes)", g_device); //TimeTaker timer1("flowWater (active_nodes)", g_irrlicht);
//dstream<<"active_nodes.size() = "<<active_nodes.size()<<std::endl; //dstream<<"active_nodes.size() = "<<active_nodes.size()<<std::endl;
u32 stoptime = 0; u32 stoptime = 0;
if(g_device != NULL) if(g_irrlicht != NULL)
{ {
stoptime = g_device->getTimer()->getRealTime() + timelimit; stoptime = g_irrlicht->getTime() + timelimit;
} }
// Count of handled active nodes // Count of handled active nodes