Skip to content

Commit

Permalink
Renderer|Resources: Improved 3D model error checking
Browse files Browse the repository at this point in the history
Invalid animation and mesh IDs and material definitions should be reported.
  • Loading branch information
skyjake committed Oct 27, 2018
1 parent c1c518f commit d938b6c
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 31 deletions.
75 changes: 48 additions & 27 deletions doomsday/apps/client/src/render/modelloader.cpp
Expand Up @@ -461,31 +461,41 @@ DENG2_PIMPL(ModelLoader)
model.materialIndexForName.insert(MATERIAL_DEFAULT, 0);
if (asset.has(DEF_MATERIAL))
{
asset.subrecord(DEF_MATERIAL).forSubrecords(
[this, &model] (String const &blockName, Record const &block)
{
if (ScriptedInfo::blockType(block) == DEF_VARIANT)
{
String const materialName = blockName;
if (!model.materialIndexForName.contains(materialName))
asset.subrecord(DEF_MATERIAL)
.forSubrecords([this, &model](String const &blockName, Record const &block) {
try
{
// Add a new material.
model.materialIndexForName.insert(materialName, model.addMaterial());
if (ScriptedInfo::blockType(block) == DEF_VARIANT)
{
String const materialName = blockName;
if (!model.materialIndexForName.contains(materialName))
{
// Add a new material.
model.materialIndexForName.insert(materialName,
model.addMaterial());
}
block.forSubrecords([this, &model, &materialName](
String const &matName, Record const &matDef) {
setupMaterial(model,
matName,
model.materialIndexForName[materialName],
matDef);
return LoopContinue;
});
}
else
{
// The default material.
setupMaterial(model, blockName, 0, block);
}
}
block.forSubrecords([this, &model, &materialName]
(String const &matName, Record const &matDef)
catch (const Error &er)
{
setupMaterial(model, matName, model.materialIndexForName[materialName], matDef);
return LoopContinue;
});
}
else
{
// The default material.
setupMaterial(model, blockName, 0, block);
}
return LoopContinue;
});
LOG_GL_ERROR("Material variant \"%s\" is invalid: %s")
<< blockName << er.asText();
}
return LoopContinue;
});
}

// Set up the animation sequences for states.
Expand Down Expand Up @@ -551,6 +561,12 @@ DENG2_PIMPL(ModelLoader)
int meshId = identifierFromText(value->asText(), [&model] (String const &text) {
return model.meshId(text);
});
if (meshId < 0 || meshId >= model.meshCount())
{
throw DefinitionError("ModelLoader::bankLoaded",
"Unknown mesh \"" + value->asText() + "\" in " +
ScriptedInfo::sourceLocation(def));
}
pass.meshes.setBit(meshId, true);
}

Expand Down Expand Up @@ -651,11 +667,16 @@ DENG2_PIMPL(ModelLoader)
duint materialIndex,
Record const &matDef)
{
ModelDrawable::MeshId const mesh {
duint(identifierFromText(meshName, [&model] (String const &text) {
return model.meshId(text); })),
materialIndex
};
int mid = identifierFromText(meshName,
[&model](const String &text) { return model.meshId(text); });
if (mid < 0 || mid >= model.meshCount())
{
throw DefinitionError("ModelLoader::setupMaterial",
"Mesh \"" + meshName + "\" not found in " +
ScriptedInfo::sourceLocation(matDef));
}

const ModelDrawable::MeshId mesh{duint(mid), materialIndex};

setupMaterialTexture(model, mesh, matDef, QStringLiteral("diffuseMap"), ModelDrawable::Diffuse);
setupMaterialTexture(model, mesh, matDef, QStringLiteral("normalMap"), ModelDrawable::Normals);
Expand Down
11 changes: 11 additions & 0 deletions doomsday/apps/client/src/render/modelrenderer.cpp
Expand Up @@ -374,6 +374,12 @@ static Value *Function_StateAnimator_StartSequence(Context &ctx, Function::Argum

anim.startAnimation(animId, priority, looping, node);
}
else
{
LOG_SCR_ERROR("%s has no animation \"%s\"")
<< anim.objectNamespace().gets("ID")
<< args.at(0)->asText();
}
return nullptr;
}

Expand All @@ -389,6 +395,11 @@ static Value *Function_StateAnimator_StartTimeline(Context &ctx, Function::Argum
timelineName);
return new TextValue(timelineName);
}
else
{
LOG_SCR_ERROR("%s has no timeline \"%s\"")
<< anim.objectNamespace().gets("ID") << timelineName;
}
return nullptr;
}

Expand Down
22 changes: 18 additions & 4 deletions doomsday/apps/client/src/render/stateanimator.cpp
Expand Up @@ -657,6 +657,13 @@ void StateAnimator::triggerByState(String const &stateName)
String const node = seq.def->gets(DEF_NODE, "");
int animId = d->animationId(seq.name);

if (animId < 0)
{
LOG_GL_ERROR("%s: animation sequence \"%s\" not found")
<< ScriptedInfo::sourceLocation(*seq.def) << seq.name;
break;
}

bool const alwaysTrigger = ScriptedInfo::isTrue(*seq.def, DEF_ALWAYS_TRIGGER, false);
if (!alwaysTrigger)
{
Expand Down Expand Up @@ -711,7 +718,7 @@ void StateAnimator::triggerByState(String const &stateName)
}
catch (ModelDrawable::Animator::InvalidError const &er)
{
LOGDEV_GL_WARNING("Failed to start animation \"%s\": %s")
LOG_GL_WARNING("Failed to start animation \"%s\": %s")
<< seq.name << er.asText();
continue;
}
Expand Down Expand Up @@ -748,9 +755,16 @@ void StateAnimator::triggerDamage(int points, struct mobj_s const *inflictor)

void StateAnimator::startAnimation(int animationId, int priority, bool looping, String const &node)
{
using Seq = Impl::Sequence;
d->start(Seq(animationId, node, looping? Seq::Looping : Seq::NotLooping,
priority));
LOG_AS("StateAnimator::startAnimation");
try
{
using Seq = Impl::Sequence;
d->start(Seq(animationId, node, looping ? Seq::Looping : Seq::NotLooping, priority));
}
catch (const Error &er)
{
LOG_GL_ERROR("%s: %s") << d->names.gets(VAR_ID) << er.asText();
}
}

int StateAnimator::animationId(String const &name) const
Expand Down

0 comments on commit d938b6c

Please sign in to comment.