2061 lines
64 KiB
C++
2061 lines
64 KiB
C++
/*=============================================================================
|
|
CREOcLeaf.cpp : implementation of OcLeaf Render Element.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
#include "RenderPCH.h"
|
|
#include "../NvTriStrip/NVTriStrip.h"
|
|
#include <ICryAnimation.h>
|
|
|
|
CREOcLeaf *CREOcLeaf::m_pLastRE;
|
|
|
|
void CREOcLeaf::mfCenter(Vec3d& Pos, CCObject*pObj)
|
|
{
|
|
if (m_Flags & FCEF_CALCCENTER)
|
|
{
|
|
Pos = m_Center;
|
|
if (pObj)
|
|
Pos += pObj->GetTranslation();
|
|
return;
|
|
}
|
|
m_Flags |= FCEF_CALCCENTER;
|
|
int i;
|
|
CRenderer *rd = gRenDev;
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
|
|
Pos = Vec3d(0,0,0);
|
|
byte *pD = lb->m_pSecVertBuffer ? (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData : 0;
|
|
if (!pD)
|
|
{
|
|
Vec3d Mins = m_pBuffer->m_vBoxMin;
|
|
Vec3d Maxs = m_pBuffer->m_vBoxMax;
|
|
Pos = (Mins + Maxs) * 0.5f;
|
|
m_Center = Pos;
|
|
if (pObj)
|
|
Pos += pObj->GetTranslation();
|
|
return;
|
|
}
|
|
int Stride = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
|
pD += m_pChunk->nFirstVertId * Stride;
|
|
for (i=0; i<m_pChunk->nNumVerts; i++, pD+=Stride)
|
|
{
|
|
Vec3d *p = (Vec3d *)pD;
|
|
Pos += *p;
|
|
}
|
|
float f = 1.0f / (float)m_pChunk->nNumVerts;
|
|
Pos *= f;
|
|
m_Center = Pos;
|
|
if (pObj)
|
|
Pos += pObj->GetTranslation();
|
|
}
|
|
|
|
void CREOcLeaf::mfGetBBox(Vec3d& vMins, Vec3d& vMaxs)
|
|
{
|
|
vMins = m_pBuffer->GetVertexContainer()->m_vBoxMin;
|
|
vMaxs = m_pBuffer->GetVertexContainer()->m_vBoxMax;
|
|
}
|
|
|
|
float CREOcLeaf::mfDistanceToCameraSquared(const CCObject & thisObject)
|
|
{
|
|
if (thisObject.m_fDistanceToCam >= 0)
|
|
return thisObject.m_fDistanceToCam;
|
|
|
|
CRenderer *rd = gRenDev;
|
|
|
|
Vec3d Mins = m_pBuffer->m_vBoxMin;
|
|
Vec3d Maxs = m_pBuffer->m_vBoxMax;
|
|
Vec3d Center = (Mins + Maxs) * 0.5f;
|
|
Center += thisObject.GetTranslation();
|
|
Vec3d Delta = rd->m_RP.m_ViewOrg - Center;
|
|
return GetLengthSquared(Delta);
|
|
}
|
|
|
|
|
|
bool CREOcLeaf::mfCullByClipPlane(CCObject *pObj)
|
|
{
|
|
CRenderer *rd = gRenDev;
|
|
|
|
if (rd->m_RP.m_ClipPlaneEnabled && CRenderer::CV_r_cullbyclipplanes)
|
|
{
|
|
Vec3d Mins = m_pBuffer->m_vBoxMin;
|
|
Vec3d Maxs = m_pBuffer->m_vBoxMax;
|
|
if (!(pObj->m_ObjFlags & FOB_TRANS_ROTATE))
|
|
{
|
|
// Non rotated bounding-box. Fast solution
|
|
if (!(pObj->m_ObjFlags & FOB_TRANS_SCALE))
|
|
{
|
|
Mins += pObj->GetTranslation();
|
|
Maxs += pObj->GetTranslation();
|
|
}
|
|
else
|
|
{
|
|
Matrix44& m = pObj->GetMatrix();
|
|
Mins = m.TransformPointOLD(Mins);
|
|
Maxs = m.TransformPointOLD(Maxs);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// General slow solution (separatelly transform all 8 points of
|
|
// non transformed cube and calculate axis aligned bounding box)
|
|
Vec3d v[8];
|
|
int i;
|
|
Matrix44& m = pObj->GetMatrix();
|
|
for (i=0; i<8; i++)
|
|
{
|
|
if (i & 1)
|
|
v[i].x = Mins.x;
|
|
else
|
|
v[i].x = Maxs.x;
|
|
|
|
if (i & 2)
|
|
v[i].y = Mins.y;
|
|
else
|
|
v[i].y = Maxs.y;
|
|
|
|
if (i & 4)
|
|
v[i].z = Mins.z;
|
|
else
|
|
v[i].z = Maxs.z;
|
|
v[i] = m.TransformPointOLD(v[i]);
|
|
}
|
|
Mins=SetMaxBB();
|
|
Maxs=SetMinBB();
|
|
for (i=0; i<8; i++)
|
|
{
|
|
AddToBounds(v[i], Mins, Maxs);
|
|
}
|
|
}
|
|
if (CullBoxByPlane(&Mins.x, &Maxs.x, &rd->m_RP.m_CurClipPlaneCull) == 2)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
//#undef DO_ASM
|
|
|
|
_inline byte *sCopyTransf_P_T(struct_VERTEX_FORMAT_P3F_TEX2F *dst, Matrix44 *mat, int nNumVerts, byte *OffsP, int nP, byte *OffsT, int nT)
|
|
{
|
|
#ifdef DO_ASM
|
|
_asm
|
|
{
|
|
mov eax, mat
|
|
mov ecx, nNumVerts;
|
|
movaps xmm2,xmmword ptr [eax]
|
|
mov esi, OffsP
|
|
movaps xmm4,xmmword ptr [eax+10h]
|
|
mov ebx, OffsT
|
|
movaps xmm6,xmmword ptr [eax+20h]
|
|
mov edi, dst
|
|
movaps xmm5,xmmword ptr [eax+30h]
|
|
align 16
|
|
_Loop2:
|
|
prefetchT0 [esi+20]
|
|
movlps xmm1,qword ptr [esi]
|
|
movss xmm0,dword ptr [esi+8]
|
|
shufps xmm0,xmm0,0
|
|
movaps xmm3,xmm1
|
|
mulps xmm0,xmm6
|
|
add edi, 20
|
|
shufps xmm3,xmm1,55h
|
|
mov eax, [ebx]
|
|
mulps xmm3,xmm4
|
|
shufps xmm1,xmm1,0
|
|
mov [edi+12-20], eax
|
|
mulps xmm1,xmm2
|
|
addps xmm3,xmm1
|
|
mov eax, [ebx+4]
|
|
addps xmm3,xmm0
|
|
add ebx, nT
|
|
addps xmm3,xmm5
|
|
add esi, nP
|
|
movhlps xmm1,xmm3
|
|
movlps qword ptr [edi-20],xmm3
|
|
dec ecx
|
|
mov [edi+16-20], eax
|
|
movss dword ptr [edi+8-20],xmm1
|
|
jne _Loop2
|
|
mov dst, edi
|
|
}
|
|
#else
|
|
for (int i=0; i<nNumVerts; i++, OffsP+=nP, OffsT+=nT)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3d *)OffsP);
|
|
dst->st[0] = *(float *)OffsT;
|
|
dst->st[1] = *(float *)(OffsT+4);
|
|
dst++;
|
|
}
|
|
#endif
|
|
return (byte *)dst;
|
|
}
|
|
|
|
_inline byte *sCopyTransf_P_C_T(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *dst, Matrix44 *mat, int nNumVerts, byte *OffsP, int nP, byte *OffsD, int nD, byte *OffsT, int nT)
|
|
{
|
|
#ifdef DO_ASM
|
|
_asm
|
|
{
|
|
mov eax, mat
|
|
mov ecx, nNumVerts;
|
|
movaps xmm2,xmmword ptr [eax]
|
|
mov esi, OffsP
|
|
movaps xmm4,xmmword ptr [eax+10h]
|
|
mov ebx, OffsT
|
|
movaps xmm6,xmmword ptr [eax+20h]
|
|
mov edi, dst
|
|
movaps xmm5,xmmword ptr [eax+30h]
|
|
mov edx, OffsD
|
|
align 16
|
|
_Loop1:
|
|
prefetchT0 [esi+24]
|
|
movlps xmm1,qword ptr [esi]
|
|
movss xmm0,dword ptr [esi+8]
|
|
shufps xmm0,xmm0,0
|
|
add edi, 24
|
|
movaps xmm3,xmm1
|
|
mulps xmm0,xmm6
|
|
mov eax, [edx]
|
|
shufps xmm3,xmm1,55h
|
|
mulps xmm3,xmm4
|
|
mov [edi+12-24], eax
|
|
shufps xmm1,xmm1,0
|
|
mulps xmm1,xmm2
|
|
mov eax, [ebx]
|
|
addps xmm3,xmm1
|
|
mov [edi+16-24], eax
|
|
addps xmm3,xmm0
|
|
mov eax, [ebx+4]
|
|
add ebx, nT
|
|
addps xmm3,xmm5
|
|
add esi, nP
|
|
movhlps xmm1,xmm3
|
|
add edx, nD
|
|
movlps qword ptr [edi-24],xmm3
|
|
dec ecx
|
|
mov [edi+20-24], eax
|
|
movss dword ptr [edi+8-24],xmm1
|
|
jne _Loop1
|
|
mov dst, edi
|
|
}
|
|
#else
|
|
for (int i=0; i<nNumVerts; i++, OffsP+=nP, OffsD+=nD, OffsT+=nT)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst->color.dcolor = *(DWORD *)OffsD;
|
|
dst->st[0] = *(float *)OffsT;
|
|
dst->st[1] = *(float *)(OffsT+4);
|
|
dst++;
|
|
}
|
|
#endif
|
|
return (byte *)dst;
|
|
}
|
|
|
|
_inline byte *sCopyTransf_P_C_C1_T(struct_VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F *dst, Matrix44 *mat, int nNumVerts, byte *OffsP, int nP, byte *OffsD, int nD, byte *OffsT, int nT)
|
|
{
|
|
#ifdef DO_ASM
|
|
_asm
|
|
{
|
|
mov eax, mat
|
|
mov ecx, nNumVerts;
|
|
movaps xmm2,xmmword ptr [eax]
|
|
mov esi, OffsP
|
|
movaps xmm4,xmmword ptr [eax+10h]
|
|
mov ebx, OffsT
|
|
movaps xmm6,xmmword ptr [eax+20h]
|
|
mov edi, dst
|
|
movaps xmm5,xmmword ptr [eax+30h]
|
|
mov edx, OffsD
|
|
align 16
|
|
_Loop1:
|
|
prefetchT0 [esi+28]
|
|
movlps xmm1,qword ptr [esi]
|
|
movss xmm0,dword ptr [esi+8]
|
|
shufps xmm0,xmm0,0
|
|
add edi, 28
|
|
movaps xmm3,xmm1
|
|
mov eax, [edx]
|
|
mulps xmm0,xmm6
|
|
shufps xmm3,xmm1,55h
|
|
mov [edi+12-28], eax
|
|
mulps xmm3,xmm4
|
|
mov eax, [esi+16]
|
|
shufps xmm1,xmm1,0
|
|
mov [edi+16-28], eax
|
|
mulps xmm1,xmm2
|
|
mov eax, [ebx]
|
|
addps xmm3,xmm1
|
|
mov [edi+20-28], eax
|
|
addps xmm3,xmm0
|
|
mov eax, [ebx+4]
|
|
add ebx, nT
|
|
addps xmm3,xmm5
|
|
add esi, nP
|
|
movhlps xmm1,xmm3
|
|
add edx, nD
|
|
movlps qword ptr [edi-28],xmm3
|
|
dec ecx
|
|
mov [edi+24-28], eax
|
|
movss dword ptr [edi+8-28],xmm1
|
|
jne _Loop1
|
|
mov dst, edi
|
|
}
|
|
#else
|
|
for (int i=0; i<nNumVerts; i++, OffsP+=nP, OffsD+=nD, OffsT+=nT)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst->color.dcolor = *(DWORD *)OffsD;
|
|
dst->seccolor.dcolor = *(DWORD *)(OffsD+4);
|
|
dst->st[0] = *(float *)OffsT;
|
|
dst->st[1] = *(float *)(OffsT+4);
|
|
dst++;
|
|
}
|
|
#endif
|
|
return (byte *)dst;
|
|
}
|
|
|
|
_inline void sCopyInds8(uint *dinds, uint *inds, int nInds8, int n)
|
|
{
|
|
if (!nInds8)
|
|
return;
|
|
#ifdef DO_ASM
|
|
_asm
|
|
{
|
|
mov edi, dinds
|
|
mov esi, inds
|
|
mov ecx, nInds8
|
|
mov eax, n
|
|
align 4
|
|
_Loop:
|
|
prefetchT0 [esi+10h]
|
|
mov edx, [esi]
|
|
add edx, eax
|
|
mov [edi], edx
|
|
mov ebx, [esi+4]
|
|
add edi, 16
|
|
add ebx, eax
|
|
mov [edi+4-16], ebx
|
|
mov edx, [esi+8]
|
|
add edx, eax
|
|
add esi, 16
|
|
mov [edi+8-16], edx
|
|
mov ebx, [esi+12-16]
|
|
add ebx, eax
|
|
dec ecx
|
|
mov [edi+12-16], ebx
|
|
jne _Loop
|
|
}
|
|
#else
|
|
for (int i=0; i<nInds8; i++, dinds+=4, inds+=4)
|
|
{
|
|
dinds[0] = inds[0] + n;
|
|
dinds[1] = inds[1] + n;
|
|
dinds[2] = inds[2] + n;
|
|
dinds[3] = inds[3] + n;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CREOcLeaf::mfFillRB(CCObject *pObj)
|
|
{
|
|
int i;
|
|
CRenderer *rd = gRenDev;
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
CMatInfo *mi = m_pChunk;
|
|
|
|
rd->EF_CheckOverflow(mi->nNumVerts, mi->nNumIndices/3, this);
|
|
|
|
SShader *ef = rd->m_RP.m_pShader;
|
|
SRenderShaderResources *Res = rd->m_RP.m_pShaderResources;
|
|
SShaderTechnique *hs = rd->m_RP.m_pCurTechnique;
|
|
int nFlags = hs ? hs->m_Flags : 0;
|
|
|
|
int nDstV = rd->m_RP.m_RendNumVerts;
|
|
int nDstI = rd->m_RP.m_RendNumIndices;
|
|
|
|
int n = nDstV - mi->nFirstVertId;
|
|
ushort *inds = &lb->m_SecIndices[mi->nFirstIndexId];
|
|
ushort *dinds = &rd->m_RP.m_SysRendIndices[nDstI];
|
|
int nInds = mi->nNumIndices;
|
|
rd->m_RP.m_RendNumIndices += nInds;
|
|
if (n >= 0)
|
|
{
|
|
int m = n | n<<16;
|
|
int nInds8 = nInds>>3;
|
|
sCopyInds8((uint *)dinds, (uint *)inds, nInds8, m);
|
|
nInds &= 7;
|
|
nInds8 <<= 3;
|
|
dinds += nInds8;
|
|
inds += nInds8;
|
|
}
|
|
for (i=0; i<nInds; i++)
|
|
{
|
|
dinds[i] = inds[i] + n;
|
|
}
|
|
|
|
UPipeVertex ptr = rd->m_RP.m_NextPtr;
|
|
int nVFormat = rd->m_RP.m_CurVFormat;
|
|
Matrix44 *mat = &pObj->m_Matrix;
|
|
/*Vec3d v = pObj->GetTranslation();
|
|
if ((v-Vec3d(810.5,1819,43.5)).Length() <= 0.9f)
|
|
{
|
|
int nnn = 0;
|
|
}*/
|
|
/*if (pObj->m_ObjFlags & FOB_SELECTED)
|
|
{
|
|
int nnn = 0;
|
|
}*/
|
|
int nNumVerts = mi->nNumVerts;
|
|
byte *OffsD, *OffsT, *OffsN, *OffsP;
|
|
int nD, nT, nN, nP;
|
|
byte *pData = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
|
SBufInfoTable *pOffs = &gBufInfoTable[lb->m_pSecVertBuffer->m_vertexformat];
|
|
int Stride = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
|
nP = Stride;
|
|
OffsP = &pData[mi->nFirstVertId*Stride];
|
|
switch (nVFormat)
|
|
{
|
|
case VERTEX_FORMAT_P3F_COL4UB_TEX2F:
|
|
{
|
|
// Used mostly for vegetations
|
|
if (pOffs->OffsColor)
|
|
{
|
|
OffsD = &OffsP[pOffs->OffsColor];
|
|
nD = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsD = (byte *)&lb->m_TempColors[mi->nFirstVertId];
|
|
nD = sizeof(UCol);
|
|
}
|
|
if (pOffs->OffsTC)
|
|
{
|
|
OffsT = &OffsP[pOffs->OffsTC];
|
|
nT = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsT = (byte *)&lb->m_TempTexCoords[mi->nFirstVertId];
|
|
nT = sizeof(SMRendTexVert);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *dst = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)ptr.Ptr;
|
|
rd->m_RP.m_NextPtr.Ptr = sCopyTransf_P_C_T(dst, mat, nNumVerts, OffsP, nP, OffsD, nD, OffsT, nT);
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F:
|
|
{
|
|
// Used mostly for vegetations
|
|
assert (pOffs->OffsColor);
|
|
if (pOffs->OffsColor)
|
|
{
|
|
OffsD = &OffsP[pOffs->OffsColor];
|
|
nD = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsD = (byte *)&lb->m_TempColors[mi->nFirstVertId];
|
|
nD = sizeof(UCol);
|
|
}
|
|
if (pOffs->OffsTC)
|
|
{
|
|
OffsT = &OffsP[pOffs->OffsTC];
|
|
nT = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsT = (byte *)&lb->m_TempTexCoords[mi->nFirstVertId];
|
|
nT = sizeof(SMRendTexVert);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F *dst = (struct_VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F *)ptr.Ptr;
|
|
rd->m_RP.m_NextPtr.Ptr = sCopyTransf_P_C_C1_T(dst, mat, nNumVerts, OffsP, nP, OffsD, nD, OffsT, nT);
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F_TEX2F:
|
|
{
|
|
// Used mostly for brushes/entities
|
|
if (pOffs->OffsTC)
|
|
{
|
|
OffsT = &OffsP[pOffs->OffsTC];
|
|
nT = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsT = (byte *)&lb->m_TempTexCoords[mi->nFirstVertId];
|
|
nT = sizeof(SMRendTexVert);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_TEX2F *dst = (struct_VERTEX_FORMAT_P3F_TEX2F *)ptr.Ptr;
|
|
rd->m_RP.m_NextPtr.Ptr = sCopyTransf_P_T(dst, mat, nNumVerts, OffsP, nP, OffsT, nT);
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F_N:
|
|
{
|
|
if (pOffs->OffsNormal)
|
|
{
|
|
OffsN = &pData[mi->nFirstVertId*Stride+pOffs->OffsNormal];
|
|
nN = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsN = (byte *)&lb->m_TempNormals[mi->nFirstVertId];
|
|
nN = sizeof(Vec3);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_N *dst = (struct_VERTEX_FORMAT_P3F_N *)ptr.Ptr;
|
|
for (i=0; i<mi->nNumVerts; i++, OffsP+=nP, OffsN+=nN)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst->normal = mat->TransformVectorOLD(*(Vec3 *)OffsN);
|
|
dst++;
|
|
}
|
|
rd->m_RP.m_NextPtr.Ptr = dst;
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F_N_TEX2F:
|
|
{
|
|
if (pOffs->OffsTC)
|
|
{
|
|
OffsT = &pData[mi->nFirstVertId*Stride+pOffs->OffsTC];
|
|
nT = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsT = (byte *)&lb->m_TempTexCoords[mi->nFirstVertId];
|
|
nT = sizeof(SMRendTexVert);
|
|
}
|
|
if (pOffs->OffsNormal)
|
|
{
|
|
OffsN = &pData[mi->nFirstVertId*Stride+pOffs->OffsNormal];
|
|
nN = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsN = (byte *)&lb->m_TempNormals[mi->nFirstVertId];
|
|
nN = sizeof(Vec3);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_N_TEX2F *dst = (struct_VERTEX_FORMAT_P3F_N_TEX2F *)ptr.Ptr;
|
|
for (i=0; i<mi->nNumVerts; i++, OffsP+=nP, OffsT+=nT, OffsN+=nN)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst->normal = mat->TransformVectorOLD(*(Vec3 *)OffsN);
|
|
dst->st[0] = *(float *)OffsT;
|
|
dst->st[1] = *(float *)(OffsT+4);
|
|
dst++;
|
|
}
|
|
rd->m_RP.m_NextPtr.Ptr = dst;
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F_N_COL4UB_TEX2F:
|
|
{
|
|
if (pOffs->OffsTC)
|
|
{
|
|
OffsT = &pData[mi->nFirstVertId*Stride+pOffs->OffsTC];
|
|
nT = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsT = (byte *)&lb->m_TempTexCoords[mi->nFirstVertId];
|
|
nT = sizeof(SMRendTexVert);
|
|
}
|
|
if (pOffs->OffsNormal)
|
|
{
|
|
OffsN = &pData[mi->nFirstVertId*Stride+pOffs->OffsNormal];
|
|
nN = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsN = (byte *)&lb->m_TempNormals[mi->nFirstVertId];
|
|
nN = sizeof(Vec3);
|
|
}
|
|
if (pOffs->OffsColor)
|
|
{
|
|
OffsD = &OffsP[pOffs->OffsColor];
|
|
nD = Stride;
|
|
}
|
|
else
|
|
{
|
|
OffsD = (byte *)&lb->m_TempColors[mi->nFirstVertId];
|
|
nD = sizeof(UCol);
|
|
}
|
|
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *dst = (struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *)ptr.Ptr;
|
|
for (i=0; i<mi->nNumVerts; i++, OffsP+=nP, OffsT+=nT, OffsN+=nN, OffsD+=nD)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst->color.dcolor = *(DWORD *)OffsD;
|
|
dst->normal = mat->TransformVectorOLD(*(Vec3 *)OffsN);
|
|
dst->st[0] = *(float *)OffsT;
|
|
dst->st[1] = *(float *)(OffsT+4);
|
|
dst++;
|
|
}
|
|
rd->m_RP.m_NextPtr.Ptr = dst;
|
|
}
|
|
break;
|
|
case VERTEX_FORMAT_P3F:
|
|
{
|
|
struct_VERTEX_FORMAT_P3F *dst = (struct_VERTEX_FORMAT_P3F *)ptr.Ptr;
|
|
for (i=0; i<mi->nNumVerts; i++, OffsP+=nP)
|
|
{
|
|
dst->xyz = mat->TransformPointOLD(*(Vec3 *)OffsP);
|
|
dst++;
|
|
}
|
|
rd->m_RP.m_NextPtr.Ptr = dst;
|
|
}
|
|
break;
|
|
default:
|
|
assert(false);
|
|
}
|
|
if (nFlags & (FHF_TANGENTS | FHF_LMTC))
|
|
{
|
|
rd->m_RP.m_MergedREs.AddElem(this);
|
|
rd->m_RP.m_MergedObjs.AddElem(pObj);
|
|
}
|
|
|
|
rd->m_RP.m_ObjFlags &= ~FOB_TRANS_MASK;
|
|
rd->m_RP.m_RendNumVerts += mi->nNumVerts;
|
|
}
|
|
|
|
void CREOcLeaf::mfPrepare()
|
|
{
|
|
CRenderer *rd = gRenDev;
|
|
|
|
{
|
|
//PROFILE_FRAME_TOTAL(Mesh_REPrepare_Ocleaf);
|
|
|
|
if (rd->m_RP.m_ClipPlaneEnabled && CRenderer::CV_r_cullbyclipplanes)
|
|
{
|
|
if (mfCullByClipPlane(rd->m_RP.m_pCurObject))
|
|
{
|
|
rd->EF_CheckOverflow(0, 0, this);
|
|
// Completly culled by plane (nothing to do with it)
|
|
rd->m_RP.m_pRE = NULL;
|
|
rd->m_RP.m_RendNumIndices = 0;
|
|
rd->m_RP.m_RendNumVerts = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
CMatInfo *mi = m_pChunk;
|
|
if (m_Flags & FCEF_MODIF_MASK)
|
|
{
|
|
m_Flags &= ~FCEF_MODIF_MASK;
|
|
lb->UpdateVidVertices(lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, lb->m_SecVertCount);
|
|
}
|
|
|
|
if (CRenderer::CV_r_rb_merge && !lb->m_bOnlyVideoBuffer)
|
|
{
|
|
if ((m_Flags & FCEF_MERGABLE) && mi->nNumVerts < abs(CRenderer::CV_r_rb_merge))
|
|
{
|
|
if (rd->m_RP.m_pCurObject->IsMergable())
|
|
{
|
|
SShader *ef = rd->m_RP.m_pShader;
|
|
SShaderTechnique *hs = rd->m_RP.m_pCurTechnique;
|
|
if (!hs || !(hs->m_Flags & FHF_NOMERGE))
|
|
{
|
|
rd->m_RP.m_FlagsPerFlush |= RBSI_MERGED;
|
|
mfFillRB(rd->m_RP.m_pCurObject);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rd->EF_CheckOverflow(0, 0, this);
|
|
|
|
rd->m_RP.m_pRE = this;
|
|
|
|
if (rd->m_RP.m_pShader->m_Flags2 & EF2_REDEPEND)
|
|
{
|
|
// Choose appropriate shader technique depend on some input parameters
|
|
SShader *ef = rd->m_RP.m_pShader;
|
|
if (ef->m_HWTechniques.Num())
|
|
{
|
|
int nHW = rd->EF_SelectHWTechnique(ef);
|
|
if (nHW >= 0)
|
|
rd->m_RP.m_pCurTechnique = ef->m_HWTechniques[nHW];
|
|
else
|
|
rd->m_RP.m_pCurTechnique = NULL;
|
|
}
|
|
else
|
|
rd->m_RP.m_pCurTechnique = NULL;
|
|
}
|
|
|
|
if (lb->m_nPrimetiveType == R_PRIMV_TRIANGLE_STRIP)
|
|
{
|
|
rd->m_RP.m_FirstVertex = 0;
|
|
rd->m_RP.m_FirstIndex = 0;
|
|
rd->m_RP.m_RendNumIndices = mi->nNumIndices;
|
|
rd->m_RP.m_RendNumVerts = mi->nNumVerts;
|
|
}
|
|
else
|
|
{
|
|
rd->m_RP.m_FirstVertex = mi->nFirstVertId;
|
|
rd->m_RP.m_FirstIndex = mi->nFirstIndexId;
|
|
rd->m_RP.m_RendNumIndices = mi->nNumIndices;
|
|
rd->m_RP.m_RendNumVerts = mi->nNumVerts;
|
|
if (lb->m_pVertexBuffer)
|
|
rd->m_RP.m_BaseVertex = lb->m_pVertexBuffer->m_fence;
|
|
}
|
|
}
|
|
}
|
|
|
|
list2<CMatInfo> *CREOcLeaf::mfGetMatInfoList()
|
|
{
|
|
return m_pBuffer->m_pMats;
|
|
}
|
|
|
|
int CREOcLeaf::mfGetMatId()
|
|
{
|
|
return m_pChunk->m_Id;
|
|
}
|
|
|
|
CMatInfo *CREOcLeaf::mfGetMatInfo()
|
|
{
|
|
return m_pChunk;
|
|
}
|
|
|
|
void CREOcLeaf::mfGenerateIndicesInsideFrustrum(SLightIndicies *li, CDLight *pDLight)
|
|
{
|
|
CCamera cam;
|
|
int i;
|
|
Vec3d mins, maxs;
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
byte *pD = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
|
int Stride = m_VertexSize[lb->m_pVertexBuffer->m_vertexformat];
|
|
Vec3d *v0, *v1, *v2;
|
|
|
|
Vec3d objectSpaceLightPosition;
|
|
TransformPosition(objectSpaceLightPosition, pDLight->m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
|
|
cam.SetPos(objectSpaceLightPosition);
|
|
Vec3d Angles(pDLight->m_ProjAngles[1], 0, pDLight->m_ProjAngles[2]+90.0f);
|
|
cam.SetAngle(Angles);
|
|
cam.Init(1, 1, (pDLight->m_fLightFrustumAngle*2)/180.0f*PI, 1024.0f, 1.0f, 0.0f);
|
|
cam.Update();
|
|
li->m_pIndiciesAttenFrustr.Free();
|
|
if (!cam.IsAABBVisibleFast( AABB(m_pBuffer->m_vBoxMin,m_pBuffer->m_vBoxMax) ))
|
|
return;
|
|
for (i=0; i<li->m_pIndicies.Num(); i+=3)
|
|
{
|
|
mins=SetMaxBB();
|
|
maxs=SetMinBB();
|
|
int i0 = li->m_pIndicies[i+0];
|
|
int i1 = li->m_pIndicies[i+1];
|
|
int i2 = li->m_pIndicies[i+2];
|
|
v0 = (Vec3d *)&pD[i0*Stride];
|
|
v1 = (Vec3d *)&pD[i1*Stride];
|
|
v2 = (Vec3d *)&pD[i2*Stride];
|
|
AddToBounds( (*v0), mins, maxs);
|
|
AddToBounds( (*v1), mins, maxs);
|
|
AddToBounds( (*v2), mins, maxs);
|
|
if (cam.IsAABBVisibleFast( AABB(mins,maxs) ))
|
|
{
|
|
li->m_pIndiciesAttenFrustr.AddElem(i0);
|
|
li->m_pIndiciesAttenFrustr.AddElem(i1);
|
|
li->m_pIndiciesAttenFrustr.AddElem(i2);
|
|
}
|
|
}
|
|
}
|
|
|
|
float sDistPointToSegment(Vec3d& P, Vec3d& SP0, Vec3d& SP1)
|
|
{
|
|
Vec3d v = SP1 - SP0;
|
|
Vec3d w = P - SP0;
|
|
|
|
float c1 = w.Dot(v);
|
|
if (c1 <= 0)
|
|
return GetDistance(P,SP0);
|
|
|
|
float c2 = v.Dot(v);
|
|
if (c2 <= c1)
|
|
return GetDistance(P,SP1);
|
|
|
|
float b = c1 / c2;
|
|
Vec3d Pb = SP0 + b * v;
|
|
return GetDistance(P,Pb);
|
|
}
|
|
|
|
void CREOcLeaf::mfGenerateIndicesForAttenuation(SLightIndicies *li, CDLight *pDLight)
|
|
{
|
|
TArray<unsigned short> NewInds;
|
|
int i;
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
byte *pD = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
|
int Stride = m_VertexSize[lb->m_pVertexBuffer->m_vertexformat];
|
|
Vec3d *v0, *v1, *v2;
|
|
Vec3d objectSpaceLightPosition;
|
|
TransformPosition(objectSpaceLightPosition, pDLight->m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
|
|
li->m_pIndiciesAttenFrustr.Free();
|
|
|
|
for (i=0; i<li->m_pIndicies.Num(); i+=3)
|
|
{
|
|
int i0 = li->m_pIndicies[i+0];
|
|
int i1 = li->m_pIndicies[i+1];
|
|
int i2 = li->m_pIndicies[i+2];
|
|
v0 = (Vec3d *)&pD[i0*Stride];
|
|
v1 = (Vec3d *)&pD[i1*Stride];
|
|
v2 = (Vec3d *)&pD[i2*Stride];
|
|
Plane pl;
|
|
pl.CalcPlane(*v0, *v1, *v2);
|
|
float fDist = pl.DistFromPlane(objectSpaceLightPosition);
|
|
Vec3d vProjPoint = objectSpaceLightPosition + pl.n * -fDist;
|
|
if (!Overlap::PointInTriangle(vProjPoint, *v0, *v1, *v2, pl.n))
|
|
{
|
|
float fDist0 = sDistPointToSegment(objectSpaceLightPosition, *v0, *v1);
|
|
float fDist1 = sDistPointToSegment(objectSpaceLightPosition, *v0, *v2);
|
|
float fDist2 = sDistPointToSegment(objectSpaceLightPosition, *v1, *v2);
|
|
fDist = min(fDist0, fDist1);
|
|
fDist = min(fDist, fDist2);
|
|
}
|
|
|
|
if (fDist <= pDLight->m_fRadius)
|
|
{
|
|
li->m_pIndiciesAttenFrustr.AddElem(i0);
|
|
li->m_pIndiciesAttenFrustr.AddElem(i1);
|
|
li->m_pIndiciesAttenFrustr.AddElem(i2);
|
|
}
|
|
}
|
|
}
|
|
|
|
SLightIndicies *CREOcLeaf::mfGetIndiciesForLight(CDLight *pDLight)
|
|
{
|
|
CLeafBuffer *lb = m_pBuffer;
|
|
CMatInfo *mi = m_pChunk;
|
|
int i, j;
|
|
|
|
ushort *pInds = lb->GetIndices(NULL);
|
|
|
|
if (!m_Faces || (m_Flags & FCEF_DYNAMIC))
|
|
return &gRenDev->m_RP.m_FakeLightIndices;
|
|
|
|
if (gRenDev->m_FS.m_bEnable)
|
|
{
|
|
float fDistToCam = mfMinDistanceToCamera(gRenDev->m_RP.m_pCurObject);
|
|
if (fDistToCam > gRenDev->m_FS.m_FogStart)
|
|
return &gRenDev->m_RP.m_FakeLightIndices;
|
|
}
|
|
|
|
if (!m_LIndicies)
|
|
m_LIndicies = new TArray <SLightIndicies*>;
|
|
|
|
Vec3d objPos, objAng;
|
|
float fObjScale;
|
|
objPos = gRenDev->m_RP.m_pCurObject ? gRenDev->m_RP.m_pCurObject->GetTranslation() : Vec3d(0,0,0);
|
|
objAng = Vec3d(0,0,0);
|
|
fObjScale = gRenDev->m_RP.m_pCurObject->GetScaleX();
|
|
|
|
SLightIndicies *li = NULL;
|
|
int Best = -1;
|
|
for (i=0; i<m_LIndicies->Num(); i++)
|
|
{
|
|
li = m_LIndicies->Get(i);
|
|
// if ((li->m_AssociatedLight.m_Flags & DLF_LIGHTTYPE_MASK) == (pDLight->m_Flags & DLF_LIGHTTYPE_MASK) && li->m_AssociatedLight.m_Origin == pDLight->m_Origin && li->m_AssociatedLight.m_Orientation.m_vForward == objPos && li->m_AssociatedLight.m_Orientation.m_vRight == objAng && li->m_AssociatedLight.m_Orientation.m_vUp[0] == fObjScale)
|
|
if ((li->m_AssociatedLight.m_Flags & DLF_LIGHTTYPE_MASK) == (pDLight->m_Flags & DLF_LIGHTTYPE_MASK) && IsEquivalent(li->m_AssociatedLight.m_Origin,pDLight->m_Origin) && IsEquivalent(li->m_AssociatedLight.m_Orientation.m_vForward,objPos) && IsEquivalent(li->m_AssociatedLight.m_Orientation.m_vRight,objAng) && li->m_AssociatedLight.m_Orientation.m_vUp[0] == fObjScale)
|
|
{
|
|
if (li->m_AssociatedLight.m_NumCM)
|
|
{
|
|
li->m_AssociatedLight.m_Id = gRenDev->GetFrameID();
|
|
if (pDLight->m_Flags & DLF_PROJECT)
|
|
{
|
|
bool bNeedList = false;
|
|
|
|
//if (li->m_AssociatedLight.m_ProjAngles != pDLight->m_ProjAngles || li->m_AssociatedLight.m_fLightFrustumAngle != pDLight->m_fLightFrustumAngle)
|
|
if ( !IsEquivalent(li->m_AssociatedLight.m_ProjAngles,pDLight->m_ProjAngles) || li->m_AssociatedLight.m_fLightFrustumAngle != pDLight->m_fLightFrustumAngle)
|
|
{
|
|
li->m_AssociatedLight.m_ProjAngles = pDLight->m_ProjAngles;
|
|
li->m_AssociatedLight.m_fLightFrustumAngle = pDLight->m_fLightFrustumAngle;
|
|
li->m_AssociatedLight.m_fLifeTime = gRenDev->m_RP.m_RealTime;
|
|
if (CRenderer::CV_r_cullgeometryforlights != 2)
|
|
{
|
|
li->m_AssociatedLight.m_NumCM &= ~2;
|
|
Best = i;
|
|
break;
|
|
}
|
|
}
|
|
// if static already
|
|
if (li->m_AssociatedLight.m_fLifeTime+1.0f < gRenDev->m_RP.m_RealTime)
|
|
{
|
|
if (!(li->m_AssociatedLight.m_NumCM & 2))
|
|
bNeedList = true;
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_cullgeometryforlights == 2)
|
|
bNeedList = true;
|
|
if (bNeedList)
|
|
{
|
|
STexPic *pic = (STexPic *)((ITexPic*)pDLight->m_pLightImage);
|
|
if (pic && (pic->m_Flags2 & FT2_CUBEASSINGLETEXTURE))
|
|
{
|
|
li->m_AssociatedLight.m_fLastTime = gRenDev->m_RP.m_RealTime;
|
|
li->m_AssociatedLight.m_ProjAngles = pDLight->m_ProjAngles;
|
|
li->m_AssociatedLight.m_fLightFrustumAngle = pDLight->m_fLightFrustumAngle;
|
|
li->m_AssociatedLight.m_NumCM |= 2;
|
|
mfGenerateIndicesInsideFrustrum(li, pDLight);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (pDLight->m_Flags & DLF_POINT)
|
|
{
|
|
bool bNeedList = false;
|
|
if (li->m_AssociatedLight.m_fRadius != pDLight->m_fRadius)
|
|
{
|
|
li->m_AssociatedLight.m_fRadius = pDLight->m_fRadius;
|
|
li->m_AssociatedLight.m_fLifeTime = gRenDev->m_RP.m_RealTime;
|
|
if (CRenderer::CV_r_cullgeometryforlights != 2)
|
|
{
|
|
Best = i;
|
|
li->m_AssociatedLight.m_NumCM &= ~2;
|
|
break;
|
|
}
|
|
}
|
|
// if static already
|
|
if (li->m_AssociatedLight.m_fLifeTime+1.0f < gRenDev->m_RP.m_RealTime)
|
|
{
|
|
if (!(li->m_AssociatedLight.m_NumCM & 2))
|
|
bNeedList = true;
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_cullgeometryforlights == 2)
|
|
bNeedList = true;
|
|
if (bNeedList)
|
|
{
|
|
li->m_AssociatedLight.m_fRadius = pDLight->m_fRadius;
|
|
li->m_AssociatedLight.m_NumCM |= 2;
|
|
mfGenerateIndicesForAttenuation(li, pDLight);
|
|
}
|
|
}
|
|
li->m_AssociatedLight.m_fLastTime = gRenDev->m_RP.m_RealTime;
|
|
if (li->m_AssociatedLight.m_NumCM & 2)
|
|
{
|
|
int nInds = li->m_pIndiciesAttenFrustr.Num();
|
|
if (nInds)
|
|
{
|
|
return li;
|
|
}
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
int nInds = li->m_pIndicies.Num();
|
|
if (nInds)
|
|
{
|
|
return li;
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Best = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Best < 0)
|
|
{
|
|
for (i=0; i<m_LIndicies->Num(); i++)
|
|
{
|
|
li = m_LIndicies->Get(i);
|
|
if ((li->m_AssociatedLight.m_Name[0] && !strcmp(li->m_AssociatedLight.m_Name, pDLight->m_Name)) || li->m_AssociatedLight.m_fLastTime+8 < gRenDev->m_RP.m_RealTime)
|
|
{
|
|
Best = i;
|
|
li->m_AssociatedLight.m_NumCM = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (Best < 0)
|
|
{
|
|
li = new SLightIndicies;
|
|
li->m_AssociatedLight.m_NumCM = 0;
|
|
m_LIndicies->AddElem(li);
|
|
memset(li, 0, sizeof(SLightIndicies));
|
|
}
|
|
}
|
|
else
|
|
li = m_LIndicies->Get(Best);
|
|
li->m_AssociatedLight.m_Flags = pDLight->m_Flags;
|
|
li->m_AssociatedLight.m_Orientation.m_vForward = objPos;
|
|
li->m_AssociatedLight.m_Orientation.m_vRight = objAng;
|
|
|
|
li->m_AssociatedLight.m_Orientation.m_vUp.Set(fObjScale,fObjScale,fObjScale);
|
|
|
|
li->m_AssociatedLight.m_Origin = pDLight->m_Origin;
|
|
li->m_AssociatedLight.m_ProjAngles = pDLight->m_ProjAngles;
|
|
li->m_AssociatedLight.m_fLightFrustumAngle = pDLight->m_fLightFrustumAngle;
|
|
strcpy(li->m_AssociatedLight.m_Name, pDLight->m_Name);
|
|
|
|
li->m_AssociatedLight.m_fLastTime = gRenDev->m_RP.m_RealTime;
|
|
li->m_AssociatedLight.m_fLifeTime = gRenDev->m_RP.m_RealTime;
|
|
if (!(li->m_AssociatedLight.m_NumCM & 1))
|
|
{
|
|
li->m_AssociatedLight.m_NumCM = 1;
|
|
li->m_pIndicies.Free();
|
|
|
|
Vec3d pos;
|
|
TransformPosition(pos, li->m_AssociatedLight.m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
|
|
|
|
switch(lb->m_nPrimetiveType)
|
|
{
|
|
case R_PRIMV_TRIANGLES:
|
|
{
|
|
int n = 0;
|
|
int nOffs = mi->nFirstIndexId;
|
|
int nNumInds = mi->nNumIndices;
|
|
for(i=0; i<nNumInds-2; i+=3, n++)
|
|
{
|
|
SMeshFace *mf = &m_Faces->Get(n);
|
|
Vec3d vDelt = pos - mf->m_Middle;
|
|
vDelt.NormalizeFast();
|
|
if ((vDelt | mf->m_Normal) > -0.5f)
|
|
{
|
|
unsigned short * face = &pInds[i+nOffs];
|
|
li->m_pIndicies.AddElem(face[0]);
|
|
li->m_pIndicies.AddElem(face[1]);
|
|
li->m_pIndicies.AddElem(face[2]);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case R_PRIMV_MULTI_GROUPS:
|
|
{
|
|
int nOffs = mi->nFirstIndexId;
|
|
unsigned int n;
|
|
for (j=0; j<mi->m_dwNumSections; j++)
|
|
{
|
|
SPrimitiveGroup *g = &mi->m_pPrimitiveGroups[j];
|
|
int incr;
|
|
switch (g->type)
|
|
{
|
|
case PT_LIST:
|
|
incr = 3;
|
|
break;
|
|
case PT_STRIP:
|
|
case PT_FAN:
|
|
incr = 1;
|
|
break;
|
|
}
|
|
int nf = g->nFirstFace;
|
|
int offs = g->offsIndex + nOffs;
|
|
for (n=0; n<g->numIndices-2; n+=incr)
|
|
{
|
|
int i0, i1, i2;
|
|
switch (g->type)
|
|
{
|
|
case PT_LIST:
|
|
i0 = pInds[offs+n];
|
|
i1 = pInds[offs+n+1];
|
|
i2 = pInds[offs+n+2];
|
|
break;
|
|
case PT_STRIP:
|
|
i0 = pInds[offs+n];
|
|
i1 = pInds[offs+n+1];
|
|
i2 = pInds[offs+n+2];
|
|
break;
|
|
case PT_FAN:
|
|
i0 = pInds[offs+0];
|
|
i1 = pInds[offs+n+1];
|
|
i2 = pInds[offs+n+2];
|
|
break;
|
|
}
|
|
// ignore degenerate triangle
|
|
if (i0==i1 || i0==i2 || i1==i2)
|
|
continue;
|
|
|
|
SMeshFace *mf = &m_Faces->Get(nf);
|
|
Vec3d vDelt = pos - mf->m_Middle;
|
|
vDelt.NormalizeFast();
|
|
if ((vDelt | mf->m_Normal) > -0.5f)
|
|
{
|
|
li->m_pIndicies.AddElem(i0);
|
|
li->m_pIndicies.AddElem(i1);
|
|
li->m_pIndicies.AddElem(i2);
|
|
}
|
|
nf++;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
li->m_pIndicies.Shrink();
|
|
}
|
|
if (li->m_AssociatedLight.m_NumCM & 2)
|
|
{
|
|
int nInds = li->m_pIndiciesAttenFrustr.Num();
|
|
if (nInds)
|
|
{
|
|
#if defined (DIRECT3D8) || defined (DIRECT3D9)
|
|
gRenDev->UpdateIndexBuffer(&li->m_IndexBuffer, &li->m_pIndiciesAttenFrustr[0], nInds);
|
|
#endif
|
|
return li;
|
|
}
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
int nInds = li->m_pIndicies.Num();
|
|
if (nInds)
|
|
{
|
|
#if defined (DIRECT3D8) || defined (DIRECT3D9)
|
|
gRenDev->UpdateIndexBuffer(&li->m_IndexBuffer, &li->m_pIndicies[0], nInds);
|
|
#endif
|
|
return li;
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
float CREOcLeaf::mfMinDistanceToCamera(CCObject *pObj)
|
|
{
|
|
Vec3d pos = gRenDev->GetCamera().GetPos();
|
|
CMatInfo *mi = m_pChunk;
|
|
float fDist = 0;
|
|
if (!mi->m_fRadius)
|
|
{
|
|
Vec3d vMins, vMaxs, vCenterRE;
|
|
mfGetBBox(vMins, vMaxs);
|
|
vCenterRE = (vMins + vMaxs) * 0.5f;
|
|
vCenterRE += pObj->GetTranslation();
|
|
float fRadRE = (vMaxs - vMins).GetLength() * 0.5f;
|
|
float fScale = pObj->m_Matrix(0,0)*pObj->m_Matrix(0,0) + pObj->m_Matrix(0,1)*pObj->m_Matrix(0,1) + pObj->m_Matrix(0,2)*pObj->m_Matrix(0,2);
|
|
fScale = cryISqrtf(fScale);
|
|
fDist = (pos - vCenterRE).GetLength();
|
|
fDist = fDist - fRadRE / fScale;
|
|
}
|
|
else
|
|
{
|
|
Vec3d vMid = mi->m_vCenter;
|
|
|
|
vMid += pObj->GetTranslation();
|
|
float fScale = pObj->m_Matrix(0,0)*pObj->m_Matrix(0,0) + pObj->m_Matrix(0,1)*pObj->m_Matrix(0,1) + pObj->m_Matrix(0,2)*pObj->m_Matrix(0,2);
|
|
fScale = cryISqrtf(fScale);
|
|
fDist = (pos - vMid).GetLength();
|
|
fDist -= mi->m_fRadius / fScale * 2.0f;
|
|
}
|
|
if (fDist < 0.25f)
|
|
fDist = 0.25f;
|
|
|
|
return fDist;
|
|
}
|
|
|
|
bool CREOcLeaf::mfCheckUpdate(int nVertFormat, int Flags)
|
|
{
|
|
//PROFILE_FRAME(Mesh_CheckUpdate);
|
|
|
|
CLeafBuffer *lb = m_pBuffer->GetVertexContainer();
|
|
|
|
bool bNeedAddNormals = false;
|
|
if ((Flags & SHPF_NORMALS) && g_VertFormatNormalOffsets[lb->m_pSecVertBuffer->m_vertexformat] < 0)
|
|
bNeedAddNormals = true;
|
|
|
|
if (gRenDev->m_RP.m_pShader && (gRenDev->m_RP.m_pShader->m_Flags2 & EF2_DEFAULTVERTEXFORMAT))
|
|
nVertFormat = lb->m_nVertexFormat;
|
|
bool bWasReleased = m_pBuffer->CheckUpdate(nVertFormat, Flags, bNeedAddNormals);
|
|
|
|
if (!lb->m_pVertexBuffer)
|
|
return false;
|
|
|
|
#if defined (DIRECT3D8) || defined (DIRECT3D9)
|
|
gRenDev->m_RP.m_CurVFormat = lb->m_pVertexBuffer->m_vertexformat;
|
|
#endif
|
|
|
|
#ifndef PIPE_USE_INSTANCING
|
|
if((Flags & SHPF_LMTC) && gRenDev->m_RP.m_pCurObject->m_pLMTCBufferO)
|
|
{
|
|
lb = gRenDev->m_RP.m_pCurObject->m_pLMTCBufferO;
|
|
if (!lb->m_pVertexBuffer)
|
|
lb->UpdateVidVertices(lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, lb->m_SecVertCount);
|
|
if (!lb->m_pVertexBuffer)
|
|
return false;
|
|
}
|
|
#else
|
|
if((Flags & SHPF_LMTC))
|
|
{
|
|
CCObject *pObj = gRenDev->m_RP.m_pCurObject;
|
|
int nObj = 0;
|
|
while (true)
|
|
{
|
|
if (pObj->m_pLMTCBufferO)
|
|
{
|
|
lb = pObj->m_pLMTCBufferO;
|
|
lb->Unlink();
|
|
lb->Link(&CLeafBuffer::m_Root);
|
|
if (!lb->m_pVertexBuffer)
|
|
lb->UpdateVidVertices(lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, lb->m_SecVertCount);
|
|
if (!lb->m_pVertexBuffer)
|
|
return false;
|
|
}
|
|
nObj++;
|
|
if (nObj >= gRenDev->m_RP.m_MergedObjects.Num())
|
|
break;
|
|
pObj = gRenDev->m_RP.m_MergedObjects[nObj];
|
|
}
|
|
}
|
|
#endif
|
|
if (bWasReleased && !lb->m_pSecVertBuffer && !(Flags & FHF_FORANIM) && lb->m_pVertexBuffer)
|
|
{
|
|
// Callback function can change buffer sizes
|
|
gRenDev->m_RP.m_FirstVertex = m_pChunk->nFirstVertId;
|
|
gRenDev->m_RP.m_FirstIndex = m_pChunk->nFirstIndexId;
|
|
gRenDev->m_RP.m_RendNumIndices = m_pChunk->nNumIndices;
|
|
gRenDev->m_RP.m_RendNumVerts = m_pChunk->nNumVerts;
|
|
if (gRenDev->m_RP.m_pCurObject && gRenDev->m_RP.m_pCurObject->m_pCharInstance)
|
|
{
|
|
PROFILE_FRAME(Mesh_CheckUpdateSkinning);
|
|
double time0 = 0;
|
|
ticks(time0);
|
|
gRenDev->m_RP.m_pCurObject->m_pCharInstance->ProcessSkinning(Vec3(zero),gRenDev->m_RP.m_pCurObject->m_Matrix, gRenDev->m_RP.m_pCurObject->m_nTemplId, gRenDev->m_RP.m_pCurObject->m_nLod, true);
|
|
unticks(time0);
|
|
gRenDev->m_RP.m_PS.m_fSkinningTime += (float)(time0*1000.0*g_SecondsPerCycle);
|
|
}
|
|
}
|
|
#ifndef OPENGL
|
|
if (!m_pBuffer->m_Indices.m_VData)
|
|
{
|
|
//assert(!m_pChunk->nNumIndices);
|
|
return false;
|
|
}
|
|
#else
|
|
if (!m_pBuffer->m_SecIndices.Num())
|
|
{
|
|
#ifndef WIN64
|
|
//assert(!m_pChunk->nNumIndices);
|
|
#endif //WIN64
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
static _inline byte *sGetBuf(CLeafBuffer *lb, int *Stride, int Stream, int Flags)
|
|
{
|
|
byte *pD;
|
|
if (Flags & FGP_WAIT)
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0, Stream);
|
|
if (!(Flags & FGP_SRC))
|
|
{
|
|
pD = (byte*)lb->m_pVertexBuffer->m_VS[Stream].m_VData;
|
|
gRenDev->m_RP.m_nCurBufferID = lb->m_pVertexBuffer->m_VS[Stream].m_VertBuf.m_nID;
|
|
}
|
|
else
|
|
{
|
|
if (!lb->m_pSecVertBuffer)
|
|
pD = NULL;
|
|
else
|
|
pD = (byte *)lb->m_pSecVertBuffer->m_VS[Stream].m_VData;
|
|
}
|
|
if (!pD && !gRenDev->m_RP.m_nCurBufferID)
|
|
return pD;
|
|
if (Stream == VSF_GENERAL)
|
|
*Stride = m_VertexSize[lb->m_nVertexFormat];
|
|
else
|
|
if (Stream == VSF_TANGENTS)
|
|
*Stride = sizeof(SPipTangents);
|
|
else
|
|
assert(0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if (Flags & FGP_REAL)
|
|
pD = &pD[Offs];
|
|
|
|
return pD;
|
|
}
|
|
|
|
void *CREOcLeaf::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
|
|
{
|
|
SBufInfoTable *pOffs;
|
|
CLeafBuffer *lb = m_pBuffer->GetVertexContainer();
|
|
byte *pD;
|
|
|
|
switch(ePT)
|
|
{
|
|
case eSrcPointer_Vert:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
gRenDev->m_RP.m_nCurBufferOffset = 0;
|
|
return pD;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
if (pOffs->OffsTC)
|
|
{
|
|
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsTC;
|
|
return &pD[pOffs->OffsTC];
|
|
}
|
|
else
|
|
{
|
|
if (!(Flags & FGP_SRC))
|
|
{
|
|
Warning( 0,0,"Error: Missed texcoord pointer for shader '%s'", gRenDev->m_RP.m_pShader->m_Name.c_str());
|
|
return NULL;
|
|
}
|
|
*Stride = sizeof(SMRendTexVert);
|
|
if (Flags & FGP_REAL)
|
|
return &lb->m_TempTexCoords[gRenDev->m_RP.m_FirstVertex];
|
|
else
|
|
return lb->m_TempTexCoords;
|
|
}
|
|
break;
|
|
case eSrcPointer_TexLM:
|
|
if(gRenDev->m_RP.m_pCurObject && gRenDev->m_RP.m_pCurObject->m_pLMTCBufferO)
|
|
{ // separate stream for lightmaps
|
|
CVertexBuffer * pVideoBuffer = gRenDev->m_RP.m_pCurObject->m_pLMTCBufferO->m_pVertexBuffer;
|
|
assert(pVideoBuffer->m_vertexformat==VERTEX_FORMAT_TEX2F); // M.M.
|
|
*Stride = m_VertexSize[pVideoBuffer->m_vertexformat];
|
|
gRenDev->m_RP.m_nCurBufferOffset = 0;
|
|
gRenDev->m_RP.m_nCurBufferID = pVideoBuffer->m_VS[VSF_GENERAL].m_VertBuf.m_nID;
|
|
return(pVideoBuffer->m_VS[VSF_GENERAL].m_VData);
|
|
}
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
gRenDev->m_RP.m_nCurBufferOffset = 0;
|
|
return pD;
|
|
case eSrcPointer_Normal:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
if (pOffs->OffsNormal)
|
|
{
|
|
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsNormal;
|
|
return &pD[pOffs->OffsNormal];
|
|
}
|
|
else
|
|
{
|
|
if (!(Flags & FGP_SRC))
|
|
{
|
|
Warning( 0,0,"Error: Missed normal pointer for shader '%s'", gRenDev->m_RP.m_pShader->m_Name.c_str());
|
|
return NULL;
|
|
}
|
|
*Stride = sizeof(Vec3d);
|
|
if (Flags & FGP_REAL)
|
|
return &lb->m_TempNormals[gRenDev->m_RP.m_FirstVertex];
|
|
else
|
|
return lb->m_TempNormals;
|
|
}
|
|
return &pD[0];
|
|
case eSrcPointer_Binormal:
|
|
pD = sGetBuf(lb, Stride, VSF_TANGENTS, Flags);
|
|
gRenDev->m_RP.m_nCurBufferOffset = 12;
|
|
return &pD[12];
|
|
case eSrcPointer_TNormal:
|
|
pD = sGetBuf(lb, Stride, VSF_TANGENTS, Flags);
|
|
gRenDev->m_RP.m_nCurBufferOffset = 24;
|
|
return &pD[24];
|
|
case eSrcPointer_Tangent:
|
|
pD = sGetBuf(lb, Stride, VSF_TANGENTS, Flags);
|
|
gRenDev->m_RP.m_nCurBufferOffset = 0;
|
|
return &pD[0];
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsColor;
|
|
return &pD[pOffs->OffsColor];
|
|
case eSrcPointer_SecColor:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsSecColor;
|
|
return &pD[pOffs->OffsSecColor];
|
|
|
|
|
|
case eSrcPointer_LightVector:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_LightVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELV) && Dst != eSrcPointer_LightVector)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
Vec3d *lv = gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight];
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcLight)
|
|
{
|
|
mFrameCalcLight = gRenDev->m_RP.m_Frame;
|
|
mMaskLight0 = 0;
|
|
}
|
|
if (!(mMaskLight0 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight0 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight])
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcLightVectors(Dst, *Stride);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_LightVector_Terrain:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_LightVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELV) && Dst != eSrcPointer_LightVector_Terrain)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
Vec3d *lv = gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight];
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcLight)
|
|
{
|
|
mFrameCalcLight = gRenDev->m_RP.m_Frame;
|
|
mMaskLight0 = 0;
|
|
}
|
|
if (!(mMaskLight0 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight0 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight])
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcLightVectors_Terrain(Dst, *Stride);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_NormLightVector:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_LightVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELV) && Dst != eSrcPointer_NormLightVector)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
Vec3d *lv = gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight];
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
if (Type == GL_FLOAT)
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
float fInvLen=1.0f/cry_sqrtf(lv->x*lv->x+lv->y*lv->y+lv->z*lv->z);
|
|
fd[0] = lv->x * fInvLen;
|
|
fd[1] = lv->y * fInvLen;
|
|
fd[2] = lv->z * fInvLen;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
byte *fd = (byte *)Dst;
|
|
float fInvLen=1.0f/cry_sqrtf(lv->x*lv->x+lv->y*lv->y+lv->z*lv->z);
|
|
fd[0] = (byte)(lv->x * fInvLen * 128.0f + 128.0f);
|
|
fd[1] = (byte)(lv->y * fInvLen * 128.0f + 128.0f);
|
|
fd[2] = (byte)(lv->z * fInvLen * 128.0f + 128.0f);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcLight)
|
|
{
|
|
mFrameCalcLight = gRenDev->m_RP.m_Frame;
|
|
mMaskLight0 = 0;
|
|
}
|
|
if (!(mMaskLight0 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight0 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pLightVectors[gRenDev->m_RP.m_nCurLight])
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcNormLightVectors(Dst, *Stride, Type);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_HalfAngleVector:
|
|
{
|
|
byte *dst;
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_HalfAngleVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPAREHAV) && Dst != eSrcPointer_HalfAngleVector)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
Vec3d *lv = gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight];
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcHalfAngle)
|
|
{
|
|
mFrameCalcHalfAngle = gRenDev->m_RP.m_Frame;
|
|
mMaskLight1 = 0;
|
|
}
|
|
if (!(mMaskLight1 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight1 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight])
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcHalfAngles(Type, Dst, *Stride);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_HalfAngleVector_Terrain:
|
|
{
|
|
byte *dst;
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_HalfAngleVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPAREHAV) && Dst != eSrcPointer_HalfAngleVector_Terrain)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
Vec3d *lv = gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight];
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcHalfAngle)
|
|
{
|
|
mFrameCalcHalfAngle = gRenDev->m_RP.m_Frame;
|
|
mMaskLight1 = 0;
|
|
}
|
|
if (!(mMaskLight1 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight1 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight])
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcHalfAngles_Terrain(Type, Dst, *Stride);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_LAttenuationSpec0:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_LAttenuationSpec0:
|
|
dst = (byte *)&gRenDev->m_RP.m_pLAttenSpec0[0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELAS0) && Dst != eSrcPointer_LAttenuationSpec0)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
Vec3d *lv = gRenDev->m_RP.m_pLAttenSpec0;
|
|
if (Type == GL_FLOAT)
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
byte *fd = Dst;
|
|
fd[0] = (byte)(lv->x * 255.0f);
|
|
fd[1] = (byte)(lv->y * 255.0f);
|
|
fd[2] = (byte)(lv->z * 255.0f);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcLAttenSpec0)
|
|
{
|
|
mFrameCalcLAttenSpec0 = gRenDev->m_RP.m_Frame;
|
|
mMaskLight2 = 0;
|
|
}
|
|
if (!(mMaskLight2 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight2 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pLAttenSpec0)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
int StrLV;
|
|
byte *lv = (byte *)SRendItem::mfGetPointerCommon(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
|
|
if (dst)
|
|
SRendItem::mfCalcLAttenuationSpec0(Dst, *Stride, lv, StrLV, Type);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_LAttenuationSpec1:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_LAttenuationSpec1:
|
|
dst = (byte *)&gRenDev->m_RP.m_pLAttenSpec1[0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_HalfAngleVector:
|
|
dst = (byte *)&gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight][0];
|
|
*Stride = sizeof(Vec3d);
|
|
break;
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELAS1) && Dst != eSrcPointer_LAttenuationSpec1)
|
|
{
|
|
byte *Dst = dst;
|
|
int str = *Stride;
|
|
if (!(Flags & FGP_REAL))
|
|
Dst = &Dst[Offs];
|
|
Vec3d *lv = gRenDev->m_RP.m_pLAttenSpec1;
|
|
if (Type == GL_FLOAT)
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
float *fd = (float *)Dst;
|
|
fd[0] = lv->x;
|
|
fd[1] = lv->y;
|
|
fd[2] = lv->z;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, Dst+=str, lv++)
|
|
{
|
|
byte *fd = Dst;
|
|
fd[0] = uchar(lv->x * 255.0f);
|
|
fd[1] = uchar(lv->y * 255.0f);
|
|
fd[2] = uchar(lv->z * 255.0f);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcLAttenSpec1)
|
|
{
|
|
mFrameCalcLAttenSpec1 = gRenDev->m_RP.m_Frame;
|
|
mMaskLight3 = 0;
|
|
}
|
|
if (!(mMaskLight3 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight3 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if ((Flags & FGP_REAL) || dst == (byte *)gRenDev->m_RP.m_pLAttenSpec1)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
int StrLV;
|
|
byte *lv = (byte *)SRendItem::mfGetPointerCommon(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
|
|
if (dst)
|
|
SRendItem::mfCalcLAttenuationSpec1(Dst, *Stride, lv, StrLV, Type);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_Refract:
|
|
{
|
|
byte *dst;
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcRefract)
|
|
{
|
|
mFrameCalcRefract = gRenDev->m_RP.m_Frame;
|
|
byte *Dst;
|
|
if (Flags & FGP_REAL)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcRefractVectors(Type, Dst, *Stride);
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_Project:
|
|
{
|
|
byte *dst;
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
static float Smat[16] =
|
|
{
|
|
0.5f, 0, 0, 0,
|
|
0, 0.5f, 0, 0,
|
|
0, 0, 0.5f, 0,
|
|
0.5f, 0.5f, 0.5f, 1.0f
|
|
};
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcProject)
|
|
{
|
|
mFrameCalcProject = gRenDev->m_RP.m_Frame;
|
|
float fRefract = -1000.0f;
|
|
if (gRenDev->m_RP.m_pCurObject)
|
|
fRefract = gRenDev->m_RP.m_pCurObject->m_fRefract;
|
|
byte *Dst;
|
|
if (Flags & FGP_REAL)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
float matProj[16], matView[16], m1[16], m2[16];
|
|
gRenDev->GetProjectionMatrix(matProj);
|
|
gRenDev->GetModelViewMatrix(matView);
|
|
multMatrices(m2, Smat, matProj);
|
|
multMatrices(m1, m2, matView);
|
|
SRendItem::mfCalcProjectVectors(Type, m1, fRefract, Dst, *Stride);
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_ProjectTexture:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcProject)
|
|
{
|
|
mFrameCalcProject = gRenDev->m_RP.m_Frame;
|
|
byte *Dst;
|
|
if (Flags & FGP_REAL)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SShaderPass *sl = gRenDev->m_RP.m_CurrPass;
|
|
int nl = Flags >> FGP_STAGE_SHIFT;
|
|
if (nl < sl->m_TUnits.Num())
|
|
{
|
|
SShaderTexUnit *tl = &sl->m_TUnits[nl];
|
|
float *matr = tl->m_TexPic->m_Matrix;
|
|
if (matr)
|
|
SRendItem::mfCalcProjectVectors(Type, matr, 0.5f, Dst, *Stride);
|
|
}
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
case eSrcPointer_Attenuation:
|
|
{
|
|
byte *dst;
|
|
switch (Dst)
|
|
{
|
|
case eSrcPointer_Tex:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
case eSrcPointer_Color:
|
|
pD = sGetBuf(lb, Stride, VSF_GENERAL, Flags);
|
|
pOffs = &gBufInfoTable[lb->m_pVertexBuffer->m_vertexformat];
|
|
dst = &pD[pOffs->OffsTC];
|
|
break;
|
|
}
|
|
if (!(Flags & FGP_NOCALC))
|
|
{
|
|
if (!(Flags & (FGP_SRC | FGP_WAIT)))
|
|
gRenDev->UpdateBuffer(lb->m_pVertexBuffer, NULL, 0, false, 0);
|
|
int Offs = gRenDev->m_RP.m_FirstVertex * (*Stride);
|
|
if (gRenDev->m_RP.m_Frame != mFrameCalcAtten)
|
|
{
|
|
mFrameCalcAtten = gRenDev->m_RP.m_Frame;
|
|
mMaskLight4 = 0;
|
|
}
|
|
if (!(mMaskLight4 & (1<<gRenDev->m_RP.m_nCurLight)))
|
|
{
|
|
mMaskLight4 |= (1<<gRenDev->m_RP.m_nCurLight);
|
|
byte *Dst;
|
|
if (Flags & FGP_REAL)
|
|
Dst = dst;
|
|
else
|
|
Dst = &dst[Offs];
|
|
SRendItem::mfCalcLightAttenuation(Type, Dst, *Stride);
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(false);
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#include "../NvTriStrip/NVTriStrip.h"
|
|
|
|
void CREOcLeaf::mfGetPlane(Plane& pl)
|
|
{
|
|
CLeafBuffer *lb = m_pBuffer->GetVertexContainer();
|
|
|
|
byte *p = (byte *)lb->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
|
int size = m_VertexSize[lb->m_pSecVertBuffer->m_vertexformat];
|
|
|
|
ushort *inds;
|
|
inds = &lb->GetIndices(NULL)[0]+m_pChunk->nFirstIndexId;
|
|
float *f0 = (float *)&p[inds[0]*size];
|
|
float *f1 = (float *)&p[inds[1]*size];
|
|
float *f2 = (float *)&p[inds[2]*size];
|
|
Vec3d p0 = Vec3d(f0[0], f0[1], f0[2]);
|
|
Vec3d p1 = Vec3d(f1[0], f1[1], f1[2]);
|
|
Vec3d p2 = Vec3d(f2[0], f2[1], f2[2]);
|
|
pl.CalcPlane(p2, p1, p0);
|
|
}
|