mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Fix crashes in entity rendering on OSX
This commit is contained in:
parent
a0ae9ee747
commit
37b184d982
6 changed files with 70 additions and 55 deletions
|
@ -91,20 +91,27 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
||||||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_particleProperties != newParticleProperties) {
|
|
||||||
|
if (resultWithReadLock<bool>([&]{ return _particleProperties != newParticleProperties; })) {
|
||||||
_timeUntilNextEmit = 0;
|
_timeUntilNextEmit = 0;
|
||||||
_particleProperties = newParticleProperties;
|
withWriteLock([&]{
|
||||||
|
_particleProperties = newParticleProperties;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_emitting = entity->getIsEmitting();
|
_emitting = entity->getIsEmitting();
|
||||||
|
|
||||||
if (_particleProperties.textures.isEmpty()) {
|
bool hasTexture = resultWithReadLock<bool>([&]{ return _particleProperties.textures.isEmpty(); });
|
||||||
|
if (hasTexture) {
|
||||||
if (_networkTexture) {
|
if (_networkTexture) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_networkTexture.reset();
|
_networkTexture.reset();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures)) {
|
bool textureNeedsUpdate = resultWithReadLock<bool>([&]{
|
||||||
|
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
||||||
|
});
|
||||||
|
if (textureNeedsUpdate) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||||
});
|
});
|
||||||
|
@ -115,15 +122,17 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
||||||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
// Fill in Uniforms structure
|
// Fill in Uniforms structure
|
||||||
ParticleUniforms particleUniforms;
|
ParticleUniforms particleUniforms;
|
||||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
withReadLock([&]{
|
||||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||||
particleUniforms.color.start = _particleProperties.getColorStart();
|
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||||
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
particleUniforms.color.start = _particleProperties.getColorStart();
|
||||||
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
particleUniforms.color.middle = _particleProperties.getColorMiddle();
|
||||||
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
particleUniforms.color.finish = _particleProperties.getColorFinish();
|
||||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
particleUniforms.color.spread = _particleProperties.getColorSpread();
|
||||||
|
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||||
|
});
|
||||||
// Update particle uniforms
|
// Update particle uniforms
|
||||||
memcpy(&_uniformBuffer.edit<ParticleUniforms>(), &particleUniforms, sizeof(ParticleUniforms));
|
memcpy(&_uniformBuffer.edit<ParticleUniforms>(), &particleUniforms, sizeof(ParticleUniforms));
|
||||||
}
|
}
|
||||||
|
@ -146,35 +155,26 @@ Item::Bound ParticleEffectEntityRenderer::getBound() {
|
||||||
|
|
||||||
static const size_t VERTEX_PER_PARTICLE = 4;
|
static const size_t VERTEX_PER_PARTICLE = 4;
|
||||||
|
|
||||||
bool ParticleEffectEntityRenderer::emitting() const {
|
ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties) {
|
||||||
return (
|
|
||||||
_emitting &&
|
|
||||||
_particleProperties.emission.rate > 0.0f &&
|
|
||||||
_particleProperties.lifespan > 0.0f &&
|
|
||||||
_particleProperties.polar.start <= _particleProperties.polar.finish
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
|
||||||
CpuParticle particle;
|
CpuParticle particle;
|
||||||
|
|
||||||
const auto& accelerationSpread = _particleProperties.emission.acceleration.spread;
|
const auto& accelerationSpread = particleProperties.emission.acceleration.spread;
|
||||||
const auto& azimuthStart = _particleProperties.azimuth.start;
|
const auto& azimuthStart = particleProperties.azimuth.start;
|
||||||
const auto& azimuthFinish = _particleProperties.azimuth.finish;
|
const auto& azimuthFinish = particleProperties.azimuth.finish;
|
||||||
const auto& emitDimensions = _particleProperties.emission.dimensions;
|
const auto& emitDimensions = particleProperties.emission.dimensions;
|
||||||
const auto& emitAcceleration = _particleProperties.emission.acceleration.target;
|
const auto& emitAcceleration = particleProperties.emission.acceleration.target;
|
||||||
auto emitOrientation = _particleProperties.emission.orientation;
|
auto emitOrientation = particleProperties.emission.orientation;
|
||||||
const auto& emitRadiusStart = glm::max(_particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
const auto& emitRadiusStart = glm::max(particleProperties.radiusStart, EPSILON); // Avoid math complications at center
|
||||||
const auto& emitSpeed = _particleProperties.emission.speed.target;
|
const auto& emitSpeed = particleProperties.emission.speed.target;
|
||||||
const auto& speedSpread = _particleProperties.emission.speed.spread;
|
const auto& speedSpread = particleProperties.emission.speed.spread;
|
||||||
const auto& polarStart = _particleProperties.polar.start;
|
const auto& polarStart = particleProperties.polar.start;
|
||||||
const auto& polarFinish = _particleProperties.polar.finish;
|
const auto& polarFinish = particleProperties.polar.finish;
|
||||||
|
|
||||||
particle.seed = randFloatInRange(-1.0f, 1.0f);
|
particle.seed = randFloatInRange(-1.0f, 1.0f);
|
||||||
particle.expiration = now + (uint64_t)(_particleProperties.lifespan * USECS_PER_SECOND);
|
particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND);
|
||||||
if (_particleProperties.emission.shouldTrail) {
|
if (particleProperties.emission.shouldTrail) {
|
||||||
particle.position = _modelTransform.getTranslation();
|
particle.position = baseTransform.getTranslation();
|
||||||
emitOrientation = _modelTransform.getRotation() * emitOrientation;
|
emitOrientation = baseTransform.getRotation() * emitOrientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position, velocity, and acceleration
|
// Position, velocity, and acceleration
|
||||||
|
@ -232,7 +232,7 @@ void ParticleEffectEntityRenderer::createParticle(uint64_t now) {
|
||||||
particle.acceleration = emitAcceleration + randFloatInRange(-1.0f, 1.0f) * accelerationSpread;
|
particle.acceleration = emitAcceleration + randFloatInRange(-1.0f, 1.0f) * accelerationSpread;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cpuParticles.push_back(particle);
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityRenderer::stepSimulation() {
|
void ParticleEffectEntityRenderer::stepSimulation() {
|
||||||
|
@ -244,14 +244,19 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
||||||
const auto now = usecTimestampNow();
|
const auto now = usecTimestampNow();
|
||||||
const auto interval = std::min<uint64_t>(USECS_PER_SECOND / 60, now - _lastSimulated);
|
const auto interval = std::min<uint64_t>(USECS_PER_SECOND / 60, now - _lastSimulated);
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
|
|
||||||
|
particle::Properties particleProperties;
|
||||||
|
withReadLock([&]{
|
||||||
|
particleProperties = _particleProperties;
|
||||||
|
});
|
||||||
|
|
||||||
if (emitting()) {
|
if (_emitting && particleProperties.emitting()) {
|
||||||
uint64_t emitInterval = (uint64_t)(USECS_PER_SECOND / _particleProperties.emission.rate);
|
uint64_t emitInterval = particleProperties.emitIntervalUsecs();
|
||||||
if (interval >= _timeUntilNextEmit) {
|
if (emitInterval > 0 && interval >= _timeUntilNextEmit) {
|
||||||
auto timeRemaining = interval;
|
auto timeRemaining = interval;
|
||||||
while (timeRemaining > _timeUntilNextEmit) {
|
while (timeRemaining > _timeUntilNextEmit) {
|
||||||
// emit particle
|
// emit particle
|
||||||
createParticle(now);
|
_cpuParticles.push_back(createParticle(now, _modelTransform, particleProperties));
|
||||||
_timeUntilNextEmit = emitInterval;
|
_timeUntilNextEmit = emitInterval;
|
||||||
if (emitInterval < timeRemaining) {
|
if (emitInterval < timeRemaining) {
|
||||||
timeRemaining -= emitInterval;
|
timeRemaining -= emitInterval;
|
||||||
|
@ -263,7 +268,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill any particles that have expired or are over the max size
|
// Kill any particles that have expired or are over the max size
|
||||||
while (_cpuParticles.size() > _particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) {
|
||||||
_cpuParticles.pop_front();
|
_cpuParticles.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,9 +93,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void createParticle(uint64_t now);
|
static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties);
|
||||||
void stepSimulation();
|
void stepSimulation();
|
||||||
bool emitting() const;
|
|
||||||
|
|
||||||
particle::Properties _particleProperties;
|
particle::Properties _particleProperties;
|
||||||
CpuParticles _cpuParticles;
|
CpuParticles _cpuParticles;
|
||||||
|
|
|
@ -30,14 +30,11 @@ TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextEntityRenderer::~TextEntityRenderer() {
|
||||||
void TextEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
if (_geometryID && geometryCache) {
|
if (_geometryID && geometryCache) {
|
||||||
geometryCache->releaseID(_geometryID);
|
geometryCache->releaseID(_geometryID);
|
||||||
}
|
}
|
||||||
delete _textRenderer;
|
|
||||||
_textRenderer = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||||
|
|
|
@ -24,14 +24,13 @@ class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
||||||
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
using Pointer = std::shared_ptr<TextEntityRenderer>;
|
||||||
public:
|
public:
|
||||||
TextEntityRenderer(const EntityItemPointer& entity);
|
TextEntityRenderer(const EntityItemPointer& entity);
|
||||||
|
~TextEntityRenderer();
|
||||||
private:
|
private:
|
||||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
int _geometryID{ 0 };
|
int _geometryID{ 0 };
|
||||||
TextRenderer3D* _textRenderer;
|
std::shared_ptr<TextRenderer3D> _textRenderer;
|
||||||
bool _faceCamera;
|
bool _faceCamera;
|
||||||
glm::vec3 _dimensions;
|
glm::vec3 _dimensions;
|
||||||
glm::vec3 _textColor;
|
glm::vec3 _textColor;
|
||||||
|
|
|
@ -104,7 +104,7 @@ bool operator!=(const Properties& a, const Properties& b) {
|
||||||
return !(a == b);
|
return !(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool particle::Properties::valid() const {
|
bool Properties::valid() const {
|
||||||
if (glm::any(glm::isnan(emission.orientation))) {
|
if (glm::any(glm::isnan(emission.orientation))) {
|
||||||
qCWarning(entities) << "Bad particle data";
|
qCWarning(entities) << "Bad particle data";
|
||||||
return false;
|
return false;
|
||||||
|
@ -133,6 +133,19 @@ bool particle::Properties::valid() const {
|
||||||
(radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS));
|
(radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Properties::emitting() const {
|
||||||
|
return emission.rate > 0.0f && lifespan > 0.0f && polar.start <= polar.finish;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Properties::emitIntervalUsecs() const {
|
||||||
|
if (emission.rate > 0.0f) {
|
||||||
|
return (uint64_t)(USECS_PER_SECOND / emission.rate);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
EntityItemPointer entity { new ParticleEffectEntityItem(entityID) };
|
||||||
entity->setProperties(properties);
|
entity->setProperties(properties);
|
||||||
|
|
|
@ -160,7 +160,9 @@ namespace particle {
|
||||||
Properties() {};
|
Properties() {};
|
||||||
Properties(const Properties& other) { *this = other; }
|
Properties(const Properties& other) { *this = other; }
|
||||||
bool valid() const;
|
bool valid() const;
|
||||||
|
bool emitting() const;
|
||||||
|
uint64_t emitIntervalUsecs() const;
|
||||||
|
|
||||||
Properties& operator =(const Properties& other) {
|
Properties& operator =(const Properties& other) {
|
||||||
color = other.color;
|
color = other.color;
|
||||||
alpha = other.alpha;
|
alpha = other.alpha;
|
||||||
|
|
Loading…
Reference in a new issue