From d8e9b2a9ac15e0325e59ba72e28547162a649c29 Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 31 Aug 2013 07:11:51 +0100 Subject: [PATCH] Refactor|Client: Relocated various functions from r_things.cpp to better homes --- doomsday/client/include/r_util.h | 6 + doomsday/client/include/render/r_shadow.h | 8 ++ doomsday/client/include/render/r_things.h | 27 +--- doomsday/client/include/world/p_object.h | 14 +- doomsday/client/src/r_util.cpp | 23 +++ doomsday/client/src/render/lumobj.cpp | 3 +- doomsday/client/src/render/r_shadow.cpp | 79 ++++++++++- doomsday/client/src/render/r_things.cpp | 154 +-------------------- doomsday/client/src/render/rend_shadow.cpp | 4 +- doomsday/client/src/world/p_mobj.cpp | 110 ++++++++++++--- doomsday/client/src/world/p_objlink.cpp | 2 +- doomsday/server/src/server_dummies.cpp | 6 - 12 files changed, 229 insertions(+), 207 deletions(-) diff --git a/doomsday/client/include/r_util.h b/doomsday/client/include/r_util.h index 43ea922664..c2d0fe8101 100644 --- a/doomsday/client/include/r_util.h +++ b/doomsday/client/include/r_util.h @@ -25,6 +25,12 @@ #include #include +float R_MovementYaw(float const mom[2]); +float R_MovementXYYaw(float momx, float momy); + +float R_MovementPitch(float const mom[3]); +float R_MovementXYZPitch(float momx, float momy, float momz); + /** * Get a global angle from Cartesian coordinates in the map coordinate space * relative to the viewer. diff --git a/doomsday/client/include/render/r_shadow.h b/doomsday/client/include/render/r_shadow.h index 21865c78c8..f7323292ee 100644 --- a/doomsday/client/include/render/r_shadow.h +++ b/doomsday/client/include/render/r_shadow.h @@ -91,4 +91,12 @@ int R_IterateShadowProjections(uint listIdx, int (*callback) (shadowprojection_t */ Plane *R_FindShadowPlane(struct mobj_s *mobj); +/** + * Calculate the strength of the shadow this mobj should cast. + * + * @note Implemented using a greatly simplified version of the lighting equation; + * no light diminishing or light range compression. + */ +float R_ShadowStrength(struct mobj_s *mo); + #endif // DENG_RENDER_SHADOW_H diff --git a/doomsday/client/include/render/r_things.h b/doomsday/client/include/render/r_things.h index 25f2355d46..cf42bef839 100644 --- a/doomsday/client/include/render/r_things.h +++ b/doomsday/client/include/render/r_things.h @@ -21,7 +21,7 @@ #ifndef DENG_RENDER_THINGS_H #define DENG_RENDER_THINGS_H -#include "Materials" +#include DENG_EXTERN_C int levelFullBright; DENG_EXTERN_C float pspOffset[2], pspLightLevelMultiplier; @@ -38,31 +38,6 @@ DENG_EXTERN_C int psp3d; extern "C" { #endif -/// @return Radius of the mobj as it would visually appear to be. -coord_t R_VisualRadius(struct mobj_s *mo); - -/** - * Calculate the strength of the shadow this mobj should cast. - * - * @note Implemented using a greatly simplified version of the lighting equation; - * no light diminishing or light range compression. - */ -float R_ShadowStrength(struct mobj_s *mo); - -float R_Alpha(struct mobj_s *mo); - -/** - * @return The current floatbob offset for the mobj, if the mobj is flagged - * for bobbing; otherwise @c 0. - */ -coord_t R_GetBobOffset(struct mobj_s *mo); - -float R_MovementYaw(float const mom[2]); -float R_MovementXYYaw(float momx, float momy); - -float R_MovementPitch(float const mom[3]); -float R_MovementXYZPitch(float momx, float momy, float momz); - /** * Generates a vissprite for a mobj if it might be visible. */ diff --git a/doomsday/client/include/world/p_object.h b/doomsday/client/include/world/p_object.h index 19a22e58fe..21b8a34703 100644 --- a/doomsday/client/include/world/p_object.h +++ b/doomsday/client/include/world/p_object.h @@ -36,8 +36,7 @@ extern "C" { typedef struct mobj_s { DD_BASE_MOBJ_ELEMENTS() -} -mobj_t; +} mobj_t; #define MOBJ_SIZE gx.mobjSize @@ -68,6 +67,17 @@ coord_t Mobj_ApproxPointDistance(mobj_t *start, coord_t const *point); boolean Mobj_UnlinkFromSector(mobj_t *mobj); +/** + * @return The current floatbob offset for the mobj, if the mobj is flagged + * for bobbing; otherwise @c 0. + */ +coord_t Mobj_BobOffset(mobj_t *mobj); + +float Mobj_Alpha(mobj_t *mo); + +/// @return Radius of the mobj as it would visually appear to be. +coord_t Mobj_VisualRadius(mobj_t *mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/doomsday/client/src/r_util.cpp b/doomsday/client/src/r_util.cpp index 490667e579..95c790cabb 100644 --- a/doomsday/client/src/r_util.cpp +++ b/doomsday/client/src/r_util.cpp @@ -34,6 +34,29 @@ using namespace de; +float R_MovementYaw(float const mom[]) +{ + // Multiply by 100 to get some artificial accuracy in bamsAtan2. + return BANG2DEG(bamsAtan2(-100 * mom[MY], 100 * mom[MX])); +} + +float R_MovementXYYaw(float momx, float momy) +{ + float mom[2] = { momx, momy }; + return R_MovementYaw(mom); +} + +float R_MovementPitch(float const mom[]) +{ + return BANG2DEG(bamsAtan2 (100 * mom[MZ], 100 * V2f_Length(mom))); +} + +float R_MovementXYZPitch(float momx, float momy, float momz) +{ + float mom[3] = { momx, momy, momz }; + return R_MovementPitch(mom); +} + angle_t R_ViewPointToAngle(Vector2d point) { viewdata_t const *viewData = R_ViewData(viewPlayer - ddPlayers); diff --git a/doomsday/client/src/render/lumobj.cpp b/doomsday/client/src/render/lumobj.cpp index 411b64d676..59a51319b7 100644 --- a/doomsday/client/src/render/lumobj.cpp +++ b/doomsday/client/src/render/lumobj.cpp @@ -27,6 +27,7 @@ #include "de_console.h" #include "de_render.h" #include "de_graphics.h" +#include "de_resource.h" #include "de_misc.h" #include "de_play.h" #include "de_defs.h" @@ -801,7 +802,7 @@ static void addLuminous(mobj_t *mo) } Texture &tex = ms.texture(MTU_PRIMARY).generalCase(); - float center = -tex.origin().y - mo->floorClip - R_GetBobOffset(mo) - yOffset; + float center = -tex.origin().y - mo->floorClip - Mobj_BobOffset(mo) - yOffset; // Will the sprite be allowed to go inside the floor? float mul = mo->origin[VZ] + -tex.origin().y - (float) ms.height() - mo->bspLeaf->visFloor().height(); diff --git a/doomsday/client/src/render/r_shadow.cpp b/doomsday/client/src/render/r_shadow.cpp index 57edd33518..3b42ff272b 100644 --- a/doomsday/client/src/render/r_shadow.cpp +++ b/doomsday/client/src/render/r_shadow.cpp @@ -30,11 +30,14 @@ #include "de_console.h" #include "de_render.h" #include "de_play.h" +#include "de_resource.h" #include "api_map.h" #include "world/map.h" #include "BspLeaf" +#include "gl/gl_tex.h" + #include "render/r_shadow.h" using namespace de; @@ -227,7 +230,7 @@ int RIT_ProjectShadowToSurfaceIterator(void *mobj, void *parameters) return false; // Calculate the radius of the shadow. - float shadowRadius = R_VisualRadius(mo); + float shadowRadius = Mobj_VisualRadius(mo); if(shadowRadius <= 0) return false; @@ -236,7 +239,7 @@ int RIT_ProjectShadowToSurfaceIterator(void *mobj, void *parameters) mobjOrigin[VZ] -= mo->floorClip; if(mo->ddFlags & DDMF_BOB) - mobjOrigin[VZ] -= R_GetBobOffset(mo); + mobjOrigin[VZ] -= Mobj_BobOffset(mo); coord_t mobjHeight = mo->height; if(!mobjHeight) mobjHeight = 1; @@ -381,3 +384,75 @@ Plane *R_FindShadowPlane(mobj_t *mo) } return 0; } + +static modeldef_t *currentModelDefForMobj(mobj_t *mo) +{ + // If models are being used, use the model's radius. + if(useModels) + { + modeldef_t *mf = 0, *nextmf = 0; + Models_ModelForMobj(mo, &mf, &nextmf); + return mf; + } + return 0; +} + +float R_ShadowStrength(mobj_t *mo) +{ + DENG_ASSERT(mo); + + float const minSpriteAlphaLimit = .1f; + float ambientLightLevel, strength = .65f; ///< Default strength factor. + + // Is this mobj in a valid state for shadow casting? + if(!mo->state || !mo->bspLeaf) return 0; + + // Should this mobj even have a shadow? + if((mo->state->flags & STF_FULLBRIGHT) || + (mo->ddFlags & DDMF_DONTDRAW) || (mo->ddFlags & DDMF_ALWAYSLIT)) + return 0; + + // Sample the ambient light level at the mobj's position. + if(useBias && App_World().map().hasLightGrid()) + { + // Evaluate in the light grid. + ambientLightLevel = App_World().map().lightGrid().evaluateLightLevel(mo->origin); + } + else + { + ambientLightLevel = mo->bspLeaf->sector().lightLevel(); + Rend_ApplyLightAdaptation(ambientLightLevel); + } + + // Sprites have their own shadow strength factor. + if(!currentModelDefForMobj(mo)) + { + Material *mat = R_MaterialForSprite(mo->sprite, mo->frame); + if(mat) + { + // 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); + DENG_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 *= MIN_OF(1, 0.2f + weightedSpriteAlpha); + } + } + + // Factor in Mobj alpha. + strength *= Mobj_Alpha(mo); + + /// @note This equation is the same as that used for fakeradio. + return (0.6f - ambientLightLevel * 0.4f) * strength; +} diff --git a/doomsday/client/src/render/r_things.cpp b/doomsday/client/src/render/r_things.cpp index 831949bb89..40dd391ec5 100644 --- a/doomsday/client/src/render/r_things.cpp +++ b/doomsday/client/src/render/r_things.cpp @@ -73,122 +73,6 @@ int maxModelDistance = 1500; int levelFullBright; #ifdef __CLIENT__ -static modeldef_t *currentModelDefForMobj(mobj_t *mo) -{ - // If models are being used, use the model's radius. - if(useModels) - { - modeldef_t *mf = 0, *nextmf = 0; - Models_ModelForMobj(mo, &mf, &nextmf); - return mf; - } - return 0; -} - -coord_t R_VisualRadius(mobj_t *mo) -{ - // If models are being used, use the model's radius. - if(modeldef_t *mf = currentModelDefForMobj(mo)) - { - return mf->visualRadius; - } - - // Use the sprite frame's width? - if(Material *material = R_MaterialForSprite(mo->sprite, mo->frame)) - { - MaterialSnapshot const &ms = material->prepare(Rend_SpriteMaterialSpec()); - return ms.width() / 2; - } - - // Use the physical radius. - return mo->radius; -} - -float R_ShadowStrength(mobj_t *mo) -{ - DENG_ASSERT(mo); - - float const minSpriteAlphaLimit = .1f; - float ambientLightLevel, strength = .65f; ///< Default strength factor. - - // Is this mobj in a valid state for shadow casting? - if(!mo->state || !mo->bspLeaf) return 0; - - // Should this mobj even have a shadow? - if((mo->state->flags & STF_FULLBRIGHT) || - (mo->ddFlags & DDMF_DONTDRAW) || (mo->ddFlags & DDMF_ALWAYSLIT)) - return 0; - - // Sample the ambient light level at the mobj's position. - if(useBias && App_World().map().hasLightGrid()) - { - // Evaluate in the light grid. - ambientLightLevel = App_World().map().lightGrid().evaluateLightLevel(mo->origin); - } - else - { - ambientLightLevel = mo->bspLeaf->sector().lightLevel(); - Rend_ApplyLightAdaptation(ambientLightLevel); - } - - // Sprites have their own shadow strength factor. - if(!currentModelDefForMobj(mo)) - { - Material *mat = R_MaterialForSprite(mo->sprite, mo->frame); - if(mat) - { - // 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); - DENG_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 *= MIN_OF(1, 0.2f + weightedSpriteAlpha); - } - } - - // Factor in Mobj alpha. - strength *= R_Alpha(mo); - - /// @note This equation is the same as that used for fakeradio. - return (0.6f - ambientLightLevel * 0.4f) * strength; -} - -float R_Alpha(mobj_t *mo) -{ - DENG_ASSERT(mo); - - float alpha = (mo->ddFlags & DDMF_BRIGHTSHADOW)? .80f : - (mo->ddFlags & DDMF_SHADOW )? .33f : - (mo->ddFlags & DDMF_ALTSHADOW )? .66f : 1; - /** - * The three highest bits of the selector are used for alpha. - * 0 = opaque (alpha -1) - * 1 = 1/8 transparent - * 4 = 1/2 transparent - * 7 = 7/8 transparent - */ - int selAlpha = mo->selector >> DDMOBJ_SELECTOR_SHIFT; - if(selAlpha & 0xe0) - { - alpha *= 1 - ((selAlpha & 0xe0) >> 5) / 8.0f; - } - else if(mo->translucency) - { - alpha *= 1 - mo->translucency * reciprocal255; - } - return alpha; -} void R_ProjectPlayerSprites() { @@ -302,29 +186,6 @@ void R_ProjectPlayerSprites() } } -float R_MovementYaw(float const mom[]) -{ - // Multiply by 100 to get some artificial accuracy in bamsAtan2. - return BANG2DEG(bamsAtan2(-100 * mom[MY], 100 * mom[MX])); -} - -float R_MovementXYYaw(float momx, float momy) -{ - float mom[2] = { momx, momy }; - return R_MovementYaw(mom); -} - -float R_MovementPitch(float const mom[]) -{ - return BANG2DEG(bamsAtan2 (100 * mom[MZ], 100 * V2f_Length(mom))); -} - -float R_MovementXYZPitch(float momx, float momy, float momz) -{ - float mom[3] = { momx, momy, momz }; - return R_MovementPitch(mom); -} - typedef struct { vissprite_t *vis; mobj_t const *mo; @@ -559,7 +420,7 @@ void R_ProjectSprite(mobj_t *mo) spriteframe_t *sprFrame = spriteFrame(mo->sprite, mo->frame); if(!sprFrame) return; // ...fully transparent? - float const alpha = R_Alpha(mo); + float const alpha = Mobj_Alpha(mo); if(alpha <= 0) return; // ...origin lies in a sector with no volume? if(!mo->bspLeaf->hasWorldVolume()) return; @@ -616,7 +477,7 @@ void R_ProjectSprite(mobj_t *mo) * relative to the viewer and determining if the whole of the segment has * been clipped away according to the 360 degree angle clipper. */ - coord_t const visWidth = R_VisualRadius(mo) * 2; /// @todo ignorant of rotation... + coord_t const visWidth = Mobj_VisualRadius(mo) * 2; /// @todo ignorant of rotation... Vector2d v1, v2; R_ProjectViewRelativeLine2D(moPos, mf || viewAlign, visWidth, (mf? 0 : coord_t(-tex.origin().x) - (visWidth / 2.0f)), @@ -669,7 +530,7 @@ void R_ProjectSprite(mobj_t *mo) if(mo->ddFlags & DDMF_BOB) { // Bobbing is applied using floorclip. - floorClip += R_GetBobOffset(mo); + floorClip += Mobj_BobOffset(mo); } float yaw = 0, pitch = 0; @@ -892,13 +753,4 @@ void R_ProjectSprite(mobj_t *mo) } } -coord_t R_GetBobOffset(mobj_t* mo) -{ - if(mo->ddFlags & DDMF_BOB) - { - return (sin(MOBJ_TO_ID(mo) + App_World().time() / 1.8286 * 2 * PI) * 8); - } - return 0; -} - #endif // __CLIENT__ diff --git a/doomsday/client/src/render/rend_shadow.cpp b/doomsday/client/src/render/rend_shadow.cpp index 52938efc9d..05dc0a71f9 100644 --- a/doomsday/client/src/render/rend_shadow.cpp +++ b/doomsday/client/src/render/rend_shadow.cpp @@ -108,13 +108,13 @@ static void processMobjShadow(mobj_t *mo) if(usingFog) shadowStrength /= 2; if(shadowStrength <= 0) return; - coord_t shadowRadius = R_VisualRadius(mo); + coord_t shadowRadius = Mobj_VisualRadius(mo); if(shadowRadius <= 0) return; // Check the height. coord_t moz = mo->origin[VZ] - mo->floorClip; if(mo->ddFlags & DDMF_BOB) - moz -= R_GetBobOffset(mo); + moz -= Mobj_BobOffset(mo); coord_t heightFromSurface = moz - mo->floorZ; coord_t moh = mo->height; diff --git a/doomsday/client/src/world/p_mobj.cpp b/doomsday/client/src/world/p_mobj.cpp index e91da0780c..3e73d9fd77 100644 --- a/doomsday/client/src/world/p_mobj.cpp +++ b/doomsday/client/src/world/p_mobj.cpp @@ -28,12 +28,16 @@ #include "de_system.h" #include "de_network.h" #include "de_play.h" +#include "de_resource.h" #include "de_misc.h" #include "de_audio.h" #include "def_main.h" #include "render/r_main.h" // validCount, viewport #include "render/r_things.h" // useSRVO +#ifdef __CLIENT__ +# include "render/sprite.h" +#endif #include "world/thinkers.h" #include "BspLeaf" @@ -141,6 +145,28 @@ void P_MobjRecycle(mobj_t* mo) unusedMobjs = mo; } +/** + * Two links to update: + * 1) The link to us from the previous node (sprev, always set) will + * be modified to point to the node following us. + * 2) If there is a node following us, set its sprev pointer to point + * to the pointer that points back to it (our sprev, just modified). + */ +boolean Mobj_UnlinkFromSector(mobj_t *mo) +{ + if(!mo || !IS_SECTOR_LINKED(mo)) + return false; + + if((*mo->sPrev = mo->sNext)) + mo->sNext->sPrev = mo->sPrev; + + // Not linked any more. + mo->sNext = 0; + mo->sPrev = 0; + + return true; +} + /** * 'statenum' must be a valid state (not null!). */ @@ -271,26 +297,78 @@ coord_t Mobj_ApproxPointDistance(mobj_t* mo, coord_t const* point) point[VY] - mo->origin[VY])); } -/** - * Two links to update: - * 1) The link to us from the previous node (sprev, always set) will - * be modified to point to the node following us. - * 2) If there is a node following us, set its sprev pointer to point - * to the pointer that points back to it (our sprev, just modified). - */ -boolean Mobj_UnlinkFromSector(mobj_t *mo) +coord_t Mobj_BobOffset(mobj_t *mo) { - if(!mo || !IS_SECTOR_LINKED(mo)) - return false; + if(mo->ddFlags & DDMF_BOB) + { + return (sin(MOBJ_TO_ID(mo) + App_World().time() / 1.8286 * 2 * PI) * 8); + } + return 0; +} - if((*mo->sPrev = mo->sNext)) - mo->sNext->sPrev = mo->sPrev; +float Mobj_Alpha(mobj_t *mo) +{ + DENG_ASSERT(mo); + + float alpha = (mo->ddFlags & DDMF_BRIGHTSHADOW)? .80f : + (mo->ddFlags & DDMF_SHADOW )? .33f : + (mo->ddFlags & DDMF_ALTSHADOW )? .66f : 1; + /** + * The three highest bits of the selector are used for alpha. + * 0 = opaque (alpha -1) + * 1 = 1/8 transparent + * 4 = 1/2 transparent + * 7 = 7/8 transparent + */ + int selAlpha = mo->selector >> DDMOBJ_SELECTOR_SHIFT; + if(selAlpha & 0xe0) + { + alpha *= 1 - ((selAlpha & 0xe0) >> 5) / 8.0f; + } + else if(mo->translucency) + { + alpha *= 1 - mo->translucency * reciprocal255; + } + return alpha; +} - // Not linked any more. - mo->sNext = 0; - mo->sPrev = 0; +#ifdef __CLIENT__ - return true; +static modeldef_t *currentModelDefForMobj(mobj_t *mo) +{ + // If models are being used, use the model's radius. + if(useModels) + { + modeldef_t *mf = 0, *nextmf = 0; + Models_ModelForMobj(mo, &mf, &nextmf); + return mf; + } + return 0; +} + +#endif // __CLIENT__ + +coord_t Mobj_VisualRadius(mobj_t *mo) +{ +#ifdef __CLIENT__ + + // If models are being used, use the model's radius. + if(modeldef_t *mf = currentModelDefForMobj(mo)) + { + return mf->visualRadius; + } + + // Use the sprite frame's width? + if(Material *material = R_MaterialForSprite(mo->sprite, mo->frame)) + { + MaterialSnapshot const &ms = material->prepare(Rend_SpriteMaterialSpec()); + return ms.width() / 2; + } + +#endif + + // Use the physical radius. + return mo->radius; } D_CMD(InspectMobj) diff --git a/doomsday/client/src/world/p_objlink.cpp b/doomsday/client/src/world/p_objlink.cpp index 907d949cbf..c7cb0c861a 100644 --- a/doomsday/client/src/world/p_objlink.cpp +++ b/doomsday/client/src/world/p_objlink.cpp @@ -520,7 +520,7 @@ static void findContacts(objlink_t *link) mobj_t *mo = (mobj_t *) link->obj; origin = mo->origin; - radius = R_VisualRadius(mo); + radius = Mobj_VisualRadius(mo); bspLeaf = mo->bspLeaf; break; } diff --git a/doomsday/server/src/server_dummies.cpp b/doomsday/server/src/server_dummies.cpp index c8baec7540..f24b909c7a 100644 --- a/doomsday/server/src/server_dummies.cpp +++ b/doomsday/server/src/server_dummies.cpp @@ -693,12 +693,6 @@ void Sys_MessageBoxWithDetailsFromFile(messageboxtype_t /*type*/, const char* /* { } -DENG_EXTERN_C coord_t R_VisualRadius(struct mobj_s *mo) -{ - DENG_UNUSED(mo); - return 0; -} - DENG_EXTERN_C void R_ProjectSprite(struct mobj_s *mo) { DENG_UNUSED(mo);