12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310 |
- /******************************************************************************
- @File PVRTShadowVol.cpp
- @Title PVRTShadowVol
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform ANSI compatible
- @Description Declarations of functions relating to shadow volume generation.
- ******************************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #include "PVRTGlobal.h"
- #include "PVRTContext.h"
- #include "PVRTFixedPoint.h"
- #include "PVRTMatrix.h"
- #include "PVRTTrans.h"
- #include "PVRTShadowVol.h"
- #include "PVRTError.h"
- /****************************************************************************
- ** Build options
- ****************************************************************************/
- /****************************************************************************
- ** Defines
- ****************************************************************************/
- /****************************************************************************
- ** Macros
- ****************************************************************************/
- /****************************************************************************
- ** Structures
- ****************************************************************************/
- struct SVertexShVol {
- float x, y, z;
- unsigned int dwExtrude;
- #if defined(BUILD_OGLES)
- float fWeight;
- #endif
- };
- /****************************************************************************
- ** Constants
- ****************************************************************************/
- const static unsigned short c_pwLinesHyperCube[64] = {
- // Cube0
- 0, 1, 2, 3, 0, 2, 1, 3,
- 4, 5, 6, 7, 4, 6, 5, 7,
- 0, 4, 1, 5, 2, 6, 3, 7,
- // Cube1
- 8, 9, 10, 11, 8, 10, 9, 11,
- 12, 13, 14, 15, 12, 14, 13, 15,
- 8, 12, 9, 13, 10, 14, 11, 15,
- // Hyper cube jn
- 0, 8, 1, 9, 2, 10, 3, 11,
- 4, 12, 5, 13, 6, 14, 7, 15
- };
- const static PVRTVECTOR3 c_pvRect[4] = {
- { -1, -1, 1 },
- { -1, 1, 1 },
- { 1, -1, 1 },
- { 1, 1, 1 }
- };
- /****************************************************************************
- ** Shared globals
- ****************************************************************************/
- /****************************************************************************
- ** Globals
- ****************************************************************************/
- /****************************************************************************
- ** Declarations
- ****************************************************************************/
- /****************************************************************************
- ** Code
- ****************************************************************************/
- /****************************************************************************
- @Function FindOrCreateVertex
- @Modified psMesh The mesh to check against/add to
- @Input pV The vertex to compare/add
- @Return unsigned short The array index of the vertex
- @Description Searches through the mesh data to see if the vertex has
- already been used. If it has, the array index of the vertex
- is returned. If the mesh does not already use the vertex,
- it is appended to the vertex array and the array count is incremented.
- The index in the array of the new vertex is then returned.
- ****************************************************************************/
- static unsigned short FindOrCreateVertex(PVRTShadowVolShadowMesh * const psMesh, const PVRTVECTOR3 * const pV) {
- unsigned short wCurr;
- /*
- First check whether we already have a vertex here
- */
- for(wCurr = 0; wCurr < psMesh->nV; wCurr++) {
- if(memcmp(&psMesh->pV[wCurr], pV, sizeof(*pV)) == 0) {
- /* Don't do anything more if the vertex already exists */
- return wCurr;
- }
- }
- /*
- Add the vertex then!
- */
- psMesh->pV[psMesh->nV] = *pV;
- return (unsigned short) psMesh->nV++;
- }
- /****************************************************************************
- @Function FindOrCreateEdge
- @Modified psMesh The mesh to check against/add to
- @Input pv0 The first point that defines the edge
- @Input pv1 The second point that defines the edge
- @Return PVRTShadowVolMEdge The index of the found/created edge in the
- mesh's array
- @Description Searches through the mesh data to see if the edge has
- already been used. If it has, the array index of the edge
- is returned. If the mesh does not already use the edge,
- it is appended to the edge array and the array cound is incremented.
- The index in the array of the new edge is then returned.
- ****************************************************************************/
- static PVRTShadowVolMEdge *FindOrCreateEdge(PVRTShadowVolShadowMesh * const psMesh, const PVRTVECTOR3 * const pv0, const PVRTVECTOR3 * const pv1) {
- unsigned int nCurr;
- unsigned short wV0, wV1;
- wV0 = FindOrCreateVertex(psMesh, pv0);
- wV1 = FindOrCreateVertex(psMesh, pv1);
- /*
- First check whether we already have a edge here
- */
- for(nCurr = 0; nCurr < psMesh->nE; nCurr++) {
- if(
- (psMesh->pE[nCurr].wV0 == wV0 && psMesh->pE[nCurr].wV1 == wV1) ||
- (psMesh->pE[nCurr].wV0 == wV1 && psMesh->pE[nCurr].wV1 == wV0))
- {
- /* Don't do anything more if the edge already exists */
- return &psMesh->pE[nCurr];
- }
- }
- /*
- Add the edge then!
- */
- psMesh->pE[psMesh->nE].wV0 = wV0;
- psMesh->pE[psMesh->nE].wV1 = wV1;
- psMesh->pE[psMesh->nE].nVis = 0;
- return &psMesh->pE[psMesh->nE++];
- }
- /****************************************************************************
- @Function CrossProduct
- @Output pvOut The resultant vector
- @Input pv0 Vector zero
- @Input pv1 Vector one
- @Input pv2 Vector two
- @Description Finds the vector between vector zero and vector one,
- and the vector between vector zero and vector two.
- These two resultant vectors are then multiplied together
- and the result is assigned to the output vector.
- ****************************************************************************/
- static void CrossProduct(
- PVRTVECTOR3 * const pvOut,
- const PVRTVECTOR3 * const pv0,
- const PVRTVECTOR3 * const pv1,
- const PVRTVECTOR3 * const pv2)
- {
- PVRTVECTOR3 v0, v1;
- v0.x = pv1->x - pv0->x;
- v0.y = pv1->y - pv0->y;
- v0.z = pv1->z - pv0->z;
- v1.x = pv2->x - pv0->x;
- v1.y = pv2->y - pv0->y;
- v1.z = pv2->z - pv0->z;
- PVRTMatrixVec3CrossProduct(*pvOut, v0, v1);
- }
- /****************************************************************************
- @Function FindOrCreateTriangle
- @Modified psMesh The mesh to check against/add to
- @Input pv0 Vertex zero
- @Input pv1 Vertex one
- @Input pv2 Vertex two
- @Description Searches through the mesh data to see if the triangle has
- already been used. If it has, the function returns.
- If the mesh does not already use the triangle,
- it is appended to the triangle array and the array cound is incremented.
- ****************************************************************************/
- static void FindOrCreateTriangle(
- PVRTShadowVolShadowMesh * const psMesh,
- const PVRTVECTOR3 * const pv0,
- const PVRTVECTOR3 * const pv1,
- const PVRTVECTOR3 * const pv2)
- {
- unsigned int nCurr;
- PVRTShadowVolMEdge *psE0, *psE1, *psE2;
- psE0 = FindOrCreateEdge(psMesh, pv0, pv1);
- psE1 = FindOrCreateEdge(psMesh, pv1, pv2);
- psE2 = FindOrCreateEdge(psMesh, pv2, pv0);
- _ASSERT(psE0);
- _ASSERT(psE1);
- _ASSERT(psE2);
- if(psE0 == psE1 || psE1 == psE2 || psE2 == psE0) {
- /* Don't add degenerate triangles */
- _RPT0(_CRT_WARN, "FindOrCreateTriangle() Degenerate triangle.\n");
- return;
- }
- /*
- First check whether we already have a triangle here
- */
- for(nCurr = 0; nCurr < psMesh->nT; nCurr++) {
- if(
- (psMesh->pT[nCurr].pE0 == psE0 || psMesh->pT[nCurr].pE0 == psE1 || psMesh->pT[nCurr].pE0 == psE2) &&
- (psMesh->pT[nCurr].pE1 == psE0 || psMesh->pT[nCurr].pE1 == psE1 || psMesh->pT[nCurr].pE1 == psE2) &&
- (psMesh->pT[nCurr].pE2 == psE0 || psMesh->pT[nCurr].pE2 == psE1 || psMesh->pT[nCurr].pE2 == psE2))
- {
- /* Don't do anything more if the triangle already exists */
- return;
- }
- }
- /*
- Add the triangle then!
- */
- psMesh->pT[psMesh->nT].pE0 = psE0;
- psMesh->pT[psMesh->nT].pE1 = psE1;
- psMesh->pT[psMesh->nT].pE2 = psE2;
- /*
- Store the triangle indices; these are indices into the shadow mesh, not the source model indices
- */
- if(psE0->wV0 == psE1->wV0 || psE0->wV0 == psE1->wV1)
- psMesh->pT[psMesh->nT].w[0] = psE0->wV1;
- else
- psMesh->pT[psMesh->nT].w[0] = psE0->wV0;
- if(psE1->wV0 == psE2->wV0 || psE1->wV0 == psE2->wV1)
- psMesh->pT[psMesh->nT].w[1] = psE1->wV1;
- else
- psMesh->pT[psMesh->nT].w[1] = psE1->wV0;
- if(psE2->wV0 == psE0->wV0 || psE2->wV0 == psE0->wV1)
- psMesh->pT[psMesh->nT].w[2] = psE2->wV1;
- else
- psMesh->pT[psMesh->nT].w[2] = psE2->wV0;
- /* Calculate the triangle normal */
- CrossProduct(&psMesh->pT[psMesh->nT].vNormal, pv0, pv1, pv2);
- /* Check which edges have the correct winding order for this triangle */
- psMesh->pT[psMesh->nT].nWinding = 0;
- if(memcmp(&psMesh->pV[psE0->wV0], pv0, sizeof(*pv0)) == 0) psMesh->pT[psMesh->nT].nWinding |= 0x01;
- if(memcmp(&psMesh->pV[psE1->wV0], pv1, sizeof(*pv1)) == 0) psMesh->pT[psMesh->nT].nWinding |= 0x02;
- if(memcmp(&psMesh->pV[psE2->wV0], pv2, sizeof(*pv2)) == 0) psMesh->pT[psMesh->nT].nWinding |= 0x04;
- psMesh->nT++;
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshCreateMesh
- @Modified psMesh The shadow volume mesh to populate
- @Input pVertex A list of vertices
- @Input nNumVertex The number of vertices
- @Input pFaces A list of faces
- @Input nNumFaces The number of faces
- @Description Creates a mesh format suitable for generating shadow volumes
- *************************************************************************/
- void PVRTShadowVolMeshCreateMesh(
- PVRTShadowVolShadowMesh * const psMesh,
- const float * const pVertex,
- const unsigned int nNumVertex,
- const unsigned short * const pFaces,
- const unsigned int nNumFaces)
- {
- unsigned int nCurr;
- /*
- Prep the structure to return
- */
- memset(psMesh, 0, sizeof(*psMesh));
- /*
- Allocate some working space to find the unique vertices
- */
- psMesh->pV = (PVRTVECTOR3*)malloc(nNumVertex * sizeof(*psMesh->pV));
- psMesh->pE = (PVRTShadowVolMEdge*)malloc(nNumFaces * sizeof(*psMesh->pE) * 3);
- psMesh->pT = (PVRTShadowVolMTriangle*)malloc(nNumFaces * sizeof(*psMesh->pT));
- _ASSERT(psMesh->pV);
- _ASSERT(psMesh->pE);
- _ASSERT(psMesh->pT);
- for(nCurr = 0; nCurr < nNumFaces; nCurr++) {
- FindOrCreateTriangle(psMesh,
- (PVRTVECTOR3*)&pVertex[3 * pFaces[3 * nCurr + 0]],
- (PVRTVECTOR3*)&pVertex[3 * pFaces[3 * nCurr + 1]],
- (PVRTVECTOR3*)&pVertex[3 * pFaces[3 * nCurr + 2]]);
- }
- _ASSERT(psMesh->nV <= nNumVertex);
- _ASSERT(psMesh->nE < nNumFaces * 3);
- _ASSERT(psMesh->nT == nNumFaces);
- _RPT2(_CRT_WARN, "Unique vertices : %d (from %d)\n", psMesh->nV, nNumVertex);
- _RPT2(_CRT_WARN, "Unique edges : %d (from %d)\n", psMesh->nE, nNumFaces * 3);
- _RPT2(_CRT_WARN, "Unique triangles: %d (from %d)\n", psMesh->nT, nNumFaces);
- /*
- Create the real unique lists
- */
- psMesh->pV = (PVRTVECTOR3*)realloc(psMesh->pV, psMesh->nV * sizeof(*psMesh->pV));
- psMesh->pE = (PVRTShadowVolMEdge*)realloc(psMesh->pE, psMesh->nE * sizeof(*psMesh->pE));
- psMesh->pT = (PVRTShadowVolMTriangle*)realloc(psMesh->pT, psMesh->nT * sizeof(*psMesh->pT));
- _ASSERT(psMesh->pV);
- _ASSERT(psMesh->pE);
- _ASSERT(psMesh->pT);
- #if defined(_DEBUG) && !defined(_UNICODE) && defined(WIN32)
- /*
- Check we have sensible model data
- */
- {
- unsigned int nTri, nEdge;
- PVRTERROR_OUTPUT_DEBUG("ShadowMeshCreate() Sanity check...");
- for(nEdge = 0; nEdge < psMesh->nE; nEdge++) {
- nCurr = 0;
- for(nTri = 0; nTri < psMesh->nT; nTri++) {
- if(psMesh->pT[nTri].pE0 == &psMesh->pE[nEdge])
- nCurr++;
- if(psMesh->pT[nTri].pE1 == &psMesh->pE[nEdge])
- nCurr++;
- if(psMesh->pT[nTri].pE2 == &psMesh->pE[nEdge])
- nCurr++;
- }
- /*
- Every edge should be referenced exactly twice
- */
- _ASSERTE(nCurr == 2);
- }
- PVRTERROR_OUTPUT_DEBUG("done.\n");
- }
- #endif
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshInitMesh
- @Input psMesh The shadow volume mesh
- @Input pContext A struct for API specific data
- @Returns True on success
- @Description Init the mesh
- *************************************************************************/
- bool PVRTShadowVolMeshInitMesh(
- PVRTShadowVolShadowMesh * const psMesh,
- const SPVRTContext * const pContext)
- {
- unsigned int nCurr;
- #if defined(BUILD_DX9) || defined(BUILD_DX10)
- HRESULT hRes;
- #endif
- SVertexShVol *pvData;
- #if defined(BUILD_OGL)
- _ASSERT(pContext && pContext->pglExt);
- if(!pContext || !pContext->pglExt)
- return false;
- #endif
- #if defined(BUILD_OGLES2) || defined(BUILD_OGLES)
- PVRT_UNREFERENCED_PARAMETER(pContext);
- #endif
- _ASSERT(psMesh);
- _ASSERT(psMesh->nV);
- _ASSERT(psMesh->nE);
- _ASSERT(psMesh->nT);
- /*
- Allocate a vertex buffer for the shadow volumes
- */
- _ASSERT(psMesh->pivb == NULL);
- _RPT3(_CRT_WARN, "ShadowMeshInitMesh() %5d byte VB (%3dv x 2 x size(%d))\n", psMesh->nV * 2 * sizeof(*pvData), psMesh->nV, sizeof(*pvData));
- #if defined(BUILD_DX9)
- hRes = pContext->pDev->CreateVertexBuffer(psMesh->nV * 2 * sizeof(*pvData), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &psMesh->pivb, NULL);
- if(FAILED(hRes)) {
- _ASSERT(false);
- return false;
- }
- hRes = psMesh->pivb->Lock(0, 0, (void**)&pvData, 0);
- if(FAILED(hRes)) {
- _ASSERT(false);
- return false;
- }
- #endif
- #if defined(BUILD_DX10)
- pvData = (SVertexShVol*)psMesh->pivb;
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- psMesh->pivb = malloc(psMesh->nV * 2 * sizeof(*pvData));
- pvData = (SVertexShVol*)psMesh->pivb;
- #endif
- /*
- Fill the vertex buffer with two subtly different copies of the vertices
- */
- for(nCurr = 0; nCurr < psMesh->nV; ++nCurr) {
- pvData[nCurr].x = psMesh->pV[nCurr].x;
- pvData[nCurr].y = psMesh->pV[nCurr].y;
- pvData[nCurr].z = psMesh->pV[nCurr].z;
- pvData[nCurr].dwExtrude = 0;
- #if defined(BUILD_OGLES)
- pvData[nCurr].fWeight = 1;
- pvData[nCurr + psMesh->nV].fWeight = 1;
- #endif
- pvData[nCurr + psMesh->nV] = pvData[nCurr];
- pvData[nCurr + psMesh->nV].dwExtrude = 0x04030201; // Order is wzyx
- }
- #if defined(BUILD_DX9)
- psMesh->pivb->Unlock();
- #endif
- #if defined(BUILD_DX10)
- D3D10_BUFFER_DESC sBufDesc;
- sBufDesc.ByteWidth = psMesh->nV * 2 * sizeof(*pvData);
- sBufDesc.Usage = D3D10_USAGE_IMMUTABLE;
- sBufDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
- sBufDesc.CPUAccessFlags = 0;
- sBufDesc.MiscFlags = 0;
- D3D10_SUBRESOURCE_DATA sSRData;
- sSRData.pSysMem = pvData;
- hRes = pContext->pDev->CreateBuffer(&sBufDesc, &sSRData, &psMesh->pivb);
- if(FAILED(hRes))
- {
- _ASSERT(false);
- return false;
- }
- #endif
- return true;
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshInitVol
- @Modified psVol The shadow volume struct
- @Input psMesh The shadow volume mesh
- @Input pContext A struct for API specific data
- @Returns True on success
- @Description Init the renderable shadow volume information.
- *************************************************************************/
- bool PVRTShadowVolMeshInitVol(
- PVRTShadowVolShadowVol * const psVol,
- const PVRTShadowVolShadowMesh * const psMesh,
- const SPVRTContext * const pContext)
- {
- #if defined(BUILD_DX9)
- HRESULT hRes;
- #endif
- #if defined(BUILD_OGLES2) || defined(BUILD_OGLES) || defined(BUILD_OGL)
- PVRT_UNREFERENCED_PARAMETER(pContext);
- #endif
- _ASSERT(psVol);
- _ASSERT(psMesh);
- _ASSERT(psMesh->nV);
- _ASSERT(psMesh->nE);
- _ASSERT(psMesh->nT);
- _RPT1(_CRT_WARN, "ShadowMeshInitVol() %5d byte IB\n", psMesh->nT * 2 * 3 * sizeof(unsigned short));
- /*
- Allocate a index buffer for the shadow volumes
- */
- #if defined(_DEBUG)
- psVol->nIdxCntMax = psMesh->nT * 2 * 3;
- #endif
- #if defined(BUILD_DX9)
- hRes = pContext->pDev->CreateIndexBuffer(psMesh->nT * 2 * 3 * sizeof(unsigned short),
- D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &psVol->piib, NULL);
- if(FAILED(hRes)) {
- _ASSERT(false);
- return false;
- }
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- psVol->piib = (unsigned short*)malloc(psMesh->nT * 2 * 3 * sizeof(unsigned short));
- #endif
- return true;
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshDestroyMesh
- @Input psMesh The shadow volume mesh to destroy
- @Description Destroys all shadow volume mesh data created by PVRTShadowVolMeshCreateMesh
- *************************************************************************/
- void PVRTShadowVolMeshDestroyMesh(
- PVRTShadowVolShadowMesh * const psMesh)
- {
- FREE(psMesh->pV);
- FREE(psMesh->pE);
- FREE(psMesh->pT);
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshReleaseMesh
- @Input psMesh The shadow volume mesh to release
- @Description Releases all shadow volume mesh data created by PVRTShadowVolMeshInitMesh
- *************************************************************************/
- void PVRTShadowVolMeshReleaseMesh(
- PVRTShadowVolShadowMesh * const psMesh)
- {
- #if defined(BUILD_DX9)
- RELEASE(psMesh->pivb);
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- FREE(psMesh->pivb);
- #endif
- }
- /*!***********************************************************************
- @Function PVRTShadowVolMeshReleaseVol
- @Input psVol The shadow volume information to release
- @Description Releases all data create by PVRTShadowVolMeshInitVol
- *************************************************************************/
- void PVRTShadowVolMeshReleaseVol(
- PVRTShadowVolShadowVol * const psVol)
- {
- #if defined(BUILD_DX9)
- RELEASE(psVol->piib);
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- FREE(psVol->piib);
- #endif
- }
- /*!***********************************************************************
- @Function PVRTShadowVolSilhouetteProjectedBuild
- @Modified psVol The shadow volume information
- @Input dwVisFlags Shadow volume creation flags
- @Input psMesh The shadow volume mesh
- @Input pvLightModel The light position/direction
- @Input bPointLight Is the light a point light
- @Description Using the light set up the shadow volume so it can be extruded.
- *************************************************************************/
- void PVRTShadowVolSilhouetteProjectedBuild(
- PVRTShadowVolShadowVol * const psVol,
- const unsigned int dwVisFlags,
- const PVRTShadowVolShadowMesh * const psMesh,
- const PVRTVec3 * const pvLightModel,
- const bool bPointLight)
- {
- PVRTShadowVolSilhouetteProjectedBuild(psVol, dwVisFlags,psMesh, (PVRTVECTOR3*) pvLightModel, bPointLight);
- }
- /*!***********************************************************************
- @Function PVRTShadowVolSilhouetteProjectedBuild
- @Modified psVol The shadow volume information
- @Input dwVisFlags Shadow volume creation flags
- @Input psMesh The shadow volume mesh
- @Input pvLightModel The light position/direction
- @Input bPointLight Is the light a point light
- @Description Using the light set up the shadow volume so it can be extruded.
- *************************************************************************/
- void PVRTShadowVolSilhouetteProjectedBuild(
- PVRTShadowVolShadowVol * const psVol,
- const unsigned int dwVisFlags,
- const PVRTShadowVolShadowMesh * const psMesh,
- const PVRTVECTOR3 * const pvLightModel,
- const bool bPointLight)
- {
- PVRTVECTOR3 v;
- PVRTShadowVolMTriangle *psTri;
- PVRTShadowVolMEdge *psEdge;
- unsigned short *pwIdx;
- #if defined(BUILD_DX9) || defined(BUILD_DX10)
- HRESULT hRes;
- #endif
- unsigned int nCurr;
- float f;
- /*
- Lock the index buffer; this is where we create the shadow volume
- */
- _ASSERT(psVol && psVol->piib);
- #if defined(BUILD_DX9)
- hRes = psVol->piib->Lock(0, 0, (void**)&pwIdx, D3DLOCK_DISCARD);
- _ASSERT(SUCCEEDED(hRes));
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES) || defined(BUILD_OGLES2)
- pwIdx = psVol->piib;
- #endif
- psVol->nIdxCnt = 0;
- /*
- Run through triangles, testing which face the From point
- */
- for(nCurr = 0; nCurr < psMesh->nT; nCurr++) {
- psTri = &psMesh->pT[nCurr];
- if(bPointLight) {
- v.x = psMesh->pV[psTri->pE0->wV0].x - pvLightModel->x;
- v.y = psMesh->pV[psTri->pE0->wV0].y - pvLightModel->y;
- v.z = psMesh->pV[psTri->pE0->wV0].z - pvLightModel->z;
- f = PVRTMatrixVec3DotProduct(psTri->vNormal, v);
- } else {
- f = PVRTMatrixVec3DotProduct(psTri->vNormal, *pvLightModel);
- }
- if(f >= 0) {
- /* Triangle is in the light */
- psTri->pE0->nVis |= 0x01;
- psTri->pE1->nVis |= 0x01;
- psTri->pE2->nVis |= 0x01;
- if(dwVisFlags & PVRTSHADOWVOLUME_NEED_CAP_FRONT) {
- // Add the triangle to the volume, unextruded.
- pwIdx[psVol->nIdxCnt+0] = psTri->w[0];
- pwIdx[psVol->nIdxCnt+1] = psTri->w[1];
- pwIdx[psVol->nIdxCnt+2] = psTri->w[2];
- psVol->nIdxCnt += 3;
- }
- } else {
- /* Triangle is in shade; set Bit3 if the winding order needs reversed */
- psTri->pE0->nVis |= 0x02 | (psTri->nWinding & 0x01) << 2;
- psTri->pE1->nVis |= 0x02 | (psTri->nWinding & 0x02) << 1;
- psTri->pE2->nVis |= 0x02 | (psTri->nWinding & 0x04);
- if(dwVisFlags & PVRTSHADOWVOLUME_NEED_CAP_BACK) {
- // Add the triangle to the volume, extruded.
- // psMesh->nV is used as an offst so that the new index refers to the
- // corresponding position in the second array of vertices (which are extruded)
- pwIdx[psVol->nIdxCnt+0] = (unsigned short) psMesh->nV + psTri->w[0];
- pwIdx[psVol->nIdxCnt+1] = (unsigned short) psMesh->nV + psTri->w[1];
- pwIdx[psVol->nIdxCnt+2] = (unsigned short) psMesh->nV + psTri->w[2];
- psVol->nIdxCnt += 3;
- }
- }
- }
- #if defined(_DEBUG)
- _ASSERT(psVol->nIdxCnt <= psVol->nIdxCntMax);
- for(nCurr = 0; nCurr < psVol->nIdxCnt; ++nCurr) {
- _ASSERT(pwIdx[nCurr] < psMesh->nV*2);
- }
- #endif
- /*
- Run through edges, testing which are silhouette edges
- */
- for(nCurr = 0; nCurr < psMesh->nE; nCurr++) {
- psEdge = &psMesh->pE[nCurr];
- if((psEdge->nVis & 0x03) == 0x03) {
- /*
- Silhouette edge found!
- The edge is both visible and hidden,
- so it is along the silhouette of the model
- (See header notes for more info)
- */
- if(psEdge->nVis & 0x04) {
- pwIdx[psVol->nIdxCnt+0] = psEdge->wV0;
- pwIdx[psVol->nIdxCnt+1] = psEdge->wV1;
- pwIdx[psVol->nIdxCnt+2] = psEdge->wV0 + (unsigned short) psMesh->nV;
- pwIdx[psVol->nIdxCnt+3] = psEdge->wV0 + (unsigned short) psMesh->nV;
- pwIdx[psVol->nIdxCnt+4] = psEdge->wV1;
- pwIdx[psVol->nIdxCnt+5] = psEdge->wV1 + (unsigned short) psMesh->nV;
- } else {
- pwIdx[psVol->nIdxCnt+0] = psEdge->wV1;
- pwIdx[psVol->nIdxCnt+1] = psEdge->wV0;
- pwIdx[psVol->nIdxCnt+2] = psEdge->wV1 + (unsigned short) psMesh->nV;
- pwIdx[psVol->nIdxCnt+3] = psEdge->wV1 + (unsigned short) psMesh->nV;
- pwIdx[psVol->nIdxCnt+4] = psEdge->wV0;
- pwIdx[psVol->nIdxCnt+5] = psEdge->wV0 + (unsigned short) psMesh->nV;
- }
- psVol->nIdxCnt += 6;
- }
- /* Zero for next render */
- psEdge->nVis = 0;
- }
- #if defined(_DEBUG)
- _ASSERT(psVol->nIdxCnt <= psVol->nIdxCntMax);
- for(nCurr = 0; nCurr < psVol->nIdxCnt; ++nCurr) {
- _ASSERT(pwIdx[nCurr] < psMesh->nV*2);
- }
- #endif
- #if defined(BUILD_DX9)
- psVol->piib->Unlock();
- #endif
- #if defined(BUILD_DX10)
- D3D10_BUFFER_DESC sIdxBufferDesc;
- sIdxBufferDesc.ByteWidth = psVol->nIdxCnt * sizeof(WORD);
- sIdxBufferDesc.Usage = D3D10_USAGE_DEFAULT;
- sIdxBufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
- sIdxBufferDesc.CPUAccessFlags = 0;
- sIdxBufferDesc.MiscFlags = 0;
- D3D10_SUBRESOURCE_DATA sIdxBufferData;
- ZeroMemory(&sIdxBufferData, sizeof(D3D10_SUBRESOURCE_DATA));
- sIdxBufferData.pSysMem = pwIdx;
- hRes = pContext->pDev->CreateBuffer(&sIdxBufferDesc, &sIdxBufferData, &psVol->piib));
- _ASSERT(SUCCEEDED(hRes));
- #endif
- }
- /*!***********************************************************************
- @Function IsBoundingBoxVisibleEx
- @Input pBoundingHyperCube The hypercube to test against
- @Input fCamZ The camera's position along the z-axis
- @Return bool Returns true if the bounding box is visible
- @Description This method tests the bounding box's position against
- the camera's position to determine if it is visible.
- If it is visible, the function returns true.
- *************************************************************************/
- static bool IsBoundingBoxVisibleEx(
- const PVRTVECTOR4 * const pBoundingHyperCube,
- const float fCamZ)
- {
- PVRTVECTOR3 v, vShift[16];
- unsigned int dwClipFlags;
- int i, j;
- unsigned short w0, w1;
- dwClipFlags = 0; // Assume all are off-screen
- i = 8;
- while(i)
- {
- i--;
- if(pBoundingHyperCube[i].x < pBoundingHyperCube[i].w)
- dwClipFlags |= 1 << 0;
- if(pBoundingHyperCube[i].x > -pBoundingHyperCube[i].w)
- dwClipFlags |= 1 << 1;
- if(pBoundingHyperCube[i].y < pBoundingHyperCube[i].w)
- dwClipFlags |= 1 << 2;
- if(pBoundingHyperCube[i].y > -pBoundingHyperCube[i].w)
- dwClipFlags |= 1 << 3;
- if(pBoundingHyperCube[i].z > 0)
- dwClipFlags |= 1 << 4;
- }
- /*
- Volume is hidden if all the vertices are over a screen edge
- */
- if(dwClipFlags != 0x1F)
- return false;
- /*
- Well, according to the simple bounding box check, it might be
- visible. Let's now test the view frustrum against the bounding
- cube. (Basically the reverse of the previous test!)
- This catches those cases where a diagonal cube passes near a
- screen edge.
- */
- // Subtract the camera position from the vertices. I.e. move the camera to 0,0,0
- for(i = 0; i < 8; ++i) {
- vShift[i].x = pBoundingHyperCube[i].x;
- vShift[i].y = pBoundingHyperCube[i].y;
- vShift[i].z = pBoundingHyperCube[i].z - fCamZ;
- }
- i = 12;
- while(i) {
- --i;
- w0 = c_pwLinesHyperCube[2 * i + 0];
- w1 = c_pwLinesHyperCube[2 * i + 1];
- PVRTMatrixVec3CrossProduct(v, vShift[w0], vShift[w1]);
- dwClipFlags = 0;
- j = 4;
- while(j) {
- --j;
- if(PVRTMatrixVec3DotProduct(c_pvRect[j], v) < 0)
- ++dwClipFlags;
- }
- // dwClipFlagsA will be 0 or 4 if the screen edges are on the outside of
- // this bounding-box-silhouette-edge.
- if(dwClipFlags % 4)
- continue;
- j = 8;
- while(j) {
- --j;
- if((j != w0) & (j != w1) && (PVRTMatrixVec3DotProduct(vShift[j], v) > 0))
- ++dwClipFlags;
- }
- // dwClipFlagsA will be 0 or 18 if this is a silhouette edge of the bounding box
- if(dwClipFlags % 12)
- continue;
- return false;
- }
- return true;
- }
- /*!***********************************************************************
- @Function IsHyperBoundingBoxVisibleEx
- @Input pBoundingHyperCube The hypercube to test against
- @Input fCamZ The camera's position along the z-axis
- @Return bool Returns true if the bounding box is visible
- @Description This method tests the hypercube bounding box's position against
- the camera's position to determine if it is visible.
- If it is visible, the function returns true.
- *************************************************************************/
- static bool IsHyperBoundingBoxVisibleEx(
- const PVRTVECTOR4 * const pBoundingHyperCube,
- const float fCamZ)
- {
- const PVRTVECTOR4 *pv0;
- PVRTVECTOR3 v, vShift[16];
- unsigned int dwClipFlagsA, dwClipFlagsB;
- int i, j;
- unsigned short w0, w1;
- pv0 = &pBoundingHyperCube[8];
- dwClipFlagsA = 0; // Assume all are off-screen
- dwClipFlagsB = 0;
- i = 8;
- while(i)
- {
- i--;
- // Far
- if(pv0[i].x < pv0[i].w)
- dwClipFlagsA |= 1 << 0;
- if(pv0[i].x > -pv0[i].w)
- dwClipFlagsA |= 1 << 1;
- if(pv0[i].y < pv0[i].w)
- dwClipFlagsA |= 1 << 2;
- if(pv0[i].y > -pv0[i].w)
- dwClipFlagsA |= 1 << 3;
- if(pv0[i].z > 0)
- dwClipFlagsA |= 1 << 4;
- // Near
- if(pBoundingHyperCube[i].x < pBoundingHyperCube[i].w)
- dwClipFlagsB |= 1 << 0;
- if(pBoundingHyperCube[i].x > -pBoundingHyperCube[i].w)
- dwClipFlagsB |= 1 << 1;
- if(pBoundingHyperCube[i].y < pBoundingHyperCube[i].w)
- dwClipFlagsB |= 1 << 2;
- if(pBoundingHyperCube[i].y > -pBoundingHyperCube[i].w)
- dwClipFlagsB |= 1 << 3;
- if(pBoundingHyperCube[i].z > 0)
- dwClipFlagsB |= 1 << 4;
- }
- /*
- Volume is hidden if all the vertices are over a screen edge
- */
- if((dwClipFlagsA | dwClipFlagsB) != 0x1F)
- return false;
- /*
- Well, according to the simple bounding box check, it might be
- visible. Let's now test the view frustrum against the bounding
- hyper cube. (Basically the reverse of the previous test!)
- This catches those cases where a diagonal hyper cube passes near a
- screen edge.
- */
- // Subtract the camera position from the vertices. I.e. move the camera to 0,0,0
- for(i = 0; i < 16; ++i) {
- vShift[i].x = pBoundingHyperCube[i].x;
- vShift[i].y = pBoundingHyperCube[i].y;
- vShift[i].z = pBoundingHyperCube[i].z - fCamZ;
- }
- i = 32;
- while(i) {
- --i;
- w0 = c_pwLinesHyperCube[2 * i + 0];
- w1 = c_pwLinesHyperCube[2 * i + 1];
- PVRTMatrixVec3CrossProduct(v, vShift[w0], vShift[w1]);
- dwClipFlagsA = 0;
- j = 4;
- while(j) {
- --j;
- if(PVRTMatrixVec3DotProduct(c_pvRect[j], v) < 0)
- ++dwClipFlagsA;
- }
- // dwClipFlagsA will be 0 or 4 if the screen edges are on the outside of
- // this bounding-box-silhouette-edge.
- if(dwClipFlagsA % 4)
- continue;
- j = 16;
- while(j) {
- --j;
- if((j != w0) & (j != w1) && (PVRTMatrixVec3DotProduct(vShift[j], v) > 0))
- ++dwClipFlagsA;
- }
- // dwClipFlagsA will be 0 or 18 if this is a silhouette edge of the bounding box
- if(dwClipFlagsA % 18)
- continue;
- return false;
- }
- return true;
- }
- /*!***********************************************************************
- @Function IsFrontClipInVolume
- @Input pBoundingHyperCube The hypercube to test against
- @Return bool
- @Description Returns true if the hypercube is within the view frustrum.
- *************************************************************************/
- static bool IsFrontClipInVolume(
- const PVRTVECTOR4 * const pBoundingHyperCube)
- {
- const PVRTVECTOR4 *pv0, *pv1;
- unsigned int dwClipFlags;
- int i;
- float fScale, x, y, w;
- /*
- OK. The hyper-bounding-box is in the view frustrum.
- Now decide if we can use Z-pass instead of Z-fail.
- TODO: if we calculate the convex hull of the front-clip intersection
- points, we can use the connecting lines to do a more accurate on-
- screen check (currently it just uses the bounding box of the
- intersection points.)
- */
- dwClipFlags = 0;
- i = 32;
- while(i) {
- --i;
- pv0 = &pBoundingHyperCube[c_pwLinesHyperCube[2 * i + 0]];
- pv1 = &pBoundingHyperCube[c_pwLinesHyperCube[2 * i + 1]];
- // If both coords are negative, or both coords are positive, it doesn't cross the Z=0 plane
- if(pv0->z * pv1->z > 0)
- continue;
- // TODO: if fScale > 0.5f, do the lerp in the other direction; this is
- // because we want fScale to be close to 0, not 1, to retain accuracy.
- fScale = (0 - pv0->z) / (pv1->z - pv0->z);
- x = fScale * pv1->x + (1.0f - fScale) * pv0->x;
- y = fScale * pv1->y + (1.0f - fScale) * pv0->y;
- w = fScale * pv1->w + (1.0f - fScale) * pv0->w;
- if(x > -w)
- dwClipFlags |= 1 << 0;
- if(x < w)
- dwClipFlags |= 1 << 1;
- if(y > -w)
- dwClipFlags |= 1 << 2;
- if(y < w)
- dwClipFlags |= 1 << 3;
- }
- if(dwClipFlags == 0x0F)
- return true;
- return false;
- }
- /*!***********************************************************************
- @Function PVRTShadowVolBoundingBoxExtrude
- @Modified pvExtrudedCube 8 Vertices to represent the extruded box
- @Input pBoundingBox The bounding box to extrude
- @Input pvLightMdl The light position/direction
- @Input bPointLight Is the light a point light
- @Input fVolLength The length the volume has been extruded by
- @Description Extrudes the bounding box of the volume
- *************************************************************************/
- void PVRTShadowVolBoundingBoxExtrude(
- PVRTVECTOR3 * const pvExtrudedCube,
- const PVRTBOUNDINGBOX * const pBoundingBox,
- const PVRTVECTOR3 * const pvLightMdl,
- const bool bPointLight,
- const float fVolLength)
- {
- int i;
- if(bPointLight) {
- i = 8;
- while(i)
- {
- i--;
- pvExtrudedCube[i].x = pBoundingBox->Point[i].x + fVolLength * (pBoundingBox->Point[i].x - pvLightMdl->x);
- pvExtrudedCube[i].y = pBoundingBox->Point[i].y + fVolLength * (pBoundingBox->Point[i].y - pvLightMdl->y);
- pvExtrudedCube[i].z = pBoundingBox->Point[i].z + fVolLength * (pBoundingBox->Point[i].z - pvLightMdl->z);
- }
- } else {
- i = 8;
- while(i)
- {
- i--;
- pvExtrudedCube[i].x = pBoundingBox->Point[i].x + fVolLength * pvLightMdl->x;
- pvExtrudedCube[i].y = pBoundingBox->Point[i].y + fVolLength * pvLightMdl->y;
- pvExtrudedCube[i].z = pBoundingBox->Point[i].z + fVolLength * pvLightMdl->z;
- }
- }
- }
- /*!***********************************************************************
- @Function PVRTShadowVolBoundingBoxIsVisible
- @Modified pdwVisFlags Visibility flags
- @Input bObVisible Unused set to true
- @Input bNeedsZClipping Unused set to true
- @Input pBoundingBox The volumes bounding box
- @Input pmTrans The projection matrix
- @Input pvLightMdl The light position/direction
- @Input bPointLight Is the light a point light
- @Input fCamZProj The camera's z projection value
- @Input fVolLength The length the volume is extruded by
- @Description Determines if the volume is visible and if it needs caps
- *************************************************************************/
- void PVRTShadowVolBoundingBoxIsVisible(
- unsigned int * const pdwVisFlags,
- const bool bObVisible, // Is the object visible?
- const bool bNeedsZClipping, // Does the object require Z clipping?
- const PVRTBOUNDINGBOX * const pBoundingBox,
- const PVRTMATRIX * const pmTrans,
- const PVRTVECTOR3 * const pvLightMdl,
- const bool bPointLight,
- const float fCamZProj,
- const float fVolLength)
- {
- PVRTVECTOR3 pvExtrudedCube[8];
- PVRTVECTOR4 BoundingHyperCubeT[16];
- int i;
- unsigned int dwClipFlagsA, dwClipZCnt;
- float fLightProjZ;
- PVRT_UNREFERENCED_PARAMETER(bObVisible);
- PVRT_UNREFERENCED_PARAMETER(bNeedsZClipping);
- _ASSERT((bObVisible && bNeedsZClipping) || !bNeedsZClipping);
- /*
- Transform the eight bounding box points into projection space
- */
- PVRTTransformVec3Array(&BoundingHyperCubeT[0], sizeof(*BoundingHyperCubeT), pBoundingBox->Point, sizeof(*pBoundingBox->Point), pmTrans, 8);
- /*
- Get the light Z coordinate in projection space
- */
- fLightProjZ =
- pmTrans->f[ 2] * pvLightMdl->x +
- pmTrans->f[ 6] * pvLightMdl->y +
- pmTrans->f[10] * pvLightMdl->z +
- pmTrans->f[14];
- /*
- Where is the object relative to the near clip plane and light?
- */
- dwClipZCnt = 0;
- dwClipFlagsA = 0;
- i = 8;
- while(i) {
- --i;
- if(BoundingHyperCubeT[i].z <= 0)
- ++dwClipZCnt;
- if(BoundingHyperCubeT[i].z <= fLightProjZ)
- ++dwClipFlagsA;
- }
- if(dwClipZCnt == 8 && dwClipFlagsA == 8) {
- // hidden
- *pdwVisFlags = 0;
- return;
- }
- /*
- Shadow the bounding box into pvExtrudedCube.
- */
- PVRTShadowVolBoundingBoxExtrude(pvExtrudedCube, pBoundingBox, pvLightMdl, bPointLight, fVolLength);
- /*
- Transform to projection space
- */
- PVRTTransformVec3Array(&BoundingHyperCubeT[8], sizeof(*BoundingHyperCubeT), pvExtrudedCube, sizeof(*pvExtrudedCube), pmTrans, 8);
- /*
- Check whether any part of the hyper bounding box is even visible
- */
- if(!IsHyperBoundingBoxVisibleEx(BoundingHyperCubeT, fCamZProj)) {
- *pdwVisFlags = 0;
- return;
- }
- /*
- It's visible, so choose a render method
- */
- if(dwClipZCnt == 8) {
- // 1
- if(IsFrontClipInVolume(BoundingHyperCubeT)) {
- *pdwVisFlags = PVRTSHADOWVOLUME_VISIBLE | PVRTSHADOWVOLUME_NEED_ZFAIL;
- if(IsBoundingBoxVisibleEx(&BoundingHyperCubeT[8], fCamZProj))
- {
- *pdwVisFlags |= PVRTSHADOWVOLUME_NEED_CAP_BACK;
- }
- } else {
- *pdwVisFlags = PVRTSHADOWVOLUME_VISIBLE;
- }
- } else {
- if(!(dwClipZCnt | dwClipFlagsA)) {
- // 3
- *pdwVisFlags = PVRTSHADOWVOLUME_VISIBLE;
- } else {
- // 5
- if(IsFrontClipInVolume(BoundingHyperCubeT)) {
- *pdwVisFlags = PVRTSHADOWVOLUME_VISIBLE | PVRTSHADOWVOLUME_NEED_ZFAIL;
- if(IsBoundingBoxVisibleEx(BoundingHyperCubeT, fCamZProj))
- {
- *pdwVisFlags |= PVRTSHADOWVOLUME_NEED_CAP_FRONT;
- }
- if(IsBoundingBoxVisibleEx(&BoundingHyperCubeT[8], fCamZProj))
- {
- *pdwVisFlags |= PVRTSHADOWVOLUME_NEED_CAP_BACK;
- }
- } else {
- *pdwVisFlags = PVRTSHADOWVOLUME_VISIBLE;
- }
- }
- }
- }
- /*!***********************************************************************
- @Function PVRTShadowVolSilhouetteProjectedRender
- @Input psMesh Shadow volume mesh
- @Input psVol Renderable shadow volume information
- @Input pContext A struct for passing in API specific data
- @Description Draws the shadow volume
- *************************************************************************/
- int PVRTShadowVolSilhouetteProjectedRender(
- const PVRTShadowVolShadowMesh * const psMesh,
- const PVRTShadowVolShadowVol * const psVol,
- const SPVRTContext * const pContext)
- {
- #if defined(BUILD_DX9)
- HRESULT hRes;
- _ASSERT(psMesh->pivb);
- pContext->pDev->SetStreamSource(0, psMesh->pivb, 0, sizeof(SVertexShVol));
- pContext->pDev->SetIndices(psVol->piib);
- _ASSERT(psVol->nIdxCnt <= psVol->nIdxCntMax);
- _ASSERT(psVol->nIdxCnt % 3 == 0);
- _ASSERT(psVol->nIdxCnt / 3 <= 0xFFFF);
- hRes = pContext->pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, psMesh->nV * 2, 0, psVol->nIdxCnt / 3);
- _ASSERT(SUCCEEDED(hRes));
- return psVol->nIdxCnt / 3;
- #endif
- #if defined(BUILD_OGL) || defined(BUILD_OGLES2) || defined(BUILD_OGLES)
- _ASSERT(psMesh->pivb);
- #if defined(_DEBUG) // To fix error in Linux
- _ASSERT(psVol->nIdxCnt <= psVol->nIdxCntMax);
- _ASSERT(psVol->nIdxCnt % 3 == 0);
- _ASSERT(psVol->nIdxCnt / 3 <= 0xFFFF);
- #endif
- #if defined(BUILD_OGL)
- _ASSERT(pContext && pContext->pglExt);
- pContext->pglExt->glVertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].x);
- pContext->pglExt->glEnableVertexAttribArrayARB(0);
- pContext->pglExt->glVertexAttribPointerARB(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].dwExtrude);
- pContext->pglExt->glEnableVertexAttribArrayARB(1);
- glDrawElements(GL_TRIANGLES, psVol->nIdxCnt, GL_UNSIGNED_SHORT, psVol->piib);
- pContext->pglExt->glDisableVertexAttribArrayARB(0);
- pContext->pglExt->glDisableVertexAttribArrayARB(1);
- return psVol->nIdxCnt / 3;
- #else
- #if defined(BUILD_OGLES2)
- PVRT_UNREFERENCED_PARAMETER(pContext);
- GLint i32CurrentProgram;
- glGetIntegerv(GL_CURRENT_PROGRAM, &i32CurrentProgram);
- _ASSERT(i32CurrentProgram); //no program currently set
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].x);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].dwExtrude);
- glEnableVertexAttribArray(1);
- glDrawElements(GL_TRIANGLES, psVol->nIdxCnt, GL_UNSIGNED_SHORT, psVol->piib);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
- return psVol->nIdxCnt / 3;
- #else
- #if defined(BUILD_OGLES)
- #if defined(__BADA__) && defined(_WIN32)
- return 0; // The bada simulator is missing the matrix palette defines
- #else
- _ASSERT(pContext && pContext->pglesExt);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_MATRIX_INDEX_ARRAY_OES);
- glEnableClientState(GL_WEIGHT_ARRAY_OES);
- glVertexPointer(3, GL_FLOAT, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].x);
- pContext->pglesExt->glMatrixIndexPointerOES(1, GL_UNSIGNED_BYTE, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].dwExtrude);
- pContext->pglesExt->glWeightPointerOES(1, GL_FLOAT, sizeof(SVertexShVol), &((SVertexShVol*)psMesh->pivb)[0].fWeight);
- glDrawElements(GL_TRIANGLES, psVol->nIdxCnt, GL_UNSIGNED_SHORT, psVol->piib);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_MATRIX_INDEX_ARRAY_OES);
- glDisableClientState(GL_WEIGHT_ARRAY_OES);
- return psVol->nIdxCnt / 3;
- #endif
- #endif
- #endif
- #endif
- #endif
- }
- /*****************************************************************************
- End of file (PVRTShadowVol.cpp)
- *****************************************************************************/
|