charcoal/OpenGLEngine/MeshFactory.h

380 lines
11 KiB
C
Raw Normal View History

#pragma once
#include <vector>
#include "DrawMode.h"
#include "Exception.h"
#include "Mesh.h"
2018-09-12 21:03:46 +00:00
namespace charcoal
{
2018-09-12 21:03:46 +00:00
template <typename VertexType, typename IndexType>
class MeshFactory
{
public:
typedef Mesh<VertexType, IndexType> MeshType;
2018-09-12 21:03:46 +00:00
private:
MeshFactory() {} // Prevent instanciation of this static class
2018-09-12 21:03:46 +00:00
public:
typedef unsigned int SizeType;
2018-09-12 21:03:46 +00:00
virtual ~MeshFactory()
{
2018-09-12 21:03:46 +00:00
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;
}
}
2018-09-12 21:03:46 +00:00
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c, const VertexType& d)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
static MeshType* gen(const DrawMode& draw_mode, const std::vector<VertexType>& vertices, const std::vector<IndexType>& indices)
{
2018-09-12 21:03:46 +00:00
MeshType* mesh;
switch (draw_mode)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
// 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
)
{
2018-09-12 21:03:46 +00:00
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));
}
}
2018-09-12 21:03:46 +00:00
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;
}
2018-09-12 21:03:46 +00:00
private:
static std::vector<MeshType*> m_meshes;
};
2018-09-12 21:03:46 +00:00
template <typename VertexType, typename IndexType>
std::vector<Mesh<VertexType, IndexType>*> MeshFactory<VertexType, IndexType>::m_meshes = std::vector<Mesh<VertexType, IndexType>*>();
}