charcoal/OpenGLEngine/MeshFactory.h
elipzer 31e3d15ab1 Builtins
Starting the setup for builtin types for rendering. This will allow
the engine to be easier to use for beginners while still offering
great modularity and functionality. The builtin namespace is
intended to simplify mesh loading and rendering. It should
eventually offer pre-made shaders to simplify the rendering of the
builtin types. Possibly in the future, it could have partially
setup scenes/application to simplify scene/application building
2018-09-12 18:46:36 -04:00

380 lines
11 KiB
C++

#pragma once
#include <vector>
#include "DrawMode.h"
#include "Exception.h"
#include "Mesh.h"
namespace charcoal
{
template <typename VertexType, typename IndexType>
class MeshFactory
{
public:
typedef Mesh<VertexType, IndexType> MeshType;
private:
MeshFactory() {} // Prevent instanciation of this static class
public:
typedef unsigned int SizeType;
virtual ~MeshFactory()
{
for (SizeType i = 0; i < m_meshes.size(); ++i)
{
delete[] m_meshes[i]->vertices;
m_meshes[i]->vertices = nullptr;
delete[] m_meshes[i]->indices;
m_meshes[i]->indices = nullptr;
delete m_meshes[i];
m_meshes[i] = nullptr;
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
mesh = create_mesh(1, 1);
mesh->vertices[0] = a;
mesh->indices[0] = 0;
return mesh;
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
mesh = create_mesh(2, 2);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
return mesh;
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(3, 3);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
return mesh;
case DrawMode::DRAW_LINES:
mesh = create_mesh(3, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 0;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c, const VertexType& d)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
mesh = create_mesh(4, 4);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 3;
return mesh;
case DrawMode::DRAW_LINES: // Implementation similar to LINE_LOOP
mesh = create_mesh(4, 8);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(4, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 2;
mesh->indices[4] = 1;
mesh->indices[5] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const std::vector<VertexType>& vertices, const std::vector<IndexType>& indices)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
int n = vertices.size();
mesh = create_mesh(n, n);
for (SizeType i = 0; i < vertices.size(); ++i)
{
mesh->vertices[i] = vertices[i];
mesh->indices[i] = i;
}
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
// Generates a "cube" (8-vert shape) with 8 vertices. This function should probably not be used
// if the vertices are expected to have normals.
static MeshType* gen_cube(
const DrawMode& draw_mode,
const VertexType& top_left_front,
const VertexType& bottom_left_front,
const VertexType& top_right_front,
const VertexType& bottom_right_front,
const VertexType& top_left_back,
const VertexType& bottom_left_back,
const VertexType& top_right_back,
const VertexType& bottom_right_back
)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
mesh = create_mesh(8, 8);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 3;
mesh->indices[3] = 3;
mesh->indices[4] = 4;
mesh->indices[5] = 5;
mesh->indices[6] = 6;
mesh->indices[7] = 7;
return mesh;
case DrawMode::DRAW_LINES:
mesh = create_mesh(8, 24);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Front
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
// Back
mesh->indices[8] = 4;
mesh->indices[9] = 5;
mesh->indices[10] = 5;
mesh->indices[11] = 6;
mesh->indices[12] = 6;
mesh->indices[13] = 7;
mesh->indices[14] = 7;
mesh->indices[15] = 4;
// Connecting
mesh->indices[16] = 0;
mesh->indices[17] = 4;
mesh->indices[18] = 1;
mesh->indices[19] = 5;
mesh->indices[20] = 2;
mesh->indices[21] = 6;
mesh->indices[22] = 3;
mesh->indices[23] = 7;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(8, 36);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Counter Clockwise
// Front
mesh->indices[0] = 1;
mesh->indices[1] = 3;
mesh->indices[2] = 0;
mesh->indices[3] = 0;
mesh->indices[4] = 3;
mesh->indices[5] = 2;
// Right
mesh->indices[6] = 3;
mesh->indices[7] = 7;
mesh->indices[8] = 2;
mesh->indices[9] = 2;
mesh->indices[10] = 7;
mesh->indices[11] = 6;
// Back
mesh->indices[12] = 7;
mesh->indices[13] = 5;
mesh->indices[14] = 6;
mesh->indices[15] = 6;
mesh->indices[16] = 5;
mesh->indices[17] = 4;
// Left
mesh->indices[18] = 5;
mesh->indices[19] = 1;
mesh->indices[20] = 4;
mesh->indices[21] = 4;
mesh->indices[22] = 1;
mesh->indices[23] = 0;
// Top
mesh->indices[24] = 0;
mesh->indices[25] = 2;
mesh->indices[26] = 4;
mesh->indices[27] = 4;
mesh->indices[28] = 2;
mesh->indices[29] = 6;
// Bottom
mesh->indices[30] = 5;
mesh->indices[31] = 7;
mesh->indices[32] = 1;
mesh->indices[33] = 1;
mesh->indices[34] = 7;
mesh->indices[35] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP: // Could probably implement this one in some way in the future
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen_cube for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* create_mesh(unsigned int vertex_count, unsigned int index_count)
{
MeshType* mesh = new MeshType();
mesh->vertices = new VertexType[vertex_count];
mesh->vertex_count = vertex_count;
mesh->indices = new IndexType[index_count];
mesh->index_count = index_count;
m_meshes.push_back(mesh);
return mesh;
}
private:
static std::vector<MeshType*> m_meshes;
};
template <typename VertexType, typename IndexType>
std::vector<Mesh<VertexType, IndexType>*> MeshFactory<VertexType, IndexType>::m_meshes = std::vector<Mesh<VertexType, IndexType>*>();
}