diff --git a/openVulkanoCpp/Scene/GeometryFactory.cpp b/openVulkanoCpp/Scene/GeometryFactory.cpp new file mode 100644 index 0000000..be01625 --- /dev/null +++ b/openVulkanoCpp/Scene/GeometryFactory.cpp @@ -0,0 +1,308 @@ +/* + * 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 +#include + +namespace OpenVulkano::Scene +{ + Geometry* GeometryFactory::MakeCube(float x, float y, float z, const Math::Vector4f& color) + { + Geometry *result = new Geometry(); + result->Init(24, 36); + result->SetIndices(new uint32_t[result->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->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; + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Scene/GeometryFactory.hpp b/openVulkanoCpp/Scene/GeometryFactory.hpp new file mode 100644 index 0000000..99d642f --- /dev/null +++ b/openVulkanoCpp/Scene/GeometryFactory.hpp @@ -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)); + }; +}