Add new radiusSpread entity particle property

This commit is contained in:
David Rowe 2015-09-03 12:43:36 -07:00
parent a701ae0553
commit 45ff118249
8 changed files with 69 additions and 30 deletions

View file

@ -168,52 +168,63 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) {
updateRenderItem();
}
static glm::vec3 zSortAxis;
static bool zSort(const glm::vec3& rhs, const glm::vec3& lhs) {
return glm::dot(rhs, ::zSortAxis) > glm::dot(lhs, ::zSortAxis);
}
uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24);
}
class PositionAndRadius {
public:
PositionAndRadius(glm::vec3 position, float radius) : position(position), radius(radius) { }
glm::vec3 position;
float radius;
};
static glm::vec3 zSortAxis;
static bool zSort(const PositionAndRadius& rhs, const PositionAndRadius& lhs) {
return glm::dot(rhs.position, ::zSortAxis) > glm::dot(lhs.position, ::zSortAxis);
}
void RenderableParticleEffectEntityItem::updateRenderItem() {
if (!_scene) {
return;
}
float particleRadius = getParticleRadius();
//float particleRadius = _particleRadiuses[i];
auto xcolor = getXColor();
auto alpha = (uint8_t)(glm::clamp(getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f);
auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha);
// make a copy of each particle position
std::vector<glm::vec3> positions;
positions.reserve(getLivingParticleCount());
// make a copy of each particle position and radius
std::vector<PositionAndRadius> positionsAndRadiuses;
positionsAndRadiuses.reserve(getLivingParticleCount());
for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) {
positions.push_back(_particlePositions[i]);
positionsAndRadiuses.push_back(PositionAndRadius(_particlePositions[i], _particleRadiuses[i]));
}
// sort particles back to front
// NOTE: this is view frustum might be one frame out of date.
auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum();
::zSortAxis = frustum->getDirection();
qSort(positions.begin(), positions.end(), zSort);
qSort(positionsAndRadiuses.begin(), positionsAndRadiuses.end(), zSort);
// allocate vertices
_vertices.clear();
// build vertices from particle positions
const glm::vec3 upOffset = frustum->getUp() * particleRadius;
const glm::vec3 rightOffset = frustum->getRight() * particleRadius;
for (auto&& pos : positions) {
const glm::vec3 up = frustum->getUp();
const glm::vec3 right = frustum->getRight();
for (auto&& particle : positionsAndRadiuses) {
glm::vec3 upOffset = up * particle.radius;
glm::vec3 rightOffset = right * particle.radius;
// generate corners of quad aligned to face the camera.
_vertices.emplace_back(pos + rightOffset + upOffset, glm::vec2(1.0f, 1.0f), rgba);
_vertices.emplace_back(pos - rightOffset + upOffset, glm::vec2(0.0f, 1.0f), rgba);
_vertices.emplace_back(pos - rightOffset - upOffset, glm::vec2(0.0f, 0.0f), rgba);
_vertices.emplace_back(pos + rightOffset - upOffset, glm::vec2(1.0f, 0.0f), rgba);
_vertices.emplace_back(particle.position + rightOffset + upOffset, glm::vec2(1.0f, 1.0f), rgba);
_vertices.emplace_back(particle.position - rightOffset + upOffset, glm::vec2(0.0f, 1.0f), rgba);
_vertices.emplace_back(particle.position - rightOffset - upOffset, glm::vec2(0.0f, 0.0f), rgba);
_vertices.emplace_back(particle.position + rightOffset - upOffset, glm::vec2(1.0f, 0.0f), rgba);
}
render::PendingChanges pendingChanges;
pendingChanges.updateItem<ParticlePayload>(_renderItemId, [this](ParticlePayload& payload) {
// update vertex buffer

View file

@ -89,6 +89,7 @@ CONSTRUCT_PROPERTY(velocitySpread, ParticleEffectEntityItem::DEFAULT_VELOCITY_SP
CONSTRUCT_PROPERTY(emitAcceleration, ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION),
CONSTRUCT_PROPERTY(accelerationSpread, ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD),
CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS),
CONSTRUCT_PROPERTY(radiusSpread, ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD),
CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID),
CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR),
CONSTRUCT_PROPERTY(keyLightIntensity, ZoneEntityItem::DEFAULT_KEYLIGHT_INTENSITY),
@ -355,6 +356,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_EMIT_ACCELERATION, emitAcceleration);
CHECK_PROPERTY_CHANGE(PROP_ACCELERATION_SPREAD, accelerationSpread);
CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius);
CHECK_PROPERTY_CHANGE(PROP_RADIUS_SPREAD, radiusSpread);
CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID);
CHECK_PROPERTY_CHANGE(PROP_NAME, name);
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, keyLightColor);
@ -458,6 +460,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(emitAcceleration);
COPY_PROPERTY_TO_QSCRIPTVALUE(accelerationSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius);
COPY_PROPERTY_TO_QSCRIPTVALUE(radiusSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID);
COPY_PROPERTY_TO_QSCRIPTVALUE(name);
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionSoundURL);
@ -579,6 +582,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, glmVec3, setEmitAcceleration);
COPY_PROPERTY_FROM_QSCRIPTVALUE(accelerationSpread, glmVec3, setAccelerationSpread);
COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius);
COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusSpread, float, setRadiusSpread);
COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID);
COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL);
@ -821,7 +825,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, properties.getEmitAcceleration());
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, properties.getAccelerationSpread());
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, properties.getRadiusSpread());
}
if (properties.getType() == EntityTypes::Zone) {
@ -1091,6 +1095,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS_SPREAD, float, setRadiusSpread);
}
if (properties.getType() == EntityTypes::Zone) {
@ -1223,6 +1228,7 @@ void EntityItemProperties::markAllChanged() {
_emitAccelerationChanged = true;
_accelerationSpreadChanged = true;
_particleRadiusChanged = true;
_radiusSpreadChanged = true;
_marketplaceIDChanged = true;

View file

@ -136,6 +136,7 @@ public:
DEFINE_PROPERTY(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3);
DEFINE_PROPERTY(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3);
DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float);
DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float);
DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString);
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor);
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
@ -316,6 +317,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitAcceleration, emitAcceleration, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AccelerationSpread, accelerationSpread, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, RadiusSpread, radiusSpread, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundMode, backgroundMode, "");
DEBUG_PROPERTY_IF_CHANGED(debug, properties, VoxelVolumeSize, voxelVolumeSize, "");

View file

@ -138,6 +138,7 @@ enum EntityPropertyList {
// used by particles
PROP_VELOCITY_SPREAD,
PROP_ACCELERATION_SPREAD,
PROP_RADIUS_SPREAD,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line

View file

@ -54,6 +54,7 @@ const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(3.0f, 0.0f, 3.
const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f);
const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f);
const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f;
const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f;
const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = "";
@ -72,6 +73,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
_emitAcceleration(DEFAULT_EMIT_ACCELERATION),
_accelerationSpread(DEFAULT_ACCELERATION_SPREAD),
_particleRadius(DEFAULT_PARTICLE_RADIUS),
_radiusSpread(DEFAULT_RADIUS_SPREAD),
_lastAnimated(usecTimestampNow()),
_animationLoop(),
_animationSettings(),
@ -82,6 +84,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
_particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
_particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
_particleAccelerations(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
_particleRadiuses(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS),
_timeUntilNextEmit(0.0f),
_particleHeadIndex(0),
_particleTailIndex(0),
@ -111,7 +114,6 @@ void ParticleEffectEntityItem::setVelocitySpread(const glm::vec3& velocitySpread
computeAndUpdateDimensions();
}
void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) {
_emitAcceleration = emitAcceleration;
computeAndUpdateDimensions();
@ -126,6 +128,10 @@ void ParticleEffectEntityItem::setParticleRadius(float particleRadius) {
_particleRadius = particleRadius;
}
void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) {
_radiusSpread = radiusSpread;
}
void ParticleEffectEntityItem::computeAndUpdateDimensions() {
const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error
@ -163,9 +169,9 @@ EntityItemProperties ParticleEffectEntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitVelocity, getEmitVelocity);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitAcceleration, getEmitAcceleration);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusSpread, getRadiusSpread);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
return properties;
@ -185,11 +191,12 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitVelocity, setEmitVelocity);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocitySpread, setVelocitySpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitAcceleration, setEmitAcceleration);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(accelerationSpread, setAccelerationSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusSpread, setRadiusSpread);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocitySpread, setVelocitySpread);
if (somethingChanged) {
bool wantDebug = false;
@ -257,6 +264,10 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
}
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_RADIUS_SPREAD) {
READ_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, float, setRadiusSpread);
}
return bytesRead;
}
@ -280,6 +291,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
requestedProperties += PROP_PARTICLE_RADIUS;
requestedProperties += PROP_TEXTURES;
requestedProperties += PROP_VELOCITY_SPREAD;
requestedProperties += PROP_RADIUS_SPREAD;
return requestedProperties;
}
@ -308,6 +320,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius());
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, getVelocitySpread());
APPEND_ENTITY_PROPERTY(PROP_RADIUS_SPREAD, getRadiusSpread());
}
bool ParticleEffectEntityItem::isAnimatingSomething() const {
@ -514,7 +527,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
}
}
// emit new particles, but only if animaiton is playing
// emit new particles, but only if animation is playing
if (getAnimationIsPlaying()) {
float timeLeftInFrame = deltaTime;
@ -527,12 +540,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
quint32 i = _particleTailIndex;
_particleLifetimes[i] = _lifespan;
_particleRadiuses[i] = _particleRadius + (2.0f * randFloat() - 1) * _radiusSpread;
glm::vec3 spreadOffset;
spreadOffset.x = -_velocitySpread.x + randFloat() * (_velocitySpread.x * 2.0f);
spreadOffset.y = -_velocitySpread.y + randFloat() * (_velocitySpread.y * 2.0f);
spreadOffset.z = -_velocitySpread.z + randFloat() * (_velocitySpread.z * 2.0f);
// set initial conditions
_particlePositions[i] = getPosition();
@ -571,8 +584,9 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
_particleLifetimes.resize(_maxParticles);
_particlePositions.resize(_maxParticles);
_particleVelocities.resize(_maxParticles);
_particleRadiuses.resize(_maxParticles);
// effectivly clear all particles and start emitting new ones from scratch.
// effectively clear all particles and start emitting new ones from scratch.
_particleHeadIndex = 0;
_particleTailIndex = 0;
_timeUntilNextEmit = 0.0f;

View file

@ -102,12 +102,10 @@ public:
void setEmitVelocity(const glm::vec3& emitVelocity);
const glm::vec3& getEmitVelocity() const { return _emitVelocity; }
static const glm::vec3 DEFAULT_VELOCITY_SPREAD;
void setVelocitySpread(const glm::vec3& velocitySpread);
const glm::vec3& getVelocitySpread() const { return _velocitySpread; }
static const glm::vec3 DEFAULT_EMIT_ACCELERATION;
void setEmitAcceleration(const glm::vec3& emitAcceleration);
const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; }
@ -119,7 +117,11 @@ public:
static const float DEFAULT_PARTICLE_RADIUS;
void setParticleRadius(float particleRadius);
float getParticleRadius() const { return _particleRadius; }
static const float DEFAULT_RADIUS_SPREAD;
void setRadiusSpread(float radiusSpread);
float getRadiusSpread() const { return _radiusSpread; }
void computeAndUpdateDimensions();
@ -155,6 +157,7 @@ protected:
glm::vec3 _emitAcceleration;
glm::vec3 _accelerationSpread;
float _particleRadius;
float _radiusSpread;
quint64 _lastAnimated;
AnimationLoop _animationLoop;
QString _animationSettings;
@ -167,6 +170,7 @@ protected:
QVector<glm::vec3> _particlePositions;
QVector<glm::vec3> _particleVelocities;
QVector<glm::vec3> _particleAccelerations;
QVector<float> _particleRadiuses;
float _timeUntilNextEmit;
// particle arrays are a ring buffer, use these indicies

View file

@ -67,7 +67,7 @@ PacketVersion versionForPacketType(PacketType::Value packetType) {
case EntityAdd:
case EntityEdit:
case EntityData:
return VERSION_ENTITIES_PARTICLE_MODIFICATIONS;
return VERSION_ENTITIES_PARTICLE_RADIUS_SPREAD;
case AvatarData:
return 13;
default:

View file

@ -144,5 +144,6 @@ const PacketVersion VERSION_POLYVOX_TEXTURES = 36;
const PacketVersion VERSION_ENTITIES_POLYLINE = 37;
const PacketVersion VERSION_OCTREE_CENTERED_ORIGIN = 38;
const PacketVersion VERSION_ENTITIES_PARTICLE_MODIFICATIONS = 39;
const PacketVersion VERSION_ENTITIES_PARTICLE_RADIUS_SPREAD = 40;
#endif // hifi_PacketHeaders_h