#include "filesys.h"
#include "utility.h"
#include "settings.h"
+#include "mesh.h"
#include <ICameraSceneNode.h>
#include "log.h"
#include "mapnode.h" // For texture atlas making
return fullpath;
}
+/*
+ An internal variant of AtlasPointer with more data.
+ (well, more like a wrapper)
+*/
+
+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_)
+ {
+ }
+};
+
+/*
+ SourceImageCache: A cache used for storing source images.
+*/
+
+class SourceImageCache
+{
+public:
+ void insert(const std::string &name, video::IImage *img,
+ bool prefer_local, video::IVideoDriver *driver)
+ {
+ assert(img);
+ // Remove old image
+ core::map<std::string, video::IImage*>::Node *n;
+ n = m_images.find(name);
+ if(n){
+ video::IImage *oldimg = n->getValue();
+ if(oldimg)
+ oldimg->drop();
+ }
+ // Try to use local texture instead if asked to
+ if(prefer_local){
+ std::string path = getTexturePath(name.c_str());
+ if(path != ""){
+ video::IImage *img2 = driver->createImageFromFile(path.c_str());
+ if(img2){
+ m_images[name] = img2;
+ return;
+ }
+ }
+ }
+ img->grab();
+ m_images[name] = img;
+ }
+ video::IImage* get(const std::string &name)
+ {
+ core::map<std::string, video::IImage*>::Node *n;
+ n = m_images.find(name);
+ if(n)
+ return n->getValue();
+ return NULL;
+ }
+ // Primarily fetches from cache, secondarily tries to read from filesystem
+ video::IImage* getOrLoad(const std::string &name, IrrlichtDevice *device)
+ {
+ core::map<std::string, video::IImage*>::Node *n;
+ n = m_images.find(name);
+ if(n){
+ n->getValue()->grab(); // Grab for caller
+ return n->getValue();
+ }
+ video::IVideoDriver* driver = device->getVideoDriver();
+ std::string path = getTexturePath(name.c_str());
+ if(path == ""){
+ infostream<<"SourceImageCache::getOrLoad(): No path found for \""
+ <<name<<"\""<<std::endl;
+ return NULL;
+ }
+ infostream<<"SourceImageCache::getOrLoad(): Loading path \""<<path
+ <<"\""<<std::endl;
+ video::IImage *img = driver->createImageFromFile(path.c_str());
+ // Even if could not be loaded, put as NULL
+ //m_images[name] = img;
+ if(img){
+ m_images[name] = img;
+ img->grab(); // Grab for caller
+ }
+ return img;
+ }
+private:
+ core::map<std::string, video::IImage*> m_images;
+};
+
/*
TextureSource
*/
*/
u32 getTextureIdDirect(const std::string &name);
- /*
- Finds out the name of a cached texture.
- */
+ // Finds out the name of a cached texture.
std::string getTextureName(u32 id);
/*
// Gets a separate texture
video::ITexture* getTextureRaw(const std::string &name)
{
- AtlasPointer ap = getTexture(name);
+ AtlasPointer ap = getTexture(name + "^[forcesingle");
return ap.atlas;
}
- /*
- Update new texture pointer and texture coordinates to an
- AtlasPointer based on it's texture id
- */
+ // Update new texture pointer and texture coordinates to an
+ // AtlasPointer based on it's texture id
void updateAP(AtlasPointer &ap);
- /*
- Build the main texture atlas which contains most of the
- textures.
-
- This is called by the constructor.
- */
- void buildMainAtlas(class IGameDef *gamedef);
+ // Processes queued texture requests from other threads.
+ // Shall be called from the main thread.
+ void processQueue();
- /*
- Processes queued texture requests from other threads.
+ // Insert an image into the cache without touching the filesystem.
+ // Shall be called from the main thread.
+ void insertSourceImage(const std::string &name, video::IImage *img);
+
+ // Rebuild images and textures from the current set of source images
+ // Shall be called from the main thread.
+ void rebuildImagesAndTextures();
- Shall be called from the main thread.
- */
- void processQueue();
+ // Build the main texture atlas which contains most of the
+ // textures.
+ void buildMainAtlas(class IGameDef *gamedef);
private:
// The irrlicht device
IrrlichtDevice *m_device;
+ // Cache of source images
+ // This should be only accessed from the main thread
+ SourceImageCache m_sourcecache;
+
// A texture id is index in this array.
// The first position contains a NULL texture.
core::array<SourceAtlasPointer> m_atlaspointer_cache;
{
}
-void TextureSource::processQueue()
-{
- /*
- Fetch textures
- */
- if(m_get_texture_queue.size() > 0)
- {
- GetRequest<std::string, u32, u8, u8>
- request = m_get_texture_queue.pop();
-
- infostream<<"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)
{
//infostream<<"getTextureId(): \""<<name<<"\""<<std::endl;
// Draw a progress bar on the image
void make_progressbar(float value, video::IImage *image);
+// Brighten image
+void brighten(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,
- IrrlichtDevice *device);
+ IrrlichtDevice *device, SourceImageCache *sourcecache);
/*
Generates an image from a full string like
This is used by buildMainAtlas().
*/
video::IImage* generate_image_from_scratch(std::string name,
- IrrlichtDevice *device);
+ IrrlichtDevice *device, SourceImageCache *sourcecache);
/*
This method generates all the textures
n = m_name_to_id.find(name);
if(n != NULL)
{
- infostream<<"getTextureIdDirect(): \""<<name
- <<"\" found in cache"<<std::endl;
+ /*infostream<<"getTextureIdDirect(): \""<<name
+ <<"\" found in cache"<<std::endl;*/
return n->getValue();
}
}
- infostream<<"getTextureIdDirect(): \""<<name
- <<"\" NOT found in cache. Creating it."<<std::endl;
+ /*infostream<<"getTextureIdDirect(): \""<<name
+ <<"\" NOT found in cache. Creating it."<<std::endl;*/
/*
Get the base image
if(image == NULL)
{
- infostream<<"getTextureIdDirect(): NULL image in "
+ infostream<<"getTextureIdDirect(): WARNING: NULL image in "
<<"cache: \""<<base_image_name<<"\""
<<std::endl;
}
//infostream<<"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, m_device) == false)
+ if(!generate_image(last_part_of_name, baseimg, m_device, &m_sourcecache))
{
- infostream<<"getTextureIdDirect(): "
+ errorstream<<"getTextureIdDirect(): "
"failed to generate \""<<last_part_of_name<<"\""
<<std::endl;
}
// If no resulting image, print a warning
if(baseimg == NULL)
{
- infostream<<"getTextureIdDirect(): baseimg is NULL (attempted to"
+ errorstream<<"getTextureIdDirect(): baseimg is NULL (attempted to"
" create texture \""<<name<<"\""<<std::endl;
}
if(id >= m_atlaspointer_cache.size())
{
- infostream<<"TextureSource::getTextureName(): id="<<id
+ errorstream<<"TextureSource::getTextureName(): id="<<id
<<" >= m_atlaspointer_cache.size()="
<<m_atlaspointer_cache.size()<<std::endl;
return "";
ap = ap2;
}
+void TextureSource::processQueue()
+{
+ /*
+ Fetch textures
+ */
+ if(m_get_texture_queue.size() > 0)
+ {
+ GetRequest<std::string, u32, u8, u8>
+ request = m_get_texture_queue.pop();
+
+ /*infostream<<"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);
+ }
+}
+
+void TextureSource::insertSourceImage(const std::string &name, video::IImage *img)
+{
+ //infostream<<"TextureSource::insertSourceImage(): name="<<name<<std::endl;
+
+ assert(get_current_thread_id() == m_main_thread);
+
+ m_sourcecache.insert(name, img, true, m_device->getVideoDriver());
+}
+
+void TextureSource::rebuildImagesAndTextures()
+{
+ JMutexAutoLock lock(m_atlaspointer_cache_mutex);
+
+ /*// Oh well... just clear everything, they'll load sometime.
+ m_atlaspointer_cache.clear();
+ m_name_to_id.clear();*/
+
+ video::IVideoDriver* driver = m_device->getVideoDriver();
+
+ // Remove source images from textures to disable inheriting textures
+ // from existing textures
+ /*for(u32 i=0; i<m_atlaspointer_cache.size(); i++){
+ SourceAtlasPointer *sap = &m_atlaspointer_cache[i];
+ sap->atlas_img->drop();
+ sap->atlas_img = NULL;
+ }*/
+
+ // Recreate textures
+ for(u32 i=0; i<m_atlaspointer_cache.size(); i++){
+ SourceAtlasPointer *sap = &m_atlaspointer_cache[i];
+ video::IImage *img =
+ generate_image_from_scratch(sap->name, m_device, &m_sourcecache);
+ // Create texture from resulting image
+ video::ITexture *t = NULL;
+ if(img)
+ t = driver->addTexture(sap->name.c_str(), img);
+
+ // Replace texture
+ sap->a.atlas = t;
+ sap->a.pos = v2f(0,0);
+ sap->a.size = v2f(1,1);
+ sap->a.tiled = 0;
+ sap->atlas_img = img;
+ sap->intpos = v2s32(0,0);
+ sap->intsize = img->getDimension();
+ }
+}
+
void TextureSource::buildMainAtlas(class IGameDef *gamedef)
{
assert(gamedef->tsrc() == this);
{
std::string name = i.getNode()->getKey();
- /*video::IImage *img = driver->createImageFromFile(
- getTexturePath(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, m_device);
+ video::IImage *img2 = generate_image_from_scratch(name, m_device,
+ &m_sourcecache);
if(img2 == NULL)
{
- infostream<<"TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
+ errorstream<<"TextureSource::buildMainAtlas(): "
+ <<"Couldn't generate image \""<<name<<"\""<<std::endl;
continue;
}
pos_in_atlas.X += column_width + column_padding;
}
- infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
- <<"\" to texture atlas"<<std::endl;
+ /*infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
+ <<"\" to texture atlas"<<std::endl;*/
// Tile it a few times in the X direction
u16 xwise_tiling = column_width / dim.Width;
for(u32 j=0; j<xwise_tiling; j++)
{
// Copy the copy to the atlas
- img2->copyToWithAlpha(atlas_img,
+ /*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->copyTo(atlas_img,
+ pos_in_atlas + v2s32(j*dim.Width,0),
+ core::rect<s32>(v2s32(0,0), dim),
NULL);
}
if(n){
id = n->getValue();
reuse_old_id = true;
+ /*infostream<<"TextureSource::buildMainAtlas(): "
+ <<"Replacing old AtlasPointer"<<std::endl;*/
}
- infostream<<"TextureSource::buildMainAtlas(): "
- <<"Replacing old AtlasPointer"<<std::endl;
// Create AtlasPointer
AtlasPointer ap(id);
}
video::IImage* generate_image_from_scratch(std::string name,
- IrrlichtDevice *device)
+ IrrlichtDevice *device, SourceImageCache *sourcecache)
{
/*infostream<<"generate_image_from_scratch(): "
"\""<<name<<"\""<<std::endl;*/
/*infostream<<"generate_image_from_scratch(): Calling itself recursively"
" to get base image of \""<<name<<"\" = \""
<<base_image_name<<"\""<<std::endl;*/
- baseimg = generate_image_from_scratch(base_image_name, device);
+ baseimg = generate_image_from_scratch(base_image_name, device,
+ sourcecache);
}
/*
//infostream<<"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, device) == false)
+ if(!generate_image(last_part_of_name, baseimg, device, sourcecache))
{
- infostream<<"generate_image_from_scratch(): "
+ errorstream<<"generate_image_from_scratch(): "
"failed to generate \""<<last_part_of_name<<"\""
<<std::endl;
return NULL;
}
bool generate_image(std::string part_of_name, video::IImage *& baseimg,
- IrrlichtDevice *device)
+ IrrlichtDevice *device, SourceImageCache *sourcecache)
{
video::IVideoDriver* driver = device->getVideoDriver();
assert(driver);
// Stuff starting with [ are special commands
- if(part_of_name[0] != '[')
+ if(part_of_name.size() == 0 || part_of_name[0] != '[')
{
- // A normal texture; load it from a file
- std::string path = getTexturePath(part_of_name.c_str());
- /*infostream<<"generate_image(): Loading path \""<<path
- <<"\""<<std::endl;*/
-
- video::IImage *image = driver->createImageFromFile(path.c_str());
+ video::IImage *image = sourcecache->getOrLoad(part_of_name, device);
if(image == NULL)
{
- infostream<<"generate_image(): Could not load image \""
- <<part_of_name<<"\" from path \""<<path<<"\""
- <<" while building texture"<<std::endl;
-
- //return false;
-
- infostream<<"generate_image(): Creating a dummy"
- <<" image for \""<<part_of_name<<"\""<<std::endl;
+ if(part_of_name != ""){
+ errorstream<<"generate_image(): Could not load image \""
+ <<part_of_name<<"\""<<" while building texture"<<std::endl;
+ errorstream<<"generate_image(): Creating a dummy"
+ <<" image for \""<<part_of_name<<"\""<<std::endl;
+ }
// Just create a dummy image
//core::dimension2d<u32> dim(2,2);
{
// A special texture modification
- infostream<<"generate_image(): generating special "
+ /*infostream<<"generate_image(): generating special "
<<"modification \""<<part_of_name<<"\""
- <<std::endl;
+ <<std::endl;*/
/*
This is the simplest of all; it just adds stuff to the
*/
if(part_of_name == "[forcesingle")
{
+ // If base image is NULL, create a random color
+ if(baseimg == NULL)
+ {
+ core::dimension2d<u32> dim(1,1);
+ baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
+ assert(baseimg);
+ baseimg->setPixel(0,0, video::SColor(255,myrand()%256,
+ myrand()%256,myrand()%256));
+ }
}
/*
[crackN
{
if(baseimg == NULL)
{
- infostream<<"generate_image(): baseimg==NULL "
+ errorstream<<"generate_image(): baseimg==NULL "
<<"for part_of_name=\""<<part_of_name
<<"\", cancelling."<<std::endl;
return false;
It is an image with a number of cracking stages
horizontally tiled.
*/
- video::IImage *img_crack = driver->createImageFromFile(
- getTexturePath("crack.png").c_str());
+ video::IImage *img_crack = sourcecache->getOrLoad("crack.png", device);
if(img_crack)
{
infostream<<"Adding \""<<filename
<<"\" to combined ("<<x<<","<<y<<")"
<<std::endl;
- video::IImage *img = driver->createImageFromFile(
- getTexturePath(filename.c_str()).c_str());
+ video::IImage *img = sourcecache->getOrLoad(filename, device);
if(img)
{
core::dimension2d<u32> dim = img->getDimension();
{
if(baseimg == NULL)
{
- infostream<<"generate_image(): baseimg==NULL "
+ errorstream<<"generate_image(): baseimg==NULL "
<<"for part_of_name=\""<<part_of_name
<<"\", cancelling."<<std::endl;
return false;
make_progressbar(value, baseimg);
}
/*
- "[noalpha:filename.png"
- Use an image without it's alpha channel.
- Used for the leaves texture when in old leaves mode, so
- that the transparent parts don't look completely black
- when simple alpha channel is used for rendering.
+ "[brighten"
*/
- else if(part_of_name.substr(0,8) == "[noalpha")
+ else if(part_of_name.substr(0,9) == "[brighten")
{
- if(baseimg != NULL)
+ if(baseimg == NULL)
{
- infostream<<"generate_image(): baseimg!=NULL "
+ errorstream<<"generate_image(): 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 = getTexturePath(filename.c_str());
-
- infostream<<"generate_image(): Loading path \""<<path
- <<"\""<<std::endl;
-
- video::IImage *image = driver->createImageFromFile(path.c_str());
-
- if(image == NULL)
- {
- infostream<<"generate_image(): 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();
- }
+ brighten(baseimg);
}
/*
- "[makealpha:R,G,B:filename.png"
- Use an image with converting one color to transparent.
+ "[noalpha"
+ Make image completely opaque.
+ Used for the leaves texture when in old leaves mode, so
+ that the transparent parts don't look completely black
+ when simple alpha channel is used for rendering.
*/
- else if(part_of_name.substr(0,11) == "[makealpha:")
+ else if(part_of_name.substr(0,8) == "[noalpha")
{
- if(baseimg != NULL)
+ if(baseimg == NULL)
{
- infostream<<"generate_image(): baseimg!=NULL "
+ errorstream<<"generate_image(): baseimg==NULL "
<<"for part_of_name=\""<<part_of_name
<<"\", cancelling."<<std::endl;
return false;
}
- Strfnd sf(part_of_name.substr(11));
- u32 r1 = stoi(sf.next(","));
- u32 g1 = stoi(sf.next(","));
- u32 b1 = stoi(sf.next(":"));
- std::string filename = sf.next("");
-
- std::string path = getTexturePath(filename.c_str());
-
- infostream<<"generate_image(): Loading path \""<<path
- <<"\""<<std::endl;
+ core::dimension2d<u32> dim = baseimg->getDimension();
- video::IImage *image = driver->createImageFromFile(path.c_str());
-
- if(image == NULL)
- {
- infostream<<"generate_image(): Loading path \""
- <<path<<"\" failed"<<std::endl;
- }
- else
+ // Set alpha to full
+ for(u32 y=0; y<dim.Height; y++)
+ for(u32 x=0; x<dim.Width; x++)
{
- core::dimension2d<u32> dim = image->getDimension();
- baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
-
- // Blit
- image->copyTo(baseimg);
-
- image->drop();
-
- for(u32 y=0; y<dim.Height; y++)
- for(u32 x=0; x<dim.Width; x++)
- {
- video::SColor c = baseimg->getPixel(x,y);
- u32 r = c.getRed();
- u32 g = c.getGreen();
- u32 b = c.getBlue();
- if(!(r == r1 && g == g1 && b == b1))
- continue;
- c.setAlpha(0);
- baseimg->setPixel(x,y,c);
- }
+ video::SColor c = baseimg->getPixel(x,y);
+ c.setAlpha(255);
+ baseimg->setPixel(x,y,c);
}
}
/*
- "[makealpha2:R,G,B;R2,G2,B2:filename.png"
- Use an image with converting two colors to transparent.
+ "[makealpha:R,G,B"
+ Convert one color to transparent.
*/
- else if(part_of_name.substr(0,12) == "[makealpha2:")
+ else if(part_of_name.substr(0,11) == "[makealpha:")
{
- if(baseimg != NULL)
+ if(baseimg == NULL)
{
- infostream<<"generate_image(): baseimg!=NULL "
+ errorstream<<"generate_image(): baseimg==NULL "
<<"for part_of_name=\""<<part_of_name
<<"\", cancelling."<<std::endl;
return false;
}
- Strfnd sf(part_of_name.substr(12));
+ Strfnd sf(part_of_name.substr(11));
u32 r1 = stoi(sf.next(","));
u32 g1 = stoi(sf.next(","));
- u32 b1 = stoi(sf.next(";"));
- u32 r2 = stoi(sf.next(","));
- u32 g2 = stoi(sf.next(","));
- u32 b2 = stoi(sf.next(":"));
+ u32 b1 = stoi(sf.next(""));
std::string filename = sf.next("");
- std::string path = getTexturePath(filename.c_str());
-
- infostream<<"generate_image(): Loading path \""<<path
- <<"\""<<std::endl;
-
- video::IImage *image = driver->createImageFromFile(path.c_str());
+ core::dimension2d<u32> dim = baseimg->getDimension();
- if(image == NULL)
- {
- infostream<<"generate_image(): Loading path \""
- <<path<<"\" failed"<<std::endl;
- }
- else
- {
- core::dimension2d<u32> dim = image->getDimension();
- baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
-
- // Blit
- image->copyTo(baseimg);
+ /*video::IImage *oldbaseimg = baseimg;
+ baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
+ oldbaseimg->copyTo(baseimg);
+ oldbaseimg->drop();*/
- image->drop();
-
- for(u32 y=0; y<dim.Height; y++)
- for(u32 x=0; x<dim.Width; x++)
- {
- video::SColor c = baseimg->getPixel(x,y);
- u32 r = c.getRed();
- u32 g = c.getGreen();
- u32 b = c.getBlue();
- if(!(r == r1 && g == g1 && b == b1) &&
- !(r == r2 && g == g2 && b == b2))
- continue;
- c.setAlpha(0);
- baseimg->setPixel(x,y,c);
- }
+ // Set alpha to full
+ for(u32 y=0; y<dim.Height; y++)
+ for(u32 x=0; x<dim.Width; x++)
+ {
+ video::SColor c = baseimg->getPixel(x,y);
+ u32 r = c.getRed();
+ u32 g = c.getGreen();
+ u32 b = c.getBlue();
+ if(!(r == r1 && g == g1 && b == b1))
+ continue;
+ c.setAlpha(0);
+ baseimg->setPixel(x,y,c);
}
}
/*
{
if(baseimg != NULL)
{
- infostream<<"generate_image(): baseimg!=NULL "
+ errorstream<<"generate_image(): baseimg!=NULL "
<<"for part_of_name=\""<<part_of_name
<<"\", cancelling."<<std::endl;
return false;
std::string imagename_right = sf.next("{");
#if 1
- //TODO
+ // TODO: Create cube with different textures on different sides
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
{
- infostream<<"generate_image(): EVDF_RENDER_TO_TARGET"
+ errorstream<<"generate_image(): EVDF_RENDER_TO_TARGET"
" not supported. Creating fallback image"<<std::endl;
baseimg = generate_image_from_scratch(
- imagename_top, device);
+ imagename_top, device, sourcecache);
return true;
}
// Generate images for the faces of the cube
video::IImage *img_top = generate_image_from_scratch(
- imagename_top, device);
+ imagename_top, device, sourcecache);
video::IImage *img_left = generate_image_from_scratch(
- imagename_left, device);
+ imagename_left, device, sourcecache);
video::IImage *img_right = generate_image_from_scratch(
- imagename_right, device);
+ imagename_right, device, sourcecache);
assert(img_top && img_left && img_right);
- // TODO: Create textures from images
+ // Create textures from images
video::ITexture *texture_top = driver->addTexture(
(imagename_top + "__temp__").c_str(), img_top);
- assert(texture_top);
-
+ video::ITexture *texture_left = driver->addTexture(
+ (imagename_left + "__temp__").c_str(), img_left);
+ video::ITexture *texture_right = driver->addTexture(
+ (imagename_right + "__temp__").c_str(), img_right);
+ assert(texture_top && texture_left && texture_right);
+
// Drop images
img_top->drop();
img_left->drop();
Create scene:
- An unit cube is centered at 0,0,0
- Camera looks at cube from Y+, Z- towards Y-, Z+
- NOTE: Cube has to be changed to something else because
- the textures cannot be set individually (or can they?)
*/
- scene::ISceneNode* cube = smgr->addCubeSceneNode(1.0, NULL, -1,
- v3f(0,0,0), v3f(0, 45, 0));
+ scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1));
+ setMeshColor(cube, video::SColor(255, 255, 255, 255));
+
+ scene::IMeshSceneNode* cubenode = smgr->addMeshSceneNode(cube, NULL, -1, v3f(0,0,0), v3f(0,45,0), v3f(1,1,1), true);
+ cube->drop();
+
// Set texture of cube
- cube->setMaterialTexture(0, texture_top);
- //cube->setMaterialFlag(video::EMF_LIGHTING, false);
- cube->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
- cube->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
+ cubenode->getMaterial(0).setTexture(0, texture_top);
+ cubenode->getMaterial(1).setTexture(0, texture_top);
+ cubenode->getMaterial(2).setTexture(0, texture_right);
+ cubenode->getMaterial(3).setTexture(0, texture_right);
+ cubenode->getMaterial(4).setTexture(0, texture_left);
+ cubenode->getMaterial(5).setTexture(0, texture_left);
+ cubenode->setMaterialFlag(video::EMF_LIGHTING, true);
+ cubenode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
+ cubenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, true);
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
v3f(0, 1.0, -1.5), v3f(0, 0, 0));
camera->setProjectionMatrix(pm, true);
/*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
- v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
+ v3f(-50, 100, -75), video::SColorf(0.5,0.5,0.5), 1000);
smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));
// Unset render target
driver->setRenderTarget(0, true, true, 0);
- //TODO: Free textures of images
+ // Free textures of images
driver->removeTexture(texture_top);
+ driver->removeTexture(texture_left);
+ driver->removeTexture(texture_right);
// Create image of render target
video::IImage *image = driver->createImage(rtt, v2s32(0,0), dim);
}
else
{
- infostream<<"generate_image(): Invalid "
+ errorstream<<"generate_image(): Invalid "
" modification: \""<<part_of_name<<"\""<<std::endl;
}
}
}
}
+void brighten(video::IImage *image)
+{
+ if(image == NULL)
+ return;
+
+ core::dimension2d<u32> dim = image->getDimension();
+
+ for(u32 y=0; y<dim.Height; y++)
+ for(u32 x=0; x<dim.Width; x++)
+ {
+ video::SColor c = image->getPixel(x,y);
+ c.setRed(0.5 * 255 + 0.5 * (float)c.getRed());
+ c.setGreen(0.5 * 255 + 0.5 * (float)c.getGreen());
+ c.setBlue(0.5 * 255 + 0.5 * (float)c.getBlue());
+ image->setPixel(x,y,c);
+ }
+}
+