mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge pull request #6014 from ctrlaltdavid/20699
Sanitize particle properties, fix crashes
This commit is contained in:
commit
a6e1fbd50f
5 changed files with 261 additions and 55 deletions
|
@ -28,7 +28,7 @@
|
|||
FAST_EMIT_SPEED = 1.0,
|
||||
GRAVITY_EMIT_ACCELERATON = { x: 0.0, y: -0.3, z: 0.0 },
|
||||
ZERO_EMIT_ACCELERATON = { x: 0.0, y: 0.0, z: 0.0 },
|
||||
PI = 3.141593,
|
||||
PI = 3.141592,
|
||||
DEG_TO_RAD = PI / 180.0,
|
||||
NUM_PARTICLE_EXAMPLES = 18;
|
||||
|
||||
|
|
|
@ -620,7 +620,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(textColor, xColor, setTextColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, xColor, setBackgroundColor);
|
||||
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isEmitting, bool, setIsEmitting);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate);
|
||||
|
@ -1320,7 +1320,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
|
||||
if (properties.getType() == EntityTypes::ParticleEffect) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, quint32, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTING_PARTICLES, bool, setIsEmitting);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate);
|
||||
|
|
|
@ -173,6 +173,10 @@ typedef QVector<glm::vec3> qVectorVec3;
|
|||
typedef QVector<float> qVectorFloat;
|
||||
inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); }
|
||||
inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); }
|
||||
inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) {
|
||||
// Use QString::toUInt() so that isValid is set to false if the number is outside the quint32 range.
|
||||
return v.toString().toUInt(&isValid);
|
||||
}
|
||||
inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); }
|
||||
inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); }
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
//
|
||||
// ParticleEffectEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
|
@ -31,8 +30,6 @@
|
|||
#include <glm/gtx/transform.hpp>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <Interpolate.h>
|
||||
|
@ -46,27 +43,53 @@
|
|||
const glm::vec3 X_AXIS = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
const glm::vec3 Z_AXIS = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work
|
||||
|
||||
const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 };
|
||||
const xColor ParticleEffectEntityItem::DEFAULT_COLOR_SPREAD = { 0, 0, 0 };
|
||||
const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f;
|
||||
const float ParticleEffectEntityItem::DEFAULT_ALPHA_SPREAD = 0.0f;
|
||||
const float ParticleEffectEntityItem::DEFAULT_ALPHA_START = DEFAULT_ALPHA;
|
||||
const float ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA;
|
||||
const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f;
|
||||
const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000;
|
||||
const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1;
|
||||
const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000;
|
||||
const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f;
|
||||
const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day
|
||||
const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f;
|
||||
const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f;
|
||||
const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f;
|
||||
const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3
|
||||
const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f;
|
||||
const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical
|
||||
const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point
|
||||
const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE;
|
||||
const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0)
|
||||
const float ParticleEffectEntityItem::MINIMUM_EMIT_RADIUS_START = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_EMIT_RADIUS_START = 1.0f;
|
||||
const float ParticleEffectEntityItem::MINIMUM_POLAR = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_POLAR = SCRIPT_MAXIMUM_PI;
|
||||
const float ParticleEffectEntityItem::DEFAULT_POLAR_START = 0.0f; // Emit along z-axis
|
||||
const float ParticleEffectEntityItem::DEFAULT_POLAR_FINISH = 0.0f; // ""
|
||||
const float ParticleEffectEntityItem::MINIMUM_AZIMUTH = -SCRIPT_MAXIMUM_PI;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_AZIMUTH = SCRIPT_MAXIMUM_PI;
|
||||
const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_START = -PI; // Emit full circumference (when polarFinish > 0)
|
||||
const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_FINISH = PI; // ""
|
||||
const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f);
|
||||
const float ParticleEffectEntityItem::MINIMUM_EMIT_ACCELERATION = -100.0f; // ~ 10g
|
||||
const float ParticleEffectEntityItem::MAXIMUM_EMIT_ACCELERATION = 100.0f;
|
||||
const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f);
|
||||
const float ParticleEffectEntityItem::MINIMUM_ACCELERATION_SPREAD = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_ACCELERATION_SPREAD = 100.0f;
|
||||
const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f;
|
||||
const float ParticleEffectEntityItem::MINIMUM_PARTICLE_RADIUS = 0.0f;
|
||||
const float ParticleEffectEntityItem::MAXIMUM_PARTICLE_RADIUS = (float)TREE_SCALE;
|
||||
const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f;
|
||||
const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS;
|
||||
const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS;
|
||||
|
@ -111,37 +134,177 @@ ParticleEffectEntityItem::~ParticleEffectEntityItem() {
|
|||
}
|
||||
|
||||
|
||||
void ParticleEffectEntityItem::setAlpha(float alpha) {
|
||||
if (MINIMUM_ALPHA <= alpha && alpha <= MAXIMUM_ALPHA) {
|
||||
_alpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAlphaStart(float alphaStart) {
|
||||
if (MINIMUM_ALPHA <= alphaStart && alphaStart <= MAXIMUM_ALPHA) {
|
||||
_alphaStart = alphaStart;
|
||||
_isAlphaStartInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAlphaFinish(float alphaFinish) {
|
||||
if (MINIMUM_ALPHA <= alphaFinish && alphaFinish <= MAXIMUM_ALPHA) {
|
||||
_alphaFinish = alphaFinish;
|
||||
_isAlphaFinishInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAlphaSpread(float alphaSpread) {
|
||||
if (MINIMUM_ALPHA <= alphaSpread && alphaSpread <= MAXIMUM_ALPHA) {
|
||||
_alphaSpread = alphaSpread;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setLifespan(float lifespan) {
|
||||
if (MINIMUM_LIFESPAN <= lifespan && lifespan <= MAXIMUM_LIFESPAN) {
|
||||
_lifespan = lifespan;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitRate(float emitRate) {
|
||||
if (MINIMUM_EMIT_RATE <= emitRate && emitRate <= MAXIMUM_EMIT_RATE) {
|
||||
_emitRate = emitRate;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitSpeed(float emitSpeed) {
|
||||
_emitSpeed = emitSpeed;
|
||||
computeAndUpdateDimensions();
|
||||
if (MINIMUM_EMIT_SPEED <= emitSpeed && emitSpeed <= MAXIMUM_EMIT_SPEED) {
|
||||
_emitSpeed = emitSpeed;
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) {
|
||||
_speedSpread = speedSpread;
|
||||
computeAndUpdateDimensions();
|
||||
if (MINIMUM_EMIT_SPEED <= speedSpread && speedSpread <= MAXIMUM_EMIT_SPEED) {
|
||||
_speedSpread = speedSpread;
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation) {
|
||||
_emitOrientation = emitOrientation;
|
||||
_emitOrientation = glm::normalize(emitOrientation);
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
|
||||
|
||||
void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions) {
|
||||
_emitDimensions = emitDimensions;
|
||||
computeAndUpdateDimensions();
|
||||
bool updated = false;
|
||||
if (MINIMUM_EMIT_DIMENSION <= emitDimensions.x && emitDimensions.x <= MAXIMUM_EMIT_DIMENSION) {
|
||||
_emitDimensions.x = emitDimensions.x;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_EMIT_DIMENSION <= emitDimensions.y && emitDimensions.y <= MAXIMUM_EMIT_DIMENSION) {
|
||||
_emitDimensions.y = emitDimensions.y;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_EMIT_DIMENSION <= emitDimensions.z && emitDimensions.z <= MAXIMUM_EMIT_DIMENSION) {
|
||||
_emitDimensions.z = emitDimensions.z;
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitRadiusStart(float emitRadiusStart) {
|
||||
if (MINIMUM_EMIT_RADIUS_START <= emitRadiusStart && emitRadiusStart <= MAXIMUM_EMIT_RADIUS_START) {
|
||||
_emitRadiusStart = emitRadiusStart;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setPolarStart(float polarStart) {
|
||||
if (MINIMUM_POLAR <= polarStart && polarStart <= MAXIMUM_POLAR) {
|
||||
_polarStart = polarStart;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setPolarFinish(float polarFinish) {
|
||||
if (MINIMUM_POLAR <= polarFinish && polarFinish <= MAXIMUM_POLAR) {
|
||||
_polarFinish = polarFinish;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAzimuthStart(float azimuthStart) {
|
||||
if (MINIMUM_AZIMUTH <= azimuthStart && azimuthStart <= MAXIMUM_AZIMUTH) {
|
||||
_azimuthStart = azimuthStart;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAzimuthFinish(float azimuthFinish) {
|
||||
if (MINIMUM_AZIMUTH <= azimuthFinish && azimuthFinish <= MAXIMUM_AZIMUTH) {
|
||||
_azimuthFinish = azimuthFinish;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) {
|
||||
_emitAcceleration = emitAcceleration;
|
||||
computeAndUpdateDimensions();
|
||||
bool updated = false;
|
||||
if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.x && emitAcceleration.x <= MAXIMUM_EMIT_ACCELERATION) {
|
||||
_emitAcceleration.x = emitAcceleration.x;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.y && emitAcceleration.y <= MAXIMUM_EMIT_ACCELERATION) {
|
||||
_emitAcceleration.y = emitAcceleration.y;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.z && emitAcceleration.z <= MAXIMUM_EMIT_ACCELERATION) {
|
||||
_emitAcceleration.z = emitAcceleration.z;
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){
|
||||
_accelerationSpread = accelerationSpread;
|
||||
computeAndUpdateDimensions();
|
||||
bool updated = false;
|
||||
if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.x && accelerationSpread.x <= MAXIMUM_ACCELERATION_SPREAD) {
|
||||
_accelerationSpread.x = accelerationSpread.x;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.y && accelerationSpread.y <= MAXIMUM_ACCELERATION_SPREAD) {
|
||||
_accelerationSpread.y = accelerationSpread.y;
|
||||
updated = true;
|
||||
}
|
||||
if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.z && accelerationSpread.z <= MAXIMUM_ACCELERATION_SPREAD) {
|
||||
_accelerationSpread.z = accelerationSpread.z;
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
computeAndUpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setParticleRadius(float particleRadius) {
|
||||
if (MINIMUM_PARTICLE_RADIUS <= particleRadius && particleRadius <= MAXIMUM_PARTICLE_RADIUS) {
|
||||
_particleRadius = particleRadius;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusStart(float radiusStart) {
|
||||
if (MINIMUM_PARTICLE_RADIUS <= radiusStart && radiusStart <= MAXIMUM_PARTICLE_RADIUS) {
|
||||
_radiusStart = radiusStart;
|
||||
_isRadiusStartInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusFinish(float radiusFinish) {
|
||||
if (MINIMUM_PARTICLE_RADIUS <= radiusFinish && radiusFinish <= MAXIMUM_PARTICLE_RADIUS) {
|
||||
_radiusFinish = radiusFinish;
|
||||
_isRadiusFinishInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) {
|
||||
if (MINIMUM_PARTICLE_RADIUS <= radiusSpread && radiusSpread <= MAXIMUM_PARTICLE_RADIUS) {
|
||||
_radiusSpread = radiusSpread;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ParticleEffectEntityItem::computeAndUpdateDimensions() {
|
||||
const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error
|
||||
|
||||
|
@ -485,12 +648,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
_particleLifetimes[i] -= deltaTime;
|
||||
|
||||
// if particle has died.
|
||||
if (_particleLifetimes[i] <= 0.0f) {
|
||||
if (_particleLifetimes[i] <= 0.0f || _lifespan == 0.0f) {
|
||||
// move head forward
|
||||
_particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles;
|
||||
}
|
||||
else {
|
||||
float age = (1.0f - _particleLifetimes[i] / _lifespan); // 0.0 .. 1.0
|
||||
float age = 1.0f - _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0
|
||||
updateRadius(i, age);
|
||||
updateColor(i, age);
|
||||
updateAlpha(i, age);
|
||||
|
@ -500,7 +663,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
}
|
||||
|
||||
// emit new particles, but only if we are emmitting
|
||||
if (isEmittingParticles()) {
|
||||
if (isEmittingParticles() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) {
|
||||
|
||||
float timeLeftInFrame = deltaTime;
|
||||
while (_timeUntilNextEmit < timeLeftInFrame) {
|
||||
|
@ -518,10 +681,18 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
_radiusMiddles[i] =_particleRadius;
|
||||
_radiusFinishes[i] = getRadiusFinish();
|
||||
} else {
|
||||
float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius;
|
||||
_radiusStarts[i] = spreadMultiplier * getRadiusStart();
|
||||
_radiusMiddles[i] = spreadMultiplier * _particleRadius;
|
||||
_radiusFinishes[i] = spreadMultiplier * getRadiusFinish();
|
||||
float spreadMultiplier;
|
||||
if (_particleRadius > 0.0f) {
|
||||
spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius;
|
||||
} else {
|
||||
spreadMultiplier = 1.0f;
|
||||
}
|
||||
_radiusStarts[i] =
|
||||
glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
_radiusMiddles[i] =
|
||||
glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
_radiusFinishes[i] =
|
||||
glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS);
|
||||
}
|
||||
updateRadius(i, 0.0f);
|
||||
|
||||
|
@ -530,8 +701,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
// Emit along z-axis from position
|
||||
_particlePositions[i] = getPosition();
|
||||
_particleVelocities[i] =
|
||||
(_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS);
|
||||
_particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread;
|
||||
(_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS);
|
||||
_particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread;
|
||||
|
||||
} else {
|
||||
// Emit around point or from ellipsoid
|
||||
|
@ -547,15 +718,14 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
if (_azimuthFinish >= _azimuthStart) {
|
||||
azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat();
|
||||
} else {
|
||||
azimuth = _azimuthStart + (2.0f * PI + _azimuthFinish - _azimuthStart) * randFloat();
|
||||
azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat();
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 emitDirection;
|
||||
|
||||
if (_emitDimensions == glm::vec3()) {
|
||||
// Point
|
||||
emitDirection = glm::angleAxis(PI_OVER_TWO - elevation, X_AXIS) * Z_AXIS;
|
||||
emitDirection = glm::angleAxis(azimuth, Z_AXIS) * emitDirection;
|
||||
emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Z_AXIS;
|
||||
|
||||
_particlePositions[i] = getPosition();
|
||||
} else {
|
||||
|
@ -563,7 +733,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
float radiusScale = 1.0f;
|
||||
if (_emitRadiusStart < 1.0f) {
|
||||
float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center
|
||||
float randRadius = emitRadiusStart + (1.0f - emitRadiusStart) * randFloat();
|
||||
float randRadius =
|
||||
emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart);
|
||||
radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f);
|
||||
}
|
||||
|
||||
|
@ -582,8 +753,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
}
|
||||
|
||||
_particleVelocities[i] =
|
||||
(_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * emitDirection);
|
||||
_particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread;
|
||||
(_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection);
|
||||
_particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread;
|
||||
}
|
||||
integrateParticle(i, timeLeftInFrame);
|
||||
extendBounds(_particlePositions[i]);
|
||||
|
@ -598,10 +769,13 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
xColor middleColor = getXColor();
|
||||
xColor finishColor = getColorFinish();
|
||||
|
||||
float spread = 2.0f * randFloat() - 1.0f;
|
||||
float spreadMultiplierRed = 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red;
|
||||
float spreadMultiplierGreen = 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green;
|
||||
float spreadMultiplierBlue = 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue;
|
||||
float spread = randFloatInRange(-1.0f, 1.0f);
|
||||
float spreadMultiplierRed =
|
||||
middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f;
|
||||
float spreadMultiplierGreen =
|
||||
middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f;
|
||||
float spreadMultiplierBlue =
|
||||
middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f;
|
||||
|
||||
_colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f);
|
||||
_colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f);
|
||||
|
@ -623,7 +797,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
_alphaMiddles[i] = _alpha;
|
||||
_alphaFinishes[i] = getAlphaFinish();
|
||||
} else {
|
||||
float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1) * _alphaSpread / _alpha;
|
||||
float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha;
|
||||
_alphaStarts[i] = spreadMultiplier * getAlphaStart();
|
||||
_alphaMiddles[i] = spreadMultiplier * _alpha;
|
||||
_alphaFinishes[i] = spreadMultiplier * getAlphaFinish();
|
||||
|
@ -645,7 +819,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
|||
}
|
||||
|
||||
void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
|
||||
if (_maxParticles != maxParticles) {
|
||||
if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) {
|
||||
_maxParticles = maxParticles;
|
||||
|
||||
// TODO: try to do something smart here and preserve the state of existing particles.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define hifi_ParticleEffectEntityItem_h
|
||||
|
||||
#include <AnimationLoop.h>
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class ParticleEffectEntityItem : public EntityItem {
|
||||
|
@ -69,22 +70,25 @@ public:
|
|||
void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; }
|
||||
xColor getColorSpread() const { return _colorSpread; }
|
||||
|
||||
static const float MAXIMUM_ALPHA;
|
||||
static const float MINIMUM_ALPHA;
|
||||
|
||||
static const float DEFAULT_ALPHA;
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
void setAlpha(float alpha);
|
||||
float getAlpha() const { return _alpha; }
|
||||
|
||||
static const float DEFAULT_ALPHA_START;
|
||||
bool _isAlphaStartInitialized = false;
|
||||
void setAlphaStart(float alphaStart) { _alphaStart = alphaStart; _isAlphaStartInitialized = true; }
|
||||
void setAlphaStart(float alphaStart);
|
||||
float getAlphaStart() const { return _isAlphaStartInitialized ? _alphaStart : _alpha; }
|
||||
|
||||
static const float DEFAULT_ALPHA_FINISH;
|
||||
bool _isAlphaFinishInitialized = false;
|
||||
void setAlphaFinish(float alphaFinish) { _alphaFinish = alphaFinish; _isAlphaFinishInitialized = true; }
|
||||
void setAlphaFinish(float alphaFinish);
|
||||
float getAlphaFinish() const { return _isAlphaFinishInitialized ? _alphaFinish : _alpha; }
|
||||
|
||||
static const float DEFAULT_ALPHA_SPREAD;
|
||||
void setAlphaSpread(float alphaSpread) { _alphaSpread = alphaSpread; }
|
||||
void setAlphaSpread(float alphaSpread);
|
||||
float getAlphaSpread() const { return _alphaSpread; }
|
||||
|
||||
void updateShapeType(ShapeType type);
|
||||
|
@ -97,18 +101,26 @@ public:
|
|||
void setIsEmitting(bool isEmitting) { _isEmitting = isEmitting; }
|
||||
|
||||
static const quint32 DEFAULT_MAX_PARTICLES;
|
||||
static const quint32 MINIMUM_MAX_PARTICLES;
|
||||
static const quint32 MAXIMUM_MAX_PARTICLES;
|
||||
void setMaxParticles(quint32 maxParticles);
|
||||
quint32 getMaxParticles() const { return _maxParticles; }
|
||||
|
||||
static const float DEFAULT_LIFESPAN;
|
||||
void setLifespan(float lifespan) { _lifespan = lifespan; }
|
||||
static const float MINIMUM_LIFESPAN;
|
||||
static const float MAXIMUM_LIFESPAN;
|
||||
void setLifespan(float lifespan);
|
||||
float getLifespan() const { return _lifespan; }
|
||||
|
||||
static const float DEFAULT_EMIT_RATE;
|
||||
void setEmitRate(float emitRate) { _emitRate = emitRate; }
|
||||
static const float MINIMUM_EMIT_RATE;
|
||||
static const float MAXIMUM_EMIT_RATE;
|
||||
void setEmitRate(float emitRate);
|
||||
float getEmitRate() const { return _emitRate; }
|
||||
|
||||
static const float DEFAULT_EMIT_SPEED;
|
||||
static const float MINIMUM_EMIT_SPEED;
|
||||
static const float MAXIMUM_EMIT_SPEED;
|
||||
void setEmitSpeed(float emitSpeed);
|
||||
float getEmitSpeed() const { return _emitSpeed; }
|
||||
|
||||
|
@ -121,53 +133,69 @@ public:
|
|||
const glm::quat& getEmitOrientation() const { return _emitOrientation; }
|
||||
|
||||
static const glm::vec3 DEFAULT_EMIT_DIMENSIONS;
|
||||
static const float MINIMUM_EMIT_DIMENSION;
|
||||
static const float MAXIMUM_EMIT_DIMENSION;
|
||||
void setEmitDimensions(const glm::vec3& emitDimensions);
|
||||
const glm::vec3& getEmitDimensions() const { return _emitDimensions; }
|
||||
|
||||
static const float DEFAULT_EMIT_RADIUS_START;
|
||||
void setEmitRadiusStart(float emitRadiusStart) { _emitRadiusStart = emitRadiusStart; }
|
||||
static const float MINIMUM_EMIT_RADIUS_START;
|
||||
static const float MAXIMUM_EMIT_RADIUS_START;
|
||||
void setEmitRadiusStart(float emitRadiusStart);
|
||||
float getEmitRadiusStart() const { return _emitRadiusStart; }
|
||||
|
||||
static const float MINIMUM_POLAR;
|
||||
static const float MAXIMUM_POLAR;
|
||||
|
||||
static const float DEFAULT_POLAR_START;
|
||||
void setPolarStart(float polarStart) { _polarStart = polarStart; }
|
||||
void setPolarStart(float polarStart);
|
||||
float getPolarStart() const { return _polarStart; }
|
||||
|
||||
static const float DEFAULT_POLAR_FINISH;
|
||||
void setPolarFinish(float polarFinish) { _polarFinish = polarFinish; }
|
||||
void setPolarFinish(float polarFinish);
|
||||
float getPolarFinish() const { return _polarFinish; }
|
||||
|
||||
static const float MINIMUM_AZIMUTH;
|
||||
static const float MAXIMUM_AZIMUTH;
|
||||
|
||||
static const float DEFAULT_AZIMUTH_START;
|
||||
void setAzimuthStart(float azimuthStart) { _azimuthStart = azimuthStart; }
|
||||
void setAzimuthStart(float azimuthStart);
|
||||
float getAzimuthStart() const { return _azimuthStart; }
|
||||
|
||||
static const float DEFAULT_AZIMUTH_FINISH;
|
||||
void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = azimuthFinish; }
|
||||
void setAzimuthFinish(float azimuthFinish);
|
||||
float getAzimuthFinish() const { return _azimuthFinish; }
|
||||
|
||||
static const glm::vec3 DEFAULT_EMIT_ACCELERATION;
|
||||
static const float MINIMUM_EMIT_ACCELERATION;
|
||||
static const float MAXIMUM_EMIT_ACCELERATION;
|
||||
void setEmitAcceleration(const glm::vec3& emitAcceleration);
|
||||
const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; }
|
||||
|
||||
static const glm::vec3 DEFAULT_ACCELERATION_SPREAD;
|
||||
static const float MINIMUM_ACCELERATION_SPREAD;
|
||||
static const float MAXIMUM_ACCELERATION_SPREAD;
|
||||
void setAccelerationSpread(const glm::vec3& accelerationSpread);
|
||||
const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; }
|
||||
|
||||
static const float DEFAULT_PARTICLE_RADIUS;
|
||||
void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; }
|
||||
static const float MINIMUM_PARTICLE_RADIUS;
|
||||
static const float MAXIMUM_PARTICLE_RADIUS;
|
||||
void setParticleRadius(float particleRadius);
|
||||
float getParticleRadius() const { return _particleRadius; }
|
||||
|
||||
static const float DEFAULT_RADIUS_START;
|
||||
bool _isRadiusStartInitialized = false;
|
||||
void setRadiusStart(float radiusStart) { _radiusStart = radiusStart; _isRadiusStartInitialized = true; }
|
||||
void setRadiusStart(float radiusStart);
|
||||
float getRadiusStart() const { return _isRadiusStartInitialized ? _radiusStart : _particleRadius; }
|
||||
|
||||
static const float DEFAULT_RADIUS_FINISH;
|
||||
bool _isRadiusFinishInitialized = false;
|
||||
void setRadiusFinish(float radiusFinish) { _radiusFinish = radiusFinish; _isRadiusFinishInitialized = true; }
|
||||
void setRadiusFinish(float radiusFinish);
|
||||
float getRadiusFinish() const { return _isRadiusFinishInitialized ? _radiusFinish : _particleRadius; }
|
||||
|
||||
static const float DEFAULT_RADIUS_SPREAD;
|
||||
void setRadiusSpread(float radiusSpread) { _radiusSpread = radiusSpread; }
|
||||
void setRadiusSpread(float radiusSpread);
|
||||
float getRadiusSpread() const { return _radiusSpread; }
|
||||
|
||||
void computeAndUpdateDimensions();
|
||||
|
|
Loading…
Reference in a new issue