commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
275
include/engine/core/emitter.cpp
Normal file
275
include/engine/core/emitter.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/emitter.h"
|
||||
#include "core/camera.h"
|
||||
#include "core/resource_factories.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/render_resource_factory.h"
|
||||
#include "timing/benchmark.h"
|
||||
#include "rand/rand.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
ParticleModel::ParticleModel()
|
||||
{
|
||||
gravity.Set(0, 0, 0);
|
||||
|
||||
SetColor(Color(1, 1, 1, 1));
|
||||
// size_curve.SetDefaultValue(1);
|
||||
|
||||
time_to_live.setSec(4.f);
|
||||
damping = 1.f;
|
||||
}
|
||||
void ParticleModel::SetColor(const Color &color)
|
||||
{
|
||||
// red_curve.SetDefaultValue(color.x);
|
||||
// green_curve.SetDefaultValue(color.y);
|
||||
// blue_curve.SetDefaultValue(color.z);
|
||||
// opacity_curve.SetDefaultValue(color.w);
|
||||
}
|
||||
void ParticleModel::AddColorPoint(const Time &t, const Color &color)
|
||||
{
|
||||
red_curve.Insert(CurvePoint(t, color.x));
|
||||
green_curve.Insert(CurvePoint(t, color.y));
|
||||
blue_curve.Insert(CurvePoint(t, color.z));
|
||||
opacity_curve.Insert(CurvePoint(t, color.w));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ParticleModel::RenderSetup(ResourceFactories *f)
|
||||
{
|
||||
if ((render_data = new RenderData) != NULL)
|
||||
if (f && f->render)
|
||||
render_data->material = f->render->LoadMaterial(material);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Emitter::ComputeMinMax(MinMax &minmax) const
|
||||
{
|
||||
minmax.mn = minmax.mx = GetMatrix().GetRow(3);
|
||||
if (!GetParticleCount())
|
||||
return;
|
||||
|
||||
for (uint n = 0; n < GetParticleCount(); ++n)
|
||||
{
|
||||
Particle *p = GetParticle(n);
|
||||
minmax.Grow(MinMax(p->position - Vector4(p->size, p->size, p->size), p->position + Vector4(p->size, p->size, p->size)));
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Emitter::GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Renderable::Context context, bool cull)
|
||||
{
|
||||
if (cull)
|
||||
{
|
||||
MinMax minmax;
|
||||
ComputeMinMax(minmax);
|
||||
|
||||
if (view.frustum.ClassifyMinMax(minmax) == Frustum::Outside)
|
||||
return 1;
|
||||
}
|
||||
|
||||
is_seen = true;
|
||||
|
||||
const Matrix4 &vm = view.GetMatrix();
|
||||
list.Push(new Render::Primitive(this, this, vm.GetRow(2).Dot(GetMatrix().GetRow(3) - vm.GetRow(3))));
|
||||
|
||||
return 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Emitter::Sort(const Matrix4 &view)
|
||||
{
|
||||
if (!particle_pool || !is_seen)
|
||||
return;
|
||||
|
||||
Vector4 view_front = view.GetRow(2).Normalized(),
|
||||
view_pos = view.GetRow(3);
|
||||
|
||||
alive_count = 0;
|
||||
for (uint n = 0; n < particle_pool.GetCount(); ++n)
|
||||
if (particle_pool[n].IsAlive())
|
||||
{
|
||||
sort_array[alive_count].v = (particle_pool[n].position - view_pos).Dot(view_front);
|
||||
sort_array[alive_count].o = n;
|
||||
alive_count++;
|
||||
}
|
||||
|
||||
GS::Sort <float, uint> ::QuickSort(alive_count, sort_array);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Emitter::Update(const Time &dt)
|
||||
{
|
||||
if (!particle_pool || !is_seen)
|
||||
return;
|
||||
|
||||
// Spawn particles.
|
||||
uint n = 0;
|
||||
for (birth_time += dt * birth_rate * birth_rate_scale; birth_time.toSec() > 1; birth_time -= Time::fromSec(1))
|
||||
{
|
||||
// Seek next free particle.
|
||||
for ( ; n < particle_pool.GetCount(); ++n)
|
||||
if (particle_pool[n].time.toSec() < 0)
|
||||
break;
|
||||
|
||||
// Emitter pool exhausted.
|
||||
if (n == particle_pool.GetCount())
|
||||
break;
|
||||
|
||||
// Spawn particle.
|
||||
Particle &p = particle_pool[n];
|
||||
|
||||
p.time = birth_time / birth_rate;
|
||||
p.angle = 0;
|
||||
p.size = 0;
|
||||
p.color.Set(0, 0, 0, 0);
|
||||
|
||||
ModelParticle(p, *this, time);
|
||||
}
|
||||
|
||||
// Update running particles and drop dead ones.
|
||||
if (render_data.IsValid())
|
||||
if (ParticleModel *model = render_data->particle_model)
|
||||
{
|
||||
float damping = Math::Pow(model->damping, dt.toSec());
|
||||
|
||||
for (n = 0; n < particle_pool.GetCount(); ++n)
|
||||
{
|
||||
Particle &p = particle_pool[n];
|
||||
if (!p.IsAlive())
|
||||
continue;
|
||||
|
||||
// Kill particle.
|
||||
p.time += dt;
|
||||
|
||||
if (p.time >= model->time_to_live)
|
||||
p.time.setSec(-1);
|
||||
|
||||
else
|
||||
{
|
||||
float k_dt = dt.toSec();
|
||||
|
||||
p.position += p.velocity * k_dt;
|
||||
p.velocity += render_data->particle_model->gravity * k_dt;
|
||||
p.velocity *= damping;
|
||||
|
||||
model->size_curve.Evaluate(p.time, &p.size);
|
||||
model->angle_curve.Evaluate(p.time, &p.angle);
|
||||
|
||||
model->red_curve.Evaluate(p.time, &p.color.x);
|
||||
model->green_curve.Evaluate(p.time, &p.color.y);
|
||||
model->blue_curve.Evaluate(p.time, &p.color.z);
|
||||
model->opacity_curve.Evaluate(p.time, &p.color.w);
|
||||
|
||||
p.size *= p.size_scale;
|
||||
p.color.w *= p.opacity_scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_seen = false;
|
||||
time += dt;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Emitter::RenderSetup(ResourceFactories *f)
|
||||
{
|
||||
if ((render_data = new RenderData) != NULL)
|
||||
if (f && f->graphic)
|
||||
if ((render_data->particle_model = f->graphic->LoadParticleModel(particle_model)) != NULL)
|
||||
render_data->particle_model->RenderSetup(f);
|
||||
}
|
||||
bool Emitter::Setup()
|
||||
{
|
||||
alive_count = 0;
|
||||
if (!particle_pool.Allocate(pool_size) || !sort_array.Allocate(pool_size))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate emitter particle pool (size " << pool_size << ").\n", false)
|
||||
|
||||
for (uint n = 0; n < pool_size; ++n)
|
||||
particle_pool[n].time.setSec(-1);
|
||||
|
||||
time.setSec(0);
|
||||
birth_time.setSec(0);
|
||||
|
||||
is_seen = true;
|
||||
return true;
|
||||
}
|
||||
void Emitter::Free()
|
||||
{
|
||||
particle_pool.Free();
|
||||
sort_array.Free();
|
||||
alive_count = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Emitter::SetSprayModel(float angle)
|
||||
{
|
||||
model = Model_Spray;
|
||||
spray_angle = angle;
|
||||
}
|
||||
void Emitter::ModelParticle(Particle &p, const Item &i, const Time &/*emitter_time*/)
|
||||
{
|
||||
Vector4 ip = i.GetMatrix().GetRow(3);
|
||||
|
||||
switch (model)
|
||||
{
|
||||
default:
|
||||
p.position = ip;
|
||||
p.velocity.Set(0, 0, 0);
|
||||
break;
|
||||
|
||||
case Model_Spray:
|
||||
{
|
||||
p.position = ip;
|
||||
|
||||
using namespace Random;
|
||||
|
||||
float a = (FRand(2.f) - 1.f) * spray_angle;
|
||||
Vector4 d(Math::Sin(a), 0, Math::Cos(a));
|
||||
Matrix3::RotationMatrixZAxis(FRand(Units::Deg(360.f))).Apply(&p.velocity, &d);
|
||||
p.velocity = (p.velocity.Normalized() * FRRand(birth_speed_min, birth_speed_max)) * birth_speed_scale * Matrix3::FromMatrix4(i.GetMatrix());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
p.size_scale = birth_size_scale;
|
||||
p.opacity_scale = birth_opacity_scale;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Emitter::Emitter()
|
||||
{
|
||||
is_seen = true;
|
||||
|
||||
birth_speed_min = 1;
|
||||
birth_speed_max = 1.5;
|
||||
pool_size = 500;
|
||||
birth_rate = (float)pool_size / Units::Sec(5.f);
|
||||
|
||||
birth_rate_scale = 1;
|
||||
birth_opacity_scale = 1;
|
||||
birth_speed_scale = 1;
|
||||
birth_size_scale = 1;
|
||||
|
||||
SetSprayModel(Units::Deg(45.f));
|
||||
|
||||
alive_count = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user