Use vertices with tangents only when its needed.
authorRealBadAngel <maciej.kasatkin@o2.pl>
Fri, 12 Feb 2016 11:25:20 +0000 (12:25 +0100)
committerparamat <mat.gregory@virginmedia.com>
Mon, 15 Feb 2016 06:05:39 +0000 (06:05 +0000)
src/client.cpp
src/client.h
src/mapblock_mesh.cpp
src/mapblock_mesh.h

index 2dc537782b0dbac1931a15a5c3366673549b0b3a..ed5ff96fefad4f3c24fddda1931ff37712820a36 100644 (file)
@@ -263,6 +263,9 @@ Client::Client(
 
        m_cache_smooth_lighting = g_settings->getBool("smooth_lighting");
        m_cache_enable_shaders  = g_settings->getBool("enable_shaders");
+       m_cache_use_tangent_vertices = m_cache_enable_shaders && (
+               g_settings->getBool("enable_bumpmapping") || 
+               g_settings->getBool("enable_parallax_occlusion"));
 }
 
 void Client::Stop()
@@ -1582,7 +1585,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
                Create a task to update the mesh of the block
        */
 
-       MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders);
+       MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders,
+               m_cache_use_tangent_vertices);
 
        {
                //TimeTaker timer("data fill");
index 98a8bc12970cf1897d6d8359c8fbe0db12f6fc36..c16e9b77aee6f1d9fdab26607fa4d3455e88af6a 100644 (file)
@@ -677,6 +677,7 @@ private:
        // TODO: Add callback to update these when g_settings changes
        bool m_cache_smooth_lighting;
        bool m_cache_enable_shaders;
+       bool m_cache_use_tangent_vertices;
 
        DISABLE_CLASS_COPY(Client);
 };
index 9486220e0138bdf3c33a07f2a92e889fa01a0c6c..8b3d3c0dd1f8d8552a9c4cb5881d8ea3bfaa3931 100644 (file)
@@ -33,24 +33,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/directiontables.h"
 #include <IMeshManipulator.h>
 
-static void applyFacesShading(video::SColor& color, float factor)
+static void applyFacesShading(video::SColor &color, const float factor)
 {
-       color.setRed(core::clamp(core::round32(color.getRed()*factor), 0, 255));
-       color.setGreen(core::clamp(core::round32(color.getGreen()*factor), 0, 255));
+       color.setRed(core::clamp(core::round32(color.getRed() * factor), 0, 255));
+       color.setGreen(core::clamp(core::round32(color.getGreen() * factor), 0, 255));
 }
 
 /*
        MeshMakeData
 */
 
-MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders):
+MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders,
+               bool use_tangent_vertices):
        m_vmanip(),
        m_blockpos(-1337,-1337,-1337),
        m_crack_pos_relative(-1337, -1337, -1337),
        m_smooth_lighting(false),
        m_show_hud(false),
        m_gamedef(gamedef),
-       m_use_shaders(use_shaders)
+       m_use_shaders(use_shaders),
+       m_use_tangent_vertices(use_tangent_vertices)
 {}
 
 void MeshMakeData::fill(MapBlock *block)
@@ -1032,6 +1034,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
        m_daynight_diffs()
 {
        m_enable_shaders = data->m_use_shaders;
+       m_use_tangent_vertices = data->m_use_tangent_vertices;
 
        if (g_settings->getBool("enable_minimap")) {
                m_minimap_mapblock = new MinimapMapblock;
@@ -1064,15 +1067,14 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                Convert FastFaces to MeshCollector
        */
 
-       MeshCollector collector;
+       MeshCollector collector(m_use_tangent_vertices);
 
        {
                // avg 0ms (100ms spikes when loading textures the first time)
                // (NOTE: probably outdated)
                //TimeTaker timer2("MeshCollector building");
 
-               for(u32 i=0; i<fastfaces_new.size(); i++)
-               {
+               for (u32 i = 0; i < fastfaces_new.size(); i++) {
                        FastFace &f = fastfaces_new[i];
 
                        const u16 indices[] = {0,1,2,2,3,0};
@@ -1150,35 +1152,43 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                        p.tile.texture = animation_frame.texture;
                }
 
-               for(u32 j = 0; j < p.vertices.size(); j++)
-               {
-                       video::S3DVertex *vertex = &p.vertices[j];
+               u32 vertex_count = m_use_tangent_vertices ?
+                       p.tangent_vertices.size() : p.vertices.size();
+               for (u32 j = 0; j < vertex_count; j++) {
+                       v3f *Normal;
+                       video::SColor *vc;
+                       if (m_use_tangent_vertices) {
+                               vc = &p.tangent_vertices[j].Color;
+                               Normal = &p.tangent_vertices[j].Normal;
+                       } else {
+                               vc = &p.vertices[j].Color;
+                               Normal = &p.vertices[j].Normal;
+                       }
                        // Note applyFacesShading second parameter is precalculated sqrt
                        // value for speed improvement
                        // Skip it for lightsources and top faces.
-                       video::SColor &vc = vertex->Color;
-                       if (!vc.getBlue()) {
-                               if (vertex->Normal.Y < -0.5) {
-                                       applyFacesShading (vc, 0.447213);
-                               } else if (vertex->Normal.X > 0.5) {
-                                       applyFacesShading (vc, 0.670820);
-                               } else if (vertex->Normal.X < -0.5) {
-                                       applyFacesShading (vc, 0.670820);
-                               } else if (vertex->Normal.Z > 0.5) {
-                                       applyFacesShading (vc, 0.836660);
-                               } else if (vertex->Normal.Z < -0.5) {
-                                       applyFacesShading (vc, 0.836660);
+                       if (!vc->getBlue()) {
+                               if (Normal->Y < -0.5) {
+                                       applyFacesShading(*vc, 0.447213);
+                               } else if (Normal->X > 0.5) {
+                                       applyFacesShading(*vc, 0.670820);
+                               } else if (Normal->X < -0.5) {
+                                       applyFacesShading(*vc, 0.670820);
+                               } else if (Normal->Z > 0.5) {
+                                       applyFacesShading(*vc, 0.836660);
+                               } else if (Normal->Z < -0.5) {
+                                       applyFacesShading(*vc, 0.836660);
                                }
                        }
-                       if(!m_enable_shaders)
-                       {
+                       if (!m_enable_shaders) {
                                // - Classic lighting (shaders handle this by themselves)
                                // Set initial real color and store for later updates
-                               u8 day = vc.getRed();
-                               u8 night = vc.getGreen();
-                               finalColorBlend(vc, day, night, 1000);
-                               if(day != night)
+                               u8 day = vc->getRed();
+                               u8 night = vc->getGreen();
+                               finalColorBlend(*vc, day, night, 1000);
+                               if (day != night) {
                                        m_daynight_diffs[i][j] = std::make_pair(day, night);
+                               }
                        }
                }
 
@@ -1201,34 +1211,46 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
                        p.tile.applyMaterialOptions(material);
                }
 
-       // Create meshbuffer
-       scene::SMeshBuffer *buf = new scene::SMeshBuffer();
-       // Set material
-       buf->Material = material;
-       // Add to mesh
-       scene::SMesh *mesh = (scene::SMesh *)m_mesh;
-       mesh->addMeshBuffer(buf);
-       // Mesh grabbed it
-       buf->drop();
-       buf->append(&p.vertices[0], p.vertices.size(),
-               &p.indices[0], p.indices.size());
-}
-       m_camera_offset = camera_offset;
+               scene::SMesh *mesh = (scene::SMesh *)m_mesh;
+
+               // Create meshbuffer, add to mesh
+               if (m_use_tangent_vertices) {
+                       scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents();
+                       // Set material
+                       buf->Material = material;
+                       // Add to mesh
+                       mesh->addMeshBuffer(buf);
+                       // Mesh grabbed it
+                       buf->drop();
+                       buf->append(&p.tangent_vertices[0], p.tangent_vertices.size(),
+                               &p.indices[0], p.indices.size());
+               } else {
+                       scene::SMeshBuffer *buf = new scene::SMeshBuffer();
+                       // Set material
+                       buf->Material = material;
+                       // Add to mesh
+                       mesh->addMeshBuffer(buf);
+                       // Mesh grabbed it
+                       buf->drop();
+                       buf->append(&p.vertices[0], p.vertices.size(),
+                               &p.indices[0], p.indices.size());
+               }
+       }
 
        /*
                Do some stuff to the mesh
        */
+       m_camera_offset = camera_offset;
+       translateMesh(m_mesh,
+               intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
 
-       translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS));
-
-       if (m_enable_shaders) {
-               scene::IMeshManipulator* meshmanip = m_gamedef->getSceneManager()->getMeshManipulator();
-               scene::IMesh* tangentMesh = meshmanip->createMeshWithTangents(m_mesh);
-               m_mesh->drop();
-               m_mesh = tangentMesh;
+       if (m_use_tangent_vertices) {
+               scene::IMeshManipulator* meshmanip =
+                       m_gamedef->getSceneManager()->getMeshManipulator();
+               meshmanip->recalculateTangents(m_mesh, true, false, false);
        }
 
-       if(m_mesh)
+       if (m_mesh)
        {
 #if 0
                // Usually 1-700 faces and 1-7 materials
@@ -1400,17 +1422,30 @@ void MeshCollector::append(const TileSpec &tile,
                p = &prebuffers[prebuffers.size() - 1];
        }
 
-       u32 vertex_count = p->vertices.size();
-       for (u32 i = 0; i < numIndices; i++)    {
+       u32 vertex_count;
+       if (m_use_tangent_vertices) {
+               vertex_count = p->tangent_vertices.size();
+               p->tangent_vertices.reserve(vertex_count + numVertices);
+               for (u32 i = 0; i < numVertices; i++) {
+                       video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal,
+                               vertices[i].Color, vertices[i].TCoords);
+                       p->tangent_vertices.push_back(vert);
+               }
+       } else {
+               vertex_count = p->vertices.size();
+               p->vertices.reserve(vertex_count + numVertices);
+               for (u32 i = 0; i < numVertices; i++) {
+                       video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
+                               vertices[i].Color, vertices[i].TCoords);
+                       p->vertices.push_back(vert);
+               }
+       } 
+
+       p->indices.reserve(p->indices.size() + numIndices);
+       for (u32 i = 0; i < numIndices; i++) {
                u32 j = indices[i] + vertex_count;
                p->indices.push_back(j);
        }
-
-       for (u32 i = 0; i < numVertices; i++) {
-               video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal,
-                       vertices[i].Color, vertices[i].TCoords);
-               p->vertices.push_back(vert);
-       }
 }
 
 /*
@@ -1446,15 +1481,28 @@ void MeshCollector::append(const TileSpec &tile,
                p = &prebuffers[prebuffers.size() - 1];
        }
 
-       u32 vertex_count = p->vertices.size();
+       u32 vertex_count;
+       if (m_use_tangent_vertices) {
+               vertex_count = p->tangent_vertices.size();
+               p->tangent_vertices.reserve(vertex_count + numVertices);
+               for (u32 i = 0; i < numVertices; i++) {
+                       video::S3DVertexTangents vert(vertices[i].Pos + pos,
+                               vertices[i].Normal, c, vertices[i].TCoords);
+                       p->tangent_vertices.push_back(vert);
+               }
+       } else {
+               vertex_count = p->vertices.size();
+               p->vertices.reserve(vertex_count + numVertices);
+               for (u32 i = 0; i < numVertices; i++) {
+                       video::S3DVertex vert(vertices[i].Pos + pos,
+                               vertices[i].Normal, c, vertices[i].TCoords);
+                       p->vertices.push_back(vert);
+               }
+       } 
+
+       p->indices.reserve(p->indices.size() + numIndices);
        for (u32 i = 0; i < numIndices; i++) {
                u32 j = indices[i] + vertex_count;
                p->indices.push_back(j);
        }
-
-       for (u32 i = 0; i < numVertices; i++) {
-               video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal,
-                       c, vertices[i].TCoords);
-               p->vertices.push_back(vert);
-       }
 }
index 421e8f2b39d2960c86cfa685b2849e2b7100da68..987490408171084996c47f68fc5001cd0904e698 100644 (file)
@@ -46,8 +46,10 @@ struct MeshMakeData
 
        IGameDef *m_gamedef;
        bool m_use_shaders;
+       bool m_use_tangent_vertices;
 
-       MeshMakeData(IGameDef *gamedef, bool use_shaders);
+       MeshMakeData(IGameDef *gamedef, bool use_shaders,
+                       bool use_tangent_vertices = false);
 
        /*
                Copy central data directly from block, and other data from
@@ -130,6 +132,7 @@ private:
        IShaderSource *m_shdrsrc;
 
        bool m_enable_shaders;
+       bool m_use_tangent_vertices;
 
        // Must animate() be called before rendering?
        bool m_has_animation;
@@ -167,11 +170,19 @@ struct PreMeshBuffer
        TileSpec tile;
        std::vector<u16> indices;
        std::vector<video::S3DVertex> vertices;
+       std::vector<video::S3DVertexTangents> tangent_vertices;
 };
 
 struct MeshCollector
 {
        std::vector<PreMeshBuffer> prebuffers;
+       bool m_use_tangent_vertices;
+
+       MeshCollector(bool use_tangent_vertices):
+               m_use_tangent_vertices(use_tangent_vertices)
+       {
+       }
+
        void append(const TileSpec &material,
                        const video::S3DVertex *vertices, u32 numVertices,
                        const u16 *indices, u32 numIndices);