From 050a426ed1c5d95089d1f035eb186d87793eef4f Mon Sep 17 00:00:00 2001 From: skyjake Date: Tue, 9 Jul 2013 15:53:18 +0300 Subject: [PATCH] Fixed|Renderer|Resources: Illegal access of submodel particle offsets The particle offsets are currently kept in a separate array where the indices match those of the submodels array. Fixed an out-of-bounds access of the particle offsets when spawning particles. --- doomsday/client/include/resource/models.h | 22 +++++++++++++++++--- doomsday/client/src/render/rend_particle.cpp | 9 ++++---- doomsday/client/src/resource/models.cpp | 9 +++----- doomsday/client/src/world/p_particle.cpp | 18 ++++++++-------- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/doomsday/client/include/resource/models.h b/doomsday/client/include/resource/models.h index bbe7b3835b..8c21c03ef7 100644 --- a/doomsday/client/include/resource/models.h +++ b/doomsday/client/include/resource/models.h @@ -144,7 +144,7 @@ struct ModelDef float scale[3]; typedef std::vector PtcOffsets; - PtcOffsets ptcOffset; + PtcOffsets _ptcOffset; float visualRadius; @@ -184,14 +184,14 @@ struct ModelDef SubmodelDef *addSub() { _sub.push_back(SubmodelDef()); - ptcOffset.push_back(de::Vector3f()); + _ptcOffset.push_back(de::Vector3f()); return &_sub.back(); } void clearSubs() { _sub.clear(); - ptcOffset.clear(); + _ptcOffset.clear(); } uint subCount() const @@ -227,6 +227,22 @@ struct ModelDef { return subnum < _sub.size(); } + + de::Vector3f particleOffset(unsigned int subnum) const + { + if(hasSub(subnum)) + { + DENG_ASSERT(subnum < _ptcOffset.size()); + return _ptcOffset[subnum]; + } + return de::Vector3f(); + } + + void setParticleOffset(unsigned int subnum, de::Vector3f const &off) + { + DENG_ASSERT(hasSub(subnum)); + _ptcOffset[subnum] = off; + } }; typedef ModelDef modeldef_t; diff --git a/doomsday/client/src/render/rend_particle.cpp b/doomsday/client/src/render/rend_particle.cpp index e183b2cea2..5c0f23e58c 100644 --- a/doomsday/client/src/render/rend_particle.cpp +++ b/doomsday/client/src/render/rend_particle.cpp @@ -630,10 +630,11 @@ static void renderParticles(int rtype, boolean withBlend) { // We may need to change the blending mode. newMode = - (gen->flags & PGF_SUB_BLEND ? BM_SUBTRACT : gen-> - flags & PGF_REVSUB_BLEND ? BM_REVERSE_SUBTRACT : gen-> - flags & PGF_MUL_BLEND ? BM_MUL : gen-> - flags & PGF_INVMUL_BLEND ? BM_INVERSE_MUL : BM_NORMAL); + (gen->flags & PGF_SUB_BLEND ? BM_SUBTRACT : + gen->flags & PGF_REVSUB_BLEND ? BM_REVERSE_SUBTRACT : + gen->flags & PGF_MUL_BLEND ? BM_MUL : + gen->flags & PGF_INVMUL_BLEND ? BM_INVERSE_MUL : + BM_NORMAL); if(newMode != mode) { glEnd(); diff --git a/doomsday/client/src/resource/models.cpp b/doomsday/client/src/resource/models.cpp index ca45845ae5..cdba809b6b 100644 --- a/doomsday/client/src/resource/models.cpp +++ b/doomsday/client/src/resource/models.cpp @@ -1251,6 +1251,7 @@ static void setupModel(ded_model_t& def) for(uint i = 0; i < modef->subCount(); ++i) { SubmodelDef *sub = &modef->subModelDef(i); + de::Vector3f off; if(sub->modelId) { Models_ToModel(sub->modelId)->frame(sub->frame).getBounds(min, max); @@ -1258,14 +1259,10 @@ static void setupModel(ded_model_t& def) // Apply the various scalings and offsets. for(int k = 0; k < 3; ++k) { - modef->ptcOffset[i][k] = - ((max[k] + min[k]) / 2 + sub->offset[k]) * modef->scale[k] + modef->offset[k]; + off[k] = ((max[k] + min[k]) / 2 + sub->offset[k]) * modef->scale[k] + modef->offset[k]; } } - else - { - modef->ptcOffset[i] = de::Vector3f(); - } + modef->setParticleOffset(i, off); } // Calculate visual radius for shadows. diff --git a/doomsday/client/src/world/p_particle.cpp b/doomsday/client/src/world/p_particle.cpp index e8f6754657..c0f000ce0f 100644 --- a/doomsday/client/src/world/p_particle.cpp +++ b/doomsday/client/src/world/p_particle.cpp @@ -591,24 +591,24 @@ static void P_NewParticle(ptcgen_t *gen) // Interpolate the offset. if(inter > 0 && nextmf) { - off[VX] = nextmf->ptcOffset[subidx][VX] - mf->ptcOffset[subidx][VX]; - off[VY] = nextmf->ptcOffset[subidx][VY] - mf->ptcOffset[subidx][VY]; - off[VZ] = nextmf->ptcOffset[subidx][VZ] - mf->ptcOffset[subidx][VZ]; + off[VX] = nextmf->particleOffset(subidx)[VX] - mf->particleOffset(subidx)[VX]; + off[VY] = nextmf->particleOffset(subidx)[VY] - mf->particleOffset(subidx)[VY]; + off[VZ] = nextmf->particleOffset(subidx)[VZ] - mf->particleOffset(subidx)[VZ]; off[VX] *= inter; off[VY] *= inter; off[VZ] *= inter; } - off[VX] += mf->ptcOffset[subidx][VX]; - off[VY] += mf->ptcOffset[subidx][VY]; - off[VZ] += mf->ptcOffset[subidx][VZ]; + off[VX] += mf->particleOffset(subidx)[VX]; + off[VY] += mf->particleOffset(subidx)[VY]; + off[VZ] += mf->particleOffset(subidx)[VZ]; // Apply it to the particle coords. - pt->origin[VX] += FixedMul(fineCosine[ang], FLT2FIX(off[VX])); + pt->origin[VX] += FixedMul(fineCosine[ang], FLT2FIX(off[VX])); pt->origin[VX] += FixedMul(fineCosine[ang2], FLT2FIX(off[VZ])); - pt->origin[VY] += FixedMul(finesine[ang], FLT2FIX(off[VX])); - pt->origin[VY] += FixedMul(finesine[ang2], FLT2FIX(off[VZ])); + pt->origin[VY] += FixedMul(finesine[ang], FLT2FIX(off[VX])); + pt->origin[VY] += FixedMul(finesine[ang2], FLT2FIX(off[VZ])); pt->origin[VZ] += FLT2FIX(off[VY]); } }