3ds模型的天空

在《OpenGL--天空盒》为基础模板来实现。把SkyBox.h,SkyBox.cpp复制过来,由于不用 CBMPLoader(天空盒的bmp图太大,用jpg),对这两个文件略着修改.

SkyBox.h:

//2,天空盒实现类

//SkyBox.h   开始
#ifndef __SKYBOX_H__
#define __SKYBOX_H__

#include <stdio.h>
//#include "CBMPLoader.h"

#include "Vector.h"
#include "Camera.h"

#define GL_CLAMP_TO_EDGE    0x812F
int BuildTexture(char *szPathName, GLuint &texid);//这个函数在其它cpp上

/* 天空盒类 */
class CSkyBox
{
public:
    /* 构造函数 */
    CSkyBox();
    ~CSkyBox();

    /* 初始化 */
    bool Init();

    /* 渲染天空 */
    void  CreateSkyBox(float x, float y, float z, 
                       float width, float height, 
                       float length);

private:

    GLuint  m_texture[6];   /*< 天空盒纹理 */

};


#endif ///__SKYBOX_H__
//SkyBox.h   结束
SkyBox.cpp:

#include "SkyBox.h"

CSkyBox::CSkyBox()
{
}

CSkyBox::~CSkyBox()
{
    /* 删除纹理对象及其占用的内存 */
    for(int i =0 ;i< 6; i++)
    {
        //m_texture[i].FreeImage();
        glDeleteTextures(1,&m_texture[i]);
    }

}

/* 天空盒初始化 */
bool CSkyBox::Init()
{
    char filename[128] ;                                         /*< 用来保存文件名 */
    char *bmpName[] = { "back","front","bottom","top","left","right"};
    for(int i=0; i< 6; i++)
    {
        sprintf(filename,"%s",bmpName[i]);//注意路径??把你的jpg文件放在相应文件夹中
        strcat(filename,".jpg");//bmp

        //if(!m_texture[i].LoadBitmap(filename))                     /*< 载入位图文件 */
		if(!BuildTexture(filename, m_texture[i]))
        {
            //MessageBox(NULL, (LPCWSTR)"装载位图文件失败!", (LPCWSTR)"错误", MB_OK);    /*< 如果载入失败则弹出对话框 * 这句乱码用下句 */ 
            MessageBox(NULL, TEXT("装载位图文件失败!"),  TEXT("错误"), MB_OK);    /*< 如果载入失败则弹出对话框 */
            exit(0);
        }
        //glGenTextures(1, &m_texture[i].ID);                        /*< 生成一个纹理对象名称 */

        //glBindTexture(GL_TEXTURE_2D, m_texture[i].ID);             /*< 创建纹理对象 */
        ///* 控制滤波: */
        ///*
        //    其中GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T通常可设置为GL_REPEAT或GL_CLAMP两种方式。
        //    当待填充的多边形大于纹理的时候,GL_REPEAT表示多余的部分用重复的方式填充;GL_CLAMP表示多余的部分用相连边缘的相邻像素填充。
        //    在实际绘制中,我们一般采用GL_CLAMP_EDGE来处理,这就消除了接缝处的细线,增强了天空盒的真实感。
        //*/
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);  
        //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        ///* 创建纹理 */
        //gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, m_texture[i].imageWidth,
        //                m_texture[i].imageHeight, GL_RGB, GL_UNSIGNED_BYTE,
        //                m_texture[i].image);
    }
    return true;

}




/* 构造天空盒 */ 
void  CSkyBox::CreateSkyBox(float x, float y, float z, 
                            float box_width, float box_height,
                            float box_length)
{
	//定义地面网格 
	const unsigned int MAP_WIDTH = 1024; 
	const unsigned int CELL_WIDTH = 16; 
	const unsigned int MAP = MAP_WIDTH * CELL_WIDTH / 2;

   /* 获得场景中光照状态 */
    GLboolean lp;
    glGetBooleanv(GL_LIGHTING,&lp);

    /* 计算天空盒长 宽 高 */
    float width = MAP * box_width/8;
    float height = MAP * box_height/8;
    float length = MAP * box_length/8;

    /* 计算天空盒中心位置 */
    x = x+ MAP/8 - width  / 2;
    y = y+ MAP/24 - height / 2;
    z = z+ MAP/8 - length / 2;

    glDisable(GL_LIGHTING);            /*< 关闭光照 */

    /* 开始绘制 */
    glPushMatrix();
    glTranslatef(-x,-y,-z);

    /* 绘制背面 */
    glBindTexture(GL_TEXTURE_2D, m_texture[0]);

    glBegin(GL_QUADS);      

        /* 指定纹理坐标和顶点坐标 */
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,          z);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x,         y + height, z);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x,         y,          z);

    glEnd();

    /* 绘制前面 */
    glBindTexture(GL_TEXTURE_2D, m_texture[1]);

    glBegin(GL_QUADS);  

        /* 指定纹理坐标和顶点坐标 */
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x,         y,          z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x,         y + height, z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,          z + length);

    glEnd();

    /* 绘制底面 */
    //glBindTexture(GL_TEXTURE_2D, m_texture[2]);

    //glBegin(GL_QUADS);      

    //    /* 指定纹理坐标和顶点坐标 */
    //    glTexCoord2f(1.0f, 0.0f); glVertex3f(x,         y,          z);
    //    glTexCoord2f(1.0f, 1.0f); glVertex3f(x,         y,          z + length);
    //    glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y,          z + length); 
    //    glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,          z);

    //glEnd();

    /* 绘制顶面 */
    glBindTexture(GL_TEXTURE_2D, m_texture[3]);

    glBegin(GL_QUADS);      

        /* 指定纹理坐标和顶点坐标 */
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x,         y + height, z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x,         y + height, z);

    glEnd();

    /* 绘制左面 */
    glBindTexture(GL_TEXTURE_2D, m_texture[4]);

    glBegin(GL_QUADS);      

        /* 指定纹理坐标和顶点坐标 */
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x,         y + height, z); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x,         y + height, z + length); 
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x,         y,          z + length);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x,         y,          z);     

    glEnd();

    /* 绘制右面 */
    glBindTexture(GL_TEXTURE_2D, m_texture[5]);

    glBegin(GL_QUADS);      

        /* 指定纹理坐标和顶点坐标 */
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,          z);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,          z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
    glEnd();

    glPopMatrix();                 /* 绘制结束 */

    if(lp)                         /* 恢复光照状态 */  
        glEnable(GL_LIGHTING);

}

主cpp:

在void display(void)中,相对于天空盒,要加以平移和缩放:

#include <stdio.h>
//1,主程序:
#include<gl/glut.h>
#include<gl/glu.h>
#include<gl/gl.h>

#include "motionModel.h"

#include "Camera.h"
#include "SkyBox.h"

/** 定义光源的属性值 */
GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };    /**< 环境光参数 */
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };    /**< 漫射光参数 */
GLfloat LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };   /**< 镜面光参数 */
GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };   /**< 光源位置 */

Camera m_Camera;
CSkyBox m_SkyBox;

bool LoadTexture();

void init(void)
{
    /* 用户自定义的初始化过程 */
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    /* 启用纹理 */
    glEnable(GL_TEXTURE_2D);

	    /** 载入纹理 */
    //if (!LoadTexture())
    //    MessageBox(NULL, (LPCWSTR)"载入纹理失败!", (LPCWSTR)"错误", MB_OK);

	ModelInit();


    /* 初始化天空 */
    if (!m_SkyBox.Init())
    {
        //MessageBox(NULL, (LPCWSTR)"初始化天空失败!", (LPCWSTR)"错误", MB_OK);
        MessageBox(NULL, L"初始化天空失败!", L"错误", MB_OK);
        exit(0);
    }
	    
    /** 设置光源的属性值 */
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);     /**< 设置环境光 */
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);     /**< 设置漫射光 */
    glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);   /**< 设置漫射光 */
    glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);   /**< 设置光源位置 */

	glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT1);


    /* 设置摄像机 */
    m_Camera.setCamera(500, 35, 400, 501, 35, 400, 0, 1, 0);
    //m_Camera.setCamera(0.0f, 1.5f, 6.0f, 0.0f, 1.5f, 0.0f, 0.0f, 1.0f, 0.0f);

	m_Camera.setViewByMouse();

}

void display(void)
{
    /* 用户自定义的绘制过程 */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    /* 放置摄像机 */
    m_Camera.setLook();

    /* 绘制天空 */
    m_SkyBox.CreateSkyBox(0, 0, 0, 1.0, 0.5, 1.0);

	//DrawGrid2();
    //DrawBox();
    glPushAttrib(GL_CURRENT_BIT);   /**< 保存当前属性 */
	glPushMatrix();

	//由于相对于天空盒所以要加以平移和缩放
    glTranslatef(600.0f, 22.0f, 600.0f);//平移:表示将当前图形向x轴平移5,向y轴平移-2,向z轴平移-10
    glScalef(12.0f, 12.0f, 12.0f);//缩放:表示将当前图形沿x,y,z轴分别放大为原来的12倍
	drawAllModel();//绘制所有模型

    glPopMatrix();
    glPopAttrib();

    glFlush();                   /*< 强制执行所有的OpenGL命令 */
}

void ChangeSize(int width, int height)
{
    glViewport(0, 0, width, height);                                    /*< 重新设置视口 */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 4000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void motion(int x, int y)
{
    m_Camera.setViewByMouse();

    glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
        case 27:
            exit(0);
            break;
        case '1':
            m_Camera.setSpeed(0.2f);
            break;
        case '2':
            m_Camera.setSpeed(1.0f);
            break;
        case 'w':
            m_Camera.moveCamera(m_Camera.getSpeed());
            break;
        case 's':
            m_Camera.moveCamera(-m_Camera.getSpeed());
            break;
        case 'a':
            m_Camera.yawCamera(-m_Camera.getSpeed());
            break;
        case 'd':
            m_Camera.yawCamera(m_Camera.getSpeed());
            break;
    }

    glutPostRedisplay();
    printf("key::%d\n", key);
}


int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB);
    glutInitWindowSize(800, 600);
    glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) >> 1) - 400, (GetSystemMetrics(SM_CYSCREEN) >> 1) - 300);
    glutCreateWindow("天空盒");
    init();
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(display);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}
效果图:

由于该博文并没有天空盒图。如需要更好的请自己另找。

附天空图,分别是"back","front","bottom","top","left","right":

好,全文完。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值