- 通过程序来构建模型
- 加载外部创建的模型
程序构建模型——球体
通过算法建立球体模型
- 模型精度
- 高
- 宽
- 顶点分组为三角形
- 根据纹理图像性质选择纹理坐标
- 生成法向量
索引定义三角形
一些模型使用索引定义三角形
顶点数组:一个数组计算每个切片的顶点位置,
索引数组:为三角形关系数组,通过整形引用索引到顶点数组的元素上。
这是为了节省内存
因为顶点坐标数据,需要按照正确的顺序,并且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);
}