From 9fcc0c1217fcd3acabaa11239631de10032fa126 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Thu, 22 Mar 2018 22:59:49 +0300 Subject: [PATCH] Update mesh collector and move it to a separate file (#6904) * Update MeshCollector * Simplify MeshCollector --- build/android/jni/Android.mk | 1 + src/client/CMakeLists.txt | 1 + src/client/meshgen/collector.cpp | 104 +++++++++++ src/client/meshgen/collector.h | 65 +++++++ src/content_mapblock.cpp | 1 + src/mapblock_mesh.cpp | 293 +++++-------------------------- src/mapblock_mesh.h | 45 ----- src/wieldmesh.cpp | 3 +- 8 files changed, 222 insertions(+), 291 deletions(-) create mode 100644 src/client/meshgen/collector.cpp create mode 100644 src/client/meshgen/collector.h diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index 4d4968feb..4f2e788a8 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -274,6 +274,7 @@ LOCAL_SRC_FILES := \ jni/src/unittest/test_voxelmanipulator.cpp \ jni/src/settings.cpp \ jni/src/wieldmesh.cpp \ + jni/src/client/meshgen/collector.cpp \ jni/src/client/clientlauncher.cpp \ jni/src/client/gameui.cpp \ jni/src/client/hud.cpp \ diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index c69b2c2d4..ea8acd064 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -1,4 +1,5 @@ set(client_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/meshgen/collector.cpp ${CMAKE_CURRENT_SOURCE_DIR}/render/anaglyph.cpp ${CMAKE_CURRENT_SOURCE_DIR}/render/core.cpp ${CMAKE_CURRENT_SOURCE_DIR}/render/factory.cpp diff --git a/src/client/meshgen/collector.cpp b/src/client/meshgen/collector.cpp new file mode 100644 index 000000000..c317a0772 --- /dev/null +++ b/src/client/meshgen/collector.cpp @@ -0,0 +1,104 @@ +/* +Minetest +Copyright (C) 2018 numzero, Lobachevskiy Vitaliy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "collector.h" +#include +#include "log.h" +#include "mesh.h" + +void MeshCollector::append(const TileSpec &tile, const video::S3DVertex *vertices, + u32 numVertices, const u16 *indices, u32 numIndices) +{ + for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { + const TileLayer *layer = &tile.layers[layernum]; + if (layer->texture_id == 0) + continue; + append(*layer, vertices, numVertices, indices, numIndices, layernum, + tile.world_aligned); + } +} + +void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *vertices, + u32 numVertices, const u16 *indices, u32 numIndices, u8 layernum, + bool use_scale) +{ + PreMeshBuffer &p = findBuffer(layer, layernum, numVertices); + + f32 scale = 1.0f; + if (use_scale) + scale = 1.0f / layer.scale; + + u32 vertex_count = p.vertices.size(); + for (u32 i = 0; i < numVertices; i++) + p.vertices.emplace_back(vertices[i].Pos, vertices[i].Normal, + vertices[i].Color, scale * vertices[i].TCoords); + + for (u32 i = 0; i < numIndices; i++) + p.indices.push_back(indices[i] + vertex_count); +} + +void MeshCollector::append(const TileSpec &tile, const video::S3DVertex *vertices, + u32 numVertices, const u16 *indices, u32 numIndices, v3f pos, + video::SColor c, u8 light_source) +{ + for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { + const TileLayer *layer = &tile.layers[layernum]; + if (layer->texture_id == 0) + continue; + append(*layer, vertices, numVertices, indices, numIndices, pos, c, + light_source, layernum, tile.world_aligned); + } +} + +void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *vertices, + u32 numVertices, const u16 *indices, u32 numIndices, v3f pos, + video::SColor c, u8 light_source, u8 layernum, bool use_scale) +{ + PreMeshBuffer &p = findBuffer(layer, layernum, numVertices); + + f32 scale = 1.0f; + if (use_scale) + scale = 1.0f / layer.scale; + + u32 vertex_count = p.vertices.size(); + for (u32 i = 0; i < numVertices; i++) { + video::SColor color = c; + if (!light_source) + applyFacesShading(color, vertices[i].Normal); + p.vertices.emplace_back(vertices[i].Pos + pos, vertices[i].Normal, color, + scale * vertices[i].TCoords); + } + + for (u32 i = 0; i < numIndices; i++) + p.indices.push_back(indices[i] + vertex_count); +} + +PreMeshBuffer &MeshCollector::findBuffer( + const TileLayer &layer, u8 layernum, u32 numVertices) +{ + if (numVertices > U16_MAX) + throw std::invalid_argument( + "Mesh can't contain more than 65536 vertices"); + std::vector &buffers = prebuffers[layernum]; + for (PreMeshBuffer &p : buffers) + if (p.layer == layer && p.vertices.size() + numVertices <= U16_MAX) + return p; + buffers.emplace_back(layer); + return buffers.back(); +} diff --git a/src/client/meshgen/collector.h b/src/client/meshgen/collector.h new file mode 100644 index 000000000..e4189088e --- /dev/null +++ b/src/client/meshgen/collector.h @@ -0,0 +1,65 @@ +/* +Minetest +Copyright (C) 2018 numzero, Lobachevskiy Vitaliy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once +#include +#include +#include "irrlichttypes.h" +#include +#include "client/tile.h" + +struct PreMeshBuffer +{ + TileLayer layer; + std::vector indices; + std::vector vertices; + + PreMeshBuffer() = default; + explicit PreMeshBuffer(const TileLayer &layer) : layer(layer) {} +}; + +struct MeshCollector +{ + std::array, MAX_TILE_LAYERS> prebuffers; + + // clang-format off + void append(const TileSpec &material, + const video::S3DVertex *vertices, u32 numVertices, + const u16 *indices, u32 numIndices); + void append(const TileSpec &material, + const video::S3DVertex *vertices, u32 numVertices, + const u16 *indices, u32 numIndices, + v3f pos, video::SColor c, u8 light_source); + // clang-format on + +private: + // clang-format off + void append(const TileLayer &material, + const video::S3DVertex *vertices, u32 numVertices, + const u16 *indices, u32 numIndices, + u8 layernum, bool use_scale = false); + void append(const TileLayer &material, + const video::S3DVertex *vertices, u32 numVertices, + const u16 *indices, u32 numIndices, + v3f pos, video::SColor c, u8 light_source, + u8 layernum, bool use_scale = false); + // clang-format on + + PreMeshBuffer &findBuffer(const TileLayer &layer, u8 layernum, u32 numVertices); +}; diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 348748c91..0259ca3af 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/tile.h" #include "mesh.h" #include +#include "client/meshgen/collector.h" #include "client/renderingengine.h" #include "client.h" #include "noise.h" diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 6a94e78df..a616a98b7 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "minimap.h" #include "content_mapblock.h" #include "util/directiontables.h" +#include "client/meshgen/collector.h" #include "client/renderingengine.h" #include @@ -450,7 +451,7 @@ static void getNodeTextureCoords(v3f base, const v3f &scale, v3s16 dir, float *u struct FastFace { - TileLayer layer; + TileSpec tile; video::S3DVertex vertices[4]; // Precalculated vertices /*! * The face is divided into two triangles. If this is true, @@ -458,8 +459,6 @@ struct FastFace * are connected. */ bool vertex_0_2_connected; - u8 layernum; - bool world_aligned; }; static void makeFastFace(const TileSpec &tile, u16 li0, u16 li1, u16 li2, u16 li3, @@ -630,35 +629,25 @@ static void makeFastFace(const TileSpec &tile, u16 li0, u16 li1, u16 li2, u16 li core::vector2d(x0, y0), core::vector2d(x0 + w * abs_scale, y0) }; - for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { - const TileLayer *layer = &tile.layers[layernum]; - if (layer->texture_id == 0) - continue; + // equivalent to dest.push_back(FastFace()) but faster + dest.emplace_back(); + FastFace& face = *dest.rbegin(); - // equivalent to dest.push_back(FastFace()) but faster - dest.emplace_back(); - FastFace& face = *dest.rbegin(); + for (u8 i = 0; i < 4; i++) { + video::SColor c = encode_light(li[i], tile.emissive_light); + if (!tile.emissive_light) + applyFacesShading(c, normal); - for (u8 i = 0; i < 4; i++) { - video::SColor c = encode_light(li[i], tile.emissive_light); - if (!tile.emissive_light) - applyFacesShading(c, normal); - - face.vertices[i] = video::S3DVertex(vertex_pos[i], normal, c, f[i]); - } - - /* - Revert triangles for nicer looking gradient if the - brightness of vertices 1 and 3 differ less than - the brightness of vertices 0 and 2. - */ - face.vertex_0_2_connected = vertex_0_2_connected; - - face.layer = *layer; - face.layernum = layernum; - - face.world_aligned = tile.world_aligned; + face.vertices[i] = video::S3DVertex(vertex_pos[i], normal, c, f[i]); } + + /* + Revert triangles for nicer looking gradient if the + brightness of vertices 1 and 3 differ less than + the brightness of vertices 0 and 2. + */ + face.vertex_0_2_connected = vertex_0_2_connected; + face.tile = tile; } /* @@ -1012,6 +1001,20 @@ static void updateAllFastFaceRows(MeshMakeData *data, dest); } +static void applyTileColor(PreMeshBuffer &pmb) +{ + video::SColor tc = pmb.layer.color; + if (tc == video::SColor(0xFFFFFFFF)) + return; + for (video::S3DVertex &vertex : pmb.vertices) { + video::SColor *c = &vertex.Color; + c->set(c->getAlpha(), + c->getRed() * tc.getRed() / 255, + c->getGreen() * tc.getGreen() / 255, + c->getBlue() * tc.getBlue() / 255); + } +} + /* MapBlockMesh */ @@ -1061,7 +1064,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): Convert FastFaces to MeshCollector */ - MeshCollector collector(m_use_tangent_vertices); + MeshCollector collector; { // avg 0ms (100ms spikes when loading textures the first time) @@ -1071,15 +1074,9 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): for (const FastFace &f : fastfaces_new) { static const u16 indices[] = {0, 1, 2, 2, 3, 0}; static const u16 indices_alternate[] = {0, 1, 3, 2, 3, 1}; - - if (!f.layer.texture) - continue; - const u16 *indices_p = f.vertex_0_2_connected ? indices : indices_alternate; - - collector.append(f.layer, f.vertices, 4, indices_p, 6, - f.layernum, f.world_aligned); + collector.append(f.tile, f.vertices, 4, indices_p, 6); } } @@ -1096,8 +1093,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): generator.generate(); } - collector.applyTileColors(); - /* Convert MeshCollector to SMesh */ @@ -1107,6 +1102,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): { PreMeshBuffer &p = collector.prebuffers[layer][i]; + applyTileColor(p); + // Generate animation data // - Cracks if (p.layer.material_flags & MATERIAL_FLAG_CRACK) { @@ -1151,16 +1148,10 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): // Dummy sunlight to handle non-sunlit areas video::SColorf sunlight; get_sunlight_color(&sunlight, 0); - u32 vertex_count = m_use_tangent_vertices ? - p.tangent_vertices.size() : p.vertices.size(); + u32 vertex_count = p.vertices.size(); for (u32 j = 0; j < vertex_count; j++) { - video::SColor *vc; - if (m_use_tangent_vertices) { - vc = &p.tangent_vertices[j].Color; - } else { - vc = &p.vertices[j].Color; - } - video::SColor copy(*vc); + video::SColor *vc = &p.vertices[j].Color; + video::SColor copy = *vc; if (vc->getAlpha() == 0) // No sunlight - no need to animate final_color_blend(vc, copy, sunlight); // Finalize color else // Record color to animate @@ -1197,24 +1188,23 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): if (m_use_tangent_vertices) { scene::SMeshBufferTangents *buf = new scene::SMeshBufferTangents(); - // Set material buf->Material = material; - // Add to mesh + buf->Vertices.reallocate(p.vertices.size()); + buf->Indices.reallocate(p.indices.size()); + for (const video::S3DVertex &v: p.vertices) + buf->Vertices.push_back(video::S3DVertexTangents(v.Pos, v.Color, v.TCoords)); + for (u16 i: p.indices) + buf->Indices.push_back(i); + buf->recalculateBoundingBox(); 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()); + mesh->addMeshBuffer(buf); + buf->drop(); } } @@ -1370,193 +1360,6 @@ void MapBlockMesh::updateCameraOffset(v3s16 camera_offset) } } -/* - MeshCollector -*/ - -void MeshCollector::append(const TileSpec &tile, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices) -{ - for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { - const TileLayer *layer = &tile.layers[layernum]; - if (layer->texture_id == 0) - continue; - append(*layer, vertices, numVertices, indices, numIndices, - layernum, tile.world_aligned); - } -} - -void MeshCollector::append(const TileLayer &layer, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, u8 layernum, - bool use_scale) -{ - if (numIndices > 65535) { - dstream << "FIXME: MeshCollector::append() called with numIndices=" - << numIndices << " (limit 65535)" << std::endl; - return; - } - std::vector *buffers = &prebuffers[layernum]; - - PreMeshBuffer *p = NULL; - for (PreMeshBuffer &pp : *buffers) { - if (pp.layer == layer && pp.indices.size() + numIndices <= 65535) { - p = &pp; - break; - } - } - - if (p == NULL) { - PreMeshBuffer pp; - pp.layer = layer; - buffers->push_back(pp); - p = &(*buffers)[buffers->size() - 1]; - } - - f32 scale = 1.0; - if (use_scale) - scale = 1.0 / layer.scale; - - u32 vertex_count; - if (m_use_tangent_vertices) { - vertex_count = p->tangent_vertices.size(); - for (u32 i = 0; i < numVertices; i++) { - - video::S3DVertexTangents vert(vertices[i].Pos, vertices[i].Normal, - vertices[i].Color, scale * vertices[i].TCoords); - p->tangent_vertices.push_back(vert); - } - } else { - vertex_count = p->vertices.size(); - for (u32 i = 0; i < numVertices; i++) { - video::S3DVertex vert(vertices[i].Pos, vertices[i].Normal, - vertices[i].Color, scale * vertices[i].TCoords); - - p->vertices.push_back(vert); - } - } - - for (u32 i = 0; i < numIndices; i++) { - u32 j = indices[i] + vertex_count; - p->indices.push_back(j); - } -} - -/* - MeshCollector - for meshnodes and converted drawtypes. -*/ - -void MeshCollector::append(const TileSpec &tile, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, - v3f pos, video::SColor c, u8 light_source) -{ - for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) { - const TileLayer *layer = &tile.layers[layernum]; - if (layer->texture_id == 0) - continue; - append(*layer, vertices, numVertices, indices, numIndices, pos, - c, light_source, layernum, tile.world_aligned); - } -} - -void MeshCollector::append(const TileLayer &layer, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, - v3f pos, video::SColor c, u8 light_source, u8 layernum, - bool use_scale) -{ - if (numIndices > 65535) { - dstream << "FIXME: MeshCollector::append() called with numIndices=" - << numIndices << " (limit 65535)" << std::endl; - return; - } - std::vector *buffers = &prebuffers[layernum]; - - PreMeshBuffer *p = NULL; - for (PreMeshBuffer &pp : *buffers) { - if (pp.layer == layer && pp.indices.size() + numIndices <= 65535) { - p = &pp; - break; - } - } - - if (p == NULL) { - PreMeshBuffer pp; - pp.layer = layer; - buffers->push_back(pp); - p = &(*buffers)[buffers->size() - 1]; - } - - f32 scale = 1.0; - if (use_scale) - scale = 1.0 / layer.scale; - - video::SColor original_c = c; - u32 vertex_count; - if (m_use_tangent_vertices) { - vertex_count = p->tangent_vertices.size(); - for (u32 i = 0; i < numVertices; i++) { - if (!light_source) { - c = original_c; - applyFacesShading(c, vertices[i].Normal); - } - video::S3DVertexTangents vert(vertices[i].Pos + pos, - vertices[i].Normal, c, scale * vertices[i].TCoords); - p->tangent_vertices.push_back(vert); - } - } else { - vertex_count = p->vertices.size(); - for (u32 i = 0; i < numVertices; i++) { - if (!light_source) { - c = original_c; - applyFacesShading(c, vertices[i].Normal); - } - video::S3DVertex vert(vertices[i].Pos + pos, vertices[i].Normal, c, - scale * vertices[i].TCoords); - p->vertices.push_back(vert); - } - } - - for (u32 i = 0; i < numIndices; i++) { - u32 j = indices[i] + vertex_count; - p->indices.push_back(j); - } -} - -void MeshCollector::applyTileColors() -{ - if (m_use_tangent_vertices) - for (auto &prebuffer : prebuffers) { - for (PreMeshBuffer &pmb : prebuffer) { - video::SColor tc = pmb.layer.color; - if (tc == video::SColor(0xFFFFFFFF)) - continue; - for (video::S3DVertexTangents &tangent_vertex : pmb.tangent_vertices) { - video::SColor *c = &tangent_vertex.Color; - c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255, - c->getGreen() * tc.getGreen() / 255, - c->getBlue() * tc.getBlue() / 255); - } - } - } - else - for (auto &prebuffer : prebuffers) { - for (PreMeshBuffer &pmb : prebuffer) { - video::SColor tc = pmb.layer.color; - if (tc == video::SColor(0xFFFFFFFF)) - continue; - for (video::S3DVertex &vertex : pmb.vertices) { - video::SColor *c = &vertex.Color; - c->set(c->getAlpha(), c->getRed() * tc.getRed() / 255, - c->getGreen() * tc.getGreen() / 255, - c->getBlue() * tc.getBlue() / 255); - } - } - } -} - video::SColor encode_light(u16 light, u8 emissive_light) { // Get components diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h index 2f1f3871d..39bc2f318 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -173,51 +173,6 @@ private: v3s16 m_camera_offset; }; - - -/* - This is used because CMeshBuffer::append() is very slow -*/ -struct PreMeshBuffer -{ - TileLayer layer; - std::vector indices; - std::vector vertices; - std::vector tangent_vertices; -}; - -struct MeshCollector -{ - std::array, MAX_TILE_LAYERS> 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); - void append(const TileLayer &material, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, u8 layernum, - bool use_scale = false); - void append(const TileSpec &material, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, v3f pos, - video::SColor c, u8 light_source); - void append(const TileLayer &material, - const video::S3DVertex *vertices, u32 numVertices, - const u16 *indices, u32 numIndices, v3f pos, - video::SColor c, u8 light_source, u8 layernum, - bool use_scale = false); - /*! - * Colorizes all vertices in the collector. - */ - void applyTileColors(); -}; - /*! * Encodes light of a node. * The result is not the final color, but a diff --git a/src/wieldmesh.cpp b/src/wieldmesh.cpp index dd97bc08a..7414701b7 100644 --- a/src/wieldmesh.cpp +++ b/src/wieldmesh.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mesh.h" #include "content_mapblock.h" #include "mapblock_mesh.h" +#include "client/meshgen/collector.h" #include "client/tile.h" #include "log.h" #include "util/numeric.h" @@ -304,7 +305,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector *colors) { MeshMakeData mesh_make_data(client, false, false); - MeshCollector collector(false); + MeshCollector collector; mesh_make_data.setSmoothLighting(false); MapblockMeshGenerator gen(&mesh_make_data, &collector); gen.renderSingle(id);