Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactor|Map Renderer: Reworked WallDivs into a C++ class
  • Loading branch information
danij-deng committed May 1, 2013
1 parent c6394e4 commit d578c42
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 252 deletions.
4 changes: 2 additions & 2 deletions doomsday/client/include/render/rend_dynlight.h
Expand Up @@ -35,11 +35,11 @@ typedef struct {
bool isWall;
struct {
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} left;
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} right;
} wall;
Expand Down
4 changes: 2 additions & 2 deletions doomsday/client/include/render/rend_fakeradio.h
Expand Up @@ -161,11 +161,11 @@ struct RendRadioWallSectionParms
Sector const *frontSec, *backSec;
struct {
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} left;
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} right;
} wall;
Expand Down
4 changes: 2 additions & 2 deletions doomsday/client/include/render/rend_shadow.h
Expand Up @@ -52,11 +52,11 @@ typedef struct {
bool isWall;
struct {
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} left;
struct {
walldivnode_t *firstDiv;
de::WallDivs::Intercept *firstDiv;
uint divCount;
} right;
} wall;
Expand Down
18 changes: 7 additions & 11 deletions doomsday/client/include/render/rendpoly.h
Expand Up @@ -29,7 +29,7 @@

#include <de/Vector>

struct walldivnode_s;
#include "render/walldiv.h"

typedef struct rvertex_s {
float pos[3];
Expand Down Expand Up @@ -110,8 +110,6 @@ typedef struct rtexmapuint_s {
#endif
} rtexmapunit_t;

#ifdef __CLIENT__

extern byte rendInfoRPolys;

void R_PrintRendPoolInfo(void);
Expand Down Expand Up @@ -213,19 +211,17 @@ inline void Rtu_TranslateOffset(rtexmapunit_t *rtu, float s, float t)
}

void R_DivVerts(rvertex_t *dst, rvertex_t const *src,
struct walldivnode_s *leftDivFirst, uint leftDivCount,
struct walldivnode_s *rightDivFirst, uint rightDivCount);
de::WallDivs::Intercept *leftDivFirst, uint leftDivCount,
de::WallDivs::Intercept *rightDivFirst, uint rightDivCount);

void R_DivTexCoords(rtexcoord_t *dst, rtexcoord_t const *src,
struct walldivnode_s *leftDivFirst, uint leftDivCount,
struct walldivnode_s *rightDivFirst, uint rightDivCount,
de::WallDivs::Intercept *leftDivFirst, uint leftDivCount,
de::WallDivs::Intercept *rightDivFirst, uint rightDivCount,
float bL, float tL, float bR, float tR);

void R_DivVertColors(ColorRawf *dst, ColorRawf const *src,
struct walldivnode_s *leftDivFirst, uint leftDivCount,
struct walldivnode_s *rightDivFirst, uint rightDivCount,
de::WallDivs::Intercept *leftDivFirst, uint leftDivCount,
de::WallDivs::Intercept *rightDivFirst, uint rightDivCount,
float bL, float tL, float bR, float tR);

#endif // __CLIENT__

#endif // DENG_RENDER_RENDPOLY_H
195 changes: 165 additions & 30 deletions doomsday/client/include/render/walldiv.h
Expand Up @@ -21,50 +21,185 @@
#ifndef DENG_RENDER_WALLDIV_H
#define DENG_RENDER_WALLDIV_H

#include "dd_types.h"
#include <de/Error>

struct walldivs_s;
/// Maximum number of walldivnode_ts in a walldivs_t dataset.
#define WALLDIVS_MAX_INTERCEPTS 64

typedef struct walldivnode_s {
struct walldivs_s *divs;
coord_t height;
} walldivnode_t;
namespace de {

coord_t WallDivNode_Height(walldivnode_t *node);
walldivnode_t *WallDivNode_Next(walldivnode_t *node);
walldivnode_t *WallDivNode_Prev(walldivnode_t *node);
class WallDivs
{
public:
/// Required intercept is missing. @ingroup errors
DENG2_ERROR(MissingInterceptError);

/// Maximum number of walldivnode_ts in a walldivs_t dataset.
#define WALLDIVS_MAX_NODES 64
class Intercept
{
protected:
Intercept() : _wallDivs(0), _distance(0) {}

public:
ddouble operator - (Intercept const &other) const
{
return distance() - other.distance();
}

bool operator < (Intercept const &other) const
{
return distance() < other.distance();
}

ddouble distance() const { return _distance; }

bool hasNext() const
{
int idx = this - _wallDivs->_intercepts;
return (idx + 1 < _wallDivs->_interceptCount);
}

bool hasPrev() const
{
int idx = this - _wallDivs->_intercepts;
return (idx > 0);
}

Intercept &next() const
{
int idx = this - _wallDivs->_intercepts;
if(idx + 1 < _wallDivs->_interceptCount)
{
return _wallDivs->_intercepts[idx+1];
}
throw WallDivs::MissingInterceptError("WallDivs::Intercept", "No next neighbor");
}

Intercept &prev() const
{
int idx = this - _wallDivs->_intercepts;
if(idx > 0)
{
return _wallDivs->_intercepts[idx-1];
}
throw WallDivs::MissingInterceptError("WallDivs::Intercept", "No previous neighbor");
}

friend class WallDivs;

private:
WallDivs *_wallDivs;
ddouble _distance;
};

typedef struct walldivs_s {
uint num;
struct walldivnode_s nodes[WALLDIVS_MAX_NODES];
typedef Intercept Intercepts[WALLDIVS_MAX_INTERCEPTS];

walldivs_s() : num(0)
public:
WallDivs() : _interceptCount(0)
{
std::memset(nodes, 0, sizeof(nodes));
std::memset(_intercepts, 0, sizeof(_intercepts));
}

} walldivs_t;
int count() const { return _interceptCount; }

uint WallDivs_Size(walldivs_t const *wallDivs);
walldivnode_t *WallDivs_First(walldivs_t *wallDivs);
walldivnode_t *WallDivs_Last(walldivs_t *wallDivs);
walldivs_t *WallDivs_Append(walldivs_t *wallDivs, coord_t height);
inline bool isEmpty() const { return count() == 0; }

/**
* Ensure the divisions are sorted (in ascending Z order).
*/
void WallDivs_AssertSorted(walldivs_t *wallDivs);
Intercept &first() const
{
if(_interceptCount > 0)
{
return const_cast<Intercept &>(_intercepts[0]);
}
throw MissingInterceptError("WallDivs::first", "Intercepts list is empty");
}

/**
* Ensure the divisions do not exceed the specified range.
*/
void WallDivs_AssertInRange(walldivs_t *wallDivs, coord_t low, coord_t hi);
Intercept &last() const
{
if(_interceptCount > 0)
{
return const_cast<Intercept &>(_intercepts[_interceptCount-1]);
}
throw MissingInterceptError("WallDivs::last", "Intercepts list is empty");
}

void append(ddouble distance)
{
Intercept *node = &_intercepts[_interceptCount++];
node->_wallDivs = this;
node->_distance = distance;
}

Intercept *find(ddouble distance) const
{
for(int i = 0; i < _interceptCount; ++i)
{
Intercept *icpt = const_cast<Intercept *>(&_intercepts[i]);
if(icpt->distance() == distance)
return icpt;
}
return 0;
}

static int compareIntercepts(void const *e1, void const *e2)
{
ddouble const delta = (*reinterpret_cast<Intercept const *>(e1)) - (*reinterpret_cast<Intercept const *>(e2));
if(delta > 0) return 1;
if(delta < 0) return -1;
return 0;
}

void sort()
{
if(count() < 2) return;

// Sorting is required. This shouldn't take too long...
// There seldom are more than two or three intercepts.
qsort(_intercepts, _interceptCount, sizeof(*_intercepts), compareIntercepts);
assertSorted();
}

#ifdef DENG_DEBUG
void debugPrint() const
{
LOG_DEBUG("WallDivs [%p]:") << de::dintptr(this);
for(int i = 0; i < _interceptCount; ++i)
{
Intercept const *node = &_intercepts[i];
LOG_DEBUG(" %i: %f") << i << node->distance();
}
}
#endif

Intercepts const &intercepts() const
{
return _intercepts;
}

private:
/**
* Ensure the intercepts are sorted (in ascending distance order).
*/
void assertSorted() const
{
#ifdef DENG_DEBUG
void WallDivs_DebugPrint(walldivs_t *wallDivs);
if(isEmpty()) return;

WallDivs::Intercept *node = &first();
ddouble farthest = node->distance();
forever
{
DENG2_ASSERT(node->distance() >= farthest);
farthest = node->distance();

if(!node->hasNext()) break;
node = &node->next();
}
#endif
}

int _interceptCount;
Intercepts _intercepts;
};

} // namespace de

#endif // DENG_RENDER_WALLDIV_H

0 comments on commit d578c42

Please sign in to comment.