矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 691|回复: 3

AI真强,OBJ/STP/STL 3D模型浏览器

[复制链接]
     
发表于 2025-3-5 16:23:30 | 显示全部楼层 |阅读模式
Image 1092.jpg
Image 1090.jpg
Image 1091.jpg
使用glut,编写一个wrl和obj模型文件浏览工具,可以通过鼠标左键进行上下左右旋转3D模型,x键放大y键缩小。有基础的全局环境光照和透视效果。
让这个代码支持stp stl文件
回到最初的代码,让opengl显示出模型棱角的线条

  1. #include <GL/glut.h>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <sstream>
  5. #include <vector>
  6. #include <string>
  7. #include <cstring>
  8. #include <stdlib.h>

  9. // 模型数据
  10. std::vector<float> vertices;
  11. std::vector<int> indices;

  12. // 旋转角度
  13. float rotateX = 0.0f;
  14. float rotateY = 0.0f;

  15. // 缩放因子
  16. float scaleFactor = 1.0f;

  17. // 鼠标状态
  18. bool mouseLeftDown = false;
  19. int lastMouseX = 0;
  20. int lastMouseY = 0;

  21. // 读取OBJ文件
  22. void loadOBJ(const std::string& filename) {
  23.         std::ifstream file(filename.c_str());
  24.         if (!file.is_open()) {
  25.                 std::cerr << "无法打开文件: " << filename << std::endl;
  26.                 return;
  27.         }

  28.         std::string line;
  29.         while (std::getline(file, line)) {
  30.                 std::istringstream iss(line);
  31.                 std::string type;
  32.                 iss >> type;

  33.                 if (type == "v") {
  34.                         float x, y, z;
  35.                         iss >> x >> y >> z;
  36.                         vertices.push_back(x);
  37.                         vertices.push_back(y);
  38.                         vertices.push_back(z);
  39.                 } else if (type == "f") {
  40.                         int v1, v2, v3;
  41.                         std::string vertex1, vertex2, vertex3;
  42.                         iss >> vertex1 >> vertex2 >> vertex3;
  43.                         v1 = atol(vertex1.substr(0, vertex1.find('/')).c_str()) - 1;
  44.                         v2 = atol(vertex2.substr(0, vertex2.find('/')).c_str()) - 1;
  45.                         v3 = atol(vertex3.substr(0, vertex3.find('/')).c_str()) - 1;
  46.                         indices.push_back(v1);
  47.                         indices.push_back(v2);
  48.                         indices.push_back(v3);
  49.                 }
  50.         }

  51.         file.close();
  52. }

  53. // 读取 ASCII STL 文件
  54. void loadASCIISTL(const std::string& filename) {
  55.         std::ifstream file(filename.c_str());
  56.         if (!file.is_open()) {
  57.                 std::cerr << "无法打开文件: " << filename << std::endl;
  58.                 return;
  59.         }

  60.         std::string line;
  61.         while (std::getline(file, line)) {
  62.                 std::istringstream iss(line);
  63.                 std::string type;
  64.                 iss >> type;

  65.                 if (type == "vertex") {
  66.                         float x, y, z;
  67.                         iss >> x >> y >> z;
  68.                         vertices.push_back(x);
  69.                         vertices.push_back(y);
  70.                         vertices.push_back(z);
  71.                         indices.push_back(vertices.size() / 3 - 1);
  72.                 }
  73.         }

  74.         file.close();
  75. }

  76. // 读取二进制 STL 文件
  77. void loadBinarySTL(const std::string& filename) {
  78.         std::ifstream file(filename.c_str(), std::ios::binary);
  79.         if (!file.is_open()) {
  80.                 std::cerr << "无法打开文件: " << filename << std::endl;
  81.                 return;
  82.         }

  83.         char header[80];
  84.         file.read(header, 80);

  85.         unsigned int numTriangles;
  86.         file.read(reinterpret_cast<char*>(&numTriangles), 4);

  87.         for (unsigned int i = 0; i < numTriangles; ++i) {
  88.                 float normal[3];
  89.                 file.read(reinterpret_cast<char*>(normal), 12);

  90.                 for (int j = 0; j < 3; ++j) {
  91.                         float vertex[3];
  92.                         file.read(reinterpret_cast<char*>(vertex), 12);
  93.                         vertices.push_back(vertex[0]);
  94.                         vertices.push_back(vertex[1]);
  95.                         vertices.push_back(vertex[2]);
  96.                         indices.push_back(vertices.size() / 3 - 1);
  97.                 }

  98.                 unsigned short attributeByteCount;
  99.                 file.read(reinterpret_cast<char*>(&attributeByteCount), 2);
  100.         }

  101.         file.close();
  102. }

  103. // 自动检测并加载 STL 文件
  104. void loadSTL(const std::string& filename) {
  105.         std::ifstream file(filename.c_str());
  106.         std::string firstLine;
  107.         std::getline(file, firstLine);
  108.         file.close();

  109.         if (firstLine.find("solid") != std::string::npos) {
  110.                 loadASCIISTL(filename);
  111.         } else {
  112.                 loadBinarySTL(filename);
  113.         }
  114. }

  115. // 初始化OpenGL设置
  116. void init() {
  117.         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  118.         glEnable(GL_DEPTH_TEST);

  119.         // 启用光照
  120.         glEnable(GL_LIGHTING);
  121.         glEnable(GL_LIGHT0);

  122.         // 设置环境光
  123.         GLfloat ambientLight[] = {0.2f, 0.2f, 0.2f, 1.0f};
  124.         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);

  125.         // 设置光源位置
  126.         GLfloat lightPosition[] = {1.0f, 1.0f, 1.0f, 0.0f};
  127.         glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

  128.         // 设置材质属性
  129.         GLfloat materialDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
  130.         glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse);

  131.         // 设置多边形渲染模式为线框模式
  132.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

  133. }

  134. // 显示回调函数
  135. void display() {
  136.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  137.         glMatrixMode(GL_MODELVIEW);
  138.         glLoadIdentity();

  139.         // 设置相机位置
  140.         gluLookAt(0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

  141.         // 应用旋转和缩放
  142.         glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
  143.         glRotatef(rotateY, 0.0f, 1.0f, 0.0f);
  144.         glScalef(scaleFactor, scaleFactor, scaleFactor);

  145.         // 绘制模型
  146.         glBegin(GL_TRIANGLES);
  147.         for (size_t i = 0; i < indices.size(); i++) {
  148.                 int index = indices[i];
  149.                 glVertex3f(vertices[index * 3], vertices[index * 3 + 1], vertices[index * 3 + 2]);
  150.         }
  151.         glEnd();

  152.         glutSwapBuffers();
  153. }

  154. // 调整窗口大小回调函数
  155. void reshape(int width, int height) {
  156.         if (height == 0) height = 1;
  157.         float aspect = (float)width / (float)height;

  158.         glViewport(0, 0, width, height);
  159.         glMatrixMode(GL_PROJECTION);
  160.         glLoadIdentity();
  161.         gluPerspective(45.0f, aspect, 0.1f, 100.0f);
  162. }

  163. // 鼠标事件回调函数
  164. void mouse(int button, int state, int x, int y) {
  165.         if (button == GLUT_LEFT_BUTTON) {
  166.                 if (state == GLUT_DOWN) {
  167.                         mouseLeftDown = true;
  168.                         lastMouseX = x;
  169.                         lastMouseY = y;
  170.                 } else {
  171.                         mouseLeftDown = false;
  172.                 }
  173.         }
  174. }

  175. // 鼠标移动事件回调函数
  176. void motion(int x, int y) {
  177.         if (mouseLeftDown) {
  178.                 int dx = x - lastMouseX;
  179.                 int dy = y - lastMouseY;

  180.                 rotateX += dy * 0.5f;
  181.                 rotateY += dx * 0.5f;

  182.                 lastMouseX = x;
  183.                 lastMouseY = y;

  184.                 glutPostRedisplay();
  185.         }
  186. }

  187. // 键盘事件回调函数
  188. void keyboard(unsigned char key, int x, int y) {
  189.         switch (key) {
  190.                 case 'x':
  191.                         scaleFactor *= 1.1f;
  192.                         glutPostRedisplay();
  193.                         break;
  194.                 case 'y':
  195.                         scaleFactor /= 1.1f;
  196.                         glutPostRedisplay();
  197.                         break;
  198.                 case 27: // ESC键退出
  199.                         exit(0);
  200.                         break;
  201.         }
  202. }

  203. // 检测文件扩展名并加载相应文件
  204. void loadFile(const std::string& filename) {
  205.         size_t dotPos = filename.find_last_of('.');
  206.         if (dotPos != std::string::npos) {
  207.                 std::string extension = filename.substr(dotPos + 1);
  208.                 if (extension == "obj") {
  209.                         loadOBJ(filename);
  210.                 } else if (extension == "stl") {
  211.                         loadSTL(filename);
  212.                 } else {
  213.                         std::cerr << "不支持的文件格式: " << extension << std::endl;
  214.                 }
  215.         } else {
  216.                 std::cerr << "无法识别文件扩展名" << std::endl;
  217.         }
  218. }

  219. int main(int argc, char** argv) {
  220.         if (argc < 2) {
  221.                 std::cerr << "用法: " << argv[0] << " <文件路径>" << std::endl;
  222.                 return 1;
  223.         }

  224.         // 加载文件
  225.         loadFile(argv[1]);

  226.         // 初始化GLUT
  227.         glutInit(&argc, argv);
  228.         glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  229.         glutInitWindowSize(800, 600);
  230.         glutCreateWindow("3D模型浏览工具");

  231.         // 初始化OpenGL
  232.         init();

  233.         // 设置回调函数
  234.         glutDisplayFunc(display);
  235.         glutReshapeFunc(reshape);
  236.         glutMouseFunc(mouse);
  237.         glutMotionFunc(motion);
  238.         glutKeyboardFunc(keyboard);

  239.         // 进入主循环
  240.         glutMainLoop();

  241.         return 0;
  242. }
复制代码
     
 楼主| 发表于 2025-3-5 17:22:33 | 显示全部楼层
回复 支持 反对

使用道具 举报

     
发表于 2025-3-5 17:51:49 | 显示全部楼层
现在AI确实强大,经常让AI作诗作文章来读
回复 支持 反对

使用道具 举报

     
发表于 2025-3-5 18:03:55 | 显示全部楼层
无处不AI啊,连怀旧论坛也在AI
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-29 11:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表