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; # Enable smooth lighting with simple ambient occlusion;
# disable for speed or for different looks. # disable for speed or for different looks.
#smooth_lighting = true #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. # Path to texture directory. All textures are first searched from here.
#texture_path = #texture_path =
# Video back-end. # Video back-end.

@ -320,12 +320,6 @@ Client::Client(
m_playerpos_send_timer = 0.0; m_playerpos_send_timer = 0.0;
m_ignore_damage_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 Add local player
*/ */
@ -2855,11 +2849,6 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
infostream<<"- Rebuilding images and textures"<<std::endl; infostream<<"- Rebuilding images and textures"<<std::endl;
m_tsrc->rebuildImagesAndTextures(); 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 // Rebuild shaders
m_shsrc->rebuildShaders(); m_shsrc->rebuildShaders();

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

@ -50,7 +50,7 @@ public:
m_spritenode = smgr->addBillboardSceneNode( m_spritenode = smgr->addBillboardSceneNode(
NULL, v2f(1,1), pos, -1); NULL, v2f(1,1), pos, -1);
m_spritenode->setMaterialTexture(0, 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_LIGHTING, false);
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
//m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); //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]), 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++) for(int i = 0; i < tilecount; i++)
{ {
switch (tiles[i].rotation) 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)); vertices[i*4+x].TCoords.rotateBy(270,irr::core::vector2df(0, 0));
break; break;
case 4: //FXR90 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)); 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; break;
case 5: //FXR270 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)); 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; break;
case 6: //FYR90 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)); 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; break;
case 7: //FYR270 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)); 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; break;
case 8: //FX case 8: //FX
tiles[i].texture.pos.Y += tiles[i].texture.size.Y; for (int x = 0; x < 4; x++){
tiles[i].texture.size.Y *= -1; vertices[i*4+x].TCoords.X = 1.0 - vertices[i*4+x].TCoords.X;
}
break; break;
case 9: //FY case 9: //FY
tiles[i].texture.pos.X += tiles[i].texture.size.X; for (int x = 0; x < 4; x++){
tiles[i].texture.size.X *= -1; vertices[i*4+x].TCoords.Y = 1.0 - vertices[i*4+x].TCoords.Y;
}
break; break;
default: default:
break; 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}; u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector // Add to mesh collector
for(s32 j=0; j<24; j+=4) 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 = f.special_tiles[0];
TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data); TileSpec tile_liquid_bfculled = getNodeTile(n, p, v3s16(0,0,0), data);
AtlasPointer &pa_liquid = tile_liquid.texture;
bool top_is_same_liquid = false; bool top_is_same_liquid = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); 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 vertices[4] =
{ {
video::S3DVertex(-BS/2,0,BS/2,0,0,0, c, video::S3DVertex(-BS/2,0,BS/2,0,0,0, c, 0,1),
pa_liquid.x0(), pa_liquid.y1()), video::S3DVertex(BS/2,0,BS/2,0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2,0,0,0, c, video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
pa_liquid.x1(), pa_liquid.y1()), 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_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
}; };
/* /*
@ -359,14 +347,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
pa_liquid.x0(), pa_liquid.y1()), video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
pa_liquid.x1(), pa_liquid.y1()), 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_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
}; };
v3f offset(p.X*BS, p.Y*BS + (-0.5+node_liquid_level)*BS, p.Z*BS); 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 = f.special_tiles[0];
TileSpec tile_liquid_bfculled = f.special_tiles[1]; TileSpec tile_liquid_bfculled = f.special_tiles[1];
AtlasPointer &pa_liquid = tile_liquid.texture;
bool top_is_same_liquid = false; bool top_is_same_liquid = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); 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 vertices[4] =
{ {
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
pa_liquid.x0(), pa_liquid.y1()), video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
pa_liquid.x1(), pa_liquid.y1()), 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_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
}; };
/* /*
@ -647,14 +626,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{ {
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
pa_liquid.x0(), pa_liquid.y1()), video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,0),
pa_liquid.x1(), pa_liquid.y1()), 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_liquid.x1(), pa_liquid.y0()),
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
pa_liquid.x0(), pa_liquid.y0()),
}; };
// To get backface culling right, the vertices need to go // To get backface culling right, the vertices need to go
@ -725,7 +700,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
case NDT_GLASSLIKE: case NDT_GLASSLIKE:
{ {
TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data); TileSpec tile = getNodeTile(n, p, v3s16(0,0,0), data);
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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+ // The face at Z+
video::S3DVertex vertices[4] = { video::S3DVertex vertices[4] = {
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
ap.x0(), ap.y1()), 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, video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
ap.x1(), ap.y1()), 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,
ap.x1(), ap.y0()),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
ap.x0(), ap.y0()),
}; };
// Rotations in the g_6dirs format // Rotations in the g_6dirs format
@ -910,7 +880,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{ {
TileSpec tile_leaves = getNodeTile(n, p, TileSpec tile_leaves = getNodeTile(n, p,
v3s16(0,0,0), data); v3s16(0,0,0), data);
AtlasPointer pa_leaves = tile_leaves.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY; tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source));
// Wall at X+ of node // Wall at X+ of node
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
ap.x0(), ap.y1()), video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
ap.x1(), ap.y1()), video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
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()),
}; };
for(s32 i=0; i<4; i++) 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); TileSpec tile = getNodeTileN(n, p, 0, data);
tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING; tile.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY; tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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 // Wall at X+ of node
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 0,0),
ap.x0(), ap.y0()), 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, video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 1,1),
ap.x1(), ap.y0()), video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 0,1),
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()),
}; };
v3s16 dir = n.getWallMountedDir(nodedef); v3s16 dir = n.getWallMountedDir(nodedef);
@ -1037,7 +995,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
{ {
TileSpec tile = getNodeTileN(n, p, 0, data); TileSpec tile = getNodeTileN(n, p, 0, data);
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY; tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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 vertices[4] =
{ {
video::S3DVertex(-BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, video::S3DVertex(-BS/2*f.visual_scale,-BS/2,0, 0,0,0, c, 0,1),
ap.x0(), ap.y1()), 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,0, 0,0,0, c,
ap.x1(), ap.y1()),
video::S3DVertex( BS/2*f.visual_scale, video::S3DVertex( BS/2*f.visual_scale,
-BS/2 + f.visual_scale*BS,0, 0,0,0, c, -BS/2 + f.visual_scale*BS,0, 0,0,0, c, 1,0),
ap.x1(), ap.y0()),
video::S3DVertex(-BS/2*f.visual_scale, video::S3DVertex(-BS/2*f.visual_scale,
-BS/2 + f.visual_scale*BS,0, 0,0,0, c, -BS/2 + f.visual_scale*BS,0, 0,0,0, c, 0,0),
ap.x0(), ap.y0()),
}; };
if(j == 0) if(j == 0)
@ -1088,10 +1041,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// A hack to put wood the right way around in the posts // A hack to put wood the right way around in the posts
ITextureSource *tsrc = data->m_gamedef->tsrc(); ITextureSource *tsrc = data->m_gamedef->tsrc();
std::string texturestring_rot = tsrc->getTextureName(
tile.texture_id) + "^[transformR90";
TileSpec tile_rot = tile; TileSpec tile_rot = tile;
tile_rot.texture = tsrc->getTexture(tsrc->getTextureName( tile_rot.texture = tsrc->getTexture(
tile.texture.id) + "^[transformR90"); texturestring_rot,
&tile_rot.texture_id);
u16 l = getInteriorLight(n, 1, data); u16 l = getInteriorLight(n, 1, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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_BACKFACE_CULLING;
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY; tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
AtlasPointer ap = tile.texture;
u16 l = getInteriorLight(n, 0, data); u16 l = getInteriorLight(n, 0, data);
video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); 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 vertices[4] =
{ {
video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c, video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c, 0,1),
ap.x0(), ap.y1()), video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c, video::S3DVertex(BS/2,g*BS/2+d,BS/2, 0,0,0, c, 1,0),
ap.x1(), ap.y1()), video::S3DVertex(-BS/2,g*BS/2+d,BS/2, 0,0,0, c, 0,0),
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()),
}; };
for(s32 i=0; i<4; i++) 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_water", "false");
settings->setDefault("new_style_leaves", "true"); settings->setDefault("new_style_leaves", "true");
settings->setDefault("smooth_lighting", "true"); settings->setDefault("smooth_lighting", "true");
settings->setDefault("enable_texture_atlas", "false");
settings->setDefault("texture_path", ""); settings->setDefault("texture_path", "");
settings->setDefault("shader_path", ""); settings->setDefault("shader_path", "");
settings->setDefault("video_driver", "opengl"); 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_BACK_FACE_CULLING, false);
m_materials[1].setFlag(video::EMF_BILINEAR_FILTER, false); m_materials[1].setFlag(video::EMF_BILINEAR_FILTER, false);
m_materials[1].setFlag(video::EMF_FOG_ENABLE, 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].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_materials[1].setFlag(video::EMF_FOG_ENABLE, true); m_materials[1].setFlag(video::EMF_FOG_ENABLE, true);

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

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

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

@ -341,7 +341,7 @@ public:
cc->inventory_texture = NULL; cc->inventory_texture = NULL;
if(def->inventory_image != "") 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) else if(def->type == ITEM_NODE)
{ {
@ -365,7 +365,7 @@ public:
imagename = def->inventory_image; imagename = def->inventory_image;
cc->wield_mesh = createExtrudedMesh( cc->wield_mesh = createExtrudedMesh(
tsrc->getTextureRaw(imagename), tsrc->getTexture(imagename),
driver, driver,
def->wield_scale * v3f(40.0, 40.0, 4.0)); def->wield_scale * v3f(40.0, 40.0, 4.0));
if(cc->wield_mesh == NULL) if(cc->wield_mesh == NULL)
@ -446,7 +446,7 @@ public:
if(cc->inventory_texture == NULL) if(cc->inventory_texture == NULL)
{ {
cc->inventory_texture = cc->inventory_texture =
tsrc->getTextureRaw(f.tiledef[0].name); tsrc->getTexture(f.tiledef[0].name);
} }
} }
else 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. // Position is at the center of the cube.
v3f pos = p * BS; v3f pos = p * BS;
float x0 = 0.0;
float y0 = 0.0;
float w = 1.0;
float h = 1.0;
v3f vertex_pos[4]; v3f vertex_pos[4];
v3s16 vertex_dirs[4]; v3s16 vertex_dirs[4];
getNodeVertexDirs(dir, vertex_dirs); 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[3] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[1]; vertex_dirs[2] = vertex_dirs[1];
vertex_dirs[1] = t; vertex_dirs[1] = t;
tile.texture.pos.Y += tile.texture.size.Y; y0 += h;
tile.texture.size.Y *= -1; h *= -1;
break; break;
case 5: //FXR270 case 5: //FXR270
t = vertex_dirs[0]; 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[1] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[3]; vertex_dirs[2] = vertex_dirs[3];
vertex_dirs[3] = t; vertex_dirs[3] = t;
tile.texture.pos.Y += tile.texture.size.Y; y0 += h;
tile.texture.size.Y *= -1; h *= -1;
break; break;
case 6: //FYR90 case 6: //FYR90
t = vertex_dirs[0]; 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[3] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[1]; vertex_dirs[2] = vertex_dirs[1];
vertex_dirs[1] = t; vertex_dirs[1] = t;
tile.texture.pos.X += tile.texture.size.X; x0 += w;
tile.texture.size.X *= -1; w *= -1;
break; break;
case 7: //FYR270 case 7: //FYR270
t = vertex_dirs[0]; 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[1] = vertex_dirs[2];
vertex_dirs[2] = vertex_dirs[3]; vertex_dirs[2] = vertex_dirs[3];
vertex_dirs[3] = t; vertex_dirs[3] = t;
tile.texture.pos.X += tile.texture.size.X; x0 += w;
tile.texture.size.X *= -1; w *= -1;
break; break;
case 8: //FX case 8: //FX
tile.texture.pos.Y += tile.texture.size.Y; y0 += h;
tile.texture.size.Y *= -1; h *= -1;
break; break;
case 9: //FY case 9: //FY
tile.texture.pos.X += tile.texture.size.X; x0 += w;
tile.texture.size.X *= -1; w *= -1;
break; break;
default: default:
break; break;
@ -555,11 +560,6 @@ static void makeFastFace(TileSpec tile, u16 li0, u16 li1, u16 li2, u16 li3,
u8 alpha = tile.alpha; 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, face.vertices[0] = video::S3DVertex(vertex_pos[0], normal,
MapBlock_LightColor(alpha, li0, light_source), MapBlock_LightColor(alpha, li0, light_source),
core::vector2d<f32>(x0+w*abs_scale, y0+h)); 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) if(p == data->m_crack_pos_relative)
{ {
spec.material_flags |= MATERIAL_FLAG_CRACK; 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; return spec;
} }
@ -717,7 +711,7 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 dir, MeshMakeData *data)
u16 tile_index=facedir*16 + dir_i; u16 tile_index=facedir*16 + dir_i;
TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data); TileSpec spec = getNodeTileN(mn, p, dir_to_tile[tile_index], data);
spec.rotation=dir_to_tile[tile_index + 1]; 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; return spec;
} }
@ -889,23 +883,7 @@ static void updateFastFaceRow(
continuous_tiles_count++; continuous_tiles_count++;
// This is set to true if the texture doesn't allow more tiling if(next_is_different)
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)
{ {
/* /*
Create a face if there should be one 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[] = {0,1,2,2,3,0};
const u16 indices_alternate[] = {0,1,3,2,3,1}; const u16 indices_alternate[] = {0,1,3,2,3,1};
if(f.tile.texture.atlas == NULL) if(f.tile.texture == NULL)
continue; continue;
const u16 *indices_p = indices; const u16 *indices_p = indices;
@ -1112,7 +1090,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
if(p.tile.material_flags & MATERIAL_FLAG_CRACK) if(p.tile.material_flags & MATERIAL_FLAG_CRACK)
{ {
ITextureSource *tsrc = data->m_gamedef->tsrc(); 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) if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
crack_basename += "^[cracko"; crack_basename += "^[cracko";
else else
@ -1137,9 +1115,11 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
} }
// Replace tile texture with the first animation frame // Replace tile texture with the first animation frame
std::ostringstream os(std::ios::binary); 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"; 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) // - Classic lighting (shaders handle this by themselves)
if(!enable_shaders) if(!enable_shaders)
@ -1173,7 +1153,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE); //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
material.MaterialType material.MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material.setTexture(0, p.tile.texture.atlas); material.setTexture(0, p.tile.texture);
if(enable_shaders) if(enable_shaders)
p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2, shadermat3); p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2, shadermat3);
else else
@ -1259,8 +1239,8 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
ITextureSource *tsrc = m_gamedef->getTextureSource(); ITextureSource *tsrc = m_gamedef->getTextureSource();
std::ostringstream os; std::ostringstream os;
os<<basename<<crack; os<<basename<<crack;
AtlasPointer ap = tsrc->getTexture(os.str()); buf->getMaterial().setTexture(0,
buf->getMaterial().setTexture(0, ap.atlas); tsrc->getTexture(os.str()));
} }
m_last_crack = crack; 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 // Create new texture name from original
std::ostringstream os(std::ios::binary); 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; os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
// Set the texture // Set the texture
AtlasPointer ap = tsrc->getTexture(os.str()); buf->getMaterial().setTexture(0, tsrc->getTexture(os.str()));
buf->getMaterial().setTexture(0, ap.atlas);
} }
// Day-night transition // Day-night transition

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

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

@ -57,7 +57,9 @@ Particle::Particle(
float expirationtime, float expirationtime,
float size, float size,
bool collisiondetection, bool collisiondetection,
AtlasPointer ap video::ITexture *texture,
v2f texpos,
v2f texsize
): ):
scene::ISceneNode(smgr->getRootSceneNode(), smgr) scene::ISceneNode(smgr->getRootSceneNode(), smgr)
{ {
@ -70,8 +72,9 @@ Particle::Particle(
m_material.setFlag(video::EMF_BILINEAR_FILTER, false); m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
m_material.setFlag(video::EMF_FOG_ENABLE, true); m_material.setFlag(video::EMF_FOG_ENABLE, true);
m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_material.setTexture(0, ap.atlas); m_material.setTexture(0, texture);
m_ap = ap; m_texpos = texpos;
m_texsize = texsize;
// Particle related // Particle related
@ -180,14 +183,19 @@ void Particle::updateLight(ClientEnvironment &env)
void Particle::updateVertices() void Particle::updateVertices()
{ {
video::SColor c(255, m_light, m_light, m_light); 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, 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, 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, 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, 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++) for(u16 i=0; i<4; i++)
{ {
@ -248,19 +256,19 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
{ {
// Texture // Texture
u8 texid = myrand_range(0,5); 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 size = rand()%64/512.;
float visual_size = BS*size; float visual_size = BS*size;
float texsize = size*2; v2f texsize(size*2, ymax*size*2);
v2f texpos;
float x1 = ap.x1(); texpos.X = ((rand()%64)/64.-texsize.X);
float y1 = ap.y1(); texpos.Y = ymax*((rand()%64)/64.-texsize.Y);
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);
// Physics // Physics
v3f velocity( (rand()%100/50.-1)/1.5, v3f velocity( (rand()%100/50.-1)/1.5,
@ -285,7 +293,9 @@ void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr,
rand()%100/100., // expiration time rand()%100/100., // expiration time
visual_size, visual_size,
true, true,
ap); texture,
texpos,
texsize);
} }
/* /*
@ -296,7 +306,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
u16 amount, float time, u16 amount, float time,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize, 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_gamedef = gamedef;
m_smgr = smgr; m_smgr = smgr;
@ -314,7 +324,7 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
m_minsize = minsize; m_minsize = minsize;
m_maxsize = maxsize; m_maxsize = maxsize;
m_collisiondetection = collisiondetection; m_collisiondetection = collisiondetection;
m_ap = ap; m_texture = texture;
m_time = 0; m_time = 0;
for (u16 i = 0; i<=m_amount; i++) for (u16 i = 0; i<=m_amount; i++)
@ -362,7 +372,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
exptime, exptime,
size, size,
m_collisiondetection, m_collisiondetection,
m_ap); m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
m_spawntimes.erase(i); m_spawntimes.erase(i);
} }
else else
@ -398,7 +410,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment &env)
exptime, exptime,
size, size,
m_collisiondetection, 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 expirationtime,
float size, float size,
bool collisiondetection, bool collisiondetection,
AtlasPointer texture video::ITexture *texture,
v2f texpos,
v2f texsize
); );
~Particle(); ~Particle();
@ -81,16 +83,13 @@ private:
core::aabbox3d<f32> m_box; core::aabbox3d<f32> m_box;
core::aabbox3d<f32> m_collisionbox; core::aabbox3d<f32> m_collisionbox;
video::SMaterial m_material; video::SMaterial m_material;
v2f m_texpos;
v2f m_texsize;
v3f m_pos; v3f m_pos;
v3f m_velocity; v3f m_velocity;
v3f m_acceleration; v3f m_acceleration;
float tex_x0;
float tex_x1;
float tex_y0;
float tex_y1;
LocalPlayer *m_player; LocalPlayer *m_player;
float m_size; float m_size;
AtlasPointer m_ap;
u8 m_light; u8 m_light;
bool m_collisiondetection; bool m_collisiondetection;
}; };
@ -109,7 +108,7 @@ class ParticleSpawner
float minexptime, float maxexptime, float minexptime, float maxexptime,
float minsize, float maxsize, float minsize, float maxsize,
bool collisiondetection, bool collisiondetection,
AtlasPointer ap, video::ITexture *texture,
u32 id); u32 id);
~ParticleSpawner(); ~ParticleSpawner();
@ -136,7 +135,7 @@ class ParticleSpawner
float m_maxexptime; float m_maxexptime;
float m_minsize; float m_minsize;
float m_maxsize; float m_maxsize;
AtlasPointer m_ap; video::ITexture *m_texture;
std::vector<float> m_spawntimes; std::vector<float> m_spawntimes;
bool m_collisiondetection; bool m_collisiondetection;
}; };

@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mesh.h" #include "mesh.h"
#include <ICameraSceneNode.h> #include <ICameraSceneNode.h>
#include "log.h" #include "log.h"
#include "mapnode.h" // For texture atlas making
#include "nodedef.h" // For texture atlas making
#include "gamedef.h" #include "gamedef.h"
#include "util/string.h" #include "util/string.h"
#include "util/container.h" #include "util/container.h"
@ -165,31 +163,23 @@ std::string getTexturePath(const std::string &filename)
} }
/* /*
An internal variant of AtlasPointer with more data. Stores internal information about a texture.
(well, more like a wrapper)
*/ */
struct SourceAtlasPointer struct TextureInfo
{ {
std::string name; std::string name;
AtlasPointer a; video::ITexture *texture;
video::IImage *atlas_img; // The source image of the atlas video::IImage *img; // The source image
// Integer variants of position and size
v2s32 intpos;
v2u32 intsize;
SourceAtlasPointer( TextureInfo(
const std::string &name_, const std::string &name_,
AtlasPointer a_=AtlasPointer(0, NULL), video::ITexture *texture_=NULL,
video::IImage *atlas_img_=NULL, video::IImage *img_=NULL
v2s32 intpos_=v2s32(0,0),
v2u32 intsize_=v2u32(0,0)
): ):
name(name_), name(name_),
a(a_), texture(texture_),
atlas_img(atlas_img_), img(img_)
intpos(intpos_),
intsize(intsize_)
{ {
} }
}; };
@ -307,7 +297,7 @@ public:
Example case #2: Example case #2:
- Assume a texture with the id 1 exists, and has the name - 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 - Now getNodeTile() stumbles upon a node which uses
texture id 1, and determines that MATERIAL_FLAG_CRACK texture id 1, and determines that MATERIAL_FLAG_CRACK
must be applied to the tile must be applied to the tile
@ -315,7 +305,7 @@ public:
has received the current crack level 0 from the client. It has received the current crack level 0 from the client. It
finds out the name of the texture with getTextureName(1), finds out the name of the texture with getTextureName(1),
appends "^crack0" to it and gets a new texture id with 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 and not found in cache, the call is queued to the main thread
for processing. 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 video::ITexture* getTexture(const std::string &name, u32 *id);
AtlasPointer getTextureRawAP(const AtlasPointer &ap)
{
return getTexture(getTextureName(ap.id) + m_forcesingle_suffix);
}
// Returns a pointer to the irrlicht device // Returns a pointer to the irrlicht device
virtual IrrlichtDevice* getDevice() virtual IrrlichtDevice* getDevice()
@ -380,10 +354,6 @@ public:
return m_device; 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 isKnownSourceImage(const std::string &name)
{ {
bool is_known = false; bool is_known = false;
@ -407,10 +377,6 @@ public:
// Rebuild images and textures from the current set of source images // Rebuild images and textures from the current set of source images
// Shall be called from the main thread. // Shall be called from the main thread.
void rebuildImagesAndTextures(); void rebuildImagesAndTextures();
// Build the main texture atlas which contains most of the
// textures.
void buildMainAtlas(class IGameDef *gamedef);
private: private:
@ -428,17 +394,12 @@ private:
// A texture id is index in this array. // A texture id is index in this array.
// The first position contains a NULL texture. // 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. // Maps a texture name to an index in the former.
std::map<std::string, u32> m_name_to_id; std::map<std::string, u32> m_name_to_id;
// The two former containers are behind this mutex // The two former containers are behind this mutex
JMutex m_atlaspointer_cache_mutex; JMutex m_textureinfo_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;
// Queued texture fetches (to be processed by the main thread) // Queued texture fetches (to be processed by the main thread)
RequestQueue<std::string, u32, u8, u8> m_get_texture_queue; RequestQueue<std::string, u32, u8, u8> m_get_texture_queue;
@ -453,18 +414,16 @@ IWritableTextureSource* createTextureSource(IrrlichtDevice *device)
} }
TextureSource::TextureSource(IrrlichtDevice *device): TextureSource::TextureSource(IrrlichtDevice *device):
m_device(device), m_device(device)
m_main_atlas_image(NULL),
m_main_atlas_texture(NULL)
{ {
assert(m_device); assert(m_device);
m_atlaspointer_cache_mutex.Init(); m_textureinfo_cache_mutex.Init();
m_main_thread = get_current_thread_id(); m_main_thread = get_current_thread_id();
// Add a NULL AtlasPointer as the first index, named "" // Add a NULL TextureInfo as the first index, named ""
m_atlaspointer_cache.push_back(SourceAtlasPointer("")); m_textureinfo_cache.push_back(TextureInfo(""));
m_name_to_id[""] = 0; m_name_to_id[""] = 0;
} }
@ -474,21 +433,19 @@ TextureSource::~TextureSource()
unsigned int textures_before = driver->getTextureCount(); unsigned int textures_before = driver->getTextureCount();
for (std::vector<SourceAtlasPointer>::iterator iter = for (std::vector<TextureInfo>::iterator iter =
m_atlaspointer_cache.begin(); iter != m_atlaspointer_cache.end(); m_textureinfo_cache.begin();
iter++) iter != m_textureinfo_cache.end(); iter++)
{ {
video::ITexture *t = driver->getTexture(iter->name.c_str());
//cleanup texture //cleanup texture
if (t) if (iter->texture)
driver->removeTexture(t); driver->removeTexture(iter->texture);
//cleanup source image //cleanup source image
if (iter->atlas_img) if (iter->img)
iter->atlas_img->drop(); iter->img->drop();
} }
m_atlaspointer_cache.clear(); m_textureinfo_cache.clear();
for (std::list<video::ITexture*>::iterator iter = for (std::list<video::ITexture*>::iterator iter =
m_texture_trash.begin(); iter != m_texture_trash.end(); 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 See if texture already exists
*/ */
JMutexAutoLock lock(m_atlaspointer_cache_mutex); JMutexAutoLock lock(m_textureinfo_cache_mutex);
std::map<std::string, u32>::iterator n; std::map<std::string, u32>::iterator n;
n = m_name_to_id.find(name); n = m_name_to_id.find(name);
if(n != m_name_to_id.end()) 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 Generates an image from a full string like
"stone.png^mineral_coal.png^[crack0". "stone.png^mineral_coal.png^[crack0".
This is used by buildMainAtlas().
*/ */
video::IImage* generate_image_from_scratch(std::string name, video::IImage* generate_image_from_scratch(std::string name,
IrrlichtDevice *device, SourceImageCache *sourcecache); IrrlichtDevice *device, SourceImageCache *sourcecache);
@ -625,7 +580,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
See if texture already exists See if texture already exists
*/ */
{ {
JMutexAutoLock lock(m_atlaspointer_cache_mutex); JMutexAutoLock lock(m_textureinfo_cache_mutex);
std::map<std::string, u32>::iterator n; std::map<std::string, u32>::iterator n;
n = m_name_to_id.find(name); 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 a base image was found, copy it to baseimg
if(base_image_id != 0) 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 " infostream<<"getTextureIdDirect(): WARNING: NULL image in "
<<"cache: \""<<base_image_name<<"\"" <<"cache: \""<<base_image_name<<"\""
@ -707,17 +660,14 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
} }
else else
{ {
core::dimension2d<u32> dim = ap.intsize; core::dimension2d<u32> dim = ti->img->getDimension();
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
core::position2d<s32> pos_to(0,0); ti->img->copyTo(
core::position2d<s32> pos_from = ap.intpos;
image->copyTo(
baseimg, // target baseimg, // target
v2s32(0,0), // position in 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 \"" /*infostream<<"getTextureIdDirect(): Loaded \""
@ -759,19 +709,11 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
Add texture to caches (add NULL textures too) 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(); u32 id = m_textureinfo_cache.size();
AtlasPointer ap(id); TextureInfo ti(name, t, baseimg);
ap.atlas = t; m_textureinfo_cache.push_back(ti);
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);
m_name_to_id[name] = id; m_name_to_id[name] = id;
/*infostream<<"getTextureIdDirect(): " /*infostream<<"getTextureIdDirect(): "
@ -782,34 +724,36 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
std::string TextureSource::getTextureName(u32 id) 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 errorstream<<"TextureSource::getTextureName(): id="<<id
<<" >= m_atlaspointer_cache.size()=" <<" >= m_textureinfo_cache.size()="
<<m_atlaspointer_cache.size()<<std::endl; <<m_textureinfo_cache.size()<<std::endl;
return ""; return "";
} }
return m_atlaspointer_cache[id].name; return m_textureinfo_cache[id].name;
} }
video::ITexture* TextureSource::getTexture(u32 id)
AtlasPointer TextureSource::getTexture(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())
return AtlasPointer(0, NULL); 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); u32 actual_id = getTextureId(name);
ap = ap2; if(id){
*id = actual_id;
}
return getTexture(actual_id);
} }
void TextureSource::processQueue() void TextureSource::processQueue()
@ -849,299 +793,29 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
void TextureSource::rebuildImagesAndTextures() void TextureSource::rebuildImagesAndTextures()
{ {
JMutexAutoLock lock(m_atlaspointer_cache_mutex); JMutexAutoLock lock(m_textureinfo_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(); 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 // Recreate textures
for(u32 i=0; i<m_atlaspointer_cache.size(); i++){ for(u32 i=0; i<m_textureinfo_cache.size(); i++){
SourceAtlasPointer *sap = &m_atlaspointer_cache[i]; TextureInfo *ti = &m_textureinfo_cache[i];
video::IImage *img = 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 // Create texture from resulting image
video::ITexture *t = NULL; video::ITexture *t = NULL;
if(img) if(img)
t = driver->addTexture(sap->name.c_str(), img); t = driver->addTexture(ti->name.c_str(), img);
video::ITexture *t_old = sap->a.atlas; video::ITexture *t_old = ti->texture;
// Replace texture // Replace texture
sap->a.atlas = t; ti->texture = t;
sap->a.pos = v2f(0,0); ti->img = img;
sap->a.size = v2f(1,1);
sap->a.tiled = 0;
sap->atlas_img = img;
sap->intpos = v2s32(0,0);
sap->intsize = img->getDimension();
if (t_old != 0) if (t_old != 0)
m_texture_trash.push_back(t_old); 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, video::IImage* generate_image_from_scratch(std::string name,
IrrlichtDevice *device, SourceImageCache *sourcecache) IrrlichtDevice *device, SourceImageCache *sourcecache)
{ {
@ -1285,31 +959,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
<<"modification \""<<part_of_name<<"\"" <<"modification \""<<part_of_name<<"\""
<<std::endl;*/ <<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 [crackN
Adds a cracking texture Adds a cracking texture
*/ */
else if(part_of_name.substr(0,6) == "[crack") if(part_of_name.substr(0,6) == "[crack")
{ {
if(baseimg == NULL) if(baseimg == NULL)
{ {

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