Added mesh generator
This commit is contained in:
@@ -3,6 +3,7 @@ set(HEADERS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
|
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/fbo.h
|
${CMAKE_CURRENT_SOURCE_DIR}/fbo.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/shader.h
|
${CMAKE_CURRENT_SOURCE_DIR}/shader.h
|
||||||
@@ -15,6 +16,7 @@ set(SOURCE
|
|||||||
${SOURCE}
|
${SOURCE}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/fbo.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/fbo.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/shader.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/shader.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp
|
||||||
|
|||||||
@@ -0,0 +1,606 @@
|
|||||||
|
#include "mesh_generator.h"
|
||||||
|
#include "glm/gtx/rotate_vector.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
static void add_vertex(mesh &m, float x, float y, float z) {
|
||||||
|
vertex v{};
|
||||||
|
v.position.x = x;
|
||||||
|
v.position.y = y;
|
||||||
|
v.position.z = z;
|
||||||
|
m.vertices.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_facet(mesh &m, size_t a, size_t b, size_t c,
|
||||||
|
float u1, float v1,
|
||||||
|
float u2, float v2,
|
||||||
|
float u3, float v3,
|
||||||
|
bool edge1_visible,
|
||||||
|
bool edge2_visible,
|
||||||
|
bool edge3_visible,
|
||||||
|
float nx = 0, float ny = 0, float nz = 0) {
|
||||||
|
facet f{};
|
||||||
|
f.a = a;
|
||||||
|
f.b = b;
|
||||||
|
f.c = c;
|
||||||
|
f.text_coords[0] = glm::vec2(u1, v1);
|
||||||
|
f.text_coords[1] = glm::vec2(u2, v2);
|
||||||
|
f.text_coords[2] = glm::vec2(u3, v3);
|
||||||
|
f.normal.x = nx;
|
||||||
|
f.normal.y = ny;
|
||||||
|
f.normal.z = nz;
|
||||||
|
m.facets.push_back(f);
|
||||||
|
|
||||||
|
if (edge1_visible) m.edges.push_back({a, b});
|
||||||
|
if (edge2_visible) m.edges.push_back({b, c});
|
||||||
|
if (edge3_visible) m.edges.push_back({c, a});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::cube() {
|
||||||
|
mesh *result = new mesh;
|
||||||
|
|
||||||
|
add_vertex(*result, -0.5, -0.5, -0.5);
|
||||||
|
add_vertex(*result, 0.5, -0.5, -0.5);
|
||||||
|
add_vertex(*result, 0.5, 0.5, -0.5);
|
||||||
|
add_vertex(*result, -0.5, 0.5, -0.5);
|
||||||
|
|
||||||
|
add_vertex(*result, -0.5, -0.5, 0.5);
|
||||||
|
add_vertex(*result, 0.5, -0.5, 0.5);
|
||||||
|
add_vertex(*result, 0.5, 0.5, 0.5);
|
||||||
|
add_vertex(*result, -0.5, 0.5, 0.5);
|
||||||
|
|
||||||
|
// back
|
||||||
|
add_facet(*result, 0, 2, 1, 1, 0, 0, 1, 0, 0, false, true, true, 0, 0, -1);
|
||||||
|
add_facet(*result, 2, 0, 3, 0, 1, 1, 0, 1, 1, false, true, true, 0, 0, -1);
|
||||||
|
|
||||||
|
// front
|
||||||
|
add_facet(*result, 5, 7, 4, 1, 0, 0, 1, 0, 0, false, true, true, 0, 0, 1);
|
||||||
|
add_facet(*result, 7, 5, 6, 0, 1, 1, 0, 1, 1, false, true, true, 0, 0, 1);
|
||||||
|
|
||||||
|
// right side
|
||||||
|
add_facet(*result, 1, 6, 5, 1, 0, 0, 1, 0, 0, false, true, true, 1, 0, 0);
|
||||||
|
add_facet(*result, 6, 1, 2, 0, 1, 1, 0, 1, 1, false, true, true, 1, 0, 0);
|
||||||
|
|
||||||
|
// left side
|
||||||
|
add_facet(*result, 4, 3, 0, 1, 0, 0, 1, 0, 0, false, true, true, -1, 0, 0);
|
||||||
|
add_facet(*result, 3, 4, 7, 0, 1, 1, 0, 1, 1, false, true, true, -1, 0, 0);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
add_facet(*result, 4, 1, 5, 1, 0, 0, 1, 0, 0, false, true, true, 0, -1, 0);
|
||||||
|
add_facet(*result, 1, 4, 0, 0, 1, 1, 0, 1, 1, false, true, true, 0, -1, 0);
|
||||||
|
|
||||||
|
// top
|
||||||
|
add_facet(*result, 3, 6, 2, 1, 0, 0, 1, 0, 0, false, true, true, 0, 1, 0);
|
||||||
|
add_facet(*result, 6, 3, 7, 0, 1, 1, 0, 1, 1, false, true, true, 0, 1, 0);
|
||||||
|
|
||||||
|
calculate_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::sphere(int lon_points, int lat_points) {
|
||||||
|
mesh *result = new mesh;
|
||||||
|
|
||||||
|
vertex v{};
|
||||||
|
facet f{};
|
||||||
|
edge edge{};
|
||||||
|
|
||||||
|
double x, y, z;
|
||||||
|
|
||||||
|
double du = 1.0 / static_cast<double>(lon_points);
|
||||||
|
double dv = 1.0 / static_cast<double>(lat_points + 1);
|
||||||
|
|
||||||
|
for (int j = 0; j < lat_points; j++) {
|
||||||
|
|
||||||
|
y = 1.0 - (j + 1) * 2.0 / static_cast<double>(lat_points + 1);
|
||||||
|
double current_circle_radius = sin(M_PI * (j + 1) / static_cast<double>(lat_points + 1));
|
||||||
|
|
||||||
|
for (int i = 0; i < lon_points; i++) {
|
||||||
|
|
||||||
|
x = current_circle_radius * cos((i * 2.0 * M_PI) / static_cast<double>(lon_points));
|
||||||
|
z = current_circle_radius * sin((i * 2.0 * M_PI) / static_cast<double>(lon_points));
|
||||||
|
|
||||||
|
v.position = glm::normalize(glm::vec3(x, y, z));
|
||||||
|
result->vertices.push_back(v);
|
||||||
|
|
||||||
|
if (j > 0) {
|
||||||
|
int current_vertex_index = j * lon_points + i;
|
||||||
|
int new_vertex_index = j * lon_points + ((i + 1) % lon_points);
|
||||||
|
int top_vertex_index = (j - 1) * lon_points + i;
|
||||||
|
int top_next_vertex_index = (j - 1) * lon_points + ((i + 1) % lon_points);
|
||||||
|
|
||||||
|
glm::vec2 current_uv = glm::vec2(i * du, (j + 2) * dv);
|
||||||
|
glm::vec2 next_uv = glm::vec2((i + 1) * du, (j + 2) * dv);
|
||||||
|
glm::vec2 top_uv = glm::vec2(i * du, (j + 1) * dv);
|
||||||
|
glm::vec2 top_next_uv = glm::vec2((i + 1) * du, (j + 1) * dv);
|
||||||
|
|
||||||
|
f.a = current_vertex_index;
|
||||||
|
f.b = top_vertex_index;
|
||||||
|
f.c = new_vertex_index;
|
||||||
|
|
||||||
|
f.text_coords[0] = current_uv;
|
||||||
|
f.text_coords[1] = top_uv;
|
||||||
|
f.text_coords[2] = next_uv;
|
||||||
|
|
||||||
|
result->facets.push_back(f);
|
||||||
|
|
||||||
|
f.a = new_vertex_index;
|
||||||
|
f.b = top_vertex_index;
|
||||||
|
f.c = top_next_vertex_index;
|
||||||
|
|
||||||
|
f.text_coords[0] = next_uv;
|
||||||
|
f.text_coords[1] = top_uv;
|
||||||
|
f.text_coords[2] = top_next_uv;
|
||||||
|
|
||||||
|
result->facets.push_back(f);
|
||||||
|
|
||||||
|
edge.from = top_vertex_index;
|
||||||
|
edge.to = top_next_vertex_index;
|
||||||
|
result->edges.push_back(edge);
|
||||||
|
|
||||||
|
edge.from = top_vertex_index;
|
||||||
|
edge.to = current_vertex_index;
|
||||||
|
result->edges.push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// top capping
|
||||||
|
v.position = glm::vec3(0, 1.0, 0);
|
||||||
|
result->vertices.push_back(v);
|
||||||
|
|
||||||
|
int top_vertex_index = lon_points * lat_points;
|
||||||
|
for (int i = 0; i < lon_points; i++) {
|
||||||
|
|
||||||
|
int current_vertex_index = i;
|
||||||
|
int new_vertex_index = (current_vertex_index + 1) % lon_points;
|
||||||
|
|
||||||
|
glm::vec2 current_uv = glm::vec2(i * du, dv);
|
||||||
|
glm::vec2 next_uv = glm::vec2((i + 1) * du, dv);
|
||||||
|
glm::vec2 top_uv = glm::vec2((i + 0.5) * du, 0);
|
||||||
|
|
||||||
|
f.text_coords[0] = current_uv;
|
||||||
|
f.text_coords[1] = next_uv;
|
||||||
|
f.text_coords[2] = top_uv;
|
||||||
|
|
||||||
|
f.a = current_vertex_index;
|
||||||
|
f.c = new_vertex_index;
|
||||||
|
f.b = top_vertex_index;
|
||||||
|
result->facets.push_back(f);
|
||||||
|
|
||||||
|
edge.from = top_vertex_index;
|
||||||
|
edge.to = current_vertex_index;
|
||||||
|
result->edges.push_back(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom capping
|
||||||
|
v.position = glm::vec3(0, -1.0, 0);
|
||||||
|
result->vertices.push_back(v);
|
||||||
|
|
||||||
|
int bottom_vertex_index = top_vertex_index + 1;
|
||||||
|
for (int i = 0; i < lon_points; i++) {
|
||||||
|
|
||||||
|
int current_vertex_index = i + (lat_points - 1) * lon_points;
|
||||||
|
int next_vertex_index = (i + 1) % lon_points + (lat_points - 1) * lon_points;
|
||||||
|
|
||||||
|
glm::vec2 current_uv = glm::vec2(i * du, 1.0 - dv);
|
||||||
|
glm::vec2 next_uv = glm::vec2((i + 1) * du, 1.0 - dv);
|
||||||
|
glm::vec2 bottom_uv = glm::vec2((i + 0.5) * du, 1.0);
|
||||||
|
|
||||||
|
f.text_coords[0] = current_uv;
|
||||||
|
f.text_coords[1] = bottom_uv;
|
||||||
|
f.text_coords[2] = next_uv;
|
||||||
|
|
||||||
|
f.a = current_vertex_index;
|
||||||
|
f.c = bottom_vertex_index;
|
||||||
|
f.b = next_vertex_index;
|
||||||
|
result->facets.push_back(f);
|
||||||
|
|
||||||
|
edge.from = current_vertex_index;
|
||||||
|
edge.to = next_vertex_index;
|
||||||
|
result->edges.push_back(edge);
|
||||||
|
|
||||||
|
edge.from = current_vertex_index;
|
||||||
|
edge.to = bottom_vertex_index;
|
||||||
|
result->edges.push_back(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::grid(int x_segments, int y_segments) {
|
||||||
|
mesh *result = new mesh;
|
||||||
|
for (int y = 0; y < (y_segments + 1); y++) {
|
||||||
|
float y_pos = (static_cast<float>(y) / static_cast<float>(y_segments)) - 0.5f;
|
||||||
|
for (int x = 0; x < (x_segments + 1); x++) {
|
||||||
|
float x_pos = (static_cast<float>(x) / static_cast<float>(x_segments)) - 0.5f;
|
||||||
|
add_vertex(*result, x_pos, y_pos, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < y_segments; y++) {
|
||||||
|
for (int x = 0; x < x_segments; x++) {
|
||||||
|
int current = x + (y * (y_segments + 1));
|
||||||
|
int next = current + 1;
|
||||||
|
int bottom = next + x_segments;
|
||||||
|
int bottom_next = bottom + 1;
|
||||||
|
add_facet(*result, current, bottom, next,
|
||||||
|
result->vertices[current].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[current].position.y,
|
||||||
|
result->vertices[bottom].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[bottom].position.y,
|
||||||
|
result->vertices[next].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[next].position.y,
|
||||||
|
true, false, true);
|
||||||
|
|
||||||
|
add_facet(*result, next, bottom, bottom_next,
|
||||||
|
result->vertices[next].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[next].position.y,
|
||||||
|
result->vertices[bottom].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[bottom].position.y,
|
||||||
|
result->vertices[bottom_next].position.x + 0.5f,
|
||||||
|
0.5f - result->vertices[bottom_next].position.y,
|
||||||
|
false, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::cylinder(int x_segments, int y_segments, bool cap_top, bool cap_bottom) {
|
||||||
|
mesh *result = new mesh;
|
||||||
|
for (int y = 0; y <= y_segments; y++) {
|
||||||
|
float yPos = 1.0f - (static_cast<float>(y) / static_cast<float>(y_segments)) - 0.5f;
|
||||||
|
for (int x = 0; x <= x_segments; x++) {
|
||||||
|
float xPos = 0.5f * sinf((static_cast<float>(x) / static_cast<float>(x_segments * 2.0 * M_PI)));
|
||||||
|
float zPos = 0.5f * cosf((static_cast<float>(x) / static_cast<float>(x_segments * 2.0 * M_PI)));
|
||||||
|
add_vertex(*result, xPos, yPos, zPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float du = 1.0f / static_cast<float>(x_segments);
|
||||||
|
float dv = 1.0f / static_cast<float>(y_segments + 2); // +2 because of capping
|
||||||
|
|
||||||
|
for (int y = 0; y < y_segments; y++) {
|
||||||
|
for (int x = 0; x < x_segments; x++) {
|
||||||
|
int current = x + (y * (y_segments + 1));
|
||||||
|
int next = current + 1;
|
||||||
|
int bottom = next + x_segments;
|
||||||
|
int bottomNext = bottom + 1;
|
||||||
|
add_facet(*result, current, bottom, next,
|
||||||
|
static_cast<float>(x) * du,
|
||||||
|
static_cast<float>(y + 1) * dv,
|
||||||
|
static_cast<float>(x) * du,
|
||||||
|
static_cast<float>(y + 2) * dv,
|
||||||
|
static_cast<float>(x + 1) * du,
|
||||||
|
static_cast<float>(y + 1) * dv,
|
||||||
|
true, false, true);
|
||||||
|
|
||||||
|
add_facet(*result, next, bottom, bottomNext,
|
||||||
|
static_cast<float>(x + 1) * du,
|
||||||
|
static_cast<float>(y + 1) * dv,
|
||||||
|
static_cast<float>(x) * du,
|
||||||
|
static_cast<float>(y + 2) * dv,
|
||||||
|
static_cast<float>(x + 1) * du,
|
||||||
|
static_cast<float>(y + 2) * dv,
|
||||||
|
false, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cap_top) {
|
||||||
|
int topCapIndex = (int) result->vertices.size();
|
||||||
|
add_vertex(*result, 0, 0.5f, 0);
|
||||||
|
|
||||||
|
for (int x = 0; x < x_segments; x++) {
|
||||||
|
add_facet(*result, x, x + 1, topCapIndex,
|
||||||
|
static_cast<float>(x) * du,
|
||||||
|
1.0f - dv,
|
||||||
|
static_cast<float>(x + 1) * du,
|
||||||
|
1.0f - dv,
|
||||||
|
(static_cast<float>(x) + 0.5f) * du,
|
||||||
|
1.0f,
|
||||||
|
false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cap_bottom) {
|
||||||
|
int bottomCapIndex = (int) result->vertices.size();
|
||||||
|
add_vertex(*result, 0, -0.5f, 0);
|
||||||
|
|
||||||
|
int offsetOfLastRing = (x_segments + 1) * y_segments;
|
||||||
|
|
||||||
|
for (int x = 0; x < x_segments; x++) {
|
||||||
|
add_facet(*result, x + 1 + offsetOfLastRing, x + offsetOfLastRing, bottomCapIndex,
|
||||||
|
static_cast<float>(x + 1) * du,
|
||||||
|
dv,
|
||||||
|
static_cast<float>(x) * du,
|
||||||
|
dv,
|
||||||
|
static_cast<float>(x + 0.5f) * du,
|
||||||
|
0,
|
||||||
|
false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::cog(float wheel_inner_diameter,
|
||||||
|
float wheel_outer_diameter,
|
||||||
|
int wheel_contour_segments,
|
||||||
|
int number_of_teeth,
|
||||||
|
float tooth_height,
|
||||||
|
float tooth_width_base,
|
||||||
|
float tooth_width_top,
|
||||||
|
float cog_depth) {
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh = mesh_generator::revolve({
|
||||||
|
{-wheel_inner_diameter / 2.0f, cog_depth / 2.0f},
|
||||||
|
{-wheel_outer_diameter / 2.0f, cog_depth / 2.0f},
|
||||||
|
{-wheel_outer_diameter / 2.0f, -cog_depth /
|
||||||
|
2.0f},
|
||||||
|
{-wheel_inner_diameter / 2.0f, -cog_depth /
|
||||||
|
2.0f},
|
||||||
|
{-wheel_inner_diameter / 2.0f, cog_depth / 2.0f}
|
||||||
|
}, wheel_contour_segments);
|
||||||
|
return mesh;
|
||||||
|
|
||||||
|
// return MeshGenerator::extrude(MeshGenerator::sphere(20, 20), {100, 101, 200, 201, 400, 401}, 0.05, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::revolve(const std::vector<glm::vec2> &contour, int rotation_steps) {
|
||||||
|
mesh *result = new mesh;
|
||||||
|
|
||||||
|
// create vertices by revolving the contours
|
||||||
|
for (int i = 0; i < rotation_steps; i++) {
|
||||||
|
for (auto v: contour) {
|
||||||
|
add_vertex(*result,
|
||||||
|
(float) (v.x * cos(i * 2.0 * M_PI / rotation_steps)),
|
||||||
|
v.y,
|
||||||
|
(float) (v.x * sin(i * 2.0 * M_PI / rotation_steps)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create facets by linking between the revolved pieces
|
||||||
|
int number_of_contour_vertices = (int) contour.size();
|
||||||
|
for (int i = 0; i < rotation_steps; i++) {
|
||||||
|
int current_rotation_index = i;
|
||||||
|
int next_rotation_index = (i + 1) % rotation_steps;
|
||||||
|
|
||||||
|
for (int j = 0; j < (number_of_contour_vertices - 1); j++) {
|
||||||
|
int a = current_rotation_index * number_of_contour_vertices + j;
|
||||||
|
int b = current_rotation_index * number_of_contour_vertices + j + 1;
|
||||||
|
int c = next_rotation_index * number_of_contour_vertices + j + 1;
|
||||||
|
int d = next_rotation_index * number_of_contour_vertices + j;
|
||||||
|
|
||||||
|
add_facet(*result, a, b, c, 0, 0, 0, 0, 0, 0, false, true, false);
|
||||||
|
add_facet(*result, c, d, a, 0, 0, 0, 0, 0, 0, false, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_normals(*result);
|
||||||
|
flip_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<mesh> mesh_generator::extrude(const std::shared_ptr<mesh> &m,
|
||||||
|
std::vector<int> facets_to_extrude,
|
||||||
|
float extrusion_height,
|
||||||
|
int times) {
|
||||||
|
|
||||||
|
mesh *result = new mesh;
|
||||||
|
result->copy(*m);
|
||||||
|
|
||||||
|
glm::vec3 normal_offset = glm::vec3(0);
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
std::vector<int> new_facets_to_extrude;
|
||||||
|
for (int facetIndex: facets_to_extrude) {
|
||||||
|
new_facets_to_extrude.push_back(
|
||||||
|
extrude_face(result, result->facets[facetIndex], extrusion_height, normal_offset));
|
||||||
|
}
|
||||||
|
facets_to_extrude = new_facets_to_extrude;
|
||||||
|
normal_offset += glm::vec3(1, 0, 0);
|
||||||
|
calculate_normals(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flip_normals(*result);
|
||||||
|
return std::shared_ptr<mesh>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the index of the extruded face cap
|
||||||
|
int mesh_generator::extrude_face(mesh *m, facet facet, float amount, glm::vec3 normal_offset) {
|
||||||
|
|
||||||
|
size_t new_a = m->vertices.size();
|
||||||
|
size_t new_b = m->vertices.size() + 1;
|
||||||
|
size_t new_c = m->vertices.size() + 2;
|
||||||
|
|
||||||
|
glm::mat4 normal_rotation_matrix = glm::rotate(0.2f, glm::normalize(glm::vec3(2, 1, 1)));
|
||||||
|
|
||||||
|
for (unsigned long v: facet.vertices) {
|
||||||
|
glm::vec3 new_vertex = m->vertices[v].position + amount * facet.normal;
|
||||||
|
new_vertex = glm::vec3(glm::vec4(new_vertex, 1.0f) * normal_rotation_matrix);
|
||||||
|
add_vertex(*m, new_vertex.x, new_vertex.y, new_vertex.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AB extrusion plan
|
||||||
|
add_facet(*m,
|
||||||
|
facet.a, facet.b, new_b,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
add_facet(*m,
|
||||||
|
new_b, new_a, facet.a,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
// BC extrusion plan
|
||||||
|
add_facet(*m,
|
||||||
|
facet.b, facet.c, new_c,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
add_facet(*m,
|
||||||
|
new_c, new_b, facet.b,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
// CA extrusion plan
|
||||||
|
add_facet(*m,
|
||||||
|
facet.c, facet.a, new_a,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
add_facet(*m,
|
||||||
|
new_a, new_c, facet.c,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
// facet replica on top
|
||||||
|
add_facet(*m,
|
||||||
|
new_a, new_b, new_c,
|
||||||
|
facet.text_coords[0].x,
|
||||||
|
facet.text_coords[0].y,
|
||||||
|
facet.text_coords[1].x,
|
||||||
|
facet.text_coords[1].y,
|
||||||
|
facet.text_coords[2].x,
|
||||||
|
facet.text_coords[2].y,
|
||||||
|
true, true, true);
|
||||||
|
|
||||||
|
return (int) (m->facets.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_transform(std::shared_ptr<mesh> mesh,
|
||||||
|
texture_generator &texgen,
|
||||||
|
uint8_t layer,
|
||||||
|
uint8_t channel,
|
||||||
|
float effect_intensity) {
|
||||||
|
|
||||||
|
std::vector<vertex> original_vertices(mesh->vertices);
|
||||||
|
|
||||||
|
uint8_t *data = texgen.get(layer);
|
||||||
|
|
||||||
|
for (auto &f: mesh->facets) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
uint16_t u = static_cast<uint16_t>(f.text_coords[i].x * static_cast<float>(texgen.width)) % texgen.width;
|
||||||
|
uint16_t v = static_cast<uint16_t>(f.text_coords[i].y * static_cast<float>(texgen.height)) % texgen.height;
|
||||||
|
|
||||||
|
uint8_t map_value = data[(u + v * texgen.width) * 4 + channel];
|
||||||
|
float normalized_value_in_map = static_cast<float>(map_value) / 255.0f;
|
||||||
|
|
||||||
|
mesh->vertices[f.vertices[i]].position = original_vertices[f.vertices[i]].position +
|
||||||
|
(mesh->vertices[f.vertices[i]].normal * normalized_value_in_map *
|
||||||
|
effect_intensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t index_in_map(uint16_t from, uint16_t to) {
|
||||||
|
return from < to ?
|
||||||
|
from + (static_cast<unsigned int>(to) << 16) :
|
||||||
|
to + (static_cast<unsigned int>(from) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subdivide(const std::shared_ptr<mesh> &m) {
|
||||||
|
vertex v{};
|
||||||
|
|
||||||
|
// we need to keep the old facets because we're modifying the new ones as we go
|
||||||
|
std::vector<facet> old_facets = m->facets;
|
||||||
|
|
||||||
|
// key is encoded as from/to edge, 16 bits each, from in lower 16 bits, to in upper 16 bits
|
||||||
|
// "from" is always smaller than "to"
|
||||||
|
std::map<uint32_t, size_t> subdivided_vertices;
|
||||||
|
|
||||||
|
int facet_index = 0;
|
||||||
|
for (auto &f: old_facets) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
unsigned int from = f.vertices[j];
|
||||||
|
unsigned int to = f.vertices[(j + 1) % 3];
|
||||||
|
|
||||||
|
// make sure all subdivided vertices are unique and not duplicated
|
||||||
|
if (subdivided_vertices[index_in_map(from, to)] == 0) {
|
||||||
|
subdivided_vertices[index_in_map(from, to)] = m->vertices.size();
|
||||||
|
v.position = (m->vertices[from].position + m->vertices[to].position) / 2.0f;
|
||||||
|
m->vertices.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new facets
|
||||||
|
add_facet(*m,
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[0], f.vertices[1])],
|
||||||
|
f.vertices[1],
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[1], f.vertices[2])],
|
||||||
|
(f.text_coords[0].x + f.text_coords[1].x) / 2.0f, (f.text_coords[0].y + f.text_coords[1].y) / 2.0f,
|
||||||
|
f.text_coords[1].x, f.text_coords[1].y,
|
||||||
|
(f.text_coords[1].x + f.text_coords[2].x) / 2.0f, (f.text_coords[1].y + f.text_coords[2].y) / 2.0f,
|
||||||
|
false, false, false);
|
||||||
|
|
||||||
|
add_facet(*m,
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[1], f.vertices[2])],
|
||||||
|
f.vertices[2],
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[2], f.vertices[0])],
|
||||||
|
(f.text_coords[1].x + f.text_coords[2].x) / 2.0f, (f.text_coords[1].y + f.text_coords[2].y) / 2.0f,
|
||||||
|
f.text_coords[2].x, f.text_coords[2].y,
|
||||||
|
(f.text_coords[2].x + f.text_coords[0].x) / 2.0f, (f.text_coords[2].y + f.text_coords[0].y) / 2.0f,
|
||||||
|
false, false, false);
|
||||||
|
|
||||||
|
add_facet(*m,
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[2], f.vertices[0])],
|
||||||
|
f.vertices[0],
|
||||||
|
subdivided_vertices[index_in_map(f.vertices[0], f.vertices[1])],
|
||||||
|
(f.text_coords[2].x + f.text_coords[0].x) / 2.0f, (f.text_coords[2].y + f.text_coords[0].y) / 2.0f,
|
||||||
|
f.text_coords[0].x, f.text_coords[0].y,
|
||||||
|
(f.text_coords[0].x + f.text_coords[1].x) / 2.0f, (f.text_coords[0].y + f.text_coords[1].y) / 2.0f,
|
||||||
|
false, false, false);
|
||||||
|
|
||||||
|
// modify current face to make it center of the subdivision
|
||||||
|
m->facets[facet_index].vertices[0] = subdivided_vertices[index_in_map(f.vertices[0], f.vertices[1])];
|
||||||
|
m->facets[facet_index].vertices[1] = subdivided_vertices[index_in_map(f.vertices[1], f.vertices[2])];
|
||||||
|
m->facets[facet_index].vertices[2] = subdivided_vertices[index_in_map(f.vertices[2], f.vertices[0])];
|
||||||
|
|
||||||
|
m->facets[facet_index].text_coords[0] =
|
||||||
|
(old_facets[facet_index].text_coords[0] + old_facets[facet_index].text_coords[1]) / 2.0f;
|
||||||
|
m->facets[facet_index].text_coords[1] =
|
||||||
|
(old_facets[facet_index].text_coords[1] + old_facets[facet_index].text_coords[2]) / 2.0f;
|
||||||
|
m->facets[facet_index].text_coords[2] =
|
||||||
|
(old_facets[facet_index].text_coords[2] + old_facets[facet_index].text_coords[0]) / 2.0f;
|
||||||
|
|
||||||
|
facet_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_normals(*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "texture_generator.h"
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
struct mesh_generator {
|
||||||
|
|
||||||
|
static std::shared_ptr<mesh> cube();
|
||||||
|
static std::shared_ptr<mesh> sphere(int lon_points, int lat_points);
|
||||||
|
static std::shared_ptr<mesh> grid(int x_segments, int y_segments);
|
||||||
|
static std::shared_ptr<mesh> cylinder(int x_segments, int y_segments, bool cap_top, bool cap_botton);
|
||||||
|
static std::shared_ptr<mesh> revolve(const std::vector<glm::vec2> &contour, int rotation_steps);
|
||||||
|
static std::shared_ptr<mesh> extrude(const std::shared_ptr<mesh> &mesh,
|
||||||
|
std::vector<int> facets_to_extrude,
|
||||||
|
float extrusion_height,
|
||||||
|
int times);
|
||||||
|
static std::shared_ptr<mesh> cog(float wheel_inner_diameter,
|
||||||
|
float wheel_outer_diameter,
|
||||||
|
int wheel_contour_segments,
|
||||||
|
int number_of_teeth,
|
||||||
|
float tooth_height,
|
||||||
|
float tooth_width_base,
|
||||||
|
float tooth_width_top,
|
||||||
|
float cog_depth);
|
||||||
|
static int extrude_face(mesh *m, facet facet, float amount, glm::vec3 normal_offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
void map_transform(std::shared_ptr<mesh> mesh,
|
||||||
|
texture_generator &texgen,
|
||||||
|
uint8_t layer,
|
||||||
|
uint8_t channel,
|
||||||
|
float effect_intensity);
|
||||||
|
void subdivide(const std::shared_ptr<mesh> &mesh);
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
Reference in New Issue
Block a user