Remove texture atlas / AtlasPointer, rename getTextureRaw to getTexture

This commit is contained in:
Kahrl 2013-06-24 04:17:50 +02:00
parent caf0b67e47
commit 8161ab573f
18 changed files with 260 additions and 753 deletions

@ -112,9 +112,6 @@
# Enable smooth lighting with simple ambient occlusion;
# disable for speed or for different looks.
#smooth_lighting = true
# Enable combining mainly used textures to a bigger one for improved speed
# disable if it causes graphics glitches.
#enable_texture_atlas = false
# Path to texture directory. All textures are first searched from here.
#texture_path =
# Video back-end.

@ -320,12 +320,6 @@ Client::Client(
m_playerpos_send_timer = 0.0;
m_ignore_damage_timer = 0.0;
// Build main texture atlas, now that the GameDef exists (that is, us)
if(g_settings->getBool("enable_texture_atlas"))
m_tsrc->buildMainAtlas(this);
else
infostream<<"Not building texture atlas."<<std::endl;
/*
Add local player
*/
@ -2855,11 +2849,6 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
infostream<<"- Rebuilding images and textures"<<std::endl;
m_tsrc->rebuildImagesAndTextures();
// Update texture atlas
infostream<<"- Updating texture atlas"<<std::endl;
if(g_settings->getBool("enable_texture_atlas"))
m_tsrc->buildMainAtlas(this);
// Rebuild shaders
m_shsrc->rebuildShaders();

@ -223,7 +223,7 @@ void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
buf->getMaterial().setTexture(0, tsrc->getTexture("rat.png"));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@ -393,7 +393,7 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
// Initialize with a generated placeholder texture
buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
buf->getMaterial().setTexture(0, tsrc->getTexture(""));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@ -864,7 +864,7 @@ public:
m_spritenode = smgr->addBillboardSceneNode(
NULL, v2f(1, 1), v3f(0,0,0), -1);
m_spritenode->setMaterialTexture(0,
tsrc->getTextureRaw("unknown_node.png"));
tsrc->getTexture("unknown_node.png"));
m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
@ -1273,7 +1273,7 @@ public:
texturestring = m_prop.textures[0];
texturestring += mod;
m_spritenode->setMaterialTexture(0,
tsrc->getTextureRaw(texturestring));
tsrc->getTexture(texturestring));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
@ -1300,7 +1300,7 @@ public:
if(texturestring == "")
continue; // Empty texture string means don't modify that material
texturestring += mod;
video::ITexture* texture = tsrc->getTextureRaw(texturestring);
video::ITexture* texture = tsrc->getTexture(texturestring);
if(!texture)
{
errorstream<<"GenericCAO::updateTextures(): Could not load texture "<<texturestring<<std::endl;
@ -1338,20 +1338,15 @@ public:
if(m_prop.textures.size() > i)
texturestring = m_prop.textures[i];
texturestring += mod;
AtlasPointer ap = tsrc->getTexture(texturestring);
// Get the tile texture and atlas transformation
video::ITexture* atlas = ap.atlas;
v2f pos = ap.pos;
v2f size = ap.size;
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
material.setTexture(0,
tsrc->getTexture(texturestring));
material.getTextureMatrix(0).makeIdentity();
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
@ -1378,7 +1373,7 @@ public:
tname += mod;
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
buf->getMaterial().setTexture(0,
tsrc->getTextureRaw(tname));
tsrc->getTexture(tname));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
@ -1403,7 +1398,7 @@ public:
tname += mod;
scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
buf->getMaterial().setTexture(0,
tsrc->getTextureRaw(tname));
tsrc->getTexture(tname));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest

@ -50,7 +50,7 @@ public:
m_spritenode = smgr->addBillboardSceneNode(
NULL, v2f(1,1), pos, -1);
m_spritenode->setMaterialTexture(0,
env->getGameDef()->tsrc()->getTextureRaw("smoke_puff.png"));
env->getGameDef()->tsrc()->getTexture("smoke_puff.png"));
m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
//m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);

@ -99,7 +99,6 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[20],txc[23]),
};
v2f t;
for(int i = 0; i < tilecount; i++)
{
switch (tiles[i].rotation)
@ -119,49 +118,43 @@ void makeCuboid(MeshCollector *collector, const aabb3f &box,
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
break;
case 4: //FXR90
for (int x = 0; x < 4; x++)
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.X = 1.0 - vertices[i*4+x].TCoords.X;
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
tiles[i].texture.size.Y *= -1;
}
break;
case 5: //FXR270
for (int x = 0; x < 4; x++)
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.X = 1.0 - vertices[i*4+x].TCoords.X;
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
t=vertices[i*4].TCoords;
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
tiles[i].texture.size.Y *= -1;
}
break;
case 6: //FYR90
for (int x = 0; x < 4; x++)
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.Y = 1.0 - vertices[i*4+x].TCoords.Y;
vertices[i*4+x].TCoords.rotateBy(90,irr::core::vector2df(0, 0));
tiles[i].texture.pos.X += tiles[i].texture.size.X;
tiles[i].texture.size.X *= -1;
}
break;
case 7: //FYR270
for (int x = 0; x < 4; x++)
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.Y = 1.0 - vertices[i*4+x].TCoords.Y;
vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
tiles[i].texture.pos.X += tiles[i].texture.size.X;
tiles[i].texture.size.X *= -1;
}
break;
case 8: //FX
tiles[i].texture.pos.Y += tiles[i].texture.size.Y;
tiles[i].texture.size.Y *= -1;
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.X = 1.0 - vertices[i*4+x].TCoords.X;
}
break;
case 9: //FY
tiles[i].texture.pos.X += tiles[i].texture.size.X;
tiles[i].texture.size.X *= -1;
for (int x = 0; x < 4; x++){
vertices[i*4+x].TCoords.Y = 1.0 - vertices[i*4+x].TCoords.Y;
}
break;
default:
break;
}
}
for(s32 j=0; j<24; j++)
{
int tileindex = MYMIN(j/4, tilecount-1);
vertices[j].TCoords *= tiles[tileindex].texture.size;
vertices[j].TCoords += tiles[tileindex].texture.pos;
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
for(s32 j=0; j<24; j+=4)
@ -218,7 +211,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
*/
TileSpec tile_liquid = f.special_tiles[0];
TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);
AtlasPointer &pa_liquid = tile_liquid.texture;
bool top_is_same_liquid = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
@ -280,14 +272,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,BS/2,0,0,0, c,
pa_liquid.x0(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2,0,0,0, c,
pa_liquid.x1(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
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,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
};
/*
@ -359,14 +347,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
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,0),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
};
v3f offset(p.X*BS, p.Y*BS + (-0.5+node_liquid_level)*BS, p.Z*BS);
@ -386,7 +370,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
*/
TileSpec tile_liquid = f.special_tiles[0];
TileSpec tile_liquid_bfculled = f.special_tiles[1];
AtlasPointer &pa_liquid = tile_liquid.texture;
bool top_is_same_liquid = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
@ -566,14 +549,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
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,0),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
};
/*
@ -647,14 +626,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y1()),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
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,0),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,0),
};
// To get backface culling right, the vertices need to go
@ -725,7 +700,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
case NDT_GLASSLIKE:
{
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -741,14 +715,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// The face at Z+
video::S3DVertex vertices[4] = {
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
ap.x0(), ap.y1()),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
ap.x1(), ap.y0()),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
ap.x0(), ap.y0()),
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,0),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),
};
// Rotations in the g_6dirs format
@ -910,7 +880,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
TileSpec tile_leaves = getNodeTile(n, p,
v3s16(0,0,0), data);
AtlasPointer pa_leaves = tile_leaves.texture;
u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -945,22 +914,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
// Wall at X+ of node
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
ap.x0(), ap.y1()),
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
ap.x1(), ap.y0()),
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
ap.x0(), ap.y0()),
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
};
for(s32 i=0; i<4; i++)
@ -990,7 +953,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
TileSpec tile = getNodeTileN(n, p, 0, data);
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -999,14 +961,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Wall at X+ of node
video::S3DVertex vertices[4] =
{
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
ap.x0(), ap.y0()),
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
ap.x1(), ap.y0()),
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
ap.x0(), ap.y1()),
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 0,0),
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 1,0),
video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 0,1),
};
v3s16 dir = n.getWallMountedDir(nodedef);
@ -1037,7 +995,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
TileSpec tile = getNodeTileN(n, p, 0, data);
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -1046,16 +1003,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2*f.visual_scale,-BS/2,0, 0,0,0, c,
ap.x0(), ap.y1()),
video::S3DVertex( BS/2*f.visual_scale,-BS/2,0, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex(-BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, 0,1),
video::S3DVertex( BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, 1,1),
video::S3DVertex( BS/2*f.visual_scale,
-BS/2 + f.visual_scale*BS,0, 0,0,0, c,
ap.x1(), ap.y0()),
-BS/2 + f.visual_scale*BS,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2*f.visual_scale,
-BS/2 + f.visual_scale*BS,0, 0,0,0, c,
ap.x0(), ap.y0()),
-BS/2 + f.visual_scale*BS,0, 0,0,0, c, 0,0),
};
if(j == 0)
@ -1088,9 +1041,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// A hack to put wood the right way around in the posts
ITextureSource *tsrc = data->m_gamedef->tsrc();
std::string texturestring_rot = tsrc->getTextureName(
tile.texture_id) + "^[transformR90";
TileSpec tile_rot = tile;
tile_rot.texture = tsrc->getTexture(tsrc->getTextureName(
tile.texture.id) + "^[transformR90");
tile_rot.texture = tsrc->getTexture(
texturestring_rot,
&tile_rot.texture_id);
u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -1341,8 +1297,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
@ -1354,14 +1308,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
ap.x0(), ap.y1()),
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex(BS/2,g*BS/2+d,BS/2, 0,0,0, c,
ap.x1(), ap.y0()),
video::S3DVertex(-BS/2,g*BS/2+d,BS/2, 0,0,0, c,
ap.x0(), ap.y0()),
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,g*BS/2+d,BS/2, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,g*BS/2+d,BS/2, 0,0,0, c, 0,0),
};
for(s32 i=0; i<4; i++)

@ -94,7 +94,6 @@ void set_default_settings(Settings *settings)
settings->setDefault("new_style_water", "false");
settings->setDefault("new_style_leaves", "true");
settings->setDefault("smooth_lighting", "true");
settings->setDefault("enable_texture_atlas", "false");
settings->setDefault("texture_path", "");
settings->setDefault("shader_path", "");
settings->setDefault("video_driver", "opengl");

@ -65,7 +65,7 @@ FarMesh::FarMesh(
m_materials[1].setFlag(video::EMF_BACK_FACE_CULLING, false);
m_materials[1].setFlag(video::EMF_BILINEAR_FILTER, false);
m_materials[1].setFlag(video::EMF_FOG_ENABLE, false);
m_materials[1].setTexture(0, client->tsrc()->getTextureRaw("treeprop.png"));
m_materials[1].setTexture(0, client->tsrc()->getTexture("treeprop.png"));
m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_materials[1].setFlag(video::EMF_FOG_ENABLE, true);

@ -1345,7 +1345,7 @@ void the_game(
*/
int crack_animation_length = 5;
{
video::ITexture *t = tsrc->getTextureRaw("crack_anylength.png");
video::ITexture *t = tsrc->getTexture("crack_anylength.png");
v2u32 size = t->getOriginalSize();
crack_animation_length = size.Y / size.X;
}
@ -2312,7 +2312,7 @@ void the_game(
else if(event.type == CE_SPAWN_PARTICLE)
{
LocalPlayer* player = client.getEnv().getLocalPlayer();
AtlasPointer ap =
video::ITexture *texture =
gamedef->tsrc()->getTexture(*(event.spawn_particle.texture));
new Particle(gamedef, smgr, player, client.getEnv(),
@ -2321,12 +2321,15 @@ void the_game(
*event.spawn_particle.acc,
event.spawn_particle.expirationtime,
event.spawn_particle.size,
event.spawn_particle.collisiondetection, ap);
event.spawn_particle.collisiondetection,
texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
}
else if(event.type == CE_ADD_PARTICLESPAWNER)
{
LocalPlayer* player = client.getEnv().getLocalPlayer();
AtlasPointer ap =
video::ITexture *texture =
gamedef->tsrc()->getTexture(*(event.add_particlespawner.texture));
new ParticleSpawner(gamedef, smgr, player,
@ -2343,7 +2346,7 @@ void the_game(
event.add_particlespawner.minsize,
event.add_particlespawner.maxsize,
event.add_particlespawner.collisiondetection,
ap,
texture,
event.add_particlespawner.id);
}
else if(event.type == CE_DELETE_PARTICLESPAWNER)

@ -519,7 +519,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
if(type == "image_button_exit")
spec.is_exit = true;
video::ITexture *texture = m_gamedef->tsrc()->getTextureRaw(fimage);
video::ITexture *texture = m_gamedef->tsrc()->getTexture(fimage);
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
e->setUseAlphaChannel(true);
e->setImage(texture);
@ -805,7 +805,7 @@ void GUIFormSpecMenu::drawMenu()
{
const ImageDrawSpec &spec = m_backgrounds[i];
video::ITexture *texture =
m_gamedef->tsrc()->getTextureRaw(spec.name);
m_gamedef->tsrc()->getTexture(spec.name);
// Image size on screen
core::rect<s32> imgrect(0, 0, spec.geom.X, spec.geom.Y);
// Image rectangle on screen
@ -825,7 +825,7 @@ void GUIFormSpecMenu::drawMenu()
{
const ImageDrawSpec &spec = m_images[i];
video::ITexture *texture =
m_gamedef->tsrc()->getTextureRaw(spec.name);
m_gamedef->tsrc()->getTexture(spec.name);
// Image size on screen
core::rect<s32> imgrect(0, 0, spec.geom.X, spec.geom.Y);
// Image rectangle on screen

@ -178,7 +178,7 @@ void Hud::drawLuaElements() {
v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
switch (e->type) {
case HUD_ELEM_IMAGE: {
video::ITexture *texture = tsrc->getTextureRaw(e->text);
video::ITexture *texture = tsrc->getTexture(e->text);
if (!texture)
continue;
@ -228,7 +228,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
const video::SColor color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color};
video::ITexture *stat_texture = tsrc->getTextureRaw(texture);
video::ITexture *stat_texture = tsrc->getTexture(texture);
if (!stat_texture)
return;
@ -306,7 +306,7 @@ void Hud::drawCrosshair() {
return;
if (use_crosshair_image) {
video::ITexture *crosshair = tsrc->getTextureRaw("crosshair.png");
video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
v2u32 size = crosshair->getOriginalSize();
v2s32 lsize = v2s32(displaycenter.X - (size.X / 2),
displaycenter.Y - (size.Y / 2));

@ -341,7 +341,7 @@ public:
cc->inventory_texture = NULL;
if(def->inventory_image != "")
{
cc->inventory_texture = tsrc->getTextureRaw(def->inventory_image);
cc->inventory_texture = tsrc->getTexture(def->inventory_image);
}
else if(def->type == ITEM_NODE)
{
@ -365,7 +365,7 @@ public:
imagename = def->inventory_image;
cc->wield_mesh = createExtrudedMesh(
tsrc->getTextureRaw(imagename),
tsrc->getTexture(imagename),
driver,
def->wield_scale * v3f(40.0, 40.0, 4.0));
if(cc->wield_mesh == NULL)
@ -446,7 +446,7 @@ public:
if(cc->inventory_texture == NULL)
{
cc->inventory_texture =
tsrc->getTextureRaw(f.tiledef[0].name);
tsrc->getTexture(f.tiledef[0].name);
}
}
else

@ -452,6 +452,11 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
// Position is at the center of the cube.
v3f pos = p * BS;
float x0 = 0.0;
float y0 = 0.0;
float w = 1.0;
float h = 1.0;
v3f vertex_pos[4];
v3s16 vertex_dirs[4];
getNodeVertexDirs(dir, vertex_dirs);
@ -488,8 +493,8 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
vertex_dirs[3] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[1];
vertex_dirs[1] = t;
tile.texture.pos.Y += tile.texture.size.Y;
tile.texture.size.Y *= -1;
y0 += h;
h *= -1;
break;
case 5: //FXR270
t = vertex_dirs[0];
@ -497,8 +502,8 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
vertex_dirs[1] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[3];
vertex_dirs[3] = t;
tile.texture.pos.Y += tile.texture.size.Y;
tile.texture.size.Y *= -1;
y0 += h;
h *= -1;
break;
case 6: //FYR90
t = vertex_dirs[0];
@ -506,8 +511,8 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
vertex_dirs[3] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[1];
vertex_dirs[1] = t;
tile.texture.pos.X += tile.texture.size.X;
tile.texture.size.X *= -1;
x0 += w;
w *= -1;
break;
case 7: //FYR270
t = vertex_dirs[0];
@ -515,16 +520,16 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
vertex_dirs[1] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[3];
vertex_dirs[3] = t;
tile.texture.pos.X += tile.texture.size.X;
tile.texture.size.X *= -1;
x0 += w;
w *= -1;
break;
case 8: //FX
tile.texture.pos.Y += tile.texture.size.Y;
tile.texture.size.Y *= -1;
y0 += h;
h *= -1;
break;
case 9: //FY
tile.texture.pos.X += tile.texture.size.X;
tile.texture.size.X *= -1;
x0 += w;
w *= -1;
break;
default:
break;
@ -555,11 +560,6 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
u8 alpha = tile.alpha;
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], normal,
MapBlock_LightColor(alpha, li0, light_source),
core::vector2d<f32>(x0+w*abs_scale, y0+h));
@ -645,12 +645,6 @@ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
if(p == data->m_crack_pos_relative)
{
spec.material_flags |= MATERIAL_FLAG_CRACK;
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
}
// If animated, replace tile texture with one without texture atlas
if(spec.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
{
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
}
return spec;
}
@ -717,7 +711,7 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
u16 tile_index=facedir*16 + dir_i;
TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data);
spec.rotation=dir_to_tile[tile_index + 1];
spec.texture = data->m_gamedef->tsrc()->getTexture(spec.texture.id);
spec.texture = data->m_gamedef->tsrc()->getTexture(spec.texture_id);
return spec;
}
@ -889,23 +883,7 @@ static void updateFastFaceRow(
continuous_tiles_count++;
// 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.
*/
if(tile.texture.atlas != NULL && tile.texture.tiled != 0)
{
if(tile.texture.tiled <= continuous_tiles_count)
end_of_texture = true;
}
// Do this to disable tiling textures
//end_of_texture = true; //DEBUG
if(next_is_different || end_of_texture)
if(next_is_different)
{
/*
Create a face if there should be one
@ -1060,7 +1038,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
const u16 indices[] = {0,1,2,2,3,0};
const u16 indices_alternate[] = {0,1,3,2,3,1};
if(f.tile.texture.atlas == NULL)
if(f.tile.texture == NULL)
continue;
const u16 *indices_p = indices;
@ -1112,7 +1090,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
if(p.tile.material_flags & MATERIAL_FLAG_CRACK)
{
ITextureSource *tsrc = data->m_gamedef->tsrc();
std::string crack_basename = tsrc->getTextureName(p.tile.texture.id);
std::string crack_basename = tsrc->getTextureName(p.tile.texture_id);
if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
crack_basename += "^[cracko";
else
@ -1137,9 +1115,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
}
// Replace tile texture with the first animation frame
std::ostringstream os(std::ios::binary);
os<<tsrc->getTextureName(p.tile.texture.id);
os<<tsrc->getTextureName(p.tile.texture_id);
os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0";
p.tile.texture = tsrc->getTexture(os.str());
p.tile.texture = tsrc->getTexture(
os.str(),
&p.tile.texture_id);
}
// - Classic lighting (shaders handle this by themselves)
if(!enable_shaders)
@ -1173,7 +1153,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
material.MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material.setTexture(0, p.tile.texture.atlas);
material.setTexture(0, p.tile.texture);
if(enable_shaders)
p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2, shadermat3);
else
@ -1259,8 +1239,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
ITextureSource *tsrc = m_gamedef->getTextureSource();
std::ostringstream os;
os<<basename<<crack;
AtlasPointer ap = tsrc->getTexture(os.str());
buf->getMaterial().setTexture(0, ap.atlas);
buf->getMaterial().setTexture(0,
tsrc->getTexture(os.str()));
}
m_last_crack = crack;
@ -1287,11 +1267,10 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
// Create new texture name from original
std::ostringstream os(std::ios::binary);
os<<tsrc->getTextureName(tile.texture.id);
os<<tsrc->getTextureName(tile.texture_id);
os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
// Set the texture
AtlasPointer ap = tsrc->getTexture(os.str());
buf->getMaterial().setTexture(0, ap.atlas);
buf->getMaterial().setTexture(0, tsrc->getTexture(os.str()));
}
// Day-night transition

@ -674,7 +674,9 @@ public:
// Tiles (fill in f->tiles[])
for(u16 j=0; j<6; j++){
// Texture
f->tiles[j].texture = tsrc->getTexture(tiledef[j].name);
f->tiles[j].texture = tsrc->getTexture(
tiledef[j].name,
&f->tiles[j].texture_id);
// Alpha
f->tiles[j].alpha = f->alpha;
// Material type
@ -689,10 +691,9 @@ public:
if(f->tiles[j].material_flags &
MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
{
// Get raw texture size to determine frame count by
// Get texture size to determine frame count by
// aspect ratio
video::ITexture *t = tsrc->getTextureRaw(tiledef[j].name);
v2u32 size = t->getOriginalSize();
v2u32 size = f->tiles[j].texture->getOriginalSize();
int frame_height = (float)size.X /
(float)tiledef[j].animation.aspect_w *
(float)tiledef[j].animation.aspect_h;
@ -715,8 +716,9 @@ public:
// Special tiles (fill in f->special_tiles[])
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
// Texture
f->special_tiles[j].texture =
tsrc->getTexture(f->tiledef_special[j].name);
f->special_tiles[j].texture = tsrc->getTexture(
f->tiledef_special[j].name,
&f->special_tiles[j].texture_id);
// Alpha
f->special_tiles[j].alpha = f->alpha;
// Material type
@ -731,10 +733,9 @@ public:
if(f->special_tiles[j].material_flags &
MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
{
// Get raw texture size to determine frame count by
// Get texture size to determine frame count by
// aspect ratio
video::ITexture *t = tsrc->getTextureRaw(f->tiledef_special[j].name);
v2u32 size = t->getOriginalSize();
v2u32 size = f->special_tiles[j].texture->getOriginalSize();
int frame_height = (float)size.X /
(float)f->tiledef_special[j].animation.aspect_w *
(float)f->tiledef_special[j].animation.aspect_h;

@ -312,7 +312,6 @@ public:
/*
Update tile textures to latest return values of TextueSource.
Call after updating the texture atlas of a TextureSource.
*/
virtual void updateTextures(ITextureSource *tsrc)=0;

@ -57,7 +57,9 @@ Particle::Particle(
float expirationtime,
float size,
bool collisiondetection,
AtlasPointer ap
video::ITexture *texture,
v2f texpos,
v2f texsize
):
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
{
@ -70,8 +72,9 @@ Particle::Particle(
m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
m_material.setFlag(video::EMF_FOG_ENABLE, true);
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_material.setTexture(0, ap.atlas);
m_ap = ap;
m_material.setTexture(0, texture);
m_texpos = texpos;
m_texsize = texsize;
// Particle related
@ -180,14 +183,19 @@ void Particle::updateLight(ClientEnvironment &env)
void Particle::updateVertices()
{
video::SColor c(255, m_light, m_light, m_light);
f32 tx0 = m_texpos.X;
f32 tx1 = m_texpos.X + m_texsize.X;
f32 ty0 = m_texpos.Y;
f32 ty1 = m_texpos.Y + m_texsize.Y;
m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
c, m_ap.x0(), m_ap.y1());
c, tx0, ty1);
m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0,
c, m_ap.x1(), m_ap.y1());
c, tx1, ty1);
m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0,
c, m_ap.x1(), m_ap.y0());
c, tx1, ty0);
m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0,
c ,m_ap.x0(), m_ap.y0());
c, tx0, ty0);
for(u16 i=0; i<4; i++)
{
@ -248,19 +256,19 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
{
// Texture
u8 texid = myrand_range(0,5);
AtlasPointer ap = tiles[texid].texture;
video::ITexture *texture = tiles[texid].texture;
// Only use first frame of animated texture
f32 ymax = 1;
if(tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
ymax /= tiles[texid].animation_frame_count;
float size = rand()%64/512.;
float visual_size = BS*size;
float texsize = size*2;
float x1 = ap.x1();
float y1 = ap.y1();
ap.size.X = (ap.x1() - ap.x0()) * texsize;
ap.size.Y = (ap.x1() - ap.x0()) * texsize;
ap.pos.X = ap.x0() + (x1 - ap.x0()) * ((rand()%64)/64.-texsize);
ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
v2f texsize(size*2, ymax*size*2);
v2f texpos;
texpos.X = ((rand()%64)/64.-texsize.X);
texpos.Y = ymax*((rand()%64)/64.-texsize.Y);
// Physics
v3f velocity( (rand()%100/50.-1)/1.5,
@ -285,7 +293,9 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
rand()%100/100., // expiration time
visual_size,
true,
ap);
texture,
texpos,
texsize);
}
/*
@ -296,7 +306,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
u16 amount, float time,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize,
bool collisiondetection, AtlasPointer ap, u32 id)
bool collisiondetection, video::ITexture *texture, u32 id)
{
m_gamedef = gamedef;
m_smgr = smgr;
@ -314,7 +324,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
m_minsize = minsize;
m_maxsize = maxsize;
m_collisiondetection = collisiondetection;
m_ap = ap;
m_texture = texture;
m_time = 0;
for (u16 i = 0; i<=m_amount; i++)
@ -362,7 +372,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
exptime,
size,
m_collisiondetection,
m_ap);
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
m_spawntimes.erase(i);
}
else
@ -398,7 +410,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
exptime,
size,
m_collisiondetection,
m_ap);
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
}
}
}

@ -42,7 +42,9 @@ class Particle : public scene::ISceneNode
float expirationtime,
float size,
bool collisiondetection,
AtlasPointer texture
video::ITexture *texture,
v2f texpos,
v2f texsize
);
~Particle();
@ -81,16 +83,13 @@ private:
core::aabbox3d<f32> m_box;
core::aabbox3d<f32> m_collisionbox;
video::SMaterial m_material;
v2f m_texpos;
v2f m_texsize;
v3f m_pos;
v3f m_velocity;
v3f m_acceleration;
float tex_x0;
float tex_x1;
float tex_y0;
float tex_y1;
LocalPlayer *m_player;
float m_size;
AtlasPointer m_ap;
u8 m_light;
bool m_collisiondetection;
};
@ -109,7 +108,7 @@ class ParticleSpawner
float minexptime, float maxexptime,
float minsize, float maxsize,
bool collisiondetection,
AtlasPointer ap,
video::ITexture *texture,
u32 id);
~ParticleSpawner();
@ -136,7 +135,7 @@ class ParticleSpawner
float m_maxexptime;
float m_minsize;
float m_maxsize;
AtlasPointer m_ap;
video::ITexture *m_texture;
std::vector<float> m_spawntimes;
bool m_collisiondetection;
};

@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mesh.h"
#include <ICameraSceneNode.h>
#include "log.h"
#include "mapnode.h" // For texture atlas making
#include "nodedef.h" // For texture atlas making
#include "gamedef.h"
#include "util/string.h"
#include "util/container.h"
@ -165,31 +163,23 @@ std::string getTexturePath(const std::string &filename)
}
/*
An internal variant of AtlasPointer with more data.
(well, more like a wrapper)
Stores internal information about a texture.
*/
struct SourceAtlasPointer
struct TextureInfo
{
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;
video::ITexture *texture;
video::IImage *img; // The source image
SourceAtlasPointer(
TextureInfo(
const std::string &name_,
AtlasPointer a_=AtlasPointer(0, NULL),
video::IImage *atlas_img_=NULL,
v2s32 intpos_=v2s32(0,0),
v2u32 intsize_=v2u32(0,0)
video::ITexture *texture_=NULL,
video::IImage *img_=NULL
):
name(name_),
a(a_),
atlas_img(atlas_img_),
intpos(intpos_),
intsize(intsize_)
texture(texture_),
img(img_)
{
}
};
@ -307,7 +297,7 @@ public:
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.
"stone.png^mineral_coal.png".
- Now getNodeTile() stumbles upon a node which uses
texture id 1, and determines that MATERIAL_FLAG_CRACK
must be applied to the tile
@ -315,7 +305,7 @@ public:
has received the current crack level 0 from the client. 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").
getTextureId("stone.png^mineral_coal.png^crack0").
*/
@ -354,25 +344,9 @@ public:
and not found in cache, the call is queued to the main thread
for processing.
*/
AtlasPointer getTexture(u32 id);
video::ITexture* getTexture(u32 id);
AtlasPointer getTexture(const std::string &name)
{
return getTexture(getTextureId(name));
}
// Gets a separate texture
video::ITexture* getTextureRaw(const std::string &name)
{
AtlasPointer ap = getTexture(name + m_forcesingle_suffix);
return ap.atlas;
}
// Gets a separate texture atlas pointer
AtlasPointer getTextureRawAP(const AtlasPointer &ap)
{
return getTexture(getTextureName(ap.id) + m_forcesingle_suffix);
}
video::ITexture* getTexture(const std::string &name, u32 *id);
// Returns a pointer to the irrlicht device
virtual IrrlichtDevice* getDevice()
@ -380,10 +354,6 @@ public:
return m_device;
}
// Update new texture pointer and texture coordinates to an
// AtlasPointer based on it's texture id
void updateAP(AtlasPointer &ap);
bool isKnownSourceImage(const std::string &name)
{
bool is_known = false;
@ -408,10 +378,6 @@ public:
// Shall be called from the main thread.
void rebuildImagesAndTextures();
// Build the main texture atlas which contains most of the
// textures.
void buildMainAtlas(class IGameDef *gamedef);
private:
// The id of the thread that is allowed to use irrlicht directly
@ -428,16 +394,11 @@ private:
// A texture id is index in this array.
// The first position contains a NULL texture.
std::vector<SourceAtlasPointer> m_atlaspointer_cache;
std::vector<TextureInfo> m_textureinfo_cache;
// Maps a texture name to an index in the former.
std::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;
std::string m_forcesingle_suffix;
JMutex m_textureinfo_cache_mutex;
// Queued texture fetches (to be processed by the main thread)
RequestQueue<std::string, u32, u8, u8> m_get_texture_queue;
@ -453,18 +414,16 @@ IWritableTextureSource* createTextureSource(IrrlichtDevice *device)
}
TextureSource::TextureSource(IrrlichtDevice *device):
m_device(device),
m_main_atlas_image(NULL),
m_main_atlas_texture(NULL)
m_device(device)
{
assert(m_device);
m_atlaspointer_cache_mutex.Init();
m_textureinfo_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(""));
// Add a NULL TextureInfo as the first index, named ""
m_textureinfo_cache.push_back(TextureInfo(""));
m_name_to_id[""] = 0;
}
@ -474,21 +433,19 @@ TextureSource::~TextureSource()
unsigned int textures_before = driver->getTextureCount();
for (std::vector<SourceAtlasPointer>::iterator iter =
m_atlaspointer_cache.begin(); iter != m_atlaspointer_cache.end();
iter++)
for (std::vector<TextureInfo>::iterator iter =
m_textureinfo_cache.begin();
iter != m_textureinfo_cache.end(); iter++)
{
video::ITexture *t = driver->getTexture(iter->name.c_str());
//cleanup texture
if (t)
driver->removeTexture(t);
if (iter->texture)
driver->removeTexture(iter->texture);
//cleanup source image
if (iter->atlas_img)
iter->atlas_img->drop();
if (iter->img)
iter->img->drop();
}
m_atlaspointer_cache.clear();
m_textureinfo_cache.clear();
for (std::list<video::ITexture*>::iterator iter =
m_texture_trash.begin(); iter != m_texture_trash.end();
@ -512,7 +469,7 @@ u32 TextureSource::getTextureId(const std::string &name)
/*
See if texture already exists
*/
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_cache_mutex);
std::map<std::string, u32>::iterator n;
n = m_name_to_id.find(name);
if(n != m_name_to_id.end())
@ -591,8 +548,6 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
/*
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,
IrrlichtDevice *device, SourceImageCache *sourcecache);
@ -625,7 +580,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
See if texture already exists
*/
{
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_cache_mutex);
std::map<std::string, u32>::iterator n;
n = m_name_to_id.find(name);
@ -693,13 +648,11 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
// If a base image was found, copy it to baseimg
if(base_image_id != 0)
{
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_cache_mutex);
SourceAtlasPointer ap = m_atlaspointer_cache[base_image_id];
TextureInfo *ti = &m_textureinfo_cache[base_image_id];
video::IImage *image = ap.atlas_img;
if(image == NULL)
if(ti->img == NULL)
{
infostream<<"getTextureIdDirect(): WARNING: NULL image in "
<<"cache: \""<<base_image_name<<"\""
@ -707,17 +660,14 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
}
else
{
core::dimension2d<u32> dim = ap.intsize;
core::dimension2d<u32> dim = ti->img->getDimension();
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
core::position2d<s32> pos_to(0,0);
core::position2d<s32> pos_from = ap.intpos;
image->copyTo(
ti->img->copyTo(
baseimg, // target
v2s32(0,0), // position in target
core::rect<s32>(pos_from, dim) // from
core::rect<s32>(v2s32(0,0), dim) // from
);
/*infostream<<"getTextureIdDirect(): Loaded \""
@ -759,19 +709,11 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
Add texture to caches (add NULL textures too)
*/
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_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;
core::dimension2d<u32> baseimg_dim(0,0);
if(baseimg)
baseimg_dim = baseimg->getDimension();
SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg_dim);
m_atlaspointer_cache.push_back(nap);
u32 id = m_textureinfo_cache.size();
TextureInfo ti(name, t, baseimg);
m_textureinfo_cache.push_back(ti);
m_name_to_id[name] = id;
/*infostream<<"getTextureIdDirect(): "
@ -782,34 +724,36 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
std::string TextureSource::getTextureName(u32 id)
{
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_cache_mutex);
if(id >= m_atlaspointer_cache.size())
if(id >= m_textureinfo_cache.size())
{
errorstream<<"TextureSource::getTextureName(): id="<<id
<<" >= m_atlaspointer_cache.size()="
<<m_atlaspointer_cache.size()<<std::endl;
<<" >= m_textureinfo_cache.size()="
<<m_textureinfo_cache.size()<<std::endl;
return "";
}
return m_atlaspointer_cache[id].name;
return m_textureinfo_cache[id].name;
}
AtlasPointer TextureSource::getTexture(u32 id)
video::ITexture* TextureSource::getTexture(u32 id)
{
JMutexAutoLock lock(m_atlaspointer_cache_mutex);
JMutexAutoLock lock(m_textureinfo_cache_mutex);
if(id >= m_atlaspointer_cache.size())
return AtlasPointer(0, NULL);
if(id >= m_textureinfo_cache.size())
return NULL;
return m_atlaspointer_cache[id].a;
return m_textureinfo_cache[id].texture;
}
void TextureSource::updateAP(AtlasPointer &ap)
video::ITexture* TextureSource::getTexture(const std::string &name, u32 *id)
{
AtlasPointer ap2 = getTexture(ap.id);
ap = ap2;
u32 actual_id = getTextureId(name);
if(id){
*id = actual_id;
}
return getTexture(actual_id);
}
void TextureSource::processQueue()
@ -849,299 +793,29 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
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();*/
JMutexAutoLock lock(m_textureinfo_cache_mutex);
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];
for(u32 i=0; i<m_textureinfo_cache.size(); i++){
TextureInfo *ti = &m_textureinfo_cache[i];
video::IImage *img =
generate_image_from_scratch(sap->name, m_device, &m_sourcecache);
generate_image_from_scratch(ti->name, m_device, &m_sourcecache);
// Create texture from resulting image
video::ITexture *t = NULL;
if(img)
t = driver->addTexture(sap->name.c_str(), img);
video::ITexture *t_old = sap->a.atlas;
t = driver->addTexture(ti->name.c_str(), img);
video::ITexture *t_old = ti->texture;
// 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();
ti->texture = t;
ti->img = img;
if (t_old != 0)
m_texture_trash.push_back(t_old);
}
}
void TextureSource::buildMainAtlas(class IGameDef *gamedef)
{
assert(gamedef->tsrc() == this);
INodeDefManager *ndef = gamedef->ndef();
infostream<<"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> max_dim = driver->getMaxTextureSize();
core::dimension2d<u32> atlas_dim(2048,2048);
atlas_dim.Width = MYMIN(atlas_dim.Width, max_dim.Width);
atlas_dim.Height = MYMIN(atlas_dim.Height, max_dim.Height);
video::IImage *atlas_img =
driver->createImage(video::ECF_A8R8G8B8, atlas_dim);
//assert(atlas_img);
if(atlas_img == NULL)
{
errorstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
"image; not building texture atlas."<<std::endl;
return;
}
/*
Grab list of stuff to include in the texture atlas from the
main content features
*/
std::set<std::string> sourcelist;
for(u16 j=0; j<MAX_CONTENT+1; j++)
{
if(j == CONTENT_IGNORE || j == CONTENT_AIR)
continue;
const ContentFeatures &f = ndef->get(j);
for(u32 i=0; i<6; i++)
{
std::string name = f.tiledef[i].name;
sourcelist.insert(name);
}
}
infostream<<"Creating texture atlas out of textures: ";
for(std::set<std::string>::iterator
i = sourcelist.begin();
i != sourcelist.end(); ++i)
{
std::string name = *i;
infostream<<"\""<<name<<"\" ";
}
infostream<<std::endl;
// Padding to disallow texture bleeding
// (16 needed if mipmapping is used; otherwise less will work too)
s32 padding = 16;
s32 column_padding = 16;
s32 column_width = 256; // Space for 16 pieces of 16x16 textures
/*
First pass: generate almost everything
*/
core::position2d<s32> pos_in_atlas(0,0);
pos_in_atlas.X = column_padding;
pos_in_atlas.Y = padding;
for(std::set<std::string>::iterator
i = sourcelist.begin();
i != sourcelist.end(); ++i)
{
std::string name = *i;
// Generate image by name
video::IImage *img2 = generate_image_from_scratch(name, m_device,
&m_sourcecache);
if(img2 == NULL)
{
errorstream<<"TextureSource::buildMainAtlas(): "
<<"Couldn't generate image \""<<name<<"\""<<std::endl;
continue;
}
core::dimension2d<u32> dim = img2->getDimension();
// Don't add to atlas if image is too large
core::dimension2d<u32> max_size_in_atlas(64,64);
if(dim.Width > max_size_in_atlas.Width
|| dim.Height > max_size_in_atlas.Height)
{
infostream<<"TextureSource::buildMainAtlas(): Not adding "
<<"\""<<name<<"\" because image is large"<<std::endl;
continue;
}
// Wrap columns and stop making atlas if atlas is full
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
{
if(pos_in_atlas.X > (s32)atlas_dim.Width - column_width - column_padding){
errorstream<<"TextureSource::buildMainAtlas(): "
<<"Atlas is full, not adding more textures."
<<std::endl;
break;
}
pos_in_atlas.Y = padding;
pos_in_atlas.X += column_width + column_padding*2;
}
/*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;
if(xwise_tiling > 16) // Limit to 16 (more gives no benefit)
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->copyTo(atlas_img,
pos_in_atlas + v2s32(j*dim.Width,0),
core::rect<s32>(v2s32(0,0), dim),
NULL);
}
// Copy the borders a few times to disallow texture bleeding
for(u32 side=0; side<2; side++) // top and bottom
for(s32 y0=0; y0<padding; y0++)
for(s32 x0=0; x0<(s32)xwise_tiling*(s32)dim.Width; x0++)
{
s32 dst_y;
s32 src_y;
if(side==0)
{
dst_y = y0 + pos_in_atlas.Y + dim.Height;
src_y = pos_in_atlas.Y + dim.Height - 1;
}
else
{
dst_y = -y0 + pos_in_atlas.Y-1;
src_y = pos_in_atlas.Y;
}
s32 x = x0 + pos_in_atlas.X;
video::SColor c = atlas_img->getPixel(x, src_y);
atlas_img->setPixel(x,dst_y,c);
}
for(u32 side=0; side<2; side++) // left and right
for(s32 x0=0; x0<column_padding; x0++)
for(s32 y0=-padding; y0<(s32)dim.Height+padding; y0++)
{
s32 dst_x;
s32 src_x;
if(side==0)
{
dst_x = x0 + pos_in_atlas.X + dim.Width*xwise_tiling;
src_x = pos_in_atlas.X + dim.Width*xwise_tiling - 1;
}
else
{
dst_x = -x0 + pos_in_atlas.X-1;
src_x = pos_in_atlas.X;
}
s32 y = y0 + pos_in_atlas.Y;
s32 src_y = MYMAX((int)pos_in_atlas.Y, MYMIN((int)pos_in_atlas.Y + (int)dim.Height - 1, y));
s32 dst_y = y;
video::SColor c = atlas_img->getPixel(src_x, src_y);
atlas_img->setPixel(dst_x,dst_y,c);
}
img2->drop();
/*
Add texture to caches
*/
bool reuse_old_id = false;
u32 id = m_atlaspointer_cache.size();
// Check old id without fetching a texture
std::map<std::string, u32>::iterator n;
n = m_name_to_id.find(name);
// If it exists, we will replace the old definition
if(n != m_name_to_id.end()){
id = n->second;
reuse_old_id = true;
/*infostream<<"TextureSource::buildMainAtlas(): "
<<"Replacing old AtlasPointer"<<std::endl;*/
}
// 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);
if(reuse_old_id)
m_atlaspointer_cache[id] = nap;
else
m_atlaspointer_cache.push_back(nap);
m_name_to_id[name] = id;
// Increment position
pos_in_atlas.Y += dim.Height + padding * 2;
}
/*
Make texture
*/
video::ITexture *t = driver->addTexture("__main_atlas__", atlas_img);
assert(t);
/*
Second pass: set texture pointer in generated AtlasPointers
*/
for(std::set<std::string>::iterator
i = sourcelist.begin();
i != sourcelist.end(); ++i)
{
std::string name = *i;
if(m_name_to_id.find(name) == m_name_to_id.end())
continue;
u32 id = m_name_to_id[name];
//infostream<<"id of name "<<name<<" is "<<id<<std::endl;
m_atlaspointer_cache[id].a.atlas = t;
}
/*
Write image to file so that it can be inspected
*/
/*std::string atlaspath = porting::path_user
+ DIR_DELIM + "generated_texture_atlas.png";
infostream<<"Removing and writing texture atlas for inspection to "
<<atlaspath<<std::endl;
fs::RecursiveDelete(atlaspath);
driver->writeImageToFile(atlas_img, atlaspath.c_str());*/
m_forcesingle_suffix = "^[forcesingle";
}
video::IImage* generate_image_from_scratch(std::string name,
IrrlichtDevice *device, SourceImageCache *sourcecache)
{
@ -1285,31 +959,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
<<"modification \""<<part_of_name<<"\""
<<std::endl;*/
/*
This is the simplest of all; it just adds stuff to the
name so that a separate texture is created.
It is used to make textures for stuff that doesn't want
to implement getting the texture from a bigger texture
atlas.
*/
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
Adds a cracking texture
*/
else if(part_of_name.substr(0,6) == "[crack")
if(part_of_name.substr(0,6) == "[crack")
{
if(baseimg == NULL)
{

@ -57,69 +57,6 @@ std::string getImagePath(std::string path);
*/
std::string getTexturePath(const std::string &filename);
/*
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():
id(0),
atlas(NULL),
pos(0,0),
size(1,1),
tiled(1)
{}
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) const
{
return (
id == other.id
);
/*return (
id == other.id &&
atlas == other.atlas &&
pos == other.pos &&
size == other.size &&
tiled == other.tiled
);*/
}
bool operator!=(const AtlasPointer &other) const
{
return !(*this == other);
}
float x0(){ return pos.X; }
float x1(){ return pos.X + size.X; }
float y0(){ return pos.Y; }
float y1(){ return pos.Y + size.Y; }
};
/*
TextureSource creates and caches textures.
*/
@ -132,16 +69,14 @@ public:
virtual u32 getTextureId(const std::string &name){return 0;}
virtual u32 getTextureIdDirect(const std::string &name){return 0;}
virtual std::string getTextureName(u32 id){return "";}
virtual AtlasPointer getTexture(u32 id){return AtlasPointer(0);}
virtual AtlasPointer getTexture(const std::string &name)
{return AtlasPointer(0);}
virtual video::ITexture* getTextureRaw(const std::string &name)
{return NULL;}
virtual AtlasPointer getTextureRawAP(const AtlasPointer &ap)
{return AtlasPointer(0);}
virtual video::ITexture* getTexture(u32 id){return NULL;}
virtual video::ITexture* getTexture(
const std::string &name, u32 *id = NULL){
if(id) *id = 0;
return NULL;
}
virtual IrrlichtDevice* getDevice()
{return NULL;}
virtual void updateAP(AtlasPointer &ap){};
virtual bool isKnownSourceImage(const std::string &name)=0;
};
@ -153,20 +88,18 @@ public:
virtual u32 getTextureId(const std::string &name){return 0;}
virtual u32 getTextureIdDirect(const std::string &name){return 0;}
virtual std::string getTextureName(u32 id){return "";}
virtual AtlasPointer getTexture(u32 id){return AtlasPointer(0);}
virtual AtlasPointer getTexture(const std::string &name)
{return AtlasPointer(0);}
virtual video::ITexture* getTextureRaw(const std::string &name)
{return NULL;}
virtual IrrlichtDevice* getDevice()
{return NULL;}
virtual void updateAP(AtlasPointer &ap){};
virtual video::ITexture* getTexture(u32 id){return NULL;}
virtual video::ITexture* getTexture(
const std::string &name, u32 *id = NULL){
if(id) *id = 0;
return NULL;
}
virtual IrrlichtDevice* getDevice(){return NULL;}
virtual bool isKnownSourceImage(const std::string &name)=0;
virtual void processQueue()=0;
virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
virtual void rebuildImagesAndTextures()=0;
virtual void buildMainAtlas(class IGameDef *gamedef)=0;
};
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
@ -189,8 +122,6 @@ enum MaterialType{
// Animation made up by splitting the texture to vertical frames, as
// defined by extra parameters
#define MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES 0x08
// Whether liquid shader should be used
#define MATERIAL_FLAG_
/*
This fully defines the looks of a tile.
@ -199,7 +130,8 @@ enum MaterialType{
struct TileSpec
{
TileSpec():
texture(0),
texture_id(0),
texture(NULL),
alpha(255),
material_type(TILE_MATERIAL_BASIC),
material_flags(
@ -207,14 +139,16 @@ struct TileSpec
MATERIAL_FLAG_BACKFACE_CULLING
),
animation_frame_count(1),
animation_frame_length_ms(0)
animation_frame_length_ms(0),
rotation(0)
{
}
bool operator==(const TileSpec &other) const
{
return (
texture == other.texture &&
texture_id == other.texture_id &&
/* texture == other.texture && */
alpha == other.alpha &&
material_type == other.material_type &&
material_flags == other.material_flags &&
@ -268,14 +202,8 @@ struct TileSpec
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) ? true : false;
}
// NOTE: Deprecated, i guess?
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;
u32 texture_id;
video::ITexture *texture;
// Vertex alpha (when MATERIAL_ALPHA_VERTEX is used)
u8 alpha;
// Material parameters