Skip to content

Commit

Permalink
Sector: New mechanisms for querying/updating ambient light color and …
Browse files Browse the repository at this point in the history
…level
  • Loading branch information
danij-deng committed Apr 8, 2013
1 parent 42e7e14 commit c7c24f9
Show file tree
Hide file tree
Showing 18 changed files with 370 additions and 179 deletions.
6 changes: 4 additions & 2 deletions doomsday/client/include/map/r_world.h
Expand Up @@ -20,13 +20,15 @@
#ifndef LIBDENG_MAP_WORLD_H
#define LIBDENG_MAP_WORLD_H

#include <de/Observers>
#include <de/Vector>

#include "resource/r_data.h"
#include "map/vertex.h"
#include "map/sector.h"
#include "map/sidedef.h"
#include "map/plane.h"
#include "map/sidedef.h"
#include <de/Observers>

/// @todo The MapChange audience belongs in a class.
DENG2_DECLARE_AUDIENCE(MapChange, void currentMapChanged())
Expand All @@ -45,7 +47,7 @@ extern boolean firstFrameAfterLoad;
/**
* Sector light color may be affected by the sky light color.
*/
const_pvec3f_t &R_GetSectorLightColor(Sector const *sector);
de::Vector3f const &R_GetSectorLightColor(Sector const &sector);

float R_DistAttenuateLightLevel(float distToViewer, float lightLevel);

Expand Down
146 changes: 132 additions & 14 deletions doomsday/client/include/map/sector.h
Expand Up @@ -62,6 +62,12 @@ class Sector : public de::MapElement
/// The referenced property is not writeable. @ingroup errors
DENG2_ERROR(WritePropertyError);

DENG2_DEFINE_AUDIENCE(LightLevelChange,
void lightLevelChanged(Sector &sector, float oldLightLevel))

DENG2_DEFINE_AUDIENCE(LightColorChange,
void lightColorChanged(Sector &sector, de::Vector3f const &oldLightColor))

typedef QList<LineDef *> Lines;
typedef QList<Plane *> Planes;
typedef QList<BspLeaf *> BspLeafs;
Expand Down Expand Up @@ -101,10 +107,10 @@ class Sector : public de::MapElement
float _oldLightLevel;

/// Ambient light color in the sector.
vec3f_t _lightColor;
de::Vector3f _lightColor;

/// Old ambient light color in the sector. For smoothing.
vec3f_t _oldLightColor;
de::Vector3f _oldLightColor;

/// Head of the linked list of mobjs "in" the sector (not owned).
struct mobj_s *_mobjList;
Expand Down Expand Up @@ -135,18 +141,8 @@ class Sector : public de::MapElement
int _origIndex;

public:
Sector();
~Sector();

/**
* Returns the ambient light level in the sector.
*/
float lightLevel() const;

/**
* Returns the ambient light color in the sector.
*/
const_pvec3f_t &lightColor() const;
Sector(float lightLevel = 1.f,
de::Vector3f const &lightColor = de::Vector3f(1.f, 1.f, 1.f));

/**
* Returns the first mobj in the linked list of mobjs "in" the sector.
Expand Down Expand Up @@ -328,6 +324,125 @@ class Sector : public de::MapElement
*/
void updateSoundEmitterOrigin();

/**
* Returns the ambient light level in the sector. The LightLevelChange
* audience is notified whenever the light level changes.
*
* @see setLightLevel()
*/
float lightLevel() const;

/**
* Change the ambient light level in the sector. The LightLevelChange
* audience is notified whenever the light level changes.
*
* @param newLightLevel New ambient light level.
*
* @see lightLevel()
*/
void setLightLevel(float newLightLevel);

/**
* Returns the ambient light color in the sector. The LightColorChange
* audience is notified whenever the light color changes.
*
* @see setLightColor(), lightColorComponent(), lightRed(), lightGreen(), lightBlue()
*/
de::Vector3f const &lightColor() const;

/**
* Returns the strength of the specified @a component of the ambient light
* color in the sector. The LightColorChange audience is notified whenever
* the light color changes.
*
* @param component RGB index of the color component (0=Red, 1=Green, 2=Blue).
*
* @see lightColor(), lightRed(), lightGreen(), lightBlue()
*/
inline float lightColorComponent(int component) const { return lightColor()[component]; }

/**
* Returns the strength of the @em red component of the ambient light
* color in the sector. The LightColorChange audience is notified whenever
* the light color changes.
*
* @see lightColorComponent(), lightGreen(), lightBlue()
*/
inline float lightRed() const { return lightColorComponent(0); }

/**
* Returns the strength of the @em green component of the ambient light
* color in the sector. The LightColorChange audience is notified whenever
* the light color changes.
*
* @see lightColorComponent(), lightRed(), lightBlue()
*/
inline float lightGreen() const { return lightColorComponent(1); }

/**
* Returns the strength of the @em blue component of the ambient light
* color in the sector. The LightColorChange audience is notified whenever
* the light color changes.
*
* @see lightColorComponent(), lightRed(), lightGreen()
*/
inline float lightBlue() const { return lightColorComponent(2); }

/**
* Change the ambient light color in the sector. The LightColorChange
* audience is notified whenever the light color changes.
*
* @param newLightColor New ambient light color.
*
* @see lightColor(), setLightColorComponent(), setLightRed(), setLightGreen(), setLightBlue()
*/
void setLightColor(de::Vector3f const &newLightColor);

/**
* Change the strength of the specified @a component of the ambient light
* color in the sector. The LightColorChange audience is notified whenever
* the light color changes.
*
* @param component RGB index of the color component (0=Red, 1=Green, 2=Blue).
* @param newStrength New strength factor for the color component.
*
* @see setLightColor(), setLightRed(), setLightGreen(), setLightBlue()
*/
inline void setLightColorComponent(int component, float newStrength);

/**
* Change the strength of the red component of the ambient light color in
* the sector. The LightColorChange audience is notified whenever the light
* color changes.
*
* @param newStrength New red strength for the ambient light color.
*
* @see setLightColorComponent(), setLightGreen(), setLightBlue()
*/
inline void setLightRed(float newStrength) { setLightColorComponent(0, newStrength); }

/**
* Change the strength of the green component of the ambient light color in
* the sector. The LightColorChange audience is notified whenever the light
* color changes.
*
* @param newStrength New green strength for the ambient light color.
*
* @see setLightColorComponent(), setLightRed(), setLightBlue()
*/
inline void setLightGreen(float newStrength) { setLightColorComponent(1, newStrength); }

/**
* Change the strength of the blue component of the ambient light color in
* the sector. The LightColorChange audience is notified whenever the light
* color changes.
*
* @param newStrength New blue strength for the ambient light color.
*
* @see setLightColorComponent(), setLightRed(), setLightGreen()
*/
inline void setLightBlue(float newStrength) { setLightColorComponent(2, newStrength); }

/**
* Get a property value, selected by DMU_* name.
*
Expand All @@ -343,6 +458,9 @@ class Sector : public de::MapElement
* @return Always @c 0 (can be used as an iterator).
*/
int setProperty(setargs_t const &args);

private:
DENG2_PRIVATE(d)
};

#endif // LIBDENG_MAP_SECTOR
11 changes: 2 additions & 9 deletions doomsday/client/include/r_util.h
Expand Up @@ -24,14 +24,11 @@
#ifndef LIBDENG_REFRESH_UTIL_H
#define LIBDENG_REFRESH_UTIL_H

#include <de/Vector>
#include <de/vector1.h>
#include "map/bspnode.h"
#include "map/p_mapdata.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* Get a global angle from Cartesian coordinates relative to the viewer.
*
Expand All @@ -58,7 +55,7 @@ void R_ProjectViewRelativeLine2D(coord_t const center[2], boolean alignToViewPla
/**
* Scale @a color uniformly so that the highest component becomes one.
*/
void R_AmplifyColor(float color[3]);
void R_AmplifyColor(de::Vector3f &color);

void R_ScaleAmbientRGB(float* out, const float* in, float mul);

Expand All @@ -82,8 +79,4 @@ boolean R_GenerateTexCoords(pvec2f_t s, pvec2f_t t, const_pvec3d_t point, float

char const *R_NameForBlendMode(blendmode_t mode);

#ifdef __cplusplus
} // extern "C"
#endif

#endif /* LIBDENG_REFRESH_UTIL_H */
6 changes: 3 additions & 3 deletions doomsday/client/src/client/cl_world.cpp
Expand Up @@ -654,11 +654,11 @@ void Cl_ReadSectorDelta2(int deltaType, boolean /*skip*/)
speed[PLN_CEILING] = FIX2FLT(Reader_ReadByte(msgReader) << (df & SDF_CEILING_SPEED_44 ? 12 : 15));

if(df & SDF_COLOR_RED)
sec->_lightColor[0] = Reader_ReadByte(msgReader) / 255.f;
sec->setLightRed(Reader_ReadByte(msgReader) / 255.f);
if(df & SDF_COLOR_GREEN)
sec->_lightColor[1] = Reader_ReadByte(msgReader) / 255.f;
sec->setLightGreen(Reader_ReadByte(msgReader) / 255.f);
if(df & SDF_COLOR_BLUE)
sec->_lightColor[2] = Reader_ReadByte(msgReader) / 255.f;
sec->setLightBlue(Reader_ReadByte(msgReader) / 255.f);

if(df & SDF_FLOOR_COLOR_RED)
sec->floorSurface().setColorRed(Reader_ReadByte(msgReader) / 255.f);
Expand Down
17 changes: 6 additions & 11 deletions doomsday/client/src/edit_map.cpp
Expand Up @@ -119,19 +119,14 @@ class EditableMap
return sideDef;
}

Sector *createSector(Vector3f const &ambientLightColor, float lightLevel)
Sector *createSector(float lightLevel, Vector3f const &lightColor)
{
Sector *sec = new Sector;
Sector *sector = new Sector(lightLevel, lightColor);

sec->_lightColor[CR] = de::clamp(0.f, ambientLightColor.x, 1.f);
sec->_lightColor[CG] = de::clamp(0.f, ambientLightColor.y, 1.f);
sec->_lightColor[CB] = de::clamp(0.f, ambientLightColor.z, 1.f);
sec->_lightLevel = de::clamp(0.f, lightLevel, 1.f);
sectors.append(sector);
sector->_origIndex = sectors.count(); // 1-based index, 0 = NIL.

sectors.append(sec);
sec->_origIndex = sectors.count(); // 1-based index, 0 = NIL.

return sec;
return sector;
}

Polyobj *createPolyobj()
Expand Down Expand Up @@ -1275,7 +1270,7 @@ uint MPE_SectorCreate(float lightlevel, float red, float green, float blue)
{
if(!editMapInited) return 0;

Sector *s = editMap.createSector(Vector3f(red, green, blue), lightlevel);
Sector *s = editMap.createSector(lightlevel, Vector3f(red, green, blue));
return s->origIndex();
}

Expand Down
37 changes: 20 additions & 17 deletions doomsday/client/src/gl/gl_main.cpp
Expand Up @@ -954,21 +954,20 @@ uint8_t* GL_ConvertBuffer(const uint8_t* in, int width, int height, int informat
}
}

void GL_CalcLuminance(const uint8_t* buffer, int width, int height, int pixelSize, colorpalette_t* palette,
float* retBrightX, float* retBrightY, ColorRawf* retColor, float* retLumSize)
void GL_CalcLuminance(uint8_t const *buffer, int width, int height, int pixelSize,
colorpalette_t *palette, float *retBrightX, float *retBrightY,
ColorRawf *retColor, float *retLumSize)
{
const uint8_t sizeLimit = 192, brightLimit = 224, colLimit = 192;
const uint8_t* src, *alphaSrc;
DENG_ASSERT(buffer && retBrightX && retBrightY && retColor && retLumSize);

uint8_t const sizeLimit = 192, brightLimit = 224, colLimit = 192;
uint8_t const *src, *alphaSrc;
int avgCnt = 0, lowCnt = 0;
int cnt = 0, posCnt = 0;
int i, x, y, c;
long average[3], lowAvg[3];
long bright[2];
uint8_t rgb[3];
int region[4];
boolean zeroAreaRegion;

DENG_ASSERT(buffer && retBrightX && retBrightY && retColor && retLumSize);

if(pixelSize == 1 && !palette)
{
Expand All @@ -988,8 +987,9 @@ void GL_CalcLuminance(const uint8_t* buffer, int width, int height, int pixelSiz
// Default to a zero-size light.
*retLumSize = 0;

int region[4];
FindClipRegionNonAlpha(buffer, width, height, pixelSize, region);
zeroAreaRegion = (region[0] > region[1] || region[2] > region[3]);
boolean zeroAreaRegion = (region[0] > region[1] || region[2] > region[3]);
if(zeroAreaRegion) return;

/*
Expand Down Expand Up @@ -1029,7 +1029,7 @@ void GL_CalcLuminance(const uint8_t* buffer, int width, int height, int pixelSiz
for(x = region[0]; x <= region[1]; ++x, src += pixelSize, alphaSrc++)
{
// Alpha pixels don't count. Why? -ds
const boolean pixelIsTransparent = (pixelSize == 1? *alphaSrc < 255 :
boolean const pixelIsTransparent = (pixelSize == 1? *alphaSrc < 255 :
pixelSize == 4? src[3] < 255 : false);

if(pixelIsTransparent) continue;
Expand Down Expand Up @@ -1093,14 +1093,12 @@ void GL_CalcLuminance(const uint8_t* buffer, int width, int height, int pixelSiz
}

// Determine rounding (to the nearest pixel center).
{
int roundXDir = (int) (*retBrightX + .5f) == (int) *retBrightX ? 1 : -1;
int roundYDir = (int) (*retBrightY + .5f) == (int) *retBrightY ? 1 : -1;
int roundXDir = int( *retBrightX + .5f ) == int( *retBrightX )? 1 : -1;
int roundYDir = int( *retBrightY + .5f ) == int( *retBrightY )? 1 : -1;

// Apply all rounding and output as decimal.
*retBrightX = (ROUND(*retBrightX) + .5f * roundXDir) / (float) width;
*retBrightY = (ROUND(*retBrightY) + .5f * roundYDir) / (float) height;
}
*retBrightX = (ROUND(*retBrightX) + .5f * roundXDir) / float( width );
*retBrightY = (ROUND(*retBrightY) + .5f * roundYDir) / float( height );

if(avgCnt || lowCnt)
{
Expand All @@ -1118,7 +1116,12 @@ void GL_CalcLuminance(const uint8_t* buffer, int width, int height, int pixelSiz
retColor->rgb[c] = average[c] / avgCnt / 255.f;
}

R_AmplifyColor(retColor->rgb);
Vector3f color(retColor->rgb);
R_AmplifyColor(color);
for(int i = 0; i < 3; ++i)
{
retColor->rgb[i] = color[i];
}

// How about the size of the light source?
/// @todo These factors should be cvars.
Expand Down

0 comments on commit c7c24f9

Please sign in to comment.