Skip to content

Commit

Permalink
Refactor|Renderer|SkyDrawable: Moved sky model animation state to Sky…
Browse files Browse the repository at this point in the history
…Drawable::Animator
  • Loading branch information
danij-deng committed Sep 7, 2014
1 parent efcc58f commit cf84047
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 61 deletions.
58 changes: 40 additions & 18 deletions doomsday/client/include/render/skydrawable.h
Expand Up @@ -42,17 +42,13 @@ class Sky;
class SkyDrawable
{
public:
/// Required model is missing. @ingroup errors
DENG2_ERROR(MissingModelError);
/// Required model config is missing. @ingroup errors
DENG2_ERROR(MissingModelConfigError);

struct ModelData
struct ModelConfig
{
de::Record const *def; // Sky model def
ModelDef *model;
int frame;
int timer;
int maxTimer;
float yaw;
};

/**
Expand All @@ -63,10 +59,13 @@ class SkyDrawable
class Animator
{
public:
/// Required layer is missing. @ingroup errors
DENG2_ERROR(MissingLayerError);
/// Required layer state is missing. @ingroup errors
DENG2_ERROR(MissingLayerStateError);

struct LayerData
/// Required model state is missing. @ingroup errors
DENG2_ERROR(MissingModelStateError);

struct LayerState
{
bool active;
bool masked;
Expand All @@ -75,6 +74,14 @@ class SkyDrawable
float fadeOutLimit;
};

struct ModelState
{
int frame;
int timer;
int maxTimer;
float yaw;
};

public:
Animator();
Animator(SkyDrawable &sky);
Expand All @@ -93,22 +100,37 @@ class SkyDrawable
float horizonOffset() const;

/**
* Determines whether the specified sky layer @a index is valid.
* Determines whether the specified animation layer state @a index is valid.
* @see layer()
*/
bool hasLayer(int index) const;

/**
* Lookup a sky layer by it's unique @a index.
* Lookup an animation layer state by it's unique @a index.
* @see hasLayer()
*/
LayerData &layer(int index);
LayerState &layer(int index);

/// @copydoc layer()
LayerData const &layer(int index) const;
LayerState const &layer(int index) const;

int firstActiveLayer() const;

/**
* Determines whether the specified animation model state @a index is valid.
* @see model()
*/
bool hasModel(int index) const;

/**
* Lookup an animation model state by it's unique @a index.
* @see hasModel()
*/
ModelState &model(int index);

/// @copydoc model()
ModelState const &model(int index) const;

/**
* Advances the animation state.
*
Expand Down Expand Up @@ -139,19 +161,19 @@ class SkyDrawable
void draw(Animator const *animator = 0) const;

/**
* Determines whether the specified sky model @a index is valid.
* Determines whether the specified model config @a index is valid.
* @see model()
*/
bool hasModel(int index) const;

/**
* Lookup a sky model by it's unique @a index.
* Lookup a model config by it's unique @a index.
* @see hasModel()
*/
ModelData &model(int index);
ModelConfig &model(int index);

/// @copydoc model()
ModelData const &model(int index) const;
ModelConfig const &model(int index) const;

public:
static de::MaterialVariantSpec const &layerMaterialSpec(bool masked);
Expand Down
126 changes: 83 additions & 43 deletions doomsday/client/src/render/skydrawable.cpp
Expand Up @@ -87,7 +87,7 @@ struct Hemisphere
/**
* Determine the material to use for the given sky @a layer.
*/
static Material *chooseMaterialForSkyLayer(SkyDrawable::Animator::LayerData const &layer)
static Material *chooseMaterialForSkyLayer(SkyDrawable::Animator::LayerState const &layer)
{
if(renderTextures == 0)
{
Expand All @@ -108,7 +108,7 @@ struct Hemisphere
* Determine the cap/fadeout color to use for the given sky @a layer.
*/
static Vector3f chooseCapColor(SphereComponent hemisphere,
SkyDrawable::Animator::LayerData const &layer,
SkyDrawable::Animator::LayerState const &layer,
bool *needFadeOut = 0)
{
if(Material *mat = chooseMaterialForSkyLayer(layer))
Expand Down Expand Up @@ -201,7 +201,7 @@ struct Hemisphere

for(int i = firstActiveLayer; i < MAX_LAYERS; ++i)
{
SkyDrawable::Animator::LayerData const &layer = animator->layer(i);
SkyDrawable::Animator::LayerState const &layer = animator->layer(i);

if(!layer.active) continue;

Expand Down Expand Up @@ -358,7 +358,7 @@ using namespace ::internal;

DENG2_PIMPL(SkyDrawable)
{
ModelData models[MAX_MODELS];
ModelConfig models[MAX_MODELS];
bool haveModels = false;
bool alwaysDrawSphere = false;

Expand Down Expand Up @@ -420,8 +420,10 @@ DENG2_PIMPL(SkyDrawable)

for(int i = 0; i < MAX_MODELS; ++i)
{
ModelData const &mdata = self.model(i);
Record const *skyModelDef = mdata.def;
ModelConfig const &mcfg = self.model(i);
Record const *skyModelDef = mcfg.def;
ModelDef *modef = mcfg.model;
Animator::ModelState const &mstate = animator->model(i);

if(!skyModelDef) continue;

Expand All @@ -438,16 +440,16 @@ DENG2_PIMPL(SkyDrawable)
vis.pose.distance = 1;

Vector2f rotate(skyModelDef->get("rotate"));
vis.pose.yaw = mdata.yaw;
vis.pose.yaw = mstate.yaw;
vis.pose.extraYawAngle = vis.pose.yawAngleOffset = rotate.x;
vis.pose.extraPitchAngle = vis.pose.pitchAngleOffset = rotate.y;

drawmodelparams_t &visModel = *VS_MODEL(&vis);
visModel.inter = (mdata.maxTimer > 0 ? mdata.timer / float(mdata.maxTimer) : 0);
visModel.mf = mdata.model;
visModel.inter = (mstate.maxTimer > 0 ? mstate.timer / float(mstate.maxTimer) : 0);
visModel.mf = modef;
visModel.alwaysInterpolate = true;
visModel.shineTranslateWithViewerPos = true;
resSys().setModelDefFrame(*mdata.model, mdata.frame);
resSys().setModelDefFrame(*modef, mstate.frame);

vis.light.ambientColor = Vector4f(skyModelDef->get("color"), 1);

Expand Down Expand Up @@ -483,24 +485,19 @@ void SkyDrawable::setupModels(defn::Sky const *def)
for(int i = 0; i < def->modelCount(); ++i)
{
Record const &modef = def->model(i);
ModelData &mdata = model(i);
ModelConfig &mcfg = model(i);

// Is the model ID set?
try
{
mdata.model = &d->resSys().modelDef(modef.gets("id"));
if(!mdata.model->subCount())
mcfg.model = &d->resSys().modelDef(modef.gets("id"));
if(mcfg.model->subCount())
{
continue;
}

// There is a model here.
d->haveModels = true;
mcfg.def = modef.accessedRecordPtr();

mdata.def = modef.accessedRecordPtr();
mdata.maxTimer = int(TICSPERSEC * modef.getf("frameInterval"));
mdata.yaw = modef.getf("yaw");
mdata.frame = mdata.model->subModelDef(0).frame;
// There is a model here.
d->haveModels = true;
}
}
catch(ResourceSystem::MissingModelDefError const &)
{} // Ignore this error.
Expand All @@ -512,19 +509,19 @@ bool SkyDrawable::hasModel(int index) const
return (index >= 0 && index < MAX_MODELS);
}

SkyDrawable::ModelData &SkyDrawable::model(int index)
SkyDrawable::ModelConfig &SkyDrawable::model(int index)
{
if(hasModel(index))
{
return d->models[index];
}
/// @throw MissingModelError An invalid model index was specified.
throw MissingModelError("SkyDrawable::model", "Invalid model index #" + String::number(index) + ".");
/// @throw MissingModelConfigError An invalid model index was specified.
throw MissingModelConfigError("SkyDrawable::model", "Invalid model config index #" + String::number(index) + ".");
}

SkyDrawable::ModelData const &SkyDrawable::model(int index) const
SkyDrawable::ModelConfig const &SkyDrawable::model(int index) const
{
return const_cast<ModelData const &>(const_cast<SkyDrawable *>(this)->model(index));
return const_cast<ModelConfig const &>(const_cast<SkyDrawable *>(this)->model(index));
}

void SkyDrawable::cacheDrawableAssets(Sky const *sky)
Expand All @@ -543,7 +540,7 @@ void SkyDrawable::cacheDrawableAssets(Sky const *sky)
{
for(int i = 0; i < MAX_MODELS; ++i)
{
ModelData &mdata = model(i);
ModelConfig &mdata = model(i);
if(!mdata.def) continue;

d->resSys().cache(mdata.model);
Expand Down Expand Up @@ -600,12 +597,15 @@ DENG2_PIMPL_NOREF(SkyDrawable::Animator)
float height = 1;
float horizonOffset = 0;

LayerData layers[MAX_LAYERS];
LayerState layers[MAX_LAYERS];
int firstActiveLayer = -1; ///< @c -1= no active layers.

ModelState models[MAX_MODELS];

Instance(SkyDrawable *sky = 0) : sky(sky)
{
de::zap(layers);
de::zap(models);
}
};

Expand All @@ -621,6 +621,25 @@ SkyDrawable::Animator::~Animator()
void SkyDrawable::Animator::setSky(SkyDrawable *sky)
{
d->sky = sky;

// (Re)Initalize animation states.
de::zap(d->layers);
de::zap(d->models);

for(int i = 0; i < MAX_MODELS; ++i)
{
ModelState &mstate = model(i);

// Is this model in use?
SkyDrawable::ModelConfig const &mdata = sky->model(i);
if(mdata.def)
{
Record const *skyModelDef = mdata.def;
mstate.maxTimer = int(TICSPERSEC * skyModelDef->getf("frameInterval"));
mstate.yaw = skyModelDef->getf("yaw");
mstate.frame = mdata.model->subModelDef(0).frame;
}
}
}

SkyDrawable &SkyDrawable::Animator::sky() const
Expand All @@ -640,7 +659,7 @@ SkyDrawable::Animator &SkyDrawable::Animator::configure(Sky const &sky)
for(int i = 0; i < MAX_LAYERS; ++i)
{
SkyLayer const *skyLayer = sky.layer(i);
LayerData &ldata = layer(i);
LayerState &ldata = layer(i);

ldata.active = skyLayer->isActive();
ldata.masked = skyLayer->isMasked();
Expand Down Expand Up @@ -671,26 +690,46 @@ bool SkyDrawable::Animator::hasLayer(int index) const
return (index >= 0 && index < MAX_LAYERS);
}

SkyDrawable::Animator::LayerData &SkyDrawable::Animator::layer(int index)
SkyDrawable::Animator::LayerState &SkyDrawable::Animator::layer(int index)
{
if(hasLayer(index))
{
return d->layers[index];
}
/// @throw MissingLayerError An invalid layer index was specified.
throw MissingModelError("SkyDrawable::Animator::layer", "Invalid layer index #" + String::number(index) + ".");
/// @throw MissingLayerStateError An invalid layer state index was specified.
throw MissingLayerStateError("SkyDrawable::Animator::layer", "Invalid layer state index #" + String::number(index) + ".");
}

SkyDrawable::Animator::LayerData const &SkyDrawable::Animator::layer(int index) const
SkyDrawable::Animator::LayerState const &SkyDrawable::Animator::layer(int index) const
{
return const_cast<LayerData const &>(const_cast<SkyDrawable::Animator *>(this)->layer(index));
return const_cast<LayerState const &>(const_cast<SkyDrawable::Animator *>(this)->layer(index));
}

int SkyDrawable::Animator::firstActiveLayer() const
{
return d->firstActiveLayer; // Updated at configure time.
}

bool SkyDrawable::Animator::hasModel(int index) const
{
return (index >= 0 && index < MAX_MODELS);
}

SkyDrawable::Animator::ModelState &SkyDrawable::Animator::model(int index)
{
if(hasModel(index))
{
return d->models[index];
}
/// @throw MissingModelStateError An invalid model state index was specified.
throw MissingModelStateError("SkyDrawable::Animator::model", "Invalid model state index #" + String::number(index) + ".");
}

SkyDrawable::Animator::ModelState const &SkyDrawable::Animator::model(int index) const
{
return const_cast<ModelState const &>(const_cast<SkyDrawable::Animator *>(this)->model(index));
}

void SkyDrawable::Animator::advanceTime(timespan_t /*elapsed*/)
{
LOG_AS("SkyDrawable::Animator");
Expand All @@ -703,26 +742,27 @@ void SkyDrawable::Animator::advanceTime(timespan_t /*elapsed*/)
// Animate layers.
/*for(int i = 0; i < MAX_LAYERS; ++i)
{
LayerData &lyr = sky().layer(i);
LayerState &lyr = layer(i);
}*/

// Animate models.
for(int i = 0; i < MAX_MODELS; ++i)
{
ModelData &mdata = sky().model(i);
if(!mdata.def) continue;
ModelConfig &mcfg = sky().model(i);
ModelState &mstate = model(i);
if(!mcfg.def) continue;

// Rotate the model.
mdata.yaw += mdata.def->getf("yawSpeed") / TICSPERSEC;
mstate.yaw += mcfg.def->getf("yawSpeed") / TICSPERSEC;

// Is it time to advance to the next frame?
if(mdata.maxTimer > 0 && ++mdata.timer >= mdata.maxTimer)
if(mstate.maxTimer > 0 && ++mstate.timer >= mstate.maxTimer)
{
mdata.frame++;
mdata.timer = 0;
mstate.frame++;
mstate.timer = 0;

// Execute a console command?
String const execute = mdata.def->gets("execute");
String const execute = mcfg.def->gets("execute");
if(!execute.isEmpty())
{
Con_Execute(CMDS_SCRIPT, execute.toUtf8().constData(), true, false);
Expand Down

0 comments on commit cf84047

Please sign in to comment.