Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
#5919: Fix crash when updating particle geometry.
Updating a RenderableGeometry instance with an empty set of vertices will clear the structure, including its shader.
  • Loading branch information
codereader committed Mar 27, 2022
1 parent 5ad75e5 commit 1dc59bf
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 17 deletions.
7 changes: 2 additions & 5 deletions libs/render/RenderableGeometry.h
Expand Up @@ -2,7 +2,6 @@

#include <vector>
#include "igeometryrenderer.h"
#include "isurfacerenderer.h"
#include "irenderableobject.h"
#include "irender.h"

Expand Down Expand Up @@ -117,7 +116,7 @@ class RenderableGeometry :
RenderableGeometry(const RenderableGeometry& other) = delete;
RenderableGeometry& operator=(const RenderableGeometry& other) = delete;

virtual ~RenderableGeometry()
virtual ~RenderableGeometry() override
{
clear();
}
Expand All @@ -127,9 +126,7 @@ class RenderableGeometry :
// to be different from the last update.
void update(const ShaderPtr& shader)
{
bool shaderChanged = _shader != shader;

if (shaderChanged)
if (_shader != shader)
{
clear();
}
Expand Down
9 changes: 8 additions & 1 deletion radiantcore/particles/RenderableParticle.cpp
Expand Up @@ -49,9 +49,16 @@ void RenderableParticle::update(const Matrix4& viewRotation, const Matrix4& loca
continue;
}

// Update the particle geometry
// Update the particle quads
stage->update(time, invViewRotation);

// Check if the stage is empty, otherwise remove any geometry
if (stage->getNumQuads() == 0)
{
stage->clear();
continue;
}

// Attach the geometry to the shader
stage->submitGeometry(pair.second.shader, localToWorld);

Expand Down
28 changes: 17 additions & 11 deletions radiantcore/particles/RenderableParticleStage.cpp
Expand Up @@ -75,13 +75,18 @@ void RenderableParticleStage::submitGeometry(const ShaderPtr& shader, const Matr
RenderableGeometry::update(shader);
}

std::size_t RenderableParticleStage::getNumQuads() const
{
return (_bunches[0] ? _bunches[0]->getNumQuads() : 0) +
(_bunches[1] ? _bunches[1]->getNumQuads() : 0);
}

void RenderableParticleStage::updateGeometry()
{
std::vector<render::RenderVertex> vertices;
std::vector<unsigned int> indices;

auto numQuads = (_bunches[0] ? _bunches[0]->getNumQuads() : 0) +
(_bunches[1] ? _bunches[1]->getNumQuads() : 0);
auto numQuads = getNumQuads();

if (numQuads == 0)
{
Expand Down Expand Up @@ -169,7 +174,7 @@ void RenderableParticleStage::ensureBunches(std::size_t localTimeMSec)
{
// This is the only active bunch (the first one), there is no previous cycle
// it's possible that this one is already existing.
if (_bunches[0] == NULL || _bunches[0]->getIndex() != curCycleIndex)
if (!_bunches[0] || _bunches[0]->getIndex() != curCycleIndex)
{
// First bunch is not matching, re-assign
_bunches[0] = createBunch(curCycleIndex);
Expand All @@ -194,7 +199,7 @@ void RenderableParticleStage::ensureBunches(std::size_t localTimeMSec)
// We've exceeded the maximum number of cycles
_bunches[0].reset();
}
else if (cur != NULL)
else if (cur)
{
_bunches[0] = cur;
}
Expand All @@ -208,7 +213,7 @@ void RenderableParticleStage::ensureBunches(std::size_t localTimeMSec)
// We've exceeded the maximum number of cycles
_bunches[1].reset();
}
else if (prev != NULL)
else if (prev)
{
_bunches[1] = prev;
}
Expand All @@ -221,8 +226,8 @@ void RenderableParticleStage::ensureBunches(std::size_t localTimeMSec)

RenderableParticleBunchPtr RenderableParticleStage::createBunch(std::size_t cycleIndex)
{
return RenderableParticleBunchPtr(new RenderableParticleBunch(
cycleIndex, getSeed(cycleIndex), _stageDef, _viewRotation, _direction, _entityColour));
return std::make_shared<RenderableParticleBunch>(cycleIndex, getSeed(cycleIndex),
_stageDef, _viewRotation, _direction, _entityColour);
}

Rand48::result_type RenderableParticleStage::getSeed(std::size_t cycleIndex)
Expand All @@ -232,11 +237,12 @@ Rand48::result_type RenderableParticleStage::getSeed(std::size_t cycleIndex)

RenderableParticleBunchPtr RenderableParticleStage::getExistingBunchByIndex(std::size_t index)
{
if (_bunches[0] != NULL && _bunches[0]->getIndex() == index)
if (_bunches[0] && _bunches[0]->getIndex() == index)
{
return _bunches[0];
}
else if (_bunches[1] != NULL && _bunches[1]->getIndex() == index)

if (_bunches[1] && _bunches[1]->getIndex() == index)
{
return _bunches[1];
}
Expand All @@ -246,13 +252,13 @@ RenderableParticleBunchPtr RenderableParticleStage::getExistingBunchByIndex(std:

void RenderableParticleStage::calculateBounds()
{
if (_bunches[0] != NULL)
if (_bunches[0])
{
// Get one of our seed values
_bounds.includeAABB(_bunches[0]->getBounds());
}

if (_bunches[1] != NULL)
if (_bunches[1])
{
_bounds.includeAABB(_bunches[1]->getBounds());
}
Expand Down
3 changes: 3 additions & 0 deletions radiantcore/particles/RenderableParticleStage.h
Expand Up @@ -60,6 +60,9 @@ class RenderableParticleStage :
/// Return the stage definition associated with this renderable
const IStageDef& getDef() const;

// Returns the number of quads in this stage
std::size_t getNumQuads() const;

protected:
void updateGeometry() override;

Expand Down

0 comments on commit 1dc59bf

Please sign in to comment.