diff --git a/doomsday/engine/include/def_data.h b/doomsday/engine/include/def_data.h index b7e55b232f..b3af4f24df 100644 --- a/doomsday/engine/include/def_data.h +++ b/doomsday/engine/include/def_data.h @@ -420,18 +420,23 @@ typedef struct ded_ptcgen_s { ded_count_t stageCount; } ded_ptcgen_t; -typedef struct ded_decorlight_s { +typedef struct ded_decorlight_stage_s { float pos[2]; // Coordinates on the surface. float elevation; // Distance from the surface. float color[3]; // Light color. float radius; // Dynamic light radius (-1 = no light). float haloRadius; // Halo radius (zero = no halo). - int patternOffset[2]; - int patternSkip[2]; float lightLevels[2]; // Fade by sector lightlevel. int flareTexture; Uri* up, *down, *sides; Uri* flare; // Overrides flare_texture +} ded_decorlight_stage_t; + +typedef struct ded_decorlight_s { + int patternOffset[2]; + int patternSkip[2]; + ded_decorlight_stage_t *stages; + ded_count_t stageCount; } ded_decorlight_t; // There is a fixed number of light decorations in each decoration. @@ -644,7 +649,7 @@ int DED_AddState(ded_t* ded, char const* id); int DED_AddSprite(ded_t* ded, char const* name); int DED_AddLight(ded_t* ded, char const* stateID); int DED_AddMaterial(ded_t* ded, char const* uri); -int DED_AddMaterialLayerStage(ded_material_layer_t* ml); +int DED_AddMaterialLayerStage(ded_material_layer_t *ml); int DED_AddModel(ded_t* ded, char const* spr); int DED_AddSky(ded_t* ded, char const* id); int DED_AddSound(ded_t* ded, char const* id); @@ -658,6 +663,7 @@ int DED_AddPtcGen(ded_t* ded, char const* state); int DED_AddPtcGenStage(ded_ptcgen_t* gen); int DED_AddFinale(ded_t* ded); int DED_AddDecoration(ded_t* ded); +int DED_AddDecorLightStage(ded_decorlight_t *li); int DED_AddReflection(ded_t* ded); int DED_AddGroup(ded_t* ded); int DED_AddGroupMember(ded_group_t* grp); diff --git a/doomsday/engine/include/render/rend_decor.h b/doomsday/engine/include/render/rend_decor.h index 67873877b8..f141023d69 100644 --- a/doomsday/engine/include/render/rend_decor.h +++ b/doomsday/engine/include/render/rend_decor.h @@ -1,50 +1,58 @@ -/**\file rend_decor.h - *\section License - * License: GPL - * Online License Link: http://www.gnu.org/licenses/gpl.html +/** @file rend_decor.h Surface Decoration Projection. * - *\author Copyright © 2003-2013 Jaakko Keränen - *\author Copyright © 2006-2013 Daniel Swanson + * @author Copyright © 2003-2013 Jaakko Keränen + * @author Copyright © 2006-2013 Daniel Swanson * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -/** - * Surface Decorations. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses */ #ifndef LIBDENG_RENDER_DECOR_H #define LIBDENG_RENDER_DECOR_H +#include + +DENG_EXTERN_C byte useLightDecorations; +DENG_EXTERN_C float decorMaxDist; ///< No decorations are visible beyond this. +DENG_EXTERN_C float decorLightBrightFactor; +DENG_EXTERN_C float decorLightFadeAngle; + #ifdef __cplusplus extern "C" { #endif -extern byte useLightDecorations; -extern float decorMaxDist; // No decorations are visible beyond this. -extern float decorLightBrightFactor; -extern float decorLightFadeAngle; +void Rend_DecorRegister(void); -void Rend_DecorRegister(void); +/** + * Re-initialize the decoration source tracking (might be called during a map + * load or othersuch situation). + */ +void Rend_DecorInit(void); -void Rend_DecorInit(void); +/** + * Decorations are generated for each frame. + */ +void Rend_InitDecorationsForFrame(void); -void Rend_InitDecorationsForFrame(void); -void Rend_AddLuminousDecorations(void); -void Rend_ProjectDecorations(void); +/** + * Create lumobjs for all decorations who want them. + */ +void Rend_AddLuminousDecorations(void); + +/** + * Project all the non-clipped decorations. They become regular vissprites. + */ +void Rend_ProjectDecorations(void); #ifdef __cplusplus } // extern "C" diff --git a/doomsday/engine/include/resource/material.h b/doomsday/engine/include/resource/material.h index b05e0b8845..3e811618f0 100644 --- a/doomsday/engine/include/resource/material.h +++ b/doomsday/engine/include/resource/material.h @@ -74,6 +74,8 @@ class Material struct Decoration { + ded_decorlight_t *def; + /* float pos[2]; // Coordinates in material space. float elevation; // Distance from the surface. float color[3]; // Light color. @@ -85,6 +87,37 @@ class Material int flareTexture; de::Uri up, down, sides; de::Uri flare; // Overrides flare_texture + */ + + Decoration(ded_decorlight_t &_def) : def(&_def) + { + /* + std::memcpy(decor->pos, def->pos, sizeof(decor->pos)); + decor->elevation = def->elevation; + std::memcpy(decor->color, def->color, sizeof(decor->color)); + decor->radius = def->radius; + decor->haloRadius = def->haloRadius; + std::memcpy(decor->patternOffset, def->patternOffset, sizeof(decor->patternOffset)); + std::memcpy(decor->patternSkip, def->patternSkip, sizeof(decor->patternSkip)); + std::memcpy(decor->lightLevels, def->lightLevels, sizeof(decor->lightLevels)); + decor->flareTexture = def->flareTexture; + if(def->up) + { + decor->up = *reinterpret_cast(def->up); + } + if(def->down) + { + decor->down = *reinterpret_cast(def->down); + } + if(def->sides) + { + decor->sides = *reinterpret_cast(def->sides); + } + if(def->flare) + { + decor->flare = *reinterpret_cast(def->flare); + }*/ + } }; /// A list of decorations. @@ -113,7 +146,7 @@ material_t *Material_New(short flags, ded_material_t *def, Size2Raw *dimensions, void Material_Delete(material_t *mat); -void Material_AddDecoration(material_t *mat, ded_decorlight_t const *def); +void Material_AddDecoration(material_t *mat, ded_decorlight_t *def); int Material_DecorationCount(material_t const *mat); diff --git a/doomsday/engine/src/dd_main.cpp b/doomsday/engine/src/dd_main.cpp index 758b82fbd9..5b91866849 100644 --- a/doomsday/engine/src/dd_main.cpp +++ b/doomsday/engine/src/dd_main.cpp @@ -1123,6 +1123,8 @@ static int DD_ActivateGameWorker(void* parameters) R_InitCompositeTextures(); R_InitFlatTextures(); R_InitSpriteTextures(); + App_Textures()->scheme("Lightmaps").clear(); + App_Textures()->scheme("Flaremaps").clear(); if(p->initiatedBusyMode) Con_SetProgress(50); @@ -1967,6 +1969,8 @@ boolean DD_Init(void) R_InitCompositeTextures(); R_InitFlatTextures(); R_InitSpriteTextures(); + App_Textures()->scheme("Lightmaps").clear(); + App_Textures()->scheme("Flaremaps").clear(); Def_Read(); diff --git a/doomsday/engine/src/def_data.c b/doomsday/engine/src/def_data.c index d379c4e211..d443c633bc 100644 --- a/doomsday/engine/src/def_data.c +++ b/doomsday/engine/src/def_data.c @@ -257,26 +257,30 @@ void DED_Clear(ded_t* ded) for(i = 0; i < ded->count.materials.num; ++i) { ded_material_t* mat = &ded->materials[i]; - if(mat->uri) Uri_Delete(mat->uri); for(j = 0; j < DED_MAX_MATERIAL_LAYERS; ++j) { - for(k = 0; k < mat->layers[j].stageCount.num; ++k) + ded_material_layer_t *layer = &mat->layers[j]; + for(k = 0; k < layer->stageCount.num; ++k) { - if(mat->layers[j].stages[k].texture) Uri_Delete(mat->layers[j].stages[k].texture); + if(layer->stages[k].texture) Uri_Delete(layer->stages[k].texture); } - M_Free(mat->layers[j].stages); + M_Free(layer->stages); } for(j = 0; j < DED_DECOR_NUM_LIGHTS; ++j) { - ded_decorlight_t* li = &mat->lights[j]; - - if(li->up) Uri_Delete(li->up); - if(li->down) Uri_Delete(li->down); - if(li->sides) Uri_Delete(li->sides); - if(li->flare) Uri_Delete(li->flare); + ded_decorlight_t *light = &mat->lights[j]; + for(k = 0; k < light->stageCount.num; ++k) + { + ded_decorlight_stage_t *stage = &light->stages[k]; + if(stage->up) Uri_Delete(stage->up); + if(stage->down) Uri_Delete(stage->down); + if(stage->sides) Uri_Delete(stage->sides); + if(stage->flare) Uri_Delete(stage->flare); + } + M_Free(light->stages); } } M_Free(ded->materials); @@ -343,21 +347,25 @@ void DED_Clear(ded_t* ded) if(ded->decorations) { - int i, j; + int i, j, k; for(i = 0; i < ded->count.decorations.num; ++i) { - ded_decor_t* dec = &ded->decorations[i]; + ded_decor_t *dec = &ded->decorations[i]; if(dec->material) Uri_Delete(dec->material); for(j = 0; j < DED_DECOR_NUM_LIGHTS; ++j) { - ded_decorlight_t* li = &dec->lights[j]; - - if(li->up) Uri_Delete(li->up); - if(li->down) Uri_Delete(li->down); - if(li->sides) Uri_Delete(li->sides); - if(li->flare) Uri_Delete(li->flare); + ded_decorlight_t *light = &dec->lights[j]; + for(k = 0; k < light->stageCount.num; ++k) + { + ded_decorlight_stage_t *stage = &light->stages[k]; + if(stage->up) Uri_Delete(stage->up); + if(stage->down) Uri_Delete(stage->down); + if(stage->sides) Uri_Delete(stage->sides); + if(stage->flare) Uri_Delete(stage->flare); + } + M_Free(light->stages); } } M_Free(ded->decorations); @@ -574,22 +582,12 @@ int DED_AddMaterial(ded_t* ded, char const* uri) { ded_material_t* mat = DED_NewEntry((void**) &ded->materials, &ded->count.materials, sizeof(ded_material_t)); if(uri) mat->uri = Uri_NewWithPath2(uri, RC_NULL); - - // Init some default values. - { int i; - for(i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) - { - // The color (0,0,0) means the light is not active. - mat->lights[i].elevation = 1; - mat->lights[i].radius = 1; - }} - return mat - ded->materials; } -int DED_AddMaterialLayerStage(ded_material_layer_t* ml) +int DED_AddMaterialLayerStage(ded_material_layer_t *ml) { - ded_material_layer_stage_t* stage = DED_NewEntry((void**) &ml->stages, &ml->stageCount, sizeof(*stage)); + ded_material_layer_stage_t *stage = DED_NewEntry((void**) &ml->stages, &ml->stageCount, sizeof(*stage)); return stage - ml->stages; } @@ -805,12 +803,10 @@ int DED_AddDecoration(ded_t* ded) ded_decor_t* decor = DED_NewEntry((void**) &ded->decorations, &ded->count.decorations, sizeof(ded_decor_t)); int i; - // Init some default values. + // Each decorlight supports only one stage. for(i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) { - // The color (0,0,0) means the light is not active. - decor->lights[i].elevation = 1; - decor->lights[i].radius = 1; + DED_AddDecorLightStage(&decor->lights[i]); } return decor - ded->decorations; @@ -821,6 +817,17 @@ void DED_RemoveDecoration(ded_t* ded, int index) DED_DelEntry(index, (void**) &ded->decorations, &ded->count.decorations, sizeof(ded_decor_t)); } +int DED_AddDecorLightStage(ded_decorlight_t *li) +{ + ded_decorlight_stage_t *stage = DED_NewEntry((void**) &li->stages, &li->stageCount, sizeof(*stage)); + + // The color (0,0,0) means the light is not active. + stage->elevation = 1; + stage->radius = 1; + + return stage - li->stages; +} + int DED_AddReflection(ded_t* ded) { ded_reflection_t* ref = DED_NewEntry((void**) &ded->reflections, &ded->count.reflections, sizeof(ded_reflection_t)); diff --git a/doomsday/engine/src/def_main.cpp b/doomsday/engine/src/def_main.cpp index 5750ad016f..82ec770205 100644 --- a/doomsday/engine/src/def_main.cpp +++ b/doomsday/engine/src/def_main.cpp @@ -91,6 +91,9 @@ static mobjinfo_t* gettingFor; xgclass_t nullXgClassLinks; // Used when none defined. xgclass_t* xgClassLinks; +static void defineFlaremap(uri_s const *_resourceUri); +static void defineLightmap(uri_s const *_resourceUri); + /** * Retrieves the XG Class list from the Game. * XGFunc links are provided by the Game, who owns the actual @@ -1141,6 +1144,35 @@ void Def_Read() for(int i = 0; i < defs.count.materials.num; ++i) { ded_material_t *def = &defs.materials[i]; + + for(int k = 0; k < DED_DECOR_NUM_LIGHTS; ++k) + { + ded_decorlight_t* lig = &def->lights[k]; + for(int m = 0; m < lig->stageCount.num; ++m) + { + ded_decorlight_stage_t *stage = &lig->stages[m]; + + if(!Def_IsValidLightDecoration(lig)) break; + + if(stage->up) + { + defineLightmap(stage->up); + } + if(stage->down) + { + defineLightmap(stage->down); + } + if(stage->sides) + { + defineLightmap(stage->sides); + } + if(stage->flare) + { + defineFlaremap(stage->flare); + } + } + } + try { MaterialManifest &bind = App_Materials()->find(*reinterpret_cast(def->uri)); @@ -1503,8 +1535,6 @@ void Def_PostInit(void) } // Lights. - App_Textures()->scheme("Lightmaps").clear(); - App_Textures()->scheme("Flaremaps").clear(); for(int i = 0; i < defs.count.lights.num; ++i) { ded_light_t* lig = &defs.lights[i]; @@ -1527,38 +1557,6 @@ void Def_PostInit(void) } } - for(int i = 0; i < defs.count.decorations.num; ++i) - { - ded_decor_t* decor = &defs.decorations[i]; - - // Ignore definitions which do not specify a material. - if(!decor->material || Uri_IsEmpty(decor->material)) continue; - - for(int k = 0; k < DED_DECOR_NUM_LIGHTS; ++k) - { - ded_decorlight_t* lig = &decor->lights[k]; - - if(!Def_IsValidLightDecoration(lig)) break; - - if(lig->up) - { - defineLightmap(lig->up); - } - if(lig->down) - { - defineLightmap(lig->down); - } - if(lig->sides) - { - defineLightmap(lig->sides); - } - if(lig->flare) - { - defineFlaremap(lig->flare); - } - } - } - // Surface reflections. App_Textures()->scheme("Reflections").clear(); App_Textures()->scheme("Masks").clear(); @@ -2118,9 +2116,9 @@ StringArray* Def_ListStateIDs(void) boolean Def_IsValidLightDecoration(ded_decorlight_t const* lightDef) { - return (lightDef && - (lightDef->color[0] != 0 || lightDef->color[1] != 0 || - lightDef->color[2] != 0)); + return (lightDef && lightDef->stageCount.num && + (lightDef->stages[0].color[0] != 0 || lightDef->stages[0].color[1] != 0 || + lightDef->stages[0].color[2] != 0)); } #if 0 // $revise-texture-animation diff --git a/doomsday/engine/src/def_read.cpp b/doomsday/engine/src/def_read.cpp index f65d00f7fa..0b58ad6b32 100644 --- a/doomsday/engine/src/def_read.cpp +++ b/doomsday/engine/src/def_read.cpp @@ -1139,22 +1139,23 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) if(ISTOKEN("Material")) { boolean bModify = false; - ded_material_t* mat, dummyMat; + ded_material_t *mat, dummyMat; uint layer = 0; + int layerStage; uint light = 0; - int stage; + int lightStage; ReadToken(); if(!ISTOKEN("Mods")) { // A new material. - idx = DED_AddMaterial(ded, NULL); + idx = DED_AddMaterial(ded, 0); mat = &ded->materials[idx]; } else if(!bCopyNext) { - uri_s* otherMat = NULL; - AutoStr* otherMatPath; + uri_s *otherMat = 0; + AutoStr *otherMatPath; READURI(&otherMat, NULL); ReadToken(); @@ -1213,21 +1214,30 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) mat->layers[i].stages = (ded_material_layer_stage_t*) M_Malloc(sizeof(*mat->layers[i].stages) * l->stageCount.max); std::memcpy(mat->layers[i].stages, l->stages, sizeof(*mat->layers[i].stages) * l->stageCount.num); - for(int j = 0; j < l->stageCount.num; ++j) + for(int k = 0; k < l->stageCount.num; ++k) { - if(l->stages[j].texture) - mat->layers[i].stages[j].texture = Uri_Dup(l->stages[j].texture); + if(l->stages[k].texture) + mat->layers[i].stages[k].texture = Uri_Dup(l->stages[k].texture); } } // Duplicate decorations. for(int i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) { - ded_decorlight_t* dl = &mat->lights[i]; - if(dl->flare) dl->flare = Uri_Dup(dl->flare); - if(dl->up) dl->up = Uri_Dup(dl->up); - if(dl->down) dl->down = Uri_Dup(dl->down); - if(dl->sides) dl->sides = Uri_Dup(dl->sides); + ded_decorlight_t const *dl = &prevMaterial->lights[i]; + if(!dl->stages) continue; + + mat->lights[i].stages = (ded_decorlight_stage_t *) M_Malloc(sizeof(*mat->lights[i].stages) * dl->stageCount.max); + std::memcpy(mat->lights[i].stages, dl->stages, sizeof(*mat->lights[i].stages) * dl->stageCount.num); + + for(int k = 0; k < dl->stageCount.num; ++k) + { + ded_decorlight_stage_t *stage = &mat->lights[i].stages[k]; + if(stage->flare) stage->flare = Uri_Dup(stage->flare); + if(stage->up) stage->up = Uri_Dup(stage->up); + if(stage->down) stage->down = Uri_Dup(stage->down); + if(stage->sides) stage->sides = Uri_Dup(stage->sides); + } } } @@ -1245,7 +1255,7 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) RV_INT("Height", mat->height) if(ISLABEL("Layer")) { - stage = 0; + layerStage = 0; if(layer >= DED_MAX_MATERIAL_LAYERS) { SetError("Too many Material layers."); @@ -1262,12 +1272,12 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) ded_material_layer_stage_t* st = NULL; // Need to allocate a new stage? - if(stage >= mat->layers[layer].stageCount.num) + if(layerStage >= mat->layers[layer].stageCount.num) { - stage = DED_AddMaterialLayerStage(&mat->layers[layer]); + layerStage = DED_AddMaterialLayerStage(&mat->layers[layer]); } - st = &mat->layers[layer].stages[stage]; + st = &mat->layers[layer].stages[layerStage]; FINDBEGIN; for(;;) @@ -1282,7 +1292,7 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) RV_END CHECKSC; } - ++stage; + ++layerStage; } else RV_END CHECKSC; @@ -1291,8 +1301,7 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) } else if(ISLABEL("Light")) { - ded_decorlight_t *dl = &mat->lights[light]; - + lightStage = 0; if(light == DED_DECOR_NUM_LIGHTS) { SetError("Too many lights in material."); @@ -1300,41 +1309,60 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) goto ded_end_read; } + ded_decorlight_t *dl = &mat->lights[light]; FINDBEGIN; for(;;) { READLABEL; - RV_VEC("Offset", dl->pos, 2) - RV_FLT("Distance", dl->elevation) - RV_VEC("Color", dl->color, 3) - RV_FLT("Radius", dl->radius) - RV_FLT("Halo radius", dl->haloRadius) RV_IVEC("Pattern offset", dl->patternOffset, 2) RV_IVEC("Pattern skip", dl->patternSkip, 2) - if(ISLABEL("Levels")) + if(ISLABEL("Stage")) { + // Need to allocate a new stage? + if(lightStage >= dl->stageCount.num) + { + layerStage = DED_AddDecorLightStage(dl); + } + + ded_decorlight_stage_t *st = &dl->stages[lightStage]; FINDBEGIN; - for(int b = 0; b < 2; ++b) + for(;;) { - READFLT(dl->lightLevels[b]) - dl->lightLevels[b] /= 255.0f; - if(dl->lightLevels[b] < 0) - dl->lightLevels[b] = 0; - else if(dl->lightLevels[b] > 1) - dl->lightLevels[b] = 1; + READLABEL; + RV_VEC("Offset", st->pos, 2) + RV_FLT("Distance", st->elevation) + RV_VEC("Color", st->color, 3) + RV_FLT("Radius", st->radius) + RV_FLT("Halo radius", st->haloRadius) + if(ISLABEL("Levels")) + { + FINDBEGIN; + for(int b = 0; b < 2; ++b) + { + READFLT(st->lightLevels[b]) + st->lightLevels[b] /= 255.0f; + if(st->lightLevels[b] < 0) + st->lightLevels[b] = 0; + else if(st->lightLevels[b] > 1) + st->lightLevels[b] = 1; + } + ReadToken(); + } + else + RV_INT("Flare texture", st->flareTexture) + RV_URI("Flare map", &st->flare, "LightMaps") + RV_URI("Top map", &st->up, "LightMaps") + RV_URI("Bottom map", &st->down, "LightMaps") + RV_URI("Side map", &st->sides, "LightMaps") + RV_END + CHECKSC; } - ReadToken(); + ++lightStage; } - else - RV_INT("Flare texture", dl->flareTexture) - RV_URI("Flare map", &dl->flare, "LightMaps") - RV_URI("Top map", &dl->up, "LightMaps") - RV_URI("Bottom map", &dl->down, "LightMaps") - RV_URI("Side map", &dl->sides, "LightMaps") - RV_END + else RV_END CHECKSC; } - light++; + ++light; } else RV_END CHECKSC; @@ -2248,11 +2276,11 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) for(int i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) { - ded_decorlight_t *dl = &decor->lights[i]; - if(dl->flare) dl->flare = Uri_Dup(dl->flare); - if(dl->up) dl->up = Uri_Dup(dl->up); - if(dl->down) dl->down = Uri_Dup(dl->down); - if(dl->sides) dl->sides = Uri_Dup(dl->sides); + ded_decorlight_stage_t *stage = &decor->lights[i].stages[0]; + if(stage->flare) stage->flare = Uri_Dup(stage->flare); + if(stage->up) stage->up = Uri_Dup(stage->up); + if(stage->down) stage->down = Uri_Dup(stage->down); + if(stage->sides) stage->sides = Uri_Dup(stage->sides); } } @@ -2277,6 +2305,7 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) else if(ISLABEL("Light")) { ded_decorlight_t *dl = &decor->lights[sub]; + ded_decorlight_stage_t *st = &dl->stages[0]; if(sub == DED_DECOR_NUM_LIGHTS) { @@ -2289,11 +2318,11 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) for(;;) { READLABEL; - RV_VEC("Offset", dl->pos, 2) - RV_FLT("Distance", dl->elevation) - RV_VEC("Color", dl->color, 3) - RV_FLT("Radius", dl->radius) - RV_FLT("Halo radius", dl->haloRadius) + RV_VEC("Offset", st->pos, 2) + RV_FLT("Distance", st->elevation) + RV_VEC("Color", st->color, 3) + RV_FLT("Radius", st->radius) + RV_FLT("Halo radius", st->haloRadius) RV_IVEC("Pattern offset", dl->patternOffset, 2) RV_IVEC("Pattern skip", dl->patternSkip, 2) if(ISLABEL("Levels")) @@ -2301,21 +2330,21 @@ static int DED_ReadData(ded_t* ded, const char* buffer, const char* _sourceFile) FINDBEGIN; for(int b = 0; b < 2; ++b) { - READFLT(dl->lightLevels[b]) - dl->lightLevels[b] /= 255.0f; - if(dl->lightLevels[b] < 0) - dl->lightLevels[b] = 0; - else if(dl->lightLevels[b] > 1) - dl->lightLevels[b] = 1; + READFLT(st->lightLevels[b]) + st->lightLevels[b] /= 255.0f; + if(st->lightLevels[b] < 0) + st->lightLevels[b] = 0; + else if(st->lightLevels[b] > 1) + st->lightLevels[b] = 1; } ReadToken(); } else - RV_INT("Flare texture", dl->flareTexture) - RV_URI("Flare map", &dl->flare, "LightMaps") - RV_URI("Top map", &dl->up, "LightMaps") - RV_URI("Bottom map", &dl->down, "LightMaps") - RV_URI("Side map", &dl->sides, "LightMaps") + RV_INT("Flare texture", st->flareTexture) + RV_URI("Flare map", &st->flare, "LightMaps") + RV_URI("Top map", &st->up, "LightMaps") + RV_URI("Bottom map", &st->down, "LightMaps") + RV_URI("Side map", &st->sides, "LightMaps") RV_END CHECKSC; } diff --git a/doomsday/engine/src/render/rend_decor.cpp b/doomsday/engine/src/render/rend_decor.cpp index b2387d44a7..6642fb5e05 100644 --- a/doomsday/engine/src/render/rend_decor.cpp +++ b/doomsday/engine/src/render/rend_decor.cpp @@ -26,13 +26,18 @@ #include "de_play.h" #include "de_graphics.h" #include "de_render.h" -#include "de_misc.h" #include - #include "def_main.h" +#include "m_profiler.h" #include "resource/materialvariant.h" +#include "render/rend_decor.h" + +extern void getLightingParams(coord_t x, coord_t y, coord_t z, BspLeaf *bspLeaf, + coord_t distance, boolean fullBright, + float ambientColor[3], uint *lightListIdx); + using namespace de; // Quite a bit of decorations, there! @@ -49,16 +54,13 @@ typedef struct decorsource_s { coord_t maxDistance; Surface const *surface; BspLeaf *bspLeaf; - unsigned int lumIdx; // Index+1 of linked lumobj, or 0. + uint lumIdx; // Index+1 of linked lumobj, or 0. float fadeMul; - Material::Decoration const *def; + Material::Decoration const *decor; DGLuint flareTex; struct decorsource_s *next; } decorsource_t; -static void updateSideSectionDecorations(LineDef *lineDef, byte side, SideDefSection section); -static void updatePlaneDecorations(Plane *pln); - byte useLightDecorations = true; float decorMaxDist = 2048; // No decorations are visible beyond this. float decorLightBrightFactor = 1; @@ -69,77 +71,69 @@ static uint numDecorations = 0; static decorsource_t *sourceFirst = 0; static decorsource_t *sourceCursor = 0; +static void updateSideSectionDecorations(LineDef &lineDef, byte side, SideDefSection section); +static void updatePlaneDecorations(Plane &pln); + void Rend_DecorRegister() { - C_VAR_BYTE("rend-light-decor", &useLightDecorations, 0, 0, 1); - C_VAR_FLOAT("rend-light-decor-angle", &decorLightFadeAngle, 0, 0, 1); + C_VAR_BYTE("rend-light-decor", &useLightDecorations, 0, 0, 1); + C_VAR_FLOAT("rend-light-decor-angle", &decorLightFadeAngle, 0, 0, 1); C_VAR_FLOAT("rend-light-decor-bright", &decorLightBrightFactor, 0, 0, 10); } -/** - * Clears the list of decoration dummies. - */ static void clearDecorations() { numDecorations = 0; sourceCursor = sourceFirst; } -extern void getLightingParams(coord_t x, coord_t y, coord_t z, BspLeaf* bspLeaf, - coord_t distance, boolean fullBright, - float ambientColor[3], uint* lightListIdx); - -static void projectDecoration(decorsource_t *src) +static void projectDecoration(decorsource_t const &src) { - float brightness, min, max; - lumobj_t const *lum; - vissprite_t *vis; - coord_t distance; + ded_decorlight_stage_t const *def = &src.decor->def->stages[0]; // Does it pass the sector light limitation? - min = src->def->lightLevels[0]; - max = src->def->lightLevels[1]; + float min = def->lightLevels[0]; + float max = def->lightLevels[1]; - if(!((brightness = R_CheckSectorLight(src->bspLeaf->sector->lightLevel, min, max)) > 0)) - return; + float brightness = R_CheckSectorLight(src.bspLeaf->sector->lightLevel, min, max); + if(!(brightness > 0)) return; - if(src->fadeMul <= 0) - return; + if(src.fadeMul <= 0) return; // Is the point in range? - distance = Rend_PointDist3D(src->origin); - if(distance > src->maxDistance) - return; + coord_t distance = Rend_PointDist3D(src.origin); + if(distance > src.maxDistance) return; /// @todo dj: Why is LO_GetLuminous returning NULL given a supposedly valid index? - if(!LO_GetLuminous(src->lumIdx)) - return; + if(!LO_GetLuminous(src.lumIdx)) return; /** * Model decorations become model-type vissprites. * Light decorations become flare-type vissprites. */ - vis = R_NewVisSprite(); + vissprite_t *vis = R_NewVisSprite(); vis->type = VSPR_FLARE; - V3d_Copy(vis->origin, src->origin); + V3d_Copy(vis->origin, src.origin); vis->distance = distance; - lum = LO_GetLuminous(src->lumIdx); + lumobj_t const *lum = LO_GetLuminous(src.lumIdx); vis->data.flare.isDecoration = true; - vis->data.flare.lumIdx = src->lumIdx; + vis->data.flare.lumIdx = src.lumIdx; // Color is taken from the associated lumobj. V3f_Copy(vis->data.flare.color, LUM_OMNI(lum)->color); - if(src->def->haloRadius > 0) - vis->data.flare.size = MAX_OF(1, src->def->haloRadius * 60 * (50 + haloSize) / 100.0f); + if(def->haloRadius > 0) + vis->data.flare.size = MAX_OF(1, def->haloRadius * 60 * (50 + haloSize) / 100.0f); else vis->data.flare.size = 0; - if(src->flareTex != 0) - vis->data.flare.tex = src->flareTex; + if(src.flareTex != 0) + { + vis->data.flare.tex = src.flareTex; + } else { // Primary halo disabled. vis->data.flare.flags |= RFF_NO_PRIMARY; @@ -148,17 +142,17 @@ static void projectDecoration(decorsource_t *src) // Halo brightness drops as the angle gets too big. vis->data.flare.mul = 1; - if(src->def->elevation < 2 && decorLightFadeAngle > 0) // Close the surface? + if(def->elevation < 2 && decorLightFadeAngle > 0) // Close the surface? { - float vector[3], dot; - - V3f_Set(vector, src->origin[VX] - vOrigin[VX], - src->origin[VY] - vOrigin[VZ], - src->origin[VZ] - vOrigin[VY]); + float vector[3]; + V3f_Set(vector, src.origin[VX] - vOrigin[VX], + src.origin[VY] - vOrigin[VZ], + src.origin[VZ] - vOrigin[VY]); V3f_Normalize(vector); - dot = -(src->surface->normal[VX] * vector[VX] + - src->surface->normal[VY] * vector[VY] + - src->surface->normal[VZ] * vector[VZ]); + + float dot = -(src.surface->normal[VX] * vector[VX] + + src.surface->normal[VY] * vector[VY] + + src.surface->normal[VZ] * vector[VZ]); if(dot < decorLightFadeAngle / 2) vis->data.flare.mul = 0; @@ -167,69 +161,54 @@ static void projectDecoration(decorsource_t *src) } } -/** - * Re-initialize the decoration source tracking (might be called during a map - * load or othersuch situation). - */ void Rend_DecorInit() { clearDecorations(); } -/** - * Project all the non-clipped decorations. They become regular vissprites. - */ void Rend_ProjectDecorations() { if(!useLightDecorations) return; - if(sourceFirst == sourceCursor) return; - - decorsource_t *src = sourceFirst; - do + for(decorsource_t *src = sourceFirst; src != sourceCursor; src = src->next) { - projectDecoration(src); - } while((src = src->next) != sourceCursor); + projectDecoration(*src); + } } -static void addLuminousDecoration(decorsource_t *src) +static void addLuminousDecoration(decorsource_t &src) { - de::Material::Decoration const *def = src->def; - float brightness; - uint i, lumIdx; - float min, max; - lumobj_t* l; + ded_decorlight_stage_t const *def = &src.decor->def->stages[0]; // Does it pass the sector light limitation? - min = def->lightLevels[0]; - max = def->lightLevels[1]; + float min = def->lightLevels[0]; + float max = def->lightLevels[1]; - if(!((brightness = R_CheckSectorLight(src->bspLeaf->sector->lightLevel, min, max)) > 0)) - return; + float brightness = R_CheckSectorLight(src.bspLeaf->sector->lightLevel, min, max); + if(!(brightness > 0)) return; // Apply the brightness factor (was calculated using sector lightlevel). - src->fadeMul = brightness * decorLightBrightFactor; - src->lumIdx = 0; + src.fadeMul = brightness * decorLightBrightFactor; + src.lumIdx = 0; - if(src->fadeMul <= 0) - return; + if(src.fadeMul <= 0) return; /** * @todo From here on is pretty much the same as LO_AddLuminous, * reconcile the two. */ - lumIdx = LO_NewLuminous(LT_OMNI, src->bspLeaf); - l = LO_GetLuminous(lumIdx); + uint lumIdx = LO_NewLuminous(LT_OMNI, src.bspLeaf); + lumobj_t *l = LO_GetLuminous(lumIdx); - V3d_Copy(l->origin, src->origin); - l->maxDistance = src->maxDistance; - l->decorSource = src; + V3d_Copy(l->origin, src.origin); + l->maxDistance = src.maxDistance; + l->decorSource = (void*)&src; LUM_OMNI(l)->zOff = 0; - LUM_OMNI(l)->tex = GL_PrepareLightmap(reinterpret_cast(&def->sides)); - LUM_OMNI(l)->ceilTex = GL_PrepareLightmap(reinterpret_cast(&def->up)); - LUM_OMNI(l)->floorTex = GL_PrepareLightmap(reinterpret_cast(&def->down)); + LUM_OMNI(l)->tex = GL_PrepareLightmap(def->sides); + LUM_OMNI(l)->ceilTex = GL_PrepareLightmap(def->up); + LUM_OMNI(l)->floorTex = GL_PrepareLightmap(def->down); // These are the same rules as in DL_MobjRadius(). LUM_OMNI(l)->radius = def->radius * 40 * loRadiusFactor; @@ -238,15 +217,12 @@ static void addLuminousDecoration(decorsource_t *src) if(LUM_OMNI(l)->radius > loMaxRadius) LUM_OMNI(l)->radius = loMaxRadius; - for(i = 0; i < 3; ++i) - LUM_OMNI(l)->color[i] = def->color[i] * src->fadeMul; + for(uint i = 0; i < 3; ++i) + LUM_OMNI(l)->color[i] = def->color[i] * src.fadeMul; - src->lumIdx = lumIdx; + src.lumIdx = lumIdx; } -/** - * Create lumobjs for all decorations who want them. - */ void Rend_AddLuminousDecorations() { BEGIN_PROF( PROF_DECOR_ADD_LUMINOUS ); @@ -256,7 +232,7 @@ BEGIN_PROF( PROF_DECOR_ADD_LUMINOUS ); decorsource_t *src = sourceFirst; do { - addLuminousDecoration(src); + addLuminousDecoration(*src); } while((src = src->next) != sourceCursor); } @@ -266,7 +242,7 @@ END_PROF( PROF_DECOR_ADD_LUMINOUS ); /** * Create a new decoration source. */ -static decorsource_t *addDecoration() +static decorsource_t *allocDecorSource() { decorsource_t *src; @@ -297,7 +273,7 @@ static decorsource_t *addDecoration() V3d_Set(src->origin, 0, 0, 0); src->bspLeaf = 0; src->surface = 0; - src->def = NULL; + src->decor = NULL; src->flareTex = 0; // Advance the cursor. @@ -308,41 +284,39 @@ static decorsource_t *addDecoration() } /** - * A decorsource is created from the specified surface decoration. + * A source is created from the specified surface decoration. */ -static void createDecorSource(Surface const *suf, Surface::Decoration const &dec, float maxDistance) +static void createDecorSource(Surface const &suf, Surface::Decoration const &dec, + float maxDistance) { // Out of sources? if(numDecorations >= MAX_DECOR_LIGHTS) return; ++numDecorations; + decorsource_t *src = allocDecorSource(); // Fill in the data for a new surface decoration. - decorsource_t *src = addDecoration(); V3d_Copy(src->origin, dec.origin); src->maxDistance = maxDistance; src->bspLeaf = dec.bspLeaf; - src->surface = suf; + src->surface = &suf; src->fadeMul = 1; - src->def = dec.def; - if(src->def) + src->decor = dec.def; + + ded_decorlight_stage_t const *def = &src->decor->def->stages[0]; + de::Uri const *flareUri = reinterpret_cast(def->flare); + if((!flareUri || flareUri->isEmpty()) || flareUri->path() != Path("-")) { - de::Material::Decoration const *def = src->def; - if(def->flare.isEmpty() || def->flare.path() != Path("-")) - { - src->flareTex = GL_PrepareFlareTexture(reinterpret_cast(&def->flare), - def->flareTexture); - } + src->flareTex = GL_PrepareFlareTexture(def->flare, def->flareTexture); } } /** * @return As this can also be used with iterators, will always return @c true. */ -boolean R_ProjectSurfaceDecorations(Surface *suf, void *context) +static boolean projectSurfaceDecorations(Surface *suf, void *context) { - float maxDist = *((float *) context); - uint i; + float const maxDist = *((float *) context); if(suf->inFlags & SUIF_UPDATE_DECORATIONS) { @@ -353,15 +327,17 @@ boolean R_ProjectSurfaceDecorations(Surface *suf, void *context) case DMU_SIDEDEF: { SideDef *sideDef = (SideDef *)suf->owner; LineDef *line = sideDef->line; - updateSideSectionDecorations(line, sideDef == line->L_frontsidedef? FRONT : BACK, + updateSideSectionDecorations(*line, sideDef == line->L_frontsidedef? FRONT : BACK, &sideDef->SW_middlesurface == suf? SS_MIDDLE : &sideDef->SW_bottomsurface == suf? SS_BOTTOM : SS_TOP); break; } + case DMU_PLANE: - updatePlaneDecorations((Plane *)suf->owner); + updatePlaneDecorations(*((Plane *)suf->owner)); break; + default: - Con_Error("R_ProjectSurfaceDecorations: Internal Error, unknown type %s.", DMU_Str(DMU_GetType(suf->owner))); + Con_Error("projectSurfaceDecorations: Unknown type %s.", DMU_Str(DMU_GetType(suf->owner))); break; } suf->inFlags &= ~SUIF_UPDATE_DECORATIONS; @@ -370,20 +346,18 @@ boolean R_ProjectSurfaceDecorations(Surface *suf, void *context) if(useLightDecorations) { Surface::Decoration const *decorations = (Surface::Decoration const *)suf->decorations; - for(i = 0; i < suf->numDecorations; ++i) + for(uint i = 0; i < suf->numDecorations; ++i) { - createDecorSource(suf, decorations[i], maxDist); + createDecorSource(*suf, decorations[i], maxDist); } } return true; } -/** - * Determine proper skip values. - */ -static void getDecorationSkipPattern(int const patternSkip[2], int *skip) +static inline void getDecorationSkipPattern(int const patternSkip[2], int skip[2]) { + DENG_ASSERT(patternSkip && skip); for(uint i = 0; i < 2; ++i) { // Skip must be at least one. @@ -392,46 +366,46 @@ static void getDecorationSkipPattern(int const patternSkip[2], int *skip) } } -static uint generateDecorLights(Material::Decoration const *def, Surface *suf, +static uint generateDecorLights(Material::Decoration const &decor, Surface &suf, material_t *mat, pvec3d_t const v1, pvec3d_t const /*v2*/, coord_t width, coord_t height, - pvec3d_t const delta, int axis, float offsetS, float offsetT, Sector* sec) + pvec3d_t const delta, int axis, float offsetS, float offsetT, Sector *sec) { - vec3d_t originBase, origin; - coord_t patternW, patternH; - float s, t; // Horizontal and vertical offset. - int skip[2]; - uint num; + ded_decorlight_stage_t const *def = &decor.def->stages[0]; if(!mat /*|| !Def_IsValidLightDecoration(def)*/) return 0; // Skip must be at least one. - getDecorationSkipPattern(def->patternSkip, skip); + int skip[2]; + getDecorationSkipPattern(decor.def->patternSkip, skip); - patternW = Material_Width(mat) * skip[0]; - patternH = Material_Height(mat) * skip[1]; + coord_t patternW = Material_Width(mat) * skip[0]; + coord_t patternH = Material_Height(mat) * skip[1]; if(0 == patternW && 0 == patternH) return 0; - V3d_Set(originBase, def->elevation * suf->normal[VX], - def->elevation * suf->normal[VY], - def->elevation * suf->normal[VZ]); + vec3d_t originBase; + V3d_Set(originBase, def->elevation * suf.normal[VX], + def->elevation * suf.normal[VY], + def->elevation * suf.normal[VZ]); V3d_Sum(originBase, originBase, v1); // Let's see where the top left light is. - s = M_CycleIntoRange(def->pos[0] - - Material_Width(mat) * def->patternOffset[0] + - offsetS, patternW); - num = 0; + float s = M_CycleIntoRange(def->pos[0] - + Material_Width(mat) * decor.def->patternOffset[0] + + offsetS, patternW); + uint num = 0; for(; s < width; s += patternW) { - t = M_CycleIntoRange(def->pos[1] - - Material_Height(mat) * def->patternOffset[1] + - offsetT, patternH); + float t = M_CycleIntoRange(def->pos[1] - + Material_Height(mat) * decor.def->patternOffset[1] + + offsetT, patternH); for(; t < height; t += patternH) { - float offS = s / width, offT = t / height; + float const offS = s / width; + float const offT = t / height; + vec3d_t origin; V3d_Set(origin, delta[VX] * offS, delta[VY] * (axis == VZ? offT : offS), delta[VZ] * (axis == VZ? offS : offT)); @@ -444,11 +418,11 @@ static uint generateDecorLights(Material::Decoration const *def, Surface *suf, continue; } - if(Surface::Decoration *dec = Surface_NewDecoration(suf)) + if(Surface::Decoration *dec = Surface_NewDecoration(&suf)) { V3d_Copy(dec->origin, origin); dec->bspLeaf = P_BspLeafAtPoint(dec->origin); - dec->def = def; + dec->def = &decor; num++; } } @@ -460,7 +434,7 @@ static uint generateDecorLights(Material::Decoration const *def, Surface *suf, /** * Generate decorations for the specified surface. */ -static void updateSurfaceDecorations2(Surface *suf, float offsetS, float offsetT, +static void updateSurfaceDecorations2(Surface &suf, float offsetS, float offsetT, vec3d_t v1, vec3d_t v2, Sector *sec, boolean visible) { if(!visible) return; @@ -470,16 +444,17 @@ static void updateSurfaceDecorations2(Surface *suf, float offsetS, float offsetT if(delta[VX] * delta[VY] != 0 || delta[VX] * delta[VZ] != 0 || delta[VY] * delta[VZ] != 0) { - int const axis = V3f_MajorAxis(suf->normal); + int const axis = V3f_MajorAxis(suf.normal); + coord_t width, height; if(axis == VX || axis == VY) { - width = sqrt(delta[VX] * delta[VX] + delta[VY] * delta[VY]); + width = sqrt(delta[VX] * delta[VX] + delta[VY] * delta[VY]); height = delta[VZ]; } else { - width = sqrt(delta[VX] * delta[VX]); + width = sqrt(delta[VX] * delta[VX]); height = delta[VY]; } @@ -487,80 +462,70 @@ static void updateSurfaceDecorations2(Surface *suf, float offsetS, float offsetT if(height < 0) height = -height; // Generate a number of lights. - Material::Decorations const &decorations = Material_Decorations(suf->material); + Material::Decorations const &decorations = Material_Decorations(suf.material); DENG2_FOR_EACH_CONST(Material::Decorations, i, decorations) { - generateDecorLights(*i, suf, suf->material, v1, v2, width, height, + generateDecorLights(**i, suf, suf.material, v1, v2, width, height, delta, axis, offsetS, offsetT, sec); } } } -/** - * Generate decorations for a plane. - */ -static void updatePlaneDecorations(Plane *pln) +static void updatePlaneDecorations(Plane &pln) { - Sector *sec = pln->sector; - Surface *suf = &pln->surface; - vec3d_t v1, v2; - float offsetS, offsetT; + Sector &sec = *pln.sector; + Surface &suf = pln.surface; - if(pln->type == PLN_FLOOR) + vec3d_t v1, v2; + if(pln.type == PLN_FLOOR) { - V3d_Set(v1, sec->aaBox.minX, sec->aaBox.maxY, pln->visHeight); - V3d_Set(v2, sec->aaBox.maxX, sec->aaBox.minY, pln->visHeight); + V3d_Set(v1, sec.aaBox.minX, sec.aaBox.maxY, pln.visHeight); + V3d_Set(v2, sec.aaBox.maxX, sec.aaBox.minY, pln.visHeight); } else { - V3d_Set(v1, sec->aaBox.minX, sec->aaBox.minY, pln->visHeight); - V3d_Set(v2, sec->aaBox.maxX, sec->aaBox.maxY, pln->visHeight); + V3d_Set(v1, sec.aaBox.minX, sec.aaBox.minY, pln.visHeight); + V3d_Set(v2, sec.aaBox.maxX, sec.aaBox.maxY, pln.visHeight); } - offsetS = -fmod(sec->aaBox.minX, 64) - suf->visOffset[0]; - offsetT = -fmod(sec->aaBox.minY, 64) - suf->visOffset[1]; + float offsetS = -fmod(sec.aaBox.minX, 64) - suf.visOffset[0]; + float offsetT = -fmod(sec.aaBox.minY, 64) - suf.visOffset[1]; - updateSurfaceDecorations2(suf, offsetS, offsetT, v1, v2, sec, suf->material? true : false); + updateSurfaceDecorations2(suf, offsetS, offsetT, v1, v2, &sec, suf.material? true : false); } -static void updateSideSectionDecorations(LineDef *line, byte side, SideDefSection section) +static void updateSideSectionDecorations(LineDef &line, byte side, SideDefSection section) { + if(!line.L_sidedef(side)) return; + + Surface &surface = line.L_sidedef(side)->SW_surface(section); + boolean visible = false; float matOffset[2]; - Surface *surface; vec3d_t v1, v2; - boolean visible = false; - - if(!line || !line->L_sidedef(side)) return; - surface = &line->L_sidedef(side)->SW_surface(section); - if(surface->material) + if(surface.material) { - Sector *frontSec = line->L_sector(side); - Sector *backSec = line->L_sector(side^1); - SideDef *frontDef = line->L_sidedef(side); - SideDef *backDef = line->L_sidedef(side^1); + Sector *frontSec = line.L_sector(side); + Sector *backSec = line.L_sector(side^1); + SideDef *frontDef = line.L_sidedef(side); + SideDef *backDef = line.L_sidedef(side^1); coord_t low, hi; - visible = R_FindBottomTop2(section, line->flags, frontSec, backSec, frontDef, backDef, + visible = R_FindBottomTop2(section, line.flags, frontSec, backSec, frontDef, backDef, &low, &hi, matOffset); if(visible) { - V3d_Set(v1, line->L_vorigin(side )[VX], line->L_vorigin(side )[VY], hi); - V3d_Set(v2, line->L_vorigin(side^1)[VX], line->L_vorigin(side^1)[VY], low); + V3d_Set(v1, line.L_vorigin(side )[VX], line.L_vorigin(side )[VY], hi); + V3d_Set(v2, line.L_vorigin(side^1)[VX], line.L_vorigin(side^1)[VY], low); } } updateSurfaceDecorations2(surface, -matOffset[0], -matOffset[1], v1, v2, NULL, visible); } -/** - * Decorations are generated for each frame. - */ void Rend_InitDecorationsForFrame() { - surfacelist_t *slist; #ifdef DD_PROFILE static int i; - if(++i > 40) { i = 0; @@ -577,10 +542,9 @@ BEGIN_PROF( PROF_DECOR_PROJECT ); clearDecorations(); - slist = GameMap_DecoratedSurfaces(theMap); - if(slist) + if(surfacelist_t *slist = GameMap_DecoratedSurfaces(theMap)) { - R_SurfaceListIterate(slist, R_ProjectSurfaceDecorations, &decorMaxDist); + R_SurfaceListIterate(slist, projectSurfaceDecorations, &decorMaxDist); } END_PROF( PROF_DECOR_PROJECT ); diff --git a/doomsday/engine/src/resource/material.cpp b/doomsday/engine/src/resource/material.cpp index ad4b33dec9..66e238e4e1 100644 --- a/doomsday/engine/src/resource/material.cpp +++ b/doomsday/engine/src/resource/material.cpp @@ -287,35 +287,10 @@ void Material_Delete(material_t *mat) } } -void Material_AddDecoration(material_t *mat, ded_decorlight_t const *def) +void Material_AddDecoration(material_t *mat, ded_decorlight_t *def) { - DENG_ASSERT(mat); - Material::Decoration *decor = new Material::Decoration(); - std::memcpy(decor->pos, def->pos, sizeof(decor->pos)); - decor->elevation = def->elevation; - std::memcpy(decor->color, def->color, sizeof(decor->color)); - decor->radius = def->radius; - decor->haloRadius = def->haloRadius; - std::memcpy(decor->patternOffset, def->patternOffset, sizeof(decor->patternOffset)); - std::memcpy(decor->patternSkip, def->patternSkip, sizeof(decor->patternSkip)); - std::memcpy(decor->lightLevels, def->lightLevels, sizeof(decor->lightLevels)); - decor->flareTexture = def->flareTexture; - if(def->up) - { - decor->up = *reinterpret_cast(def->up); - } - if(def->down) - { - decor->down = *reinterpret_cast(def->down); - } - if(def->sides) - { - decor->sides = *reinterpret_cast(def->sides); - } - if(def->flare) - { - decor->flare = *reinterpret_cast(def->flare); - } + DENG_ASSERT(mat && def); + Material::Decoration *decor = new Material::Decoration(*def); mat->decorations.push_back(decor); }