work-in-progress texture atlas optimization
parent
949383a2f7
commit
1704badc30
BIN
data/water.png
BIN
data/water.png
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
@ -75,6 +75,7 @@ set(minetest_SRCS
|
||||||
guiPauseMenu.cpp
|
guiPauseMenu.cpp
|
||||||
irrlichtwrapper.cpp
|
irrlichtwrapper.cpp
|
||||||
client.cpp
|
client.cpp
|
||||||
|
tile.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -118,9 +118,9 @@ void Environment::step(float dtime)
|
||||||
/*
|
/*
|
||||||
Apply water resistance
|
Apply water resistance
|
||||||
*/
|
*/
|
||||||
if(player->in_water_stable)
|
if(player->in_water_stable || player->in_water)
|
||||||
{
|
{
|
||||||
f32 max_down = 1.5*BS;
|
f32 max_down = 2.0*BS;
|
||||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||||
|
|
||||||
f32 max = 2.5*BS;
|
f32 max = 2.5*BS;
|
||||||
|
|
|
@ -21,6 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define IIRRLICHTWRAPPER_HEADER
|
#define IIRRLICHTWRAPPER_HEADER
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: This is deprecated and should be removed completely
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IrrlichtWrapper prototype.
|
IrrlichtWrapper prototype.
|
||||||
|
@ -38,15 +43,18 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should be called only from the main thread
|
||||||
|
virtual IrrlichtDevice* getDevice(){ return NULL; }
|
||||||
|
|
||||||
virtual u32 getTime()
|
virtual u32 getTime()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual textureid_t getTextureId(const std::string &name){ return 0; }
|
/*virtual textureid_t getTextureId(const std::string &name){ return 0; }
|
||||||
virtual std::string getTextureName(textureid_t id){ return ""; }
|
virtual std::string getTextureName(textureid_t id){ return ""; }
|
||||||
virtual video::ITexture* getTexture(const std::string &name){ return NULL; }
|
virtual video::ITexture* getTexture(const std::string &name){ return NULL; }
|
||||||
virtual video::ITexture* getTexture(const TextureSpec &spec){ return NULL; }
|
virtual video::ITexture* getTexture(const TextureSpec &spec){ return NULL; }*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -96,13 +96,17 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * MapBlockObjectItem::getImage()
|
video::ITexture * MapBlockObjectItem::getImage()
|
||||||
{
|
{
|
||||||
|
//TODO
|
||||||
|
|
||||||
if(m_inventorystring.substr(0,3) == "Rat")
|
if(m_inventorystring.substr(0,3) == "Rat")
|
||||||
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("rat.png").c_str());
|
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("rat.png").c_str());
|
||||||
return g_irrlicht->getTexture("rat.png");
|
//return g_irrlicht->getTexture("rat.png");
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if(m_inventorystring.substr(0,4) == "Sign")
|
if(m_inventorystring.substr(0,4) == "Sign")
|
||||||
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("sign.png").c_str());
|
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("sign.png").c_str());
|
||||||
return g_irrlicht->getTexture("sign.png");
|
//return g_irrlicht->getTexture("sign.png");
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,12 +122,9 @@ public:
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * getImage()
|
video::ITexture * getImage()
|
||||||
{
|
{
|
||||||
/*if(m_content >= USEFUL_CONTENT_COUNT)
|
//TODO
|
||||||
return NULL;
|
//return g_irrlicht->getTexture(content_features(m_content).inventory_texture);
|
||||||
|
return NULL;
|
||||||
return g_irrlicht->getTexture(g_content_inventory_texture_paths[m_content]);*/
|
|
||||||
|
|
||||||
return g_irrlicht->getTexture(content_features(m_content).inventory_texture);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::string getText()
|
std::string getText()
|
||||||
|
@ -264,7 +261,9 @@ public:
|
||||||
name = "cloud.png";
|
name = "cloud.png";
|
||||||
|
|
||||||
// Get such a texture
|
// Get such a texture
|
||||||
return g_irrlicht->getTexture(name);
|
//return g_irrlicht->getTexture(name);
|
||||||
|
//TODO
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::string getText()
|
std::string getText()
|
||||||
|
@ -351,10 +350,12 @@ public:
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os<<"[progressbar"<<value_f;
|
os<<"[progressbar"<<value_f;
|
||||||
|
|
||||||
TextureSpec spec;
|
/*TextureSpec spec;
|
||||||
spec.addTid(g_irrlicht->getTextureId(basename));
|
spec.addTid(g_irrlicht->getTextureId(basename));
|
||||||
spec.addTid(g_irrlicht->getTextureId(os.str()));
|
spec.addTid(g_irrlicht->getTextureId(os.str()));
|
||||||
return g_irrlicht->getTexture(spec);
|
return g_irrlicht->getTexture(spec);*/
|
||||||
|
//TODO
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/*// Make texture name for the new texture with a progress bar
|
/*// Make texture name for the new texture with a progress bar
|
||||||
float value_f = (float)toolprogress / (float)maxprogress;
|
float value_f = (float)toolprogress / (float)maxprogress;
|
||||||
|
|
|
@ -11,8 +11,22 @@ IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
|
||||||
m_device = device;
|
m_device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IrrlichtWrapper::~IrrlichtWrapper()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// Clear image cache
|
||||||
|
for(core::map<std::string, video::IImage*>::Iterator
|
||||||
|
i = m_imagecache.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
i.getNode()->getValue()->drop();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void IrrlichtWrapper::Run()
|
void IrrlichtWrapper::Run()
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Fetch textures
|
Fetch textures
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +48,7 @@ void IrrlichtWrapper::Run()
|
||||||
|
|
||||||
request.dest->push_back(result);
|
request.dest->push_back(result);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrrlichtWrapper::Shutdown(bool shutdown)
|
void IrrlichtWrapper::Shutdown(bool shutdown)
|
||||||
|
@ -41,6 +56,18 @@ void IrrlichtWrapper::Shutdown(bool shutdown)
|
||||||
m_running = !shutdown;
|
m_running = !shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IrrlichtDevice* IrrlichtWrapper::getDevice()
|
||||||
|
{
|
||||||
|
if(get_current_thread_id() != m_main_thread)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: IrrlichtWrapper::getDevice() called "
|
||||||
|
"not from main thread"<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return m_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
textureid_t IrrlichtWrapper::getTextureId(const std::string &name)
|
textureid_t IrrlichtWrapper::getTextureId(const std::string &name)
|
||||||
{
|
{
|
||||||
u32 id = m_namecache.getId(name);
|
u32 id = m_namecache.getId(name);
|
||||||
|
@ -55,9 +82,9 @@ std::string IrrlichtWrapper::getTextureName(textureid_t id)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
video::ITexture* IrrlichtWrapper::getTexture(const std::string &name)
|
video::ITexture* IrrlichtWrapper::getTexture(const std::string &filename)
|
||||||
{
|
{
|
||||||
TextureSpec spec(getTextureId(name));
|
TextureSpec spec(getTextureId(filename));
|
||||||
return getTexture(spec);
|
return getTexture(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,11 +190,35 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
texture_name += name;
|
texture_name += name;
|
||||||
texture_name += "]";
|
texture_name += "]";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Try to get image from image cache
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
core::map<std::string, video::IImage*>::Node *n;
|
||||||
|
n = m_imagecache.find(texture_name);
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
video::IImage *image = n->getValue();
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureDirect(): Loaded \""
|
||||||
|
<<texture_name<<"\" from image cache"
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
|
// Do not process any further.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stuff starting with [ are special commands
|
||||||
if(name[0] != '[')
|
if(name[0] != '[')
|
||||||
{
|
{
|
||||||
// A normal texture; load it from a file
|
// A normal texture; load it from a file
|
||||||
std::string path = porting::getDataPath(name.c_str());
|
std::string path = porting::getDataPath(name.c_str());
|
||||||
dstream<<"getTextureDirect(): Loading path \""<<path
|
dstream<<"INFO: getTextureDirect(): Loading path \""<<path
|
||||||
<<"\""<<std::endl;
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
@ -192,7 +243,7 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
// If base image is NULL, load as base.
|
// If base image is NULL, load as base.
|
||||||
if(baseimg == NULL)
|
if(baseimg == NULL)
|
||||||
{
|
{
|
||||||
dstream<<"Setting "<<name<<" as base"<<std::endl;
|
dstream<<"INFO: Setting "<<name<<" as base"<<std::endl;
|
||||||
/*
|
/*
|
||||||
Copy it this way to get an alpha channel.
|
Copy it this way to get an alpha channel.
|
||||||
Otherwise images with alpha cannot be blitted on
|
Otherwise images with alpha cannot be blitted on
|
||||||
|
@ -209,7 +260,7 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
// Else blit on base.
|
// Else blit on base.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dstream<<"Blitting "<<name<<" on base"<<std::endl;
|
dstream<<"INFO: Blitting "<<name<<" on base"<<std::endl;
|
||||||
// Size of the copied area
|
// Size of the copied area
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
//core::dimension2d<u32> dim(16,16);
|
//core::dimension2d<u32> dim(16,16);
|
||||||
|
@ -229,27 +280,85 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// A special texture modification
|
// A special texture modification
|
||||||
dstream<<"getTextureDirect(): generating \""<<name<<"\""
|
dstream<<"INFO: getTextureDirect(): generating \""<<name<<"\""
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
if(name.substr(0,6) == "[crack")
|
if(name.substr(0,6) == "[crack")
|
||||||
{
|
{
|
||||||
u16 progression = stoi(name.substr(6));
|
u16 progression = stoi(name.substr(6));
|
||||||
// Size of the base image
|
// Size of the base image
|
||||||
core::dimension2d<u32> dim(16, 16);
|
core::dimension2d<u32> dim_base = baseimg->getDimension();
|
||||||
|
// Crack will be drawn at this size
|
||||||
|
u32 cracksize = 16;
|
||||||
// Size of the crack image
|
// Size of the crack image
|
||||||
//core::dimension2d<u32> dim_crack(16, 16 * CRACK_ANIMATION_LENGTH);
|
core::dimension2d<u32> dim_crack(cracksize,cracksize);
|
||||||
// Position to copy the crack to in the base image
|
|
||||||
core::position2d<s32> pos_base(0, 0);
|
|
||||||
// Position to copy the crack from in the crack image
|
// Position to copy the crack from in the crack image
|
||||||
core::position2d<s32> pos_other(0, 16 * progression);
|
core::position2d<s32> pos_other(0, 16 * progression);
|
||||||
|
|
||||||
video::IImage *crackimage = driver->createImageFromFile(
|
video::IImage *crackimage = driver->createImageFromFile(
|
||||||
porting::getDataPath("crack.png").c_str());
|
porting::getDataPath("crack.png").c_str());
|
||||||
crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
|
|
||||||
core::rect<s32>(pos_other, dim),
|
if(crackimage)
|
||||||
video::SColor(255,255,255,255),
|
{
|
||||||
NULL);
|
/*crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
|
||||||
crackimage->drop();
|
core::rect<s32>(pos_other, dim_base),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);*/
|
||||||
|
|
||||||
|
for(u32 y0=0; y0<dim_base.Height/dim_crack.Height; y0++)
|
||||||
|
for(u32 x0=0; x0<dim_base.Width/dim_crack.Width; x0++)
|
||||||
|
{
|
||||||
|
// Position to copy the crack to in the base image
|
||||||
|
core::position2d<s32> pos_base(x0*cracksize, y0*cracksize);
|
||||||
|
crackimage->copyToWithAlpha(baseimg, pos_base,
|
||||||
|
core::rect<s32>(pos_other, dim_crack),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
crackimage->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(name.substr(0,8) == "[combine")
|
||||||
|
{
|
||||||
|
// "[combine:16x128:0,0=stone.png:0,16=grass.png"
|
||||||
|
Strfnd sf(name);
|
||||||
|
sf.next(":");
|
||||||
|
u32 w0 = stoi(sf.next("x"));
|
||||||
|
u32 h0 = stoi(sf.next(":"));
|
||||||
|
dstream<<"INFO: combined w="<<w0<<" h="<<h0<<std::endl;
|
||||||
|
core::dimension2d<u32> dim(w0,h0);
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
while(sf.atend() == false)
|
||||||
|
{
|
||||||
|
u32 x = stoi(sf.next(","));
|
||||||
|
u32 y = stoi(sf.next("="));
|
||||||
|
std::string filename = sf.next(":");
|
||||||
|
dstream<<"INFO: Adding \""<<filename
|
||||||
|
<<"\" to combined ("<<x<<","<<y<<")"
|
||||||
|
<<std::endl;
|
||||||
|
video::IImage *img = driver->createImageFromFile(
|
||||||
|
porting::getDataPath(filename.c_str()).c_str());
|
||||||
|
if(img)
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim = img->getDimension();
|
||||||
|
dstream<<"INFO: Size "<<dim.Width
|
||||||
|
<<"x"<<dim.Height<<std::endl;
|
||||||
|
core::position2d<s32> pos_base(x, y);
|
||||||
|
video::IImage *img2 =
|
||||||
|
driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
img->copyTo(img2);
|
||||||
|
img->drop();
|
||||||
|
img2->copyToWithAlpha(baseimg, pos_base,
|
||||||
|
core::rect<s32>(v2s32(0,0), dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
img2->drop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: img==NULL"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(name.substr(0,12) == "[progressbar")
|
else if(name.substr(0,12) == "[progressbar")
|
||||||
{
|
{
|
||||||
|
@ -262,12 +371,31 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
" texture: \""<<name<<"\""<<std::endl;
|
" texture: \""<<name<<"\""<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add to image cache
|
||||||
|
*/
|
||||||
|
if(baseimg != NULL)
|
||||||
|
{
|
||||||
|
core::map<std::string, video::IImage*>::Node *n;
|
||||||
|
n = m_imagecache.find(texture_name);
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
video::IImage *img = n->getValue();
|
||||||
|
if(img != baseimg)
|
||||||
|
{
|
||||||
|
img->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_imagecache[texture_name] = baseimg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no resulting image, return NULL
|
// If no resulting image, return NULL
|
||||||
if(baseimg == NULL)
|
if(baseimg == NULL)
|
||||||
{
|
{
|
||||||
dstream<<"getTextureDirect(): baseimg is NULL (attempted to"
|
dstream<<"WARNING: getTextureDirect(): baseimg is NULL (attempted to"
|
||||||
" create texture \""<<texture_name<<"\""<<std::endl;
|
" create texture \""<<texture_name<<"\""<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -281,9 +409,8 @@ video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
|
|
||||||
// Create texture from resulting image
|
// Create texture from resulting image
|
||||||
t = driver->addTexture(texture_name.c_str(), baseimg);
|
t = driver->addTexture(texture_name.c_str(), baseimg);
|
||||||
baseimg->drop();
|
|
||||||
|
|
||||||
dstream<<"getTextureDirect(): created texture \""<<texture_name
|
dstream<<"INFO: getTextureDirect(): created texture \""<<texture_name
|
||||||
<<"\""<<std::endl;
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
@ -321,5 +448,5 @@ void make_progressbar(float value, video::IImage *image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <jmutexautolock.h>
|
#include <jmutexautolock.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: This is deprecated and should be removed completely
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe texture pointer cache.
|
A thread-safe texture pointer cache.
|
||||||
|
|
||||||
|
@ -38,45 +42,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
threads, because texture pointers have to be handled in
|
threads, because texture pointers have to be handled in
|
||||||
background threads.
|
background threads.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
class TextureCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TextureCache()
|
|
||||||
{
|
|
||||||
m_mutex.Init();
|
|
||||||
assert(m_mutex.IsInitialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(std::string name, video::ITexture *texture)
|
|
||||||
{
|
|
||||||
if(texture == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
m_textures[name] = texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
video::ITexture* get(const std::string &name)
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_mutex);
|
|
||||||
|
|
||||||
core::map<std::string, video::ITexture*>::Node *n;
|
|
||||||
n = m_textures.find(name);
|
|
||||||
|
|
||||||
if(n != NULL)
|
|
||||||
return n->getValue();
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
core::map<std::string, video::ITexture*> m_textures;
|
|
||||||
JMutex m_mutex;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe texture pointer cache
|
A thread-safe texture pointer cache
|
||||||
*/
|
*/
|
||||||
|
@ -116,6 +83,7 @@ private:
|
||||||
core::map<TextureSpec, video::ITexture*> m_textures;
|
core::map<TextureSpec, video::ITexture*> m_textures;
|
||||||
JMutex m_mutex;
|
JMutex m_mutex;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe wrapper for irrlicht, to be accessed from
|
A thread-safe wrapper for irrlicht, to be accessed from
|
||||||
|
@ -124,6 +92,8 @@ private:
|
||||||
Queues tasks to be done in the main thread.
|
Queues tasks to be done in the main thread.
|
||||||
|
|
||||||
Also caches texture specification strings to ids and textures.
|
Also caches texture specification strings to ids and textures.
|
||||||
|
|
||||||
|
TODO: Remove this and move all texture functionality to TextureSource
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IrrlichtWrapper : public IIrrlichtWrapper
|
class IrrlichtWrapper : public IIrrlichtWrapper
|
||||||
|
@ -135,12 +105,16 @@ public:
|
||||||
|
|
||||||
IrrlichtWrapper(IrrlichtDevice *device);
|
IrrlichtWrapper(IrrlichtDevice *device);
|
||||||
|
|
||||||
|
~IrrlichtWrapper();
|
||||||
|
|
||||||
// Run queued tasks
|
// Run queued tasks
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
// Shutdown wrapper; this disables queued texture fetching
|
// Shutdown wrapper; this disables queued texture fetching
|
||||||
void Shutdown(bool shutdown);
|
void Shutdown(bool shutdown);
|
||||||
|
|
||||||
|
IrrlichtDevice* getDevice();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These are called from other threads
|
These are called from other threads
|
||||||
*/
|
*/
|
||||||
|
@ -152,6 +126,7 @@ public:
|
||||||
return m_device->getTimer()->getRealTime();
|
return m_device->getTimer()->getRealTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Format of a texture name:
|
Format of a texture name:
|
||||||
"stone.png" (filename in image data directory)
|
"stone.png" (filename in image data directory)
|
||||||
|
@ -167,20 +142,18 @@ public:
|
||||||
// The reverse of the above
|
// The reverse of the above
|
||||||
std::string getTextureName(textureid_t id);
|
std::string getTextureName(textureid_t id);
|
||||||
// Gets a texture based on a filename
|
// Gets a texture based on a filename
|
||||||
video::ITexture* getTexture(const std::string &name);
|
video::ITexture* getTexture(const std::string &filename);
|
||||||
// Gets a texture based on a TextureSpec (a textureid_t is fine too)
|
// Gets a texture based on a TextureSpec (a textureid_t is fine too)
|
||||||
video::ITexture* getTexture(const TextureSpec &spec);
|
video::ITexture* getTexture(const TextureSpec &spec);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
Non-thread-safe variants of stuff, for internal use
|
Non-thread-safe variants of stuff, for internal use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// DEPRECATED NO-OP
|
|
||||||
//video::ITexture* getTextureDirect(const std::string &spec);
|
|
||||||
|
|
||||||
// Constructs a texture according to spec
|
// Constructs a texture according to spec
|
||||||
video::ITexture* getTextureDirect(const TextureSpec &spec);
|
//video::ITexture* getTextureDirect(const TextureSpec &spec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Members
|
Members
|
||||||
|
@ -195,14 +168,19 @@ private:
|
||||||
JMutex m_device_mutex;
|
JMutex m_device_mutex;
|
||||||
IrrlichtDevice *m_device;
|
IrrlichtDevice *m_device;
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Queued texture fetches (to be processed by the main thread)
|
// Queued texture fetches (to be processed by the main thread)
|
||||||
RequestQueue<TextureSpec, video::ITexture*, u8, u8> m_get_texture_queue;
|
RequestQueue<TextureSpec, video::ITexture*, u8, u8> m_get_texture_queue;
|
||||||
|
|
||||||
// Cache of textures by spec
|
// Cache of textures by spec
|
||||||
TextureCache m_texturecache;
|
TextureCache m_texturecache;
|
||||||
|
|
||||||
|
// Cached or generated source images by texture name
|
||||||
|
core::map<std::string, video::IImage*> m_imagecache;
|
||||||
|
|
||||||
// A mapping from texture id to string spec
|
// A mapping from texture id to string spec
|
||||||
MutexedIdGenerator<std::string> m_namecache;
|
MutexedIdGenerator<std::string> m_namecache;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
19
src/main.cpp
19
src/main.cpp
|
@ -97,6 +97,9 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into
|
||||||
different directions and then only those drawn that need to be
|
different directions and then only those drawn that need to be
|
||||||
- Also an 1-dimensional tile map would be nice probably
|
- Also an 1-dimensional tile map would be nice probably
|
||||||
|
|
||||||
|
SUGG: Calculate lighting per vertex to get a lighting effect like in
|
||||||
|
bartwe's game
|
||||||
|
|
||||||
Gaming ideas:
|
Gaming ideas:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -363,8 +366,13 @@ Doing now (most important at the top):
|
||||||
#include "guiMainMenu.h"
|
#include "guiMainMenu.h"
|
||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
#include "noise.h"
|
#include "noise.h"
|
||||||
|
#include "tile.h"
|
||||||
|
|
||||||
IrrlichtWrapper *g_irrlicht;
|
// TODO: Remove this
|
||||||
|
IrrlichtWrapper *g_irrlicht = NULL;
|
||||||
|
|
||||||
|
// This makes textures
|
||||||
|
TextureSource *g_texturesource = NULL;
|
||||||
|
|
||||||
MapDrawControl draw_control;
|
MapDrawControl draw_control;
|
||||||
|
|
||||||
|
@ -1643,6 +1651,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
g_device = device;
|
g_device = device;
|
||||||
g_irrlicht = new IrrlichtWrapper(device);
|
g_irrlicht = new IrrlichtWrapper(device);
|
||||||
|
g_texturesource = new TextureSource(device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Speed tests (done after irrlicht is loaded to get timer)
|
Speed tests (done after irrlicht is loaded to get timer)
|
||||||
|
@ -1670,7 +1679,8 @@ int main(int argc, char *argv[])
|
||||||
video::IVideoDriver* driver = device->getVideoDriver();
|
video::IVideoDriver* driver = device->getVideoDriver();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This changes the minimum allowed number of vertices in a VBO
|
This changes the minimum allowed number of vertices in a VBO.
|
||||||
|
Default is 500.
|
||||||
*/
|
*/
|
||||||
//driver->setMinHardwareBufferVertexCount(50);
|
//driver->setMinHardwareBufferVertexCount(50);
|
||||||
|
|
||||||
|
@ -2061,6 +2071,11 @@ int main(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
g_irrlicht->Run();
|
g_irrlicht->Run();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Process TextureSource's queue
|
||||||
|
*/
|
||||||
|
g_texturesource->processQueue();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Random calculations
|
Random calculations
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,15 +20,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifndef MAIN_HEADER
|
#ifndef MAIN_HEADER
|
||||||
#define MAIN_HEADER
|
#define MAIN_HEADER
|
||||||
|
|
||||||
#include "irrlichtwrapper.h"
|
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
|
#include "utility.h"
|
||||||
extern Settings g_settings;
|
extern Settings g_settings;
|
||||||
|
|
||||||
// A thread safe wrapper to irrlicht
|
// A thread safe wrapper to irrlicht
|
||||||
// On a server build, this is always NULL.
|
// On a server build, this is always NULL.
|
||||||
|
// TODO: Remove this
|
||||||
|
#include "irrlichtwrapper.h"
|
||||||
extern IrrlichtWrapper *g_irrlicht;
|
extern IrrlichtWrapper *g_irrlicht;
|
||||||
|
|
||||||
|
// This makes and maps textures
|
||||||
|
#include "tile.h"
|
||||||
|
extern TextureSource *g_texturesource;
|
||||||
|
|
||||||
// Debug streams
|
// Debug streams
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
91
src/map.cpp
91
src/map.cpp
|
@ -1974,7 +1974,7 @@ double tree_amount_2d(u64 seed, v2s16 p)
|
||||||
{
|
{
|
||||||
double noise = noise2d_perlin(
|
double noise = noise2d_perlin(
|
||||||
0.5+(float)p.X/250, 0.5+(float)p.Y/250,
|
0.5+(float)p.X/250, 0.5+(float)p.Y/250,
|
||||||
seed+2, 5, 0.6);
|
seed+2, 5, 0.66);
|
||||||
double zeroval = -0.3;
|
double zeroval = -0.3;
|
||||||
if(noise < zeroval)
|
if(noise < zeroval)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2021,9 +2021,9 @@ double base_rock_level_2d(u64 seed, v2s16 p)
|
||||||
base = base2;*/
|
base = base2;*/
|
||||||
#if 1
|
#if 1
|
||||||
// Higher ground level
|
// Higher ground level
|
||||||
double higher = (double)WATER_LEVEL + 13. + 50. * noise2d_perlin(
|
double higher = (double)WATER_LEVEL + 25. + 45. * noise2d_perlin(
|
||||||
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
|
0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
|
||||||
seed+85039, 6, 0.69);
|
seed+85039, 5, 0.69);
|
||||||
//higher = 30; // For debugging
|
//higher = 30; // For debugging
|
||||||
|
|
||||||
// Limit higher to at least base
|
// Limit higher to at least base
|
||||||
|
@ -2042,7 +2042,7 @@ double base_rock_level_2d(u64 seed, v2s16 p)
|
||||||
//double b = 20;
|
//double b = 20;
|
||||||
|
|
||||||
// Offset to more low
|
// Offset to more low
|
||||||
double a_off = -0.3;
|
double a_off = -0.15;
|
||||||
// High/low selector
|
// High/low selector
|
||||||
/*double a = 0.5 + b * (a_off + noise2d_perlin(
|
/*double a = 0.5 + b * (a_off + noise2d_perlin(
|
||||||
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
|
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
|
||||||
|
@ -2414,12 +2414,12 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
/*
|
/*
|
||||||
Make dungeons
|
Make dungeons
|
||||||
*/
|
*/
|
||||||
//u32 dungeons_count = relative_volume / 600000;
|
u32 dungeons_count = relative_volume / 600000;
|
||||||
/*u32 bruises_count = relative_volume * stone_surface_max_y / 40000000;
|
u32 bruises_count = relative_volume * stone_surface_max_y / 40000000;
|
||||||
if(stone_surface_max_y < WATER_LEVEL)
|
if(stone_surface_max_y < WATER_LEVEL)
|
||||||
bruises_count = 0;*/
|
bruises_count = 0;
|
||||||
u32 dungeons_count = 0;
|
/*u32 dungeons_count = 0;
|
||||||
u32 bruises_count = 0;
|
u32 bruises_count = 0;*/
|
||||||
for(u32 jj=0; jj<dungeons_count+bruises_count; jj++)
|
for(u32 jj=0; jj<dungeons_count+bruises_count; jj++)
|
||||||
{
|
{
|
||||||
s16 min_tunnel_diameter = 2;
|
s16 min_tunnel_diameter = 2;
|
||||||
|
@ -5116,6 +5116,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
timecheck_counter++;
|
timecheck_counter++;
|
||||||
if(timecheck_counter > 50)
|
if(timecheck_counter > 50)
|
||||||
{
|
{
|
||||||
|
timecheck_counter = 0;
|
||||||
int time2 = time(0);
|
int time2 = time(0);
|
||||||
if(time2 > time1 + 4)
|
if(time2 > time1 + 4)
|
||||||
{
|
{
|
||||||
|
@ -5167,71 +5168,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
v3s16 blockpos_nodes = block->getPosRelative();
|
|
||||||
|
|
||||||
// Block center position
|
|
||||||
v3f blockpos(
|
|
||||||
((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
|
|
||||||
((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
|
|
||||||
((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
|
|
||||||
);
|
|
||||||
|
|
||||||
// Block position relative to camera
|
|
||||||
v3f blockpos_relative = blockpos - camera_position;
|
|
||||||
|
|
||||||
// Distance in camera direction (+=front, -=back)
|
|
||||||
f32 dforward = blockpos_relative.dotProduct(camera_direction);
|
|
||||||
|
|
||||||
// Total distance
|
|
||||||
f32 d = blockpos_relative.getLength();
|
|
||||||
|
|
||||||
if(m_control.range_all == false)
|
|
||||||
{
|
|
||||||
// If block is far away, don't draw it
|
|
||||||
if(d > m_control.wanted_range * BS)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maximum radius of a block
|
|
||||||
f32 block_max_radius = 0.5*1.44*1.44*MAP_BLOCKSIZE*BS;
|
|
||||||
|
|
||||||
// If block is (nearly) touching the camera, don't
|
|
||||||
// bother validating further (that is, render it anyway)
|
|
||||||
if(d > block_max_radius * 1.5)
|
|
||||||
{
|
|
||||||
// Cosine of the angle between the camera direction
|
|
||||||
// and the block direction (camera_direction is an unit vector)
|
|
||||||
f32 cosangle = dforward / d;
|
|
||||||
|
|
||||||
// Compensate for the size of the block
|
|
||||||
// (as the block has to be shown even if it's a bit off FOV)
|
|
||||||
// This is an estimate.
|
|
||||||
cosangle += block_max_radius / dforward;
|
|
||||||
|
|
||||||
// If block is not in the field of view, skip it
|
|
||||||
//if(cosangle < cos(FOV_ANGLE/2))
|
|
||||||
if(cosangle < cos(FOV_ANGLE/2. * 4./3.))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
v3s16 blockpos_nodes = block->getPosRelative();
|
|
||||||
|
|
||||||
// Block center position
|
|
||||||
v3f blockpos(
|
|
||||||
((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
|
|
||||||
((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
|
|
||||||
((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
|
|
||||||
);
|
|
||||||
|
|
||||||
// Block position relative to camera
|
|
||||||
v3f blockpos_relative = blockpos - camera_position;
|
|
||||||
|
|
||||||
// Total distance
|
|
||||||
f32 d = blockpos_relative.getLength();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/*
|
/*
|
||||||
Update expired mesh
|
Update expired mesh
|
||||||
|
@ -5324,6 +5260,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||||
// Render transparent on transparent pass and likewise.
|
// Render transparent on transparent pass and likewise.
|
||||||
if(transparent == is_transparent_pass)
|
if(transparent == is_transparent_pass)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
This *shouldn't* hurt too much because Irrlicht
|
||||||
|
doesn't change opengl textures if the old
|
||||||
|
material is set again.
|
||||||
|
*/
|
||||||
driver->setMaterial(buf->getMaterial());
|
driver->setMaterial(buf->getMaterial());
|
||||||
driver->drawMeshBuffer(buf);
|
driver->drawMeshBuffer(buf);
|
||||||
vertex_count += buf->getVertexCount();
|
vertex_count += buf->getVertexCount();
|
||||||
|
|
|
@ -513,6 +513,8 @@ public:
|
||||||
// For debug printing
|
// For debug printing
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
|
bool isSavingEnabled(){ return m_map_saving_enabled; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Seed used for all kinds of randomness
|
// Seed used for all kinds of randomness
|
||||||
u64 m_seed;
|
u64 m_seed;
|
||||||
|
|
184
src/mapblock.cpp
184
src/mapblock.cpp
|
@ -273,13 +273,32 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
|
||||||
video::SColor c = video::SColor(alpha,li,li,li);
|
video::SColor c = video::SColor(alpha,li,li,li);
|
||||||
|
|
||||||
face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
|
face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
|
||||||
core::vector2d<f32>(0,1));
|
|
||||||
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
|
|
||||||
core::vector2d<f32>(abs_scale,1));
|
core::vector2d<f32>(abs_scale,1));
|
||||||
|
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
|
||||||
|
core::vector2d<f32>(0,1));
|
||||||
face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
|
face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
|
||||||
core::vector2d<f32>(abs_scale,0));
|
|
||||||
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
|
|
||||||
core::vector2d<f32>(0,0));
|
core::vector2d<f32>(0,0));
|
||||||
|
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
|
||||||
|
core::vector2d<f32>(abs_scale,0));
|
||||||
|
|
||||||
|
/*float x0 = (float)tile.tx/256.0;
|
||||||
|
float y0 = (float)tile.ty/256.0;
|
||||||
|
float w = ((float)tile.tw + 1.0)/256.0;
|
||||||
|
float h = ((float)tile.th + 1.0)/256.0;*/
|
||||||
|
|
||||||
|
float x0 = tile.texture.pos.X;
|
||||||
|
float y0 = tile.texture.pos.Y;
|
||||||
|
float w = tile.texture.size.X;
|
||||||
|
float h = tile.texture.size.Y;
|
||||||
|
|
||||||
|
face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0+h));
|
||||||
|
face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
|
||||||
|
core::vector2d<f32>(x0, y0+h));
|
||||||
|
face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
|
||||||
|
core::vector2d<f32>(x0, y0));
|
||||||
|
face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
|
||||||
|
core::vector2d<f32>(x0+w*abs_scale, y0));
|
||||||
|
|
||||||
face.tile = tile;
|
face.tile = tile;
|
||||||
//DEBUG
|
//DEBUG
|
||||||
|
@ -318,11 +337,26 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||||
}
|
}
|
||||||
if(mod.type == NODEMOD_CRACK)
|
if(mod.type == NODEMOD_CRACK)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Get texture id, translate it to name, append stuff to
|
||||||
|
name, get texture id
|
||||||
|
*/
|
||||||
|
// Get original texture name
|
||||||
|
u32 orig_id = spec.texture.id;
|
||||||
|
std::string orig_name = g_texturesource->getTextureName(orig_id);
|
||||||
|
// Create new texture name
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os<<"[crack"<<mod.param;
|
os<<orig_name<<"^[crack"<<mod.param;
|
||||||
|
//os<<orig_name<<"^[progressbar0.5";
|
||||||
|
//os<<"mese.png";
|
||||||
|
// Get new texture
|
||||||
|
u32 new_id = g_texturesource->getTextureId(os.str());
|
||||||
|
|
||||||
textureid_t tid = g_irrlicht->getTextureId(os.str());
|
dstream<<"MapBlock::getNodeTile(): Switching from "
|
||||||
spec.spec.addTid(tid);
|
<<orig_name<<" to "<<os.str()<<" ("
|
||||||
|
<<orig_id<<" to "<<new_id<<")"<<std::endl;
|
||||||
|
|
||||||
|
spec.texture = g_texturesource->getTexture(new_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,6 +441,8 @@ void MapBlock::updateFastFaceRow(
|
||||||
TileSpec tile1_next;
|
TileSpec tile1_next;
|
||||||
u8 light_next = 0;
|
u8 light_next = 0;
|
||||||
|
|
||||||
|
// If at last position, there is nothing to compare to and
|
||||||
|
// the face must be drawn anyway
|
||||||
if(j != length - 1)
|
if(j != length - 1)
|
||||||
{
|
{
|
||||||
p_next = p + translate_dir;
|
p_next = p + translate_dir;
|
||||||
|
@ -426,7 +462,31 @@ void MapBlock::updateFastFaceRow(
|
||||||
|
|
||||||
continuous_tiles_count++;
|
continuous_tiles_count++;
|
||||||
|
|
||||||
if(next_is_different)
|
// This is set to true if the texture doesn't allow more tiling
|
||||||
|
bool end_of_texture = false;
|
||||||
|
/*
|
||||||
|
If there is no texture, it can be tiled infinitely.
|
||||||
|
If tiled==0, it means the texture can be tiled infinitely.
|
||||||
|
Otherwise check tiled agains continuous_tiles_count.
|
||||||
|
|
||||||
|
This check has to be made for both tiles, because this is
|
||||||
|
a bit hackish and we know which one we're using only when
|
||||||
|
the decision to make the faces is made.
|
||||||
|
*/
|
||||||
|
if(tile0.texture.atlas != NULL && tile0.texture.tiled != 0)
|
||||||
|
{
|
||||||
|
if(tile0.texture.tiled <= continuous_tiles_count)
|
||||||
|
end_of_texture = true;
|
||||||
|
}
|
||||||
|
if(tile1.texture.atlas != NULL && tile1.texture.tiled != 0)
|
||||||
|
{
|
||||||
|
if(tile1.texture.tiled <= continuous_tiles_count)
|
||||||
|
end_of_texture = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//end_of_texture = true; //DEBUG
|
||||||
|
|
||||||
|
if(next_is_different || end_of_texture)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Create a face if there should be one
|
Create a face if there should be one
|
||||||
|
@ -684,10 +744,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
Convert FastFaces to SMesh
|
Convert FastFaces to SMesh
|
||||||
*/
|
*/
|
||||||
|
|
||||||
scene::SMesh *mesh_new = NULL;
|
|
||||||
|
|
||||||
mesh_new = new scene::SMesh();
|
|
||||||
|
|
||||||
MeshCollector collector;
|
MeshCollector collector;
|
||||||
|
|
||||||
if(fastfaces_new.size() > 0)
|
if(fastfaces_new.size() > 0)
|
||||||
|
@ -709,7 +765,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
|
|
||||||
const u16 indices[] = {0,1,2,2,3,0};
|
const u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
|
||||||
video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
|
//video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
|
||||||
|
video::ITexture *texture = f.tile.texture.atlas;
|
||||||
if(texture == NULL)
|
if(texture == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -717,11 +774,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
|
|
||||||
f.tile.applyMaterialOptions(material);
|
f.tile.applyMaterialOptions(material);
|
||||||
|
|
||||||
/*if(f.tile.alpha != 255)
|
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
|
||||||
else
|
|
||||||
material.MaterialType = video::EMT_SOLID;*/
|
|
||||||
|
|
||||||
collector.append(material, f.vertices, 4, indices, 6);
|
collector.append(material, f.vertices, 4, indices, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,7 +794,11 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
material_water1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material_water1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
material_water1.setFlag(video::EMF_FOG_ENABLE, true);
|
material_water1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
material_water1.setTexture(0, g_irrlicht->getTexture("water.png"));
|
//TODO
|
||||||
|
//material_water1.setTexture(0, g_irrlicht->getTexture("water.png"));
|
||||||
|
AtlasPointer pa_water1 = g_texturesource->getTexture(
|
||||||
|
g_texturesource->getTextureId("water.png"));
|
||||||
|
material_water1.setTexture(0, pa_water1.atlas);
|
||||||
|
|
||||||
// New-style leaves material
|
// New-style leaves material
|
||||||
video::SMaterial material_leaves1;
|
video::SMaterial material_leaves1;
|
||||||
|
@ -751,7 +807,11 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
material_leaves1.setTexture(0, g_irrlicht->getTexture("leaves.png"));
|
//TODO
|
||||||
|
//material_leaves1.setTexture(0, g_irrlicht->getTexture("leaves.png"));
|
||||||
|
AtlasPointer pa_leaves1 = g_texturesource->getTexture(
|
||||||
|
g_texturesource->getTextureId("leaves.png"));
|
||||||
|
material_leaves1.setTexture(0, pa_leaves1.atlas);
|
||||||
|
|
||||||
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
|
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||||
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||||
|
@ -804,7 +864,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
material.MaterialType
|
material.MaterialType
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
if(dir == v3s16(0,-1,0))
|
//TODO
|
||||||
|
/*if(dir == v3s16(0,-1,0))
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture("torch_on_floor.png"));
|
g_irrlicht->getTexture("torch_on_floor.png"));
|
||||||
else if(dir == v3s16(0,1,0))
|
else if(dir == v3s16(0,1,0))
|
||||||
|
@ -816,7 +877,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
g_irrlicht->getTexture("torch_on_floor.png"));
|
g_irrlicht->getTexture("torch_on_floor.png"));
|
||||||
else
|
else
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture("torch.png"));
|
g_irrlicht->getTexture("torch.png"));*/
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
|
@ -974,14 +1035,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
/*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
|
||||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
|
||||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
|
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y0()),
|
||||||
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1048,10 +1113,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
{
|
{
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y0()),
|
||||||
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
|
@ -1092,10 +1165,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
/*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
||||||
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
||||||
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||||
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y1()),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x1(), pa_water1.y0()),
|
||||||
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
|
||||||
|
pa_water1.x0(), pa_water1.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
|
@ -1120,10 +1201,18 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
{
|
{
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
{
|
{
|
||||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
||||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),
|
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
||||||
|
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
|
pa_leaves1.x0(), pa_leaves1.y1()),
|
||||||
|
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||||
|
pa_leaves1.x1(), pa_leaves1.y1()),
|
||||||
|
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
|
||||||
|
pa_leaves1.x1(), pa_leaves1.y0()),
|
||||||
|
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
|
||||||
|
pa_leaves1.x0(), pa_leaves1.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if(j == 0)
|
if(j == 0)
|
||||||
|
@ -1173,6 +1262,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
Add stuff from collector to mesh
|
Add stuff from collector to mesh
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
scene::SMesh *mesh_new = NULL;
|
||||||
|
mesh_new = new scene::SMesh();
|
||||||
|
|
||||||
collector.fillMesh(mesh_new);
|
collector.fillMesh(mesh_new);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1191,13 +1283,25 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||||
mesh_new = NULL;
|
mesh_new = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use VBO for mesh (this just would set this for ever buffer)
|
if(mesh_new)
|
||||||
// This will lead to infinite memory usage because or irrlicht.
|
{
|
||||||
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
|
#if 0
|
||||||
|
// Usually 1-700 faces and 1-7 materials
|
||||||
|
std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
|
||||||
|
<<"and uses "<<mesh_new->getMeshBufferCount()
|
||||||
|
<<" materials (meshbuffers)"<<std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*std::cout<<"MapBlock has "<<fastfaces_new.size()<<" faces "
|
// Use VBO for mesh (this just would set this for ever buffer)
|
||||||
<<"and uses "<<mesh_new->getMeshBufferCount()
|
// This will lead to infinite memory usage because or irrlicht.
|
||||||
<<" materials (meshbuffers)"<<std::endl;*/
|
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: If that is enabled, some kind of a queue to the main
|
||||||
|
thread should be made which would call irrlicht to delete
|
||||||
|
the hardware buffer and then delete the mesh
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replace the mesh
|
Replace the mesh
|
||||||
|
|
124
src/mapnode.cpp
124
src/mapnode.cpp
|
@ -17,6 +17,7 @@ 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
#include "mapnode.h"
|
#include "mapnode.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
@ -31,6 +32,20 @@ ContentFeatures::~ContentFeatures()
|
||||||
delete translate_to;
|
delete translate_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
|
||||||
|
{
|
||||||
|
if(g_texturesource)
|
||||||
|
{
|
||||||
|
tiles[i].texture = g_texturesource->getTexture(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alpha != 255)
|
||||||
|
{
|
||||||
|
tiles[i].alpha = alpha;
|
||||||
|
tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ContentFeatures g_content_features[256];
|
struct ContentFeatures g_content_features[256];
|
||||||
|
|
||||||
ContentFeatures & content_features(u8 i)
|
ContentFeatures & content_features(u8 i)
|
||||||
|
@ -40,56 +55,75 @@ ContentFeatures & content_features(u8 i)
|
||||||
|
|
||||||
void init_mapnode(IIrrlichtWrapper *irrlicht)
|
void init_mapnode(IIrrlichtWrapper *irrlicht)
|
||||||
{
|
{
|
||||||
|
// Read some settings
|
||||||
bool new_style_water = g_settings.getBool("new_style_water");
|
bool new_style_water = g_settings.getBool("new_style_water");
|
||||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize content feature table
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set initial material type to same in all tiles, so that the
|
||||||
|
same material can be used in more stuff.
|
||||||
|
This is set according to the leaves because they are the only
|
||||||
|
differing material to which all materials can be changed to
|
||||||
|
get this optimization.
|
||||||
|
*/
|
||||||
|
u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
|
||||||
|
/*if(new_style_leaves)
|
||||||
|
initial_material_type = MATERIAL_ALPHA_SIMPLE;
|
||||||
|
else
|
||||||
|
initial_material_type = MATERIAL_ALPHA_NONE;*/
|
||||||
|
for(u16 i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
ContentFeatures *f = &g_content_features[i];
|
||||||
|
for(u16 j=0; j<6; j++)
|
||||||
|
f->tiles[j].material_type = initial_material_type;
|
||||||
|
}
|
||||||
|
|
||||||
u8 i;
|
u8 i;
|
||||||
ContentFeatures *f = NULL;
|
ContentFeatures *f = NULL;
|
||||||
|
|
||||||
i = CONTENT_STONE;
|
i = CONTENT_STONE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("stone.png"));
|
f->setAllTextures("stone.png");
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_GRASS;
|
i = CONTENT_GRASS;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
f->setAllTextures("mud.png^grass_side.png");
|
||||||
irrlicht->getTextureId("grass_side.png")));
|
f->setTexture(0, "grass.png");
|
||||||
f->setTexture(0, irrlicht->getTextureId("grass.png"));
|
f->setTexture(1, "mud.png");
|
||||||
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
//f->setInventoryTexture(irrlicht->getTextureId("grass.png"));
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("grass.png"));
|
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_GRASS_FOOTSTEPS;
|
i = CONTENT_GRASS_FOOTSTEPS;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
//f->setInventoryTexture(irrlicht->getTextureId("grass_footsteps.png"));
|
||||||
irrlicht->getTextureId("grass_side.png")));
|
|
||||||
f->setTexture(0, irrlicht->getTextureId("grass_footsteps.png"));
|
|
||||||
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("grass_footsteps.png"));
|
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_MUD;
|
i = CONTENT_MUD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("mud.png"));
|
f->setAllTextures("mud.png");
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_SAND;
|
i = CONTENT_SAND;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("sand.png"));
|
f->setAllTextures("sand.png");
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_TREE;
|
i = CONTENT_TREE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("tree.png"));
|
f->setAllTextures("tree.png");
|
||||||
f->setTexture(0, irrlicht->getTextureId("tree_top.png"));
|
f->setTexture(0, "tree_top.png");
|
||||||
f->setTexture(1, irrlicht->getTextureId("tree_top.png"));
|
f->setTexture(1, "tree_top.png");
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("tree_top.png"));
|
//f->setInventoryTexture(irrlicht->getTextureId("tree_top.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
|
@ -105,36 +139,33 @@ void init_mapnode(IIrrlichtWrapper *irrlicht)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
f->setAllTextures(irrlicht->getTextureId("leaves.png"));
|
f->setAllTextures("[noalpha:leaves.png");
|
||||||
}
|
}
|
||||||
/*{
|
|
||||||
TileSpec t;
|
|
||||||
t.spec = TextureSpec(irrlicht->getTextureId("leaves.png"));
|
|
||||||
//t.material_type = MATERIAL_ALPHA_SIMPLE;
|
|
||||||
//t.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
|
||||||
f->setAllTiles(t);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
i = CONTENT_COALSTONE;
|
i = CONTENT_COALSTONE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
//f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
||||||
f->setAllTextures(TextureSpec(irrlicht->getTextureId("coal.png"),
|
/*f->setAllTextures(TextureSpec(irrlicht->getTextureId("coal.png"),
|
||||||
irrlicht->getTextureId("mineral_coal.png")));
|
irrlicht->getTextureId("mineral_coal.png")));*/
|
||||||
|
f->setAllTextures("stone.png^mineral_coal.png");
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_WOOD;
|
i = CONTENT_WOOD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("wood.png"));
|
//f->setAllTextures(irrlicht->getTextureId("wood.png"));
|
||||||
|
f->setAllTextures("wood.png");
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_MESE;
|
i = CONTENT_MESE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("mese.png"));
|
//f->setAllTextures(irrlicht->getTextureId("mese.png"));
|
||||||
|
f->setAllTextures("mese.png");
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_CLOUD;
|
i = CONTENT_CLOUD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures(irrlicht->getTextureId("cloud.png"));
|
//f->setAllTextures(irrlicht->getTextureId("cloud.png"));
|
||||||
|
f->setAllTextures("cloud.png");
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_AIR;
|
i = CONTENT_AIR;
|
||||||
|
@ -150,7 +181,7 @@ void init_mapnode(IIrrlichtWrapper *irrlicht)
|
||||||
|
|
||||||
i = CONTENT_WATER;
|
i = CONTENT_WATER;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
//f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->solidness = 0; // Drawn separately, makes no faces
|
f->solidness = 0; // Drawn separately, makes no faces
|
||||||
|
@ -162,21 +193,23 @@ void init_mapnode(IIrrlichtWrapper *irrlicht)
|
||||||
|
|
||||||
i = CONTENT_WATERSOURCE;
|
i = CONTENT_WATERSOURCE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
//f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||||
if(new_style_water)
|
if(new_style_water)
|
||||||
{
|
{
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
}
|
}
|
||||||
else // old style
|
else // old style
|
||||||
{
|
{
|
||||||
f->setAllTextures(irrlicht->getTextureId("water.png"), WATER_ALPHA);
|
f->solidness = 1;
|
||||||
|
|
||||||
TileSpec t;
|
TileSpec t;
|
||||||
t.spec = TextureSpec(irrlicht->getTextureId("water.png"));
|
if(g_texturesource)
|
||||||
|
t.texture = g_texturesource->getTexture("water.png");
|
||||||
|
|
||||||
t.alpha = WATER_ALPHA;
|
t.alpha = WATER_ALPHA;
|
||||||
t.material_type = MATERIAL_ALPHA_VERTEX;
|
t.material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
f->setAllTiles(t);
|
f->setAllTiles(t);
|
||||||
f->solidness = 1;
|
|
||||||
}
|
}
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
|
@ -188,7 +221,6 @@ void init_mapnode(IIrrlichtWrapper *irrlicht)
|
||||||
|
|
||||||
i = CONTENT_TORCH;
|
i = CONTENT_TORCH;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setInventoryTexture(irrlicht->getTextureId("torch_on_floor.png"));
|
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
|
@ -224,13 +256,23 @@ TileSpec MapNode::getTile(v3s16 dir)
|
||||||
else
|
else
|
||||||
spec = content_features(d).tiles[dir_i];
|
spec = content_features(d).tiles[dir_i];
|
||||||
|
|
||||||
if(content_features(d).param_type == CPT_MINERAL)
|
/*
|
||||||
|
If it contains some mineral, change texture id
|
||||||
|
*/
|
||||||
|
if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
|
||||||
{
|
{
|
||||||
u8 mineral = param & 0x1f;
|
u8 mineral = param & 0x1f;
|
||||||
// Add mineral block texture
|
std::string mineral_texture_name = mineral_block_texture(mineral);
|
||||||
textureid_t tid = mineral_block_texture(mineral);
|
if(mineral_texture_name != "")
|
||||||
if(tid != 0)
|
{
|
||||||
spec.spec.addTid(tid);
|
u32 orig_id = spec.texture.id;
|
||||||
|
std::string texture_name = g_texturesource->getTextureName(orig_id);
|
||||||
|
//texture_name += "^blit:";
|
||||||
|
texture_name += "^";
|
||||||
|
texture_name += mineral_texture_name;
|
||||||
|
u32 new_id = g_texturesource->getTextureId(texture_name);
|
||||||
|
spec.texture = g_texturesource->getTexture(new_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
|
|
|
@ -133,8 +133,10 @@ struct ContentFeatures
|
||||||
*/
|
*/
|
||||||
TileSpec tiles[6];
|
TileSpec tiles[6];
|
||||||
|
|
||||||
|
// TODO: Somehow specify inventory image
|
||||||
//std::string inventory_image_path;
|
//std::string inventory_image_path;
|
||||||
TextureSpec inventory_texture;
|
//TextureSpec inventory_texture;
|
||||||
|
//u32 inventory_texture_id;
|
||||||
|
|
||||||
bool is_ground_content; //TODO: Remove, use walkable instead
|
bool is_ground_content; //TODO: Remove, use walkable instead
|
||||||
bool light_propagates;
|
bool light_propagates;
|
||||||
|
@ -167,27 +169,36 @@ struct ContentFeatures
|
||||||
|
|
||||||
~ContentFeatures();
|
~ContentFeatures();
|
||||||
|
|
||||||
// Quickhands for simple materials
|
/*
|
||||||
void setTexture(u16 i, const TextureSpec &spec, u8 alpha=255)
|
Quickhands for simple materials
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setTexture(u16 i, std::string name, u8 alpha=255);
|
||||||
|
|
||||||
|
void setAllTextures(std::string name, u8 alpha=255)
|
||||||
{
|
{
|
||||||
tiles[i].spec = spec;
|
for(u16 i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
setTexture(i, name, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void setTexture(u16 i, AtlasPointer p, u8 alpha=255)
|
||||||
|
{
|
||||||
|
tiles[i].texture = p;
|
||||||
if(alpha != 255)
|
if(alpha != 255)
|
||||||
{
|
{
|
||||||
tiles[i].alpha = alpha;
|
tiles[i].alpha = alpha;
|
||||||
tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
|
tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void setAllTextures(const TextureSpec &spec, u8 alpha=255)
|
void setAllTextures(AtlasPointer p, u8 alpha=255)
|
||||||
{
|
{
|
||||||
for(u16 i=0; i<6; i++)
|
for(u16 i=0; i<6; i++)
|
||||||
{
|
{
|
||||||
setTexture(i, spec, alpha);
|
setTexture(i, p, alpha);
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
// Set this too so it can be left as is most times
|
|
||||||
if(inventory_texture.empty())
|
|
||||||
inventory_texture = spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTile(u16 i, const TileSpec &tile)
|
void setTile(u16 i, const TileSpec &tile)
|
||||||
{
|
{
|
||||||
|
@ -201,10 +212,10 @@ struct ContentFeatures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInventoryTexture(const TextureSpec &spec)
|
/*void setInventoryTexture(const TextureSpec &spec)
|
||||||
{
|
{
|
||||||
inventory_texture = spec;
|
inventory_texture = spec;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*void setInventoryImage(std::string imgname)
|
/*void setInventoryImage(std::string imgname)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,8 @@ const char *mineral_filenames[MINERAL_COUNT] =
|
||||||
"mineral_iron.png"
|
"mineral_iron.png"
|
||||||
};
|
};
|
||||||
|
|
||||||
textureid_t mineral_textures[MINERAL_COUNT] = {0};
|
//textureid_t mineral_textures[MINERAL_COUNT] = {0};
|
||||||
|
std::string mineral_textures[MINERAL_COUNT];
|
||||||
|
|
||||||
void init_mineral(IIrrlichtWrapper *irrlicht)
|
void init_mineral(IIrrlichtWrapper *irrlicht)
|
||||||
{
|
{
|
||||||
|
@ -35,14 +36,17 @@ void init_mineral(IIrrlichtWrapper *irrlicht)
|
||||||
{
|
{
|
||||||
if(mineral_filenames[i] == NULL)
|
if(mineral_filenames[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
mineral_textures[i] = irrlicht->getTextureId(mineral_filenames[i]);
|
//mineral_textures[i] = irrlicht->getTextureId(mineral_filenames[i]);
|
||||||
|
//mineral_textures[i] = 0;
|
||||||
|
mineral_textures[i] = mineral_filenames[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textureid_t mineral_block_texture(u8 mineral)
|
//textureid_t mineral_block_texture(u8 mineral)
|
||||||
|
std::string mineral_block_texture(u8 mineral)
|
||||||
{
|
{
|
||||||
if(mineral >= MINERAL_COUNT)
|
if(mineral >= MINERAL_COUNT)
|
||||||
return 0;
|
return "";
|
||||||
|
|
||||||
return mineral_textures[mineral];
|
return mineral_textures[mineral];
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,8 @@ void init_mineral(IIrrlichtWrapper *irrlicht);
|
||||||
|
|
||||||
#define MINERAL_COUNT 3
|
#define MINERAL_COUNT 3
|
||||||
|
|
||||||
textureid_t mineral_block_texture(u8 mineral);
|
//textureid_t mineral_block_texture(u8 mineral);
|
||||||
|
std::string mineral_block_texture(u8 mineral);
|
||||||
|
|
||||||
inline CraftItem * getDiggedMineralItem(u8 mineral)
|
inline CraftItem * getDiggedMineralItem(u8 mineral)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1642,6 +1642,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
os<<name<<L",";
|
os<<name<<L",";
|
||||||
}
|
}
|
||||||
os<<L"}";
|
os<<L"}";
|
||||||
|
if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
|
||||||
|
os<<" WARNING: Map saving is disabled."<<std::endl;
|
||||||
// Send message
|
// Send message
|
||||||
SendChatMessage(peer_id, os.str());
|
SendChatMessage(peer_id, os.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#ifndef TEXTURE_HEADER
|
#ifndef TEXTURE_HEADER
|
||||||
#define TEXTURE_HEADER
|
#define TEXTURE_HEADER
|
||||||
|
|
||||||
|
// This file now contains all that was here
|
||||||
|
#include "tile.h"
|
||||||
|
|
||||||
|
// TODO: Remove this
|
||||||
|
typedef u16 textureid_t;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
//#include "utility.h"
|
//#include "utility.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -122,3 +130,5 @@ struct TextureSpec
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
770
src/tile.cpp
770
src/tile.cpp
|
@ -18,10 +18,770 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
//#include "porting.h"
|
#include "debug.h"
|
||||||
// For IrrlichtWrapper
|
|
||||||
//#include "main.h"
|
|
||||||
//#include <string>
|
|
||||||
|
|
||||||
// Nothing here
|
TextureSource::TextureSource(IrrlichtDevice *device):
|
||||||
|
m_device(device),
|
||||||
|
m_main_atlas_image(NULL),
|
||||||
|
m_main_atlas_texture(NULL)
|
||||||
|
{
|
||||||
|
assert(m_device);
|
||||||
|
|
||||||
|
m_atlaspointer_cache_mutex.Init();
|
||||||
|
|
||||||
|
m_main_thread = get_current_thread_id();
|
||||||
|
|
||||||
|
// Add a NULL AtlasPointer as the first index, named ""
|
||||||
|
m_atlaspointer_cache.push_back(SourceAtlasPointer(""));
|
||||||
|
m_name_to_id[""] = 0;
|
||||||
|
|
||||||
|
// Build main texture atlas
|
||||||
|
buildMainAtlas();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureSource::~TextureSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureSource::processQueue()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Fetch textures
|
||||||
|
*/
|
||||||
|
if(m_get_texture_queue.size() > 0)
|
||||||
|
{
|
||||||
|
GetRequest<std::string, u32, u8, u8>
|
||||||
|
request = m_get_texture_queue.pop();
|
||||||
|
|
||||||
|
dstream<<"INFO: TextureSource::processQueue(): "
|
||||||
|
<<"got texture request with "
|
||||||
|
<<"name="<<request.key
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
|
GetResult<std::string, u32, u8, u8>
|
||||||
|
result;
|
||||||
|
result.key = request.key;
|
||||||
|
result.callers = request.callers;
|
||||||
|
result.item = getTextureIdDirect(request.key);
|
||||||
|
|
||||||
|
request.dest->push_back(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 TextureSource::getTextureId(const std::string &name)
|
||||||
|
{
|
||||||
|
//dstream<<"INFO: getTextureId(): name="<<name<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
See if texture already exists
|
||||||
|
*/
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
core::map<std::string, u32>::Node *n;
|
||||||
|
n = m_name_to_id.find(name);
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get texture
|
||||||
|
*/
|
||||||
|
if(get_current_thread_id() == m_main_thread)
|
||||||
|
{
|
||||||
|
return getTextureIdDirect(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"INFO: getTextureId(): Queued: name="<<name<<std::endl;
|
||||||
|
|
||||||
|
// We're gonna ask the result to be put into here
|
||||||
|
ResultQueue<std::string, u32, u8, u8> result_queue;
|
||||||
|
|
||||||
|
// Throw a request in
|
||||||
|
m_get_texture_queue.add(name, 0, 0, &result_queue);
|
||||||
|
|
||||||
|
dstream<<"INFO: Waiting for texture from main thread, name="
|
||||||
|
<<name<<std::endl;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Wait result for a second
|
||||||
|
GetResult<std::string, u32, u8, u8>
|
||||||
|
result = result_queue.pop_front(1000);
|
||||||
|
|
||||||
|
// Check that at least something worked OK
|
||||||
|
assert(result.key == name);
|
||||||
|
|
||||||
|
return result.item;
|
||||||
|
}
|
||||||
|
catch(ItemNotFoundException &e)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Waiting for texture timed out."<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"WARNING: getTextureId(): Failed"<<std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a progress bar on the image
|
||||||
|
void make_progressbar(float value, video::IImage *image);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate image based on a string like "stone.png" or "[crack0".
|
||||||
|
if baseimg is NULL, it is created. Otherwise stuff is made on it.
|
||||||
|
*/
|
||||||
|
bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
|
video::IVideoDriver* driver);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generates an image from a full string like
|
||||||
|
"stone.png^mineral_coal.png^[crack0".
|
||||||
|
|
||||||
|
This is used by buildMainAtlas().
|
||||||
|
*/
|
||||||
|
video::IImage* generate_image_from_scratch(std::string name,
|
||||||
|
video::IVideoDriver* driver);
|
||||||
|
|
||||||
|
/*
|
||||||
|
This method generates all the textures
|
||||||
|
*/
|
||||||
|
u32 TextureSource::getTextureIdDirect(const std::string &name)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): name="<<name<<std::endl;
|
||||||
|
|
||||||
|
// Empty name means texture 0
|
||||||
|
if(name == "")
|
||||||
|
{
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): name is empty"<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calling only allowed from main thread
|
||||||
|
*/
|
||||||
|
if(get_current_thread_id() != m_main_thread)
|
||||||
|
{
|
||||||
|
dstream<<"ERROR: TextureSource::getTextureIdDirect() "
|
||||||
|
"called not from main thread"<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See if texture already exists
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
core::map<std::string, u32>::Node *n;
|
||||||
|
n = m_name_to_id.find(name);
|
||||||
|
if(n != NULL)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): name="<<name
|
||||||
|
<<" found in cache"<<std::endl;
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): name="<<name
|
||||||
|
<<" NOT found in cache. Creating it."<<std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the base image
|
||||||
|
*/
|
||||||
|
|
||||||
|
char separator = '^';
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is set to the id of the base image.
|
||||||
|
If left 0, there is no base image and a completely new image
|
||||||
|
is made.
|
||||||
|
*/
|
||||||
|
u32 base_image_id = 0;
|
||||||
|
|
||||||
|
// Find last meta separator in name
|
||||||
|
s32 last_separator_position = -1;
|
||||||
|
for(s32 i=name.size()-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
if(name[i] == separator)
|
||||||
|
{
|
||||||
|
last_separator_position = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
If separator was found, construct the base name and make the
|
||||||
|
base image using a recursive call
|
||||||
|
*/
|
||||||
|
std::string base_image_name;
|
||||||
|
if(last_separator_position != -1)
|
||||||
|
{
|
||||||
|
// Construct base name
|
||||||
|
base_image_name = name.substr(0, last_separator_position);
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
|
||||||
|
" to get base image, name="<<base_image_name<<std::endl;
|
||||||
|
base_image_id = getTextureIdDirect(base_image_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"base_image_id="<<base_image_id<<std::endl;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
|
assert(driver);
|
||||||
|
|
||||||
|
video::ITexture *t = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
An image will be built from files and then converted into a texture.
|
||||||
|
*/
|
||||||
|
video::IImage *baseimg = NULL;
|
||||||
|
|
||||||
|
// If a base image was found, copy it to baseimg
|
||||||
|
if(base_image_id != 0)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
SourceAtlasPointer ap = m_atlaspointer_cache[base_image_id];
|
||||||
|
|
||||||
|
video::IImage *image = ap.atlas_img;
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = ap.intsize;
|
||||||
|
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
core::position2d<s32> pos_to(0,0);
|
||||||
|
core::position2d<s32> pos_from = ap.intpos;
|
||||||
|
|
||||||
|
image->copyTo(
|
||||||
|
baseimg, // target
|
||||||
|
v2s32(0,0), // position in target
|
||||||
|
core::rect<s32>(pos_from, dim) // from
|
||||||
|
);
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): Loaded \""
|
||||||
|
<<base_image_name<<"\" from image cache"
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Parse out the last part of the name of the image and act
|
||||||
|
according to it
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||||
|
dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
|
||||||
|
|
||||||
|
// Generate image according to part of name
|
||||||
|
if(generate_image(last_part_of_name, baseimg, driver) == false)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): "
|
||||||
|
"failed to generate \""<<last_part_of_name<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no resulting image, return NULL
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): baseimg is NULL (attempted to"
|
||||||
|
" create texture \""<<name<<"\""<<std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create texture from resulting image
|
||||||
|
t = driver->addTexture(name.c_str(), baseimg);
|
||||||
|
|
||||||
|
// If no texture
|
||||||
|
if(t == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add texture to caches
|
||||||
|
*/
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
u32 id = m_atlaspointer_cache.size();
|
||||||
|
AtlasPointer ap(id);
|
||||||
|
ap.atlas = t;
|
||||||
|
ap.pos = v2f(0,0);
|
||||||
|
ap.size = v2f(1,1);
|
||||||
|
ap.tiled = 0;
|
||||||
|
SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg->getDimension());
|
||||||
|
m_atlaspointer_cache.push_back(nap);
|
||||||
|
m_name_to_id.insert(name, id);
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): name="<<name
|
||||||
|
<<": succesfully returning id="<<id<<std::endl;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TextureSource::getTextureName(u32 id)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
if(id >= m_atlaspointer_cache.size())
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: TextureSource::getTextureName(): id="<<id
|
||||||
|
<<" >= m_atlaspointer_cache.size()="
|
||||||
|
<<m_atlaspointer_cache.size()<<std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_atlaspointer_cache[id].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AtlasPointer TextureSource::getTexture(u32 id)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
if(id >= m_atlaspointer_cache.size())
|
||||||
|
return AtlasPointer(0, NULL);
|
||||||
|
|
||||||
|
return m_atlaspointer_cache[id].a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureSource::buildMainAtlas()
|
||||||
|
{
|
||||||
|
dstream<<"TextureSource::buildMainAtlas()"<<std::endl;
|
||||||
|
|
||||||
|
//return; // Disable (for testing)
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
|
assert(driver);
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
|
||||||
|
|
||||||
|
// Create an image of the right size
|
||||||
|
core::dimension2d<u32> atlas_dim(1024,1024);
|
||||||
|
video::IImage *atlas_img =
|
||||||
|
driver->createImage(video::ECF_A8R8G8B8, atlas_dim);
|
||||||
|
|
||||||
|
/*
|
||||||
|
A list of stuff to add. This should contain as much of the
|
||||||
|
stuff shown in game as possible, to minimize texture changes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::array<std::string> sourcelist;
|
||||||
|
|
||||||
|
sourcelist.push_back("stone.png");
|
||||||
|
sourcelist.push_back("mud.png");
|
||||||
|
sourcelist.push_back("sand.png");
|
||||||
|
sourcelist.push_back("grass.png");
|
||||||
|
sourcelist.push_back("mud.png");
|
||||||
|
sourcelist.push_back("tree.png");
|
||||||
|
sourcelist.push_back("tree_top.png");
|
||||||
|
sourcelist.push_back("water.png");
|
||||||
|
sourcelist.push_back("leaves.png");
|
||||||
|
sourcelist.push_back("mud.png^grass_side.png");
|
||||||
|
|
||||||
|
sourcelist.push_back("stone.png^mineral_coal.png");
|
||||||
|
sourcelist.push_back("stone.png^mineral_iron.png");
|
||||||
|
sourcelist.push_back("mud.png^mineral_coal.png");
|
||||||
|
sourcelist.push_back("mud.png^mineral_iron.png");
|
||||||
|
sourcelist.push_back("sand.png^mineral_coal.png");
|
||||||
|
sourcelist.push_back("sand.png^mineral_iron.png");
|
||||||
|
|
||||||
|
/*
|
||||||
|
First pass: generate almost everything
|
||||||
|
*/
|
||||||
|
core::position2d<s32> pos_in_atlas(0,0);
|
||||||
|
for(u32 i=0; i<sourcelist.size(); i++)
|
||||||
|
{
|
||||||
|
std::string name = sourcelist[i];
|
||||||
|
|
||||||
|
/*video::IImage *img = driver->createImageFromFile(
|
||||||
|
porting::getDataPath(name.c_str()).c_str());
|
||||||
|
if(img == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = img->getDimension();
|
||||||
|
// Make a copy with the right color format
|
||||||
|
video::IImage *img2 =
|
||||||
|
driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
img->copyTo(img2);
|
||||||
|
img->drop();*/
|
||||||
|
|
||||||
|
// Generate image by name
|
||||||
|
video::IImage *img2 = generate_image_from_scratch(name, driver);
|
||||||
|
core::dimension2d<u32> dim = img2->getDimension();
|
||||||
|
|
||||||
|
// Tile it a few times in the X direction
|
||||||
|
u16 xwise_tiling = 16;
|
||||||
|
for(u32 j=0; j<xwise_tiling; j++)
|
||||||
|
{
|
||||||
|
// Copy the copy to the atlas
|
||||||
|
img2->copyToWithAlpha(atlas_img,
|
||||||
|
pos_in_atlas + v2s32(j*dim.Width,0),
|
||||||
|
core::rect<s32>(v2s32(0,0), dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
img2->drop();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add texture to caches
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Get next id
|
||||||
|
u32 id = m_atlaspointer_cache.size();
|
||||||
|
|
||||||
|
// Create AtlasPointer
|
||||||
|
AtlasPointer ap(id);
|
||||||
|
ap.atlas = NULL; // Set on the second pass
|
||||||
|
ap.pos = v2f((float)pos_in_atlas.X/(float)atlas_dim.Width,
|
||||||
|
(float)pos_in_atlas.Y/(float)atlas_dim.Height);
|
||||||
|
ap.size = v2f((float)dim.Width/(float)atlas_dim.Width,
|
||||||
|
(float)dim.Width/(float)atlas_dim.Height);
|
||||||
|
ap.tiled = xwise_tiling;
|
||||||
|
|
||||||
|
// Create SourceAtlasPointer and add to containers
|
||||||
|
SourceAtlasPointer nap(name, ap, atlas_img, pos_in_atlas, dim);
|
||||||
|
m_atlaspointer_cache.push_back(nap);
|
||||||
|
m_name_to_id.insert(name, id);
|
||||||
|
|
||||||
|
// Increment position
|
||||||
|
pos_in_atlas.Y += dim.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Make texture
|
||||||
|
*/
|
||||||
|
video::ITexture *t = driver->addTexture("__main_atlas__", atlas_img);
|
||||||
|
assert(t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Second pass: set texture pointer in generated AtlasPointers
|
||||||
|
*/
|
||||||
|
for(u32 i=0; i<sourcelist.size(); i++)
|
||||||
|
{
|
||||||
|
std::string name = sourcelist[i];
|
||||||
|
u32 id = m_name_to_id[name];
|
||||||
|
m_atlaspointer_cache[id].a.atlas = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write image to file so that it can be inspected
|
||||||
|
*/
|
||||||
|
driver->writeImageToFile(atlas_img,
|
||||||
|
porting::getDataPath("main_atlas.png").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
video::IImage* generate_image_from_scratch(std::string name,
|
||||||
|
video::IVideoDriver* driver)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: generate_image_from_scratch(): "
|
||||||
|
"name="<<name<<std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the base image
|
||||||
|
*/
|
||||||
|
|
||||||
|
video::IImage *baseimg = NULL;
|
||||||
|
|
||||||
|
char separator = '^';
|
||||||
|
|
||||||
|
// Find last meta separator in name
|
||||||
|
s32 last_separator_position = -1;
|
||||||
|
for(s32 i=name.size()-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
if(name[i] == separator)
|
||||||
|
{
|
||||||
|
last_separator_position = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*dstream<<"INFO: generate_image_from_scratch(): "
|
||||||
|
<<"last_separator_position="<<last_separator_position
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
If separator was found, construct the base name and make the
|
||||||
|
base image using a recursive call
|
||||||
|
*/
|
||||||
|
std::string base_image_name;
|
||||||
|
if(last_separator_position != -1)
|
||||||
|
{
|
||||||
|
// Construct base name
|
||||||
|
base_image_name = name.substr(0, last_separator_position);
|
||||||
|
dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
|
||||||
|
" to get base image, name="<<base_image_name<<std::endl;
|
||||||
|
baseimg = generate_image_from_scratch(base_image_name, driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Parse out the last part of the name of the image and act
|
||||||
|
according to it
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string last_part_of_name = name.substr(last_separator_position+1);
|
||||||
|
dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
|
||||||
|
|
||||||
|
// Generate image according to part of name
|
||||||
|
if(generate_image(last_part_of_name, baseimg, driver) == false)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: generate_image_from_scratch(): "
|
||||||
|
"failed to generate \""<<last_part_of_name<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseimg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
|
video::IVideoDriver* driver)
|
||||||
|
{
|
||||||
|
// Stuff starting with [ are special commands
|
||||||
|
if(part_of_name[0] != '[')
|
||||||
|
{
|
||||||
|
// A normal texture; load it from a file
|
||||||
|
std::string path = porting::getDataPath(part_of_name.c_str());
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
|
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||||
|
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Could not load image \""<<part_of_name
|
||||||
|
<<"\" from path \""<<path<<"\""
|
||||||
|
<<" while building texture"<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If base image is NULL, load as base.
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
|
||||||
|
/*
|
||||||
|
Copy it this way to get an alpha channel.
|
||||||
|
Otherwise images with alpha cannot be blitted on
|
||||||
|
images that don't have alpha in the original file.
|
||||||
|
*/
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
// Else blit on base.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
|
||||||
|
// Size of the copied area
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
//core::dimension2d<u32> dim(16,16);
|
||||||
|
// Position to copy the blitted to in the base image
|
||||||
|
core::position2d<s32> pos_to(0,0);
|
||||||
|
// Position to copy the blitted from in the blitted image
|
||||||
|
core::position2d<s32> pos_from(0,0);
|
||||||
|
// Blit
|
||||||
|
image->copyToWithAlpha(baseimg, pos_to,
|
||||||
|
core::rect<s32>(pos_from, dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
// Drop image
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A special texture modification
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): generating special "
|
||||||
|
<<"modification \""<<part_of_name<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
|
if(part_of_name.substr(0,6) == "[crack")
|
||||||
|
{
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
|
||||||
|
<<"for part_of_name="<<part_of_name
|
||||||
|
<<", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 progression = stoi(part_of_name.substr(6));
|
||||||
|
// Size of the base image
|
||||||
|
core::dimension2d<u32> dim_base = baseimg->getDimension();
|
||||||
|
// Crack will be drawn at this size
|
||||||
|
u32 cracksize = 16;
|
||||||
|
// Size of the crack image
|
||||||
|
core::dimension2d<u32> dim_crack(cracksize,cracksize);
|
||||||
|
// Position to copy the crack from in the crack image
|
||||||
|
core::position2d<s32> pos_other(0, 16 * progression);
|
||||||
|
|
||||||
|
video::IImage *crackimage = driver->createImageFromFile(
|
||||||
|
porting::getDataPath("crack.png").c_str());
|
||||||
|
|
||||||
|
if(crackimage)
|
||||||
|
{
|
||||||
|
/*crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
|
||||||
|
core::rect<s32>(pos_other, dim_base),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);*/
|
||||||
|
|
||||||
|
for(u32 y0=0; y0<dim_base.Height/dim_crack.Height; y0++)
|
||||||
|
for(u32 x0=0; x0<dim_base.Width/dim_crack.Width; x0++)
|
||||||
|
{
|
||||||
|
// Position to copy the crack to in the base image
|
||||||
|
core::position2d<s32> pos_base(x0*cracksize, y0*cracksize);
|
||||||
|
crackimage->copyToWithAlpha(baseimg, pos_base,
|
||||||
|
core::rect<s32>(pos_other, dim_crack),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
crackimage->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(part_of_name.substr(0,8) == "[combine")
|
||||||
|
{
|
||||||
|
// "[combine:16x128:0,0=stone.png:0,16=grass.png"
|
||||||
|
Strfnd sf(part_of_name);
|
||||||
|
sf.next(":");
|
||||||
|
u32 w0 = stoi(sf.next("x"));
|
||||||
|
u32 h0 = stoi(sf.next(":"));
|
||||||
|
dstream<<"INFO: combined w="<<w0<<" h="<<h0<<std::endl;
|
||||||
|
core::dimension2d<u32> dim(w0,h0);
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
while(sf.atend() == false)
|
||||||
|
{
|
||||||
|
u32 x = stoi(sf.next(","));
|
||||||
|
u32 y = stoi(sf.next("="));
|
||||||
|
std::string filename = sf.next(":");
|
||||||
|
dstream<<"INFO: Adding \""<<filename
|
||||||
|
<<"\" to combined ("<<x<<","<<y<<")"
|
||||||
|
<<std::endl;
|
||||||
|
video::IImage *img = driver->createImageFromFile(
|
||||||
|
porting::getDataPath(filename.c_str()).c_str());
|
||||||
|
if(img)
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim = img->getDimension();
|
||||||
|
dstream<<"INFO: Size "<<dim.Width
|
||||||
|
<<"x"<<dim.Height<<std::endl;
|
||||||
|
core::position2d<s32> pos_base(x, y);
|
||||||
|
video::IImage *img2 =
|
||||||
|
driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
img->copyTo(img2);
|
||||||
|
img->drop();
|
||||||
|
img2->copyToWithAlpha(baseimg, pos_base,
|
||||||
|
core::rect<s32>(v2s32(0,0), dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
img2->drop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: img==NULL"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(part_of_name.substr(0,12) == "[progressbar")
|
||||||
|
{
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
|
||||||
|
<<"for part_of_name="<<part_of_name
|
||||||
|
<<", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float value = stof(part_of_name.substr(12));
|
||||||
|
make_progressbar(value, baseimg);
|
||||||
|
}
|
||||||
|
// "[noalpha:filename.png"
|
||||||
|
// Use an image without it's alpha channel
|
||||||
|
else if(part_of_name.substr(0,8) == "[noalpha")
|
||||||
|
{
|
||||||
|
if(baseimg != NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL "
|
||||||
|
<<"for part_of_name="<<part_of_name
|
||||||
|
<<", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename = part_of_name.substr(9);
|
||||||
|
|
||||||
|
std::string path = porting::getDataPath(filename.c_str());
|
||||||
|
|
||||||
|
dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
|
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||||
|
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): Loading path \""
|
||||||
|
<<path<<"\" failed"<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
|
||||||
|
// Set alpha to full
|
||||||
|
for(u32 y=0; y<dim.Height; y++)
|
||||||
|
for(u32 x=0; x<dim.Width; x++)
|
||||||
|
{
|
||||||
|
video::SColor c = image->getPixel(x,y);
|
||||||
|
c.setAlpha(255);
|
||||||
|
image->setPixel(x,y,c);
|
||||||
|
}
|
||||||
|
// Blit
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureIdDirect(): Invalid "
|
||||||
|
" modification: \""<<part_of_name<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_progressbar(float value, video::IImage *image)
|
||||||
|
{
|
||||||
|
if(image == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
core::dimension2d<u32> size = image->getDimension();
|
||||||
|
|
||||||
|
u32 barheight = 1;
|
||||||
|
u32 barpad_x = 1;
|
||||||
|
u32 barpad_y = 1;
|
||||||
|
u32 barwidth = size.Width - barpad_x*2;
|
||||||
|
v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
|
||||||
|
|
||||||
|
u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
|
||||||
|
|
||||||
|
video::SColor active(255,255,0,0);
|
||||||
|
video::SColor inactive(255,0,0,0);
|
||||||
|
for(u32 x0=0; x0<barwidth; x0++)
|
||||||
|
{
|
||||||
|
video::SColor *c;
|
||||||
|
if(x0 < barvalue_i)
|
||||||
|
c = &active;
|
||||||
|
else
|
||||||
|
c = &inactive;
|
||||||
|
u32 x = x0 + barpos.X;
|
||||||
|
for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
|
||||||
|
{
|
||||||
|
image->setPixel(x,y, *c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
219
src/tile.h
219
src/tile.h
|
@ -21,10 +21,208 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#define TILE_HEADER
|
#define TILE_HEADER
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
//#include "utility.h"
|
#include "threads.h"
|
||||||
#include "texture.h"
|
#include "utility.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Specifies a texture in an atlas.
|
||||||
|
|
||||||
|
This is used to specify single textures also.
|
||||||
|
|
||||||
|
This has been designed to be small enough to be thrown around a lot.
|
||||||
|
*/
|
||||||
|
struct AtlasPointer
|
||||||
|
{
|
||||||
|
u32 id; // Texture id
|
||||||
|
video::ITexture *atlas; // Atlas in where the texture is
|
||||||
|
v2f pos; // Position in atlas
|
||||||
|
v2f size; // Size in atlas
|
||||||
|
u16 tiled; // X-wise tiling count. If 0, width of atlas is width of image.
|
||||||
|
|
||||||
|
AtlasPointer(
|
||||||
|
u16 id_,
|
||||||
|
video::ITexture *atlas_=NULL,
|
||||||
|
v2f pos_=v2f(0,0),
|
||||||
|
v2f size_=v2f(1,1),
|
||||||
|
u16 tiled_=1
|
||||||
|
):
|
||||||
|
id(id_),
|
||||||
|
atlas(atlas_),
|
||||||
|
pos(pos_),
|
||||||
|
size(size_),
|
||||||
|
tiled(tiled_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const AtlasPointer &other)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
id == other.id
|
||||||
|
);
|
||||||
|
/*return (
|
||||||
|
id == other.id &&
|
||||||
|
atlas == other.atlas &&
|
||||||
|
pos == other.pos &&
|
||||||
|
size == other.size &&
|
||||||
|
tiled == other.tiled
|
||||||
|
);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
float x0(){ return pos.X; }
|
||||||
|
float x1(){ return pos.X + size.X; }
|
||||||
|
float y0(){ return pos.Y; }
|
||||||
|
float y1(){ return pos.Y + size.Y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
An internal variant of the former with more data.
|
||||||
|
*/
|
||||||
|
struct SourceAtlasPointer
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
AtlasPointer a;
|
||||||
|
video::IImage *atlas_img; // The source image of the atlas
|
||||||
|
// Integer variants of position and size
|
||||||
|
v2s32 intpos;
|
||||||
|
v2u32 intsize;
|
||||||
|
|
||||||
|
SourceAtlasPointer(
|
||||||
|
const std::string &name_,
|
||||||
|
AtlasPointer a_=AtlasPointer(0, NULL),
|
||||||
|
video::IImage *atlas_img_=NULL,
|
||||||
|
v2s32 intpos_=v2s32(0,0),
|
||||||
|
v2u32 intsize_=v2u32(0,0)
|
||||||
|
):
|
||||||
|
name(name_),
|
||||||
|
a(a_),
|
||||||
|
atlas_img(atlas_img_),
|
||||||
|
intpos(intpos_),
|
||||||
|
intsize(intsize_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Creates and caches textures.
|
||||||
|
*/
|
||||||
|
class TextureSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureSource(IrrlichtDevice *device);
|
||||||
|
~TextureSource();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Processes queued texture requests from other threads.
|
||||||
|
|
||||||
|
Shall be called from the main thread.
|
||||||
|
*/
|
||||||
|
void processQueue();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example case:
|
||||||
|
Now, assume a texture with the id 1 exists, and has the name
|
||||||
|
"stone.png^mineral1".
|
||||||
|
Then a random thread calls getTextureId for a texture called
|
||||||
|
"stone.png^mineral1^crack0".
|
||||||
|
...Now, WTF should happen? Well:
|
||||||
|
- getTextureId strips off stuff recursively from the end until
|
||||||
|
the remaining part is found, or nothing is left when
|
||||||
|
something is stripped out
|
||||||
|
|
||||||
|
But it is slow to search for textures by names and modify them
|
||||||
|
like that?
|
||||||
|
- ContentFeatures is made to contain ids for the basic plain
|
||||||
|
textures
|
||||||
|
- Crack textures can be slow by themselves, but the framework
|
||||||
|
must be fast.
|
||||||
|
|
||||||
|
Example case #2:
|
||||||
|
- Assume a texture with the id 1 exists, and has the name
|
||||||
|
"stone.png^mineral1" and is specified as a part of some atlas.
|
||||||
|
- Now MapBlock::getNodeTile() stumbles upon a node which uses
|
||||||
|
texture id 1, and finds out that NODEMOD_CRACK must be applied
|
||||||
|
with progression=0
|
||||||
|
- It finds out the name of the texture with getTextureName(1),
|
||||||
|
appends "^crack0" to it and gets a new texture id with
|
||||||
|
getTextureId("stone.png^mineral1^crack0")
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets a texture id from cache or
|
||||||
|
- if main thread, from getTextureIdDirect
|
||||||
|
- if other thread, adds to request queue and waits for main thread
|
||||||
|
*/
|
||||||
|
u32 getTextureId(const std::string &name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example names:
|
||||||
|
"stone.png"
|
||||||
|
"stone.png^crack2"
|
||||||
|
"stone.png^blit:mineral_coal.png"
|
||||||
|
"stone.png^blit:mineral_coal.png^crack1"
|
||||||
|
|
||||||
|
- If texture specified by name is found from cache, return the
|
||||||
|
cached id.
|
||||||
|
- Otherwise generate the texture, add to cache and return id.
|
||||||
|
Recursion is used to find out the largest found part of the
|
||||||
|
texture and continue based on it.
|
||||||
|
|
||||||
|
The id 0 points to a NULL texture. It is returned in case of error.
|
||||||
|
*/
|
||||||
|
u32 getTextureIdDirect(const std::string &name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds out the name of a cached texture.
|
||||||
|
*/
|
||||||
|
std::string getTextureName(u32 id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If texture specified by the name pointed by the id doesn't
|
||||||
|
exist, create it, then return the cached texture.
|
||||||
|
|
||||||
|
Can be called from any thread. If called from some other thread
|
||||||
|
and not found in cache, the call is queued to the main thread
|
||||||
|
for processing.
|
||||||
|
*/
|
||||||
|
AtlasPointer getTexture(u32 id);
|
||||||
|
|
||||||
|
AtlasPointer getTexture(const std::string &name)
|
||||||
|
{
|
||||||
|
return getTexture(getTextureId(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
Build the main texture atlas which contains most of the
|
||||||
|
textures.
|
||||||
|
|
||||||
|
This is called by the constructor.
|
||||||
|
*/
|
||||||
|
void buildMainAtlas();
|
||||||
|
|
||||||
|
// The id of the thread that is allowed to use irrlicht directly
|
||||||
|
threadid_t m_main_thread;
|
||||||
|
// The irrlicht device
|
||||||
|
IrrlichtDevice *m_device;
|
||||||
|
|
||||||
|
// A texture id is index in this array.
|
||||||
|
// The first position contains a NULL texture.
|
||||||
|
core::array<SourceAtlasPointer> m_atlaspointer_cache;
|
||||||
|
// Maps a texture name to an index in the former.
|
||||||
|
core::map<std::string, u32> m_name_to_id;
|
||||||
|
// The two former containers are behind this mutex
|
||||||
|
JMutex m_atlaspointer_cache_mutex;
|
||||||
|
|
||||||
|
// Main texture atlas. This is filled at startup and is then not touched.
|
||||||
|
video::IImage *m_main_atlas_image;
|
||||||
|
video::ITexture *m_main_atlas_texture;
|
||||||
|
|
||||||
|
// Queued texture fetches (to be processed by the main thread)
|
||||||
|
RequestQueue<std::string, u32, u8, u8> m_get_texture_queue;
|
||||||
|
};
|
||||||
|
|
||||||
enum MaterialType{
|
enum MaterialType{
|
||||||
MATERIAL_ALPHA_NONE,
|
MATERIAL_ALPHA_NONE,
|
||||||
MATERIAL_ALPHA_VERTEX,
|
MATERIAL_ALPHA_VERTEX,
|
||||||
|
@ -38,12 +236,17 @@ enum MaterialType{
|
||||||
/*
|
/*
|
||||||
This fully defines the looks of a tile.
|
This fully defines the looks of a tile.
|
||||||
The SMaterial of a tile is constructed according to this.
|
The SMaterial of a tile is constructed according to this.
|
||||||
|
|
||||||
|
TODO: Change this to use an AtlasPointer
|
||||||
*/
|
*/
|
||||||
struct TileSpec
|
struct TileSpec
|
||||||
{
|
{
|
||||||
TileSpec():
|
TileSpec():
|
||||||
|
texture(0),
|
||||||
alpha(255),
|
alpha(255),
|
||||||
material_type(MATERIAL_ALPHA_NONE),
|
material_type(MATERIAL_ALPHA_NONE),
|
||||||
|
// Use this so that leaves don't need a separate material
|
||||||
|
//material_type(MATERIAL_ALPHA_SIMPLE),
|
||||||
material_flags(
|
material_flags(
|
||||||
MATERIAL_FLAG_BACKFACE_CULLING
|
MATERIAL_FLAG_BACKFACE_CULLING
|
||||||
)
|
)
|
||||||
|
@ -53,7 +256,7 @@ struct TileSpec
|
||||||
bool operator==(TileSpec &other)
|
bool operator==(TileSpec &other)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
spec == other.spec &&
|
texture == other.texture &&
|
||||||
alpha == other.alpha &&
|
alpha == other.alpha &&
|
||||||
material_type == other.material_type &&
|
material_type == other.material_type &&
|
||||||
material_flags == other.material_flags
|
material_flags == other.material_flags
|
||||||
|
@ -80,8 +283,14 @@ struct TileSpec
|
||||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specification of texture
|
// NOTE: Deprecated, i guess?
|
||||||
TextureSpec spec;
|
void setTexturePos(u8 tx_, u8 ty_, u8 tw_, u8 th_)
|
||||||
|
{
|
||||||
|
texture.pos = v2f((float)tx_/256.0, (float)ty_/256.0);
|
||||||
|
texture.size = v2f(((float)tw_ + 1.0)/256.0, ((float)th_ + 1.0)/256.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AtlasPointer texture;
|
||||||
// Vertex alpha
|
// Vertex alpha
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
// Material type
|
// Material type
|
||||||
|
|
Loading…
Reference in New Issue