particle system - spawn shape - closes #634

This commit is contained in:
Mikulas Florek 2015-12-18 21:23:51 +01:00
parent f3e9da4f0b
commit ebff4da0c8
5 changed files with 141 additions and 3 deletions

View file

@ -40,7 +40,8 @@ static ParticleEmitter::ModuleBase* createModule(uint32 type, ParticleEmitter& e
{ ParticleEmitter::AlphaModule::s_type, create<ParticleEmitter::AlphaModule> },
{ ParticleEmitter::RandomRotationModule::s_type, create<ParticleEmitter::RandomRotationModule> },
{ ParticleEmitter::SizeModule::s_type, create<ParticleEmitter::SizeModule> },
{ ParticleEmitter::AttractorModule::s_type, create<ParticleEmitter::AttractorModule> }
{ ParticleEmitter::AttractorModule::s_type, create<ParticleEmitter::AttractorModule> },
{ ParticleEmitter::SpawnShapeModule::s_type, create<ParticleEmitter::SpawnShapeModule> }
};
for(auto& i : creators)
@ -257,6 +258,54 @@ void ParticleEmitter::PlaneModule::deserialize(InputBlob& blob)
const uint32 ParticleEmitter::PlaneModule::s_type = Lumix::crc32("plane");
ParticleEmitter::SpawnShapeModule::SpawnShapeModule(ParticleEmitter& emitter)
: ModuleBase(emitter)
, m_radius(1.0f)
, m_shape(SPHERE)
{
}
void ParticleEmitter::SpawnShapeModule::spawnParticle(int index)
{
static const float INV = 1.0f / RAND_MAX;
// ugly and ~0.1% from uniform distribution, but still faster than the correct solution
float r2 = m_radius * m_radius;
for (int i = 0; i < 10; ++i)
{
Vec3 v
(
m_radius * (2 * rand() * INV - 1.0f),
m_radius * (2 * rand() * INV - 1.0f),
m_radius * (2 * rand() * INV - 1.0f)
);
if (v.squaredLength() < r2)
{
m_emitter.m_position[index] += v;
return;
}
}
}
void ParticleEmitter::SpawnShapeModule::serialize(OutputBlob& blob)
{
blob.write(m_shape);
blob.write(m_radius);
}
void ParticleEmitter::SpawnShapeModule::deserialize(InputBlob& blob)
{
blob.read(m_shape);
blob.read(m_radius);
}
const uint32 ParticleEmitter::SpawnShapeModule::s_type = Lumix::crc32("spawn_shape");
ParticleEmitter::LinearMovementModule::LinearMovementModule(ParticleEmitter& emitter)
: ModuleBase(emitter)
{

View file

@ -75,6 +75,25 @@ public:
};
struct LUMIX_RENDERER_API SpawnShapeModule : public ModuleBase
{
SpawnShapeModule(ParticleEmitter& emitter);
void spawnParticle(int index) override;
void serialize(OutputBlob& blob) override;
void deserialize(InputBlob& blob) override;
uint32 getType() const override { return s_type; }
static const uint32 s_type;
enum Shape : uint8
{
SPHERE
};
float m_radius;
Shape m_shape;
};
struct LUMIX_RENDERER_API LinearMovementModule : public ModuleBase
{
LinearMovementModule(ParticleEmitter& emitter);

View file

@ -48,6 +48,8 @@ static const uint32 PARTICLE_EMITTER_FORCE_HASH = crc32("particle_emitter_force"
static const uint32 PARTICLE_EMITTER_ATTRACTOR_HASH = crc32("particle_emitter_attractor");
static const uint32 PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH =
crc32("particle_emitter_linear_movement");
static const uint32 PARTICLE_EMITTER_SPAWN_SHAPE_HASH =
crc32("particle_emitter_spawn_shape");
static const uint32 PARTICLE_EMITTER_PLANE_HASH =
crc32("particle_emitter_plane");
static const uint32 PARTICLE_EMITTER_RANDOM_ROTATION_HASH =
@ -520,12 +522,17 @@ public:
m_universe.addComponent(
emitter->m_entity, PARTICLE_EMITTER_FADE_HASH, this, i);
}
else if(module->getType() == ParticleEmitter::ForceModule::s_type)
else if (module->getType() == ParticleEmitter::ForceModule::s_type)
{
m_universe.addComponent(
emitter->m_entity, PARTICLE_EMITTER_FORCE_HASH, this, i);
}
else if(module->getType() == ParticleEmitter::AttractorModule::s_type)
else if (module->getType() == ParticleEmitter::SpawnShapeModule::s_type)
{
m_universe.addComponent(
emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, i);
}
else if (module->getType() == ParticleEmitter::AttractorModule::s_type)
{
m_universe.addComponent(
emitter->m_entity, PARTICLE_EMITTER_ATTRACTOR_HASH, this, i);
@ -996,6 +1003,23 @@ public:
}
void destroyParticleEmitterSpawnShape(ComponentIndex component)
{
auto* emitter = m_particle_emitters[component];
for (auto* module : emitter->m_modules)
{
if (module->getType() == ParticleEmitter::SpawnShapeModule::s_type)
{
LUMIX_DELETE(m_allocator, module);
emitter->m_modules.eraseItem(module);
m_universe.destroyComponent(
emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, component);
break;
}
}
}
void destroyParticleEmitterRandomRotation(ComponentIndex component)
{
auto* emitter = m_particle_emitters[component];
@ -1275,6 +1299,23 @@ public:
}
ComponentIndex createParticleEmitterSpawnShape(Entity entity)
{
for (int i = 0; i < m_particle_emitters.size(); ++i)
{
auto* emitter = m_particle_emitters[i];
if (emitter->m_entity == entity)
{
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SpawnShapeModule)(*emitter);
emitter->addModule(module);
m_universe.addComponent(entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, i);
return i;
}
}
return INVALID_COMPONENT;
}
ComponentIndex createParticleEmitterFade(Entity entity)
{
for (int i = 0; i < m_particle_emitters.size(); ++i)
@ -2911,6 +2952,20 @@ public:
}
float getParticleEmitterShapeRadius(ComponentIndex cmp) override
{
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
return module ? module->m_radius : 0.0f;
}
void setParticleEmitterShapeRadius(ComponentIndex cmp, float value) override
{
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
if (module) module->m_radius = value;
}
int getParticleEmitterPlaneCount(ComponentIndex cmp) override
{
auto* module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
@ -3151,6 +3206,9 @@ static struct
{PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH,
&RenderSceneImpl::createParticleEmitterLinearMovement,
&RenderSceneImpl::destroyParticleEmitterLinearMovement},
{PARTICLE_EMITTER_SPAWN_SHAPE_HASH,
&RenderSceneImpl::createParticleEmitterSpawnShape,
&RenderSceneImpl::destroyParticleEmitterSpawnShape },
{PARTICLE_EMITTER_RANDOM_ROTATION_HASH,
&RenderSceneImpl::createParticleEmitterRandomRotation,
&RenderSceneImpl::destroyParticleEmitterRandomRotation},

View file

@ -218,6 +218,8 @@ public:
virtual void setParticleEmitterPlaneEntity(ComponentIndex cmp, int index, Entity entity) = 0;
virtual float getParticleEmitterPlaneBounce(ComponentIndex cmp) = 0;
virtual void setParticleEmitterPlaneBounce(ComponentIndex cmp, float value) = 0;
virtual float getParticleEmitterShapeRadius(ComponentIndex cmp) = 0;
virtual void setParticleEmitterShapeRadius(ComponentIndex cmp, float value) = 0;
virtual int getParticleEmitterAttractorCount(ComponentIndex cmp) = 0;
virtual void addParticleEmitterAttractor(ComponentIndex cmp, int index) = 0;

View file

@ -245,6 +245,7 @@ void registerRendererProperties(Lumix::WorldEditor& editor)
PropertyRegister::registerComponentType("global_light", "Global light");
PropertyRegister::registerComponentType("renderable", "Mesh");
PropertyRegister::registerComponentType("particle_emitter", "Particle emitter");
PropertyRegister::registerComponentType("particle_emitter_spawn_shape", "Particle emitter - spawn shape");
PropertyRegister::registerComponentType("particle_emitter_fade", "Particle emitter - fade");
PropertyRegister::registerComponentType("particle_emitter_plane", "Particle emitter - plane");
PropertyRegister::registerComponentType("particle_emitter_force", "Particle emitter - force");
@ -264,6 +265,15 @@ void registerRendererProperties(Lumix::WorldEditor& editor)
PropertyRegister::registerComponentDependency(
"particle_emitter_random_rotation", "particle_emitter");
PropertyRegister::add("particle_emitter_spawn_shape",
LUMIX_NEW(allocator, DecimalPropertyDescriptor<RenderScene>)("Radius",
&RenderScene::getParticleEmitterShapeRadius,
&RenderScene::setParticleEmitterShapeRadius,
0.0f,
FLT_MAX,
0.01f,
allocator));
PropertyRegister::add("particle_emitter_plane",
LUMIX_NEW(allocator, DecimalPropertyDescriptor<RenderScene>)("Bounce",
&RenderScene::getParticleEmitterPlaneBounce,