Files
FC1/Cry3DEngine/StencilShadowEdgeDetector.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

199 lines
7.4 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// CryEngine Source code
//
// File:StencilShadowEdgeDetector.h
// Declaration of class CStencilShadowEdgeDetector
//
// History:
// -:Created by Sergiy Migdalskiy <sergiy@crytek.de>
//
//////////////////////////////////////////////////////////////////////
// class CStencilShadowEdgeDetector
// AUTHOR: Sergiy Migdalskiy <sergiy@crytek.de>
//
// This is run-time (temporary, non-persistent) class that's used to construct
// the optimized shadow volume (optimized means only with the necessary boundary
// edges) for a concrete deformed model/character instance
//
// It ACCEPTS a Connectivity instance that must be pre-computed on per-model
// basis, and an array of deformed vertices.
// It OUTPUTS (constructs, prepares) a set of edges in the form prepared for
// fast construction of efficient shadow volume render data (vertex buffer)
//
#pragma once
#ifndef _STENCIL_SHADOW_EDGE_DETECTOR_HDR_
#define _STENCIL_SHADOW_EDGE_DETECTOR_HDR_
#include "StencilShadowConnectivity.h" // CStencilShadowConnectivity
#include "IEdgeConnectivityBuilder.h" // IEdgeDetector
#include "Cry3DEngineBase.h"
class CStencilShadowEdgeDetector : public IEdgeDetector, public Cry3DEngineBase
{
public:
//! default constructor
CStencilShadowEdgeDetector();
//! destructor
~CStencilShadowEdgeDetector(void);
// Re-construct the whole object
// Use this object to reuse the EdgeDetector object multiple times for different
// connectivities and vertices. This can save on reallocating internal arrays this object uses at run time
// /param pConnectivity, must not be 0 - don't use if there is nothing to do
// /param pDeformedVertices, must not be 0 - don't use if there is nothing to do
void reinit ( const IStencilShadowConnectivity* pConnectivity, const Vec3d* pDeformedVertices );
//! /param pConnectivity must not be 0
//! /param invLightPos in ???-space (World or Object)
//! /param pDeformedVertices must not be 0
virtual void BuildSilhuetteFromPos( const IStencilShadowConnectivity* pConnectivity, const Vec3d &invLightPos, const Vec3d* pDeformedVertices );
//! /param iniNumTriangles the size it should have, must not be 0 - don't use if there is nothing to do
//! /return pointer to the cleared (set to zero) bitfield where each bit represents the orientation of one triangle
virtual unsigned *getOrientationBitfield( int iniNumTriangles );
//!
//! /param pConnectivity must not be 0 - don't use if there is nothing to do
//! /param inpVertices must not be 0 - don't use if there is nothing to do
virtual void BuildSilhuetteFromBitfield( const IStencilShadowConnectivity* pConnectivity, const Vec3d* inpVertices );
//! returns a pointer to the the given shadow edges (array of 2 integers, defining the vertex indices)
//! /param
//! /return
virtual const vindex *getShadowEdgeArray( unsigned &outiNumEdges ) const;
//! number of vertices used to define the detected shadow edges
//! (at least nSE+1, at most nSE*2, where nSE is the number of shadow edges)
//! This may be less than total number of vertices since the edges may use less
//! vertices than faces
//! /return
_inline unsigned numShadowEdgeVertices() const
{
return m_numShadowEdgeVertices;
}
// number of vertices required to define the shadow volume,
// use this to determine the size of vertex buffer passed to meshShadowVolume (2*used vertices because of capping)
virtual unsigned numShadowVolumeVertices( void ) const
{
assert(m_pConnectivity);
return(m_pConnectivity->numVertices()*2);
}
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4267 )
#endif
// pointer to the triplets defining shadow faces
virtual const vindex* getShadowFaceIndices( unsigned &outCount ) const
{
outCount=m_arrShadowFaces.size();
return &m_arrShadowFaces[0];
}
// number of indices required to define the shadow volume,
// use this to determine the size of index buffer passed to meshShadowVolume
// this is always a dividend of 3
virtual unsigned numShadowVolumeIndices()const
{
// each shadow edge requires 6 indices to define the shadow volume:
// it defines one quad => 2 triangles => 6 vertex references
unsigned numShadowEdges=m_arrShadowEdges.size()/2;
unsigned numShadowFaceIndices =m_arrShadowFaces.size();
return(numShadowEdges*6 + numShadowFaceIndices*2);
}
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
//! fills in the internal array of edges and vertices with appropriate data
//! call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
//! - detected shadow edges for the given light source and model
void detectShadowEdges();
//! fills in the internal array of faces and vertices
//! - detected shadow faces for the given light source and model
void detectShadowFaces ();
//! calculates all face orientations into the bit array
//! /param invLight position of the light source in ???-space (World or Object)
void computeFaceOrientations (Vec3d invLight);
// make up the shadow volume
// constructs the shadow volume mesh, and puts the mesh definition into the
// vertex buffer (vertices that define the mesh) and index buffer (triple
// integers defining the triangular faces, counterclockwise order)
// The size of the vertex buffer must be at least numVertices()
// The size of the index buffer must be at least numIndices()
virtual void meshShadowVolume (Vec3d vLight, float fFactor, Vec3d* outpVertexBuf, unsigned short* pIndexBuf );
protected:
const CStencilShadowConnectivity* m_pConnectivity; //!<
const Vec3d* m_pModelVertices; //!<
// number of vertices used to define edges
unsigned m_numShadowEdgeVertices;
// array of shadow edges, referring to the vertices in m_vVertices
// Now, edges are defined by pairs of integers. This may change in the future
std::vector <vindex> m_arrShadowEdges;
// array of shadow faces, referring to the vertices in m_vVertices
std::vector <vindex> m_arrShadowFaces;
// returns true if the given face faces the light, and false otherwise
bool IsFaceTurnedToLight( unsigned nFace, const Vec3d& vLight );
// adds the given shadow edge to the list of boundary edges
//! /param nVertex0 0..
//! /param nVertex1 0..
void AddEdge (vindex nVertex0, vindex nVertex1);
// adds the given shadow face, in the order that is passed
//! /param nVertex0 0..
//! /param nVertex1 0..
//! /param nVertex2 0..
void AddFace (vindex nVertex0, vindex nVertex1, vindex nVertex2);
// checks whether the given edge is boundary or reverse boundary
enum EdgeTypeEnum {
nET_Boundary, // normal boundary edge
nET_ReverseBoundary, // internal boundary edge, needs reversing before insertion into the edge list
nET_Exterior, // visible to the light surface interior edge
nET_Interior // invisible to the light surface interior edge
};
//! checks the edge type by the face indices: assumes that the face orientation bits have been calculated already
//! /param nFace0
//! /param nFace1
EdgeTypeEnum CheckEdgeType (unsigned nFace0, unsigned nFace1);
//! /param nFace0
EdgeTypeEnum CheckOrphanEdgeType (unsigned nFace0);
// face orientation bit array: for each face, there's a bit, which is 1 if it's facing the light and 0 otherwise
TFixedArray<unsigned> m_arrFaceOrientations;
bool m_bBitFieldIsSet; //! for debugging purpose
};
#endif