X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmapblock.cpp;h=63f33ffc0d2d0cedb4a3264a728ced5a70946c3b;hb=607f548712ae5a41eceb668085c87d10089849b9;hp=60efa2fcfa1f015728fb3966d2df9d413b0d622b;hpb=c32da52104cc6bbe8ed0bf1ba1a7874f015cb738;p=oweals%2Fminetest.git diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 60efa2fcf..63f33ffc0 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "map.h" -// For g_materials +// For g_settings and g_irrlicht #include "main.h" #include "light.h" #include @@ -141,6 +141,8 @@ MapNode MapBlock::getNodeParentNoEx(v3s16 p) n: getNodeParent(p) n2: getNodeParent(p + face_dir) face_dir: axis oriented unit vector from p to p2 + + returns encoded light value. */ u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, v3s16 face_dir) @@ -156,11 +158,13 @@ u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, // 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) @@ -189,10 +193,10 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, 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)) { @@ -242,24 +246,42 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, //u8 li = decode_light(light); u8 li = light; + //u8 li = 255; //DEBUG - u8 alpha = 255; - + u8 alpha = tile.alpha; + /*u8 alpha = 255; if(tile.id == TILE_WATER) - { - alpha = 128; - } + alpha = WATER_ALPHA;*/ video::SColor c = video::SColor(alpha,li,li,li); face.vertices[0] = video::S3DVertex(vertex_pos[0], zerovector, c, - core::vector2d(0,1)); - face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c, core::vector2d(abs_scale,1)); + face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c, + core::vector2d(0,1)); face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c, + core::vector2d(0,0)); + face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c, core::vector2d(abs_scale,0)); + + /*float x0 = (float)tile.tx/256.0; + float y0 = (float)tile.ty/256.0; + float w = ((float)tile.tw + 1.0)/256.0; + float h = ((float)tile.th + 1.0)/256.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], zerovector, c, + core::vector2d(x0+w*abs_scale, y0+h)); + face.vertices[1] = video::S3DVertex(vertex_pos[1], zerovector, c, + core::vector2d(x0, y0+h)); + face.vertices[2] = video::S3DVertex(vertex_pos[2], zerovector, c, + core::vector2d(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], zerovector, c, - core::vector2d(0,0)); + core::vector2d(x0+w*abs_scale, y0)); face.tile = tile; //DEBUG @@ -273,56 +295,72 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, Gets node tile from any place relative to block. Returns TILE_NODE if doesn't exist or should not be drawn. */ -TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir) +TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, + NodeModMap &temp_mods) { TileSpec spec; - - /*//DEBUG - { - spec.id = TILE_STONE; - return spec; - }*/ - - spec.feature = TILEFEAT_NONE; - //spec.id = TILE_STONE; - spec.id = mn.getTile(face_dir); - + spec = mn.getTile(face_dir); + /* Check temporary modifications on this node */ - core::map::Node *n; + /*core::map::Node *n; n = m_temp_mods.find(p); - // If modified if(n != NULL) { - struct NodeMod mod = n->getValue(); + struct NodeMod mod = n->getValue();*/ + NodeMod mod; + if(temp_mods.get(p, &mod)) + { if(mod.type == NODEMOD_CHANGECONTENT) { - spec.id = content_tile(mod.param, face_dir); + MapNode mn2(mod.param); + spec = mn2.getTile(face_dir); } if(mod.type == NODEMOD_CRACK) { - spec.feature = TILEFEAT_CRACK; - spec.param.crack.progression = mod.param; + /* + 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<getTextureId(os.str()); + + /*dstream<<"MapBlock::getNodeTile(): Switching from " + <getTexture(new_id); } } return spec; } -u8 MapBlock::getNodeContent(v3s16 p, MapNode mn) +u8 MapBlock::getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods) { /* Check temporary modifications on this node */ - core::map::Node *n; + /*core::map::Node *n; n = m_temp_mods.find(p); - // If modified if(n != NULL) { - struct NodeMod mod = n->getValue(); + struct NodeMod mod = n->getValue();*/ + NodeMod mod; + if(temp_mods.get(p, &mod)) + { if(mod.type == NODEMOD_CHANGECONTENT) { // Overrides content @@ -361,7 +399,8 @@ void MapBlock::updateFastFaceRow( v3f translate_dir_f, v3s16 face_dir, v3f face_dir_f, - core::array &dest) + core::array &dest, + NodeModMap &temp_mods) { v3s16 p = startpos; @@ -372,8 +411,8 @@ void MapBlock::updateFastFaceRow( u8 light = getFaceLight(daynight_ratio, n0, n1, face_dir); - TileSpec tile0 = getNodeTile(n0, p, face_dir); - TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir); + TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods); + TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods); for(u16 j=0; j fastfaces_new; v3f posRelative_f(getPosRelative().X, getPosRelative().Y, getPosRelative().Z); // floating point conversion + /* + Avoid interlocks by copying m_temp_mods + */ + NodeModMap temp_mods; + { + 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.85; + /* We are including the faces of the trailing edges of the block. This means that when something changes, the caller must @@ -587,8 +672,8 @@ void MapBlock::updateMesh(u32 daynight_ratio) */ { - // Lock this, as m_temp_mods will be used directly - JMutexAutoLock lock(m_temp_mods_mutex); + // 4-23ms for MAP_BLOCKSIZE=16 + //TimeTaker timer2("updateMesh() collect"); /* Go through every y,z and get top faces in rows of x+ @@ -601,7 +686,8 @@ void MapBlock::updateMesh(u32 daynight_ratio) v3f (1,0,0), v3s16(0,1,0), //face dir v3f (0,1,0), - fastfaces_new); + fastfaces_new, + temp_mods); } } /* @@ -615,7 +701,8 @@ void MapBlock::updateMesh(u32 daynight_ratio) v3f (0,0,1), v3s16(1,0,0), v3f (1,0,0), - fastfaces_new); + fastfaces_new, + temp_mods); } } /* @@ -629,7 +716,8 @@ void MapBlock::updateMesh(u32 daynight_ratio) v3f (1,0,0), v3s16(0,0,1), v3f (0,0,1), - fastfaces_new); + fastfaces_new, + temp_mods); } } } @@ -640,13 +728,20 @@ void MapBlock::updateMesh(u32 daynight_ratio) Convert FastFaces to SMesh */ - scene::SMesh *mesh_new = NULL; - - mesh_new = new scene::SMesh(); - + MeshCollector collector; + if(fastfaces_new.size() > 0) { - MeshCollector collector; + // avg 0ms (100ms spikes when loading textures the first time) + //TimeTaker timer2("updateMesh() mesh building"); + + video::SMaterial material; + material.Lighting = false; + material.BackfaceCulling = false; + material.setFlag(video::EMF_BILINEAR_FILTER, false); + //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF); + //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE); + material.setFlag(video::EMF_FOG_ENABLE, true); for(u32 i=0; igetTexture( - TextureSpec(name, path, mod)); - - video::SMaterial material = tile_material_get(f.tile.id); - material.setTexture(0, texture); + //video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec); + video::ITexture *texture = f.tile.texture.atlas; + if(texture == NULL) + continue; - collector.append(material, f.vertices, 4, indices, 6); - } - else - { - // No such feature - assert(0); - } + material.setTexture(0, texture); + + f.tile.applyMaterialOptions(material); + + collector.append(material, f.vertices, 4, indices, 6); } - - collector.fillMesh(mesh_new); - - // Use VBO for mesh (this just would set this for ever buffer) - //mesh_new->setHardwareMappingHint(scene::EHM_STATIC); - - /*std::cout<<"MapBlock has "<getSize()<<" faces " - <<"and uses "<getMeshBufferCount() - <<" materials (meshbuffers)"<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; zappend(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buf->getMaterial().MaterialType + video::SMaterial material; + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BACK_FACE_CULLING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + if(dir == v3s16(0,-1,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_floor.png")); + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_floor.png")); else if(dir == v3s16(0,1,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_ceiling.png")); + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_ceiling.png")); // For backwards compatibility else if(dir == v3s16(0,0,0)) - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch_on_floor.png")); + material.setTexture(0, + g_texturesource->getTextureRaw("torch_on_floor.png")); else - buf->getMaterial().setTexture(0, - g_irrlicht->getTexture("../data/torch.png")); + material.setTexture(0, + g_texturesource->getTextureRaw("torch.png")); - // Add to mesh - mesh_new->addMeshBuffer(buf); - buf->drop(); + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material, vertices, 4, indices, 6); + } + /* + Add flowing water to mesh + */ + else if(n.d == CONTENT_WATER) + { + bool top_is_water = false; + try{ + MapNode n = getNodeParent(v3s16(x,y+1,z)); + if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + top_is_water = true; + }catch(InvalidPositionException &e){} + + u8 l = decode_light(n.getLightBlend(daynight_ratio)); + video::SColor c(WATER_ALPHA,l,l,l); + + // Neighbor water levels (key = relative position) + // Includes current node + core::map neighbor_levels; + core::map neighbor_contents; + core::map neighbor_flags; + const u8 neighborflag_top_is_water = 0x01; + v3s16 neighbor_dirs[9] = { + v3s16(0,0,0), + v3s16(0,0,1), + v3s16(0,0,-1), + v3s16(1,0,0), + v3s16(-1,0,0), + v3s16(1,0,1), + v3s16(-1,0,-1), + v3s16(1,0,-1), + v3s16(-1,0,1), + }; + for(u32 i=0; i<9; i++) + { + u8 content = CONTENT_AIR; + float level = -0.5 * BS; + u8 flags = 0; + try{ + // Check neighbor + v3s16 p2 = p + neighbor_dirs[i]; + MapNode n2 = getNodeParent(p2); + + content = n2.d; + + if(n2.d == CONTENT_WATERSOURCE) + level = (-0.5+node_water_level) * BS; + else if(n2.d == CONTENT_WATER) + level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0 + * node_water_level) * BS; + + // Check node above neighbor. + // NOTE: This doesn't get executed if neighbor + // doesn't exist + p2.Y += 1; + n2 = getNodeParent(p2); + if(n2.d == CONTENT_WATERSOURCE || n2.d == CONTENT_WATER) + flags |= neighborflag_top_is_water; + } + catch(InvalidPositionException &e){} + + neighbor_levels.insert(neighbor_dirs[i], level); + neighbor_contents.insert(neighbor_dirs[i], content); + neighbor_flags.insert(neighbor_dirs[i], flags); + } + + //float water_level = (-0.5 + ((float)n.param2 + 0.5) / 8.0) * BS; + //float water_level = neighbor_levels[v3s16(0,0,0)]; + + // Corner heights (average between four waters) + f32 corner_levels[4]; + + v3s16 halfdirs[4] = { + v3s16(0,0,0), + v3s16(1,0,0), + v3s16(1,0,1), + v3s16(0,0,1), + }; + for(u32 i=0; i<4; i++) + { + v3s16 cornerdir = halfdirs[i]; + float cornerlevel = 0; + u32 valid_count = 0; + for(u32 j=0; j<4; j++) + { + v3s16 neighbordir = cornerdir - halfdirs[j]; + u8 content = neighbor_contents[neighbordir]; + // Special case for source nodes + if(content == CONTENT_WATERSOURCE) + { + cornerlevel = (-0.5+node_water_level)*BS; + valid_count = 1; + break; + } + else if(content == CONTENT_WATER) + { + cornerlevel += neighbor_levels[neighbordir]; + valid_count++; + } + else if(content == CONTENT_AIR) + { + cornerlevel += -0.5*BS; + valid_count++; + } + } + if(valid_count > 0) + cornerlevel /= valid_count; + corner_levels[i] = cornerlevel; + } + + /* + Generate sides + */ + + v3s16 side_dirs[4] = { + v3s16(1,0,0), + v3s16(-1,0,0), + v3s16(0,0,1), + v3s16(0,0,-1), + }; + s16 side_corners[4][2] = { + {1, 2}, + {3, 0}, + {2, 3}, + {0, 1}, + }; + for(u32 i=0; i<4; i++) + { + v3s16 dir = side_dirs[i]; + + /* + If our topside is water and neighbor's topside + is water, don't draw side face + */ + if(top_is_water && + neighbor_flags[dir] & neighborflag_top_is_water) + continue; + + u8 neighbor_content = neighbor_contents[dir]; + + // Don't draw face if neighbor is not air or water + if(neighbor_content != CONTENT_AIR + && neighbor_content != CONTENT_WATER) + continue; + + bool neighbor_is_water = (neighbor_content == CONTENT_WATER); + + // Don't draw any faces if neighbor is water and top is water + if(neighbor_is_water == true && top_is_water == false) + continue; + + 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, 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, + 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 our topside is water, set upper border of face + at upper border of node + */ + if(top_is_water) + { + vertices[2].Pos.Y = 0.5*BS; + vertices[3].Pos.Y = 0.5*BS; + } + /* + Otherwise upper position of face is corner levels + */ + else + { + vertices[2].Pos.Y = corner_levels[side_corners[i][0]]; + vertices[3].Pos.Y = corner_levels[side_corners[i][1]]; + } + + /* + If neighbor is water, lower border of face is corner + water levels + */ + if(neighbor_is_water) + { + vertices[0].Pos.Y = corner_levels[side_corners[i][1]]; + vertices[1].Pos.Y = corner_levels[side_corners[i][0]]; + } + /* + If neighbor is not water, lower border of face is + lower border of node + */ + else + { + vertices[0].Pos.Y = -0.5*BS; + vertices[1].Pos.Y = -0.5*BS; + } + + for(s32 j=0; j<4; j++) + { + if(dir == v3s16(0,0,1)) + vertices[j].Pos.rotateXZBy(0); + if(dir == v3s16(0,0,-1)) + vertices[j].Pos.rotateXZBy(180); + if(dir == v3s16(-1,0,0)) + vertices[j].Pos.rotateXZBy(90); + if(dir == v3s16(1,0,-0)) + vertices[j].Pos.rotateXZBy(-90); + + vertices[j].Pos += intToFloat(p + getPosRelative()); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_water1, vertices, 4, indices, 6); + } + + /* + Generate top side, if appropriate + */ + + if(top_is_water == false) + { + 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, 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, + 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)]; + s32 j = corner_resolve[i]; + vertices[i].Pos.Y += corner_levels[j]; + vertices[i].Pos += intToFloat(p + getPosRelative()); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_water1, vertices, 4, indices, 6); + } + } + /* + Add water sources to mesh if using new style + */ + else if(n.d == CONTENT_WATERSOURCE && new_style_water) + { + //bool top_is_water = false; + bool top_is_air = false; + try{ + MapNode n = getNodeParent(v3s16(x,y+1,z)); + /*if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + top_is_water = true;*/ + if(n.d == CONTENT_AIR) + top_is_air = true; + }catch(InvalidPositionException &e){} + + /*if(top_is_water == true) + continue;*/ + if(top_is_air == false) + continue; + + u8 l = decode_light(n.getLightBlend(daynight_ratio)); + video::SColor c(WATER_ALPHA,l,l,l); + + 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, 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, + 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()); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + 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()); + } + + 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); + /* Do some stuff to the mesh */ @@ -790,6 +1272,26 @@ void MapBlock::updateMesh(u32 daynight_ratio) mesh_new = NULL; } + if(mesh_new) + { +#if 0 + // Usually 1-700 faces and 1-7 materials + std::cout<<"Updated MapBlock has "<getMeshBufferCount() + <<" materials (meshbuffers)"<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 */ @@ -857,12 +1359,21 @@ void MapBlock::updateMesh(u32 daynight_ratio) If there is a block above, continues from it. If there is no block above, assumes there is sunlight, unless - is_underground is set. + is_underground is set or highest node is water. At the moment, all sunlighted nodes are added to light_sources. - TODO: This could be optimized. + - SUGG: This could be optimized + + Turns sunglighted mud into grass. + + if remove_light==true, sets non-sunlighted nodes black. + + if black_air_left!=NULL, it is set to true if non-sunlighted + air is left in block. */ -bool MapBlock::propagateSunlight(core::map & light_sources) +bool MapBlock::propagateSunlight(core::map & light_sources, + bool remove_light, bool *black_air_left, + bool grow_grass) { // Whether the sunlight at the top of the bottom block is valid bool block_below_is_valid = true; @@ -873,6 +1384,7 @@ bool MapBlock::propagateSunlight(core::map & light_sources) { for(s16 z=0; z & light_sources) MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) { - /*if(is_underground) - { - no_sunlight = true; - }*/ no_sunlight = true; } } @@ -891,18 +1399,41 @@ bool MapBlock::propagateSunlight(core::map & light_sources) { no_top_block = true; - // TODO: This makes over-ground roofed places sunlighted + // NOTE: This makes over-ground roofed places sunlighted // Assume sunlight, unless is_underground==true if(is_underground) { no_sunlight = true; } - - // TODO: There has to be some way to allow this behaviour - // As of now, it just makes everything dark. + else + { + MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z)); + if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + { + no_sunlight = true; + } + } + // NOTE: As of now, this just would make everything dark. // No sunlight here //no_sunlight = true; } +#endif +#if 0 // Doesn't work; nothing gets light. + bool no_sunlight = true; + bool no_top_block = false; + // Check if node above block has sunlight + try{ + MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); + if(n.getLight(LIGHTBANK_DAY) == LIGHT_SUN) + { + no_sunlight = false; + } + } + catch(InvalidPositionException &e) + { + no_top_block = true; + } +#endif /*std::cout<<"("<d<