#include <windows.h> // Header File For Windows
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The Glaux Library
#include <stdio.h>
#include <olectl.h>
#include <math.h>
#include <list>
int fps(72); //帧数
#include "Misc.h"
#include "Camera.h"
#include "3DS.h"
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
char* brand=NULL; //显卡型号
char* vendor=NULL; //显卡制造商
char* version=NULL; //版本号
float Noise1(int x, int y);
float SmoothNoise_1(int x, int y);
float Cosine_Interpolate(float a, float b, float x);
float InterpolatedNoise_1(float x, float y);
float PerlinNoise_2D(float x, float y);
GLuint texgrass;
GLuint texdot;
CCamera camera;
t3DModel skybox;
CVect3 EyePosition;
GLuint AllTerrain;
long pcount(0);
float angle;
vec axis;
/////////////////////////////////////////////////////////////////////////////////
//粒子的代码
const float K = 0.002f; //阻尼常数
const float G = 0.035f; //重力加速度
float GetRandom(float minv, float maxv)
{
return (float)rand()/RAND_MAX*(maxv-minv)+minv;
}
class FireDot
{
public:
float Mass; //粒子的质量
vec Pos; //火星粒子当前的位置
vec FirstCol; //颜色1
vec SecondCol; //颜色2
vec Speed; //粒子的速度
float Energy; //粒子能量,当能量为零时,粒子即死亡
float Size; //粒子尺寸
void Render();
};
void FireDot::Render()
{
//能量为零时就不画了。
if(Energy<=0.0f) return;
pcount++;
//绘制粒子
glPushMatrix();
glTranslatef(Pos.x, Pos.y, Pos.z);
glPushMatrix();
glRotatef(angle, axis.x, axis.y, axis.z);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texdot);
if(rand()%2==0)
glColor4f(FirstCol.x, FirstCol.y, FirstCol.z, Energy/100.0f);
else
glColor4f(SecondCol.x, SecondCol.y, SecondCol.z, Energy/100.0f);
glDepthMask(GL_FALSE);
glBegin(GL_QUADS);
glTexCoord2i(0, 1); glVertex3f(-Size, Size, 0.0f);
glTexCoord2i(0, 0); glVertex3f(-Size, -Size, 0.0f);
glTexCoord2i(1, 0); glVertex3f(Size, -Size, 0.0f);
glTexCoord2i(1, 1); glVertex3f(Size, Size, 0.0f);
glEnd();
glDepthMask(GL_TRUE);
glPopAttrib();
glPopMatrix();
glPopMatrix();
//更新位置
Pos+=Speed;
//能量减少
Energy-=10.0f;
}
std::list<FireDot> fireDot;
class PreExplose
{
public:
float Mass; //质量
vec Pos; //位置
vec Speed; //速度
float Energy; //能量, 能量为零时粒子就死亡
float Size; //尺寸
bool IsExplose;
void Render();
};
void PreExplose::Render()
{
//粒子死亡后就不渲染
if(Energy<=0.0f) return;
//添加FireDot粒子
//添加10个
FireDot newDot;
for(int i=0;i<1;i++)
{
newDot.Energy = Energy;
newDot.FirstCol.x = 1.0f;
newDot.FirstCol.y = 1.0f;
newDot.FirstCol.z = 1.0f;
newDot.SecondCol.x = 1.0f;
newDot.SecondCol.y = 1.0f;
newDot.SecondCol.z = 0.0f;
newDot.Mass = 0.0001f;
newDot.Size = Size;
newDot.Pos = Pos;
newDot.Speed.x = GetRandom(-0.05f, 0.05f);
newDot.Speed.y = GetRandom(-0.05f, 0.05f);
newDot.Speed.z = GetRandom(-0.05f, 0.05f);
fireDot.push_back(newDot);
}
//更新位置
//计算重力,沿Y轴向下
vec gravity(0.0f, -Mass*G, 0.0f);
//计算合力
vec resultantf = gravity;
//计算加速度
vec acc = resultantf/Mass;
//计算速度
Speed+=acc;
//更新位置
Pos+=Speed;
//能量减少
Energy-=2.0f;
}
std::list<PreExplose> preExplose;
void DrawFireworks()
{
std::list<FireDot>::iterator pFireDot;
std::list<PreExplose>::iterator pPreExplose;
//遍例链表,删除已经死亡的例子
for(pFireDot=fireDot.begin();pFireDot!=fireDot.end();pFireDot++)
{
if(pFireDot->Energy<=0.0f)
{
pFireDot=fireDot.erase(pFireDot);
}
}
for(pPreExplose=preExplose.begin();
pPreExplose!=preExplose.end();
pPreExplose++)
{
if(pPreExplose->Energy<=0.0f && pPreExplose->IsExplose==false)
{
//添加一个烟花爆炸
PreExplose newExplose;
for(int i=0;i<80;i++)
{
newExplose.Pos.x = pPreExplose->Pos.x;
newExplose.Pos.y = pPreExplose->Pos.y;
newExplose.Pos.z = pPreExplose->Pos.z;
newExplose.Mass = 0.1f;
newExplose.Energy = GetRandom(90.0f, 100.0f);
newExplose.Size = 1.5f;
newExplose.Speed.x = GetRandom(-1.0f, 1.0f);
newExplose.Speed.y = GetRandom(-1.0f, 1.0f);
newExplose.Speed.z = GetRandom(-1.0f, 1.0f);
newExplose.IsExplose = true;
preExplose.push_back(newExplose);
}
}
if(pPreExplose->Energy<=0.0f)
pPreExplose=preExplose.erase(pPreExplose);
}
//渲染
for(pFireDot=fireDot.begin();pFireDot!=fireDot.end();pFireDot++)
{
pFireDot->Render();
}
for(pPreExplose=preExplose.begin();
pPreExplose!=preExplose.end();
pPreExplose++)
{
pPreExplose->Render();
}
//开始添加新的PreExplose单元
//限制下数量,最大50
static int ccount=0;
//fps = preExplose.size();
if(preExplose.size()>10) return;
ccount++;
if(ccount<fps*0.8f) return;
ccount=0;
PreExplose newDot;
//随机一个位置
newDot.Pos.x = GetRandom(50.0f, 60.0f);
newDot.Pos.y = 6.0f;
newDot.Pos.z = GetRandom(50.0f, 60.0f);
//确定质量
newDot.Mass = 0.9f;
//初始能量
newDot.Energy = GetRandom(95.0f, 100.0f);
//初始速度
newDot.Speed.x = GetRandom(-0.4f, 0.4f);
newDot.Speed.y = GetRandom(2.3f, 3.3f);
newDot.Speed.z = GetRandom(-0.4f, 0.4f);
newDot.Size = 1.0f;
newDot.IsExplose = false;
preExplose.push_back(newDot);
}
////////////////////////////////////////////////////////////////////////////////////
struct Terrain
{
float x, y, z;
float s, t;
float norx, nory, norz;
};
Terrain terrain[250][250];
void initTerrain()
{
for(int x=0;x<=249;x++)
for(int z=0;z<=249;z++)
{
terrain[x][z].x =(float)(x- 125)*4.0f;
terrain[x][z].y =25.0f*PerlinNoise_2D((x+10000)/10.0f, (z+10000)/10.0f);
terrain[x][z].z =(float)(z- 125)*4.0f;
terrain[x][z].s =x/15.0f;
terrain[x][z].t =z/15.0f;
}
for(x=0;x<=249;x++)
for(int z=0;z<=249;z++)
{
if(x>0 && z>0 && x<249 && z<249)
{
vec v1;
v1.x=terrain[x+1][z].y - terrain[x-1][z].y;
v1.y= 0.5f;
v1.z=terrain[x][z+1].y - terrain[x][z-1].y;
v1.Normalize();
terrain[x][z].norx =v1.x;
terrain[x][z].nory =v1.y;
terrain[x][z].norz =v1.z;
}
else
{
terrain[x][z].norx =0.0f;
terrain[x][z].nory =1.0f;
terrain[x][z].norz =0.0f;
}
}
}
//计算BILLBOARD, 算转角和转轴
void CalcTheBillboard()
{
vec eyepos(EyePosition.x-56, EyePosition.y-30, EyePosition.z-56);
vec face(0.0f, 0.0f, -1.0f);
eyepos.Normalize();
//计算转角
angle = acos(eyepos % face)*180.0f/3.14159f;
//计算转轴
axis = eyepos * face;
axis = -axis;
axis.Normalize();
}
void DrawModel(t3DModel& Model);
void DrawTerrain()
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texgrass);
for(int z=0;z<=248;z++)
{
glBegin(GL_QUAD_STRIP);
for(int x=0;x<=249;x++)
{
glNormal3f(terrain[x][z].norx , terrain[x][z].nory , terrain[x][z].norz);
glTexCoord2f(terrain[x][z].s, terrain[x][z].t);
glVertex3f(terrain[x][z].x, terrain[x][z].y, terrain[x][z].z);
glNormal3f(terrain[x][z+1].norx , terrain