[C++] [OpenGL] 生成模型

代码

#ifndef __SIMPLEGL_MODEL_MODELBUILDER_HPP__
#define __SIMPLEGL_MODEL_MODELBUILDER_HPP__
#include <glm/glm.hpp>
#include <vector>
#include <iostream>
#include "Model.hpp"

namespace SimpleGL
{
	class ModelBuilder
	{
		public:
			static std::vector<float> calcNormals(std::vector<float> vertices)
			{
				std::vector<float> normals;
				for (int i = 0; i < vertices.size() / 9; i++)
				{
					glm::vec3 A = glm::vec3(vertices.at(i * 9 + 0), vertices.at(i * 9 + 1), vertices.at(i * 9 + 2));
					glm::vec3 B = glm::vec3(vertices.at(i * 9 + 3), vertices.at(i * 9 + 4), vertices.at(i * 9 + 5));
					glm::vec3 C = glm::vec3(vertices.at(i * 9 + 6), vertices.at(i * 9 + 7), vertices.at(i * 9 + 8));

					glm::vec3 AB = glm::normalize(B - A);
					glm::vec3 BC = glm::normalize(C - B);

					glm::vec3 N = glm::normalize(glm::cross(AB, BC));

					for (int j = 0; j < 3; j++)
					{
						normals.push_back(N.x);
						normals.push_back(N.y);
						normals.push_back(N.z);
					}
				}
				return normals;
			}

			static std::vector<glm::vec3> calcNormals(std::vector<glm::vec3> vertices)
			{
				std::vector<glm::vec3> normals;
				for (int i = 0; i < vertices.size() / 3; i++)
				{
					glm::vec3 A = vertices.at(i + 0);
					glm::vec3 B = vertices.at(i + 1);
					glm::vec3 C = vertices.at(i + 2);

					glm::vec3 AB = glm::normalize(B - A);
					glm::vec3 BC = glm::normalize(C - B);

					glm::vec3 N = glm::normalize(glm::cross(AB, BC));

					for (int j = 0; j < 3; j++)
					{
						normals.push_back(N);

					}
				}
				return normals;
			}

			static glm::vec3 calcNormal(glm::vec3 A, glm::vec3 B, glm::vec3 C)
			{
				glm::vec3 AB = glm::normalize(B - A);
				glm::vec3 BC = glm::normalize(C - B);

				glm::vec3 N = glm::normalize(glm::cross(AB, BC));

				return N;
			}

			static std::vector<float> stretchTexCoords(std::vector<float> texCoords, glm::vec3 value)
			{
				std::vector<float> result;
				for (int i = 0; i < texCoords.size() / 3; i++)
				{
					result.push_back(texCoords.at(i * 3 + 0) * value.x);
					result.push_back(texCoords.at(i * 3 + 1) * value.y);
					result.push_back(texCoords.at(i * 3 + 2) * value.z);
				}
				return result;
			}

			static std::vector<float> toFloatArray(std::vector<glm::vec3> vertices)
			{
				std::vector<float> v;
				for (int i = 0; i < vertices.size(); i++)
				{
					glm::vec3 vertex = vertices.at(i);
					v.push_back(vertex.x);
					v.push_back(vertex.y);
					v.push_back(vertex.z);
				}
				return v;
			}

			static std::vector<glm::vec3> toVec3Array(std::vector<float> vertices)
			{
				std::vector<glm::vec3> v;
				for (int i = 0; i < vertices.size() / 3; i++)
				{
					float x = vertices.at(i + 0);
					float y = vertices.at(i + 1);
					float z = vertices.at(i + 2);
					v.push_back(glm::vec3(x, y, z));

				}
				return v;
			}

			static void push_back_triangle(std::vector<glm::vec3>& array, glm::vec3 A, glm::vec3 B, glm::vec3 C)
			{
				array.push_back(A);
				array.push_back(B);
				array.push_back(C);
			}

			static Model toModel(std::vector<glm::vec3> vertices, std::vector<glm::vec3> normals, std::vector<glm::vec3> texCoords)
			{
				std::vector<float> v = ModelBuilder::toFloatArray(vertices);
				std::vector<float> n = ModelBuilder::toFloatArray(normals);
				std::vector<float> t = ModelBuilder::toFloatArray(texCoords);
				return Model(v, n, t);
			}

			static void push_back_line(std::vector<float>& array, glm::vec3 A, glm::vec3 B)
			{
				array.push_back(A.x);
				array.push_back(A.y);
				array.push_back(A.z);

				array.push_back(B.x);
				array.push_back(B.y);
				array.push_back(B.z);
			}

			static void push_back_line(std::vector<glm::vec3>& array, glm::vec3 A, glm::vec3 B)
			{
				array.push_back(A);
				array.push_back(B);
			}

		public:
			//Vertices and texture coordinates are OK, but there are some problems in normals. The reason is unclear.
			//rotate around Y axis.
			static Model rotate(std::vector<glm::vec2> source_data, float span = 180.0f, bool texturePerFace = true)
			{
				const float zero = 0.0f;
				const glm::vec3 t00 = glm::vec3(0.0f, 0.0f, 0.0f);
				const glm::vec3 t01 = glm::vec3(0.0f, 1.0f, 0.0f);
				const glm::vec3 t10 = glm::vec3(1.0f, 0.0f, 0.0f);
				const glm::vec3 t11 = glm::vec3(1.0f, 1.0f, 0.0f);
				float s_unit = 1.0f / 360.f * span;
				float t_unit = 1.0f / float(source_data.size());

				std::vector<glm::vec3> vertices;
				std::vector<glm::vec3> texCoords;
				for (float angle = 0.0f; angle <= 360.0f; angle += span)
				{
					float angle0 = glm::radians(angle + 0.0f);
					float angle1 = glm::radians(angle + span);

					for (int i = 0; i < source_data.size() - 1; i++)
					{
						glm::vec2 V0 = source_data.at(i + 0);
						glm::vec2 V1 = source_data.at(i + 1);

						glm::vec3 A = glm::vec3(glm::cos(angle1) * V0.x, V0.y, glm::sin(angle1) * V0.x);
						glm::vec3 B = glm::vec3(glm::cos(angle1) * V1.x, V1.y, glm::sin(angle1) * V1.x);
						glm::vec3 C = glm::vec3(glm::cos(angle0) * V1.x, V1.y, glm::sin(angle0) * V1.x);
						glm::vec3 D = glm::vec3(glm::cos(angle0) * V0.x, V0.y, glm::sin(angle0) * V0.x);

						push_back_triangle(vertices, A, B, C);
						push_back_triangle(vertices, A, C, D);

						if (texturePerFace)
						{
							push_back_triangle(texCoords, t00, t01, t11);
							push_back_triangle(texCoords, t00, t11, t10);
						}
						else
						{
							float s0 = 1.0f - angle / span * s_unit;
							float s1 = 1.0f - (angle + span) / span * s_unit;
							float t0 = float(i) * t_unit;
							float t1 = float(i + 1) * t_unit;

							texCoords.push_back(glm::vec3(s1, t0, zero));
							texCoords.push_back(glm::vec3(s1, t1, zero));
							texCoords.push_back(glm::vec3(s0, t1, zero));

							texCoords.push_back(glm::vec3(s1, t0, zero));
							texCoords.push_back(glm::vec3(s0, t1, zero));
							texCoords.push_back(glm::vec3(s0, t0, zero));
						}
					}
				}
				std::vector<glm::vec3> normals = calcNormals(vertices);

				return toModel(vertices, normals, texCoords);
			}

			static std::vector<float> generateWireframe(std::vector<float> vertices)
			{
				int size = vertices.size();

				std::vector<glm::vec3> lines;
				for (int i = 0; i < size / 9; i++)
				{
					glm::vec3 A = glm::vec3(vertices.at(i * 9 + 0), vertices.at(i * 9 + 1), vertices.at(i * 9 + 2));
					glm::vec3 B = glm::vec3(vertices.at(i * 9 + 3), vertices.at(i * 9 + 4), vertices.at(i * 9 + 5));
					glm::vec3 C = glm::vec3(vertices.at(i * 9 + 6), vertices.at(i * 9 + 7), vertices.at(i * 9 + 8));

					push_back_line(vertices, A, B);
					push_back_line(vertices, B, C);
					push_back_line(vertices, C, A);
				}

				return toFloatArray(lines);
			}
	};
}

#endif

运行结果

在这里插入图片描述
额…没开光照,因为法线有问题。
生成法线的函数应该没问题,面的顺序也没问题(这张图开了面剔除,没被剔除掉说明顺序没问题),但就是有些法线生成得不对,还是有规律的不对,给我整懵了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值