OpenGL--------读取PLY格式的bunny兔子文件以便画出兔子

       写在前面的话:PLY文件格式是Stanford大学开发的一套三维mesh模型数据格式,开发目标是建立一套针对多边形模型的,结构简单但是能够满足大多数图形应用需要的模型格式,而且它允许以ASCII码格式或二进制形式存储文件(来源于https://blog.csdn.net/shine_cherise/article/details/79435774 )。PLY格式可以用notepad++等文档查看器直接打开,里面大部分是数字,还有部分英文表明属性等。当前我没有找到可以直接使用的读取ply文件的插件,不同的ply文件在存储上也存在着不一样,所以可以按照直接读取文件的方式获得其中的信息。整个过程分成两部分:理清PLY文件的内容,获取所需的部分。如果对于文件的读取比较熟悉可以只看第一部分,第二部分可以选看。

       文件来源:https://www.cc.gatech.edu/projects/large_models/bunny.html 这是斯坦福兔子模型的下载地址。感谢大佬https://blog.csdn.net/u013467442/article/details/46673331  的提供,上面的链接里面还有一些常用模型,需要的可以自行下载。如果下载出现问题,可以邮箱联系。

       第一部分:PLY文件里面都有什么?

       典型的PLY文件结构: 
        头部 
        顶点列表 
        面片列表 
      (其他元素列表)        

       基础的了解可以参考这一位的看法:https://blog.csdn.net/shine_cherise/article/details/79435774 

       下面将对bunny.ply文件进行具体的解析:

           第一行表示这个文件是ply文件,第二行表示是ascii码,是标准属性,第3-4暂时不用管,第5行是顶点信息,表明有35947个顶点vertex,6-10行表明顶点是由x,y,z,confidence和intensity构成,是float32型,第11行表明面片face有69451个,第12行也是一些信息,具体的可以看前面的博客。第13行表明头部结束。第14行开始是顶点的属性,每行是一个顶点,每个顶点有5个元素。在后面有关于面片的,第一个是面片由几个顶点构成,后面是顶点的编号。

     第二部分:使用程序进行读取。整个绘制的时候,我们只需要考虑三个内容:顶点信息,面信息,纹理信息。我们使用三个数组进行存储:float vertices[35947 * 3];//顶点的存储  float face[69451*3];  //面的存储  float vertice[35947 * 5]; // 添加纹理数组到顶点存储信息里面。这里面的数字是博主按照ply文件里面的的数字给出的大小,可以考虑设置一个比较大的数组空间就不用管那么多了。如果你不需要进行纹理贴图的话(兔子的三角形太多,贴出来好丑),可以不用考虑vertice数组和AddTexture()函数。

    绘制阶段采用的是OPENGL,当时用的入门教程是这个:https://learnopengl-cn.github.io/   中文版,跟着学就能画出东西来。

     文件读取的C++代码:


#include <iostream>
#include <fstream>
#include <string>

using namespace std;

float vertices[35947 * 3];//顶点的存储
float face[69451*3];  //面的存储
float vertice[35947 * 5]; // 添加纹理数组到顶点存储信息里面
int vertexNum;  // 顶点数目
int faceNum;//面的数目 

int loadFile(string p) {
    fstream fopen;
    if (!p.empty())
        fopen.open(p, ios::in);
    else return 0;
    if (!fopen.is_open()) {
        return 0;
        //读取文件失败
        cout << "Read File Fail!" << endl;
    }
    //开始读取文件
    string filein;
    while (!fopen.eof()) {
        fopen >> filein;
        if (filein == "ply" || filein == "PLY") {
            //文件开头
        }else if (filein == "comment") {
            getline(fopen, filein, '\n');
        }else if (filein == "forment") {
            getline(fopen, filein, '\n');
        }else if (filein == "element") {
            fopen >> filein;
            if (filein == "vertex") {
                fopen >> vertexNum;
                cout << "顶点个数为" <<vertexNum << endl;
                getline(fopen, filein, '\n');
            }
            else if (filein == "face") {
                fopen >> faceNum;
                cout << "面个数为" << faceNum << endl;
                getline(fopen, filein, '\n');
            }
            else {
                cout << "ignore user-defined element!" << endl;
                getline(fopen, filein, '\n');
            }
        }
        else if (filein == "property") {
            getline(fopen, filein, '\n');
        }
        else if (filein == "end_header") {
            getline(fopen, filein, '\n');
            int j = -1,n = -1;
            int nums;//面数据的第一个数据的值,判断是否为3
            float confidence;
            float intensity;
            //添加点信息到数组
            for (int i = 0; i < vertexNum; i++) {
                fopen >> vertices[++j];
                fopen >> vertices[++j];
                fopen >> vertices[++j];
    
                fopen >> confidence;
                fopen >> intensity;
            }
            cout << "confidence: " << confidence << endl;
            cout << "intensity: " <<  intensity << endl;
            //添加面信息到数组
            for (int k = 0; k < faceNum; k++) {
                fopen >> nums;
                if (nums == 3) {
                    fopen >> face[++n];
                    fopen >> face[++n];
                    fopen >> face[++n];
                }
            }
        }

    }

    return 0;
}
//纹理的数组
int AddTexture() {
    int j = 0;
    int index1,index2;
    for (int i = 0; i < 35947 * 3;) {
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = 1.0;
        vertice[j++] = 1.0;
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = 0.0;
        vertice[j++] = 0.0;
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = vertices[i++];
        vertice[j++] = 0.5;
        vertice[j++] = 0.5;
        index1 = i;
        index2 = j;
    }
    //cout <<"i的值为" << index1 <<",j的值为" << index2 << endl;
    vertice[index2++] = vertices[index1++];
    vertice[index2++] = vertices[index1++];
    vertice[index2++] = vertices[index1++];
    vertice[index2++] = 1.0;
    vertice[index2++] = 1.0;

    return 0;
}
 
int main()
{
    loadFile("D:/vsProject/ReadFile/bunny.ply");//存放ply的地址

    AddTexture();//此步可以省略,兔子模型有点小,加入纹理不好看。
    int nums = sizeof(vertices) / sizeof(vertices[0]);
    cout << nums << endl;
    for (int i = 0; i < nums; i++) {
        cout << vertices[i] << ",";
    }
    return 0;
}


博主这里只验证了vertices顶点的正确性,基本上看一下打印出来的最开始10个左右的数据和最后10个左右的数据就可以判断是否正确,当然,你要是想保证更高的正确率,自己慢慢比对吧。毕竟所有的数据都打印出来了。得到了数据,如何进行绘制就是OpenGL的事情了,在这里就不多说了。博主是个小白,欢迎各位大佬指正。

PS:读取文件距离写博客有半年多了,如果有问题记得联系我!

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值