相关链接

OpenGL环境下PLY三维模型的读入与显示的源码-CSDN下载

codeblocks配置OpenGL环境-CSDN博客

问题描述

仿照PLY格式点云读取代码,实现PLY格式三角形面片模型的读取与显示。

问题分析

分析ply文件结构
ply
format ascii 1.0 {ascii/二进制,格式版本数}
comment VCGLIB generated {注释关键词说明}
element vertex 34835 {定义“vertex”(顶点)元素,在文件中有34835个}
property float x {顶点包含浮点坐标“x”,下同}
property float y
property float z
property float nx
property float ny
property float nz
element face 69666 {在文件里有69666个“face”(面片)}
property list uchar int vertex_indices
end_header {划定头部结尾}
0.006242 0.039472 0.033507 -1.34547 -4.89656 -1.80904 {顶点列表的开始}
0.007691 0.039029 0.032395 -2.35354 -5.66907 -0.381422
0.008423 0.038501 0.033018 -3.33184 -4.82115 -1.7236

3 0 1 2   {面片列表开始}
3 3 4 5
3 6 7 8
3 8 9 10

编写程序

1)获取到ply文件中顶点的个数和面片的个数

fscanf(fp, "element vertex %d\n", &g_nVerticesNumber);

j = 0;

while (strcmp(type,"element")!=0)

{

fgets(strBuff, 256, fp);

i = 0;

while(strBuff[i]!='\0'&&strBuff[i]!=' '&&strBuff[i]!='\n')

{

type[i] = strBuff[i];

i++;

}

if (bStartPropertyCount&&strcmp(type,"property")==0)

j++;

else

bStartPropertyCount = false;

type[i] = '\0';

}

sscanf(strBuff, "element face %d\n", &g_nFacesNumber);

2)接下来逐行读取点坐标和法向量,这里的J为6

//Read in the triangles

for (i=0; i<g_nVerticesNumber; i++)

{

if (j==3)

fscanf(fp, "%f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z);

else if(j==6)

fscanf(fp, "%f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z, &g_norm[i].x, &g_norm[i].y, &g_norm[i].z);

else if (j==7)

fscanf(fp, "%f %f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z, &g_color[i].x, &g_color[i].y, &g_color[i].z, &alpha);

else if (j==10)

fscanf(fp, "%f %f %f %f %f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z,

&g_norm[i].x, &g_norm[i].y, &g_norm[i].z,

&g_color[i].x, &g_color[i].y, &g_color[i].z, &alpha);

else

{

printf("Warning: the viewer cann't read the colors of models\n");

exit(1);

}

GetMinMax(vMin, vMax, g_vet[i]);

Normalize(g_norm[i]);

}

3)将法向量标准化

void Normalize(VERTEX3D &v)

{

double length = sqrt(v.x*v.x+v.y*v.y+v.z*v.z);

if(length!=0)

{

v.x = v.x/length;

v.y = v.y/length;

v.z = v.z/length;

}

}

4)通过三角形面片绘制斯坦福兔子三维模型

void DrawVertices()
{
    int i;
    glPointSize(2.0);
    glBegin(GL_TRIANGLES);
        for(i=0;i<g_nFacesNumber;i++)
        {
            glBegin(GL_TRIANGLES);

glNormal3f(g_norm[triPatch[i].A].x,g_norm[triPatch[i].A].y,g_norm[triPatch[i].A].z);
            glNormal3f(g_norm[triPatch[i].B].x,g_norm[triPatch[i].B].y,g_norm[triPatch[i].B].z);
            glNormal3f(g_norm[triPatch[i].C].x,g_norm[triPatch[i].C].y,g_norm[triPatch[i].C].z);

glColor3f(g_color[triPatch[i].A].x,g_color[triPatch[i].A].y,g_color[triPatch[i].A].z);
            glColor3f(g_color[triPatch[i].B].x,g_color[triPatch[i].B].y,g_color[triPatch[i].B].z);
            glColor3f(g_color[triPatch[i].C].x,g_color[triPatch[i].C].y,g_color[triPatch[i].C].z);
            glVertex3f(g_vet[triPatch[i].A].x,g_vet[triPatch[i].A].y,g_vet[triPatch[i].A].z);
            glVertex3f(g_vet[triPatch[i].B].x,g_vet[triPatch[i].B].y,g_vet[triPatch[i].B].z);
            glVertex3f(g_vet[triPatch[i].C].x,g_vet[triPatch[i].C].y,g_vet[triPatch[i].C].z);
            glEnd();
        }
}

运行截图

参考代码

#include <GL/glut.h>
#include <cstdio>
#include <cmath>
//声明结构体用于处理三维点云数据
typedef struct VERTEX_3D
{float x;float y;float z;
} VERTEX3D;//三角
typedef struct _TRIANGLE
{int A;//Index of vertex 0int B;//Index of vertex 1int C;//Index of vertex 2
} TRIANGLE;VERTEX3D *g_vet;
VERTEX3D *g_norm;
VERTEX3D *g_color;TRIANGLE *triPatch;float g_rotx = 20.0f, g_roty = 30.0f, g_rotz = 0.0f;
float g_modelPos[3] = {0, 0, -15.0f};
float g_scale = 10.0f;const float g_lightPos[] = { 1.0f, 1.0f, 1.0f, 0.0f };char g_strModelName[512] = "plant.ply"; /*Problem happens when left the [512] being empty []*/
int g_nVerticesNumber;//顶点数
int g_nFacesNumber;//面数//归一化
void Normalize(VERTEX3D &v)
{double length = sqrt(v.x*v.x+v.y*v.y+v.z*v.z);if(length!=0){v.x = v.x/length;v.y = v.y/length;v.z = v.z/length;}
}//获取最小最大值
void GetMinMax(VERTEX3D &vMin, VERTEX3D &vMax, VERTEX3D v)
{if(v.x < vMin.x ) vMin.x = v.x;if(v.y < vMin.y ) vMin.y = v.y;if(v.z < vMin.z ) vMin.z = v.z;if(v.x > vMax.x ) vMax.x = v.x;if(v.y > vMax.y ) vMax.y = v.y;if(v.z > vMax.z ) vMax.z = v.z;
}//格式化几何图形
void FormatGeometry(VERTEX3D &v, VERTEX3D vMin, VERTEX3D vMax, float scale)
{v.x = scale*(v.x - 0.5*(vMin.x + vMax.x));v.y = scale*(v.y - 0.5*(vMin.y + vMax.y));v.z = scale*(v.z - 0.5*(vMin.z + vMax.z));
}//加载网格层
void LoadMeshPLY(char *FileName)
{int i, j;VERTEX3D vMin, vMax;char strBuff[512];char type[512] = "";bool bStartPropertyCount = true;//开始属性计数float alpha;vMin.x = vMin.y = vMin.z = 99999.0;vMax.x = vMax.y = vMax.z = -99999.0;FILE* fp=fopen(FileName,"r");if (fp==NULL)//文件不存在{printf("ERROR: unable to open model [%s]!\n",FileName);exit(0);}//读文件fgets(strBuff, 256, fp);fgets(strBuff, 256, fp);fgets(strBuff, 256, fp);fscanf(fp, "element vertex %d\n", &g_nVerticesNumber);j = 0;while (strcmp(type,"element")!=0){fgets(strBuff, 256, fp);i = 0;while(strBuff[i]!='\0'&&strBuff[i]!=' '&&strBuff[i]!='\n'){type[i] = strBuff[i];i++;}if (bStartPropertyCount&&strcmp(type,"property")==0)j++;elsebStartPropertyCount = false;type[i] = '\0';}sscanf(strBuff, "element face %d\n", &g_nFacesNumber);printf("Number of Triangles: %d\n", g_nFacesNumber);fgets(strBuff, 256, fp);fgets(strBuff, 256, fp);//fgets(strBuff, 256, fp);多读的一点//Allocate the triangle arrayg_vet = new VERTEX3D[g_nVerticesNumber];g_norm = new VERTEX3D[g_nVerticesNumber];g_color = new VERTEX3D[g_nVerticesNumber];triPatch = new TRIANGLE[g_nFacesNumber];//Read in the trianglesfor (i=0; i<g_nVerticesNumber; i++){if (j==3)fscanf(fp, "%f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z);else if(j==6)fscanf(fp, "%f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z, &g_norm[i].x, &g_norm[i].y, &g_norm[i].z);else if (j==7)fscanf(fp, "%f %f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z, &g_color[i].x, &g_color[i].y, &g_color[i].z, &alpha);else if (j==10)fscanf(fp, "%f %f %f %f %f %f %f %f %f %f", &g_vet[i].x, &g_vet[i].y, &g_vet[i].z,&g_norm[i].x, &g_norm[i].y, &g_norm[i].z,&g_color[i].x, &g_color[i].y, &g_color[i].z, &alpha);else{printf("Warning: the viewer cann't read the colors of models\n");exit(1);}GetMinMax(vMin, vMax, g_vet[i]);Normalize(g_norm[i]);}int tmp;for (i=0; i<g_nFacesNumber; i++){fscanf(fp, "%d %d %d %d",&tmp , &triPatch[i].A, &triPatch[i].B, &triPatch[i].C);}if((vMax.x - vMin.x) > (vMax.y-vMin.y)){if ((vMax.x - vMin.x) > (vMax.z - vMin.z))g_scale = g_scale/(vMax.x - vMin.x);elseg_scale = g_scale/(vMax.z - vMin.z);}else{if ((vMax.y - vMin.y) > (vMax.z - vMin.z))g_scale = g_scale/(vMax.y - vMin.y);elseg_scale = g_scale/(vMax.z - vMin.z);}for (i=0; i<g_nVerticesNumber; i++)FormatGeometry(g_vet[i], vMin, vMax, g_scale);fclose(fp);
}//绘图顶点
void DrawVertices()
{int i;//glEnable(GL_LIGHTING);glPointSize(2.0);glBegin(GL_TRIANGLES);for(i=0;i<g_nFacesNumber;i++){glBegin(GL_TRIANGLES);
//glBegin();创建元素的类型,比如:点,线等。
//GL_POINTS:把每个顶点作为一个点进行处理,顶点n定义了点n,绘制N个点。
//GL_LINES:   把每个顶点作为一个独立的线段,顶点2n-1和2n之间定义了n条线段,绘制N/2条线段
//GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,绘制n-1条线段。
//GL_LINE_LOOP: 绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,绘制n条线段。
//GL_TRIANGLES: 把每个顶点作为一个独立的三角形,顶点3n-2,3n-1和3n定义了第n个三角形,绘制了N/3个三角形。
//GL_TRIANGLE_STPIP:绘制一组相连的三角形,对于奇数n,顶点n,n+1,和n+2定义了第n个三角形;对于偶数n,顶点n+1,n和n+2定义了第n个三角形,绘制N-2个三角 形。
//GL_QUADS: 绘制由四个顶点组成的一组单独的四边形。顶点4n-3,4n-2,4n-1和4n定义了第n个四边形。绘制了N/4个四边形。
//GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1,2n,2n+2和2n+1定义了第n个四边形,绘制了N/2-1个   四边形。
//GL_POLYGON:      绘制了一个凸多边形。顶点1到n定义了这个多边形。glNormal3f(g_norm[triPatch[i].A].x,g_norm[triPatch[i].A].y,g_norm[triPatch[i].A].z);glNormal3f(g_norm[triPatch[i].B].x,g_norm[triPatch[i].B].y,g_norm[triPatch[i].B].z);glNormal3f(g_norm[triPatch[i].C].x,g_norm[triPatch[i].C].y,g_norm[triPatch[i].C].z);glColor3f(g_color[triPatch[i].A].x,g_color[triPatch[i].A].y,g_color[triPatch[i].A].z);glColor3f(g_color[triPatch[i].B].x,g_color[triPatch[i].B].y,g_color[triPatch[i].B].z);glColor3f(g_color[triPatch[i].C].x,g_color[triPatch[i].C].y,g_color[triPatch[i].C].z);glVertex3f(g_vet[triPatch[i].A].x,g_vet[triPatch[i].A].y,g_vet[triPatch[i].A].z);glVertex3f(g_vet[triPatch[i].B].x,g_vet[triPatch[i].B].y,g_vet[triPatch[i].B].z);glVertex3f(g_vet[triPatch[i].C].x,g_vet[triPatch[i].C].y,g_vet[triPatch[i].C].z);glEnd();}//glEnd();
}static void resize(int width, int height)
{const float ar = (float) width / (float) height;glViewport(0, 0, width, height);//0,0指定了窗口的左下角位置。//width,height表示视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。glMatrixMode(GL_PROJECTION);//将当前矩阵指定为投影矩阵glLoadIdentity();//把矩阵设为单位矩阵gluPerspective(45, ar, 1.0, 100.0);//指定要观察的视景体在世界坐标系中的具体大小glMatrixMode(GL_MODELVIEW);//指定当前要操作的矩阵, GL_MODELVIEW模型视图glLoadIdentity() ;
}static void display(void)
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity() ;glTranslatef(g_modelPos[0], g_modelPos[1], g_modelPos[2]);//定义一个平移矩阵,该矩阵与当前矩阵相乘,使后续的图形相对与当前所在的屏幕位置。进行平移变换。glRotatef(g_rotx, 1.0, 0.0, 0.0);glRotatef(g_roty, 0.0, 1.0, 0.0);glRotatef(g_rotz, 0.0, 0.0, 1.0);DrawVertices();glutSwapBuffers();
}static void key(unsigned char key, int x, int y)
{switch (key){case 27 ://ASCLL表'ESC'exit(0);break;case 'w':g_rotx += 5;break;case 's':g_rotx -= 5;break;case 'a':g_roty += 5;break;case 'd':g_roty -= 5;break;case 'q':g_rotz += 5;break;case 'e':g_rotz -= 5;break;case 'z':g_modelPos[2] += 1;break;case 'x':g_modelPos[2] -= 1;break;}glutPostRedisplay();//重绘图像,否则图像只有响应鼠标或键盘消息时才会更新图像。
}static void idle(void)
{glutPostRedisplay();
}int main(int argc, char *argv[])
{glutInit(&argc, argv);//初始化GLUTglutInitWindowSize(640,480);//定义窗口大小glutInitWindowPosition(10,10);//定义窗口位置glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);printf("Tips: use 'w', 's', 'a', 'd', 'z', 'x', 'q', 'e' keys to control the model\n");if(argc<2){printf("Input the file name (without postfix e.g. .ply) of points:");scanf("%s", g_strModelName);strcat(g_strModelName, ".ply");}else{printf("%s\n", argv[1]);strcpy(g_strModelName, argv[1]);}glutCreateWindow("PLY Model Viewer");//创建窗口("窗口标题")glutReshapeFunc(resize);//自适应屏幕窗口大小的改变glutDisplayFunc(display);glutKeyboardFunc(key);glutIdleFunc(idle);glClearColor(0.2, 0.55,1.0,1);//设置好清除颜色glDisable(GL_CULL_FACE);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glEnable(GL_LIGHT0);glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);glShadeModel(GL_SMOOTH);printf("Loading \"%s\"...\n", g_strModelName);LoadMeshPLY(g_strModelName);glutMainLoop();//使程序进入事件处理循环。该函数必须是main主函数的最后一条语句。return EXIT_SUCCESS;
}

OpenGL环境下PLY三维模型的读入与显示相关推荐

  1. idea环境下 servlet配置导致jsp页面显示源码问题

    idea环境下 servlet配置导致jsp页面显示源码问题 今天在做jsp实验(虽然是被废弃的技术但是还是课程要求)过程中遇到了一点令人感到困惑的问题:当使用idea自动生成的web.xml文件配置 ...

  2. OpenGL环境下的射线选择

    用过OpenGL的人,应该都知道,OpenGL是自带拾取功能的,但用过的人应该也知道,这功能确实不好用. OpenGL自带的选择功能主要有两种,名字堆栈(拾取)和读深度值判断选择,但这两种方法在实际项 ...

  3. opengl将bmp读成像素_在 opengl 环境下将 texture 保存为 bmp 图片

    首先说一下做这个功能的原因,是在应用里,有一个渲染线程,负责渲染出图,将最终的画面以texture形式传递给另一个线程,后者会再进行一些处理,然后渲染到屏幕上.那么在最后显示出来画面偶尔有花屏撕裂的现 ...

  4. [数据分析]-ubuntu下解决anaconda环境下matplotlib绘制图表时中文显示乱码问题

    1.问题描述 系统:ubuntu20.04 环境:anaconda下的独立环境 编译器:vscode 语言:python 数据分析时运行代码,想要显示中文信息出现如下乱码 2.问题成因 本问题的成因是 ...

  5. 在linux系统下java实现pdf导出汉字无法显示_Linux环境下iText生成pdf中文不显示问题...

    使用fc-list命令查看系统中已经安装的字体. 若 centos 系统没有 fc-list 命令,需要先使用如下命令安装相关的软件包: yum install -y fontconfig mkfon ...

  6. Mac环境下iterm使用Git命令中文显示乱码

    如果所示: 解决办法: 1.设置iterm的终端编码方式为utf-8 iterm - > perferences - > Terminal ->Character Encoding ...

  7. linux环境下常用的网络命令ping、telnet、traceroute、tcpdump

    文章目录 前言 网络 网络命令 ping telnet nc traceroute tcpdump 总结 前言 因特网(Internet)的前身是美国国防部高级研究计划局(ARPA)用于军事目的的通信 ...

  8. 解决非Unicode编码的软件多语言版本在日语、韩语环境下的乱码问题

    在第一次为公司的客户端软件定制日语版本的时候,由于软件开发是非Unicode版本的,发现当加载日语后,无论是在中文操作系统还是在日语操作系统下,软件界面上的大部分日语显示的都是乱码.在上网查看了相关的 ...

  9. 单片机小精灵t2_搭建S5P4418 ARM环境下 GPU OPENGL ES开发环境(适用 NANOPI2,3,M2,M3,T2,T3)...

    本帖最后由 3guoyangyang7 于 2017-8-20 22:38 编辑 先说一下背景,这几天做一个摄像头处理的qt项目,摄像头的像素是1280*720的,25fps,用qt的painter重 ...

最新文章

  1. 镜像打包工具clonezilla
  2. 喧喧发布 2.5.2 版本,主要修复已知问题
  3. mysql大规模读写性能_十招搞定 MySQL 大规模数据库的性能和伸缩性优化
  4. 【CV】使用计算机视觉算法检测钢板中的焊接缺陷
  5. C语言表示一元四次函数,论c语言程序设计 第四次讨论.ppt
  6. 技术干货 | 轻松两步完成向 mPaaS 小程序传递启动参数
  7. Leaf:美团分布式ID生成服务开源 1
  8. 数字图像处理:图像平均/加法_OPT小讲堂 ∣ SciSmart图像增强之二值化
  9. ES6知识点汇总(全)
  10. sftp方式从windows上传文件到Linux服务器
  11. 【前端】相信你会用到的一篇笔记---CSS篇(1)
  12. XP 多国语言包 .
  13. String类基本介绍及常用方法
  14. javascript查看详情与收起详情
  15. python图案堆积_Python数据可视化,我是如何做出泡泡堆积关联图
  16. mybatis的xmly文件与必依赖
  17. 单字节和双字节的转换
  18. 银河linux看版本,下载Linux客户端 - 银河云盘 - 银河证券
  19. 软件测试顶岗实习实习总结
  20. Response对象-响应字符数据

热门文章

  1. 计算机组成与设计chapter3,Chapter 1 计算机概要与技术
  2. 网络类型 ---- PAP认证配置 ---- CHAP认证----隧道技术
  3. 基于STM32的12864液晶理解
  4. 奥西打印机服务器重装系统教程,奥西工程机TCS400驱动程序安装方法
  5. Tensorflow of python36 in win10
  6. Linux命令全家桶以及vim/gcc/gdb/makefile/yum
  7. Connecting to 192.168.237.129:22... Could not connect to '192.168.237.129' (port 22): Connection fai
  8. em标签和i标签区别
  9. 多啦a梦的python代码_分享一篇文本文档画哆啦A梦代码!
  10. 怎么恢复相机格式化的照片?