我正在尝试使用粒子系统制作降雪模拟效果,我的意思是让粒子随机方向和随机起点和随机速度移动。以下代码示例具有沿x轴旋转30度的粒子。任何人都可以指出我需要在哪里进行更改才能进行降雪模拟
//A single particle.
struct Particle {
Vec3f pos;
Vec3f velocity;
Vec3f color;
float timeAlive; //The time that this particle has been alive.
float lifespan; //The total time that this particle is to live.
};
//Rotates the vector by the indicated number of degrees about the specified axis
Vec3f rotate(Vec3f v, Vec3f axis, float degrees) {
axis = axis.normalize();
float radians = degrees * PI / 180;
float s = sin(radians);
float c = cos(radians);
return v * c + axis * axis.dot(v) * (1 - c) + v.cross(axis) * s;
}
//Returns the position of the particle, after rotating the camera
Vec3f adjParticlePos(Vec3f pos) {
return rotate(pos, Vec3f(1, 0, 0), -30);
}
//Returns whether particle1 is in back of particle2
bool compareParticles(Particle* particle1, Particle* particle2) {
return adjParticlePos(particle1->pos)[2] < adjParticlePos(particle2->pos)[2];
}
const float GRAVITY = 2.5f;
const int NUM_PARTICLES = 1000;
//steps.
const float STEP_TIME = 0.01f;
//length of each side of the square drawn -> for each particle.
const float PARTICLE_SIZE = 0.025f;
class SnowCreator {
private:
GLuint textureId;
Particle particles[NUM_PARTICLES];
// time to next call of step function
float timeToStepFunc;
float colorTime; // color in a specific time
//Returns the current color to white
Vec3f curColor() {
Vec3f color;
if (colorTime <= 1.0f){
color = Vec3f(1.0f, 1.0f, 1.0f);
}
return color;
}
//Returns the average velocity of particles
Vec3f curVelocity() {
return Vec3f((randomFloat() + 1) * cos(angle), 2.0f,
(randomFloat() + 1) * sin(angle));
}
//Alters p to be a particle newly produced.
void snowParticle(Particle* p) {
p->pos = Vec3f( randomFloat(), randomFloat(), randomFloat());
p->velocity = curVelocity() + Vec3f(0.5f * randomFloat() - 0.25f,
0.5f * randomFloat() - 0.25f,
0.5f * randomFloat() - 0.25f);
p->color = curColor();
p->timeAlive = 0;
p->lifespan = randomFloat() + 2; //help in fading
}
//Advances the particle by STEP_TIME seconds.
void step() {
colorTime += STEP_TIME / 10;
while (colorTime >= 1) {
colorTime -= 1;
}
angle += 0.5f * STEP_TIME;
while (angle > 2 * PI) {
angle -= 2 * PI;
}
for(int i = 0; i < NUM_PARTICLES; i++) {
Particle* p = particles + i;
p->pos += p->velocity * STEP_TIME;
p->velocity += Vec3f(0.0f,-GRAVITY * STEP_TIME, 0.0f);
p->timeAlive += STEP_TIME;
if (p->timeAlive > p->lifespan) {
snowParticle(p);
}
}
}
public:
SnowCreator(GLuint textureId1) {
textureId = textureId1;
timeToStepFunc = 0;
colorTime = 0;
angle = 0;
for(int i = 0; i < NUM_PARTICLES; i++) {
snowParticle(particles + i);
}
for(int i = 0; i < 10 / STEP_TIME; i++) {
step();
}
}
//Advances the particle fountain by the specified amount of time.
void advance(float dt) {
while (dt > 0) {
if (timeToStepFunc < dt) {
dt -= timeToStepFunc;
step();
timeToStepFunc = STEP_TIME;
}
else {
timeToStepFunc -= dt;
dt = 0;
}
}
}
//Draws the particle fountain.
void draw() {
vector<Particle*> ps;
for(int i = 0; i < NUM_PARTICLES; i++) {
ps.push_back(particles + i);
}
sort(ps.begin(), ps.end(), compareParticles);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBegin(GL_QUADS);
for(unsigned int i = 0; i < ps.size(); i++) {
Particle* p = ps[i];
glColor3f(p->color[0], p->color[1], p->color[2]);
float size = PARTICLE_SIZE / 2;
Vec3f pos = adjParticlePos(p->pos);
glTexCoord2f(0, 0);
glVertex3f(pos[0] - size, pos[1] - size, pos[2]);
glTexCoord2f(0, 1);
glVertex3f(pos[0] - size, pos[1] + size, pos[2]);
glTexCoord2f(1, 1);
glVertex3f(pos[0] + size, pos[1] + size, pos[2]);
glTexCoord2f(1, 0);
glVertex3f(pos[0] + size, pos[1] - size, pos[2]);
}
glEnd();
}
};