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