Refactor VertexOffsets

- Extract from Mesh
- Rename to VertexAttributes
- Move stride on top
This commit is contained in:
Vsevolod Kremianskii 2021-05-11 19:16:39 +07:00
parent ebee8f36c6
commit 0e2ffbee9d
7 changed files with 105 additions and 77 deletions

View file

@ -195,6 +195,7 @@ set(GRAPHICS_HEADERS
src/engine/graphics/textureutil.h
src/engine/graphics/textutil.h
src/engine/graphics/types.h
src/engine/graphics/vertexattributes.h
src/engine/graphics/walkmesh/bwmreader.h
src/engine/graphics/walkmesh/walkmesh.h
src/engine/graphics/walkmesh/walkmeshes.h

View file

@ -30,11 +30,11 @@ namespace reone {
namespace graphics {
Mesh::Mesh(int vertexCount, vector<float> vertices, vector<uint16_t> indices, VertexOffsets offsets, DrawMode mode) :
Mesh::Mesh(int vertexCount, vector<float> vertices, vector<uint16_t> indices, VertexAttributes attributes, DrawMode mode) :
_vertexCount(vertexCount),
_vertices(move(vertices)),
_indices(move(indices)),
_offsets(move(offsets)),
_attributes(move(attributes)),
_mode(mode) {
}
@ -51,37 +51,37 @@ void Mesh::init() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(uint16_t), &_indices[0], GL_STATIC_DRAW);
if (_offsets.vertexCoords != -1) {
if (_attributes.offCoords != -1) {
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.vertexCoords));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offCoords));
}
if (_offsets.normals != -1) {
if (_attributes.offNormals != -1) {
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.normals));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offNormals));
}
if (_offsets.texCoords1 != -1) {
if (_attributes.offTexCoords1 != -1) {
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.texCoords1));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offTexCoords1));
}
if (_offsets.texCoords2 != -1) {
if (_attributes.offTexCoords2 != -1) {
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.texCoords2));
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offTexCoords2));
}
if (_offsets.tangents != -1) {
if (_attributes.offTangents != -1) {
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.tangents));
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offTangents));
}
if (_offsets.bitangents != -1) {
if (_attributes.offBitangents != -1) {
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.bitangents));
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offBitangents));
}
if (_offsets.boneWeights != -1) {
if (_attributes.offBoneWeights != -1) {
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.boneWeights));
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offBoneWeights));
}
if (_offsets.boneIndices != -1) {
if (_attributes.offBoneIndices != -1) {
glEnableVertexAttribArray(7);
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, _offsets.stride, reinterpret_cast<void *>(_offsets.boneIndices));
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, _attributes.stride, reinterpret_cast<void *>(_attributes.offBoneIndices));
}
glBindVertexArray(0);
@ -126,11 +126,11 @@ void Mesh::drawInstanced(int count) {
void Mesh::computeAABB() {
_aabb.reset();
int stride = _offsets.stride;
int stride = _attributes.stride;
if (stride == 0) {
stride = 3 * sizeof(float);
}
auto vertCoords = reinterpret_cast<uint8_t *>(&_vertices[0]) + _offsets.vertexCoords;
auto vertCoords = reinterpret_cast<uint8_t *>(&_vertices[0]) + _attributes.offCoords;
for (size_t i = 0; i < _vertexCount; ++i) {
_aabb.expand(glm::make_vec3(reinterpret_cast<const float *>(vertCoords)));
@ -142,12 +142,12 @@ glm::vec2 Mesh::getFaceCenterUV(int faceIdx) const {
if (faceIdx < 0 || faceIdx >= _indices.size() / 3) {
throw out_of_range("faceIdx out of range");
}
if (_offsets.texCoords1 == -1) return glm::vec2(0.0f);
if (_attributes.offTexCoords1 == -1) return glm::vec2(0.0f);
glm::vec2 result(0.0f);
const uint16_t *indices = &_indices[3 * faceIdx];
for (int i = 0; i < 3; ++i) {
const float *uv = &_vertices[(indices[i] * _offsets.stride + _offsets.texCoords1) / sizeof(float)];
const float *uv = &_vertices[(indices[i] * _attributes.stride + _attributes.offTexCoords1) / sizeof(float)];
result.x += uv[0];
result.y += uv[1];
}

View file

@ -23,6 +23,7 @@
#include <boost/noncopyable.hpp>
#include "aabb.h"
#include "vertexattributes.h"
namespace reone {
@ -42,19 +43,7 @@ public:
TriangleStrip
};
struct VertexOffsets {
int vertexCoords { 0 };
int normals { -1 };
int texCoords1 { -1 };
int texCoords2 { -1 };
int tangents { -1 };
int bitangents { -1 };
int boneWeights { -1 };
int boneIndices { -1 };
int stride { 0 };
};
Mesh(int vertexCount, std::vector<float> vertices, std::vector<uint16_t> indices, VertexOffsets offsets, DrawMode mode = DrawMode::Triangles);
Mesh(int vertexCount, std::vector<float> vertices, std::vector<uint16_t> indices, VertexAttributes attributes, DrawMode mode = DrawMode::Triangles);
~Mesh();
void init();
@ -74,14 +63,14 @@ public:
const std::vector<float> &vertices() const { return _vertices; }
const std::vector<uint16_t> &indices() const { return _indices; }
const VertexOffsets &offsets() const { return _offsets; }
const VertexAttributes &attributes() const { return _attributes; }
const AABB &aabb() const { return _aabb; }
protected:
int _vertexCount;
std::vector<float> _vertices;
std::vector<uint16_t> _indices;
VertexOffsets _offsets;
VertexAttributes _attributes;
DrawMode _mode;
bool _inited { false };

View file

@ -100,7 +100,7 @@ static const vector<float> g_grassVertices = {
static const vector<uint16_t> g_quadIndices = { 0, 1, 2, 2, 3, 0 };
static const Mesh::VertexOffsets g_quadOffsets = { 0, -1, 3 * sizeof(float), -1, -1, -1, -1, -1, 5 * sizeof(float) };
static const VertexAttributes g_quadAttributes = { 5 * sizeof(float), 0, -1, 3 * sizeof(float) };
// END Quads
@ -126,7 +126,7 @@ static const vector<uint16_t> g_cubeIndices = {
6, 0, 3, 3, 5, 6
};
static const Mesh::VertexOffsets g_cubeOffsets = { 0, -1, -1, -1, -1, -1, -1, -1, 3 * sizeof(float) };
static const VertexAttributes g_cubeAttributes = { 3 * sizeof(float), 0 };
// END Cube
@ -174,7 +174,7 @@ static const vector<uint16_t> g_cubemapIndices {
20, 21, 22, 21, 20, 23
};
static const Mesh::VertexOffsets g_cubemapOffsets { 0, 3 * sizeof(float), 6 * sizeof(float), -1, -1, -1, -1, -1, 8 * sizeof(float) };
static const VertexAttributes g_cubemapAttributes { 8 * sizeof(float), 0, 3 * sizeof(float), 6 * sizeof(float) };
// END Cubemap
@ -200,7 +200,7 @@ static const vector<uint16_t> g_aabbIndices = {
6, 0, 0, 3, 3, 5, 5, 6
};
static const Mesh::VertexOffsets g_aabbOffsets = { 0, -1, -1, -1, -1, -1, -1, -1, 3 * sizeof(float) };
static const VertexAttributes g_aabbAttributes = { 3 * sizeof(float), 0, -1, -1, -1, -1, -1, -1, -1 };
// END AABB
@ -213,10 +213,10 @@ static unique_ptr<Mesh> getMesh(
int vertexCount,
const vector<float> &vertices,
const vector<uint16_t> &indices,
const Mesh::VertexOffsets &offsets,
const VertexAttributes &attributes,
Mesh::DrawMode mode = Mesh::DrawMode::Triangles) {
auto mesh = make_unique<Mesh>(vertexCount, vertices, indices, offsets, mode);
auto mesh = make_unique<Mesh>(vertexCount, vertices, indices, attributes, mode);
mesh->init();
return move(mesh);
}
@ -227,7 +227,7 @@ static unique_ptr<Mesh> getSphereMesh() {
vector<float> vertices;
vector<uint16_t> indices;
Mesh::VertexOffsets offsets { 0, 3 * sizeof(float), 5 * sizeof(float), -1, -1, -1, -1, -1, 8 * sizeof(float) };
VertexAttributes attributes { 8 * sizeof(float), 0, 3 * sizeof(float), 5 * sizeof(float) };
for (int y = 0; y <= kNumSegmentsY; ++y) {
for (int x = 0; x <= kNumSegmentsX; ++x) {
@ -267,7 +267,7 @@ static unique_ptr<Mesh> getSphereMesh() {
oddRow = !oddRow;
}
auto mesh = make_unique<Mesh>(static_cast<int>(vertices.size()) / 8, move(vertices), move(indices), move(offsets), Mesh::DrawMode::TriangleStrip);
auto mesh = make_unique<Mesh>(static_cast<int>(vertices.size()) / 8, move(vertices), move(indices), move(attributes), Mesh::DrawMode::TriangleStrip);
mesh->init();
return move(mesh);
@ -275,20 +275,20 @@ static unique_ptr<Mesh> getSphereMesh() {
void Meshes::init() {
if (!_inited) {
_quad = getMesh(4, g_quadVertices, g_quadIndices, g_quadOffsets);
_quadFlipX = getMesh(4, g_quadFlipXVertices, g_quadIndices, g_quadOffsets);
_quadFlipY = getMesh(4, g_quadFlipYVertices, g_quadIndices, g_quadOffsets);
_quadFlipXY = getMesh(4, g_quadFlipXYVertices, g_quadIndices, g_quadOffsets);
_quadSwap = getMesh(4, g_quadSwapVertices, g_quadIndices, g_quadOffsets);
_quadSwapFlipX = getMesh(4, g_quadSwapFlipXVertices, g_quadIndices, g_quadOffsets);
_quadNDC = getMesh(4, g_quadNDCVertices, g_quadIndices, g_quadOffsets);
_quadNDCFlipY = getMesh(4, g_quadNDCFlipYVertices, g_quadIndices, g_quadOffsets);
_billboard = getMesh(4, g_billboardVertices, g_quadIndices, g_quadOffsets);
_grass = getMesh(4, g_grassVertices, g_quadIndices, g_quadOffsets);
_cube = getMesh(8, g_cubeVertices, g_cubeIndices, g_cubeOffsets);
_quad = getMesh(4, g_quadVertices, g_quadIndices, g_quadAttributes);
_quadFlipX = getMesh(4, g_quadFlipXVertices, g_quadIndices, g_quadAttributes);
_quadFlipY = getMesh(4, g_quadFlipYVertices, g_quadIndices, g_quadAttributes);
_quadFlipXY = getMesh(4, g_quadFlipXYVertices, g_quadIndices, g_quadAttributes);
_quadSwap = getMesh(4, g_quadSwapVertices, g_quadIndices, g_quadAttributes);
_quadSwapFlipX = getMesh(4, g_quadSwapFlipXVertices, g_quadIndices, g_quadAttributes);
_quadNDC = getMesh(4, g_quadNDCVertices, g_quadIndices, g_quadAttributes);
_quadNDCFlipY = getMesh(4, g_quadNDCFlipYVertices, g_quadIndices, g_quadAttributes);
_billboard = getMesh(4, g_billboardVertices, g_quadIndices, g_quadAttributes);
_grass = getMesh(4, g_grassVertices, g_quadIndices, g_quadAttributes);
_cube = getMesh(8, g_cubeVertices, g_cubeIndices, g_cubeAttributes);
_sphere = getSphereMesh();
_cubemap = getMesh(24, g_cubemapVertices, g_cubemapIndices, g_cubemapOffsets);
_aabb = getMesh(8, g_aabbVertices, g_aabbIndices, g_aabbOffsets, Mesh::DrawMode::Lines);
_cubemap = getMesh(24, g_cubemapVertices, g_cubemapIndices, g_cubemapAttributes);
_aabb = getMesh(8, g_aabbVertices, g_aabbIndices, g_aabbAttributes, Mesh::DrawMode::Lines);
_inited = true;
}

View file

@ -890,15 +890,15 @@ void MdlReader::readMesh(ModelNode &node) {
_mdxReader->seek(offMdxData);
vertices = _mdxReader->getFloatArray(header.numVertices * header.mdxVertexSize / sizeof(float));
Mesh::VertexOffsets offsets;
offsets.stride = header.mdxVertexSize;
offsets.vertexCoords = header.offMdxVertices;
offsets.normals = header.offMdxNormals;
offsets.texCoords1 = header.offMdxTexCoords1;
offsets.texCoords2 = header.offMdxTexCoords2;
VertexAttributes attributes;
attributes.stride = header.mdxVertexSize;
attributes.offCoords = header.offMdxVertices;
attributes.offNormals = header.offMdxNormals;
attributes.offTexCoords1 = header.offMdxTexCoords1;
attributes.offTexCoords2 = header.offMdxTexCoords2;
if (header.offMdxTanSpace != -1) {
offsets.bitangents = header.offMdxTanSpace + 0 * sizeof(float);
offsets.tangents = header.offMdxTanSpace + 3 * sizeof(float);
attributes.offBitangents = header.offMdxTanSpace + 0 * sizeof(float);
attributes.offTangents = header.offMdxTanSpace + 3 * sizeof(float);
}
vector<uint16_t> indices;
@ -909,7 +909,7 @@ void MdlReader::readMesh(ModelNode &node) {
seek(endPos);
loadMesh(header, header.numVertices, move(vertices), move(indices), move(offsets), node);
loadMesh(header, header.numVertices, move(vertices), move(indices), move(attributes), node);
}
MdlReader::MeshHeader MdlReader::readMeshHeader() {
@ -983,7 +983,7 @@ MdlReader::MeshHeader MdlReader::readMeshHeader() {
return move(result);
}
void MdlReader::loadMesh(const MeshHeader &header, int numVertices, vector<float> &&vertices, vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, ModelNode &node) {
void MdlReader::loadMesh(const MeshHeader &header, int numVertices, vector<float> &&vertices, vector<uint16_t> &&indices, VertexAttributes &&offsets, ModelNode &node) {
auto mesh = make_unique<Mesh>(numVertices, vertices, indices, offsets);
mesh->computeAABB();
@ -1020,8 +1020,8 @@ void MdlReader::readSkin(ModelNode &node) {
vector<uint16_t> boneIndices(readUint16Array(16));
ignore(4); // padding
node._mesh->_mesh->_offsets.boneWeights = offMdxBoneWeights;
node._mesh->_mesh->_offsets.boneIndices = offMdxBoneIndices;
node._mesh->_mesh->_attributes.offBoneWeights = offMdxBoneWeights;
node._mesh->_mesh->_attributes.offBoneIndices = offMdxBoneIndices;
unordered_map<uint16_t, uint16_t> nodeIdxByBoneIdx;
seek(kMdlDataOffset + offBones);
@ -1095,11 +1095,11 @@ void MdlReader::readSaber(ModelNode &node) {
*(verticesPtr++) = normalsPtr[2];
}
Mesh::VertexOffsets offsets;
offsets.vertexCoords = 0;
offsets.texCoords1 = 3 * sizeof(float);
offsets.normals = 5 * sizeof(float);
offsets.stride = 8 * sizeof(float);
VertexAttributes attributes;
attributes.stride = 8 * sizeof(float);
attributes.offCoords = 0;
attributes.offTexCoords1 = 3 * sizeof(float);
attributes.offNormals = 5 * sizeof(float);
vector<uint16_t> indices {
0, 13, 12, 0, 1, 13,
@ -1110,7 +1110,7 @@ void MdlReader::readSaber(ModelNode &node) {
10, 6, 7, 10, 7, 11
};
loadMesh(header, numVertices, move(vertices), move(indices), move(offsets), node);
loadMesh(header, numVertices, move(vertices), move(indices), move(attributes), node);
}
void MdlReader::readDanglymesh(ModelNode &node) {

View file

@ -99,7 +99,7 @@ private:
void readAABB(graphics::ModelNode &node);
void readSaber(graphics::ModelNode &node);
void loadMesh(const MeshHeader &header, int numVertices, std::vector<float> &&vertices, std::vector<uint16_t> &&indices, Mesh::VertexOffsets &&offsets, graphics::ModelNode &node);
void loadMesh(const MeshHeader &header, int numVertices, std::vector<float> &&vertices, std::vector<uint16_t> &&indices, VertexAttributes &&attributes, graphics::ModelNode &node);
MeshHeader readMeshHeader();
std::shared_ptr<AABBNode> readAABBNode(uint32_t offset);
};

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020-2021 The reone project contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
namespace reone {
namespace graphics {
struct VertexAttributes {
int stride { 0 };
int offCoords { 0 };
int offNormals { -1 };
int offTexCoords1 { -1 };
int offTexCoords2 { -1 };
int offTangents { -1 };
int offBitangents { -1 };
int offBoneWeights { -1 };
int offBoneIndices { -1 };
};
} // namespace graphics
} // namespace reone