OpenGL读取与构造3D模型

  • 通过程序来构建模型
  • 加载外部创建的模型

程序构建模型——球体

通过算法建立球体模型

  • 模型精度
  • 顶点分组为三角形
  • 根据纹理图像性质选择纹理坐标
  • 生成法向量

索引定义三角形

一些模型使用索引定义三角形
顶点数组:一个数组计算每个切片的顶点位置,
索引数组:为三角形关系数组,通过整形引用索引到顶点数组的元素上。
这是为了节省内存

因为顶点坐标数据,需要按照正确的顺序,并且1个四边面需要2个三角面,1个三角面需要3个顶点。所以需要通过利用索引来构造真正的顶点值数组。

在真正构造顶点数据的时候,通过遍历索引遍历顶点来构造真正需要的顶点数据。

	std::vector<int> ind = mySphere.getIndices();
	std::vector<glm::vec3> vert = mySphere.getVertices();
	std::vector<glm::vec2> tex = mySphere.getTexCoords();
	std::vector<glm::vec3> norm = mySphere.getNormals();

	std::vector<float> pvalues;
	std::vector<float> tvalues;
	std::vector<float> nvalues;
	
	int numIndices = mySphere.getNumIndices();
	for (int i = 0; i < numIndices; i++) {
    
    
		pvalues.push_back((vert[ind[i]]).x);
		pvalues.push_back((vert[ind[i]]).y);
		pvalues.push_back((vert[ind[i]]).z);
		tvalues.push_back((tex[ind[i]]).s);
		tvalues.push_back((tex[ind[i]]).t);
		nvalues.push_back((norm[ind[i]]).x);
		nvalues.push_back((norm[ind[i]]).y);
		nvalues.push_back((norm[ind[i]]).z);
	}
	glGenVertexArrays(1, vao);
	glBindVertexArray(vao[0]);
	glGenBuffers(numVBOs, vbo);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, pvalues.size()*4, &pvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, tvalues.size()*4, &tvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glBufferData(GL_ARRAY_BUFFER, nvalues.size()*4, &nvalues[0], GL_STATIC_DRAW);

OpenGL索引——环面

如何计算环面

Paul Baker的算法

如何使用OpenGL索引

设置索引的缓冲区

std::vector<int> ind = myTorus.getIndices(); // 环面索引的读取函数返回整型向量类型的索引

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]); // vbo[3]是新增的 VBO

glBufferData(GL_ELEMENT_ARRAY_BUFFER, ind.size()*4, &ind[0], GL_STATIC_DRAW);

专门的索引绘制API

numTorusIndices = myTorus.getNumIndices();

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);

glDrawElements(GL_TRIANGLES, numTorusIndices, GL_UNSIGNED_INT, 0);

加载外部构建的模型

OBJ

OBJ 文件以文本行的形式指定顶点几何数据、纹理坐标、法向量和其他信息。它有一些限制,例如无法指定模型动画。
OBJ 文件中的行以字符标签开头,以标明该行的数据类型。

补充说明

习题

球体行星

使用sphere生成顶点坐标,纹理坐标,法线坐标,并绑定到缓冲区

Sphere mySphere = Sphere(48);
void setupVertices(void) {
    
    
	std::vector<int> ind = mySphere.getIndices();
	std::vector<glm::vec3> vert = mySphere.getVertices();
	std::vector<glm::vec2> tex = mySphere.getTexCoords();
	std::vector<glm::vec3> norm = mySphere.getNormals();

	std::vector<float> pvalues;
	std::vector<float> tvalues;
	std::vector<float> nvalues;

	int numIndices = mySphere.getNumIndices();
	for (int i = 0; i < numIndices; i++) {
    
    
		pvalues.push_back((vert[ind[i]]).x);
		pvalues.push_back((vert[ind[i]]).y);
		pvalues.push_back((vert[ind[i]]).z);
		tvalues.push_back((tex[ind[i]]).s);
		tvalues.push_back((tex[ind[i]]).t);
		nvalues.push_back((norm[ind[i]]).x);
		nvalues.push_back((norm[ind[i]]).y);
		nvalues.push_back((norm[ind[i]]).z);
	}

	glGenVertexArrays(1, vao);
	glBindVertexArray(vao[0]);
	glGenBuffers(numVBOs, vbo);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, pvalues.size() * 4, &pvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, tvalues.size() * 4, &tvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glBufferData(GL_ARRAY_BUFFER, nvalues.size() * 4, &nvalues[0], GL_STATIC_DRAW);
}

改6.1,导入飞机绕太阳运行

注意:不可把obj模型文件加入到项目中,会导致链接错误!!!

ImportedModel myModel("shuttle.obj");
void setupPlaneVertices(void) {
    
    
	std::vector<glm::vec3> vert = myModel.getVertices();
	std::vector<glm::vec2> tex = myModel.getTextureCoords();
	std::vector<glm::vec3> norm = myModel.getNormals();

	std::vector<float> pvalues;
	std::vector<float> tvalues;
	std::vector<float> nvalues;

	for (int i = 0; i < myModel.getNumVertices(); i++) {
    
    
		pvalues.push_back((vert[i]).x);
		pvalues.push_back((vert[i]).y);
		pvalues.push_back((vert[i]).z);
		tvalues.push_back((tex[i]).s);
		tvalues.push_back((tex[i]).t);
		nvalues.push_back((norm[i]).x);
		nvalues.push_back((norm[i]).y);
		nvalues.push_back((norm[i]).z);
	}

	glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
	glBufferData(GL_ARRAY_BUFFER, pvalues.size() * 4, &pvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
	glBufferData(GL_ARRAY_BUFFER, tvalues.size() * 4, &tvalues[0], GL_STATIC_DRAW);

	glBindBuffer(GL_ARRAY_BUFFER, vbo[5]);
	glBufferData(GL_ARRAY_BUFFER, nvalues.size() * 4, &nvalues[0], GL_STATIC_DRAW);
}

了解使用blender,如何建模、使用UV展开工具生成纹理坐标和纹理图像、导出obj、加载使用。

blenderUV展开的方法0基础学习超详细教程超方便

猜你喜欢

转载自blog.csdn.net/2301_78647179/article/details/145601775
今日推荐