5 changed files with 284 additions and 14 deletions
@ -0,0 +1,150 @@ |
|||
|
|||
#include <Planet.h> |
|||
#include <Logger.h> |
|||
|
|||
#include <cassert> |
|||
#include <vector> |
|||
|
|||
|
|||
Vector3 lerp(Real factor, const Vector3& v0, const Vector3& v1) { |
|||
return (Real(1) - factor) * v0 + factor * v1; |
|||
} |
|||
|
|||
|
|||
Cell::Cell( |
|||
const Vector3& corner00, |
|||
const Vector3& corner01, |
|||
const Vector3& corner10, |
|||
const Vector3& corner11 |
|||
) |
|||
: m_corners{ corner00, corner01, corner10, corner11 } |
|||
, m_heightFactor(heightFactor(m_corners)) |
|||
, m_cells{ nullptr, nullptr, nullptr, nullptr } |
|||
{} |
|||
|
|||
Cell& Cell::cell(uint32_t cellIndex) { |
|||
assert(cellIndex < CellCount); |
|||
auto& cell = m_cells[cellIndex]; |
|||
if(!cell) |
|||
{ |
|||
// TODO
|
|||
} |
|||
return *cell; |
|||
} |
|||
|
|||
void Cell::writeMesh( |
|||
Vertex*& vertices, const Vertex* verticesEnd, |
|||
uint32_t*& indices, const uint32_t* indicesEnd, |
|||
uint32_t subdivCount |
|||
) const { |
|||
auto const sideEdgeCount = (1u << subdivCount); |
|||
auto const sideVertCount = sideEdgeCount + 1; |
|||
|
|||
auto const quadCount = sideEdgeCount * sideEdgeCount; |
|||
auto const triCount = 2 * quadCount; |
|||
auto const vertCount = sideVertCount * sideVertCount; |
|||
|
|||
assert(vertices + vertCount <= verticesEnd); |
|||
assert(indices + (3 * triCount) <= indicesEnd); |
|||
|
|||
auto const index = [sideVertCount](uint32_t x, uint32_t y) -> uint32_t { |
|||
return x + y * sideVertCount; |
|||
}; |
|||
auto const vertex = [vertices, &index](uint32_t x, uint32_t y) -> Vertex& { |
|||
return vertices[index(x, y)]; |
|||
}; |
|||
|
|||
Vector3 c00(0.0f, 0.0f, 1.0f); |
|||
Vector3 c01(1.0f, 0.0f, 1.0f); |
|||
Vector3 c10(0.0f, 1.0f, 1.0f); |
|||
Vector3 c11(1.0f, 1.0f, 1.0f); |
|||
|
|||
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 { |
|||
uint32_t x0, x1, y0, y1; |
|||
}; |
|||
std::vector<QuadCell> stack; |
|||
stack.reserve(quadCount / 4); |
|||
if(subdivCount > 0) { |
|||
stack.emplace_back(QuadCell { |
|||
0, sideEdgeCount, |
|||
0, sideEdgeCount, |
|||
}); |
|||
} |
|||
|
|||
while(!stack.empty()) { |
|||
const auto quadCell = stack.back(); |
|||
stack.pop_back(); |
|||
|
|||
auto const mx = (quadCell.x0 + quadCell.x1) / 2; |
|||
auto const my = (quadCell.y0 + quadCell.y1) / 2; |
|||
|
|||
auto const& v00 = vertex(quadCell.x0, quadCell.y0).position; |
|||
auto const& v01 = vertex(quadCell.x1, quadCell.y0).position; |
|||
auto const& v10 = vertex(quadCell.x0, quadCell.y1).position; |
|||
auto const& v11 = vertex(quadCell.x1, quadCell.y1).position; |
|||
|
|||
setVertex( mx, quadCell.y0, |
|||
(v00 + v01).normalized() |
|||
); |
|||
setVertex(quadCell.x0, my, |
|||
(v00 + v10).normalized() |
|||
); |
|||
setVertex(mx, my, |
|||
(v00 + v01 + v10 + v11).normalized() |
|||
); |
|||
setVertex(quadCell.x1, my, |
|||
(v01 + v11).normalized() |
|||
); |
|||
setVertex( mx, quadCell.y1, |
|||
(v10 + v11).normalized() |
|||
); |
|||
|
|||
if(quadCell.x0 + 1 < mx) { |
|||
stack.emplace_back(QuadCell { mx, quadCell.x1, my, quadCell.y1 }); |
|||
stack.emplace_back(QuadCell { quadCell.x0, mx, my, quadCell.y1 }); |
|||
stack.emplace_back(QuadCell { mx, quadCell.x1, quadCell.y0, my }); |
|||
stack.emplace_back(QuadCell { quadCell.x0, mx, quadCell.y0, my }); |
|||
} |
|||
} |
|||
vertices += vertCount; |
|||
|
|||
for(uint32_t y = 0; y < sideEdgeCount; y += 1) { |
|||
for(uint32_t x = 0; x < sideEdgeCount; x += 1) { |
|||
const auto i00 = index(x, y); |
|||
const auto i01 = i00 + 1; |
|||
const auto i10 = i00 + sideVertCount; |
|||
const auto i11 = i10 + 1; |
|||
|
|||
*(indices++) = i00; |
|||
*(indices++) = i01; |
|||
*(indices++) = i10; |
|||
|
|||
*(indices++) = i10; |
|||
*(indices++) = i01; |
|||
*(indices++) = i11; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Real Cell::heightFactor(Vector3 corners[CornerCount]) { |
|||
Vector3 c = (corners[0] + corners[1] + corners[2] + corners[3]).normalized(); |
|||
return Real(1) / corners[0].dot(c); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
#pragma once |
|||
|
|||
#include <Eigen/Dense> |
|||
|
|||
#include <memory> |
|||
|
|||
|
|||
using Real = float; |
|||
using Vector3 = Eigen::Matrix<Real, 3, 1>; |
|||
|
|||
class Cell; |
|||
using CellUP = std::unique_ptr<Cell>; |
|||
|
|||
|
|||
struct Vertex { |
|||
Vector3 position; |
|||
Vector3 color; |
|||
}; |
|||
|
|||
|
|||
Vector3 lerp(Real factor, const Vector3& v0, const Vector3& v1); |
|||
|
|||
|
|||
class Cell { |
|||
public: |
|||
static constexpr uint32_t CornerCount = 4; |
|||
static constexpr uint32_t CellCount = 4; |
|||
|
|||
public: |
|||
Cell( |
|||
const Vector3& corner00, |
|||
const Vector3& corner01, |
|||
const Vector3& corner10, |
|||
const Vector3& corner11 |
|||
); |
|||
Cell(const Cell&) = delete; |
|||
Cell(Cell&&) = default; |
|||
~Cell() = default; |
|||
|
|||
Cell& operator=(const Cell&) = delete; |
|||
Cell& operator=(Cell&&) = default; |
|||
|
|||
Cell& cell(uint32_t cellIndex); |
|||
|
|||
void writeMesh( |
|||
Vertex*& vertices, const Vertex* verticesEnd, |
|||
uint32_t*& indices, const uint32_t* indicesEnd, |
|||
uint32_t subdivCount = 4 |
|||
) const; |
|||
|
|||
private: |
|||
static Real heightFactor(Vector3 corners[CornerCount]); |
|||
|
|||
private: |
|||
Vector3 m_corners[CornerCount]; |
|||
Real m_heightFactor; |
|||
CellUP m_cells[CellCount]; |
|||
}; |
|||
|
|||
|
|||
class Planet { |
|||
public: |
|||
static constexpr uint32_t CellCount = 6; |
|||
|
|||
public: |
|||
Planet(); |
|||
Planet(const Planet&) = delete; |
|||
Planet(Planet&&) = default; |
|||
~Planet() = default; |
|||
|
|||
Planet& operator=(const Planet&) = delete; |
|||
Planet& operator=(Planet&&) = default; |
|||
|
|||
Cell& cell(uint32_t cellIndex); |
|||
|
|||
private: |
|||
CellUP m_cells[CellCount]; |
|||
}; |
|||
Loading…
Reference in new issue