Merge branch 'master' of https://github.com/highfidelity/hifi into animationGroupSettings

This commit is contained in:
Brad Hefta-Gaub 2015-10-07 19:55:01 -07:00
commit b479dd0a12
15 changed files with 337 additions and 123 deletions

View file

@ -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;

View file

@ -142,8 +142,15 @@ Item {
color: root.fontColor;
font.pixelSize: root.fontSize
visible: root.expanded;
text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " +
root.avatarMixerPps + "pps";
text: "Avatar Mixer In: " + root.avatarMixerInKbps + " kbps, " +
root.avatarMixerInPps + "pps";
}
Text {
color: root.fontColor;
font.pixelSize: root.fontSize
visible: root.expanded;
text: "Avatar Mixer Out: " + root.avatarMixerOutKbps + " kbps, " +
root.avatarMixerOutPps + "pps";
}
Text {
color: root.fontColor;

View file

@ -167,15 +167,15 @@ void Stats::updateStats(bool force) {
if (_expanded || force) {
SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer);
if (avatarMixer) {
STAT_UPDATE(avatarMixerKbps, roundf(
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer) +
bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
STAT_UPDATE(avatarMixerPps, roundf(
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer) +
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
STAT_UPDATE(avatarMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
} else {
STAT_UPDATE(avatarMixerKbps, -1);
STAT_UPDATE(avatarMixerPps, -1);
STAT_UPDATE(avatarMixerInKbps, -1);
STAT_UPDATE(avatarMixerInPps, -1);
STAT_UPDATE(avatarMixerOutKbps, -1);
STAT_UPDATE(avatarMixerOutPps, -1);
}
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
if (audioMixerNode || force) {

View file

@ -47,8 +47,10 @@ class Stats : public QQuickItem {
STATS_PROPERTY(QVector3D, position, QVector3D(0, 0, 0) )
STATS_PROPERTY(float, velocity, 0)
STATS_PROPERTY(float, yaw, 0)
STATS_PROPERTY(int, avatarMixerKbps, 0)
STATS_PROPERTY(int, avatarMixerPps, 0)
STATS_PROPERTY(int, avatarMixerInKbps, 0)
STATS_PROPERTY(int, avatarMixerInPps, 0)
STATS_PROPERTY(int, avatarMixerOutKbps, 0)
STATS_PROPERTY(int, avatarMixerOutPps, 0)
STATS_PROPERTY(int, audioMixerKbps, 0)
STATS_PROPERTY(int, audioMixerPps, 0)
STATS_PROPERTY(int, downloads, 0)
@ -122,8 +124,10 @@ signals:
void positionChanged();
void velocityChanged();
void yawChanged();
void avatarMixerKbpsChanged();
void avatarMixerPpsChanged();
void avatarMixerInKbpsChanged();
void avatarMixerInPpsChanged();
void avatarMixerOutKbpsChanged();
void avatarMixerOutPpsChanged();
void audioMixerKbpsChanged();
void audioMixerPpsChanged();
void downloadsChanged();

View file

@ -622,7 +622,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);
@ -1323,7 +1323,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);

View file

@ -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(); }

View file

@ -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.

View file

@ -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();

View file

@ -109,7 +109,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0);
} else {
attachement = GL_DEPTH_STENCIL_ATTACHMENT;
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachement, GL_RENDERBUFFER, gltexture->_texture);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0);
}
(void) CHECK_GL_ERROR();
}

View file

@ -50,6 +50,11 @@ public:
case gpu::DEPTH:
texel.internalFormat = GL_DEPTH_COMPONENT;
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
@ -65,11 +70,6 @@ public:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_BYTE;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
@ -160,8 +160,8 @@ public:
}
case gpu::FLOAT: {
texel.internalFormat = GL_DEPTH_COMPONENT32F;
break;
}
break;
}
case gpu::UINT16:
case gpu::INT16:
case gpu::NUINT16:
@ -182,6 +182,11 @@ public:
}
}
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_INT_24_8;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
@ -198,11 +203,6 @@ public:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
case gpu::DEPTH_STENCIL:
texel.type = GL_UNSIGNED_BYTE;
texel.format = GL_DEPTH_STENCIL;
texel.internalFormat = GL_DEPTH24_STENCIL8;
break;
default:
qCDebug(gpulogging) << "Unknown combination of texel format";
}
@ -341,32 +341,19 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
auto semantic = texture.getTexelFormat().getSemantic();
if (semantic == gpu::DEPTH_STENCIL) {
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &object->_texture);
glTexImage2D(GL_TEXTURE_2D, 0,
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
texelFormat.format, texelFormat.type, bytes);
glGenRenderbuffers(1, &object->_texture);
glBindRenderbuffer(GL_RENDERBUFFER, object->_texture);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, texture.getWidth(), texture.getHeight());
// At this point the mip pixels have been loaded, we can notify
texture.notifyMipFaceGPULoaded(0, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
} else {
glTexImage2D(GL_TEXTURE_2D, 0,
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
texelFormat.format, texelFormat.type, bytes);
if (bytes && texture.isAutogenerateMips()) {
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
object->_target = GL_TEXTURE_2D;
syncSampler(texture.getSampler(), texture.getType(), object);
if (bytes && texture.isAutogenerateMips()) {
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
object->_target = GL_TEXTURE_2D;
syncSampler(texture.getSampler(), texture.getType(), object);
// At this point the mip pixels have been loaded, we can notify
texture.notifyMipFaceGPULoaded(0, 0);

View file

@ -19,17 +19,17 @@ BandwidthRecorder::Channel::Channel() {
}
float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() {
float delt = _input.getEventDeltaAverage();
if (delt > 0.0f) {
return (1.0f / delt);
float averageTimeBetweenPackets = _input.getEventDeltaAverage();
if (averageTimeBetweenPackets > 0.0f) {
return (1.0f / averageTimeBetweenPackets);
}
return 0.0f;
}
float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() {
float delt = _input.getEventDeltaAverage();
if (delt > 0.0f) {
return (1.0f / _output.getEventDeltaAverage());
float averageTimeBetweenPackets = _output.getEventDeltaAverage();
if (averageTimeBetweenPackets > 0.0f) {
return (1.0f / averageTimeBetweenPackets);
}
return 0.0f;
}

View file

@ -71,7 +71,7 @@ void FramebufferCache::createPrimaryFramebuffer() {
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
auto stencilFormat = gpu::Element(gpu::VEC2, gpu::UINT32, gpu::DEPTH_STENCIL);
auto stencilFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
_primaryStencilTexture = gpu::TexturePointer(gpu::Texture::create2D(stencilFormat, width, height, defaultSampler));
_primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);

View file

@ -212,7 +212,11 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati
Transform transform;
if (state.clusterBuffer) {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
if (model->_cauterizeBones) {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer);
} else {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
}
} else {
if (model->_cauterizeBones) {
transform = Transform(state.cauterizedClusterMatrices[0]);

View file

@ -167,9 +167,7 @@ bool Model::updateGeometry() {
MeshState state;
state.clusterMatrices.resize(mesh.clusters.size());
state.cauterizedClusterMatrices.resize(mesh.clusters.size());
if (mesh.clusters.size() > 1) {
state.clusterBuffer = std::make_shared<gpu::Buffer>(mesh.clusters.size() * sizeof(glm::mat4), nullptr);
}
_meshStates.append(state);
auto buffer = std::make_shared<gpu::Buffer>();
@ -1006,15 +1004,21 @@ void Model::updateClusterMatrices() {
}
}
// Once computed the cluster matrices, update the buffer
if (state.clusterBuffer) {
const float* bones;
if (_cauterizeBones) {
bones = (const float*)state.cauterizedClusterMatrices.constData();
// Once computed the cluster matrices, update the buffer(s)
if (mesh.clusters.size() > 1) {
if (!state.clusterBuffer) {
state.clusterBuffer = std::make_shared<gpu::Buffer>(state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
} else {
bones = (const float*)state.clusterMatrices.constData();
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData());
}
if (!_cauterizeBoneSet.empty() && (state.cauterizedClusterMatrices.size() > 1)) {
if (!state.cauterizedClusterBuffer) {
state.cauterizedClusterBuffer = std::make_shared<gpu::Buffer>(state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
} else {
state.cauterizedClusterBuffer->setSubData(0, state.cauterizedClusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.cauterizedClusterMatrices.constData());
}
}
state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) bones);
}
}

View file

@ -256,6 +256,8 @@ protected:
QVector<glm::mat4> clusterMatrices;
QVector<glm::mat4> cauterizedClusterMatrices;
gpu::BufferPointer clusterBuffer;
gpu::BufferPointer cauterizedClusterBuffer;
};
QVector<MeshState> _meshStates;