Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)
Paste
Pasted as C++ by redwall ( 16 years ago )
#pragma once
#include "Vector2.h"
#include "stdarg.h"
#include "CLightSource.h"
class CConvexHull : public IShadowCaster
{
protected:
static const char MaxHullVertices = 8;
char fverticesCount; // количество вершин
Vector2 fvertices[MaxHullVertices]; // массив вершин
Vector2 fcenter;
hgeTriple Triple;
hgeQuad ShadowQuad;
bool EdgeIsEnlightened(ILightSource* L, int index)
{
Vector2 VertexStart = Vertex(index); // текущая точка
Vector2 VertexEnd = Vertex(index+1); // следующая
Vector2 EdgeVector = Center()-L->Position; // вектор от исчтоника к центру грани
EdgeVector.Normalize(); // делит координаты на длину
Vector2 LightVector = (VertexStart+VertexEnd)/2.0f-(L->Position+EdgeVector*L->physicalRadius);
Vector2 EdgeNormal = Vector2(VertexStart.y-VertexEnd.y,VertexEnd.x-VertexStart.x);
return (LightVector.dot(EdgeNormal)<0.0f);
}
public:
CConvexHull(char verticesCount, ...)
{
va_list marker;
va_start(marker,verticesCount);
fcenter.x = 0.0f;
fcenter.y = 0.0f;
verticesCount = verticesCount%MaxHullVertices;
fverticesCount = verticesCount;
for (int i = 0; i<verticesCount; i++)
{
float x = (float)va_arg(marker,double);
float y = (float)va_arg(marker,double);
fvertices[i] = Vector2(x,y);
fcenter.x+=fvertices[i].x;
fcenter.y+=fvertices[i].y;
}
va_end(marker);
fcenter.x /=verticesCount;
fcenter.y /=verticesCount;
}
Vector2 Vertex(int index)
{
return fvertices[index%fverticesCount];
}
virtual void RenderToZBuffer()
{
Render(true);
}
void Render(bool RenderOnlyZBuffer = false)
{
Triple.tex = 0;
if (RenderOnlyZBuffer) Triple.blend = BLEND_DEFAULT_Z;
else Triple.blend = BLEND_DEFAULT;
if (RenderOnlyZBuffer)
{
Triple.v[0].col = 0xFF000000;
Triple.v[1].col = 0xFF000000;
Triple.v[2].col = 0xFF000000;
}
else
{
Triple.v[0].col = 0xFFFF0000;
Triple.v[1].col = 0xFF800000;
Triple.v[2].col = 0xFF800000;
}
Triple.v[0].z = Triple.v[1].z = Triple.v[2].z = 0.0f;
Triple.v[0].x = fcenter.x;
Triple.v[0].y = fcenter.y;
for (int i = 0; i<fverticesCount; i++)
{
Triple.v[1].x = fvertices[i].x;
Triple.v[1].y = fvertices[i].y;
Triple.v[2].x = fvertices[(i+1)%fverticesCount].x;
Triple.v[2].y = fvertices[(i+1)%fverticesCount].y;
hge->Gfx_RenderTriple(&Triple;);
}
}
void Translate(Vector2 direction)
{
fcenter+=direction;
for (int i = 0; i<fverticesCount; i++) fvertices[i]+=direction;
}
char VerticesCount() { return fverticesCount; }
Vector2 Center() { return fcenter; }
virtual void CastShadows(ILightSource* Light)
{
bool FoundShadowStartIndex = false;
bool FoundShadowEndIndex = false;
int ShadowStartIndex = 0;
int ShadowEndIndex = 0;
float ShadowLength = Light->lightRadius+500.0f;
for (int i = 0; i < fverticesCount; i++)
{
if (EdgeIsEnlightened(Light,i)&&!EdgeIsEnlightened(Light,i+1))
{
ShadowStartIndex = i+1;
FoundShadowStartIndex = true;
}
if (!EdgeIsEnlightened(Light,i)&&EdgeIsEnlightened;(Light,i+1))
{
ShadowEndIndex = i+1;
FoundShadowEndIndex = true;
}
}
if (FoundShadowEndIndex && FoundShadowStartIndex)
{
if (ShadowEndIndex<ShadowStartIndex) ShadowEndIndex+=fverticesCount;
Vector2 PenumbraVertex1 = Vertex(ShadowStartIndex);
Vector2 LightVector1 = PenumbraVertex1-Light->Position;
Vector2 LightVector1Normal = Vector2(-LightVector1.y,LightVector1.x);
LightVector1Normal.Normalize();
Vector2 OuterPenumbraVector1 = LightVector1+LightVector1Normal*Light->physicalRadius;
Vector2 InnerPenumbraVector1 = Vertex(ShadowStartIndex)-Light->Position;
OuterPenumbraVector1.Normalize();
InnerPenumbraVector1.Normalize();
Vector2 PenumbraVertex2 = Vertex(ShadowEndIndex);
Vector2 LightVector2 = PenumbraVertex2-Light->Position;
Vector2 LightVector2Normal = Vector2(-LightVector2.y,LightVector2.x);
LightVector2Normal.Normalize();
Vector2 OuterPenumbraVector2 = LightVector2-LightVector2Normal*Light->physicalRadius;
Vector2 InnerPenumbraVector2 = Vertex(ShadowEndIndex)-Light->Position;
OuterPenumbraVector2.Normalize();
InnerPenumbraVector2.Normalize();
for (i = ShadowStartIndex; i<ShadowEndIndex; i++)
{
Vector2 ShadowVector1 = Vertex(i)-Light->Position;
ShadowVector1.Normalize(); ShadowVector1*=ShadowLength;
Vector2 ShadowVector2 = Vertex(i+1)-Light->Position;
ShadowVector2.Normalize(); ShadowVector2*=ShadowLength;
ShadowQuad.v[0].x = Vertex(i).x;
ShadowQuad.v[0].y = Vertex(i).y;
if (i==ShadowStartIndex)
{
ShadowQuad.v[1].x = Vertex(i).x+InnerPenumbraVector1.x*ShadowLength;
ShadowQuad.v[1].y = Vertex(i).y+InnerPenumbraVector1.y*ShadowLength;
}
else
{
ShadowQuad.v[1].x = Vertex(i).x+ShadowVector1.x;
ShadowQuad.v[1].y = Vertex(i).y+ShadowVector1.y;
}
if (i-1==ShadowEndIndex)
{
ShadowQuad.v[2].x = Vertex(i+1).x+InnerPenumbraVector2.x*ShadowLength;
ShadowQuad.v[2].y = Vertex(i+1).y+InnerPenumbraVector2.x*ShadowLength;
}
else
{
ShadowQuad.v[2].x = Vertex(i+1).x+ShadowVector2.x;
ShadowQuad.v[2].y = Vertex(i+1).y+ShadowVector2.y;
}
ShadowQuad.v[3].x = Vertex(i+1).x;
ShadowQuad.v[3].y = Vertex(i+1).y;
ShadowQuad.v[0].col = 0x01000000;
ShadowQuad.v[1].col = 0x01000000;
ShadowQuad.v[2].col = 0x01000000;
ShadowQuad.v[3].col = 0x01000000;
ShadowQuad.v[0].z = Light->z;
ShadowQuad.v[1].z = Light->z;
ShadowQuad.v[2].z = Light->z;
ShadowQuad.v[3].z = Light->z;
ShadowQuad.blend = BLEND_ONLYALPHA;
ShadowQuad.tex = 0;
hge->Gfx_RenderQuad(&ShadowQuad;);
}
Triple.v[0].x = PenumbraVertex1.x+InnerPenumbraVector1.x*ShadowLength;
Triple.v[0].y = PenumbraVertex1.y+InnerPenumbraVector1.y*ShadowLength;
Triple.v[1].x = PenumbraVertex1.x+OuterPenumbraVector1.x*ShadowLength;
Triple.v[1].y = PenumbraVertex1.y+OuterPenumbraVector1.y*ShadowLength;
Triple.v[2].x = PenumbraVertex1.x;
Triple.v[2].y = PenumbraVertex1.y;
Triple.v[0].z = Light->z;
Triple.v[1].z = Light->z;
Triple.v[2].z = Light->z;
Triple.v[0].col = 0xFF000000;
Triple.v[1].col = 0xFF000000;
Triple.v[2].col = 0xFF000000;
Triple.tex = PenumbraTexture;
Triple.v[0].tx = 1.0f;
Triple.v[0].ty = 0.0f;
Triple.v[1].tx = 0.0f;
Triple.v[1].ty = 0.0f;
Triple.v[2].tx = 0.0f;
Triple.v[2].ty = 1.0f;
Triple.blend = BLEND_ONLYALPHA_SUB;
hge->Gfx_RenderTriple(&Triple;);
Triple.v[0].x = PenumbraVertex2.x+InnerPenumbraVector2.x*ShadowLength;
Triple.v[0].y = PenumbraVertex2.y+InnerPenumbraVector2.y*ShadowLength;
Triple.v[1].x = PenumbraVertex2.x+OuterPenumbraVector2.x*ShadowLength;
Triple.v[1].y = PenumbraVertex2.y+OuterPenumbraVector2.y*ShadowLength;
Triple.v[2].x = PenumbraVertex2.x;
Triple.v[2].y = PenumbraVertex2.y;
hge->Gfx_RenderTriple(&Triple;);
}
}
};
Revise this Paste