利用openGL纯手工打造一个金字塔

Posted airduce

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用openGL纯手工打造一个金字塔相关的知识,希望对你有一定的参考价值。

环境:linux(ubuntu16.4)、gcc

第一步:先出一个三角形线框

  效果:

  

  实现代码:

    Makefile

BDIR = -L/usr/X11R6/lib
CC = gcc
CFLAGS = $(COMPILERFLAGS)
LIBRARIES = -lX11 -lXi  -lglut -lGL -lGLU -lm

pyramid : pyramid.o
    $(CC) $(CFLAGS) -o $@ $(LIBDIR) $? $(LIBRARIES)

clean:
    rm -f *.o

  pyramid.c

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>
#include <sys/time.h>
#include <math.h>
#define GL_PI 3.1415f

void RenderScene(void){
    //用线框绘制
    glPolygonMode(GL_FRONT,GL_LINE);
    //用当前颜色清除屏幕(也就是SetupRC中的 glClearColor 指定的颜色)
    glClear(GL_COLOR_BUFFER_BIT);

    //此三角形位于x、y轴的平面上
    glBegin(GL_TRIANGLES);
        glVertex3f(50.0f,0.0f,0.0f);//右顶点
        glVertex3f(0.0f,50.0f,0.0f);//上顶点
        glVertex3f(-50.0f,0.0f,0.0f);//左顶点
    glEnd();

    glutSwapBuffers();
}

void SetupRC()
    {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // 设置绘制颜色为绿色
    glColor3f(0.0f, 1.0f, 0.0f);
    }
void ChangeSize(int w, int h)
    {
    GLfloat nRange = 100.0f;

    // 防止清零
    if(h == 0)
        h = 1;

    // 设置视口大小为当前窗口
    glViewport(0, 0, w, h);

    //重置操作矩阵栈
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // 这是透视投影裁截体 (left, right, bottom, top, near, far)
    if (w <= h) 
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else 
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    //重置模型视图矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }


int main(int argc, char* argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("Pyramid Example");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    SetupRC();
    glutMainLoop();

    return 0;
    }

 第二步:实现旋转

  效果(当按上下左右箭头时实现旋转):

  

  实现代码:

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>

#include <sys/time.h>

#include <math.h>

#define GL_PI 3.1415f

static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;


void RenderScene(void){
    //用线框绘制
    glPolygonMode(GL_FRONT,GL_LINE);
    glPolygonMode(GL_BACK,GL_LINE);

    //用当前颜色清除屏幕(也就是SetupRC中的 glClearColor 指定的颜色)
    glClear(GL_COLOR_BUFFER_BIT);
    
    //保存当前操作矩阵
    glPushMatrix();

    //绕x轴旋转
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    //绕y轴旋转
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);


    //此三角形位于x、y轴的平面上
    glBegin(GL_TRIANGLES);
        glVertex3f(50.0f,0.0f,0.0f);//右顶点
        glVertex3f(0.0f,50.0f,0.0f);//上顶点
        glVertex3f(-50.0f,0.0f,0.0f);//左顶点
    glEnd();
    //恢复当前操作矩阵
    glPopMatrix();

    glutSwapBuffers();
}

void SetupRC()
    {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // 设置绘制颜色为绿色
    glColor3f(0.0f, 1.0f, 0.0f);
    }
void ChangeSize(int w, int h)
    {
    GLfloat nRange = 100.0f;

    // 防止清零
    if(h == 0)
        h = 1;

    // 设置视口大小为当前窗口
    glViewport(0, 0, w, h);

    //重置操作矩阵栈
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // 这是透视投影裁截体 (left, right, bottom, top, near, far)
    if (w <= h) 
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else 
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    //重置模型视图矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }
//控制键
void ControlKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        xRot-= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

    if(key > 356.0f)
        xRot = 0.0f;

    if(key < -1.0f)
        xRot = 355.0f;

    if(key > 356.0f)
        yRot = 0.0f;

    if(key < -1.0f)
        yRot = 355.0f;

    // Refresh the Window
    glutPostRedisplay();
    }

int main(int argc, char* argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("Pyramid Example");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(ControlKeys);
    glutDisplayFunc(RenderScene);

    SetupRC();
    glutMainLoop();

    return 0;
    }

 第三步:线框金字塔

  效果:红x轴,绿y轴,蓝z轴

  

  实现代码:

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>

#include <sys/time.h>

#include <math.h>

#define GL_PI 3.1415f

static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;


void RenderScene(void){
    //用线框绘制
    glPolygonMode(GL_FRONT,GL_LINE);
    glPolygonMode(GL_BACK,GL_LINE);

//    glEnable(GL_DEPTH_TEST);
    
    //用当前颜色清除屏幕(也就是SetupRC中的 glClearColor 指定的颜色)
    glClear(GL_COLOR_BUFFER_BIT);
    
    //保存当前操作矩阵
    glPushMatrix();

    //绕x轴旋转
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    //绕y轴旋转
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);
    
    //加宽线条    
    glLineWidth(3.0f);

    //金字塔底边长
    GLfloat len = 60.0f;
    
    //z轴点
    GLfloat vz = 2*len*cos(GL_PI/180*30);    
    
    //顶点的z轴点    
    GLfloat vhz = len*tan(GL_PI/180*30);
    //此三角形位于x、y轴的平面上
    glBegin(GL_TRIANGLES);
        glVertex3f(len,0.0f,0.0f);//前右
        glVertex3f(0.0f,len,-vhz);//顶点        
        glVertex3f(-len,0.0f,0.0f);//前左

        glVertex3f(0.0f,0.0f,-vz);//
                glVertex3f(0.0f,len,-vhz);//顶点
                glVertex3f(len,0.0f,0.0f);//前右
        
        glVertex3f(-len,0.0f,0.0f);//前左
                glVertex3f(0.0f,len,-vhz);//顶点
                glVertex3f(0.0f,0.0f,-vz);//
    
    glEnd();


    //绘制一个坐标系,
    GLint factor = 2;
    GLushort pattern = 0x5555;
    
    //启用点画    
    glEnable(GL_LINE_STIPPLE);
    //点画模式
        glLineStipple(factor,pattern);


    glLineWidth(1.0f);    

    glBegin(GL_LINES);
        //x轴
        glColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0);

        glVertex3f(-100.0f,0.0f,0.0f);
        glVertex3f(100.0f,0.0f,0.0f);
        
        glColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0);
        
        //y轴
        glVertex3f(0.0f,-100.0f,0.0f);
                glVertex3f(0.0f,100.0f,0.0f);
        
        //z轴
        glColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255);
        
        glVertex3f(0.0f,0.0f,-100.0f);
                glVertex3f(0.0f,0.0f,100.0f);
    glEnd();

    //关闭点画    
    glDisable(GL_LINE_STIPPLE);    
    //恢复当前操作矩阵
    glPopMatrix();

    glutSwapBuffers();
}

void SetupRC()
    {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // 设置绘制颜色为绿色
    glColor3f(0.0f, 1.0f, 0.0f);
    }
void ChangeSize(int w, int h)
    {
    GLfloat nRange = 100.0f;

    // 防止清零
    if(h == 0)
        h = 1;

    // 设置视口大小为当前窗口
    glViewport(0, 0, w, h);

    //重置操作矩阵栈
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // 这是透视投影裁截体 (left, right, bottom, top, near, far)
    if (w <= h) 
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else 
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    //重置模型视图矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }
//控制键
void controlKeys(int key, int x, int y)
    {
    if(key == GLUT_KEY_UP)
        xRot-= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

    if(key > 356.0f)
        xRot = 0.0f;

    if(key < -1.0f)
        xRot = 355.0f;

    if(key > 356.0f)
        yRot = 0.0f;

    if(key < -1.0f)
        yRot = 355.0f;

    // Refresh the Window
    glutPostRedisplay();
    }

int main(int argc, char* argv[])
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("Pyramid Example");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(controlKeys);
    glutDisplayFunc(RenderScene);

    SetupRC();
    glutMainLoop();

    return 0;
    }

 

  

以上是关于利用openGL纯手工打造一个金字塔的主要内容,如果未能解决你的问题,请参考以下文章

纯手工打造linux路由器

纯手工打造CPU的那些牛人们,欣赏令人叹为观止的纯手工布线和高超技

纯手工打造CPU的那些牛人们,欣赏令人叹为观止的纯手工布线和高超技

手写MyBatis,纯手工打造开源框架(第四篇:决胜千里)- 第272篇

史上最全面的纯手工打造 Vim 神器操作手册

纯手工打造一个 a.out (不使用编译器,就硬写)