forked from Mirrors/openclonk
implement/fix clipping during rendering of light
parent
96729ef57c
commit
239cd222e5
|
@ -5,6 +5,8 @@
|
|||
#include "C4FoWBeamTriangle.h"
|
||||
#include "C4FoWDrawStrategy.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
C4FoWLight::C4FoWLight(C4Object *pObj)
|
||||
: iX(fixtoi(pObj->fix_x)),
|
||||
iY(fixtoi(pObj->fix_y)),
|
||||
|
@ -13,23 +15,24 @@ C4FoWLight::C4FoWLight(C4Object *pObj)
|
|||
iSize(20),
|
||||
pNext(NULL),
|
||||
pObj(pObj),
|
||||
sectionUp(this, 0),
|
||||
sectionLeft(this, 270),
|
||||
sectionDown(this, 180),
|
||||
sectionRight(this, 90)
|
||||
sections(4)
|
||||
{
|
||||
sections[0] = new C4FoWLightSection(this,0);
|
||||
sections[1] = new C4FoWLightSection(this,90);
|
||||
sections[2] = new C4FoWLightSection(this,180);
|
||||
sections[3] = new C4FoWLightSection(this,270);
|
||||
}
|
||||
|
||||
C4FoWLight::~C4FoWLight()
|
||||
{
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
delete sections[i];
|
||||
}
|
||||
|
||||
void C4FoWLight::Invalidate(C4Rect r)
|
||||
{
|
||||
sectionUp.Invalidate(r);
|
||||
sectionDown.Invalidate(r);
|
||||
sectionLeft.Invalidate(r);
|
||||
sectionRight.Invalidate(r);
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
sections[i]->Invalidate(r);
|
||||
}
|
||||
|
||||
void C4FoWLight::SetReach(int32_t iReach2, int32_t iFadeout2)
|
||||
|
@ -43,52 +46,53 @@ void C4FoWLight::SetReach(int32_t iReach2, int32_t iFadeout2)
|
|||
if (iReach2 < iReach)
|
||||
{
|
||||
iReach = iReach2;
|
||||
sectionUp.Prune(iReach);
|
||||
sectionDown.Prune(iReach);
|
||||
sectionLeft.Prune(iReach);
|
||||
sectionRight.Prune(iReach);
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
sections[i]->Prune(iReach);
|
||||
|
||||
} else {
|
||||
|
||||
// Reach increased? Dirty beams that might get longer now
|
||||
iReach = iReach2;
|
||||
sectionUp.Dirty(iReach);
|
||||
sectionDown.Dirty(iReach);
|
||||
sectionLeft.Dirty(iReach);
|
||||
sectionRight.Dirty(iReach);
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
sections[i]->Dirty(iReach);
|
||||
}
|
||||
}
|
||||
|
||||
void C4FoWLight::Update(C4Rect Rec)
|
||||
{
|
||||
|
||||
// Update position from object. Clear if we moved in any way
|
||||
int32_t iNX = fixtoi(pObj->fix_x), iNY = fixtoi(pObj->fix_y);
|
||||
if (iNX != iX || iNY != iY)
|
||||
{
|
||||
sectionUp.Prune(0);
|
||||
sectionDown.Prune(0);
|
||||
sectionLeft.Prune(0);
|
||||
sectionRight.Prune(0);
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
sections[i]->Prune(0);
|
||||
iX = iNX; iY = iNY;
|
||||
}
|
||||
|
||||
sectionUp.Update(Rec);
|
||||
sectionDown.Update(Rec);
|
||||
sectionLeft.Update(Rec);
|
||||
sectionRight.Update(Rec);
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
sections[i]->Update(Rec);
|
||||
}
|
||||
|
||||
void C4FoWLight::Render(C4FoWRegion *region, const C4TargetFacet *onScreen)
|
||||
{
|
||||
std::list<C4FoWBeamTriangle> triangles;
|
||||
triangles.splice(triangles.end(), sectionUp.CalculateTriangles(region));
|
||||
triangles.splice(triangles.end(), sectionRight.CalculateTriangles(region));
|
||||
triangles.splice(triangles.end(), sectionDown.CalculateTriangles(region));
|
||||
triangles.splice(triangles.end(), sectionLeft.CalculateTriangles(region));
|
||||
|
||||
CalculateIntermediateFadeTriangles(triangles);
|
||||
bool clip = false;
|
||||
|
||||
for( int i = 0; i < sections.size(); ++i )
|
||||
{
|
||||
std::list<C4FoWBeamTriangle> §ionTriangles = sections[i]->CalculateTriangles(region);
|
||||
|
||||
// if the triangles of one section are clipped completely, the neighbouring triangles
|
||||
// must be marked as clipped
|
||||
if(!triangles.empty()) triangles.rbegin()->clipRight |= clip;
|
||||
if(!sectionTriangles.empty()) sectionTriangles.begin()->clipLeft |= clip;
|
||||
|
||||
clip = sectionTriangles.empty();
|
||||
triangles.splice(triangles.end(), sectionTriangles);
|
||||
}
|
||||
CalculateIntermediateFadeTriangles(triangles);
|
||||
|
||||
// Here's the master plan for updating the lights texture. We
|
||||
// want to add intensity (R channel) as well as the normal (GB channels).
|
||||
// Normals are obviously meant to be though of as signed, though,
|
||||
|
@ -184,7 +188,9 @@ void C4FoWLight::DrawFan(C4FoWDrawStrategy* pen, std::list<C4FoWBeamTriangle> &t
|
|||
C4FoWBeamTriangle &tri = *it, &nextTri = *nextIt; // just for convenience
|
||||
|
||||
pen->DrawLightVertex(tri.fanLX, tri.fanLY);
|
||||
pen->DrawLightVertex(tri.fanRX, tri.fanRY);
|
||||
|
||||
if(nextTri.fanLX != tri.fanRX || nextTri.fanLY != tri.fanRY)
|
||||
pen->DrawLightVertex(tri.fanRX, tri.fanRY);
|
||||
}
|
||||
pen->EndFan();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "C4FoWLightSection.h"
|
||||
#include "C4Rect.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/** This class represents one light source. A light source has an associated object with which the light source moves
|
||||
and one light section that handles the light beams for each direction (up, down, left, right).
|
||||
|
||||
|
@ -27,10 +29,7 @@ private:
|
|||
C4FoWLight *pNext;
|
||||
C4Object *pObj; // Associated object
|
||||
|
||||
C4FoWLightSection sectionUp;
|
||||
C4FoWLightSection sectionLeft;
|
||||
C4FoWLightSection sectionDown;
|
||||
C4FoWLightSection sectionRight;
|
||||
std::vector<C4FoWLightSection*> sections;
|
||||
|
||||
public:
|
||||
int32_t getX() const { return iX; }
|
||||
|
|
|
@ -397,7 +397,7 @@ void C4FoWLightSection::Invalidate(C4Rect r)
|
|||
|
||||
}
|
||||
|
||||
int32_t C4FoWLightSection::FindBeamsClipped(const C4Rect &rect, C4FoWBeam *&firstBeam, C4FoWBeam *&lastBeam)
|
||||
int32_t C4FoWLightSection::FindBeamsClipped(const C4Rect &rect, C4FoWBeam *&firstBeam, C4FoWBeam *&endBeam)
|
||||
{
|
||||
if(rect.y + rect.Hgt < 0) return 0;
|
||||
|
||||
|
@ -417,7 +417,7 @@ int32_t C4FoWLightSection::FindBeamsClipped(const C4Rect &rect, C4FoWBeam *&firs
|
|||
beam = beam->getNext();
|
||||
beamCount++;
|
||||
}
|
||||
lastBeam = beam;
|
||||
endBeam = beam;
|
||||
|
||||
return beamCount;
|
||||
}
|
||||
|
@ -426,10 +426,14 @@ std::list<C4FoWBeamTriangle> C4FoWLightSection::CalculateTriangles(C4FoWRegion *
|
|||
{
|
||||
C4FoWBeam *startBeam = NULL, *endBeam = NULL;
|
||||
int32_t beamCount = FindBeamsClipped(rtransRect(region->getRegion()), startBeam, endBeam);
|
||||
// no beams inside the rectangle? Good, nothing to render
|
||||
std::list<C4FoWBeamTriangle> result;
|
||||
|
||||
// no beams inside the rectangle? Good, nothing to render
|
||||
if(!beamCount) return result;
|
||||
|
||||
bool isStartClipped = startBeam != pBeams;
|
||||
bool isEndClipped = !!endBeam;
|
||||
|
||||
C4FoWBeam *beam = startBeam;
|
||||
for (int32_t i = 0; i < beamCount; i++, beam = beam->getNext())
|
||||
{
|
||||
|
@ -438,9 +442,15 @@ std::list<C4FoWBeamTriangle> C4FoWLightSection::CalculateTriangles(C4FoWRegion *
|
|||
tri.fanLY = float(beam->getLeftEndY());
|
||||
tri.fanRX = beam->getRightEndXf();
|
||||
tri.fanRY = float(beam->getRightEndY());
|
||||
tri.clipLeft = false; // TODO Newton: pBeams.start != startBeam
|
||||
tri.clipRight = false; // TODO Newton: pBeams.end != endBeam
|
||||
result.push_back(tri);
|
||||
if(i == 0 && isStartClipped)
|
||||
tri.clipLeft = true;
|
||||
if(i == beamCount - 1 && isEndClipped)
|
||||
{
|
||||
tri.clipRight = true;
|
||||
}
|
||||
|
||||
if(tri.fanLX != tri.fanRX || tri.fanLY != tri.fanRY)
|
||||
result.push_back(tri);
|
||||
}
|
||||
|
||||
// Phase 1: Project lower point so it lies on a line with outer left/right
|
||||
|
|
|
@ -105,8 +105,9 @@ private:
|
|||
C4FoWBeam *FindBeamLeftOf(int32_t x, int32_t y);
|
||||
|
||||
/** Find beams that go through the given rectangle. Returns the number of beams that are in the rectangle and makes
|
||||
pFirst and pLast point to the first and the last beam of these */
|
||||
int32_t FindBeamsClipped(const C4Rect &rect, C4FoWBeam *&firstBeam, C4FoWBeam *&lastBeam);
|
||||
firstBeam point to the first and endBeam point to the beam after the last of these. Thus, endBeam is NULL if
|
||||
no beams were clipped at the end. */
|
||||
int32_t FindBeamsClipped(const C4Rect &rect, C4FoWBeam *&firstBeam, C4FoWBeam *&endBeam);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue