X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapblock_mesh.cpp;h=b843448c484c1cb70461d80593d4d27f433f6b1e;hb=2b200d481fd919752bdb786142e5eb41c3932537;hp=d4921c2c5d166086deeb60d0f55319155ccddb03;hpb=f37a3a84fafb91bcfc109fed95aa6d42726f1bf7;p=dragonfireclient.git diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index d4921c2c5..b843448c4 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -22,6 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "map.h" #include "main.h" // For g_settings and g_texturesource +#include "settings.h" +#include "profiler.h" +#include "nodedef.h" +#include "gamedef.h" #include "content_mapblock.h" void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block) @@ -64,11 +68,7 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block) */ // Get map - NodeContainer *parentcontainer = block->getParent(); - // This will only work if the parent is the map - assert(parentcontainer->nodeContainerId() == NODECONTAINER_ID_MAP); - // OK, we have the map! - Map *map = (Map*)parentcontainer; + Map *map = block->getParent(); for(u16 i=0; i<6; i++) { @@ -81,10 +81,43 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block) } } +void MeshMakeData::fillSingleNode(u32 daynight_ratio, MapNode *node) +{ + m_daynight_ratio = daynight_ratio; + m_blockpos = v3s16(0,0,0); + m_temp_mods.clear(); + + v3s16 blockpos_nodes = v3s16(0,0,0); + VoxelArea area(blockpos_nodes-v3s16(1,1,1)*MAP_BLOCKSIZE, + blockpos_nodes+v3s16(1,1,1)*MAP_BLOCKSIZE*2-v3s16(1,1,1)); + s32 volume = area.getVolume(); + s32 our_node_index = area.index(1,1,1); + + // Allocate this block + neighbors + m_vmanip.clear(); + m_vmanip.addArea(area); + + // Fill in data + MapNode *data = new MapNode[volume]; + for(s32 i = 0; i < volume; i++) + { + if(i == our_node_index) + { + data[i] = *node; + } + else + { + data[i] = MapNode(CONTENT_AIR, LIGHT_MAX, 0); + } + } + m_vmanip.copyFrom(data, area, area.MinEdge, area.MinEdge, area.getExtent()); + delete[] data; +} + /* vertex_dirs: v3s16[4] */ -void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) +static void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) { /* If looked from outside the node towards the face, the corners are: @@ -144,9 +177,24 @@ void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) } } -inline video::SColor lightColor(u8 alpha, u8 light) +video::SColor MapBlock_LightColor(u8 alpha, u8 light) { +#if 0 return video::SColor(alpha,light,light,light); +#endif + //return video::SColor(alpha,light,light,MYMAX(0, (s16)light-25)+25); + /*return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/255.0, 0.8)*255.0));*/ +#if 1 + // Emphase blue a bit in darker places + float lim = 80; + float power = 0.8; + if(light > lim) + return video::SColor(alpha,light,light,light); + else + return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/lim, power)*lim)); +#endif } struct FastFace @@ -155,7 +203,7 @@ struct FastFace video::S3DVertex vertices[4]; // Precalculated vertices }; -void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, +static void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, v3s16 dir, v3f scale, v3f posRelative_f, core::array &dest) { @@ -190,8 +238,8 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, else if(scale.Y < 0.999 || scale.Y > 1.001) abs_scale = scale.Y; else if(scale.Z < 0.999 || scale.Z > 1.001) abs_scale = scale.Z; - v3f zerovector = v3f(0,0,0); - + v3f normal(dir.X, dir.Y, dir.Z); + u8 alpha = tile.alpha; /*u8 alpha = 255; if(tile.id == TILE_WATER) @@ -202,7 +250,7 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, float w = tile.texture.size.X; float h = tile.texture.size.Y; - /*video::SColor c = lightColor(alpha, li); + /*video::SColor c = MapBlock_LightColor(alpha, li); face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c, core::vector2d(x0+w*abs_scale, y0+h)); @@ -213,17 +261,17 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), c, core::vector2d(x0+w*abs_scale, y0));*/ - face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), - lightColor(alpha, li0), + face.vertices[0] = video::S3DVertex(vertex_pos[0], normal, + MapBlock_LightColor(alpha, li0), core::vector2d(x0+w*abs_scale, y0+h)); - face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), - lightColor(alpha, li1), + face.vertices[1] = video::S3DVertex(vertex_pos[1], normal, + MapBlock_LightColor(alpha, li1), core::vector2d(x0, y0+h)); - face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), - lightColor(alpha, li2), + face.vertices[2] = video::S3DVertex(vertex_pos[2], normal, + MapBlock_LightColor(alpha, li2), core::vector2d(x0, y0)); - face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), - lightColor(alpha, li3), + face.vertices[3] = video::S3DVertex(vertex_pos[3], normal, + MapBlock_LightColor(alpha, li3), core::vector2d(x0+w*abs_scale, y0)); face.tile = tile; @@ -233,15 +281,48 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, dest.push_back(face); } +static TileSpec getTile(const MapNode &node, v3s16 dir, INodeDefManager *nodemgr) +{ + // Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0), + // (0,0,1), (0,0,-1) or (0,0,0) + assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z <= 1); + + // Convert direction to single integer for table lookup + // 0 = (0,0,0) + // 1 = (1,0,0) + // 2 = (0,1,0) + // 3 = (0,0,1) + // 4 = invalid, treat as (0,0,0) + // 5 = (0,0,-1) + // 6 = (0,-1,0) + // 7 = (-1,0,0) + u8 dir_i = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7; + + // Get rotation for things like chests + u8 facedir = node.getFaceDir(nodemgr); + assert(facedir <= 3); + + static const u8 dir_to_tile[4 * 8] = + { + // 0 +X +Y +Z 0 -Z -Y -X + 0, 2, 0, 4, 0, 5, 1, 3, // facedir = 0 + 0, 4, 0, 3, 0, 2, 1, 5, // facedir = 1 + 0, 3, 0, 5, 0, 4, 1, 2, // facedir = 2 + 0, 5, 0, 2, 0, 3, 1, 4, // facedir = 3 + }; + + return nodemgr->get(node).tiles[dir_to_tile[facedir*8 + dir_i]]; +} + /* Gets node tile from any place relative to block. Returns TILE_NODE if doesn't exist or should not be drawn. */ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, - NodeModMap &temp_mods) + NodeModMap *temp_mods, ITextureSource *tsrc, INodeDefManager *ndef) { TileSpec spec; - spec = mn.getTile(face_dir); + spec = getTile(mn, face_dir, ndef); /* Check temporary modifications on this node @@ -253,13 +334,15 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, { struct NodeMod mod = n->getValue();*/ NodeMod mod; - if(temp_mods.get(p, &mod)) + if(temp_mods && temp_mods->get(p, &mod)) { + #if 0 // NODEMOD_CHANGECONTENT isn't used at the moment if(mod.type == NODEMOD_CHANGECONTENT) { MapNode mn2(mod.param); - spec = mn2.getTile(face_dir); + spec = getTile(mn2, face_dir, ndef); } + #endif if(mod.type == NODEMOD_CRACK) { /* @@ -269,39 +352,34 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, // Get original texture name u32 orig_id = spec.texture.id; - std::string orig_name = g_texturesource->getTextureName(orig_id); + std::string orig_name = tsrc->getTextureName(orig_id); // Create new texture name std::ostringstream os; os<getTextureId(os.str()); + u32 new_id = tsrc->getTextureId(os.str()); /*dstream<<"MapBlock::getNodeTile(): Switching from " <getTexture(new_id); + spec.texture = tsrc->getTexture(new_id); } } return spec; } -u8 getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods) +static content_t getNodeContent(v3s16 p, MapNode mn, NodeModMap *temp_mods) { /* Check temporary modifications on this node */ - /*core::map::Node *n; - n = m_temp_mods.find(p); - // If modified - if(n != NULL) - { - struct NodeMod mod = n->getValue();*/ + #if 0 // NODEMOD_CHANGECONTENT isn't used at the moment NodeMod mod; - if(temp_mods.get(p, &mod)) + if(temp_mods && temp_mods->get(p, &mod)) { if(mod.type == NODEMOD_CHANGECONTENT) { @@ -323,8 +401,9 @@ u8 getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods) */ } } + #endif - return mn.d; + return mn.getContent(); } v3s16 dirs8[8] = { @@ -339,7 +418,8 @@ v3s16 dirs8[8] = { }; // Calculate lighting at the XYZ- corner of p -u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio) +static u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio, + INodeDefManager *ndef) { u16 ambient_occlusion = 0; u16 light = 0; @@ -347,16 +427,16 @@ u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio) for(u32 i=0; i<8; i++) { MapNode n = vmanip.getNodeNoEx(p - dirs8[i]); - if(content_features(n.d).param_type == CPT_LIGHT + if(ndef->get(n).param_type == CPT_LIGHT // Fast-style leaves look better this way - && content_features(n.d).solidness != 2) + && ndef->get(n).solidness != 2) { - light += decode_light(n.getLightBlend(daynight_ratio)); + light += decode_light(n.getLightBlend(daynight_ratio, ndef)); light_count++; } else { - if(n.d != CONTENT_IGNORE) + if(n.getContent() != CONTENT_IGNORE) ambient_occlusion++; } } @@ -376,8 +456,8 @@ u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio) } // Calculate lighting at the given corner of p -u8 getSmoothLight(v3s16 p, v3s16 corner, - VoxelManipulator &vmanip, u32 daynight_ratio) +static u8 getSmoothLight(v3s16 p, v3s16 corner, + VoxelManipulator &vmanip, u32 daynight_ratio, INodeDefManager *ndef) { if(corner.X == 1) p.X += 1; else assert(corner.X == -1); @@ -386,18 +466,19 @@ u8 getSmoothLight(v3s16 p, v3s16 corner, if(corner.Z == 1) p.Z += 1; else assert(corner.Z == -1); - return getSmoothLight(p, vmanip, daynight_ratio); + return getSmoothLight(p, vmanip, daynight_ratio, ndef); } -void getTileInfo( +static void getTileInfo( // Input: v3s16 blockpos_nodes, v3s16 p, v3s16 face_dir, u32 daynight_ratio, VoxelManipulator &vmanip, - NodeModMap &temp_mods, + NodeModMap *temp_mods, bool smooth_lighting, + IGameDef *gamedef, // Output: bool &makes_face, v3s16 &p_corrected, @@ -406,15 +487,19 @@ void getTileInfo( TileSpec &tile ) { + ITextureSource *tsrc = gamedef->tsrc(); + INodeDefManager *ndef = gamedef->ndef(); + 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); + TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods, tsrc, ndef); + TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods, tsrc, ndef); // 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); + content_t content0 = getNodeContent(p, n0, temp_mods); + content_t content1 = getNodeContent(p + face_dir, n1, temp_mods); + bool equivalent = false; + u8 mf = face_contents(content0, content1, &equivalent, ndef); if(mf == 0) { @@ -437,10 +522,14 @@ void getTileInfo( face_dir_corrected = -face_dir; } + // eg. water and glass + if(equivalent) + tile.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING; + if(smooth_lighting == false) { lights[0] = lights[1] = lights[2] = lights[3] = - decode_light(getFaceLight(daynight_ratio, n0, n1, face_dir)); + decode_light(getFaceLight(daynight_ratio, n0, n1, face_dir, ndef)); } else { @@ -449,7 +538,7 @@ void getTileInfo( for(u16 i=0; i<4; i++) { lights[i] = getSmoothLight(blockpos_nodes + p_corrected, - vertex_dirs[i], vmanip, daynight_ratio); + vertex_dirs[i], vmanip, daynight_ratio, ndef); } } @@ -461,7 +550,7 @@ void getTileInfo( translate_dir: unit vector with only one of x, y or z face_dir: unit vector with only one of x, y or z */ -void updateFastFaceRow( +static void updateFastFaceRow( u32 daynight_ratio, v3f posRelative_f, v3s16 startpos, @@ -471,22 +560,23 @@ void updateFastFaceRow( v3s16 face_dir, v3f face_dir_f, core::array &dest, - NodeModMap &temp_mods, + NodeModMap *temp_mods, VoxelManipulator &vmanip, v3s16 blockpos_nodes, - bool smooth_lighting) + bool smooth_lighting, + IGameDef *gamedef) { v3s16 p = startpos; u16 continuous_tiles_count = 0; - bool makes_face; + bool makes_face = false; v3s16 p_corrected; v3s16 face_dir_corrected; - u8 lights[4]; + u8 lights[4] = {0,0,0,0}; TileSpec tile; getTileInfo(blockpos_nodes, p, face_dir, daynight_ratio, - vmanip, temp_mods, smooth_lighting, + vmanip, temp_mods, smooth_lighting, gamedef, makes_face, p_corrected, face_dir_corrected, lights, tile); for(u16 j=0; jadd("Meshgen: diff: next_makes_face != makes_face", + next_makes_face != makes_face ? 1 : 0); + g_profiler->add("Meshgen: diff: n_p_corr != p_corr + t_dir", + (next_p_corrected != p_corrected + translate_dir) ? 1 : 0); + g_profiler->add("Meshgen: diff: next_f_dir_corr != f_dir_corr", + next_face_dir_corrected != face_dir_corrected ? 1 : 0); + g_profiler->add("Meshgen: diff: next_lights[] != lights[]", + (next_lights[0] != lights[0] || + next_lights[0] != lights[0] || + next_lights[0] != lights[0] || + next_lights[0] != lights[0]) ? 1 : 0); + g_profiler->add("Meshgen: diff: !(next_tile == tile)", + !(next_tile == tile) ? 1 : 0); + }*/ + } + /*g_profiler->add("Meshgen: Total faces checked", 1); + if(makes_face) + g_profiler->add("Meshgen: Total makes_face checked", 1);*/ + } else { + /*if(makes_face) + g_profiler->add("Meshgen: diff: last position", 1);*/ } continuous_tiles_count++; @@ -556,6 +669,8 @@ void updateFastFaceRow( v3f pf(p_corrected.X, p_corrected.Y, p_corrected.Z); // Center point of face (kind of) v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f; + if(continuous_tiles_count != 1) + sp += translate_dir_f; v3f scale(1,1,1); if(translate_dir.X != 0) @@ -574,6 +689,11 @@ void updateFastFaceRow( makeFastFace(tile, lights[0], lights[1], lights[2], lights[3], sp, face_dir_corrected, scale, posRelative_f, dest); + + g_profiler->avg("Meshgen: faces drawn by tiling", 0); + for(int i=1; iavg("Meshgen: faces drawn by tiling", 1); + } } continuous_tiles_count = 0; @@ -592,7 +712,7 @@ void updateFastFaceRow( } } -scene::SMesh* makeMapBlockMesh(MeshMakeData *data) +scene::SMesh* makeMapBlockMesh(MeshMakeData *data, IGameDef *gamedef) { // 4-21ms for MAP_BLOCKSIZE=16 // 24-155ms for MAP_BLOCKSIZE=32 @@ -608,9 +728,9 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) /* Some settings */ - //bool new_style_water = g_settings.getBool("new_style_water"); - //bool new_style_leaves = g_settings.getBool("new_style_leaves"); - bool smooth_lighting = g_settings.getBool("smooth_lighting"); + //bool new_style_water = g_settings->getBool("new_style_water"); + //bool new_style_leaves = g_settings->getBool("new_style_leaves"); + bool smooth_lighting = g_settings->getBool("smooth_lighting"); /* We are including the faces of the trailing edges of the block. @@ -636,10 +756,11 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) v3s16(0,1,0), //face dir v3f (0,1,0), fastfaces_new, - data->m_temp_mods, + &data->m_temp_mods, data->m_vmanip, blockpos_nodes, - smooth_lighting); + smooth_lighting, + gamedef); } } /* @@ -654,10 +775,11 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) v3s16(1,0,0), v3f (1,0,0), fastfaces_new, - data->m_temp_mods, + &data->m_temp_mods, data->m_vmanip, blockpos_nodes, - smooth_lighting); + smooth_lighting, + gamedef); } } /* @@ -672,10 +794,11 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) v3s16(0,0,1), v3f (0,0,1), fastfaces_new, - data->m_temp_mods, + &data->m_temp_mods, data->m_vmanip, blockpos_nodes, - smooth_lighting); + smooth_lighting, + gamedef); } } } @@ -695,10 +818,13 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data) video::SMaterial material; material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BACK_FACE_CULLING, true); material.setFlag(video::EMF_BILINEAR_FILTER, false); 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); + material.MaterialType + = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; for(u32 i=0; i