博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用于可视化的坐标轴与外包框的网格生成算法
阅读量:5010 次
发布时间:2019-06-12

本文共 5090 字,大约阅读时间需要 16 分钟。

在三维模型显示与交互任务中, 坐标轴和外包框是其基本的辅助工具。相关方法可以分成几何体(网格构造)算法与着色器方法(点精灵方式等),本文仅讨论相关的网格生成。

考虑到坐标轴与外包框可以用柱体与锥体两大基本元素组合生成,基本元素又可进一步划分为由采样点构成的圆周,圆面和锥体斜面都可由采样点圆周与中心点构成扇形三角形区域,圆柱面则由相邻两个灯采样点圆周构成三角形条带。
890213-20180917133119125-1928666745.png
扇形三角形区域和三角形条带均可用基本共享顶点数据结构表示,处理好三角形面朝向问题,则有如下代码实现:

// 坐标轴网格构建// 1. 坐标轴的尖顶帽子效果可用等圆周三角形条带和扇形三角形实现// 2. 坐标轴的交界部分可使用扇形三角形实现YbMesh::indicesTriMesh
YbMesh::geometry::make_axes(float height,float r) { auto v = std::make_shared
>(); auto f = std::make_shared
>(); // z for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(2*r*std::sinf(delta), 2*r*std::cosf(delta), height+r*2)); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(r*std::sinf(delta), r*std::cosf(delta), height*h+r*2)); } v->emplace_back(glm::vec3(.0f, .0f, height+r*5)); v->emplace_back(glm::vec3(.0f, .0f, 0.0f)); // y for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(2*r*std::cosf(delta), height+r*2, 2*r*std::sinf(delta))); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(r*std::cosf(delta), height*h+r*2, r*std::sinf(delta))); } v->emplace_back(glm::vec3(.0f, height+r*5, .0f)); v->emplace_back(glm::vec3(.0f, 0.0f, .0f)); // x for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(height+r*2, 2*r*std::sinf(delta), 2*r*std::cosf(delta))); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(glm::vec3(height*h+r*2, r*std::sinf(delta), r*std::cosf(delta))); } v->emplace_back(glm::vec3(height+r*5, .0f, .0f)); v->emplace_back(glm::vec3(.0f, 0.0f, .0f)); for(int offset:{0,122,244}){ for(int j = 0; j < 20; j++) { // top-down faces f->emplace_back(glm::ivec3(j,(j+1)%20,120)+offset); f->emplace_back(glm::ivec3(100+(j+1)%20,100+j,121)+offset); for(int i = 0; i < 5; i++) { f->emplace_back(glm::ivec3(i*20+(j+1)%20,i*20+j,(1+i)*20+j)+offset); f->emplace_back(glm::ivec3((i+1)*20+j,(i+1)*20+(j+1)%20,i*20+(j+1)%20)+offset); } } } return YbMesh::indicesTriMesh
(v,f);}
// 外包框// 1. 棱的非交界部分用等采样点圆周的三角形条带实现// 2. 棱的交界部分用扇形三角形实现// 3. 外包框的8个视觉顶点的坐标位置与索引号的编码关系(难点)YbMesh::indicesTriMesh
YbMesh::geometry::make_box(float height,float r) { auto v = std::make_shared
>(); auto f = std::make_shared
>(); // z directions for(int e:{0,1,2,3}) { glm::vec3 offset = 0.5f*height*glm::vec3(e&2?-1.0f:1.0f,e&1?-1.0f:1.0f,-1.0f); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(offset+glm::vec3(r*std::sinf(delta), r*std::cosf(delta), r+(height-2*r)*h)); } } // y for(int e:{0,1,2,3}) { glm::vec3 offset = 0.5f*height*glm::vec3(e&2?-1.0f:1.0f,-1.0f,e&1?-1.0f:1.0f); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(offset+glm::vec3(r*std::cosf(delta), r+(height-2*r)*h, r*std::sinf(delta))); } } // x for(int e:{0,1,2,3}) { glm::vec3 offset = 0.5f*height*glm::vec3(-1.0f,e&2?-1.0f:1.0f,e&1?-1.0f:1.0f); for(float h = 1.0f; h >= 0; h -= 1.0f/4) { for(float delta = 2*PI; delta >= 0; delta -= PI/10) v->emplace_back(offset+glm::vec3(r+(height-2*r)*h, r*std::sinf(delta), r*std::cosf(delta))); } } for(int offset = 0; offset < 1200; offset += 100){ for(int j = 0; j < 20; j++) { for(int i = 0; i < 4; i++) { f->emplace_back(offset+glm::ivec3(i*20+(j+1)%20,i*20+j,(1+i)*20+j)); f->emplace_back(offset+glm::ivec3((i+1)*20+j,(i+1)*20+(j+1)%20,i*20+(j+1)%20)); } } } for(int e = 0,offset = 0; e< 8; e++) { v->emplace_back(0.5f*height*glm::vec3(e&4?-1.0f:1.0f,e&2?-1.0f:1.0f,e&1?-1.0f:1.0f)); for(int j = 0; j < 20; j++) { offset = 800+80*bool(e&4)+100*(e&3); f->emplace_back(offset%100 == 80 ? glm::ivec3((j+1)%20+offset,j+offset,1200+e):glm::ivec3(j+offset,(j+1)%20+offset,1200+e)); offset = 400+80*bool(e&2)+100*(((e&4)>>1)+(e&1)); f->emplace_back(offset%100 == 80 ? glm::ivec3((j+1)%20+offset,j+offset,1200+e):glm::ivec3(j+offset,(j+1)%20+offset,1200+e)); offset = 00+80*bool(e&1)+100*((e&6)>>1); f->emplace_back(offset%100 == 80 ? glm::ivec3((j+1)%20+offset,j+offset,1200+e):glm::ivec3(j+offset,(j+1)%20+offset,1200+e)); } } return YbMesh::indicesTriMesh
(v,f);}

具体的效果如图:

890213-20180917131242881-1306073794.png
扩展性部分,对于类似MeshLab的坐标轴的坐标尺度效果(对应本文则是坐标轴网的周期纹理效果),实现上可由顶点着色器与面元着色器简单合作完成。

转载于:https://www.cnblogs.com/xiconxi/p/9661595.html

你可能感兴趣的文章
2018-2019 ICPC, NEERC, Southern Subregional Contest(训练记录)
查看>>
20145233 《信息安全系统设计基础》第7周学习总结
查看>>
linux设备驱动程序第3版学习笔记(例程2--hellop.c)
查看>>
玩转storm
查看>>
第10章 使用Apache服务部署静态网站
查看>>
关于给予webApp框架的开发工具
查看>>
c语言编写的生成泊松分布随机数
查看>>
Maven入门笔记
查看>>
iOS webView的常见属性和方法
查看>>
理解position:relative
查看>>
Codeforces Round #344 (Div. 2) Messager KMP的应用
查看>>
20145308刘昊阳 《Java程序设计》第4周学习总结
查看>>
js倒计时
查看>>
EasyUI datagrid 格式 二
查看>>
Android虹软人脸识别sdk使用工具类
查看>>
UI:基础
查看>>
浅谈 @RequestParam 和@PathVariable
查看>>
设计模式之---装饰器设计模式
查看>>
基于WordNet的英文同义词、近义词相似度评估及代码实现
查看>>
Equation漏洞混淆利用分析总结(上)
查看>>