Welcome, guest! Login / Register - Why register?
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

Your Name: Code Language: