STL模型在单片机上3D旋转显示
STL文/件说明:
STL文/件是一种由三角形面组成3D模型的文/件,常用于3D打印机。 由于经常接触,就很好奇SLT文件到底怎么组成的?还可以怎么玩? 1:STL分为BIN格式和ASCLL格式。 BIN格式的构成大概就一堆二进制文/件,需要对应结构解码使用。
ASCLL格式则是文本格式,用记事本就可以直观看到数据说明。
这里我的代码是使用的BIN文/件格式解码。。。 2:BIN格式STL文件说明 可以看到图片中的数据,前80字节为文/件描述头,
紧接着就是4字节的关键数据:构成物体的三角面个数。 源码部分也是通过它来 【校验是否为BIN格式】 和 【显示(点/线/面)】。
紧接着的就是每个面的数据了,一个面的描述共50字节。 3*4字节float浮点的法向量数据(x,y,z), 3*4字节float浮点的点1坐标数据(x,y,z), 3*4字节float浮点的点2坐标数据(x,y,z), 3*4字节float浮点的点3坐标数据(x,y,z), 2字节的u16说明数据(可忽略)。 源码的编写:
1:结构体的定义 其实可以发现BIN格式的STL文/件就是面数量和面组成结构比较重要, 所以代码部分就省去了文/件的头结构体,你非得使用也没事。。。 //三角面结构体 typedef struct { float Normalvector[3];//法线矢量 float Vertex1[3];//顶点坐标1 float Vertex2[3];//顶点坐标2 float Vertex3[3];//顶点坐标3 uint16_t attributebytexountend;//属性统计 } TRIAN; ////BIN格式STL文件结构体 不重要,可以不用。 //typedef struct { // u8 header[80]; //80字节 “SOLID?”不重要 // uint32_t Numberoftriangles;//三角面片数量 // TRIAN trian; //} STL 2:验证是否是BIN格式STL文/件 由于文/件时存储在SD卡文/件夹内的,所以需要使用FAT文/件系统进行文件读取, 一般读取SD文/件时大多是即用即取,这里全部读取数据提高了数据获取数据,减少延时。 由于SLT-BIN格式 数据头描述固定为80+4字节,一个三角面的组成固定为50字节, 所以就可以直接通过 【总字节=80+4+面*50】 进行验证。 如上图的正方形bin.STL文件 总字节数(684)=80+4+(三角面)12*50 验证通过。 //读取文件全部一次读取方便快速计算 f_read(&stl_file,file_buff,stl_file.obj.objsize,(UINT*)&br); LCD_ShowxNum(300,170,br,5,16,0); f_close(&stl_file);//关闭文件 stl_file.obj.objsize被释放了 以br为主 //获取面个数 tmp = (u8*)&number; reda=(file_buff+80); for(x=0;x<4;x++) *tmp++ = *reda++; Show_Str(30,190,200,16,"STL 三角面个数",16,0); LCD_ShowxNum(210,190,number,5,16,0); ///判断是否为BIN格式STL 总字节=面个数*58+84 if(br != (number*50+84)) { Show_Str(30,210,400,24,"该STL文件不是BIN格式!",24,0); while(1); } 3:需要特/别注意RAM的存取BUG 在代码中,多次使用了最简单的 单字节指针进行数据传递。 for(x=0;x<4;x++) *tmp++ = *reda++; 理论上只要数据类型(强/制转换)一样就可以用等式进行传递, //trian2=*(TRIAN *)reda; 这是为什么呢?是因为前面我们将所有STL数据存储在了RAM里面, 将指针指向文/件时,在进行float类型数据储存时,部分数据没有4字节对齐, 然后就直接触发BUG了。。。。(调试了好久。。一把心酸泪啊。) reda=(file_buff+84+i*50); tmp = (u8*)&trian2; for(x=0;x<50;x++) *tmp++ = *reda++; //trian2=*(TRIAN *)reda;//直接取值会导致float 4字节不对齐 跑飞 4:3D物体的旋转及显示 旋转部分移植的网友开源的代码,也没问他具体哪里弄的(发现也是移植过的,OPENGL?)。自己也写过三维矩阵代码,但是没这个快。功能没这个多(后面不显示,面填充(应该是他写的),面颜色角度渲染)。。。 这里是通过按键进行点,线,面进行切换显示。 if(showmode==0) { //显示点 if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; pBackBuffer[(((int)cube[0][1]+LOGO16_GLCD_HEIGHT)*480+((int)cube[0][0])+LOGO16_GLCD_WIDTH)] = POINT_COLOR; if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; pBackBuffer[(((int)cube[1][1]+LOGO16_GLCD_HEIGHT)*480+((int)cube[1][0])+LOGO16_GLCD_WIDTH)] = POINT_COLOR; if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; pBackBuffer[(((int)cube[2][1]+LOGO16_GLCD_HEIGHT)*480+((int)cube[2][0])+LOGO16_GLCD_WIDTH)] = POINT_COLOR; } else if(showmode==1) { //显示点连线 全显示 if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; LCD_Buff_DrawLine(LOGO16_GLCD_WIDTH+cube[0][0],LOGO16_GLCD_HEIGHT+cube[0][1],LOGO16_GLCD_WIDTH+cube[1][0],LOGO16_GLCD_HEIGHT+cube[1][1],pBackBuffer); if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; LCD_Buff_DrawLine(LOGO16_GLCD_WIDTH+cube[0][0],LOGO16_GLCD_HEIGHT+cube[0][1],LOGO16_GLCD_WIDTH+cube[2][0],LOGO16_GLCD_HEIGHT+cube[2][1],pBackBuffer); if(++color_nm > 9)color_nm=0; POINT_COLOR=color[color_nm]; LCD_Buff_DrawLine(LOGO16_GLCD_WIDTH+cube[1][0],LOGO16_GLCD_HEIGHT+cube[1][1],LOGO16_GLCD_WIDTH+cube[2][0],LOGO16_GLCD_HEIGHT+cube[2][1],pBackBuffer); } else { //判断是否显示面 dx0=cube[1][0]-cube[0][0]; dx1=cube[2][0]-cube[0][0]; dy0=cube[1][1]-cube[0][1]; dy1=cube[2][1]-cube[0][1]; if(dx0*dy1 > dx1*dy0) { trian2.Normalvector[0]=((cube[1][1]-cube[0][1])*(cube[2][2]-cube[0][2]))-((cube[1][2]-cube[0][2])*(cube[2][1]-cube[0][1])); trian2.Normalvector[1]=((cube[1][2]-cube[0][2])*(cube[2][0]-cube[0][0]))-((cube[1][0]-cube[0][0])*(cube[2][2]-cube[0][2])); trian2.Normalvector[2]=((cube[1][0]-cube[0][0])*(cube[2][1]-cube[0][1]))-((cube[1][1]-cube[0][1])*(cube[2][0]-cube[0][0])); lenSq = trian2.Normalvector[0]*trian2.Normalvector[0]+ trian2.Normalvector[1]*trian2.Normalvector[1]+ trian2.Normalvector[2]*trian2.Normalvector[2]; ilen = sqrt(lenSq); if (fabs(ilen) > 0.001f) ilen = 1.0f/ilen; else ilen = 0; trian2.Normalvector[2] *= ilen; POINT_COLOR = sqrt(trian2.Normalvector[2]) * 31.5f; RotatePoly(cube,3); renderPolygonSub(cube,3,POINT_COLOR); } } 程序源码工程附近不支持上传,这里附上链接,或者在开源广场搜索此文章找到对应工程附件下载就行。 https:// oshwhub.com /article/dan-pian-ji-xuan-zhuai-xian-shi-3dmu-xing-stl