//CTexture类在第8章,
//CSkyBox在第24章,
//那个GL_Application可以忽略,直接在主函数中生成dos窗口运行,
#include <GL/glut.h>
#include <GLTOOLS.H>
#include <GL/OpenGLSB.h>
#include <stdlib.h>
#include <math.h>
#define SNOWFLAKE_VX 0.0f
#define SNOWFLAKE_VY -3.0f
#define SNOWFLAKE_VZ 0.0f
#define V_CHANGEX 0.2f
#define V_CHANGEY 0.5f
#define V_CHANGEZ 0.2f
#define FRAND (((float)rand()-(float)rand())/RAND_MAX)
#define SNOWFLAKE_SIZE 0.02f
#define SNOWFLAKES_PER_SEC 2000
#define NUM_TEXTURES 3
GLuint textureObjects[NUM_TEXTURES];
struct SnowFlake
{
float x, y, z; //当前位置
float pre_x, pre_y, pre_z; //上次位置
float v_x, v_y, v_z; //速度
float a_x, a_y, a_z; //加速度
float lifetime; //生命值
float size; //尺寸大小
float sizeDelta; //尺寸变化量
float red, green, blue; //颜色
};
struct SnowSystem
{
SnowFlake* snowList; //雪花链表
int maxSnow; //雪花总数目
int numSnow; //雪花当前数目
float origin_x, origin_y, origin_z; //系统中心
float height, width, depth;
float accumulatedTime; //消逝时间
}S_system;
const char *szCubeFaces[6] = {"pos_x.tga", "neg_x.tga", "pos_y.tga",
"neg_y.tga", "pos_z.tga", "neg_z.tga" };
GLenum cube[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
void CreateSystem(int m_snow, float x, float y, float z,
float height, float width, float depth)
{
S_system.maxSnow = m_snow;
S_system.origin_x = x;
S_system.origin_y = y;
S_system.origin_z = z;
S_system.height = height;
S_system.width = width;
S_system.depth = depth;
S_system.snowList = NULL;
}
void InitSystem()
{
if(S_system.snowList)
{
delete[] S_system.snowList;
S_system.snowList = NULL;
}
S_system.snowList = new SnowFlake[S_system.maxSnow];
S_system.numSnow = 0;
S_system.accumulatedTime = 0.0f;
}
void InitSnowFlake(int index)
{
//设置雪花位置
S_system.snowList[index].y = S_system.height;
S_system.snowList[index].x = S_system.origin_x + FRAND * S_system.width;
S_system.snowList[index].z = S_system.origin_z + FRAND * S_system.depth;
//设置雪花大小
S_system.snowList[index].size = SNOWFLAKE_SIZE;
//设置雪花随机速度
S_system.snowList[index].v_x = SNOWFLAKE_VX + FRAND * V_CHANGEX;
S_system.snowList[index].v_y = SNOWFLAKE_VY + FRAND * V_CHANGEY;
S_system.snowList[index].v_z = SNOWFLAKE_VZ + FRAND * V_CHANGEZ;
}
int Emit(int num)
{
while(num && (S_system.numSnow < S_system.maxSnow))
{
InitSnowFlake(S_system.numSnow ++);
-- num;
}
return num;
}
void UpdateSystem(float elapsedTime)
{
for(int i = 0; i < S_system.numSnow; )
{
//更新粒子位置
S_system.snowList[i].x = S_system.snowList[i].x +
S_system.snowList[i].v_x * elapsedTime;
S_system.snowList[i].y = S_system.snowList[i].y +
S_system.snowList[i].v_y * elapsedTime;
S_system.snowList[i].z = S_system.snowList[i].x +
S_system.snowList[i].v_z * elapsedTime;
//检测已消逝粒子
if(S_system.snowList[i].y <= S_system.origin_y)
{
//移动最后粒子到当前位置
S_system.snowList[i] = S_system.snowList[--S_system.numSnow];
}
else ++ i;
}
//存储消逝时间
S_system.accumulatedTime += elapsedTime;
//计算新粒子数目
int newSnowFlakes = SNOWFLAKES_PER_SEC * S_system.accumulatedTime;
//保存时间
S_system.accumulatedTime -= 1.0f/(float)SNOWFLAKES_PER_SEC * newSnowFlakes;
Emit(newSnowFlakes);
}
void SetupRC()
{
GLbyte *pBytes;
GLint iWidth, iHeight, iComponents;
GLenum eFormat;
int i;
// Cull backs of polygons
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
// Set up texture maps
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Load Cube Map images
for(i = 0; i < 6; i++)
{
// Load this texture map
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
pBytes = gltLoadTGA(szCubeFaces[i], &iWidth, &iHeight, &iComponents, &eFormat);
glTexImage2D(cube[i], 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);
}
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
// Enable cube mapping, and set texture environment to decal
glEnable(GL_TEXTURE_CUBE_MAP);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}
void ShutdownRC(void)
{
// Delete the textures
glDeleteTextures(NUM_TEXTURES, textureObjects);
}
void DrawSkyBox()
{
GLfloat fExtent = 15.0f;
glBegin(GL_QUADS);
//Negative X
glTexCoord3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-fExtent, -fExtent, fExtent);
glTexCoord3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-fExtent, -fExtent, -fExtent);
glTexCoord3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-fExtent, fExtent, -fExtent);
glTexCoord3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-fExtent, fExtent, fExtent);
//Postive X
glTexCoord3f(1.0f, -1.0f, -1.0f);
glVertex3f(fExtent, -fExtent, -fExtent);
glTexCoord3f(1.0f, -1.0f, 1.0f);
glVertex3f(fExtent, -fExtent, fExtent);
glTexCoord3f(1.0f, 1.0f, 1.0f);
glVertex3f(fExtent, fExtent, fExtent);
glTexCoord3f(1.0f, 1.0f, -1.0f);
glVertex3f(fExtent, fExtent, -fExtent);
// Negative Z
glTexCoord3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-fExtent, -fExtent, -fExtent);
glTexCoord3f(1.0f, -1.0f, -1.0f);
glVertex3f(fExtent, -fExtent, -fExtent);
glTexCoord3f(1.0f, 1.0f, -1.0f);
glVertex3f(fExtent, fExtent, -fExtent);
glTexCoord3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-fExtent, fExtent, -fExtent);
// Positive Z
glTexCoord3f(1.0f, -1.0f, 1.0f);
glVertex3f(fExtent, -fExtent, fExtent);
glTexCoord3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-fExtent, -fExtent, fExtent);
glTexCoord3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-fExtent, fExtent, fExtent);
glTexCoord3f(1.0f, 1.0f, 1.0f);
glVertex3f(fExtent, fExtent, fExtent);
// Positive Y
glTexCoord3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-fExtent, fExtent, fExtent);
glTexCoord3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-fExtent, fExtent, -fExtent);
glTexCoord3f(1.0f, 1.0f, -1.0f);
glVertex3f(fExtent, fExtent, -fExtent);
glTexCoord3f(1.0f, 1.0f, 1.0f);
glVertex3f(fExtent, fExtent, fExtent);
// Negative Y
glTexCoord3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-fExtent, -fExtent, -fExtent);
glTexCoord3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-fExtent, -fExtent, fExtent);
glTexCoord3f(1.0f, -1.0f, 1.0f);
glVertex3f(fExtent, -fExtent, fExtent);
glTexCoord3f(1.0f, -1.0f, -1.0f);
glVertex3f(fExtent, -fExtent, -fExtent);
glEnd();
}
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
DrawSkyBox();
glPopMatrix();
glutSwapBuffers();
}
void ChangeSize(int