JuncoJet 发表于 2025-3-5 16:23:30

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




使用glut,编写一个wrl和obj模型文件浏览工具,可以通过鼠标左键进行上下左右旋转3D模型,x键放大y键缩小。有基础的全局环境光照和透视效果。
让这个代码支持stp stl文件
回到最初的代码,让opengl显示出模型棱角的线条

#include <GL/glut.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <cstring>
#include <stdlib.h>

// 模型数据
std::vector<float> vertices;
std::vector<int> indices;

// 旋转角度
float rotateX = 0.0f;
float rotateY = 0.0f;

// 缩放因子
float scaleFactor = 1.0f;

// 鼠标状态
bool mouseLeftDown = false;
int lastMouseX = 0;
int lastMouseY = 0;

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

        std::string line;
        while (std::getline(file, line)) {
                std::istringstream iss(line);
                std::string type;
                iss >> type;

                if (type == "v") {
                        float x, y, z;
                        iss >> x >> y >> z;
                        vertices.push_back(x);
                        vertices.push_back(y);
                        vertices.push_back(z);
                } else if (type == "f") {
                        int v1, v2, v3;
                        std::string vertex1, vertex2, vertex3;
                        iss >> vertex1 >> vertex2 >> vertex3;
                        v1 = atol(vertex1.substr(0, vertex1.find('/')).c_str()) - 1;
                        v2 = atol(vertex2.substr(0, vertex2.find('/')).c_str()) - 1;
                        v3 = atol(vertex3.substr(0, vertex3.find('/')).c_str()) - 1;
                        indices.push_back(v1);
                        indices.push_back(v2);
                        indices.push_back(v3);
                }
        }

        file.close();
}

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

        std::string line;
        while (std::getline(file, line)) {
                std::istringstream iss(line);
                std::string type;
                iss >> type;

                if (type == "vertex") {
                        float x, y, z;
                        iss >> x >> y >> z;
                        vertices.push_back(x);
                        vertices.push_back(y);
                        vertices.push_back(z);
                        indices.push_back(vertices.size() / 3 - 1);
                }
        }

        file.close();
}

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

        char header;
        file.read(header, 80);

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

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

                for (int j = 0; j < 3; ++j) {
                        float vertex;
                        file.read(reinterpret_cast<char*>(vertex), 12);
                        vertices.push_back(vertex);
                        vertices.push_back(vertex);
                        vertices.push_back(vertex);
                        indices.push_back(vertices.size() / 3 - 1);
                }

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

        file.close();
}

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

        if (firstLine.find("solid") != std::string::npos) {
                loadASCIISTL(filename);
        } else {
                loadBinarySTL(filename);
        }
}

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

        // 启用光照
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

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

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

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

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

}

// 显示回调函数
void display() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

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

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

        // 绘制模型
        glBegin(GL_TRIANGLES);
        for (size_t i = 0; i < indices.size(); i++) {
                int index = indices;
                glVertex3f(vertices, vertices, vertices);
        }
        glEnd();

        glutSwapBuffers();
}

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

        glViewport(0, 0, width, height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}

// 鼠标事件回调函数
void mouse(int button, int state, int x, int y) {
        if (button == GLUT_LEFT_BUTTON) {
                if (state == GLUT_DOWN) {
                        mouseLeftDown = true;
                        lastMouseX = x;
                        lastMouseY = y;
                } else {
                        mouseLeftDown = false;
                }
        }
}

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

                rotateX += dy * 0.5f;
                rotateY += dx * 0.5f;

                lastMouseX = x;
                lastMouseY = y;

                glutPostRedisplay();
        }
}

// 键盘事件回调函数
void keyboard(unsigned char key, int x, int y) {
        switch (key) {
                case 'x':
                        scaleFactor *= 1.1f;
                        glutPostRedisplay();
                        break;
                case 'y':
                        scaleFactor /= 1.1f;
                        glutPostRedisplay();
                        break;
                case 27: // ESC键退出
                        exit(0);
                        break;
        }
}

// 检测文件扩展名并加载相应文件
void loadFile(const std::string& filename) {
        size_t dotPos = filename.find_last_of('.');
        if (dotPos != std::string::npos) {
                std::string extension = filename.substr(dotPos + 1);
                if (extension == "obj") {
                        loadOBJ(filename);
                } else if (extension == "stl") {
                        loadSTL(filename);
                } else {
                        std::cerr << "不支持的文件格式: " << extension << std::endl;
                }
        } else {
                std::cerr << "无法识别文件扩展名" << std::endl;
        }
}

int main(int argc, char** argv) {
        if (argc < 2) {
                std::cerr << "用法: " << argv << " <文件路径>" << std::endl;
                return 1;
        }

        // 加载文件
        loadFile(argv);

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

        // 初始化OpenGL
        init();

        // 设置回调函数
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
        glutMouseFunc(mouse);
        glutMotionFunc(motion);
        glutKeyboardFunc(keyboard);

        // 进入主循环
        glutMainLoop();

        return 0;
}

JuncoJet 发表于 2025-3-5 17:22:33

完整的聊天内容
https://www.doubao.com/thread/wfcf390627b7ee34c

Cachee 发表于 2025-3-5 17:51:49

现在AI确实强大,经常让AI作诗作文章来读

zerof 发表于 2025-3-5 18:03:55

无处不AI啊,连怀旧论坛也在AI:lol
页: [1]
查看完整版本: AI真强,OBJ/STP/STL 3D模型浏览器