Skip to content

Commit

Permalink
Refactor|ResourceSystem: Cleaned up access to Sprite resources
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Nov 20, 2013
1 parent bdebb03 commit e34613b
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 69 deletions.
40 changes: 37 additions & 3 deletions doomsday/client/include/resource/resourcesystem.h
Expand Up @@ -65,6 +65,9 @@ class ResourceSystem : public de::System
/// The referenced color palette could not be found. @ingroup errors
DENG2_ERROR(MissingColorPaletteError);

/// The referenced sprite could not be found. @ingroup errors
DENG2_ERROR(MissingSpriteError);

typedef QList<Sprite *> SpriteSet;
public:
/**
Expand Down Expand Up @@ -111,18 +114,49 @@ class ResourceSystem : public de::System
*/
void initSprites();

/**
* Destroys all sprites in all sprite sets.
*/
void clearAllSprites();

/**
* Returns the total number of sprite @em sets.
*/
int spriteCount();

Sprite *spritePtr(int spriteId, int frame);
/**
* Returns @c true iff a sprite exists for the specified @a spriteId and @a frame;
*
* @param spriteId Unique identifier of the sprite set.
* @param frame Frame number from the set to lookup.
*/
bool hasSprite(int spriteId, int frame);

Sprite &sprite(int spriteId, int frame);
/**
* Returns a pointer to the identified Sprite.
*
* @see hasSprite()
*/
inline Sprite *spritePtr(int spriteId, int frame) {
return hasSprite(spriteId, frame)? spriteSet(spriteId)[frame] : 0;
}

/**
* Lookup the sprite set for the specified @a spriteId.
*
* @param spriteId Unique identifier of the sprite set.
* @return The identified SpriteSet.
*/
SpriteSet &spriteSet(int spriteId);

#ifdef __CLIENT__
void cacheSpriteSet(int spriteId, de::MaterialVariantSpec const &spec);
/**
* Precache resources from the set associated with the specified @a spriteId.
*
* @param spriteId Unique identifier of the sprite set to cache.
* @param materialSpec Specification to use when caching materials.
*/
void cacheSpriteSet(int spriteId, de::MaterialVariantSpec const &materialSpec);
#endif

/**
Expand Down
10 changes: 5 additions & 5 deletions doomsday/client/src/render/api_render.cpp
Expand Up @@ -46,17 +46,17 @@ DENG_EXTERN_C boolean R_GetSpriteInfo(int spriteId, int frame, spriteinfo_t *inf

de::zapPtr(info);

Sprite *sprite = App_ResourceSystem().spritePtr(spriteId, frame);
if(!sprite)
if(!App_ResourceSystem().hasSprite(spriteId, frame))
{
LOG_WARNING("Invalid sprite id (%i) and/or frame index (%i).")
<< spriteId << frame;
return false;
}

de::zapPtr(info);
info->material = sprite->viewAngle(0).material;
info->flip = sprite->viewAngle(0).mirrorX;
SpriteViewAngle const &sprViewAngle =
App_ResourceSystem().spritePtr(spriteId, frame)->viewAngle(0);
info->material = sprViewAngle.material;
info->flip = sprViewAngle.mirrorX;

if(novideo)
{
Expand Down
7 changes: 3 additions & 4 deletions doomsday/client/src/render/billboard.cpp
Expand Up @@ -208,10 +208,9 @@ static void setupPSpriteParams(rendpspriteparams_t *params, vispsprite_t *spr)
int const frameIdx = psp->statePtr->frame;
float const offScaleY = weaponOffsetScaleY / 1000.0f;

Sprite const *sprite = &App_ResourceSystem().sprite(spriteIdx, frameIdx);

Material *material = sprite->viewAngle(0).material;
bool flip = sprite->viewAngle(0).mirrorX;
SpriteViewAngle const &sprViewAngle = App_ResourceSystem().spritePtr(spriteIdx, frameIdx)->viewAngle(0);
Material *material = sprViewAngle.material;
bool flip = sprViewAngle.mirrorX;

MaterialVariantSpec const &spec =
App_Materials().variantSpec(PSpriteContext, 0, 1, 0, 0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
Expand Down
22 changes: 12 additions & 10 deletions doomsday/client/src/render/rend_main.cpp
Expand Up @@ -2669,19 +2669,21 @@ static int projectSpriteWorker(mobj_t &mo, void * /*context*/)

if(cluster.visCeiling().surface().hasSkyMaskedMaterial())
{
Sprite *sprite = App_ResourceSystem().spritePtr(mo.sprite, mo.frame);
if(sprite->hasViewAngle(0))
if(Sprite *sprite = App_ResourceSystem().spritePtr(mo.sprite, mo.frame))
{
Material *material = sprite->viewAngle(0).material;
if(!(mo.dPlayer && (mo.dPlayer->flags & DDPF_CAMERA))
&& mo.origin[VZ] <= cluster.visCeiling().heightSmoothed()
&& mo.origin[VZ] >= cluster.visFloor().heightSmoothed())
if(sprite->hasViewAngle(0))
{
coord_t visibleTop = mo.origin[VZ] + material->height();
if(visibleTop > cluster.sector().map().skyFixCeiling())
Material *material = sprite->viewAngle(0).material;
if(!(mo.dPlayer && (mo.dPlayer->flags & DDPF_CAMERA))
&& mo.origin[VZ] <= cluster.visCeiling().heightSmoothed()
&& mo.origin[VZ] >= cluster.visFloor().heightSmoothed())
{
// Raise skyfix ceiling.
cluster.sector().map().setSkyFixCeiling(visibleTop + 16/*leeway*/);
coord_t visibleTop = mo.origin[VZ] + material->height();
if(visibleTop > cluster.sector().map().skyFixCeiling())
{
// Raise skyfix ceiling.
cluster.sector().map().setSkyFixCeiling(visibleTop + 16/*leeway*/);
}
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions doomsday/client/src/resource/models.cpp
Expand Up @@ -946,9 +946,8 @@ static void scaleModel(modeldef_t &mf, float destHeight, float offset)
mf.offset[VY] = -bottom * scale + offset;
}

static void scaleModelToSprite(modeldef_t &mf, int spriteIdx, int frameIdx)
static void scaleModelToSprite(modeldef_t &mf, Sprite *sprite)
{
Sprite *sprite = App_ResourceSystem().spritePtr(spriteIdx, frameIdx);
if(!sprite) return;
if(!sprite->hasViewAngle(0)) return;

Expand Down Expand Up @@ -1225,7 +1224,10 @@ static void setupModel(ded_model_t& def)
sprFrame = modef->state->frame;
}

scaleModelToSprite(*modef, sprNum, sprFrame);
if(Sprite *sprite = App_ResourceSystem().spritePtr(sprNum, sprFrame))
{
scaleModelToSprite(*modef, sprite);
}
}

if(modef->state)
Expand Down
21 changes: 4 additions & 17 deletions doomsday/client/src/resource/resourcesystem.cpp
Expand Up @@ -661,29 +661,16 @@ int ResourceSystem::spriteCount()
return d->spriteGroups.count();
}

Sprite *ResourceSystem::spritePtr(int spriteId, int frame)
bool ResourceSystem::hasSprite(int spriteId, int frame)
{
if(Instance::SpriteGroup *group = d->spriteGroup(spriteId))
{
if(frame >= 0 && frame < group->sprites.count())
{
return group->sprites.at(frame);
return true;
}
}
return 0;
}

Sprite &ResourceSystem::sprite(int spriteId, int frame)
{
if(Instance::SpriteGroup *group = d->spriteGroup(spriteId))
{
if(frame >= 0 && frame < group->sprites.count())
{
return *group->sprites.at(frame);
}
throw Error("sprite", QString("Invalid sprite frame %1").arg(frame));
}
throw Error("sprite", QString("Invalid sprite id %1").arg(spriteId));
return false;
}

ResourceSystem::SpriteSet &ResourceSystem::spriteSet(int spriteId)
Expand All @@ -692,7 +679,7 @@ ResourceSystem::SpriteSet &ResourceSystem::spriteSet(int spriteId)
{
return group->sprites;
}
throw Error("spriteSet", QString("Invalid sprite id %1").arg(spriteId));
throw MissingSpriteError("ResourceSystem::spriteSet", "Invalid sprite id " + String::number(spriteId));
}

Textures &ResourceSystem::textures()
Expand Down
61 changes: 34 additions & 27 deletions doomsday/client/src/world/p_mobj.cpp
Expand Up @@ -344,33 +344,37 @@ void Mobj_GenerateLumobjs(mobj_t *mo)

Mobj_UnlinkLumobjs(mo);

if(!Mobj_HasCluster(*mo))
return;
if(!Mobj_HasCluster(*mo)) return;
SectorCluster &cluster = Mobj_Cluster(*mo);

if(!(((mo->state && (mo->state->flags & STF_FULLBRIGHT)) &&
!(mo->ddFlags & DDMF_DONTDRAW)) ||
(mo->ddFlags & DDMF_ALWAYSLIT)))
{
return;
}

// Are the automatically calculated light values for fullbright sprite frames in use?
if(mo->state &&
(!mobjAutoLights || (mo->state->flags & STF_NOAUTOLIGHT)) &&
!stateLights[mo->state - states])
{
return;
}

// If the mobj's origin is outside the BSP leaf it is linked within, then
// this means it is outside the playable map (and no light should be emitted).
/// @todo Optimize: Mobj_Link() should do this and flag the mobj accordingly.
if(!Mobj_BspLeafAtOrigin(*mo).polyContains(mo->origin))
{
return;
}

Sprite *sprite = App_ResourceSystem().spritePtr(mo->sprite, mo->frame);
if(!sprite) return;

// Always use the front rotation when determining light properties.
if(!sprite->hasViewAngle(0)) return;

Material *mat = sprite->viewAngle(0).material;

MaterialSnapshot const &ms = mat->prepare(Rend_SpriteMaterialSpec());
Expand Down Expand Up @@ -463,26 +467,28 @@ float Mobj_ShadowStrength(mobj_t *mo)
if(!currentModelDefForMobj(*mo))
{
if(Sprite *sprite = App_ResourceSystem().spritePtr(mo->sprite, mo->frame))
if(sprite->hasViewAngle(0))
{
Material *mat = sprite->viewAngle(0).material;
// Ensure we've prepared this.
MaterialSnapshot const &ms = mat->prepare(Rend_SpriteMaterialSpec());

averagealpha_analysis_t const *aa = (averagealpha_analysis_t const *)
ms.texture(MTU_PRIMARY).generalCase().analysisDataPointer(Texture::AverageAlphaAnalysis);
DENG2_ASSERT(aa != 0);

// We use an average which factors in the coverage ratio
// of alpha:non-alpha pixels.
/// @todo Constant weights could stand some tweaking...
float weightedSpriteAlpha = aa->alpha * (0.4f + (1 - aa->coverage) * 0.6f);

// Almost entirely translucent sprite? => no shadow.
if(weightedSpriteAlpha < minSpriteAlphaLimit) return 0;

// Apply this factor.
strength *= de::min(1.f, .2f + weightedSpriteAlpha);
if(sprite->hasViewAngle(0))
{
Material *mat = sprite->viewAngle(0).material;
// Ensure we've prepared this.
MaterialSnapshot const &ms = mat->prepare(Rend_SpriteMaterialSpec());

averagealpha_analysis_t const *aa = (averagealpha_analysis_t const *)
ms.texture(MTU_PRIMARY).generalCase().analysisDataPointer(Texture::AverageAlphaAnalysis);
DENG2_ASSERT(aa != 0);

// We use an average which factors in the coverage ratio
// of alpha:non-alpha pixels.
/// @todo Constant weights could stand some tweaking...
float weightedSpriteAlpha = aa->alpha * (0.4f + (1 - aa->coverage) * 0.6f);

// Almost entirely translucent sprite? => no shadow.
if(weightedSpriteAlpha < minSpriteAlphaLimit) return 0;

// Apply this factor.
strength *= de::min(1.f, .2f + weightedSpriteAlpha);
}
}
}

Expand Down Expand Up @@ -583,13 +589,14 @@ coord_t Mobj_VisualRadius(mobj_t const &mobj)

// Use the sprite frame's width?
if(Sprite *sprite = App_ResourceSystem().spritePtr(mobj.sprite, mobj.frame))
if(sprite->hasViewAngle(0))
{
Material *material = sprite->viewAngle(0).material;
MaterialSnapshot const &ms = material->prepare(Rend_SpriteMaterialSpec());
return ms.width() / 2;
if(sprite->hasViewAngle(0))
{
Material *material = sprite->viewAngle(0).material;
MaterialSnapshot const &ms = material->prepare(Rend_SpriteMaterialSpec());
return ms.width() / 2;
}
}

#endif

// Use the physical radius.
Expand Down

0 comments on commit e34613b

Please sign in to comment.