summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/content_mapnode.cpp1
-rw-r--r--src/main.cpp4
-rw-r--r--src/mapnode.cpp2
-rw-r--r--src/mapnode.h8
-rw-r--r--src/tile.cpp112
5 files changed, 82 insertions, 45 deletions
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index af5e98951..139c46fb2 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -117,6 +117,7 @@ void content_mapnode_init()
f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
f->param_type = CPT_MINERAL;
f->is_ground_content = true;
+ f->often_contains_mineral = true;
f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
if(invisible_stone)
diff --git a/src/main.cpp b/src/main.cpp
index be983676e..df1347f12 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1278,6 +1278,9 @@ int main(int argc, char *argv[])
// Initial call with g_texturesource not set.
init_mapnode();
+ // Must be called before g_texturesource is created
+ // (for texture atlas making)
+ init_mineral();
/*
Run unit tests
@@ -1475,7 +1478,6 @@ int main(int argc, char *argv[])
*/
init_mapnode(); // Second call with g_texturesource set
- init_mineral();
/*
GUI stuff
diff --git a/src/mapnode.cpp b/src/mapnode.cpp
index 170500f45..484fcbe0a 100644
--- a/src/mapnode.cpp
+++ b/src/mapnode.cpp
@@ -42,6 +42,8 @@ ContentFeatures::~ContentFeatures()
#ifndef SERVER
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
{
+ used_texturenames[name] = true;
+
if(g_texturesource)
{
tiles[i].texture = g_texturesource->getTexture(name);
diff --git a/src/mapnode.h b/src/mapnode.h
index 5db337949..61f172eda 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -103,6 +103,9 @@ class NodeMetadata;
struct ContentFeatures
{
#ifndef SERVER
+ // List of all block textures that have been used (value is dummy)
+ core::map<std::string, bool> used_texturenames;
+
/*
0: up
1: down
@@ -151,6 +154,10 @@ struct ContentFeatures
// If true, node is equivalent to air. Torches are, air is. Water is not.
// Is used for example to check whether a mud block can have grass on.
bool air_equivalent;
+ // Whether this content type often contains mineral.
+ // Used for texture atlas creation.
+ // Currently only enabled for CONTENT_STONE.
+ bool often_contains_mineral;
// Inventory item string as which the node appears in inventory when dug.
// Mineral overrides this.
@@ -207,6 +214,7 @@ struct ContentFeatures
liquid_type = LIQUID_NONE;
wall_mounted = false;
air_equivalent = false;
+ often_contains_mineral = false;
dug_item = "";
initial_metadata = NULL;
liquid_alternative_flowing = CONTENT_IGNORE;
diff --git a/src/tile.cpp b/src/tile.cpp
index e274d2d3e..366f2dfb7 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include <ICameraSceneNode.h>
#include "log.h"
+#include "mapnode.h" // For texture atlas making
+#include "mineral.h" // For texture atlas making
/*
A cache from texture name to texture path
@@ -507,52 +509,62 @@ void TextureSource::buildMainAtlas()
}
/*
- A list of stuff to include in the texture atlas.
-
- It is a single-dimensional texture atlas due to the need to tile
- textures.
-
- It should contain as much of the stuff shown in game as possible,
- to minimize texture changes.
-
- It fills up quickly, so do not add anything that isn't contained
- in most MapBlocks. E.g. mese isn't suitable but stone is.
+ Grab list of stuff to include in the texture atlas from the
+ main content features
*/
- core::array<std::string> sourcelist;
-
- sourcelist.push_back("stone.png");
- sourcelist.push_back("mud.png");
- sourcelist.push_back("sand.png");
- sourcelist.push_back("grass.png");
- sourcelist.push_back("grass_footsteps.png");
- sourcelist.push_back("tree.png");
- sourcelist.push_back("tree_top.png");
- sourcelist.push_back("water.png");
- sourcelist.push_back("leaves.png");
- sourcelist.push_back("glass.png");
- sourcelist.push_back("mud.png^grass_side.png");
- sourcelist.push_back("cobble.png");
- sourcelist.push_back("mossycobble.png");
- sourcelist.push_back("gravel.png");
- sourcelist.push_back("jungletree.png");
-
- sourcelist.push_back("stone.png^mineral_coal.png");
- sourcelist.push_back("stone.png^mineral_iron.png");
+ core::map<std::string, bool> sourcelist;
+
+ for(u16 j=0; j<MAX_CONTENT+1; j++)
+ {
+ if(j == CONTENT_IGNORE || j == CONTENT_AIR)
+ continue;
+ ContentFeatures *f = &content_features(j);
+ for(core::map<std::string, bool>::Iterator
+ i = f->used_texturenames.getIterator();
+ i.atEnd() == false; i++)
+ {
+ std::string name = i.getNode()->getKey();
+ sourcelist[name] = true;
+
+ if(f->often_contains_mineral){
+ for(int k=1; k<MINERAL_COUNT; k++){
+ std::string mineraltexture = mineral_block_texture(k);
+ std::string fulltexture = name + "^" + mineraltexture;
+ sourcelist[fulltexture] = true;
+ }
+ }
+ }
+ }
+ infostream<<"Creating texture atlas out of textures: ";
+ for(core::map<std::string, bool>::Iterator
+ i = sourcelist.getIterator();
+ i.atEnd() == false; i++)
+ {
+ std::string name = i.getNode()->getKey();
+ infostream<<"\""<<name<<"\" ";
+ }
+ infostream<<std::endl;
+
// Padding to disallow texture bleeding
s32 padding = 16;
+ s32 column_width = 256;
+ s32 column_padding = 16;
+
/*
First pass: generate almost everything
*/
core::position2d<s32> pos_in_atlas(0,0);
- pos_in_atlas.Y += padding;
+ pos_in_atlas.Y = padding;
- for(u32 i=0; i<sourcelist.size(); i++)
+ for(core::map<std::string, bool>::Iterator
+ i = sourcelist.getIterator();
+ i.atEnd() == false; i++)
{
- std::string name = sourcelist[i];
+ std::string name = i.getNode()->getKey();
/*video::IImage *img = driver->createImageFromFile(
getTexturePath(name.c_str()).c_str());
@@ -586,20 +598,26 @@ void TextureSource::buildMainAtlas()
continue;
}
- // Stop making atlas if atlas is full
+ // Wrap columns and stop making atlas if atlas is full
if(pos_in_atlas.Y + dim.Height > atlas_dim.Height)
{
- infostream<<"TextureSource::buildMainAtlas(): "
- <<"Atlas is full, not adding more textures."
- <<std::endl;
- break;
+ if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - 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;
}
infostream<<"TextureSource::buildMainAtlas(): Adding \""<<name
<<"\" to texture atlas"<<std::endl;
// Tile it a few times in the X direction
- u16 xwise_tiling = 16;
+ 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
@@ -627,7 +645,7 @@ void TextureSource::buildMainAtlas()
dst_y = -y0 + pos_in_atlas.Y-1;
src_y = pos_in_atlas.Y;
}
- s32 x = x0 + pos_in_atlas.X * dim.Width;
+ s32 x = x0 + pos_in_atlas.X;
video::SColor c = atlas_img->getPixel(x, src_y);
atlas_img->setPixel(x,dst_y,c);
}
@@ -668,9 +686,11 @@ void TextureSource::buildMainAtlas()
/*
Second pass: set texture pointer in generated AtlasPointers
*/
- for(u32 i=0; i<sourcelist.size(); i++)
+ for(core::map<std::string, bool>::Iterator
+ i = sourcelist.getIterator();
+ i.atEnd() == false; i++)
{
- std::string name = sourcelist[i];
+ std::string name = i.getNode()->getKey();
if(m_name_to_id.find(name) == NULL)
continue;
u32 id = m_name_to_id[name];
@@ -681,8 +701,12 @@ void TextureSource::buildMainAtlas()
/*
Write image to file so that it can be inspected
*/
- /*driver->writeImageToFile(atlas_img,
- getTexturePath("main_atlas.png").c_str());*/
+ /*std::string atlaspath = porting::path_userdata
+ + 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());*/
}
video::IImage* generate_image_from_scratch(std::string name,