X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapblock.cpp;h=58b23bd146e6001d50055a18357c1e1ae308bde7;hb=94c9686020798c8ec8113c242dc1dfe0c2accf71;hp=69834b56a824590c0f6dc4275dafdfd322d3565d;hpb=8c1f7a0dd27782cfc85dce624ccc4e3276f18776;p=minetest.git diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 69834b56a..58b23bd14 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -133,58 +133,94 @@ u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, #ifndef SERVER -inline video::SColor lightColor(u8 alpha, u8 light) -{ - return video::SColor(alpha,light,light,light); -} - -void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, - v3s16 dir, v3f scale, v3f posRelative_f, - core::array &dest) +/* + vertex_dirs: v3s16[4] +*/ +void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) { - FastFace face; - - // Position is at the center of the cube. - v3f pos = p * BS; - posRelative_f *= BS; - - 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); - + /* + If looked from outside the node towards the face, the corners are: + 0: bottom-right + 1: bottom-left + 2: top-left + 3: top-right + */ if(dir == v3s16(0,0,1)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(0); + // If looking towards z+, this is the face that is behind + // the center point, facing towards z+. + vertex_dirs[0] = v3s16(-1,-1, 1); + vertex_dirs[1] = v3s16( 1,-1, 1); + vertex_dirs[2] = v3s16( 1, 1, 1); + vertex_dirs[3] = v3s16(-1, 1, 1); } else if(dir == v3s16(0,0,-1)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(180); + // faces towards Z- + vertex_dirs[0] = v3s16( 1,-1,-1); + vertex_dirs[1] = v3s16(-1,-1,-1); + vertex_dirs[2] = v3s16(-1, 1,-1); + vertex_dirs[3] = v3s16( 1, 1,-1); } else if(dir == v3s16(1,0,0)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(-90); + // faces towards X+ + vertex_dirs[0] = v3s16( 1,-1, 1); + vertex_dirs[1] = v3s16( 1,-1,-1); + vertex_dirs[2] = v3s16( 1, 1,-1); + vertex_dirs[3] = v3s16( 1, 1, 1); } else if(dir == v3s16(-1,0,0)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateXZBy(90); + // faces towards X- + vertex_dirs[0] = v3s16(-1,-1,-1); + vertex_dirs[1] = v3s16(-1,-1, 1); + vertex_dirs[2] = v3s16(-1, 1, 1); + vertex_dirs[3] = v3s16(-1, 1,-1); } else if(dir == v3s16(0,1,0)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateYZBy(-90); + // faces towards Y+ (assume Z- as "down" in texture) + vertex_dirs[0] = v3s16( 1, 1,-1); + vertex_dirs[1] = v3s16(-1, 1,-1); + vertex_dirs[2] = v3s16(-1, 1, 1); + vertex_dirs[3] = v3s16( 1, 1, 1); } else if(dir == v3s16(0,-1,0)) { - for(u16 i=0; i<4; i++) - vertex_pos[i].rotateYZBy(90); + // faces towards Y- (assume Z+ as "down" in texture) + vertex_dirs[0] = v3s16( 1,-1, 1); + vertex_dirs[1] = v3s16(-1,-1, 1); + vertex_dirs[2] = v3s16(-1,-1,-1); + vertex_dirs[3] = v3s16( 1,-1,-1); + } +} + +inline video::SColor lightColor(u8 alpha, u8 light) +{ + return video::SColor(alpha,light,light,light); +} + +void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, + v3s16 dir, v3f scale, v3f posRelative_f, + core::array &dest) +{ + FastFace face; + + // Position is at the center of the cube. + v3f pos = p * BS; + posRelative_f *= BS; + + v3f vertex_pos[4]; + v3s16 vertex_dirs[4]; + getNodeVertexDirs(dir, vertex_dirs); + for(u16 i=0; i<4; i++) + { + vertex_pos[i] = v3f( + BS/2*vertex_dirs[i].X, + BS/2*vertex_dirs[i].Y, + BS/2*vertex_dirs[i].Z + ); } for(u16 i=0; i<4; i++) @@ -383,6 +419,87 @@ u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio) return light; } +// Calculate lighting at the given corner of p +u8 getSmoothLight(v3s16 p, v3s16 corner, + VoxelManipulator &vmanip, u32 daynight_ratio) +{ + if(corner.X == 1) p.X += 1; + else assert(corner.X == -1); + if(corner.Y == 1) p.Y += 1; + else assert(corner.Y == -1); + if(corner.Z == 1) p.Z += 1; + else assert(corner.Z == -1); + + return getSmoothLight(p, vmanip, daynight_ratio); +} + +void getTileInfo( + // Input: + v3s16 blockpos_nodes, + v3s16 p, + v3s16 face_dir, + u32 daynight_ratio, + VoxelManipulator &vmanip, + NodeModMap &temp_mods, + bool smooth_lighting, + // Output: + bool &makes_face, + v3s16 &p_corrected, + v3s16 &face_dir_corrected, + u8 *lights, + TileSpec &tile + ) +{ + MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p); + MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir); + TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods); + TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods); + + // This is hackish + u8 content0 = getNodeContent(p, n0, temp_mods); + u8 content1 = getNodeContent(p + face_dir, n1, temp_mods); + u8 mf = face_contents(content0, content1); + + if(mf == 0) + { + makes_face = false; + return; + } + + makes_face = true; + + if(mf == 1) + { + tile = tile0; + p_corrected = p; + face_dir_corrected = face_dir; + } + else + { + tile = tile1; + p_corrected = p + face_dir; + face_dir_corrected = -face_dir; + } + + if(smooth_lighting == false) + { + lights[0] = lights[1] = lights[2] = lights[3] = + decode_light(getFaceLight(daynight_ratio, n0, n1, face_dir)); + } + else + { + v3s16 vertex_dirs[4]; + getNodeVertexDirs(face_dir_corrected, vertex_dirs); + for(u16 i=0; i<4; i++) + { + lights[i] = getSmoothLight(blockpos_nodes + p_corrected, + vertex_dirs[i], vmanip, daynight_ratio); + } + } + + return; +} + /* startpos: translate_dir: unit vector with only one of x, y or z @@ -400,28 +517,34 @@ void updateFastFaceRow( core::array &dest, NodeModMap &temp_mods, VoxelManipulator &vmanip, - v3s16 blockpos_nodes) + v3s16 blockpos_nodes, + bool smooth_lighting) { v3s16 p = startpos; u16 continuous_tiles_count = 0; - MapNode n0 = vmanip.getNodeNoEx(blockpos_nodes + p); - MapNode n1 = vmanip.getNodeNoEx(blockpos_nodes + p + face_dir); - TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods); - TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods); - u8 light = getFaceLight(daynight_ratio, n0, n1, face_dir); + bool makes_face; + v3s16 p_corrected; + v3s16 face_dir_corrected; + u8 lights[4]; + TileSpec tile; + getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio, + vmanip, temp_mods, smooth_lighting, + makes_face, p_corrected, face_dir_corrected, lights, tile); for(u16 j=0; jm_temp_mods, data->m_vmanip, - blockpos_nodes); + blockpos_nodes, + smooth_lighting); } } /* @@ -779,7 +797,8 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) fastfaces_new, data->m_temp_mods, data->m_vmanip, - blockpos_nodes); + blockpos_nodes, + smooth_lighting); } } /* @@ -796,7 +815,8 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) fastfaces_new, data->m_temp_mods, data->m_vmanip, - blockpos_nodes); + blockpos_nodes, + smooth_lighting); } } } @@ -826,6 +846,7 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) FastFace &f = fastfaces_new[i]; const u16 indices[] = {0,1,2,2,3,0}; + const u16 indices_alternate[] = {0,1,3,2,3,1}; video::ITexture *texture = f.tile.texture.atlas; if(texture == NULL) @@ -834,8 +855,18 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) material.setTexture(0, texture); f.tile.applyMaterialOptions(material); + + const u16 *indices_p = indices; + + /* + Revert triangles for nicer looking gradient if vertices + 1 and 3 have same color or 0 and 2 have different color. + */ + if(f.vertices[0].Color != f.vertices[2].Color + || f.vertices[1].Color == f.vertices[3].Color) + indices_p = indices_alternate; - collector.append(material, f.vertices, 4, indices, 6); + collector.append(material, f.vertices, 4, indices_p, 6); } } @@ -870,6 +901,17 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) g_texturesource->getTextureId("leaves.png")); material_leaves1.setTexture(0, pa_leaves1.atlas); + // Glass material + video::SMaterial material_glass; + material_glass.setFlag(video::EMF_LIGHTING, false); + material_glass.setFlag(video::EMF_BILINEAR_FILTER, false); + material_glass.setFlag(video::EMF_FOG_ENABLE, true); + material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_glass = g_texturesource->getTexture( + g_texturesource->getTextureId("glass.png")); + material_glass.setTexture(0, pa_glass.atlas); + + for(s16 z=0; zm_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, + pa_glass.x0(), pa_glass.y1()), + video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, + pa_glass.x1(), pa_glass.y1()), + video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, + pa_glass.x1(), pa_glass.y0()), + video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, + pa_glass.x0(), pa_glass.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 + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_glass, vertices, 4, indices, 6); + } + } + + + } /* @@ -2078,9 +2186,17 @@ void MapBlock::serialize(std::ostream &os, u8 version) { if(version <= 15) { - std::ostringstream oss(std::ios_base::binary); - m_node_metadata.serialize(oss); - os<