Skip to content

Commit

Permalink
Materials: Generate material layer animations from texture anim groups
Browse files Browse the repository at this point in the history
Beginning to flesh out the new staged based mechanism for material
animation.

Interpret the game-registered texture anim groups when generating
materials from/for original game textures, reconstructing their
animations in terms of material's layer stages.

Todo: Implement interpretor logics for legacy group animation defs.
Todo: Reimplement smooth texture animation.
Todo: Reimplement support for flags such as PGF_GROUP.
Todo: Cleanup
  • Loading branch information
danij-deng committed Jan 8, 2013
1 parent 86dc59c commit 2c20a7c
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 215 deletions.
2 changes: 1 addition & 1 deletion doomsday/engine/include/def_data.h
Expand Up @@ -474,14 +474,14 @@ typedef struct ded_group_s {
ded_flags_t flags;
ded_count_t count;
ded_group_member_t* members;
boolean autoGenerated;
} ded_group_t;

typedef struct ded_material_layer_stage_s {
Uri* texture;
int tics;
float variance; // Stage variance (time).
float glowStrength;
float glowStrengthVariance;
float texOrigin[2];
} ded_material_layer_stage_t;

Expand Down
1 change: 0 additions & 1 deletion doomsday/engine/src/def_data.c
Expand Up @@ -824,7 +824,6 @@ void DED_RemoveReflection(ded_t* ded, int index)
int DED_AddGroup(ded_t* ded)
{
ded_group_t* group = DED_NewEntry((void**) &ded->groups, &ded->count.groups, sizeof(ded_group_t));
group->autoGenerated = false;
return group - ded->groups;
}

Expand Down
147 changes: 62 additions & 85 deletions doomsday/engine/src/def_main.cpp
Expand Up @@ -929,53 +929,37 @@ static void readAllDefinitions(void)
VERBOSE2( Con_Message(" Done in %.2f seconds.\n", (Timer_RealMilliseconds() - startTime) / 1000.0f) );
}

void Def_GenerateGroupsFromAnims(void)
static animgroup_t const *findAnimGroupForTexture(TextureManifest &manifest)
{
int groupCount = R_AnimGroupCount(), i;
if(!groupCount) return;

// Group ids are 1-based.
for(i = 1; i < groupCount+1; ++i)
// Search backwards to allow patching.
for(int i = R_AnimGroupCount(); i > 0; i--)
{
animgroup_t const *anim = R_ToAnimGroup(i);
ded_group_member_t *gmbr;
ded_group_t *grp;
int idx, j;

idx = DED_AddGroup(&defs);
grp = &defs.groups[idx];
grp->autoGenerated = true;
grp->flags = anim->flags;

for(j = 0; j < anim->count; ++j)
for(int j = 0; j < anim->count; ++j)
{
animframe_t const *frame = &anim->frames[j];

idx = DED_AddGroupMember(grp);
gmbr = &grp->members[idx];
gmbr->tics = frame->tics;
gmbr->randomTics = frame->randomTics;
if(!frame->textureManifest) continue;

if(Texture *tex = reinterpret_cast<TextureManifest *>(frame->textureManifest)->texture())
if(&manifest == frame->textureManifest)
{
de::Uri textureUri = tex->manifest().composeUri();
gmbr->material = reinterpret_cast<uri_s *>(new de::Uri(DD_MaterialSchemeNameForTextureScheme(textureUri.scheme()), textureUri.path()));
return anim;
}
}
}
return 0; // Not found.
}

static int generateMaterialDefForCompositeTexture(TextureManifest &manifest, void * /*parameters*/)
static void generateMaterialDefForTexture(TextureManifest &manifest)
{
LOG_AS("generateMaterialDefForCompositeTexture");
LOG_AS("generateMaterialDefForTexture");

de::Uri texUri = manifest.composeUri();

int matIdx = DED_AddMaterial(&defs, 0);
ded_material_t *mat = &defs.materials[matIdx];
mat->autoGenerated = true;
mat->uri = reinterpret_cast<uri_s *>(new de::Uri("Textures", texUri.path()));
mat->uri = reinterpret_cast<uri_s *>(new de::Uri(DD_MaterialSchemeNameForTextureScheme(texUri.scheme()), texUri.path()));

if(Texture *tex = manifest.texture())
{
Expand All @@ -986,82 +970,76 @@ static int generateMaterialDefForCompositeTexture(TextureManifest &manifest, voi
#if _DEBUG
else
{
LOG_DEBUG("Texture \"%s\" yet defined, resultant Material will inherit dimensions.") << texUri;
LOG_DEBUG("Texture \"%s\" not yet defined, resultant Material will inherit dimensions.") << texUri;
}
#endif

int stage = DED_AddMaterialLayerStage(&mat->layers[0]);
ded_material_layer_stage_t *st = &mat->layers[0].stages[stage];
st->texture = reinterpret_cast<uri_s *>(new de::Uri(texUri));
return 0; // Continue iteration.
}

static int generateMaterialDefForFlatTexture(TextureManifest &manifest, void * /*parameters*/)
{
LOG_AS("generateMaterialDefForFlatTexture");

de::Uri texUri = manifest.composeUri();

int matIdx = DED_AddMaterial(&defs, 0);
ded_material_t *mat = &defs.materials[matIdx];
mat->autoGenerated = true;
mat->uri = reinterpret_cast<uri_s *>(new de::Uri("Flats", texUri.path()));

int stage = DED_AddMaterialLayerStage(&mat->layers[0]);
ded_material_layer_stage_t *st = &mat->layers[0].stages[stage];
// The first stage is implicit.
ded_material_layer_stage_t *st =
&mat->layers[0].stages[DED_AddMaterialLayerStage(&mat->layers[0])];
st->texture = reinterpret_cast<uri_s *>(new de::Uri(texUri));

if(Texture *tex = manifest.texture())
{
mat->width = tex->width();
mat->height = tex->height();
}
#if _DEBUG
else
// Is there an animation for this?
animgroup_t const *anim = findAnimGroupForTexture(manifest);
if(anim && anim->count > 1)
{
LOG_DEBUG("Texture \"%s\" not yet defined, resultant Material will inherit dimensions.") << texUri;
}
#endif
animframe_t const *animFrame;

return 0; // Continue iteration.
}
// Determine the start frame.
int startFrame = 0;
while(anim->frames[startFrame].textureManifest != &manifest)
{
startFrame++;
}

static int generateMaterialDefForSpriteTexture(TextureManifest &manifest, void * /*parameters*/)
{
LOG_AS("generateMaterialDefForSpriteTexture");
// Just animate the first in the sequence?
if(startFrame && (anim->flags & AGF_FIRST_ONLY))
return;

de::Uri texUri = manifest.composeUri();
// Complete configuration of the first stage.
animFrame = &anim->frames[startFrame];
st->tics = animFrame->tics + animFrame->randomTics;
if(animFrame->randomTics)
{
st->variance = animFrame->randomTics / float( st->tics );
}

int matIdx = DED_AddMaterial(&defs, 0);
ded_material_t *mat = &defs.materials[matIdx];
mat->autoGenerated = true;
mat->uri = reinterpret_cast<uri_s *>(new de::Uri("Sprites", texUri.path()));
// Add further stages according to the animation group.
startFrame++;
for(int i = 0; i < anim->count - 1; ++i)
{
int frame = startFrame + i;
// Wrap around?
if(frame >= anim->count) frame -= anim->count;

int stage = DED_AddMaterialLayerStage(&mat->layers[0]);
ded_material_layer_stage_t *st = &mat->layers[0].stages[stage];
st->texture = reinterpret_cast<uri_s *>(new de::Uri(texUri));
animFrame = &anim->frames[frame];
if(!animFrame->textureManifest) continue;
TextureManifest &frameManifest = *reinterpret_cast<TextureManifest *>(animFrame->textureManifest);

if(Texture *tex = manifest.texture())
{
mat->width = tex->width();
mat->height = tex->height();
}
#if _DEBUG
else
{
LOG_DEBUG("Texture \"%s\" not yet defined, resultant Material will inherit dimensions.") << texUri;
ded_material_layer_stage_t *st =
&mat->layers[0].stages[DED_AddMaterialLayerStage(&mat->layers[0])];
st->texture = reinterpret_cast<uri_s *>(new de::Uri(frameManifest.composeUrn()));
st->tics = animFrame->tics + animFrame->randomTics;
if(animFrame->randomTics)
{
st->variance = animFrame->randomTics / float( st->tics );
}
}
}
#endif
}

static int generateMaterialDefForTextureWorker(TextureManifest &manifest, void * /*params*/)
{
generateMaterialDefForTexture(manifest);
return 0; // Continue iteration.
}

void Def_GenerateAutoMaterials(void)
static void generateMaterialDefs()
{
Textures &textures = *App_Textures();
textures.iterateDeclared("Textures", generateMaterialDefForCompositeTexture);
textures.iterateDeclared("Flats", generateMaterialDefForFlatTexture);
textures.iterateDeclared("Sprites", generateMaterialDefForSpriteTexture);
textures.iterateDeclared("Textures", generateMaterialDefForTextureWorker);
textures.iterateDeclared("Flats", generateMaterialDefForTextureWorker);
textures.iterateDeclared("Sprites", generateMaterialDefForTextureWorker);
}

void Def_Read()
Expand All @@ -1086,8 +1064,7 @@ void Def_Read()
DED_Init(&defs);

// Generate definitions.
Def_GenerateGroupsFromAnims();
Def_GenerateAutoMaterials();
generateMaterialDefs();

// Read all definitions files and lumps.
Con_Message("Parsing definition files%s\n", verbose >= 1? ":" : "...");
Expand Down
1 change: 1 addition & 0 deletions doomsday/engine/src/def_read.cpp
Expand Up @@ -1276,6 +1276,7 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile)
RV_INT("Tics", st->tics)
RV_FLT("Rnd", st->variance)
RV_VEC("Offset", st->texOrigin, 2)
RV_FLT("Glow Rnd", st->glowStrengthVariance)
RV_FLT("Glow", st->glowStrength)
RV_END
CHECKSC;
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/src/resource/animgroups.cpp
Expand Up @@ -85,7 +85,7 @@ DENG_EXTERN_C int R_CreateAnimGroup(int flags)
// Init the new group.
std::memset(group, 0, sizeof *group);
group->id = numgroups; // 1-based index.
group->flags = flags;
group->flags = flags & ~AGF_PRECACHE;

return group->id;
}
Expand Down
58 changes: 42 additions & 16 deletions doomsday/engine/src/resource/materials.cpp
Expand Up @@ -674,17 +674,17 @@ void Materials::cache(material_t &mat, MaterialVariantSpec const &spec,

void Materials::ticker(timespan_t time)
{
#ifdef __CLIENT__
// Animations will only progress when the game is not paused.
if(clientPaused) return;
#endif

DENG2_FOR_EACH(MaterialList, i, d->materials)
{
Material_Ticker(*i, time);
}

#ifdef LIBDENG_OLD_MATERIAL_ANIM_METHOD
#ifdef __CLIENT__
// Animations will only progress when the game is not paused.
if(clientPaused) return;
#endif

if(DD_IsSharpTick())
{
d->animateAllGroups();
Expand Down Expand Up @@ -923,40 +923,38 @@ static void printVariantInfo(MaterialVariant &variant, int variantIdx)
}
#endif

// Print layer info:
// Print layer state info:
int const layerCount = Material_LayerCount(&variant.generalCase());
for(int i = 0; i < layerCount; ++i)
{
MaterialVariant::LayerState const &l = variant.layer(i);
de::Uri uri = reinterpret_cast<Texture &>(*l.texture).manifest().composeUri();
QByteArray path = uri.asText().toUtf8();

Con_Printf(" #%i: Stage:%i Tics:%i Texture:\"%s\""
"\n Offset: %.2f x %.2f Glow:%.2f\n",
i, l.stage, int(l.tics), path.constData(),
l.texOrigin[0], l.texOrigin[1], l.glowStrength);
Con_Printf(" #%i: Stage:%i Tics:%i Offset: %.2f x %.2f Glow:%.2f\n",
i, l.stage, int(l.tics), l.texOrigin[0], l.texOrigin[1], l.glowStrength);
}

}

static void printMaterialInfo(material_t &mat)
{
ded_material_t const *def = Material_Definition(&mat);

/// @todo kludge: Should not use App_Materials() here.
Uri uri = App_Materials()->toMaterialBind(Material_PrimaryBind(&mat))->composeUri();
QByteArray path = uri.asText().toUtf8();

// Print summary:
Con_Printf("Material \"%s\" [%p] x%u origin:%s\n",
path.constData(), (void *) &mat, Material_VariantCount(&mat),
!Material_IsCustom(&mat)? "game" : (Material_Definition(&mat)->autoGenerated? "addon" : "def"));
!Material_IsCustom(&mat)? "game" : (def->autoGenerated? "addon" : "def"));

if(Material_Width(&mat) <= 0 || Material_Height(&mat) <= 0)
Con_Printf("Dimensions: unknown (not yet prepared)\n");
else
Con_Printf("Dimensions: %d x %d\n", Material_Width(&mat), Material_Height(&mat));

Con_Printf("Layers:%i Drawable:%s EnvClass:%s Decorated:%s"
// Print synopsis:
Con_Printf("Drawable:%s EnvClass:\"%s\" Decorated:%s"
"\nDetailed:%s Glowing:%s Shiny:%s%s SkyMasked:%s\n",
Material_LayerCount(&mat),
Material_IsDrawable(&mat) ? "yes" : "no",
Material_EnvironmentClass(&mat) == MEC_UNKNOWN? "N/A" : S_MaterialEnvClassName(Material_EnvironmentClass(&mat)),
Material_HasDecorations(&mat) ? "yes" : "no",
Expand All @@ -966,6 +964,34 @@ static void printMaterialInfo(material_t &mat)
Material_ShinyMaskTexture(&mat)? "(masked)" : "",
Material_IsSkyMasked(&mat) ? "yes" : "no");

// Print full layer config:
int const layerCount = Material_LayerCount(&mat);
for(int i = 0; i < layerCount; ++i)
{
ded_material_layer_t const *lDef = &def->layers[i];

Con_Printf("Layer #%i (%i %s):\n", i, lDef->stageCount.num,
lDef->stageCount.num == 1? "Stage" : "Stages");

for(int k = 0; k < lDef->stageCount.num; ++k)
{
ded_material_layer_stage_t const *sDef = &lDef->stages[k];
QByteArray path = !sDef->texture? QString("(prev)").toUtf8()
: reinterpret_cast<Uri *>(sDef->texture)->asText().toUtf8();

Con_Printf(" #%i: Texture:\"%s\" Tics:%i (~%.2f)"
"\n Offset: %.2f x %.2f Glow:%.2f (~%.2f)\n",
k, path.constData(), sDef->tics, sDef->variance,
sDef->texOrigin[0], sDef->texOrigin[1],
sDef->glowStrength, sDef->glowStrengthVariance);
}
}

if(!Material_VariantCount(&mat)) return;

Con_PrintRuler();

// Print variant specs and current animation states:
int variantIdx = 0;
Material::Variants const &variants = Material_Variants(&mat);
DENG2_FOR_EACH_CONST(Material::Variants, i, variants)
Expand Down

0 comments on commit 2c20a7c

Please sign in to comment.