Mesh WIP.
This commit is contained in:
84
src/Mesh.h
Normal file
84
src/Mesh.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <core.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TScalar, typename TIndex>
|
||||||
|
class GenericMesh {
|
||||||
|
public:
|
||||||
|
using Scalar = TScalar;
|
||||||
|
using Index = TIndex;
|
||||||
|
using Vector = Eigen::Matrix<Scalar, 3, 1>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GenericMesh() = default;
|
||||||
|
GenericMesh(const GenericMesh&) = delete;
|
||||||
|
GenericMesh(GenericMesh&&) = default;
|
||||||
|
~GenericMesh() = default;
|
||||||
|
|
||||||
|
GenericMesh& operator=(const GenericMesh&) = delete;
|
||||||
|
GenericMesh& operator=(GenericMesh&&) = default;
|
||||||
|
|
||||||
|
inline size_t vertexCount() const {
|
||||||
|
return m_positions.size();
|
||||||
|
}
|
||||||
|
inline size_t indexCount() const {
|
||||||
|
return m_indices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void resizeVertex(Index vertexCount) {
|
||||||
|
m_positions.resize(vertexCount);
|
||||||
|
}
|
||||||
|
inline void resizeIndices(Index indexCount) {
|
||||||
|
m_indices.resize(indexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Vector& position(Index vertexIndex) const {
|
||||||
|
assert(vertexIndex < m_positions.size());
|
||||||
|
return m_positions[vertexIndex];
|
||||||
|
}
|
||||||
|
inline Vector& position(Index vertexIndex) {
|
||||||
|
assert(vertexIndex < m_positions.size());
|
||||||
|
return m_positions[vertexIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Index index(Index indexIndex) const {
|
||||||
|
assert(indexIndex < m_indices.size());
|
||||||
|
return m_indices[indexIndex];
|
||||||
|
}
|
||||||
|
inline Index& index(Index indexIndex) {
|
||||||
|
assert(indexIndex < m_indices.size());
|
||||||
|
return m_indices[indexIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Vector* positionData() const {
|
||||||
|
return m_positions.data();
|
||||||
|
}
|
||||||
|
inline Vector* positionData() {
|
||||||
|
return m_positions.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Index* indexData() const {
|
||||||
|
return m_indices.data();
|
||||||
|
}
|
||||||
|
inline Index* indexData() {
|
||||||
|
return m_indices.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::vector<Vector>& positions() const {
|
||||||
|
return m_positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::vector<Index>& indices() const {
|
||||||
|
return m_indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Vector> m_positions;
|
||||||
|
std::vector<Index> m_indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Mesh = GenericMesh<Real, uint32_t>;
|
||||||
232
src/Planet.cpp
232
src/Planet.cpp
@@ -6,9 +6,25 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
Vector3 lerp(Real factor, const Vector3& v0, const Vector3& v1) {
|
MeshView::MeshView(
|
||||||
return (Real(1) - factor) * v0 + factor * v1;
|
Index vertex_count,
|
||||||
}
|
Byte* positions, Index position_stride,
|
||||||
|
Byte* normals, Index normal_stride,
|
||||||
|
Byte* colors, Index color_stride,
|
||||||
|
Index index_count,
|
||||||
|
Byte* indices, Index index_stride
|
||||||
|
)
|
||||||
|
: m_vertex_count(vertex_count)
|
||||||
|
, m_positions(positions)
|
||||||
|
, m_position_stride(position_stride)
|
||||||
|
, m_normals(normals)
|
||||||
|
, m_normal_stride(normal_stride)
|
||||||
|
, m_colors(colors)
|
||||||
|
, m_color_stride(color_stride)
|
||||||
|
, m_index_count(index_count)
|
||||||
|
, m_indices(indices)
|
||||||
|
, m_index_stride(index_stride)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
Cell::Cell(
|
Cell::Cell(
|
||||||
@@ -18,13 +34,13 @@ Cell::Cell(
|
|||||||
const Vector3& corner11
|
const Vector3& corner11
|
||||||
)
|
)
|
||||||
: m_corners{ corner00, corner01, corner10, corner11 }
|
: m_corners{ corner00, corner01, corner10, corner11 }
|
||||||
, m_heightFactor(heightFactor(m_corners))
|
, m_height_factor(height_factor(m_corners))
|
||||||
, m_cells{ nullptr, nullptr, nullptr, nullptr }
|
, m_cells{ nullptr, nullptr, nullptr, nullptr }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Cell& Cell::cell(uint32_t cellIndex) {
|
Cell& Cell::cell(uint32_t cell_index) {
|
||||||
assert(cellIndex < CellCount);
|
assert(cell_index < CellCount);
|
||||||
auto& cell = m_cells[cellIndex];
|
auto& cell = m_cells[cell_index];
|
||||||
if(!cell)
|
if(!cell)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
@@ -32,119 +48,159 @@ Cell& Cell::cell(uint32_t cellIndex) {
|
|||||||
return *cell;
|
return *cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cell::writeMesh(
|
size_t Cell::vertex_count(uint32_t subdiv_count) {
|
||||||
Vertex*& vertices, const Vertex* verticesEnd,
|
auto const s2 = 1 << subdiv_count;
|
||||||
uint32_t*& indices, const uint32_t* indicesEnd,
|
return s2 * s2 + 2 * s2 + 1;
|
||||||
uint32_t subdivCount
|
}
|
||||||
) const {
|
|
||||||
auto const sideEdgeCount = (1u << subdivCount);
|
|
||||||
auto const sideVertCount = sideEdgeCount + 1;
|
|
||||||
|
|
||||||
auto const quadCount = sideEdgeCount * sideEdgeCount;
|
size_t Cell::triangle_count(uint32_t subdiv_count) {
|
||||||
auto const triCount = 2 * quadCount;
|
auto const s2 = 1 << subdiv_count;
|
||||||
auto const vertCount = sideVertCount * sideVertCount;
|
return 2 * s2 * s2;
|
||||||
|
}
|
||||||
|
|
||||||
assert(vertices + vertCount <= verticesEnd);
|
void Cell::build_mesh(MeshView& mesh, uint32_t subdiv_count, Index index_offset) const {
|
||||||
assert(indices + (3 * triCount) <= indicesEnd);
|
auto const side_edge_count = (1u << subdiv_count);
|
||||||
|
auto const side_vert_count = side_edge_count + 1;
|
||||||
|
|
||||||
auto const index = [sideVertCount](uint32_t x, uint32_t y) -> uint32_t {
|
auto const quad_count = side_edge_count * side_edge_count;
|
||||||
return x + y * sideVertCount;
|
auto const tri_count = 2 * quad_count;
|
||||||
|
auto const vert_count = side_vert_count * side_vert_count;
|
||||||
|
|
||||||
|
assert(mesh.vertex_count() == vert_count);
|
||||||
|
assert(mesh.index_count() == 3 * tri_count);
|
||||||
|
|
||||||
|
auto const index = [side_vert_count](uint32_t x, uint32_t y) -> uint32_t {
|
||||||
|
return x + y * side_vert_count;
|
||||||
};
|
};
|
||||||
auto const vertex = [vertices, &index](uint32_t x, uint32_t y) -> Vertex& {
|
auto const vertex = [&mesh, &index](uint32_t x, uint32_t y) -> Vector3& {
|
||||||
return vertices[index(x, y)];
|
return mesh.position(index(x, y));
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector3 c00(0.0f, 0.0f, 1.0f);
|
vertex( 0, 0) = m_corners[0];
|
||||||
Vector3 c01(1.0f, 0.0f, 1.0f);
|
vertex(side_edge_count, 0) = m_corners[1];
|
||||||
Vector3 c10(0.0f, 1.0f, 1.0f);
|
vertex( 0, side_edge_count) = m_corners[2];
|
||||||
Vector3 c11(1.0f, 1.0f, 1.0f);
|
vertex(side_edge_count, side_edge_count) = m_corners[3];
|
||||||
|
|
||||||
auto const color = [&c00, &c01, &c10, &c11, sideEdgeCount](uint32_t x, uint32_t y) -> Vector3 {
|
|
||||||
const auto c0 = lerp(Real(x) / Real(sideEdgeCount), c00, c01);
|
|
||||||
const auto c1 = lerp(Real(x) / Real(sideEdgeCount), c10, c11);
|
|
||||||
return lerp(Real(y) / Real(sideEdgeCount), c0, c1);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const setVertex = [&vertex, &color](uint32_t x, uint32_t y, const Vector3& pos) {
|
|
||||||
vertex(x, y) = Vertex {
|
|
||||||
pos,
|
|
||||||
color(x, y)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
setVertex( 0, 0, m_corners[0]);
|
|
||||||
setVertex(sideEdgeCount, 0, m_corners[1]);
|
|
||||||
setVertex( 0, sideEdgeCount, m_corners[2]);
|
|
||||||
setVertex(sideEdgeCount, sideEdgeCount, m_corners[3]);
|
|
||||||
|
|
||||||
struct QuadCell {
|
struct QuadCell {
|
||||||
uint32_t x0, x1, y0, y1;
|
uint32_t x0, x1, y0, y1;
|
||||||
};
|
};
|
||||||
std::vector<QuadCell> stack;
|
std::vector<QuadCell> stack;
|
||||||
stack.reserve(quadCount / 4);
|
stack.reserve(quad_count / 4);
|
||||||
if(subdivCount > 0) {
|
if(subdiv_count > 0) {
|
||||||
stack.emplace_back(QuadCell {
|
stack.emplace_back(QuadCell {
|
||||||
0, sideEdgeCount,
|
0, side_edge_count,
|
||||||
0, sideEdgeCount,
|
0, side_edge_count,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!stack.empty()) {
|
while(!stack.empty()) {
|
||||||
const auto quadCell = stack.back();
|
const auto quad_cell = stack.back();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
|
|
||||||
auto const mx = (quadCell.x0 + quadCell.x1) / 2;
|
auto const mx = (quad_cell.x0 + quad_cell.x1) / 2;
|
||||||
auto const my = (quadCell.y0 + quadCell.y1) / 2;
|
auto const my = (quad_cell.y0 + quad_cell.y1) / 2;
|
||||||
|
|
||||||
auto const& v00 = vertex(quadCell.x0, quadCell.y0).position;
|
auto const& v00 = vertex(quad_cell.x0, quad_cell.y0);
|
||||||
auto const& v01 = vertex(quadCell.x1, quadCell.y0).position;
|
auto const& v01 = vertex(quad_cell.x1, quad_cell.y0);
|
||||||
auto const& v10 = vertex(quadCell.x0, quadCell.y1).position;
|
auto const& v10 = vertex(quad_cell.x0, quad_cell.y1);
|
||||||
auto const& v11 = vertex(quadCell.x1, quadCell.y1).position;
|
auto const& v11 = vertex(quad_cell.x1, quad_cell.y1);
|
||||||
|
|
||||||
setVertex( mx, quadCell.y0,
|
vertex( mx, quad_cell.y0) =
|
||||||
(v00 + v01).normalized()
|
(v00 + v01).normalized();
|
||||||
);
|
vertex(quad_cell.x0, my) =
|
||||||
setVertex(quadCell.x0, my,
|
(v00 + v10).normalized();
|
||||||
(v00 + v10).normalized()
|
vertex(mx, my) =
|
||||||
);
|
(v00 + v01 + v10 + v11).normalized();
|
||||||
setVertex(mx, my,
|
vertex(quad_cell.x1, my) =
|
||||||
(v00 + v01 + v10 + v11).normalized()
|
(v01 + v11).normalized();
|
||||||
);
|
vertex( mx, quad_cell.y1) =
|
||||||
setVertex(quadCell.x1, my,
|
(v10 + v11).normalized();
|
||||||
(v01 + v11).normalized()
|
|
||||||
);
|
|
||||||
setVertex( mx, quadCell.y1,
|
|
||||||
(v10 + v11).normalized()
|
|
||||||
);
|
|
||||||
|
|
||||||
if(quadCell.x0 + 1 < mx) {
|
if(quad_cell.x0 + 1 < mx) {
|
||||||
stack.emplace_back(QuadCell { mx, quadCell.x1, my, quadCell.y1 });
|
stack.emplace_back(QuadCell { mx, quad_cell.x1, my, quad_cell.y1 });
|
||||||
stack.emplace_back(QuadCell { quadCell.x0, mx, my, quadCell.y1 });
|
stack.emplace_back(QuadCell { quad_cell.x0, mx, my, quad_cell.y1 });
|
||||||
stack.emplace_back(QuadCell { mx, quadCell.x1, quadCell.y0, my });
|
stack.emplace_back(QuadCell { mx, quad_cell.x1, quad_cell.y0, my });
|
||||||
stack.emplace_back(QuadCell { quadCell.x0, mx, quadCell.y0, my });
|
stack.emplace_back(QuadCell { quad_cell.x0, mx, quad_cell.y0, my });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vertices += vertCount;
|
|
||||||
|
|
||||||
for(uint32_t y = 0; y < sideEdgeCount; y += 1) {
|
auto indexIndex = 0;
|
||||||
for(uint32_t x = 0; x < sideEdgeCount; x += 1) {
|
for(uint32_t y = 0; y < side_edge_count; y += 1) {
|
||||||
const auto i00 = index(x, y);
|
for(uint32_t x = 0; x < side_edge_count; x += 1) {
|
||||||
|
const auto i00 = index_offset + index(x, y);
|
||||||
const auto i01 = i00 + 1;
|
const auto i01 = i00 + 1;
|
||||||
const auto i10 = i00 + sideVertCount;
|
const auto i10 = i00 + side_vert_count;
|
||||||
const auto i11 = i10 + 1;
|
const auto i11 = i10 + 1;
|
||||||
|
|
||||||
*(indices++) = i00;
|
mesh.index(indexIndex++) = i00;
|
||||||
*(indices++) = i01;
|
mesh.index(indexIndex++) = i01;
|
||||||
*(indices++) = i10;
|
mesh.index(indexIndex++) = i10;
|
||||||
|
|
||||||
*(indices++) = i10;
|
mesh.index(indexIndex++) = i10;
|
||||||
*(indices++) = i01;
|
mesh.index(indexIndex++) = i01;
|
||||||
*(indices++) = i11;
|
mesh.index(indexIndex++) = i11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Real Cell::heightFactor(Vector3 corners[CornerCount]) {
|
Real Cell::height_factor(Vector3 corners[CornerCount]) {
|
||||||
Vector3 c = (corners[0] + corners[1] + corners[2] + corners[3]).normalized();
|
Vector3 c = (corners[0] + corners[1] + corners[2] + corners[3]).normalized();
|
||||||
return Real(1) / corners[0].dot(c);
|
return Real(1) / corners[0].dot(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Planet::Planet()
|
||||||
|
: m_cells {
|
||||||
|
{
|
||||||
|
Vector3(-1.0, -1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, -1.0, -1.0).normalized(),
|
||||||
|
Vector3(-1.0, 1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, -1.0).normalized(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Vector3( 1.0, -1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, 1.0).normalized(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Vector3( 1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3(-1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, 1.0).normalized(),
|
||||||
|
Vector3(-1.0, 1.0, 1.0).normalized(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Vector3(-1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3(-1.0, -1.0, -1.0).normalized(),
|
||||||
|
Vector3(-1.0, 1.0, 1.0).normalized(),
|
||||||
|
Vector3(-1.0, 1.0, -1.0).normalized(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Vector3(-1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3( 1.0, -1.0, 1.0).normalized(),
|
||||||
|
Vector3(-1.0, -1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, -1.0, -1.0).normalized(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Vector3(-1.0, 1.0, -1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, -1.0).normalized(),
|
||||||
|
Vector3(-1.0, 1.0, 1.0).normalized(),
|
||||||
|
Vector3( 1.0, 1.0, 1.0).normalized(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Planet::build_mesh(MeshView& mesh, uint32_t subdiv_count, Index index_offset) const {
|
||||||
|
auto const vertex_count = Cell::vertex_count(subdiv_count);
|
||||||
|
auto const index_count = 3 * Cell::triangle_count(subdiv_count);
|
||||||
|
|
||||||
|
for(Index cell_index = 0; cell_index < CellCount; cell_index += 1) {
|
||||||
|
auto sub_mesh = mesh.view(
|
||||||
|
vertex_count, cell_index * vertex_count,
|
||||||
|
index_count, cell_index * index_count
|
||||||
|
);
|
||||||
|
cell(cell_index).build_mesh(sub_mesh, subdiv_count,
|
||||||
|
index_offset + cell_index * vertex_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
115
src/Planet.h
115
src/Planet.h
@@ -1,13 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Eigen/Dense>
|
#include <core.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
using Real = float;
|
|
||||||
using Vector3 = Eigen::Matrix<Real, 3, 1>;
|
|
||||||
|
|
||||||
class Cell;
|
class Cell;
|
||||||
using CellUP = std::unique_ptr<Cell>;
|
using CellUP = std::unique_ptr<Cell>;
|
||||||
|
|
||||||
@@ -18,7 +16,85 @@ struct Vertex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Vector3 lerp(Real factor, const Vector3& v0, const Vector3& v1);
|
class MeshView {
|
||||||
|
public:
|
||||||
|
MeshView(
|
||||||
|
Index vertex_count,
|
||||||
|
Byte* positions, Index position_stride,
|
||||||
|
Byte* normals, Index normal_stride,
|
||||||
|
Byte* colors, Index color_stride,
|
||||||
|
Index index_count,
|
||||||
|
Byte* indices, Index index_stride
|
||||||
|
);
|
||||||
|
~MeshView() = default;
|
||||||
|
|
||||||
|
inline Index vertex_count() const {
|
||||||
|
return m_vertex_count;
|
||||||
|
}
|
||||||
|
inline Index index_count() const {
|
||||||
|
return m_index_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshView view(
|
||||||
|
Index vertex_count, Index vertex_index,
|
||||||
|
Index index_count, Index index_index
|
||||||
|
) {
|
||||||
|
assert(vertex_index + vertex_count <= m_vertex_count);
|
||||||
|
assert(index_index + index_count <= m_index_count);
|
||||||
|
return MeshView(
|
||||||
|
vertex_count,
|
||||||
|
m_positions + (vertex_index * m_position_stride),
|
||||||
|
m_position_stride,
|
||||||
|
m_normals + (vertex_index * m_normal_stride),
|
||||||
|
m_normal_stride,
|
||||||
|
m_colors + (vertex_index * m_color_stride),
|
||||||
|
m_color_stride,
|
||||||
|
index_count,
|
||||||
|
m_indices + (index_index * m_index_stride),
|
||||||
|
m_index_stride
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector3& position(Index vertex_index) {
|
||||||
|
assert(vertex_index < m_vertex_count);
|
||||||
|
return *reinterpret_cast<Vector3*>(
|
||||||
|
m_positions + (vertex_index * m_position_stride)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector3& normal(Index vertex_index) {
|
||||||
|
assert(vertex_index < m_vertex_count);
|
||||||
|
return *reinterpret_cast<Vector3*>(
|
||||||
|
m_normals + (vertex_index * m_normal_stride)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vector3& color(Index vertex_index) {
|
||||||
|
assert(vertex_index < m_vertex_count);
|
||||||
|
return *reinterpret_cast<Vector3*>(
|
||||||
|
m_colors + (vertex_index * m_color_stride)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Index& index(Index index_index) {
|
||||||
|
assert(index_index < m_index_count);
|
||||||
|
return *reinterpret_cast<Index*>(
|
||||||
|
m_indices + (index_index * m_index_stride)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Index m_vertex_count;
|
||||||
|
Byte* m_positions;
|
||||||
|
Index m_position_stride;
|
||||||
|
Byte* m_normals;
|
||||||
|
Index m_normal_stride;
|
||||||
|
Byte* m_colors;
|
||||||
|
Index m_color_stride;
|
||||||
|
Index m_index_count;
|
||||||
|
Byte* m_indices;
|
||||||
|
Index m_index_stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Cell {
|
class Cell {
|
||||||
@@ -40,20 +116,19 @@ public:
|
|||||||
Cell& operator=(const Cell&) = delete;
|
Cell& operator=(const Cell&) = delete;
|
||||||
Cell& operator=(Cell&&) = default;
|
Cell& operator=(Cell&&) = default;
|
||||||
|
|
||||||
Cell& cell(uint32_t cellIndex);
|
Cell& cell(uint32_t cell_index);
|
||||||
|
|
||||||
void writeMesh(
|
static size_t vertex_count(uint32_t subdiv_count);
|
||||||
Vertex*& vertices, const Vertex* verticesEnd,
|
static size_t triangle_count(uint32_t subdiv_count);
|
||||||
uint32_t*& indices, const uint32_t* indicesEnd,
|
|
||||||
uint32_t subdivCount = 4
|
void build_mesh(MeshView& mesh, uint32_t subdiv_count=4, Index index_offset=0) const;
|
||||||
) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Real heightFactor(Vector3 corners[CornerCount]);
|
static Real height_factor(Vector3 corners[CornerCount]);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 m_corners[CornerCount];
|
Vector3 m_corners[CornerCount];
|
||||||
Real m_heightFactor;
|
Real m_height_factor;
|
||||||
CellUP m_cells[CellCount];
|
CellUP m_cells[CellCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,8 +146,18 @@ public:
|
|||||||
Planet& operator=(const Planet&) = delete;
|
Planet& operator=(const Planet&) = delete;
|
||||||
Planet& operator=(Planet&&) = default;
|
Planet& operator=(Planet&&) = default;
|
||||||
|
|
||||||
Cell& cell(uint32_t cellIndex);
|
inline const Cell& cell(uint32_t cell_index) const {
|
||||||
|
assert(cell_index < CellCount);
|
||||||
|
return m_cells[cell_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Cell& cell(uint32_t cell_index) {
|
||||||
|
assert(cell_index < CellCount);
|
||||||
|
return m_cells[cell_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_mesh(MeshView& mesh, uint32_t subdiv_count=4, Index index_offset=0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CellUP m_cells[CellCount];
|
Cell m_cells[CellCount];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,48 +86,40 @@ VulkanTutorial::VulkanTutorial() {
|
|||||||
m_swapchain.register_destruction_callback(
|
m_swapchain.register_destruction_callback(
|
||||||
std::bind(&VulkanTutorial::destroy_swapchain_objects, this));
|
std::bind(&VulkanTutorial::destroy_swapchain_objects, this));
|
||||||
|
|
||||||
auto const subdivCount = 2;
|
auto const subdiv_count = 4;
|
||||||
auto const sideEdgeCount = (1u << subdivCount);
|
|
||||||
auto const sideVertCount = sideEdgeCount + 1;
|
|
||||||
auto const quadCount = sideEdgeCount * sideEdgeCount;
|
|
||||||
auto const indexCount = 6 * quadCount;
|
|
||||||
auto const vertCount = sideVertCount * sideVertCount;
|
|
||||||
|
|
||||||
vertices.assign(vertCount, Vertex{
|
vertices.resize(6 * Cell::vertex_count(subdiv_count));
|
||||||
Vector3::Constant(std::numeric_limits<Real>::quiet_NaN()),
|
indices.resize(6 * 3 * Cell::triangle_count(subdiv_count));
|
||||||
Vector3::Zero()
|
|
||||||
});
|
|
||||||
indices.assign(indexCount, UINT32_MAX);
|
|
||||||
|
|
||||||
Cell cell(
|
MeshView mesh(
|
||||||
Vector3(-1.0f, -1.0f, 1.0f).normalized(),
|
vertices.size(),
|
||||||
Vector3( 1.0f, -1.0f, 1.0f).normalized(),
|
reinterpret_cast<Byte*>(vertices.data()) + offsetof(Vertex, position),
|
||||||
Vector3(-1.0f, -1.0f, -1.0f).normalized(),
|
sizeof(Vertex),
|
||||||
Vector3( 1.0f, -1.0f, -1.0f).normalized()
|
nullptr,
|
||||||
|
sizeof(Vertex),
|
||||||
|
reinterpret_cast<Byte*>(vertices.data()) + offsetof(Vertex, color),
|
||||||
|
sizeof(Vertex),
|
||||||
|
indices.size(),
|
||||||
|
reinterpret_cast<Byte*>(indices.data()),
|
||||||
|
sizeof(Index)
|
||||||
);
|
);
|
||||||
|
|
||||||
auto vertex = &*vertices.begin();
|
Planet planet;
|
||||||
const auto verticesEnd = &*vertices.end();
|
planet.build_mesh(mesh, subdiv_count);
|
||||||
auto index = &*indices.begin();
|
|
||||||
const auto indicesEnd = &*indices.end();
|
|
||||||
cell.writeMesh(
|
|
||||||
vertex, verticesEnd,
|
|
||||||
index, indicesEnd,
|
|
||||||
subdivCount
|
|
||||||
);
|
|
||||||
|
|
||||||
logger.info() << "Vertices:";
|
for (size_t vertex_index = 0; vertex_index < vertices.size(); vertex_index += 1) {
|
||||||
for(auto v = &*vertices.begin(); v < vertex; v += 1)
|
mesh.color(vertex_index) =
|
||||||
logger.debug() << (v - &*vertices.begin()) << ": "
|
mesh.position(vertex_index) / 2.0f + Vector3::Constant(0.5f);
|
||||||
<< v->position.transpose() << " - "
|
}
|
||||||
<< v->color.transpose();
|
|
||||||
|
|
||||||
logger.info() << "Indices:";
|
|
||||||
for(auto i = &*indices.begin(); i < index; i += 6)
|
|
||||||
logger.debug() << (i - &*indices.begin()) << ": "
|
|
||||||
<< i[0] << ", " << i[1] << ", " << i[2] << " - "
|
|
||||||
<< i[3] << ", " << i[4] << ", " << i[5];
|
|
||||||
|
|
||||||
|
// for(size_t vi = 0; vi < vertices.size(); vi += 1)
|
||||||
|
// logger.debug() << "v" << vi << ": "
|
||||||
|
// << vertices[vi].position.transpose();
|
||||||
|
// for(size_t ii = 0; 3 * ii < indices.size(); ii += 1)
|
||||||
|
// logger.debug() << "i" << ii << ": "
|
||||||
|
// << indices[3 * ii + 0] << ", "
|
||||||
|
// << indices[3 * ii + 1] << ", "
|
||||||
|
// << indices[3 * ii + 2];
|
||||||
// abort();
|
// abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
105
src/core.h
Normal file
105
src/core.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <Eigen/Dense>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
using Byte = unsigned char;
|
||||||
|
using Index = uint32_t;
|
||||||
|
using Real = float;
|
||||||
|
using Vector3 = Eigen::Matrix<Real, 3, 1>;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Scalar, typename Derived0, typename Derived1>
|
||||||
|
auto lerp(
|
||||||
|
Scalar factor,
|
||||||
|
const Eigen::MatrixBase<Derived0>& m0,
|
||||||
|
const Eigen::MatrixBase<Derived1>& m1
|
||||||
|
) -> std::enable_if_t<
|
||||||
|
Derived0::RowsAtCompileTime == Derived1::RowsAtCompileTime &&
|
||||||
|
Derived0::ColsAtCompileTime == Derived1::ColsAtCompileTime,
|
||||||
|
Eigen::Matrix<
|
||||||
|
std::common_type_t<
|
||||||
|
Scalar,
|
||||||
|
typename Derived0::Scalar,
|
||||||
|
typename Derived1::Scalar
|
||||||
|
>,
|
||||||
|
Derived0::RowsAtCompileTime,
|
||||||
|
Derived0::ColsAtCompileTime
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
return (Scalar(1) - factor) * m0 + factor * m1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class ArrayView {
|
||||||
|
public:
|
||||||
|
ArrayView() = default;
|
||||||
|
ArrayView(const ArrayView&) = default;
|
||||||
|
ArrayView(ArrayView&&) = default;
|
||||||
|
~ArrayView() = default;
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
ArrayView(Index size, U* data, Index stride=sizeof(T))
|
||||||
|
: m_data(reinterpret_cast<Byte*>(data))
|
||||||
|
, m_size(size)
|
||||||
|
, m_stride(stride)
|
||||||
|
{
|
||||||
|
assert(m_data != nullptr || m_size == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ArrayView(std::vector<T>& vector)
|
||||||
|
: m_data(vector.data())
|
||||||
|
, m_data(vector.size())
|
||||||
|
{}
|
||||||
|
|
||||||
|
ArrayView& operator=(const ArrayView&) = default;
|
||||||
|
ArrayView& operator=(ArrayView&&) = default;
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return m_size != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index size() const {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index stride() const {
|
||||||
|
return m_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* data() const {
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* data() {
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](Index index) const {
|
||||||
|
assert(index < m_size);
|
||||||
|
return *reinterpret_cast<T*>(m_data + index * m_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](Index index) {
|
||||||
|
return const_cast<T&>(const_cast<ArrayView&>(*this)[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayView slice(Index start, Index count, Index step=1) {
|
||||||
|
assert(step > 0);
|
||||||
|
assert(start + count * step < m_size);
|
||||||
|
return ArrayView(
|
||||||
|
count,
|
||||||
|
m_data + start * m_stride,
|
||||||
|
m_stride * step
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Byte* m_data = nullptr;
|
||||||
|
Index m_size = 0;
|
||||||
|
Index m_stride = sizeof(T);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user