Merge pull request 'Geometry Factory helper class' (#47) from geometry_factory into master

Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/47
Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
Vladyslav_Baranovskyi_EXT
2024-06-14 10:52:53 +02:00
6 changed files with 409 additions and 60 deletions

View File

@@ -8,6 +8,7 @@
#include "Scene/Scene.hpp" #include "Scene/Scene.hpp"
#include "Scene/Shader/Shader.hpp" #include "Scene/Shader/Shader.hpp"
#include "Scene/Geometry.hpp" #include "Scene/Geometry.hpp"
#include "Scene/GeometryFactory.hpp"
#include "Scene/Material.hpp" #include "Scene/Material.hpp"
#include "Scene/Vertex.hpp" #include "Scene/Vertex.hpp"
#include "Scene/SimpleDrawable.hpp" #include "Scene/SimpleDrawable.hpp"
@@ -59,9 +60,8 @@ namespace OpenVulkano
drawablesPool.resize(GEOS); drawablesPool.resize(GEOS);
for (uint32_t i = 0; i < GEOS; i++) for (uint32_t i = 0; i < GEOS; i++)
{ {
Geometry* geo = new Geometry(); Geometry* geo = GeometryFactory::MakeCube(std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f,
geo->InitCube(std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f, Vector4f((std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, 1));
Vector4f((std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, 1));
drawablesPool[i].Init(&shader, geo, &mat); drawablesPool[i].Init(&shader, geo, &mat);
} }
nodesPool.resize(OBJECTS); nodesPool.resize(OBJECTS);

View File

@@ -9,6 +9,7 @@
#include "Scene/Scene.hpp" #include "Scene/Scene.hpp"
#include "Scene/Shader/Shader.hpp" #include "Scene/Shader/Shader.hpp"
#include "Scene/Geometry.hpp" #include "Scene/Geometry.hpp"
#include "Scene/GeometryFactory.hpp"
#include "Scene/Material.hpp" #include "Scene/Material.hpp"
#include "Scene/Vertex.hpp" #include "Scene/Vertex.hpp"
#include "Scene/SimpleDrawable.hpp" #include "Scene/SimpleDrawable.hpp"
@@ -27,7 +28,7 @@ namespace OpenVulkano
{ {
struct SceneElement struct SceneElement
{ {
Scene::Geometry m_geometry; Scene::Geometry *m_geometry;
Scene::SimpleDrawable m_drawable; Scene::SimpleDrawable m_drawable;
Scene::Node m_node; Scene::Node m_node;
}; };
@@ -46,11 +47,16 @@ namespace OpenVulkano
SceneElement m_whiteBox; SceneElement m_whiteBox;
SceneElement m_redBox; SceneElement m_redBox;
void CreateSceneElement(SceneElement *dest, const Math::Vector4f &color, float scale) SceneElement m_plane;
SceneElement m_sphere;
SceneElement m_hemisphere;
SceneElement m_triangle;
SceneElement m_cylinder;
SceneElement m_pyramid;
void CompleteSceneElement(SceneElement *dest)
{ {
dest->m_geometry.InitCube(scale, scale, scale, color); dest->m_drawable.Init(&m_shader, dest->m_geometry, &m_material);
dest->m_drawable.Init(&m_shader, &dest->m_geometry, &m_material);
dest->m_node.Init(); dest->m_node.Init();
m_scene.GetRoot()->AddChild(&dest->m_node); m_scene.GetRoot()->AddChild(&dest->m_node);
dest->m_node.SetUpdateFrequency(Scene::UpdateFrequency::Always); dest->m_node.SetUpdateFrequency(Scene::UpdateFrequency::Always);
@@ -58,6 +64,48 @@ namespace OpenVulkano
dest->m_node.SetMatrix(Math::Matrix4f(1)); dest->m_node.SetMatrix(Math::Matrix4f(1));
} }
void CreateSceneElement(SceneElement *dest, const Math::Vector4f &color, float scale)
{
dest->m_geometry = Scene::GeometryFactory::MakeCube(scale, scale, scale, color);
CompleteSceneElement(dest);
}
void CreatePlane(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakePlane(1, 1, color);
CompleteSceneElement(dest);
}
void CreateSphere(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakeSphere(1, 32, 16, color);
CompleteSceneElement(dest);
}
void CreateHemisphere(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakeHemisphere(1, 16, 16, color);
CompleteSceneElement(dest);
}
void CreateTriangle(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakeTriangle(Math::Vector3f(0.5, 0., 0.), Math::Vector3f(0., 0.5, 0.), Math::Vector3f(-0.5, 0., 0.), color);
CompleteSceneElement(dest);
}
void CreateCylinder(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakeCylinder(1, 3, 64, color);
CompleteSceneElement(dest);
}
void CreatePyramid(SceneElement *dest, const Math::Vector4f& color)
{
dest->m_geometry = Scene::GeometryFactory::MakePyramid(0.5, 2, color);
CompleteSceneElement(dest);
}
public: public:
void Init() override void Init() override
{ {
@@ -95,6 +143,24 @@ namespace OpenVulkano
m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(3, 2, 1, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3); m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(3, 2, 1, 1)), Math::Vector3f_SIMD(1, 1, -1)), 3);
m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1); m_sequenceAnimationController.AddAnimationStep(Math::PoseF(Math::Utils::normalize(Math::QuaternionF(0, 0, 1, 1)), Math::Vector3f_SIMD(0, 1, 0)), 1);
m_sequenceAnimationController.SetAnimationPoseResetTime(10); m_sequenceAnimationController.SetAnimationPoseResetTime(10);
CreatePlane(&m_plane, Math::Vector4f(0.3, 0.6, 0.9, 1.0));
m_plane.m_node.worldMat = Math::Utils::translate(Math::Vector3f(3, 0, 0));
CreateSphere(&m_sphere, Math::Vector4f(0.9, 0.6, 0.9, 1.0));
m_sphere.m_node.worldMat = Math::Utils::translate(Math::Vector3f(5, 0, 0));
CreateHemisphere(&m_hemisphere, Math::Vector4f(0.6, 0.3, 0.9, 1.0));
m_hemisphere.m_node.worldMat = Math::Utils::translate(Math::Vector3f(7, 0, 0));
CreateTriangle(&m_triangle, Math::Vector4f(0.6, 0.9, 0.3, 1.0));
m_triangle.m_node.worldMat = Math::Utils::translate(Math::Vector3f(9, 0, 0));
CreateCylinder(&m_cylinder, Math::Vector4f(0.3, 0.9, 0.9, 1.0));
m_cylinder.m_node.worldMat = Math::Utils::translate(Math::Vector3f(11, 0, 0));
CreatePyramid(&m_pyramid, Math::Vector4f(0.9, 0.9, 0.6, 1.0));
m_pyramid.m_node.worldMat = Math::Utils::translate(Math::Vector3f(13, 0, 0));
} }
void OnSimpleAnimationCompleted(Scene::SimpleAnimationController *anim) void OnSimpleAnimationCompleted(Scene::SimpleAnimationController *anim)

View File

@@ -92,56 +92,6 @@ namespace OpenVulkano::Scene
#endif #endif
} }
void Geometry::InitCube(float x, float y, float z, const Math::Vector4f& color)
{
Init(24, 36);
SetIndices(new uint32_t[indexCount]{
0, 1, 2, 0, 2, 3, // front face index data
4, 5, 6, 4, 6, 7, // back face index data
8, 9, 10, 8, 10, 11, // top face index data
12, 13, 14, 12, 14, 15, // bottom face index data
16, 17, 18, 16, 18, 19, // left face index data
20, 21, 22, 20, 22, 23 // right face index data
}, indexCount);
x *= 0.5f; y *= 0.5f; z *= 0.5f;
uint32_t i = 0;
// front face vertex data
vertices[i++].Set(+x, -y, +z, +0, +0, +1, +0, +1);
vertices[i++].Set(+x, +y, +z, +0, +0, +1, +0, +0);
vertices[i++].Set(-x, +y, +z, +0, +0, +1, +1, +0);
vertices[i++].Set(-x, -y, +z, +0, +0, +1, +1, +1);
// back face vertex data
vertices[i++].Set(+x, -y, -z, +0, +0, -1, +1, +1);
vertices[i++].Set(-x, -y, -z, +0, +0, -1, +0, +1);
vertices[i++].Set(-x, +y, -z, +0, +0, -1, +0, +0);
vertices[i++].Set(+x, +y, -z, +0, +0, -1, +1, +0);
// top face vertex data
vertices[i++].Set(+x, +y, +z, +0, -1, +0, +0, +1);
vertices[i++].Set(+x, +y, -z, +0, -1, +0, +0, +0);
vertices[i++].Set(-x, +y, -z, +0, -1, +0, +1, +0);
vertices[i++].Set(-x, +y, +z, +0, -1, +0, +1, +1);
// bottom face vertex data
vertices[i++].Set(+x, -y, +z, +0, +1, +0, +1, +1);
vertices[i++].Set(-x, -y, +z, +0, +1, +0, +0, +1);
vertices[i++].Set(-x, -y, -z, +0, +1, +0, +0, +0);
vertices[i++].Set(+x, -y, -z, +0, +1, +0, +1, +0);
// Fill in the left face vertex data
vertices[i++].Set(-x, -y, -z, -1, +0, +0, +1, +1);
vertices[i++].Set(-x, -y, +z, -1, +0, +0, +0, +1);
vertices[i++].Set(-x, +y, +z, -1, +0, +0, +0, +0);
vertices[i++].Set(-x, +y, -z, -1, +0, +0, +1, +0);
// Fill in the right face vertex data
vertices[i++].Set(+x, -y, +z, +1, +0, +0, +1, +1);
vertices[i++].Set(+x, -y, -z, +1, +0, +0, +0, +1);
vertices[i++].Set(+x, +y, -z, +1, +0, +0, +0, +0);
vertices[i].Set(+x, +y, +z, +1, +0, +0, +1, +0);
for(i = 0; i < vertexCount; i++)
{
vertices[i].color = color;
}
}
void Geometry::SetIndices(const uint32_t* data, uint32_t size, uint32_t offset) const void Geometry::SetIndices(const uint32_t* data, uint32_t size, uint32_t offset) const
{ {
size += offset; size += offset;

View File

@@ -65,8 +65,6 @@ namespace OpenVulkano
void Init(aiMesh* mesh); void Init(aiMesh* mesh);
void InitCube(float x = 1, float y = 1, float z = 1, const Math::Vector4f& color = Math::Vector4f(1));
void SetIndices(const uint32_t* data, uint32_t size, uint32_t offset = 0) const; void SetIndices(const uint32_t* data, uint32_t size, uint32_t offset = 0) const;
void Close() override; void Close() override;

View File

@@ -0,0 +1,311 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "GeometryFactory.hpp"
#include "Vertex.hpp"
#define _USE_MATH_DEFINES
#include <math.h>
#include <assert.h>
namespace OpenVulkano::Scene
{
Geometry* GeometryFactory::MakeCube(float x, float y, float z, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
const int indexCount = 36;
result->Init(24, indexCount);
uint32_t indices[indexCount] =
{
0, 1, 2, 0, 2, 3, // front face index data
4, 5, 6, 4, 6, 7, // back face index data
8, 9, 10, 8, 10, 11, // top face index data
12, 13, 14, 12, 14, 15, // bottom face index data
16, 17, 18, 16, 18, 19, // left face index data
20, 21, 22, 20, 22, 23 // right face index data
};
result->SetIndices(indices, result->indexCount);
x *= 0.5f; y *= 0.5f; z *= 0.5f;
uint32_t i = 0;
// front face vertex data
result->vertices[i++].Set(+x, -y, +z, +0, +0, +1, +0, +1);
result->vertices[i++].Set(+x, +y, +z, +0, +0, +1, +0, +0);
result->vertices[i++].Set(-x, +y, +z, +0, +0, +1, +1, +0);
result->vertices[i++].Set(-x, -y, +z, +0, +0, +1, +1, +1);
// back face vertex data
result->vertices[i++].Set(+x, -y, -z, +0, +0, -1, +1, +1);
result->vertices[i++].Set(-x, -y, -z, +0, +0, -1, +0, +1);
result->vertices[i++].Set(-x, +y, -z, +0, +0, -1, +0, +0);
result->vertices[i++].Set(+x, +y, -z, +0, +0, -1, +1, +0);
// top face vertex data
result->vertices[i++].Set(+x, +y, +z, +0, -1, +0, +0, +1);
result->vertices[i++].Set(+x, +y, -z, +0, -1, +0, +0, +0);
result->vertices[i++].Set(-x, +y, -z, +0, -1, +0, +1, +0);
result->vertices[i++].Set(-x, +y, +z, +0, -1, +0, +1, +1);
// bottom face vertex data
result->vertices[i++].Set(+x, -y, +z, +0, +1, +0, +1, +1);
result->vertices[i++].Set(-x, -y, +z, +0, +1, +0, +0, +1);
result->vertices[i++].Set(-x, -y, -z, +0, +1, +0, +0, +0);
result->vertices[i++].Set(+x, -y, -z, +0, +1, +0, +1, +0);
// Fill in the left face vertex data
result->vertices[i++].Set(-x, -y, -z, -1, +0, +0, +1, +1);
result->vertices[i++].Set(-x, -y, +z, -1, +0, +0, +0, +1);
result->vertices[i++].Set(-x, +y, +z, -1, +0, +0, +0, +0);
result->vertices[i++].Set(-x, +y, -z, -1, +0, +0, +1, +0);
// Fill in the right face vertex data
result->vertices[i++].Set(+x, -y, +z, +1, +0, +0, +1, +1);
result->vertices[i++].Set(+x, -y, -z, +1, +0, +0, +0, +1);
result->vertices[i++].Set(+x, +y, -z, +1, +0, +0, +0, +0);
result->vertices[i].Set(+x, +y, +z, +1, +0, +0, +1, +0);
for(i = 0; i < result->vertexCount; i++)
{
result->vertices[i].color = color;
}
return result;
}
Geometry* GeometryFactory::MakePlane(float width, float height, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
result->Init(4, 6);
uint32_t indices[] = { 0, 2, 1, 0, 3, 2 };
result->SetIndices(indices, result->indexCount);
width *= 0.5f; height *= 0.5f;
result->vertices[0].Set(-width, -height, 0, 0, 0, 1, 0, 1);
result->vertices[1].Set(-width, height, 0, 0, 0, 1, 0, 0);
result->vertices[2].Set(width, height, 0, 0, 0, 1, 1, 0);
result->vertices[3].Set(width, -height, 0, 0, 0, 1, 1, 1);
for (uint32_t i = 0; i < result->vertexCount; i++)
{
result->vertices[i].color = color;
}
return result;
}
Geometry* GeometryFactory::MakeSphere(float radius, uint32_t segments, uint32_t rings, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
uint32_t vertexCount = (rings + 1) * (segments + 1);
uint32_t indexCount = 6 * rings * segments;
result->Init(vertexCount, indexCount);
uint32_t i = 0;
for (uint32_t ring = 0; ring <= rings; ++ring)
{
float theta = ring * M_PI / rings;
float sinTheta = sin(theta);
float cosTheta = cos(theta);
for (uint32_t segment = 0; segment <= segments; ++segment)
{
float phi = segment * 2 * M_PI / segments;
float sinPhi = sin(phi);
float cosPhi = cos(phi);
float x = cosPhi * sinTheta;
float y = cosTheta;
float z = sinPhi * sinTheta;
float u = 1 - (float(segment) / segments);
float v = float(ring) / rings;
result->vertices[i].Set(radius * x, radius * y, radius * z, x, y, z, u, v);
result->vertices[i].color = color;
++i;
}
}
i = 0;
uint32_t* indices = new uint32_t[indexCount];
for (uint32_t ring = 0; ring < rings; ++ring)
{
for (uint32_t segment = 0; segment < segments; ++segment)
{
uint32_t first = (ring * (segments + 1)) + segment;
uint32_t second = first + segments + 1;
indices[i++] = first;
indices[i++] = first + 1;
indices[i++] = second;
indices[i++] = second;
indices[i++] = first + 1;
indices[i++] = second + 1;
}
}
result->SetIndices(indices, indexCount);
delete[] indices;
return result;
}
Geometry* GeometryFactory::MakeHemisphere(float radius, uint32_t segments, uint32_t rings, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
uint32_t vertexCount = (rings + 1) * (segments + 1);
uint32_t indexCount = 6 * rings * segments;
result->Init(vertexCount, indexCount);
uint32_t i = 0;
for (uint32_t ring = 0; ring <= rings; ++ring)
{
float theta = (ring * M_PI_2) / rings;
float sinTheta = sin(theta);
float cosTheta = cos(theta);
for (uint32_t segment = 0; segment <= segments; ++segment)
{
float phi = segment * 2 * M_PI / segments;
float sinPhi = sin(phi);
float cosPhi = cos(phi);
float x = cosPhi * sinTheta;
float y = cosTheta;
float z = sinPhi * sinTheta;
float u = 1 - (float(segment) / segments);
float v = float(ring) / rings;
result->vertices[i].Set(radius * x, radius * y, radius * z, x, y, z, u, v);
result->vertices[i].color = color;
++i;
}
}
i = 0;
uint32_t* indices = new uint32_t[indexCount];
for (uint32_t ring = 0; ring < rings; ++ring)
{
for (uint32_t segment = 0; segment < segments; ++segment)
{
uint32_t first = (ring * (segments + 1)) + segment;
uint32_t second = first + segments + 1;
indices[i++] = first;
indices[i++] = first + 1;
indices[i++] = second;
indices[i++] = second;
indices[i++] = first + 1;
indices[i++] = second + 1;
}
}
result->SetIndices(indices, indexCount);
delete[] indices;
return result;
}
Geometry* GeometryFactory::MakeTriangle(const Math::Vector3f& p1, const Math::Vector3f& p2, const Math::Vector3f& p3, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
result->Init(3, 3);
uint32_t indices[] = { 0, 1, 2 };
result->SetIndices(indices, result->indexCount);
result->vertices[0].Set(p1.x, p1.y, p1.z, 0, 0, 1, 0, 0);
result->vertices[1].Set(p2.x, p2.y, p2.z, 0, 0, 1, 1, 0);
result->vertices[2].Set(p3.x, p3.y, p3.z, 0, 0, 1, 0, 1);
for (uint32_t i = 0; i < result->vertexCount; i++)
{
result->vertices[i].color = color;
}
return result;
}
Geometry* GeometryFactory::MakeCylinder(float radius, float height, uint32_t segments, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
uint32_t vertexCount = 2 * (segments + 1);
uint32_t indexCount = 12 * segments;
result->Init(vertexCount, indexCount);
float halfHeight = height * 0.5f;
uint32_t i = 0;
for (uint32_t segment = 0; segment <= segments; ++segment)
{
float theta = segment * 2 * M_PI / segments;
float x = radius * cos(theta);
float z = radius * sin(theta);
float u = float(segment) / segments;
result->vertices[i].Set(x, -halfHeight, z, x, 0, z, u, 0);
result->vertices[i++].color = color;
result->vertices[i].Set(x, halfHeight, z, x, 0, z, u, 1);
result->vertices[i++].color = color;
}
i = 0;
uint32_t* indices = new uint32_t[indexCount];
for (uint32_t segment = 0; segment < segments; ++segment)
{
uint32_t first = segment * 2;
uint32_t second = first + 1;
indices[i++] = first;
indices[i++] = second;
indices[i++] = first + 2;
indices[i++] = second;
indices[i++] = second + 2;
indices[i++] = first + 2;
indices[i++] = first;
indices[i++] = first + 2;
indices[i++] = second + 2;
indices[i++] = second;
indices[i++] = first;
indices[i++] = second + 2;
}
result->SetIndices(indices, indexCount);
delete[] indices;
return result;
}
Geometry* GeometryFactory::MakePyramid(float baseLength, float height, const Math::Vector4f& color)
{
Geometry* result = new Geometry();
result->Init(5, 18);
uint32_t indices[] = {
// Base
1, 2, 3,
1, 3, 4,
// Sides
0, 1, 2,
0, 2, 3,
0, 3, 4,
0, 4, 1
};
result->SetIndices(indices, result->indexCount);
float halfBase = baseLength * 0.5f;
// Top vertex
result->vertices[0].Set(0, height, 0, 0, 1, 0, 0.5f, 1);
// Base vertices
result->vertices[1].Set(-halfBase, 0, halfBase, 0, -1, 0, 0, 0);
result->vertices[2].Set(halfBase, 0, halfBase, 0, -1, 0, 1, 0);
result->vertices[3].Set(halfBase, 0, -halfBase, 0, -1, 0, 1, 1);
result->vertices[4].Set(-halfBase, 0, -halfBase, 0, -1, 0, 0, 1);
for (uint32_t i = 0; i < result->vertexCount; i++)
{
result->vertices[i].color = color;
}
return result;
}
}

View File

@@ -0,0 +1,24 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Geometry.hpp"
namespace OpenVulkano::Scene
{
class GeometryFactory
{
public:
static Geometry* MakeCube(float x = 1, float y = 1, float z = 1, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakePlane(float width = 1, float height = 1, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakeSphere(float radius, uint32_t segments, uint32_t rings, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakeHemisphere(float radius, uint32_t segments, uint32_t rings, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakeTriangle(const Math::Vector3f& p1, const Math::Vector3f& p2, const Math::Vector3f& p3, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakeCylinder(float radius, float height, uint32_t segments, const Math::Vector4f& color = Math::Vector4f(1));
static Geometry* MakePyramid(float baseLength = 1, float height = 1, const Math::Vector4f& color = Math::Vector4f(1));
};
}