日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/8 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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:讀取文件距離寫博客有半年多了,如果有問題記得聯系我!

總結

以上是生活随笔為你收集整理的OpenGL--------读取PLY格式的bunny兔子文件以便画出兔子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。