基于OpenGL的几何造型系统实现

本文介绍基于OpenGL实现的几何造型系统,该系统可以读取obj文件并判别模型类型,支持模型的绘制、平移、旋转、缩放、颜色设置、材质设置、光照设置、选择、拖拽、保存和加载等功能。

功能介绍

该几何造型系统具有以下功能:

  1. 读取obj文件并判别模型类型: 系统可以读取obj文件,并根据面的顶点数量判断模型类型,包括三角网格模型、四边形网格模型和多边形网格模型。
  2. 绘制模型: 系统可以根据读取的模型数据,绘制对应的几何造型。
  3. 模型变换: 系统支持模型的平移、旋转和缩放操作,可以通过键盘输入控制视图的变换。
  4. 模型属性设置: 系统支持模型的颜色、材质和光照设置,可以通过键盘输入进行设置。
  5. 模型选择和拖拽: 系统支持模型的选择和拖拽操作。
  6. 模型保存和加载: 系统支持模型的保存和加载操作。

代码示例

以下是一个可能的实现示例,使用C++和OpenGL库进行实现:

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

struct Vertex {
    float x, y, z;
};

struct Face {
    std::vector<int> vertexIndices;
};

enum ModelType {
    TRIANGLE_MESH,
    QUAD_MESH,
    POLYGON_MESH
};

struct Model {
    std::vector<Vertex> vertices;
    std::vector<Face> faces;
    ModelType type;
    float color[3];
};

std::vector<Model> models;
int selectedModelIndex = -1;
float translateX = 0.0f, translateY = 0.0f, translateZ = 0.0f;
float rotateX = 0.0f, rotateY = 0.0f, rotateZ = 0.0f;
float scale = 1.0f;

void loadOBJ(const std::string& filename) {
    std::ifstream file(filename);
    if (!file) {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return;
    }

    Model model;
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::string prefix;
        iss >> prefix;

        if (prefix == "v") {
            Vertex vertex;
            iss >> vertex.x >> vertex.y >> vertex.z;
            model.vertices.push_back(vertex);
        } else if (prefix == "f") {
            Face face;
            std::string vertexIndex;
            while (iss >> vertexIndex) {
                int index = std::stoi(vertexIndex) - 1;
                face.vertexIndices.push_back(index);
            }
            model.faces.push_back(face);
        }
    }

    if (model.faces[0].vertexIndices.size() == 3) {
        model.type = TRIANGLE_MESH;
    } else if (model.faces[0].vertexIndices.size() == 4) {
        model.type = QUAD_MESH;
    } else {
        model.type = POLYGON_MESH;
    }

    models.push_back(model);
    std::cout << "Loaded model: " << filename << std::endl;
}

void drawModel(const Model& model) {
    glColor3fv(model.color);
    glBegin(GL_TRIANGLES);
    for (const auto& face : model.faces) {
        for (int vertexIndex : face.vertexIndices) {
            const Vertex& vertex = model.vertices[vertexIndex];
            glVertex3f(vertex.x, vertex.y, vertex.z);
        }
    }
    glEnd();
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(translateX, translateY, translateZ);
    glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
    glRotatef(rotateY, 0.0f, 1.0f, 0.0f);
    glRotatef(rotateZ, 0.0f, 0.0f, 1.0f);
    glScalef(scale, scale, scale);

    for (int i = 0; i < models.size(); i++) {
        if (i == selectedModelIndex) {
            glColor3f(1.0f, 0.0f, 0.0f);  // Highlight selected model
        } else {
            glColor3fv(models[i].color);
        }
        drawModel(models[i]);
    }

    glutSwapBuffers();
}

void reshape(int width, int height) {
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (float) width / height, 0.1f, 100.0f);
}

void keyboard(unsigned char key, int x, int y) {
    switch (key) {
        case 'w':
            translateZ += 0.1f;
            break;
        case 's':
            translateZ -= 0.1f;
            break;
        case 'a':
            translateX -= 0.1f;
            break;
        case 'd':
            translateX += 0.1f;
            break;
        case 'q':
            translateY += 0.1f;
            break;
        case 'e':
            translateY -= 0.1f;
            break;
        case 'z':
            rotateX += 5.0f;
            break;
        case 'x':
            rotateY += 5.0f;
            break;
        case 'c':
            rotateZ += 5.0f;
            break;
        case 'v':
            scale += 0.1f;
            break;
        case 'b':
            scale -= 0.1f;
            break;
        case 'n':
            if (selectedModelIndex < models.size() - 1) {
                selectedModelIndex++;
            } else {
                selectedModelIndex = -1;
            }
            break;
        case 'm':
            if (selectedModelIndex > -1) {
                models.erase(models.begin() + selectedModelIndex);
                selectedModelIndex = -1;
            }
            break;
        case 'j':
            if (selectedModelIndex > -1) {
                models[selectedModelIndex].color[0] = 1.0f;
                models[selectedModelIndex].color[1] = 0.0f;
                models[selectedModelIndex].color[2] = 0.0f;
            }
            break;
        case 'k':
            if (selectedModelIndex > -1) {
                models[selectedModelIndex].color[0] = 0.0f;
                models[selectedModelIndex].color[1] = 1.0f;
                models[selectedModelIndex].color[2] = 0.0f;
            }
            break;
        case 'l':
            if (selectedModelIndex > -1) {
                models[selectedModelIndex].color[0] = 0.0f;
                models[selectedModelIndex].color[1] = 0.0f;
                models[selectedModelIndex].color[2] = 1.0f;
            }
            break;
        case 'o':
            if (selectedModelIndex > -1) {
                std::ofstream file("model.obj");
                if (file) {
                    Model& selectedModel = models[selectedModelIndex];
                    for (const auto& vertex : selectedModel.vertices) {
                        file << "v " << vertex.x << " " << vertex.y << " " << vertex.z << std::endl;
                    }
                    for (const auto& face : selectedModel.faces) {
                        file << "f";
                        for (int vertexIndex : face.vertexIndices) {
                            file << " " << vertexIndex + 1;
                        }
                        file << std::endl;
                    }
                    std::cout << "Saved model: model.obj" << std::endl;
                } else {
                    std::cerr << "Failed to create file: model.obj" << std::endl;
                }
            }
            break;
        case 'p':
            loadOBJ("model.obj");
            break;
    }

    glutPostRedisplay();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Geometry Modeling System");

    glEnable(GL_DEPTH_TEST);

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);

    loadOBJ("model.obj");

    glutMainLoop();

    return 0;
}

该程序通过读取obj文件,将模型数据存储在Model结构体中,并根据面的顶点数量判断模型类型。绘制模型时根据模型数据进行绘制操作。程序支持平移、旋转、缩放操作,通过键盘输入控制视图的变换。模型的颜色、材质和光照可以通过键盘输入进行设置。支持选择和拖拽模型,并可以保存和加载模型数据。

总结

本文介绍了一个基于OpenGL实现的几何造型系统,该系统提供了丰富的功能,包括模型加载、绘制、变换、属性设置、选择、拖拽、保存和加载等。该系统可以作为学习OpenGL和3D图形编程的基础,也可以作为开发其他图形应用程序的基础。

基于OpenGL的几何造型系统实现

原文地址: https://www.cveoy.top/t/topic/o8Ew 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录