MGLTools:方便的在OpenGL及相关3D编程辅助工具集

MGLTools是一个个人开发的工具集,包含一系列简化openGL函数,专注于3D问题的解决方案,如向量和空间变换。此工具集依赖于openGL标准库,可供开发者参考使用。

介绍

这是我个人开发的工具集,包含了围绕openGL的一系列简化函数。
以及针对3D问题常见的问题,例如向量的变换,空间的变换,等等。
我的很多代码是基于这个的,所以贴上来给大家做个参考。

如果有帮助请点个赞谢谢

依赖于:openGL std库

代码

mgltools.h

#ifndef GLTOOLS_H
#define GLTOOLS_H
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <iostream>
#include <gl/GL.h>
#include <GL/glut.h>
#include <gl/GLU.h>
#include <vector>
#include <math.h>
using namespace std;

//这个类用于扩充OPENGL各种功能,使代码更加简单
//结构化定义了光源、材质、贴图相关功能
//定义了点(向量)及其相关计算的函数
//对常见操作进行了宏定义
//作者:yinan Miao from Beihang Univ.
//共计.h与.cpp一套,遵守BSD开发协议。(可应用于任何领域但是需要在源码和手册注明作者)
//QQ:1131042645

//定义AL(X)为从角度转换位弧度的宏
//定义VERTEX(X,Y,Z)为快速创建点(向量)的宏
//定义FLATTENV(X)为展开x,y,z填写函数的宏
//定义RA(X),为限制角度在-Pi到+Pi之间的宏。不会改变角度值,只是按照2Pi调整。
#define AL(X) 3.14*X/180.0
#define WIDTH 1200
#define HEIGHT 400
#define LENGTH 1200
#define VERTEX(X,Y,Z) MGLTools::newV(X,Y,Z)
#define FLATTENV(A) A.x,A.y,A.z
#define RA(X) MGLTools::RA(X)


typedef struct vetexStruct{
    float x, y, z;
} vertex;//点(向量)

typedef struct modelStruct{
    vector<vertex> facet;//法向量
    vector<vertex> p1, p2, p3;//三个点形成一个面
} model;//.stl格式模型储存,三角形面及其法向量

typedef struct ptstrct{
    float x,y;
} pt;//点


typedef struct picStruct{
    GLint imagewidth;
    GLint imageheight;
    GLint pixellength;
    GLubyte* pixeldata;
}pic;//用于储存bmp格式位图,这里只能储存24位的位图


typedef struct materialStruct{
    GLfloat ambient[4];//环境光反射
    GLfloat diffuse[4];//漫反射
    GLfloat specular[4];//镜面反射
    GLfloat shininess;//明度
} materialStruct;//材质结构


typedef struct lightStruct{
    GLfloat ambient[4];//环境光反射
    GLfloat diffuse[4];//漫反射
    GLfloat specular[4];//镜面反射
    GLfloat positon[4];//位置
} lightStruct;//光源结构




class MGLTools
{
public:
    MGLTools();
    static vertex newV(float x,float y,float z);//新建并返回一个新建的向量
    static vertex crossProduct(vertex a,vertex b);//向量积(叉乘),返回一个向量。
    static float dot(vertex a,vertex b);//向量内积,即点乘。返回一个值。
    static vertex norm(vertex a);//归一化,向量方向不变,长度变为1.
    static vertex add(vertex a,vertex b);//求和
    static vertex mult(vertex a,float b);//乘法,向量乘以一个常数
    static vertex rotate(vertex a,vertex b,float ang);//向量旋转,b为转轴,ang为旋转角度

    static float angBtPoints(float x1,float y1,float x2,float y2);//计算两点间角度
    static float disBtPoints(float x1,float y1,float x2,float y2);//计算两点距离

    static float RA(float ang);//限制角度在-兀到+兀之间。

    /*
    Copyright (c) 2018, yinan Miao;
    All rights reserved.
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    Neither the name of the Beihang Univ. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    QQ:1131042645
    */


    static void initGL();//初始化openGL的函数
    static void setMaterials(materialStruct *m);//设置材质为指定材质,需要使用可以长期贮存的内存区域
    static void enableTexture();//开启贴图模式
    static GLuint loadTexture(pic &texture,GLuint *tex);//将一个图片绑定到贴图,并且返回一个贴图ID。
    static void disableTexture();//贴图模式结束
    static void setLight(lightStruct *l,int light);//设置光源。*l为参数,light为光源编号。需要使用glEnable来启动光源后才能设置。

    static void QUADQuick(float x1,float y1,float z1,float x2,float y2,float z2,float x3,float y3,float z3,float x4,float y4,float z4);//快速画一个带贴图的四边形
    static void CylinderGLUTQuick(float x1,float y1,float z1,float x2,float y2,float z2,float r,int s,int l);//在两点之间生成一个圆柱体。

    static void readPic(const char fileName[],pic &unit);//该函数用于读取贴图到内存之中
    static void readStl(const char fileName[],model &mod);//该函数用于读取.stl格式的模型到内存之中
    static void drawStl(model &mod,float scale);//绘制stl模型
};

#endif // GLTOOLS_H

mgltools.cpp

#include "MGLTools.h"

MGLTools::MGLTools()
{

}

vertex MGLTools::newV(float x, float y, float z)//新建一个向量(点)并且返回
{
    vertex a;
    a.x = x;
    a.y = y;
    a.z = z;
    return a;
}

vertex MGLTools::crossProduct(vertex a, vertex b)//向量积就是叉乘
{
    vertex c;
    c.x = a.y*b.z - a.z*b.y;
    c.y = a.z*b.x - a.x*b.z;
    c.z = a.x*b.y - a.y*b.x;
    return c;
}

float MGLTools::dot(vertex a, vertex b)//点乘
{
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

vertex MGLTools::norm(vertex a)//归一化
{
    float l = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
    a.x /= l;
    a.y /= l;
    a.z /= l;
    return a;
}

vertex MGLTools::add(vertex a, vertex b)
{
    vertex ans;
    ans.x = a.x + b.x;
    ans.y = a.y + b.y;
    ans.z = a.z + b.z;
    return ans;
}

vertex MGLTools::mult(vertex a, float b)
{
    vertex ans;
    ans.x = a.x*b;
    ans.y = a.y*b;
    ans.z = a.z*b;
    return ans;
}

vertex MGLTools::rotate(vertex a, vertex b, float ang)//旋转
{
    //while(ang > 3.1415926)ang-=3.1415926*2;
    //while(ang < -3.1415926)ang += 3.1415926*2;
    b = norm(b);
    vertex q,w,e;
    q = MGLTools::mult(a,cos(ang));
    w = MGLTools::mult(b,(1-cos(ang))*MGLTools::dot(a,b));
    e = MGLTools::mult(MGLTools::crossProduct(a,b),sin(ang));
    q = MGLTools::add(q,w);
    q = MGLTools::add(q,e);
    return q;
}

void MGLTools::setMaterials(materialStruct *m)//设置材质
{
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m->ambient);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m->diffuse);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m->specular);
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, m->shininess);
}

void MGLTools::enableTexture()//设置贴图并且开启贴图模式
{
    glEnable(GL_TEXTURE_2D);
}

GLuint MGLTools::loadTexture(pic &texture,GLuint *tex)//载入贴图
{
    //glEnable(GL_TEXTURE_2D);
    glGenTextures(20,tex);
    glBindTexture(GL_TEXTURE_2D,tex[0]);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.imagewidth, texture.imageheight, 0, GL_RGB, GL_UNSIGNED_BYTE, texture.pixeldata);
    return 0;
}

void MGLTools::disableTexture()//关闭贴图模式
{
    glDisable(GL_TEXTURE_2D);
}

void MGLTools::QUADQuick(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4)//根据四个点画一个面的函数
{
    //这个函数主要用于压缩其他函数的长度,否则一个函数太长不便于浏览
    glBegin(GL_QUADS);
    glTexCoord2f(0,0);
    glVertex3f(x1,y1,z1);

    glTexCoord2f(0,1);
    glVertex3f(x2,y2,z2);

    glTexCoord2f(1,1);
    glVertex3f(x3,y3,z3);

    glTexCoord2f(1,0);
    glVertex3f(x4,y4,z4);
    glEnd();
}

void MGLTools::CylinderGLUTQuick(float x1, float y1, float z1, float x2, float y2, float z2, float r, int s, int l)
{
    // 起始线段:以(0,1,0)为起点,它的长度(distance)通过目标线段计算,
    //           终点坐标为(0,1-distance,0)
    // 目标线段:以(x1,y1,z1)为起点,以(x2,y2,z2)为终点
    // 计算目标向量
    GLfloat   dx   =   x2   -   x1;
    GLfloat   dy   =   y2   -   y1;
    GLfloat   dz   =   z2   -   z1;
    // 算出目标向量模(即AB长度)
    GLfloat   distance  =  sqrt(dx*dx + dy*dy + dz*dz);
    // 计算平移量
    GLfloat  px = x1;
    GLfloat  py = y1;
    GLfloat  pz = z1;
    // 起始线段的末端点
    GLfloat  bx = px;
    GLfloat  by = py;
    GLfloat  bz = pz + distance;
    // 计算起始向量
    GLfloat  sx = bx - x1;
    GLfloat  sy = by - y1;
    GLfloat  sz = bz - z1;
    // 计算向量(sx,sy,sz)与向量(dx,dy,dz)的法向量(sy*dz - dy*sz,sz*dx - sx*dz,sx*dy - dx*sy)
    GLfloat fx = sy*dz - dy*sz;
    GLfloat fy = sz*dx - sx*dz;
    GLfloat fz = sx*dy - dx*sy;
    // 求两向量间的夹角
    // 计算第三条边的长度
    GLfloat ax = fabs(x2 - bx);
    GLfloat ay = fabs(y2 - by);
    GLfloat az = fabs(z2 - bz);
    GLfloat length = sqrt(ax*ax + ay*ay + az*az);
    // 根据余弦定理计算夹角
    GLfloat angle = acos((distance*distance*2 - length*length)/(2*distance*distance))*180.0f/3.14159;
    glPushMatrix();
    glTranslatef(x1,y1,z1);
    glRotatef(angle,fx,fy,fz);
    float ad = 3.1415926*2/l;
    float bd = distance/s;
    for(int i=0;i<l;i++)
    {
        for(int j=0;j<s;j++)
        {
            glBegin(GL_POLYGON);
            glNormal3f(cos((i+0.5)*ad),sin((i+0.5)*ad),0);
            glVertex3f(r*cos(i*ad),r*sin(i*ad),j*bd);
            glVertex3f(r*cos((i+1)*ad),r*sin((i+1)*ad),j*bd);
            glVertex3f(r*cos((i+1)*ad),r*sin((i+1)*ad),(j+1)*bd);
            glVertex3f(r*cos(i*ad),r*sin(i*ad),(j+1)*bd);
            glEnd();
        }
    }
    glPopMatrix();
}

void MGLTools::setLight(lightStruct *l, int light)//设置光源
{
    glLightfv(light, GL_AMBIENT, l->ambient);
    glLightfv(light, GL_DIFFUSE, l->diffuse);
    glLightfv(light, GL_SPECULAR, l->specular);
    glLightfv(light, GL_POSITION, l->positon);
}

void MGLTools::readPic(const char fileName[], pic &unit)//从文件读取图片到结构体,具体原理不用细究,主要是按照文件的具体结构读取的
{
    FILE* pfile = fopen(fileName, "rb");
    if (pfile == 0)
        cout << "cannot find pic:"<< fileName << endl;
    else
    {
        fseek(pfile, 0x0012, SEEK_SET);
        fread(&unit.imagewidth, sizeof(unit.imagewidth), 1, pfile);
        fseek(pfile, 0x0016, SEEK_SET);
        fread(&unit.imageheight, sizeof(unit.imageheight), 1, pfile);
        unit.pixellength = unit.imagewidth * unit.imageheight * 3;
        unit.pixeldata = (GLubyte*)malloc(unit.pixellength*2);
        if (unit.pixeldata == 0) exit(0);
        fseek(pfile, 0x0036, SEEK_SET);
        fread(unit.pixeldata, unit.pixellength, 1, pfile);
        for (int i = 0; i < unit.pixellength; i += 3)
        {
            unsigned char swap;
            swap = unit.pixeldata[i];
            unit.pixeldata[i] = unit.pixeldata[i + 2];
            unit.pixeldata[i + 2] = swap;
        }
    }
    fclose(pfile);
}

/*
Copyright (c) 2018, yinan Miao;
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the Beihang Univ. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
QQ:1131042645
*/


void MGLTools::readStl(const char fileName[], model &mod)//读取三维模型
{
    FILE *f = fopen(fileName, "r");
    unsigned char *data;
    unsigned char dataV[4];
    long long int count = 0;
    data = (unsigned char *)malloc(10000 * sizeof(unsigned char));
    fread(data, sizeof(unsigned char), 10000, f);
    for (int i = 0; i < 80; i++)
    {
        count++;
    }
    for (int i = 0; i < 4; i++)
    {
        dataV[i] = data[count];
        count++;
    }
    long long int num = *(unsigned int*)dataV;

    count = 0;
    delete data;
    fclose(f);
    f = fopen(fileName,"r");
    data = (unsigned char *)malloc((num+5)*50 * sizeof(unsigned char));
    fread(data, sizeof(unsigned char), (num+5)*50, f);
    for (int i = 0; i < 80; i++)
    {
        count++;
    }
    for (int i = 0; i < 4; i++)
    {
        dataV[i] = data[count];
        count++;
    }
    for (long long int i = 0; i < num; i++)
    {
        //cout << i << endl;
        float fl[12];
        vertex facet, p1, p2, p3;
        for (int j = 0; j < 12; j++)
        {
            char c[4];
            for (int k = 0; k < 4; k++)
            {
                dataV[k] = data[count];
                count++;
            }
            fl[j] = *(float*)dataV;
        }
        count++;
        count++;
        facet.x = fl[0];
        facet.y = fl[1];
        facet.z = fl[2];
        p1.x = fl[3];
        p1.y = fl[4];
        p1.z = fl[5];
        p2.x = fl[6];
        p2.y = fl[7];
        p2.z = fl[8];
        p3.x = fl[9];
        p3.y = fl[10];
        p3.z = fl[11];
        mod.facet.push_back(facet);
        mod.p1.push_back(p1);
        mod.p2.push_back(p2);
        mod.p3.push_back(p3);
    }
    delete data;
    fclose(f);
}

void MGLTools::drawStl(model &mod,float scale)//绘制STL文件,这种文件里其实储存的就是三角形的面以及其法向向量,因此十分好绘制
{
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glBegin(GL_TRIANGLES);
    for (int i = 0; i < mod.facet.size(); i++)
    {
        glNormal3f(mod.facet[i].x, mod.facet[i].y, mod.facet[i].z);
        glVertex3f(mod.p1[i].x , mod.p1[i].y / scale, mod.p1[i].z / scale);
        glVertex3f(mod.p2[i].x / scale, mod.p2[i].y / scale, mod.p2[i].z / scale);
        glVertex3f(mod.p3[i].x / scale, mod.p3[i].y / scale, mod.p3[i].z / scale);
    }
    glEnd();
}

float MGLTools::angBtPoints(float x1, float y1, float x2, float y2)//计算两点间夹角
{
    float ang;
    ang = atan2(y2-y1,x2-x1);
    //if(y1-y2<0)ang += 3.1415926;
    return ang;
}

float MGLTools::disBtPoints(float x1, float y1, float x2, float y2)
{
    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}

float RA(float ang)
{
    if(ang > 3.1415926)ang -= 3.1415926*2;
    if(ang < -3.1415926)ang += 3.1415926*2;
    return ang;
}

void MGLTools::initGL()
{
    glClearColor(0,0,0,0);//背景颜色黑色
    glColor3f(1,1,1);
    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHT1);
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值