Planet WIP.
This commit is contained in:
150
src/Planet.cpp
Normal file
150
src/Planet.cpp
Normal file
@@ -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);
|
||||
}
|
||||
78
src/Planet.h
Normal file
78
src/Planet.h
Normal file
@@ -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];
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <utils.h>
|
||||
#include <Logger.h>
|
||||
#include <Planet.h>
|
||||
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
|
||||
@@ -15,7 +16,7 @@
|
||||
#include <cstring>
|
||||
|
||||
|
||||
VkVertexInputBindingDescription Vertex::binding_description() {
|
||||
VkVertexInputBindingDescription vertex_binding_description() {
|
||||
return {
|
||||
.binding = 0,
|
||||
.stride = sizeof(Vertex),
|
||||
@@ -23,7 +24,7 @@ VkVertexInputBindingDescription Vertex::binding_description() {
|
||||
};
|
||||
}
|
||||
|
||||
std::array<VkVertexInputAttributeDescription, 2> Vertex::attributes_description() {
|
||||
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description() {
|
||||
return {
|
||||
VkVertexInputAttributeDescription {
|
||||
.location = 0,
|
||||
@@ -41,7 +42,7 @@ std::array<VkVertexInputAttributeDescription, 2> Vertex::attributes_description(
|
||||
}
|
||||
|
||||
|
||||
const std::vector<Vertex> vertices = {
|
||||
std::vector<Vertex> vertices = {
|
||||
{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
@@ -53,7 +54,7 @@ const std::vector<Vertex> vertices = {
|
||||
{{0.5f, 0.5f, 0.5f}, {0.2f, 0.2f, 0.2f}},
|
||||
};
|
||||
|
||||
const std::vector<uint16_t> indices = {
|
||||
std::vector<uint32_t> indices = {
|
||||
0, 1, 2,
|
||||
2, 1, 3,
|
||||
|
||||
@@ -84,6 +85,50 @@ VulkanTutorial::VulkanTutorial() {
|
||||
std::bind(&VulkanTutorial::create_swapchain_objects, this, std::placeholders::_1));
|
||||
m_swapchain.register_destruction_callback(
|
||||
std::bind(&VulkanTutorial::destroy_swapchain_objects, this));
|
||||
|
||||
auto const subdivCount = 2;
|
||||
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{
|
||||
Vector3::Constant(std::numeric_limits<Real>::quiet_NaN()),
|
||||
Vector3::Zero()
|
||||
});
|
||||
indices.assign(indexCount, UINT32_MAX);
|
||||
|
||||
Cell cell(
|
||||
Vector3(-1.0f, -1.0f, 1.0f).normalized(),
|
||||
Vector3( 1.0f, -1.0f, 1.0f).normalized(),
|
||||
Vector3(-1.0f, -1.0f, -1.0f).normalized(),
|
||||
Vector3( 1.0f, -1.0f, -1.0f).normalized()
|
||||
);
|
||||
|
||||
auto vertex = &*vertices.begin();
|
||||
const auto verticesEnd = &*vertices.end();
|
||||
auto index = &*indices.begin();
|
||||
const auto indicesEnd = &*indices.end();
|
||||
cell.writeMesh(
|
||||
vertex, verticesEnd,
|
||||
index, indicesEnd,
|
||||
subdivCount
|
||||
);
|
||||
|
||||
logger.info() << "Vertices:";
|
||||
for(auto v = &*vertices.begin(); v < vertex; v += 1)
|
||||
logger.debug() << (v - &*vertices.begin()) << ": "
|
||||
<< 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];
|
||||
|
||||
// abort();
|
||||
}
|
||||
|
||||
VulkanTutorial::~VulkanTutorial() {
|
||||
@@ -375,9 +420,9 @@ void VulkanTutorial::create_graphic_pipeline() {
|
||||
};
|
||||
|
||||
const VkVertexInputBindingDescription vertex_bindings[] = {
|
||||
Vertex::binding_description(),
|
||||
vertex_binding_description(),
|
||||
};
|
||||
const auto vertex_attributes = Vertex::attributes_description();
|
||||
const auto vertex_attributes = vertex_attributes_description();
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertex_info {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
@@ -420,6 +465,7 @@ void VulkanTutorial::create_graphic_pipeline() {
|
||||
.depthClampEnable = VK_FALSE,
|
||||
.rasterizerDiscardEnable = VK_FALSE,
|
||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||
// .cullMode = VK_CULL_MODE_NONE,
|
||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.depthBiasEnable = VK_FALSE,
|
||||
@@ -778,7 +824,7 @@ void VulkanTutorial::create_command_buffers() {
|
||||
command_buffer,
|
||||
m_index_buffer,
|
||||
0,
|
||||
VK_INDEX_TYPE_UINT16
|
||||
VK_INDEX_TYPE_UINT32
|
||||
);
|
||||
|
||||
vkCmdDrawIndexed(
|
||||
|
||||
@@ -10,13 +10,8 @@
|
||||
#include <chrono>
|
||||
|
||||
|
||||
struct Vertex {
|
||||
Eigen::Vector3f position;
|
||||
Eigen::Vector3f color;
|
||||
|
||||
static VkVertexInputBindingDescription binding_description();
|
||||
static std::array<VkVertexInputAttributeDescription, 2> attributes_description();
|
||||
};
|
||||
VkVertexInputBindingDescription vertex_binding_description();
|
||||
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description();
|
||||
|
||||
|
||||
class VulkanTutorial {
|
||||
|
||||
Reference in New Issue
Block a user