v3s16 face_dir)
{
try{
- // DEBUG
- /*{
- if(n.d == CONTENT_WATER)
- {
- u8 l = n.param2*2;
- if(l > LIGHT_MAX)
- l = LIGHT_MAX;
- return l;
- }
- if(n2.d == CONTENT_WATER)
- {
- u8 l = n2.param2*2;
- if(l > LIGHT_MAX)
- l = LIGHT_MAX;
- return l;
- }
- }*/
-
-
u8 light;
u8 l1 = n.getLightBlend(daynight_ratio);
u8 l2 = n2.getLightBlend(daynight_ratio);
// Make some nice difference to different sides
+ // This makes light come from a corner
/*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.X == -1 || face_dir.Z == -1)
light = diminish_light(light);*/
-
+
+ // All neighboring faces have different shade (like in minecraft)
if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
light = diminish_light(diminish_light(light));
else if(face_dir.Z == 1 || face_dir.Z == -1)
v3f vertex_pos[4];
// If looking towards z+, this is the face that is behind
// the center point, facing towards z+.
- vertex_pos[0] = v3f( BS/2,-BS/2,BS/2);
- vertex_pos[1] = v3f(-BS/2,-BS/2,BS/2);
- vertex_pos[2] = v3f(-BS/2, BS/2,BS/2);
- vertex_pos[3] = v3f( BS/2, BS/2,BS/2);
+ vertex_pos[0] = v3f(-BS/2,-BS/2,BS/2);
+ vertex_pos[1] = v3f( BS/2,-BS/2,BS/2);
+ vertex_pos[2] = v3f( BS/2, BS/2,BS/2);
+ vertex_pos[3] = v3f(-BS/2, BS/2,BS/2);
if(dir == v3s16(0,0,1))
{
video::SColor c = video::SColor(alpha,li,li,li);
- face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c,
- core::vector2d<f32>(0,1));
- face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c,
- core::vector2d<f32>(abs_scale,1));
- face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c,
- core::vector2d<f32>(abs_scale,0));
- face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c,
- core::vector2d<f32>(0,0));
+ 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], v3f(0,1,0), c,
+ core::vector2d<f32>(x0+w*abs_scale, y0+h));
+ face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), c,
+ core::vector2d<f32>(x0, y0+h));
+ face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), c,
+ core::vector2d<f32>(x0, y0));
+ face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), c,
+ core::vector2d<f32>(x0+w*abs_scale, y0));
face.tile = tile;
//DEBUG
}
if(mod.type == NODEMOD_CRACK)
{
+ /*
+ Get texture id, translate it to name, append stuff to
+ name, get texture id
+ */
+
+ // Get original texture name
+ u32 orig_id = spec.texture.id;
+ std::string orig_name = g_texturesource->getTextureName(orig_id);
+
+ // Create new texture name
std::ostringstream os;
- os<<"[crack"<<mod.param;
+ os<<orig_name<<"^[crack"<<mod.param;
- textureid_t tid = g_irrlicht->getTextureId(os.str());
- spec.spec.addTid(tid);
+ // Get new texture
+ u32 new_id = g_texturesource->getTextureId(os.str());
+
+ /*dstream<<"MapBlock::getNodeTile(): Switching from "
+ <<orig_name<<" to "<<os.str()<<" ("
+ <<orig_id<<" to "<<new_id<<")"<<std::endl;*/
+
+ spec.texture = g_texturesource->getTexture(new_id);
}
}
TileSpec tile0_next;
TileSpec tile1_next;
u8 light_next = 0;
-
+
+ // If at last position, there is nothing to compare to and
+ // the face must be drawn anyway
if(j != length - 1)
{
p_next = p + translate_dir;
continuous_tiles_count++;
- if(next_is_different)
+ // This is set to true if the texture doesn't allow more tiling
+ bool end_of_texture = false;
+ /*
+ If there is no texture, it can be tiled infinitely.
+ If tiled==0, it means the texture can be tiled infinitely.
+ Otherwise check tiled agains continuous_tiles_count.
+
+ This check has to be made for both tiles, because this is
+ a bit hackish and we know which one we're using only when
+ the decision to make the faces is made.
+ */
+ if(tile0.texture.atlas != NULL && tile0.texture.tiled != 0)
+ {
+ if(tile0.texture.tiled <= continuous_tiles_count)
+ end_of_texture = true;
+ }
+ if(tile1.texture.atlas != NULL && tile1.texture.tiled != 0)
+ {
+ if(tile1.texture.tiled <= continuous_tiles_count)
+ end_of_texture = true;
+ }
+
+ //end_of_texture = true; //DEBUG
+
+ if(next_is_different || end_of_texture)
{
/*
Create a face if there should be one
JMutexAutoLock lock(m_temp_mods_mutex);
m_temp_mods.copy(temp_mods);
}
-
+
+ /*
+ Some settings
+ */
bool new_style_water = g_settings.getBool("new_style_water");
+ bool new_style_leaves = g_settings.getBool("new_style_leaves");
+
float node_water_level = 1.0;
if(new_style_water)
- node_water_level = 0.8;
+ node_water_level = 0.85;
/*
We are including the faces of the trailing edges of the block.
Convert FastFaces to SMesh
*/
- scene::SMesh *mesh_new = NULL;
-
- mesh_new = new scene::SMesh();
-
MeshCollector collector;
if(fastfaces_new.size() > 0)
//TimeTaker timer2("updateMesh() mesh building");
video::SMaterial material;
- material.Lighting = false;
- material.BackfaceCulling = false;
+ material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
- material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
material.setFlag(video::EMF_FOG_ENABLE, true);
+ //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
+ //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
for(u32 i=0; i<fastfaces_new.size(); i++)
{
FastFace &f = fastfaces_new[i];
const u16 indices[] = {0,1,2,2,3,0};
-
- video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
+
+ //video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
+ video::ITexture *texture = f.tile.texture.atlas;
if(texture == NULL)
continue;
material.setTexture(0, texture);
- if(f.tile.alpha != 255)
- material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
- else
- material.MaterialType = video::EMT_SOLID;
+
+ f.tile.applyMaterialOptions(material);
collector.append(material, f.vertices, 4, indices, 6);
}
//TimeTaker timer2("updateMesh() adding special stuff");
// Flowing water material
- video::SMaterial material_w1;
- material_w1.setFlag(video::EMF_LIGHTING, false);
- material_w1.setFlag(video::EMF_BACK_FACE_CULLING, false);
- material_w1.setFlag(video::EMF_BILINEAR_FILTER, false);
- material_w1.setFlag(video::EMF_FOG_ENABLE, true);
- material_w1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
- material_w1.setTexture(0,
- g_irrlicht->getTexture("water.png"));
+ video::SMaterial material_water1;
+ material_water1.setFlag(video::EMF_LIGHTING, false);
+ //material_water1.setFlag(video::EMF_BACK_FACE_CULLING, false);
+ material_water1.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_water1.setFlag(video::EMF_FOG_ENABLE, true);
+ material_water1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
+ //TODO
+ //material_water1.setTexture(0, g_irrlicht->getTexture("water.png"));
+ AtlasPointer pa_water1 = g_texturesource->getTexture(
+ g_texturesource->getTextureId("water.png"));
+ material_water1.setTexture(0, pa_water1.atlas);
+
+ // New-style leaves material
+ video::SMaterial material_leaves1;
+ material_leaves1.setFlag(video::EMF_LIGHTING, false);
+ //material_leaves1.setFlag(video::EMF_BACK_FACE_CULLING, false);
+ material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
+ material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ //TODO
+ //material_leaves1.setTexture(0, g_irrlicht->getTexture("leaves.png"));
+ AtlasPointer pa_leaves1 = g_texturesource->getTexture(
+ g_texturesource->getTextureId("leaves.png"));
+ material_leaves1.setTexture(0, pa_leaves1.atlas);
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
if(dir == v3s16(0,1,0))
vertices[i].Pos.rotateXZBy(-45);
- vertices[i].Pos += intToFloat(p + getPosRelative());
+ vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
}
// Set material
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
material.MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
if(dir == v3s16(0,-1,0))
material.setTexture(0,
- g_irrlicht->getTexture("torch_on_floor.png"));
+ g_texturesource->getTextureRaw("torch_on_floor.png"));
else if(dir == v3s16(0,1,0))
material.setTexture(0,
- g_irrlicht->getTexture("torch_on_ceiling.png"));
+ g_texturesource->getTextureRaw("torch_on_ceiling.png"));
// For backwards compatibility
else if(dir == v3s16(0,0,0))
material.setTexture(0,
- g_irrlicht->getTexture("torch_on_floor.png"));
+ g_texturesource->getTextureRaw("torch_on_floor.png"));
else
material.setTexture(0,
- g_irrlicht->getTexture("torch.png"));
+ g_texturesource->getTextureRaw("torch.png"));
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
video::S3DVertex vertices[4] =
{
- /*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
- video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
- video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,1),
+ /*video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 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),
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y0()),
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y0()),
};
/*
if(dir == v3s16(1,0,-0))
vertices[j].Pos.rotateXZBy(-90);
- vertices[j].Pos += intToFloat(p + getPosRelative());
+ vertices[j].Pos += intToFloat(p + getPosRelative(), BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
- collector.append(material_w1, vertices, 4, indices, 6);
+ collector.append(material_water1, vertices, 4, indices, 6);
}
/*
{
video::S3DVertex vertices[4] =
{
- video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
+ /*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y0()),
+ video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y0()),
};
+
+ // This fixes a strange bug
+ s32 corner_resolve[4] = {3,2,1,0};
for(s32 i=0; i<4; i++)
{
//vertices[i].Pos.Y += water_level;
//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
- vertices[i].Pos.Y += corner_levels[i];
- vertices[i].Pos += intToFloat(p + getPosRelative());
+ s32 j = corner_resolve[i];
+ vertices[i].Pos.Y += corner_levels[j];
+ vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
- collector.append(material_w1, vertices, 4, indices, 6);
+ collector.append(material_water1, vertices, 4, indices, 6);
}
}
/*
- Add water sources to mesh
+ Add water sources to mesh if using new style
*/
else if(n.d == CONTENT_WATERSOURCE && new_style_water)
{
video::S3DVertex vertices[4] =
{
- video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
+ /*video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
- video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),*/
+ video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y1()),
+ video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
+ pa_water1.x1(), pa_water1.y0()),
+ video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
+ pa_water1.x0(), pa_water1.y0()),
};
for(s32 i=0; i<4; i++)
{
vertices[i].Pos.Y += (-0.5+node_water_level)*BS;
- vertices[i].Pos += intToFloat(p + getPosRelative());
+ vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
- collector.append(material_w1, vertices, 4, indices, 6);
+ collector.append(material_water1, vertices, 4, indices, 6);
+ }
+ /*
+ Add leaves if using new style
+ */
+ else if(n.d == CONTENT_LEAVES && new_style_leaves)
+ {
+ /*u8 l = decode_light(n.getLightBlend(daynight_ratio));*/
+ u8 l = decode_light(undiminish_light(n.getLightBlend(daynight_ratio)));
+ video::SColor c(255,l,l,l);
+
+ for(u32 j=0; j<6; j++)
+ {
+ video::S3DVertex vertices[4] =
+ {
+ /*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
+ video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
+ video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
+ video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
+ video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
+ pa_leaves1.x0(), pa_leaves1.y1()),
+ video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
+ pa_leaves1.x1(), pa_leaves1.y1()),
+ video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
+ pa_leaves1.x1(), pa_leaves1.y0()),
+ video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
+ pa_leaves1.x0(), pa_leaves1.y0()),
+ };
+
+ if(j == 0)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(0);
+ }
+ else if(j == 1)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(180);
+ }
+ else if(j == 2)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(-90);
+ }
+ else if(j == 3)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(90);
+ }
+ else if(j == 4)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateYZBy(-90);
+ }
+ else if(j == 5)
+ {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateYZBy(90);
+ }
+
+ for(u16 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ // Add to mesh collector
+ collector.append(material_leaves1, vertices, 4, indices, 6);
+ }
}
}
Add stuff from collector to mesh
*/
+ scene::SMesh *mesh_new = NULL;
+ mesh_new = new scene::SMesh();
+
collector.fillMesh(mesh_new);
/*
mesh_new = NULL;
}
- // Use VBO for mesh (this just would set this for ever buffer)
- // This will lead to infinite memory usage because or irrlicht.
- //mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
-
- /*std::cout<<"MapBlock has "<<fastfaces_new.size()<<" faces "
- <<"and uses "<<mesh_new->getMeshBufferCount()
- <<" materials (meshbuffers)"<<std::endl;*/
+ if(mesh_new)
+ {
+#if 0
+ // Usually 1-700 faces and 1-7 materials
+ std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces "
+ <<"and uses "<<mesh_new->getMeshBufferCount()
+ <<" materials (meshbuffers)"<<std::endl;
+#endif
+
+ // Use VBO for mesh (this just would set this for ever buffer)
+ // This will lead to infinite memory usage because or irrlicht.
+ //mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
+
+ /*
+ NOTE: If that is enabled, some kind of a queue to the main
+ thread should be made which would call irrlicht to delete
+ the hardware buffer and then delete the mesh
+ */
+ }
/*
Replace the mesh
if(getNode(p).d == CONTENT_AIR
&& getNode(p).getLightBlend(daynight_ratio) <= 11)
{
- RatObject *obj = new RatObject(NULL, -1, intToFloat(p));
+ RatObject *obj = new RatObject(NULL, -1, intToFloat(p, BS));
addObject(obj);
}
}
// First byte
u8 flags = 0;
if(is_underground)
- flags |= 1;
+ flags |= 0x01;
if(m_day_night_differs)
- flags |= 2;
+ flags |= 0x02;
if(m_lighting_expired)
- flags |= 3;
+ flags |= 0x04;
os.write((char*)&flags, 1);
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
u8 flags;
is.read((char*)&flags, 1);
- is_underground = (flags & 1) ? true : false;
- m_day_night_differs = (flags & 2) ? true : false;
- m_lighting_expired = (flags & 3) ? true : false;
+ is_underground = (flags & 0x01) ? true : false;
+ m_day_night_differs = (flags & 0x02) ? true : false;
+ m_lighting_expired = (flags & 0x04) ? true : false;
// Uncompress data
std::ostringstream os(std::ios_base::binary);