Skip to content

Commit

Permalink
Map Renderer|Client: Continued working on SurfaceDecorator
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Sep 9, 2013
1 parent 571f67d commit 0dd08b5
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 136 deletions.
1 change: 0 additions & 1 deletion doomsday/client/include/de_render.h
Expand Up @@ -39,7 +39,6 @@
#include "render/rend_shadow.h"
#include "render/rend_fakeradio.h"
#include "render/rend_font.h"
#include "render/rend_decor.h"
#include "render/rend_dynlight.h"
#include "render/rendpoly.h"
#include "render/sky.h"
Expand Down
17 changes: 3 additions & 14 deletions doomsday/client/include/render/surfacedecorator.h
Expand Up @@ -20,9 +20,7 @@
#ifndef DENG_CLIENT_RENDER_SURFACEDECORATOR_H
#define DENG_CLIENT_RENDER_SURFACEDECORATOR_H

#include <de/Vector>

#include "MaterialSnapshot" // remove me
#include "Decoration"
#include "Surface"

#define MAX_DECOR_LIGHTS (16384)
Expand All @@ -36,24 +34,15 @@ class SurfaceDecorator
/**
* Construct a new surface decorator.
*/
//SurfaceDecorator();
SurfaceDecorator();

/**
* Decorate @a surface.
*/
void decorate(Surface &surface);

private:
void newDecoration(SurfaceDecorSource &source);

uint generateDecorations(de::MaterialSnapshot::Decoration const &decor,
de::Vector2i const &patternOffset, de::Vector2i const &patternSkip, Surface &suf,
Material &material, de::Vector3d const &topLeft_, de::Vector3d const &/*bottomRight*/,
de::Vector2d sufDimensions, de::Vector3d const &delta, int axis,
de::Vector2f const &matOffset, Sector *containingSector);

void plotSources(Surface &suf, de::Vector2f const &offset,
de::Vector3d const &topLeft, de::Vector3d const &bottomRight, Sector *sec = 0);
DENG2_PRIVATE(d)
};

/// @todo Refactor away --------------------------------------------------------
Expand Down
241 changes: 127 additions & 114 deletions doomsday/client/src/render/surfacedecorator.cpp
@@ -1,4 +1,4 @@
/** @file rend_decor.cpp Surface Decorations.
/** @file surfacedecorator.cpp World surface decorator.
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
Expand All @@ -21,13 +21,16 @@

#include <de/memoryzone.h>

#include <de/Vector>

#include "de_platform.h"

#include "world/map.h"
#include "BspLeaf"

#include "MaterialSnapshot"

#include "render/rend_main.h" // Rend_MapSurfaceMaterialSpec()
#include "Decoration"
#include "WallEdge"

#include "render/surfacedecorator.h"
Expand Down Expand Up @@ -70,7 +73,124 @@ static Decoration *allocDecoration()
}
}

void SurfaceDecorator::decorate(Surface &surface) // static
DENG2_PIMPL(SurfaceDecorator)
{
Instance(Public *i) : Base(i)
{}

void newDecoration(SurfaceDecorSource &source)
{
// Out of sources?
if(decorCount >= MAX_DECOR_LIGHTS) return;

Decoration *decor = allocDecoration();

decor->setSource(&source);

decorCount += 1;
}

uint generateDecorations(MaterialSnapshot::Decoration const &decor,
Vector2i const &patternOffset, Vector2i const &patternSkip, Surface &suf,
Material &material, Vector3d const &topLeft_, Vector3d const &/*bottomRight*/,
Vector2d sufDimensions, Vector3d const &delta, int axis,
Vector2f const &matOffset, Sector *containingSector)
{
// Skip values must be at least one.
Vector2i skip = Vector2i(patternSkip.x + 1, patternSkip.y + 1)
.max(Vector2i(1, 1));

Vector2f repeat = material.dimensions() * skip;
if(repeat == Vector2f(0, 0))
return 0;

Vector3d topLeft = topLeft_ + suf.normal() * decor.elevation;

float s = de::wrap(decor.pos[0] - material.width() * patternOffset.x + matOffset.x,
0.f, repeat.x);

// Plot decorations.
uint plotted = 0;
for(; s < sufDimensions.x; s += repeat.x)
{
// Determine the topmost point for this row.
float t = de::wrap(decor.pos[1] - material.height() * patternOffset.y + matOffset.y,
0.f, repeat.y);

for(; t < sufDimensions.y; t += repeat.y)
{
float const offS = s / sufDimensions.x;
float const offT = t / sufDimensions.y;
Vector3d offset(offS, axis == VZ? offT : offS, axis == VZ? offS : offT);

Vector3d origin = topLeft + delta * offset;
BspLeaf &bspLeaf = suf.map().bspLeafAt(origin);
if(containingSector)
{
// The point must be inside the correct sector.
if(bspLeaf.sectorPtr() != containingSector
|| !bspLeaf.polyContains(origin))
continue;
}

if(SurfaceDecorSource *source = suf.newDecoration())
{
source->origin = origin;
source->bspLeaf = &bspLeaf;
source->matDecor = &decor;

plotted += 1;
}
}
}

return plotted;
}

void plotSources(Surface &suf, Vector2f const &offset, Vector3d const &topLeft,
Vector3d const &bottomRight, Sector *sec = 0)
{
Vector3d delta = bottomRight - topLeft;
if(de::fequal(delta.length(), 0)) return;

int const axis = suf.normal().maxAxis();

Vector2d sufDimensions;
if(axis == 0 || axis == 1)
{
sufDimensions.x = std::sqrt(delta.x * delta.x + delta.y * delta.y);
sufDimensions.y = delta.z;
}
else
{
sufDimensions.x = std::sqrt(delta.x * delta.x);
sufDimensions.y = delta.y;
}

if(sufDimensions.x < 0) sufDimensions.x = -sufDimensions.x;
if(sufDimensions.y < 0) sufDimensions.y = -sufDimensions.y;

// Generate a number of lights.
MaterialSnapshot const &ms = suf.material().prepare(Rend_MapSurfaceMaterialSpec());

Material::Decorations const &decorations = suf.material().decorations();
for(int i = 0; i < decorations.count(); ++i)
{
MaterialSnapshot::Decoration const &decor = ms.decoration(i);
MaterialDecoration const *def = decorations[i];

generateDecorations(decor, def->patternOffset(), def->patternSkip(),
suf, suf.material(), topLeft, bottomRight, sufDimensions,
delta, axis, offset, sec);
}
}

};

SurfaceDecorator::SurfaceDecorator() : d(new Instance(this))
{}

void SurfaceDecorator::decorate(Surface &surface)
{
if(surface._decorationData.needsUpdate)
{
Expand Down Expand Up @@ -99,8 +219,8 @@ void SurfaceDecorator::decorate(Surface &surface) // static
if(leftEdge.isValid() && rightEdge.isValid()
&& !de::fequal(leftEdge.bottom().z(), rightEdge.top().z()))
{
plotSources(side.surface(section), -leftEdge.materialOrigin(),
leftEdge.top().origin(), rightEdge.bottom().origin());
d->plotSources(side.surface(section), -leftEdge.materialOrigin(),
leftEdge.top().origin(), rightEdge.bottom().origin());
}
}
}
Expand All @@ -123,7 +243,7 @@ void SurfaceDecorator::decorate(Surface &surface) // static
Vector2f offset(-fmod(sectorAABox.minX, 64) - surface.visMaterialOrigin().x,
-fmod(sectorAABox.minY, 64) - surface.visMaterialOrigin().y);

plotSources(surface, offset, topLeft, bottomRight, &sector);
d->plotSources(surface, offset, topLeft, bottomRight, &sector);
}
}

Expand All @@ -133,114 +253,7 @@ void SurfaceDecorator::decorate(Surface &surface) // static
Surface::DecorSource *sources = surface._decorationData.sources;
for(int i = 0; i < surface.decorationCount(); ++i)
{
newDecoration(sources[i]);
}
}

void SurfaceDecorator::newDecoration(SurfaceDecorSource &source)
{
// Out of sources?
if(decorCount >= MAX_DECOR_LIGHTS) return;

Decoration *decor = allocDecoration();

decor->setSource(&source);

decorCount += 1;
}

uint SurfaceDecorator::generateDecorations(MaterialSnapshot::Decoration const &decor,
Vector2i const &patternOffset, Vector2i const &patternSkip, Surface &suf,
Material &material, Vector3d const &topLeft_, Vector3d const &/*bottomRight*/,
Vector2d sufDimensions, Vector3d const &delta, int axis,
Vector2f const &matOffset, Sector *containingSector)
{
// Skip values must be at least one.
Vector2i skip = Vector2i(patternSkip.x + 1, patternSkip.y + 1)
.max(Vector2i(1, 1));

Vector2f repeat = material.dimensions() * skip;
if(repeat == Vector2f(0, 0))
return 0;

Vector3d topLeft = topLeft_ + suf.normal() * decor.elevation;

float s = de::wrap(decor.pos[0] - material.width() * patternOffset.x + matOffset.x,
0.f, repeat.x);

// Plot decorations.
uint plotted = 0;
for(; s < sufDimensions.x; s += repeat.x)
{
// Determine the topmost point for this row.
float t = de::wrap(decor.pos[1] - material.height() * patternOffset.y + matOffset.y,
0.f, repeat.y);

for(; t < sufDimensions.y; t += repeat.y)
{
float const offS = s / sufDimensions.x;
float const offT = t / sufDimensions.y;
Vector3d offset(offS, axis == VZ? offT : offS, axis == VZ? offS : offT);

Vector3d origin = topLeft + delta * offset;
BspLeaf &bspLeaf = suf.map().bspLeafAt(origin);
if(containingSector)
{
// The point must be inside the correct sector.
if(bspLeaf.sectorPtr() != containingSector
|| !bspLeaf.polyContains(origin))
continue;
}

if(SurfaceDecorSource *source = suf.newDecoration())
{
source->origin = origin;
source->bspLeaf = &bspLeaf;
source->matDecor = &decor;

plotted += 1;
}
}
}

return plotted;
}

void SurfaceDecorator::plotSources(Surface &suf, Vector2f const &offset,
Vector3d const &topLeft, Vector3d const &bottomRight, Sector *sec)
{
Vector3d delta = bottomRight - topLeft;
if(de::fequal(delta.length(), 0)) return;

int const axis = suf.normal().maxAxis();

Vector2d sufDimensions;
if(axis == 0 || axis == 1)
{
sufDimensions.x = std::sqrt(delta.x * delta.x + delta.y * delta.y);
sufDimensions.y = delta.z;
}
else
{
sufDimensions.x = std::sqrt(delta.x * delta.x);
sufDimensions.y = delta.y;
}

if(sufDimensions.x < 0) sufDimensions.x = -sufDimensions.x;
if(sufDimensions.y < 0) sufDimensions.y = -sufDimensions.y;

// Generate a number of lights.
MaterialSnapshot const &ms = suf.material().prepare(Rend_MapSurfaceMaterialSpec());

Material::Decorations const &decorations = suf.material().decorations();
for(int i = 0; i < decorations.count(); ++i)
{
MaterialSnapshot::Decoration const &decor = ms.decoration(i);
MaterialDecoration const *def = decorations[i];

generateDecorations(decor, def->patternOffset(), def->patternSkip(),
suf, suf.material(), topLeft, bottomRight, sufDimensions,
delta, axis, offset, sec);
d->newDecoration(sources[i]);
}
}

Expand Down
17 changes: 10 additions & 7 deletions doomsday/client/src/world/map.cpp
Expand Up @@ -1032,6 +1032,15 @@ DENG2_OBSERVES(bsp::Partitioner, UnclosedSectorFound)
}

#ifdef __CLIENT__
SurfaceDecorator &surfaceDecorator()
{
if(decorator.isNull())
{
Rend_DecorReset();
decorator.reset(new SurfaceDecorator);
}
return *decorator;
}

/**
* $smoothplane: interpolate the visual offset of planes.
Expand Down Expand Up @@ -2947,13 +2956,7 @@ void Map::worldFrameBegins(World &world, bool resetNextViewer)
{
foreach(Surface *surface, d->decoratedSurfaces)
{
if(d->decorator.isNull())
{
Rend_DecorReset();
d->decorator.reset(new SurfaceDecorator);
}

d->decorator->decorate(*surface);
d->surfaceDecorator().decorate(*surface);
}
}

Expand Down

0 comments on commit 0dd08b5

Please sign in to comment.