diff --git a/examples/entityScripts/sprayPaintCan.js b/examples/entityScripts/sprayPaintCan.js index aa04e94341..21613bdeb5 100644 --- a/examples/entityScripts/sprayPaintCan.js +++ b/examples/entityScripts/sprayPaintCan.js @@ -79,19 +79,18 @@ lastFrame: 10000, running: true }); + var PI = 3.141593; + var DEG_TO_RAD = PI / 180.0; this.paintStream = Entities.addEntity({ type: "ParticleEffect", animationSettings: animationSettings, position: this.properties.position, textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png", - emitVelocity: ZERO_VEC, + emitSpeed: 0, + speedSpread: 0.02, + polarFinish: 2 * DEG_TO_RAD, emitAcceleration: ZERO_VEC, - velocitySpread: { - x: .1, - y: .1, - z: 0.1 - }, emitRate: 100, particleRadius: 0.01, color: { @@ -127,7 +126,8 @@ position = Vec3.sum(position, Vec3.multiply(upVec, TIP_OFFSET_Y)) Entities.editEntity(self.paintStream, { position: position, - emitVelocity: Vec3.multiply(5, forwardVec) + emitOrientation: forwardVec, + emitSpeed: 5 }); //Now check for an intersection with an entity diff --git a/examples/example/entities/particlesTest.js b/examples/example/entities/particlesTest.js index 0d1ea60005..bfa4a47ffb 100644 --- a/examples/example/entities/particlesTest.js +++ b/examples/example/entities/particlesTest.js @@ -13,35 +13,49 @@ (function () { var box, + sphere, + sphereDimensions = { x: 0.4, y: 0.8, z: 0.2 }, + pointDimensions = { x: 0.0, y: 0.0, z: 0.0 }, + sphereOrientation = Quat.fromPitchYawRollDegrees(-60.0, 30.0, 0.0), + verticalOrientation = Quat.fromPitchYawRollDegrees(-90.0, 0.0, 0.0), particles, particleExample = -1, - NUM_PARTICLE_EXAMPLES = 11, - PARTICLE_RADIUS = 0.04; + PARTICLE_RADIUS = 0.04, + SLOW_EMIT_RATE = 2.0, + HALF_EMIT_RATE = 50.0, + FAST_EMIT_RATE = 100.0, + SLOW_EMIT_SPEED = 0.025, + 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, + DEG_TO_RAD = PI / 180.0, + NUM_PARTICLE_EXAMPLES = 18; function onClickDownOnEntity(entityID) { - if (entityID === box || entityID === particles) { + if (entityID === box || entityID === sphere || entityID === particles) { particleExample = (particleExample + 1) % NUM_PARTICLE_EXAMPLES; switch (particleExample) { case 0: print("Simple emitter"); Entities.editEntity(particles, { - velocitySpread: { x: 0.0, y: 0.0, z: 0.0 }, + speedSpread: 0.0, accelerationSpread: { x: 0.0, y: 0.0, z: 0.0 }, radiusSpread: 0.0, animationIsPlaying: true }); break; case 1: - print("Velocity spread"); + print("Speed spread"); Entities.editEntity(particles, { - velocitySpread: { x: 0.1, y: 0.0, z: 0.1 } + speedSpread: 0.1 }); break; case 2: print("Acceleration spread"); Entities.editEntity(particles, { - velocitySpread: { x: 0.0, y: 0.0, z: 0.0 }, + speedSpread: 0.0, accelerationSpread: { x: 0.0, y: 0.1, z: 0.0 } }); break; @@ -104,19 +118,99 @@ }); break; case 10: - print("Stop emitting"); + print("Emit in a spread beam"); Entities.editEntity(particles, { colorStart: { red: 255, green: 255, blue: 255 }, colorFinish: { red: 255, green: 255, blue: 255 }, + alphaFinish: 0.0, + emitRate: FAST_EMIT_RATE, + polarFinish: 2.0 * DEG_TO_RAD + }); + break; + case 11: + print("Emit in all directions from point"); + Entities.editEntity(particles, { + emitSpeed: SLOW_EMIT_SPEED, + emitAcceleration: ZERO_EMIT_ACCELERATON, + polarFinish: PI + }); + break; + case 12: + print("Emit from sphere surface"); + Entities.editEntity(particles, { + colorStart: { red: 255, green: 255, blue: 255 }, + colorFinish: { red: 255, green: 255, blue: 255 }, + emitDimensions: sphereDimensions, + emitOrientation: sphereOrientation + }); + Entities.editEntity(box, { + visible: false + }); + Entities.editEntity(sphere, { + visible: true + }); + break; + case 13: + print("Emit from hemisphere of sphere surface"); + Entities.editEntity(particles, { + polarFinish: PI / 2.0 + }); + break; + case 14: + print("Emit from equator of sphere surface"); + Entities.editEntity(particles, { + polarStart: PI / 2.0, + emitRate: HALF_EMIT_RATE + }); + break; + case 15: + print("Emit from half equator of sphere surface"); + Entities.editEntity(particles, { + azimuthStart: -PI / 2.0, + azimuthFinish: PI / 2.0 + }); + break; + case 16: + print("Emit within eighth of sphere volume"); + Entities.editEntity(particles, { + polarStart: 0.0, + polarFinish: PI / 2.0, + azimuthStart: 0, + azimuthFinish: PI / 2.0, + emitRadiusStart: 0.0, + alphaFinish: 1.0, + emitSpeed: 0.0 + }); + break; + case 17: + print("Stop emitting"); + Entities.editEntity(particles, { + emitDimensions: pointDimensions, + emitOrientation: verticalOrientation, + alphaFinish: 1.0, + emitRate: SLOW_EMIT_RATE, + emitSpeed: FAST_EMIT_SPEED, + emitAcceleration: GRAVITY_EMIT_ACCELERATON, + polarStart: 0.0, + polarFinish: 0.0, + azimuthStart: -PI, + azimuthFinish: PI, animationIsPlaying: false }); + Entities.editEntity(box, { + visible: true + }); + Entities.editEntity(sphere, { + visible: false + }); break; } } } function setUp() { - var spawnPoint = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation()))), + var boxPoint, + spawnPoint, animation = { fps: 30, frameIndex: 0, @@ -126,28 +220,50 @@ loop: true }; + boxPoint = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation()))); + boxPoint = Vec3.sum(boxPoint, { x: 0.0, y: -0.5, z: 0.0 }); + spawnPoint = Vec3.sum(boxPoint, { x: 0.0, y: 1.0, z: 0.0 }); + box = Entities.addEntity({ type: "Box", - position: spawnPoint, + name: "ParticlesTest Box", + position: boxPoint, + rotation: verticalOrientation, dimensions: { x: 0.3, y: 0.3, z: 0.3 }, color: { red: 128, green: 128, blue: 128 }, - lifetime: 3600 // 1 hour; just in case + lifetime: 3600, // 1 hour; just in case + visible: true }); + // Same size and orientation as emitter when ellipsoid. + sphere = Entities.addEntity({ + type: "Sphere", + name: "ParticlesTest Sphere", + position: boxPoint, + rotation: sphereOrientation, + dimensions: sphereDimensions, + color: { red: 128, green: 128, blue: 128 }, + lifetime: 3600, // 1 hour; just in case + visible: false + }); + + // 1.0m above the box or ellipsoid. particles = Entities.addEntity({ type: "ParticleEffect", + name: "ParticlesTest Emitter", position: spawnPoint, + emitOrientation: verticalOrientation, particleRadius: PARTICLE_RADIUS, radiusSpread: 0.0, - emitRate: 2.0, - emitVelocity: { x: 0.0, y: 1.0, z: 0.0 }, - velocitySpread: { x: 0.0, y: 0.0, z: 0.0 }, - emitAcceleration: { x: 0.0, y: -0.3, z: 0.0 }, + emitRate: SLOW_EMIT_RATE, + emitSpeed: FAST_EMIT_SPEED, + speedSpread: 0.0, + emitAcceleration: GRAVITY_EMIT_ACCELERATON, accelerationSpread: { x: 0.0, y: 0.0, z: 0.0 }, textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", color: { red: 255, green: 255, blue: 255 }, lifespan: 5.0, - visible: true, + visible: false, locked: false, animationSettings: animation, animationIsPlaying: false, @@ -163,6 +279,7 @@ Entities.clickDownOnEntity.disconnect(onClickDownOnEntity); Entities.deleteEntity(particles); Entities.deleteEntity(box); + Entities.deleteEntity(sphere); } setUp(); diff --git a/examples/fireworks.js b/examples/fireworks.js index 621931ee36..3485b1687f 100644 --- a/examples/fireworks.js +++ b/examples/fireworks.js @@ -101,7 +101,6 @@ Rocket = function(point, colorPalette) { this.burst = false; this.emitRate = randInt(80, 120); - this.emitStrength = randInt(5.0, 7.0); this.rocket = Entities.addEntity({ type: "Sphere", @@ -163,6 +162,9 @@ Rocket.prototype.explode = function(position) { }); var colorIndex = 0; + var PI = 3.141593; + var DEG_TO_RAD = PI / 180.0; + for (var i = 0; i < NUM_BURSTS; ++i) { var color = this.colors[colorIndex]; print(JSON.stringify(color)); @@ -172,12 +174,7 @@ Rocket.prototype.explode = function(position) { position: position, textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png', emitRate: this.emitRate, - emitStrength: this.emitStrength, - emitDirection: { - x: Math.pow(-1, i) * randFloat(0.0, 1.4), - y: 1.0, - z: 0.0 - }, + polarFinish: 25 * DEG_TO_RAD, color: color, lifespan: 1.0, visible: true, diff --git a/examples/particleDance.js b/examples/particleDance.js index e920fcfa41..6b1f84bb8e 100644 --- a/examples/particleDance.js +++ b/examples/particleDance.js @@ -6,6 +6,9 @@ var AUDIO_RANGE = 0.5 * RANGE; var DIST_BETWEEN_BURSTS = 1.0; + var PI = 3.141593; + var DEG_TO_RAD = PI / 180.0; + var LOUDNESS_RADIUS_RATIO = 10; var TEXTURE_PATH = 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png'; @@ -86,12 +89,7 @@ position: this.point, textures: TEXTURE_PATH, emitRate: this.emitRate, - emitStrength: this.emitStrength, - emitDirection: { - x: Math.pow(-1, i) * randFloat(0.0, 0.4), - y: 1.0, - z: 0.0 - }, + polarFinish: 25 * DEG_TO_RAD, color: color, lifespan: 1.0, visible: true, diff --git a/examples/particles.js b/examples/particles.js index ad232dd781..def21704d1 100644 --- a/examples/particles.js +++ b/examples/particles.js @@ -35,13 +35,16 @@ firstFrame: 0, lastFrame: 30, loop: true }); + var PI = 3.141593; + var DEG_TO_RAD = PI / 180.0; this.entity = Entities.addEntity({ type: "ParticleEffect", animationSettings: animationSettings, position: spawnPoint, dimensions: {x: 2, y: 2, z: 2}, - emitVelocity: {x: 0, y: 5, z: 0}, - velocitySpread: {x: 2, y: 0, z: 2}, + emitSpeed: 5, + speedSpread: 2, + polarFinish: 30 * DEG_TO_RAD, emitAcceleration: {x: 0, y: -9.8, z: 0}, textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", color: color, diff --git a/examples/toys/grenade.js b/examples/toys/grenade.js index b2dfebb888..c6a9c5bdeb 100644 --- a/examples/toys/grenade.js +++ b/examples/toys/grenade.js @@ -45,6 +45,8 @@ var explodeAnimationSettings = JSON.stringify({ var GRAVITY = -9.8; var TIME_TO_EXPLODE = 2500; var DISTANCE_IN_FRONT_OF_ME = 1.0; +var PI = 3.141593; +var DEG_TO_RAD = PI / 180.0; function makeGrenade() { var position = Vec3.sum(MyAvatar.position, @@ -87,8 +89,7 @@ function update() { position: newProperties.position, textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png', emitRate: 100, - emitStrength: 2.0, - emitDirection: { x: 0.0, y: 1.0, z: 0.0 }, + polarFinish: 25 * DEG_TO_RAD, color: { red: 200, green: 0, blue: 0 }, lifespan: 10.0, visible: true, @@ -145,8 +146,7 @@ function boom() { position: properties.position, textures: 'https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png', emitRate: 200, - emitStrength: 3.0, - emitDirection: { x: 0.0, y: 1.0, z: 0.0 }, + polarFinish: 25 * DEG_TO_RAD, color: { red: 255, green: 255, blue: 0 }, lifespan: 2.0, visible: true, diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 13138e5c10..b92ea34827 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -91,8 +91,15 @@ CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), -CONSTRUCT_PROPERTY(emitVelocity, ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY), -CONSTRUCT_PROPERTY(velocitySpread, ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD), +CONSTRUCT_PROPERTY(emitSpeed, ParticleEffectEntityItem::DEFAULT_EMIT_SPEED), +CONSTRUCT_PROPERTY(speedSpread, ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD), +CONSTRUCT_PROPERTY(emitOrientation, ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION), +CONSTRUCT_PROPERTY(emitDimensions, ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS), +CONSTRUCT_PROPERTY(emitRadiusStart, ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START), +CONSTRUCT_PROPERTY(polarStart, ParticleEffectEntityItem::DEFAULT_POLAR_START), +CONSTRUCT_PROPERTY(polarFinish, ParticleEffectEntityItem::DEFAULT_POLAR_FINISH), +CONSTRUCT_PROPERTY(azimuthStart, ParticleEffectEntityItem::DEFAULT_AZIMUTH_START), +CONSTRUCT_PROPERTY(azimuthFinish, ParticleEffectEntityItem::DEFAULT_AZIMUTH_FINISH), CONSTRUCT_PROPERTY(emitAcceleration, ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION), CONSTRUCT_PROPERTY(accelerationSpread, ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), @@ -375,8 +382,15 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); - CHECK_PROPERTY_CHANGE(PROP_EMIT_VELOCITY, emitVelocity); - CHECK_PROPERTY_CHANGE(PROP_VELOCITY_SPREAD, velocitySpread); + CHECK_PROPERTY_CHANGE(PROP_EMIT_SPEED, emitSpeed); + CHECK_PROPERTY_CHANGE(PROP_SPEED_SPREAD, speedSpread); + CHECK_PROPERTY_CHANGE(PROP_EMIT_ORIENTATION, emitOrientation); + CHECK_PROPERTY_CHANGE(PROP_EMIT_DIMENSIONS, emitDimensions); + CHECK_PROPERTY_CHANGE(PROP_EMIT_RADIUS_START, emitRadiusStart); + CHECK_PROPERTY_CHANGE(PROP_POLAR_START, polarStart); + CHECK_PROPERTY_CHANGE(PROP_POLAR_FINISH, polarFinish); + CHECK_PROPERTY_CHANGE(PROP_AZIMUTH_START, azimuthStart); + CHECK_PROPERTY_CHANGE(PROP_AZIMUTH_FINISH, azimuthFinish); CHECK_PROPERTY_CHANGE(PROP_EMIT_ACCELERATION, emitAcceleration); CHECK_PROPERTY_CHANGE(PROP_ACCELERATION_SPREAD, accelerationSpread); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); @@ -478,8 +492,15 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFESPAN, lifespan); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RATE, emitRate); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_VELOCITY, emitVelocity); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VELOCITY_SPREAD, velocitySpread); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_SPEED, emitSpeed); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPEED_SPREAD, speedSpread); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_ORIENTATION, emitOrientation); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_DIMENSIONS, emitDimensions); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RADIUS_START, emitRadiusStart); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POLAR_START, polarStart); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POLAR_FINISH, polarFinish); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_AZIMUTH_START, azimuthStart); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_AZIMUTH_FINISH, azimuthFinish); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_ACCELERATION, emitAcceleration); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACCELERATION_SPREAD, accelerationSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_RADIUS, particleRadius); @@ -579,8 +600,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths); } - //COPY_PROPERTY_TO_QSCRIPTVALUE(simulationOwner); // TODO: expose this for JSON saves? - // Sitting properties support if (!skipDefaults) { QScriptValue sittingPoints = engine->newObject(); @@ -678,8 +697,15 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles); COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); - COPY_PROPERTY_FROM_QSCRIPTVALUE(emitVelocity, glmVec3, setEmitVelocity); - COPY_PROPERTY_FROM_QSCRIPTVALUE(velocitySpread, glmVec3, setVelocitySpread); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitSpeed, float, setEmitSpeed); + COPY_PROPERTY_FROM_QSCRIPTVALUE(speedSpread, float, setSpeedSpread); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitOrientation, glmQuat, setEmitOrientation); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDimensions, glmVec3, setEmitDimensions); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRadiusStart, float, setEmitRadiusStart); + COPY_PROPERTY_FROM_QSCRIPTVALUE(polarStart, float, setPolarStart); + COPY_PROPERTY_FROM_QSCRIPTVALUE(polarFinish, float, setPolarFinish); + COPY_PROPERTY_FROM_QSCRIPTVALUE(azimuthStart, float, setAzimuthStart); + COPY_PROPERTY_FROM_QSCRIPTVALUE(azimuthFinish, float, setAzimuthFinish); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, glmVec3, setEmitAcceleration); COPY_PROPERTY_FROM_QSCRIPTVALUE(accelerationSpread, glmVec3, setAccelerationSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); @@ -828,8 +854,15 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); - ADD_PROPERTY_TO_MAP(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); + ADD_PROPERTY_TO_MAP(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_START, EmitPolarStart, polarStart, float); + ADD_PROPERTY_TO_MAP(PROP_POLAR_FINISH, EmitPolarFinish, polarFinish, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_START, EmitAzimuthStart, azimuthStart, float); + ADD_PROPERTY_TO_MAP(PROP_AZIMUTH_FINISH, EmitAzimuthFinish, azimuthFinish, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); @@ -1080,8 +1113,15 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles()); APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, properties.getEmitVelocity()); - APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, properties.getVelocitySpread()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, properties.getEmitSpeed()); + APPEND_ENTITY_PROPERTY(PROP_SPEED_SPREAD, properties.getSpeedSpread()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, properties.getEmitOrientation()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, properties.getEmitDimensions()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, properties.getEmitRadiusStart()); + APPEND_ENTITY_PROPERTY(PROP_POLAR_START, properties.getPolarStart()); + APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, properties.getPolarFinish()); + APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, properties.getAzimuthStart()); + APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, properties.getAzimuthFinish()); APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, properties.getEmitAcceleration()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, properties.getAccelerationSpread()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); @@ -1364,8 +1404,15 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_SPEED, float, setEmitSpeed); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPEED_SPREAD, float, setSpeedSpread); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ORIENTATION, glm::quat, setEmitOrientation); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POLAR_START, float, setPolarStart); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POLAR_FINISH, float, setPolarFinish); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AZIMUTH_START, float, setAzimuthStart); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AZIMUTH_FINISH, float, setAzimuthFinish); 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); @@ -1513,8 +1560,15 @@ void EntityItemProperties::markAllChanged() { _maxParticlesChanged = true; _lifespanChanged = true; _emitRateChanged = true; - _emitVelocityChanged = true; - _velocitySpreadChanged = true; + _emitSpeedChanged = true; + _speedSpreadChanged = true; + _emitOrientationChanged = true; + _emitDimensionsChanged = true; + _emitRadiusStartChanged = true; + _polarStartChanged = true; + _polarFinishChanged = true; + _azimuthStartChanged = true; + _azimuthFinishChanged = true; _emitAccelerationChanged = true; _accelerationSpreadChanged = true; _particleRadiusChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9856911207..55be145d85 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -141,10 +141,17 @@ public: DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); - DEFINE_PROPERTY_REF(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3); - DEFINE_PROPERTY_REF(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3); - DEFINE_PROPERTY(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); - DEFINE_PROPERTY(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); + DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float); + DEFINE_PROPERTY(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, float); + DEFINE_PROPERTY_REF(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat); + DEFINE_PROPERTY_REF(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3); + DEFINE_PROPERTY(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float); + DEFINE_PROPERTY(PROP_POLAR_START, PolarStart, polarStart, float); + DEFINE_PROPERTY(PROP_POLAR_FINISH, PolarFinish, polarFinish, float); + DEFINE_PROPERTY(PROP_AZIMUTH_START, AzimuthStart, azimuthStart, float); + DEFINE_PROPERTY(PROP_AZIMUTH_FINISH, AzimuthFinish, azimuthFinish, float); + DEFINE_PROPERTY_REF(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); + DEFINE_PROPERTY_REF(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(PROP_RADIUS_START, RadiusStart, radiusStart, float); @@ -344,7 +351,15 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitVelocity, emitVelocity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitSpeed, emitSpeed, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpeedSpread, speedSpread, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitOrientation, emitOrientation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDimensions, emitDimensions, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRadiusStart, emitRadiusStart, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, PolarStart, polarStart, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, PolarFinish, polarFinish, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AzimuthStart, azimuthStart, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AzimuthFinish, azimuthFinish, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitAcceleration, emitAcceleration, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AccelerationSpread, accelerationSpread, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 964529afca..731e49b388 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -44,6 +44,14 @@ } \ } +#define SKIP_ENTITY_PROPERTY(P,T) \ + if (propertyFlags.getHasProperty(P)) { \ + T fromBuffer; \ + int bytes = OctreePacketData::unpackDataFromBytes(dataAt, fromBuffer); \ + dataAt += bytes; \ + bytesRead += bytes; \ + } + #define DECODE_GROUP_PROPERTY_HAS_CHANGED(P,N) \ if (propertyFlags.getHasProperty(P)) { \ set##N##Changed(true); \ diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 68c318a579..71215a5596 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -71,7 +71,7 @@ enum EntityPropertyList { PROP_MAX_PARTICLES, PROP_LIFESPAN, PROP_EMIT_RATE, - PROP_EMIT_VELOCITY, + PROP_EMIT_SPEED, PROP_EMIT_STRENGTH, PROP_EMIT_ACCELERATION, PROP_PARTICLE_RADIUS, @@ -111,7 +111,7 @@ enum EntityPropertyList { PROP_STROKE_WIDTHS, // used by particles - PROP_VELOCITY_SPREAD, + PROP_SPEED_SPREAD, PROP_ACCELERATION_SPREAD, PROP_X_N_NEIGHBOR_ID, // used by PolyVox @@ -135,6 +135,13 @@ enum EntityPropertyList { PROP_ALPHA_SPREAD, PROP_ALPHA_START, PROP_ALPHA_FINISH, + PROP_EMIT_ORIENTATION, + PROP_EMIT_DIMENSIONS, + PROP_EMIT_RADIUS_START, + PROP_POLAR_START, + PROP_POLAR_FINISH, + PROP_AZIMUTH_START, + PROP_AZIMUTH_FINISH, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line @@ -169,7 +176,7 @@ enum EntityPropertyList { PROP_ATMOSPHERE_CENTER = PROP_MAX_PARTICLES, PROP_ATMOSPHERE_INNER_RADIUS = PROP_LIFESPAN, PROP_ATMOSPHERE_OUTER_RADIUS = PROP_EMIT_RATE, - PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_VELOCITY, + PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_SPEED, PROP_ATMOSPHERE_RAYLEIGH_SCATTERING = PROP_EMIT_STRENGTH, PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_EMIT_ACCELERATION, PROP_ATMOSPHERE_HAS_STARS = PROP_PARTICLE_RADIUS, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index b493cbfa48..8c45c860fa 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -43,6 +43,9 @@ #include "EntityScriptingInterface.h" #include "ParticleEffectEntityItem.h" +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 xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 }; const xColor ParticleEffectEntityItem::DEFAULT_COLOR_SPREAD = { 0, 0, 0 }; const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f; @@ -55,8 +58,15 @@ const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 5.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(3.0f, 0.0f, 3.0f); +const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; +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::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) +const float ParticleEffectEntityItem::DEFAULT_POLAR_START = 0.0f; // Emit along z-axis +const float ParticleEffectEntityItem::DEFAULT_POLAR_FINISH = 0.0f; // "" +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 glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; @@ -104,13 +114,24 @@ ParticleEffectEntityItem::~ParticleEffectEntityItem() { } -void ParticleEffectEntityItem::setEmitVelocity(const glm::vec3& emitVelocity) { - _emitVelocity = emitVelocity; +void ParticleEffectEntityItem::setEmitSpeed(float emitSpeed) { + _emitSpeed = emitSpeed; computeAndUpdateDimensions(); } -void ParticleEffectEntityItem::setVelocitySpread(const glm::vec3& velocitySpread) { - _velocitySpread = velocitySpread; +void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) { + _speedSpread = speedSpread; + computeAndUpdateDimensions(); +} + +void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation) { + _emitOrientation = emitOrientation; + computeAndUpdateDimensions(); +} + + +void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions) { + _emitDimensions = emitDimensions; computeAndUpdateDimensions(); } @@ -126,23 +147,18 @@ void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerati void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error - - float maxVelocityX = fabsf(_velocity.x) + _velocitySpread.x; - float maxAccelerationX = fabsf(_acceleration.x) + _accelerationSpread.x; - float maxXDistance = (maxVelocityX * time) + (0.5f * maxAccelerationX * time * time); - - float maxVelocityY = fabsf(_velocity.y) + _velocitySpread.y; - float maxAccelerationY = fabsf(_acceleration.y) + _accelerationSpread.y; - float maxYDistance = (maxVelocityY * time) + (0.5f * maxAccelerationY * time * time); - - float maxVelocityZ = fabsf(_velocity.z) + _velocitySpread.z; - float maxAccelerationZ = fabsf(_acceleration.z) + _accelerationSpread.z; - float maxZDistance = (maxVelocityZ * time) + (0.5f * maxAccelerationZ * time * time); - - float maxDistance = std::max(maxXDistance, std::max(maxYDistance, maxZDistance)); - + + glm::vec3 velocity = _emitSpeed * (_emitOrientation * Z_AXIS); + glm::vec3 velocitySpread = _speedSpread * (_emitOrientation * Z_AXIS); + + glm::vec3 maxVelocity = glm::abs(velocity) + velocitySpread; + glm::vec3 maxAccleration = glm::abs(_acceleration) + _accelerationSpread; + glm::vec3 maxDistance = 0.5f * _emitDimensions + time * maxVelocity + (0.5f * time * time) * maxAccleration; + + float maxDistanceValue = std::max(maxDistance.x, std::max(maxDistance.y, maxDistance.z)); + //times 2 because dimensions are diameters not radii - glm::vec3 dims(2.0f * maxDistance); + glm::vec3 dims(2.0f * maxDistanceValue); EntityItem::setDimensions(dims); } @@ -161,8 +177,15 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); 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(velocitySpread, getVelocitySpread); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitSpeed, getEmitSpeed); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(speedSpread, getSpeedSpread); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitOrientation, getEmitOrientation); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDimensions, getEmitDimensions); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRadiusStart, getEmitRadiusStart); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(polarStart, getPolarStart); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(polarFinish, getPolarFinish); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(azimuthStart, getAzimuthStart); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(azimuthFinish, getAzimuthFinish); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitAcceleration, getEmitAcceleration); COPY_ENTITY_PROPERTY_TO_PROPERTIES(accelerationSpread, getAccelerationSpread); COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); @@ -194,8 +217,15 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); 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(emitSpeed, setEmitSpeed); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(speedSpread, setSpeedSpread); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitOrientation, setEmitOrientation); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDimensions, setEmitDimensions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRadiusStart, setEmitRadiusStart); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(polarStart, setPolarStart); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(polarFinish, setPolarFinish); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(azimuthStart, setAzimuthStart); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(azimuthFinish, setAzimuthFinish); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitAcceleration, setEmitAcceleration); SET_ENTITY_PROPERTY_FROM_PROPERTIES(accelerationSpread, setAccelerationSpread); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); @@ -258,20 +288,25 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); + if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { + // OLD PROP_EMIT_VELOCITY FAKEOUT + SKIP_ENTITY_PROPERTY(PROP_EMIT_SPEED, glm::vec3); + } if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_MODIFICATIONS) { READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); - READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); + if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { + // OLD PROP_VELOCITY_SPREAD FAKEOUT + SKIP_ENTITY_PROPERTY(PROP_SPEED_SPREAD, glm::vec3); + } } else { - // EMIT_STRENGTH FAKEOUT - READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); - // LOCAL_GRAVITY FAKEOUT - READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); - // ACTUALLY PARTICLE RADIUS + // OLD PROP_EMIT_ACCELERATION FAKEOUT + SKIP_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float); + // OLD PROP_ACCELERATION_SPREAD FAKEOUT + SKIP_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); } @@ -292,6 +327,18 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish); } + if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { + READ_ENTITY_PROPERTY(PROP_EMIT_SPEED, float, setEmitSpeed); + READ_ENTITY_PROPERTY(PROP_SPEED_SPREAD, float, setSpeedSpread); + READ_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, glm::quat, setEmitOrientation); + READ_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, glm::vec3, setEmitDimensions); + READ_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, float, setEmitRadiusStart); + READ_ENTITY_PROPERTY(PROP_POLAR_START, float, setPolarStart); + READ_ENTITY_PROPERTY(PROP_POLAR_FINISH, float, setPolarFinish); + READ_ENTITY_PROPERTY(PROP_AZIMUTH_START, float, setAzimuthStart); + READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish); + } + return bytesRead; } @@ -309,12 +356,10 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_MAX_PARTICLES; requestedProperties += PROP_LIFESPAN; requestedProperties += PROP_EMIT_RATE; - requestedProperties += PROP_EMIT_VELOCITY; requestedProperties += PROP_EMIT_ACCELERATION; requestedProperties += PROP_ACCELERATION_SPREAD; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; - requestedProperties += PROP_VELOCITY_SPREAD; requestedProperties += PROP_RADIUS_SPREAD; requestedProperties += PROP_RADIUS_START; requestedProperties += PROP_RADIUS_FINISH; @@ -325,6 +370,15 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_ALPHA_SPREAD; requestedProperties += PROP_ALPHA_START; requestedProperties += PROP_ALPHA_FINISH; + requestedProperties += PROP_EMIT_SPEED; + requestedProperties += PROP_SPEED_SPREAD; + requestedProperties += PROP_EMIT_ORIENTATION; + requestedProperties += PROP_EMIT_DIMENSIONS; + requestedProperties += PROP_EMIT_RADIUS_START; + requestedProperties += PROP_POLAR_START; + requestedProperties += PROP_POLAR_FINISH; + requestedProperties += PROP_AZIMUTH_START; + requestedProperties += PROP_AZIMUTH_FINISH; return requestedProperties; } @@ -347,12 +401,10 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles()); APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, getEmitVelocity()); APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, getEmitAcceleration()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, getAccelerationSpread()); 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()); APPEND_ENTITY_PROPERTY(PROP_RADIUS_START, getRadiusStart()); APPEND_ENTITY_PROPERTY(PROP_RADIUS_FINISH, getRadiusFinish()); @@ -363,6 +415,15 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, getAlphaSpread()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, getAlphaStart()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, getAlphaFinish()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, getEmitSpeed()); + APPEND_ENTITY_PROPERTY(PROP_SPEED_SPREAD, getSpeedSpread()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_ORIENTATION, getEmitOrientation()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIMENSIONS, getEmitDimensions()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RADIUS_START, getEmitRadiusStart()); + APPEND_ENTITY_PROPERTY(PROP_POLAR_START, getPolarStart()); + APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish()); + APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart()); + APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish()); } bool ParticleEffectEntityItem::isAnimatingSomething() const { @@ -614,7 +675,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _radiusMiddles[i] =_particleRadius; _radiusFinishes[i] = getRadiusFinish(); } else { - float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1) * _radiusSpread / _particleRadius; + float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; _radiusStarts[i] = spreadMultiplier * getRadiusStart(); _radiusMiddles[i] = spreadMultiplier * _particleRadius; _radiusFinishes[i] = spreadMultiplier * getRadiusFinish(); @@ -622,21 +683,65 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { updateRadius(i, 0.0f); // Velocity and acceleration - 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); + if (_polarStart == 0.0f && _polarFinish == 0.0f) { + // Emit along z-axis + _particlePositions[i] = getPosition(); + _particleVelocities[i] = + (_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS); + _particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread; - // set initial conditions - _particlePositions[i] = getPosition(); - _particleVelocities[i] = _emitVelocity + spreadOffset; - - spreadOffset.x = -_accelerationSpread.x + randFloat() * (_accelerationSpread.x * 2.0f); - spreadOffset.y = -_accelerationSpread.y + randFloat() * (_accelerationSpread.y * 2.0f); - spreadOffset.z = -_accelerationSpread.z + randFloat() * (_accelerationSpread.z * 2.0f); - - _particleAccelerations[i] = _emitAcceleration + spreadOffset; + } else { + // Emit around point or from ellipsoid + // - Distribute directions evenly around point + // - Distribute points relatively evenly over ellipsoid surface + // - Distribute points relatively evenly within ellipsoid volume + float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); + float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); + float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); + + float azimuth; + if (_azimuthFinish >= _azimuthStart) { + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); + } else { + azimuth = _azimuthStart + (2.0f * PI + _azimuthFinish - _azimuthStart) * randFloat(); + } + + glm::vec3 emitDirection; + + if (_emitDimensions == glm::vec3()) { + // Point + emitDirection = _emitOrientation * fromSpherical(elevation, azimuth); + + _particlePositions[i] = getPosition(); + + } else { + // Ellipsoid + 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(); + radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); + } + + glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; + float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); + float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); + float z = radiuses.z * glm::sin(elevation); + glm::vec3 emitPosition = glm::vec3(x, y, z); + emitDirection = glm::normalize(glm::vec3( + x / (radiuses.x * radiuses.x), + y / (radiuses.y * radiuses.y), + z / (radiuses.z * radiuses.z) + )); + + _particlePositions[i] = getPosition() + _emitOrientation * emitPosition; + } + + _particleVelocities[i] = + (_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + _particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread; + } integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 053301206a..74d39aa4af 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -128,13 +128,41 @@ public: void setEmitRate(float emitRate) { _emitRate = emitRate; } float getEmitRate() const { return _emitRate; } - static const glm::vec3 DEFAULT_EMIT_VELOCITY; - 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 float DEFAULT_EMIT_SPEED; + void setEmitSpeed(float emitSpeed); + float getEmitSpeed() const { return _emitSpeed; } + + static const float DEFAULT_SPEED_SPREAD; + void setSpeedSpread(float speedSpread); + float getSpeedSpread() const { return _speedSpread; } + + static const glm::quat DEFAULT_EMIT_ORIENTATION; + void setEmitOrientation(const glm::quat& emitOrientation); + const glm::quat& getEmitOrientation() const { return _emitOrientation; } + + static const glm::vec3 DEFAULT_EMIT_DIMENSIONS; + 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; } + float getEmitRadiusStart() const { return _emitRadiusStart; } + + static const float DEFAULT_POLAR_START; + void setPolarStart(float polarStart) { _polarStart = polarStart; } + float getPolarStart() const { return _polarStart; } + + static const float DEFAULT_POLAR_FINISH; + void setPolarFinish(float polarFinish) { _polarFinish = polarFinish; } + float getPolarFinish() const { return _polarFinish; } + + static const float DEFAULT_AZIMUTH_START; + void setAzimuthStart(float azimuthStart) { _azimuthStart = azimuthStart; } + float getAzimuthStart() const { return _azimuthStart; } + + static const float DEFAULT_AZIMUTH_FINISH; + void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = azimuthFinish; } + float getAzimuthFinish() const { return _azimuthFinish; } static const glm::vec3 DEFAULT_EMIT_ACCELERATION; void setEmitAcceleration(const glm::vec3& emitAcceleration); @@ -202,8 +230,15 @@ protected: quint32 _maxParticles = DEFAULT_MAX_PARTICLES; float _lifespan = DEFAULT_LIFESPAN; float _emitRate = DEFAULT_EMIT_RATE; - glm::vec3 _emitVelocity = DEFAULT_EMIT_VELOCITY; - glm::vec3 _velocitySpread = DEFAULT_VELOCITY_SPREAD; + float _emitSpeed = DEFAULT_EMIT_SPEED; + float _speedSpread = DEFAULT_SPEED_SPREAD; + glm::quat _emitOrientation = DEFAULT_EMIT_ORIENTATION; + glm::vec3 _emitDimensions = DEFAULT_EMIT_DIMENSIONS; + float _emitRadiusStart = DEFAULT_EMIT_RADIUS_START; + float _polarStart = DEFAULT_POLAR_START; + float _polarFinish = DEFAULT_POLAR_FINISH; + float _azimuthStart = DEFAULT_AZIMUTH_START; + float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; glm::vec3 _emitAcceleration = DEFAULT_EMIT_ACCELERATION; glm::vec3 _accelerationSpread = DEFAULT_ACCELERATION_SPREAD; float _particleRadius = DEFAULT_PARTICLE_RADIUS; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 7e00acfdc0..a8cf743686 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -38,7 +38,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: - return VERSION_ENTITIES_PROTOCOL_HEADER_SWAP; + return VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER; default: return 14; } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index da702358a1..9f3c5950a2 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -140,5 +140,6 @@ const PacketVersion VERSION_ENTITIES_POLYVOX_NEIGHBORS = 40; const PacketVersion VERSION_ENTITIES_PARTICLE_RADIUS_PROPERTIES = 41; const PacketVersion VERSION_ENTITIES_PARTICLE_COLOR_PROPERTIES = 42; const PacketVersion VERSION_ENTITIES_PROTOCOL_HEADER_SWAP = 43; +const PacketVersion VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER = 44; #endif // hifi_PacketHeaders_h diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index 69961bfd8e..04e3a4fe05 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -58,28 +58,3 @@ glm::vec3 Vec3::toPolar(const glm::vec3& v) { return glm::vec3(elevation, azimuth, radius); } - -glm::vec3 Vec3::fromPolar(const glm::vec3& polar) { - float x = glm::cos(polar.x) * glm::sin(polar.y); - float y = glm::sin(-polar.x); - float z = glm::cos(polar.x) * glm::cos(polar.y); - - // Round small values to 0 - if (glm::abs(x) < EPSILON) { - x = 0.0f; - } - if (glm::abs(y) < EPSILON) { - y = 0.0f; - } - if (glm::abs(z) < EPSILON) { - z = 0.0f; - } - - return polar.z * glm::vec3(x, y, z); -} - -glm::vec3 Vec3::fromPolar(float elevation, float azimuth) { - glm::vec3 v = glm::vec3(elevation, azimuth, 1.0f); - return fromPolar(v); -} - diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index b05e729a49..2d703ac87e 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -43,8 +43,8 @@ public slots: bool withinEpsilon(const glm::vec3& v1, const glm::vec3& v2, float epsilon); // FIXME misnamed, should be 'spherical' or 'euler' depending on the implementation glm::vec3 toPolar(const glm::vec3& v); - glm::vec3 fromPolar(const glm::vec3& polar); - glm::vec3 fromPolar(float elevation, float azimuth); + glm::vec3 fromPolar(const glm::vec3& polar) { return fromSpherical(polar); } + glm::vec3 fromPolar(float elevation, float azimuth) { return fromSpherical(elevation, azimuth); } const glm::vec3& UNIT_X() { return Vectors::UNIT_X; } const glm::vec3& UNIT_Y() { return Vectors::UNIT_Y; } const glm::vec3& UNIT_Z() { return Vectors::UNIT_Z; } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 7d56157e53..3d705cf99e 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -225,6 +225,30 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) { return glm::angleAxis(angle, axis); } +glm::vec3 fromSpherical(const glm::vec3& spherical) { + float x = glm::cos(spherical.x) * glm::sin(spherical.y); + float y = glm::sin(-spherical.x); + float z = glm::cos(spherical.x) * glm::cos(spherical.y); + + // Round small values to 0 + if (glm::abs(x) < EPSILON) { + x = 0.0f; + } + if (glm::abs(y) < EPSILON) { + y = 0.0f; + } + if (glm::abs(z) < EPSILON) { + z = 0.0f; + } + + return spherical.z * glm::vec3(x, y, z); +} + +glm::vec3 fromSpherical(float elevation, float azimuth) { + glm::vec3 v = glm::vec3(elevation, azimuth, 1.0f); + return fromSpherical(v); +} + bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2) { glm::vec3 v1 = p0 - p1, v2 = p2 - p1; // Non-collinear vectors contained in the plane glm::vec3 n = glm::cross(v1, v2); // Plane's normal vector, pointing out of the triangle diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 6683088306..0245ca926f 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -117,6 +117,10 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2); glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); +glm::vec3 fromSpherical(const glm::vec3& spherical); + +glm::vec3 fromSpherical(float elevation, float azimuth); + bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2); glm::vec3 extractTranslation(const glm::mat4& matrix);