Files
FC1/RenderDll/Common/RendElements/RendElement.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1524 lines
45 KiB
C++

/*=============================================================================
RendElement.cpp : common RE functions.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#include "RenderPCH.h"
//TArray<CRendElement *> CRendElement::m_AllREs;
CRendElement CRendElement::m_RootGlobal;
//===============================================================
TArray <CFColor> gCurLightStyles;
TArray<SRendItemPre> SRendItem::m_RendItems[NUMRI_LISTS];
int SRendItem::m_RecurseLevel;
int SRendItem::m_StartRI[8][NUMRI_LISTS];
int SRendItem::m_EndRI[8][NUMRI_LISTS];
static _inline int Compare(SRendItemPre &a, SRendItemPre &b)
{
#ifndef PIPE_USE_INSTANCING
if (a.SortVal.SortVal<b.SortVal.SortVal)
return -1;
else
if (a.SortVal.SortVal>b.SortVal.SortVal)
return 1;
else
return 0;
#else
if (a.SortVal.i.High<b.SortVal.i.High)
return -1;
if (a.SortVal.i.High>b.SortVal.i.High)
return 1;
if (a.ObjSort < b.ObjSort)
return -1;
if (a.ObjSort > b.ObjSort)
return 1;
if (a.Item < b.Item)
return -1;
if (a.Item > b.Item)
return 1;
if (a.DynLMask < b.DynLMask)
return -1;
if (a.DynLMask > b.DynLMask)
return 1;
int nSa = a.SortVal.i.Low&~(0xfff<<20);
int nSb = b.SortVal.i.Low&~(0xfff<<20);
if (nSa < nSb)
return -1;
if (nSa > nSb)
return 1;
return 0;
#endif
}
static _inline int Compare(SRendItemStenc &a, SRendItemStenc &b)
{
#ifndef PIPE_USE_INSTANCING
if (a.SortVal.SortVal<b.SortVal.SortVal)
return -1;
else
if (a.SortVal.SortVal>b.SortVal.SortVal)
return 1;
else
return 0;
#else
if (a.SortVal.i.High<b.SortVal.i.High)
return -1;
if (a.SortVal.i.High>b.SortVal.i.High)
return 1;
if (a.ObjSort < b.ObjSort)
return -1;
if (a.ObjSort > b.ObjSort)
return 1;
uint Itema = (uint)a.Item;
uint Itemb = (uint)b.Item;
if (a.ObjSort & FOB_IGNOREREPOINTER)
{
int nObj = (a.SortVal.i.Low>>20) & 0xfff;
CCObject *pObj = gRenDev->m_RP.m_VisObjects[nObj];
Itema = FtoI(pObj->m_SortId);
}
if (b.ObjSort & FOB_IGNOREREPOINTER)
{
int nObj = (b.SortVal.i.Low>>20) & 0xfff;
CCObject *pObj = gRenDev->m_RP.m_VisObjects[nObj];
Itemb = FtoI(pObj->m_SortId);
}
if (Itema < Itemb)
return -1;
if (Itema > Itemb)
return 1;
if (a.DynLMask < b.DynLMask)
return -1;
if (a.DynLMask > b.DynLMask)
return 1;
int nSa = a.SortVal.i.Low&~(0xfff<<20);
int nSb = b.SortVal.i.Low&~(0xfff<<20);
if (nSa<nSb)
return -1;
if (nSa>nSb)
return 1;
return 0;
#endif
}
static _inline int Compare(SRendItem &a, SRendItem &b)
{
float fDistA = a.fDist;
float fDistB = b.fDist;
if (fDistA+0.01f < fDistB)
return 1;
else
if (fDistA > fDistB+0.01f)
return -1;
else
return 0;
}
/*static _inline int Compare(SRendItemPre &a, SRendItemPre &b)
{
if (a.SortVal.SortVal<b.SortVal.SortVal)
return -1;
else
if (a.SortVal.SortVal>b.SortVal.SortVal)
return 1;
else
return 0;
}*/
void SRendItem::mfSort(SRendItemPre *First, int Num)
{
::Sort(First, Num);
}
void SRendItem::mfSortForStencil(SRendItemPre *First, int Num)
{
::Sort((SRendItemStenc *)First, Num);
}
void SRendItem::mfSortByDist(SRendItemPre *First, int Num)
{
CRenderer *rd = gRenDev;
int i;
for (i=0; i<Num; i++)
{
SRendItemPre *pRI = &First[i];
#ifndef PIPE_USE_INSTANCING
int nObject = (pRI->SortVal.i.High>>15) & 0x7ff;
#else
int nObject = (pRI->SortVal.i.Low>>20) & 0xfff;
#endif
CCObject *pObj = rd->m_RP.m_VisObjects[nObject];
float fAddDist = pObj->m_SortId+0.05f*(i&0x1f);
//SShader *pSH = SShader::m_Shaders_known[(pRI->SortVal.i.High>>14) & 0xfff];
pRI->fDist = pRI->Item->mfDistanceToCameraSquared(*pObj) + fAddDist + pRI->Item->m_SortId;
}
::Sort((SRendItem *)First, Num);
/*if (rd->m_LogFile)
rd->Logv(SRendItem::m_RecurseLevel, "*** Start Dist sort ***\n");
for (int i=0; i<Num; i++)
{
SRendItemPre *pRI = &First[i];
#ifndef PIPE_USE_INSTANCING
int nObject = (pRI->SortVal.i.High>>15) & 0x7ff;
#else
int nObject = (pRI->SortVal.i.Low>>20) & 0xfff;
#endif
CCObject *pObj = rd->m_RP.m_VisObjects[nObject];
float fAddDist = pObj->m_SortId;
SShader *pSH = SShader::m_Shaders_known[(pRI->SortVal.i.High>>14) & 0xfff];
float fDistNew = pRI->Item->mfDistanceToCameraSquared(*pObj);
Vec3d vObj = pObj->GetTranslation();
if (rd->m_LogFile)
rd->Logv(SRendItem::m_RecurseLevel, "Item %d, Dist: %.3f, ObjDist: %.3f, REDist: %d, CamDist: %.3f, Sh: %s, Obj: %d [%.3f, %.3f, %.3f]\n", i, pRI->fDist, fAddDist, pRI->Item->m_SortId, fDistNew, pSH->m_Name.c_str(), nObject, vObj.x, vObj.y, vObj.z);
}
if (rd->m_LogFile)
rd->Logv(SRendItem::m_RecurseLevel, "*** End Dist sort ***\n");*/
}
void SRendItem::mfSortByLight(SRendItemPre *First, int Num)
{
::Sort((SRendItemLight *)First, Num);
}
static _inline int Compare(SRendItemPreprocess &a, SRendItemPreprocess &b)
{
CCObject *obj1 = a.m_Object;
CCObject *obj2 = b.m_Object;
int Flags1 = obj1->m_ObjFlags & FOB_CUBE_MASK;
int Flags2 = obj2->m_ObjFlags & FOB_CUBE_MASK;
if (Flags1 < Flags2)
return -1;
if (Flags1 > Flags2)
return 1;
if (a.SortVal.SortVal < b.SortVal.SortVal)
return -1;
else
if (a.SortVal.SortVal > b.SortVal.SortVal)
return 1;
else
return 0;
}
void SRendItemPreprocess::mfSort(SRendItemPreprocess *First, int Num)
{
::Sort(First, Num);
}
//============================================================================
void CRendElement::mfPrepare()
{
}
CMatInfo *CRendElement::mfGetMatInfo() {return NULL;}
list2<CMatInfo> *CRendElement::mfGetMatInfoList() {return NULL;}
int CRendElement::mfGetMatId() {return -1;}
bool CRendElement::mfCull(CCObject *obj) {return false;}
bool CRendElement::mfCull(CCObject *obj, SShader *ef) {return false;}
void CRendElement::mfReset() {}
bool CRendElement::mfCullByClipPlane(CCObject *pObj) { return false; }
const char *CRendElement::mfTypeString()
{
switch(m_Type)
{
case eDATA_Sky:
return "Sky";
case eDATA_Beam:
return "Beam";
break;
case eDATA_Poly:
return "Poly";
break;
case eDATA_Curve:
return "Curve";
break;
case eDATA_MotModel:
return "MotModel";
break;
case eDATA_MeshModel:
return "MeshModel";
break;
case eDATA_PolyBlend:
return "PolyBlend";
break;
case eDATA_AnimPolyBlend:
return "AnimPolyBlend";
break;
case eDATA_ClientPoly:
return "ClientPoly";
break;
case eDATA_ClientPoly2D:
return "ClientPoly2D";
break;
case eDATA_ParticleSpray:
return "ParticleSpray";
break;
case eDATA_TriMesh:
return "TriMesh";
break;
case eDATA_TriMeshShadow:
return "TriMeshShadow";
break;
case eDATA_Prefab:
return "Prefab";
break;
case eDATA_Flare:
return "Flare";
break;
case eDATA_FlareGeom:
return "FlareGeom";
break;
case eDATA_FlareProp:
return "FlareProp";
break;
case eDATA_Tree:
return "Tree";
break;
case eDATA_Tree_Leaves:
return "Tree_Leaves";
break;
case eDATA_Tree_Branches:
return "Tree_Branches";
break;
case eDATA_Terrain:
return "Terrain";
break;
case eDATA_SkyZone:
return "SkyZone";
break;
case eDATA_OcLeaf:
return "OcLeaf";
break;
case eDATA_FlashBang:
return "FlashBang";
break;
case eDATA_TerrainSector:
return "TerrainSector";
break;
case eDATA_2DQuad:
return "2DQuad";
break;
case eDATA_FarTreeSprites:
return "FarTreeSprites";
break;
case eDATA_AnimModel:
return "AnimModel";
break;
case eDATA_MotionBlur:
return "MotionBlur";
break;
case eDATA_ShadowMapGen:
return "ShadowMapGen";
break;
case eDATA_TerrainDetailTextureLayers:
return "TerrainDetailTextureLayers";
break;
case eDATA_TerrainParticles:
return "TerrainParticles";
break;
case eDATA_Ocean:
return "Ocean";
break;
// tiago: added
case eDATA_ScreenProcess:
return "ScreenProcess";
break;
default:
return "Unknown";
break;
}
}
CRendElement *CRendElement::mfCopyConstruct(void)
{
CRendElement *re = new CRendElement;
*re = *this;
return re;
}
void CRendElement::mfCenter(Vec3d& centr, CCObject *pObj)
{
centr(0,0,0);
}
void CRendElement::mfGetPlane(Plane& pl)
{
pl.n = Vec3d(0,0,1);
pl.d = 0;
}
void CRendElement::mfEndFlush() {}
void CRendElement::Release() { delete this;}
int CRendElement::mfTransform(Matrix44& ViewMatr, Matrix44& ProjMatr, vec4_t *verts, vec4_t *vertsp, int Num) { return 0; }
bool CRendElement::mfIsValidTime(SShader *ef, CCObject *obj, float curtime) {return true;}
void CRendElement::mfBuildGeometry(SShader *ef) {}
bool CRendElement::mfCompile(SShader *ef, char *scr) {return true;};
CRendElement *CRendElement::mfCreateWorldRE(SShader *ef, SInpData *ds) {return NULL;}
bool CRendElement::mfDraw(SShader *ef, SShaderPass *sfm) {return false;}
void *CRendElement::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags) {return NULL;}
float CRendElement::mfDistanceToCameraSquared(const CCObject & thisObject) {return 0.1f;}
//=============================================================================
void SRendItem::mfCalcRefractVectors(int type, byte *Dst, int StrDst)
{
int StrV, StrNorm;
SParamComp_User pr;
pr.m_Name = "refraction";
float ri = pr.mfGet();
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrV, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *normals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrNorm, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
ri = CLAMP(ri, -20.0f, 20.0f);
Vec3d cur_cam_vec, cam;
cam = gRenDev->GetCamera().GetPos();
TransformPosition(cur_cam_vec, cam, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int numVerts = gRenDev->m_RP.m_RendNumVerts;
if (type == GL_UNSIGNED_BYTE)
{
}
else
if (type == GL_FLOAT)
{
for (int i=0; i<numVerts; i++, Dst+=StrDst, verts+=StrV, normals+=StrNorm)
{
float *v = (float *)verts;
float *n = (float *)normals;
float fENX = cur_cam_vec.x - v[0];
float fENY = cur_cam_vec.y - v[1];
float fENZ = cur_cam_vec.z - v[2];
float fNDotE = n[0]*fENX + n[1]*fENY + n[2]*fENZ;
float fNDotN = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
fNDotE *= 1.0f/ri;
Vec3d ref, refrot;
ref.x = n[0]*fNDotE - fENX*fNDotN;
ref.y = n[1]*fNDotE - fENY*fNDotN;
ref.z = n[2]*fNDotE - fENZ*fNDotN;
TransformVector(refrot, ref, gRenDev->m_RP.m_pCurObject->m_Matrix);
refrot.Normalize();
float *d = (float *)Dst;
d[0] = refrot.x;
d[1] = refrot.y;
d[2] = refrot.z;
}
}
}
void SRendItem::mfCalcHalfAngles(int type, byte *ha, int StrHA)
{
int StrLV;
byte *lv = (byte *)gRenDev->EF_GetPointer(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
int StrTX, StrTY, StrVrt, StrTZ;
byte *tangents = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Tangent, &StrTX, GL_FLOAT, eSrcPointer_Tangent, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *binormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Binormal, &StrTY, GL_FLOAT, eSrcPointer_Binormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *tnormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrTZ, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
Vec3d pos = gRenDev->GetCamera().GetPos();
Vec3d objectSpaceEyePosition;
TransformPosition(objectSpaceEyePosition, pos, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int numVerts = gRenDev->m_RP.m_RendNumVerts;
if (type == GL_FLOAT)
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,ha+=StrHA,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *dlv = (float *)lv;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *tz = (float *)tnormals;
const float *v = (float *)verts;
Vec3d vo; /* object-space view vector */
float *hat; /* texture-space half angle */
float x, y, z;
vo.x = objectSpaceEyePosition.x - v[0];
vo.y = objectSpaceEyePosition.y - v[1];
vo.z = objectSpaceEyePosition.z - v[2];
// vo.Normalize();
x = tx[0]*vo[0]+tx[1]*vo[1]+tx[2]*vo[2];
y = ty[0]*vo[0]+ty[1]*vo[1]+ty[2]*vo[2];
z = tz[0]*vo[0]+tz[1]*vo[1]+tz[2]*vo[2];
hat = (float*) ha;
hat[0] = dlv[0] + x;
hat[1] = dlv[1] + y;
hat[2] = dlv[2] + z;
float invlen = 1.0f / cry_sqrtf(hat[0]*hat[0] + hat[1]*hat[1] + hat[2]*hat[2]);
hat[0] *= invlen;
hat[1] *= invlen;
hat[2] *= invlen;
}
}
else
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,ha+=StrHA,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *dlv = (float *)lv;
const float *tz = (float *)tnormals;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *v = (float *)verts;
Vec3d vo; /* object-space view vector */
byte *hat; /* texture-space half angle */
float x, y, z;
vo.x = objectSpaceEyePosition.x - v[0];
vo.y = objectSpaceEyePosition.y - v[1];
vo.z = objectSpaceEyePosition.z - v[2];
// vo.Normalize();
x = tx[0]*vo[0]+tx[1]*vo[1]+tx[2]*vo[2];
y = ty[0]*vo[0]+ty[1]*vo[1]+ty[2]*vo[2];
z = tz[0]*vo[0]+tz[1]*vo[1]+tz[2]*vo[2];
hat = (byte*) ha;
Vec3d h;
h.x = dlv[0] + x;
h.y = dlv[1] + y;
h.z = dlv[2] + z;
float invlen = 1.0f / cry_sqrtf(h.x*h.x + h.y*h.y + h.z*h.z);
hat[0] = (byte)(h.x * invlen * 128.0f + 128.0f);
hat[1] = (byte)(h.y * invlen * 128.0f + 128.0f);
hat[2] = (byte)(h.z * invlen * 128.0f + 128.0f);
}
}
}
void SRendItem::mfCalcHalfAngles_Terrain(int type, byte *ha, int StrHA)
{
int StrLV;
byte *lv = (byte *)gRenDev->EF_GetPointer(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
int StrN, StrVrt;
byte *normals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrN, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
Vec3d pos = gRenDev->GetCamera().GetPos();
Vec3d objectSpaceEyePosition;
TransformPosition(objectSpaceEyePosition, pos, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int numVerts = gRenDev->m_RP.m_RendNumVerts;
float binorm[3] = {0,-1,0};
if (type == GL_FLOAT)
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,ha+=StrHA,normals+=StrN)
{
float *dlv = (float *)lv;
const float *n = (float *)normals;
const float *v = (float *)verts;
Vec3d vo; /* object-space view vector */
float *hat; /* texture-space half angle */
float x, y, z;
vo.x = objectSpaceEyePosition.x - v[0];
vo.y = objectSpaceEyePosition.y - v[1];
vo.z = objectSpaceEyePosition.z - v[2];
// vo.Normalize();
float tang[3];
tang[0] = binorm[1]*n[2]-binorm[2]*n[1]; tang[1]=binorm[2]*n[0]-binorm[0]*n[2]; tang[2]=binorm[0]*n[1]-binorm[1]*n[0];
x = binorm[0]*vo[0]+binorm[1]*vo[1]+binorm[2]*vo[2];
y = tang[0]*vo[0]+tang[1]*vo[1]+tang[2]*vo[2];
z = n[0]*vo[0]+n[1]*vo[1]+n[2]*vo[2];
hat = (float*) ha;
hat[0] = dlv[0] + x;
hat[1] = dlv[1] + y;
hat[2] = dlv[2] + z;
float invlen = 1.0f / cry_sqrtf(hat[0]*hat[0] + hat[1]*hat[1] + hat[2]*hat[2]);
hat[0] *= invlen;
hat[1] *= invlen;
hat[2] *= invlen;
}
}
else
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,ha+=StrHA,normals+=StrN)
{
float *dlv = (float *)lv;
const float *n = (float *)normals;
const float *v = (float *)verts;
Vec3d vo; /* object-space view vector */
byte *hat; /* texture-space half angle */
float x, y, z;
vo.x = objectSpaceEyePosition.x - v[0];
vo.y = objectSpaceEyePosition.y - v[1];
vo.z = objectSpaceEyePosition.z - v[2];
// vo.Normalize();
float tang[3];
tang[0] = binorm[1]*n[2]-binorm[2]*n[1]; tang[1]=binorm[2]*n[0]-binorm[0]*n[2]; tang[2]=binorm[0]*n[1]-binorm[1]*n[0];
x = binorm[0]*vo[0]+binorm[1]*vo[1]+binorm[2]*vo[2];
y = tang[0]*vo[0]+tang[1]*vo[1]+tang[2]*vo[2];
z = n[0]*vo[0]+n[1]*vo[1]+n[2]*vo[2];
hat = (byte*) ha;
Vec3d h;
h.x = dlv[0] + x;
h.y = dlv[1] + y;
h.z = dlv[2] + z;
float invlen = 1.0f / cry_sqrtf(h.x*h.x + h.y*h.y + h.z*h.z);
hat[0] = (byte)(h.x * invlen * 128.0f + 128.0f);
hat[1] = (byte)(h.y * invlen * 128.0f + 128.0f);
hat[2] = (byte)(h.z * invlen * 128.0f + 128.0f);
}
}
}
void SRendItem::mfCalcLightVectors(byte *lv, int StrLV)
{
CDLight *dl = gRenDev->m_RP.m_pCurLight;
Vec3d objectSpaceLightPosition;
TransformPosition(objectSpaceLightPosition, dl->m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int StrTX, StrTY, StrVrt,StrTZ;
byte *tangents = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Tangent, &StrTX, GL_FLOAT, eSrcPointer_Tangent, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *binormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Binormal, &StrTY, GL_FLOAT, eSrcPointer_Binormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *tnormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrTZ, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
int numVerts = gRenDev->m_RP.m_RendNumVerts;
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *dlv = (float *)lv;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *tz = (float *)tnormals;
const float *v = (float *)verts;
Vec3d lo;
lo.x = objectSpaceLightPosition.x - v[0];
lo.y = objectSpaceLightPosition.y - v[1];
lo.z = objectSpaceLightPosition.z - v[2];
dlv[0] = (tx[0]*lo[0] + tx[1]*lo[1] + tx[2]*lo[2]);
dlv[1] = (ty[0]*lo[0] + ty[1]*lo[1] + ty[2]*lo[2]);
dlv[2] = (tz[0]*lo[0] + tz[1]*lo[1] + tz[2]*lo[2]);
}
}
void SRendItem::mfCalcLightVectors_Terrain(byte *lv, int StrLV)
{
CDLight *dl = gRenDev->m_RP.m_pCurLight;
Vec3d objectSpaceLightPosition;
TransformPosition(objectSpaceLightPosition, dl->m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int StrN, StrVrt;
byte *normals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrN, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
int numVerts = gRenDev->m_RP.m_RendNumVerts;
float binorm[3] = {0,-1,0};
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,normals+=StrN)
{
float *dlv = (float *)lv;
const float *n = (float *)normals;
const float *v = (float *)verts;
Vec3d lo;
lo.x = objectSpaceLightPosition.x - v[0];
lo.y = objectSpaceLightPosition.y - v[1];
lo.z = objectSpaceLightPosition.z - v[2];
float tang[3];
tang[0] = binorm[1]*n[2]-binorm[2]*n[1]; tang[1]=binorm[2]*n[0]-binorm[0]*n[2]; tang[2]=binorm[0]*n[1]-binorm[1]*n[0];
dlv[0] = (binorm[0]*lo[0] + binorm[1]*lo[1] + binorm[2]*lo[2]);
dlv[1] = (tang[0]*lo[0] + tang[1]*lo[1] + tang[2]*lo[2]);
dlv[2] = (n[0]*lo[0] + n[1]*lo[1] + n[2]*lo[2]);
}
}
void SRendItem::mfCalcNormLightVectors(byte *lv, int StrLV, int Type)
{
CDLight *dl = gRenDev->m_RP.m_pCurLight;
Vec3d objectSpaceLightPosition;
TransformPosition(objectSpaceLightPosition, dl->m_Origin, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int StrTX, StrTY, StrVrt, StrTZ;
byte *tangents = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Tangent, &StrTX, GL_FLOAT, eSrcPointer_Tangent, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *binormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Binormal, &StrTY, GL_FLOAT, eSrcPointer_Binormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *tnormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrTZ, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
int numVerts = gRenDev->m_RP.m_RendNumVerts;
if (Type == GL_FLOAT)
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *dlv = (float *)lv;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *tz = (float *)tnormals;
const float *v = (float *)verts;
Vec3d lo;
lo.x = objectSpaceLightPosition.x - v[0];
lo.y = objectSpaceLightPosition.y - v[1];
lo.z = objectSpaceLightPosition.z - v[2];
lo.Normalize();
dlv[0] = (tx[0]*lo.x + tx[1]*lo.y + tx[2]*lo.z);
dlv[1] = (ty[0]*lo.x + ty[1]*lo.y + ty[2]*lo.z);
dlv[2] = (tz[0]*lo.x + tz[1]*lo.y + tz[2]*lo.z);
}
}
else
{
for (int i=0; i<numVerts; i++, verts+=StrVrt,lv+=StrLV,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
byte *dlv = (byte *)lv;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *tz = (float *)tnormals;
const float *v = (float *)verts;
Vec3d lo;
lo.x = objectSpaceLightPosition.x - v[0];
lo.y = objectSpaceLightPosition.y - v[1];
lo.z = objectSpaceLightPosition.z - v[2];
lo.Normalize();
dlv[0] = (byte)((tx[0]*lo.x + tx[1]*lo.y + tx[2]*lo.z) * 128.0f + 128.0f);
dlv[1] = (byte)((ty[0]*lo.x + ty[1]*lo.y + ty[2]*lo.z) * 128.0f + 128.0f);
dlv[2] = (byte)((tz[0]*lo.x + tz[1]*lo.y + tz[2]*lo.z) * 128.0f + 128.0f);
}
}
}
void SRendItem::mfCalcProjectAttenFromCamera(byte *dst, int Str)
{
Vec3d pos = gRenDev->GetCamera().GetPos();
Vec3d objectSpaceEyePosition;
TransformPosition(objectSpaceEyePosition, pos, gRenDev->m_RP.m_pCurObject->GetInvMatrix());
int StrTX, StrTY, StrVrt, StrTZ;
byte *tangents = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Tangent, &StrTX, GL_FLOAT, eSrcPointer_Tangent, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *binormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Binormal, &StrTY, GL_FLOAT, eSrcPointer_Binormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *tnormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrTZ, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
int numVerts = gRenDev->m_RP.m_RendNumVerts;
float distance = CRenderer::CV_r_detaildistance;
if (gRenDev->m_bEditor)
distance *= 100.0f;
for (int i=0; i<numVerts; i++, verts+=StrVrt,dst+=Str,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *d = (float *)dst;
const float *ty = (float *)tangents;
const float *tx = (float *)binormals;
const float *tz = (float *)tnormals;
const float *v = (float *)verts;
Vec3d lo, dlv;
lo.x = objectSpaceEyePosition.x - v[0];
lo.y = objectSpaceEyePosition.y - v[1];
lo.z = objectSpaceEyePosition.z - v[2];
dlv.x = (tx[0]*lo[0] + tx[1]*lo[1] + tx[2]*lo[2]);
dlv.y = (ty[0]*lo[0] + ty[1]*lo[1] + ty[2]*lo[2]);
dlv.z = (tz[0]*lo[0] + tz[1]*lo[1] + tz[2]*lo[2]);
Vec3d a;
a = dlv / distance;
d[0] = a.x + 0.5f;
d[1] = a.y + 0.5f;
d[2] = a.z + 0.5f;
}
}
void SRendItem::mfCalcLAttenuationSpec0(byte *dst, int StrDst, byte *lv, int StrLV, int type)
{
int numVerts = gRenDev->m_RP.m_RendNumVerts;
CDLight *dl = gRenDev->m_RP.m_pCurLight;
float brightness = dl->m_fRadius * 2.0f;
float iBr = 1.0f / brightness;
if (type == GL_UNSIGNED_BYTE)
{
float Ibr1 = iBr * 255.0f;
for (int v=0; v<numVerts; v++, dst+=StrDst,lv+=StrLV)
{
Vec3d *l = (Vec3d *)lv;
dst[0] = (byte)CLAMP(l->x * Ibr1 + 128.0f, 0.0f, 255.0f);
dst[1] = (byte)CLAMP(l->y * Ibr1 + 128.0f, 0.0f, 255.0f);
dst[2] = (byte)CLAMP(l->z * Ibr1 + 128.0f, 0.0f, 255.0f);
}
}
else
if (type == GL_FLOAT)
{
for (int v=0; v<numVerts; v++, dst+=StrDst,lv+=StrLV)
{
Vec3d *l = (Vec3d *)lv;
float *d = (float *)dst;
d[0] = CLAMP(l->x * iBr + 0.5f, 0.0f, 1.0f);
d[1] = CLAMP(l->y * iBr + 0.5f, 0.0f, 1.0f);
d[2] = CLAMP(l->z * iBr + 0.5f, 0.0f, 1.0f);
}
}
}
void SRendItem::mfCalcLAttenuationSpec1(byte *dst, int StrDst, byte *lv, int StrLV, int type)
{
int numVerts = gRenDev->m_RP.m_RendNumVerts;
CDLight *dl = gRenDev->m_RP.m_pCurLight;
float brightness = dl->m_fRadius;
if (type == GL_UNSIGNED_BYTE)
{
for (int v=0; v<numVerts; v++, dst+=StrDst,lv+=StrLV)
{
Vec3d *l = (Vec3d *)lv;
dst[0] = (byte)CLAMP(l->x * 128.0f + 128.0f, 0.0f, 255.0f);
dst[1] = (byte)CLAMP(l->y * 128.0f + 128.0f, 0.0f, 255.0f);
dst[2] = (byte)CLAMP(l->z * 128.0f + 128.0f, 0.0f, 255.0f);
}
}
else
if (type == GL_FLOAT)
{
for (int v=0; v<numVerts; v++, dst+=StrDst,lv+=StrLV)
{
Vec3d *l = (Vec3d *)lv;
float *d = (float *)dst;
d[0] = CLAMP(l->x * 0.5f + 0.5f, 0.0f, 1.0f);
d[1] = CLAMP(l->y * 0.5f + 0.5f, 0.0f, 1.0f);
d[2] = CLAMP(l->z * 0.5f + 0.5f, 0.0f, 1.0f);
}
}
}
void SRendItem::mfCalcLightAttenuation(int type, byte *Dst, int StrideDst)
{
Vec3d lpos;
CDLight *dl = gRenDev->m_RP.m_pCurLight;
lpos = dl->m_Origin;
float delta = 1.0f;
if (gRenDev->m_bEditor)
delta = 100.0f;
int numVerts = gRenDev->m_RP.m_RendNumVerts;
int StrTX, StrTY, StrVrt, StrTZ;
byte *tangents = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Tangent, &StrTX, GL_FLOAT, eSrcPointer_Tangent, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *binormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Binormal, &StrTY, GL_FLOAT, eSrcPointer_Binormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *tnormals = (byte *)gRenDev->EF_GetPointer(eSrcPointer_TNormal, &StrTZ, GL_FLOAT, eSrcPointer_TNormal, FGP_NOCALC | FGP_SRC | FGP_REAL);
byte *verts = (byte *)gRenDev->EF_GetPointer(eSrcPointer_Vert, &StrVrt, GL_FLOAT, eSrcPointer_Vert, FGP_NOCALC | FGP_SRC | FGP_REAL);
if (type == GL_UNSIGNED_BYTE)
{
byte *dst = Dst;
for (int v=0; v<numVerts; v++, dst+=StrideDst,verts+=StrVrt,tangents+=StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
Vec3d lvec = lpos - *(Vec3d*)verts;
float distance = lvec.Length();
if(distance>dl->m_fRadius+delta)
{
*(uint *)dst = 0;
continue; // no lighting here
}
lvec /= distance;
float attenuation = (dl->m_fRadius-distance)/dl->m_fRadius;
if (attenuation < 0)
attenuation = 0;
// transform
const Vec3d *lo = &lvec;
const Vec3d *ty = (Vec3d *)tangents;
const Vec3d *tx = (Vec3d *)binormals;
const Vec3d *tz = (Vec3d *)tnormals;
uchar d = (unsigned char)((0.5f * (tz->x*lo->x + tz->y*lo->y + tz->z*lo->z) + 0.5f)*255);
dst[3] = (unsigned char)(d>128 ? attenuation*255 : 0); // att
}
}
else
if (type == GL_FLOAT)
{
for (int v=0; v<numVerts; v++, Dst+=StrideDst,verts+=StrVrt,tangents += StrTX,binormals+=StrTY,tnormals+=StrTZ)
{
float *dst = (float *)Dst;
Vec3d lvec = lpos - *(Vec3d*)verts;
float distance = lvec.Length();
if(distance>dl->m_fRadius+delta)
{
dst[3] = 0;
continue; // no lighting here
}
//lvec /= distance;
float attenuation = (dl->m_fRadius-distance)/dl->m_fRadius;
if (attenuation < 0)
attenuation = 0;
// transform
const Vec3d *lo = &lvec;
const Vec3d *ty = (Vec3d *)tangents;
const Vec3d *tx = (Vec3d *)binormals;
const Vec3d *tz = (Vec3d *)tnormals;
uchar d = (unsigned char)((0.5f * (tz->x*lo->x + tz->y*lo->y + tz->z*lo->z) + 0.5f)*255);
dst[0] = (d>128 ? attenuation : 0); // att
}
}
}
void SRendItem::mfComputeTangent(const Vec3d& v0, const Vec3d& v1, const Vec3d& v2, const vec2_t t0, const vec2_t t1, const vec2_t t2, Vec3d &tangent, Vec3d& binormal, float& sign, Vec3d& face_normal)
{
Vec3d bi;
Vec3d cp;
Vec3d e0;
Vec3d e1;
sign = 1.0f;
// x
e0[0] = v1[0] - v0[0];
e0[1] = t1[0] - t0[0];
e0[2] = t1[1] - t0[1];
e1[0] = v2[0] - v0[0];
e1[1] = t2[0] - t0[0];
e1[2] = t2[1] - t0[1];
cp = e0 ^ e1;
if ( fabs(cp[0]) > 0.000001f )
{
tangent[0] = -cp[1] / cp[0];
binormal[0] = -cp[2] / cp[0];
}
// y
e0[0] = v1[1] - v0[1];
e0[1] = t1[0] - t0[0];
e0[2] = t1[1] - t0[1];
e1[0] = v2[1] - v0[1];
e1[1] = t2[0] - t0[0];
e1[2] = t2[1] - t0[1];
cp = e0 ^ e1;
if ( fabs(cp[0]) > 0.000001f )
{
tangent[1] = -cp[1] / cp[0];
binormal[1] = -cp[2] / cp[0];
}
// z
e0[0] = v1[2] - v0[2];
e0[1] = t1[0] - t0[0];
e0[2] = t1[1] - t0[1];
e1[0] = v2[2] - v0[2];
e1[1] = t2[0] - t0[0];
e1[2] = t2[1] - t0[1];
cp = e0 ^ e1;
if ( fabs(cp[0]) > 0.000001f )
{
tangent[2] = -cp[1] / cp[0];
binormal[2] = -cp[2] / cp[0];
}
tangent.Normalize();
binormal.Normalize();
/* bi = tangent ^ binormal;
dot = (float)(bi | face_normal);
if (dot < 0.0f)
{
sign = -1.0f;
binormal = -binormal;
}*/
}
void SRendItem::mfCalcTangentSpaceVectors(void)
{
int i, j;
int in[3];
float sign;
Vec3d tg, bi, nor;
Vec3d v[3];
float stc[3][2];
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
int numTris = gRenDev->m_RP.m_RendNumIndices / 3;
memset(gRenDev->m_RP.m_pBinormals, 0, sizeof(Vec3d)*gRenDev->m_RP.m_RendNumVerts);
memset(gRenDev->m_RP.m_pTangents, 0, sizeof(Vec3d)*gRenDev->m_RP.m_RendNumVerts);
memset(gRenDev->m_RP.m_pTNormals, 0, sizeof(Vec3d)*gRenDev->m_RP.m_RendNumVerts);
for (i=0; i<numTris; i++)
{
for(j=0; j<3; j++)
{
in[j] = gRenDev->m_RP.m_RendIndices[i*3+j];
struct_VERTEX_FORMAT_P3F_TEX2F *p = (struct_VERTEX_FORMAT_P3F_TEX2F *)(ptr.PtrB+in[j]*gRenDev->m_RP.m_Stride);
v[j] = p->xyz;
stc[j][0] = p->st[0];
stc[j][1] = p->st[1];
}
Vec3 uu, vv;
uu = v[1] - v[0];
vv = v[1] - v[2];
nor = uu ^ vv;
nor.Normalize();
// Calculate basis for this face
mfComputeTangent(v[0], v[1], v[2], stc[0], stc[1], stc[2], tg, bi, sign, nor);
gRenDev->m_RP.m_pTangents[in[0]] -= tg;
gRenDev->m_RP.m_pBinormals[in[0]] -= bi;
mfComputeTangent(v[2], v[0], v[1], stc[2], stc[0], stc[1], tg, bi, sign, nor);
gRenDev->m_RP.m_pTangents[in[1]] -= tg;
gRenDev->m_RP.m_pBinormals[in[1]] -= bi;
mfComputeTangent(v[1], v[2], v[0], stc[1], stc[2], stc[0], tg, bi, sign, nor);
gRenDev->m_RP.m_pTangents[in[2]] -= tg;
gRenDev->m_RP.m_pBinormals[in[2]] -= bi;
}
for(i=0; i<gRenDev->m_RP.m_RendNumVerts; i++)
{
gRenDev->m_RP.m_pTangents[i].Normalize();
gRenDev->m_RP.m_pBinormals[i].Normalize();
gRenDev->m_RP.m_pTNormals[i] = gRenDev->m_RP.m_pTangents[i].Cross(gRenDev->m_RP.m_pBinormals[i]);
//if(gRenDev->m_RP.mTNormals[i].Dot(gRenDev->m_RP.mNormals[i])) < 0)
// m_pBasises[v].tnormal = -m_pBasises[v].tnormal;
}
}
void *SRendItem::mfGetPointerCommon(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
static int sFrameCalcLight;
static int sFrameCalcLightNoAtt;
static int sFrameCalcHalfAngles;
static int sFrameCalcHANoAtt;
static int sFrameCalcTangents;
static int sFrameCalcAtten;
static int sFrameCalcRefract;
static int sMaskLight0;
static int sMaskLight1;
static int sMaskLight2;
static int sMaskLight3;
static int sMaskLight4;
int j;
switch (ePT)
{
case eSrcPointer_Binormal:
case eSrcPointer_Tangent:
case eSrcPointer_TNormal:
{
if (gRenDev->m_RP.m_Frame != sFrameCalcTangents)
{
sFrameCalcTangents = gRenDev->m_RP.m_Frame;
mfCalcTangentSpaceVectors();
}
}
*Stride = sizeof(Vec3d);
if (ePT == eSrcPointer_Binormal)
return gRenDev->m_RP.m_pBinormals;
if (ePT == eSrcPointer_Tangent)
return gRenDev->m_RP.m_pTangents;
if (ePT == eSrcPointer_TNormal)
return gRenDev->m_RP.m_pTNormals;
case eSrcPointer_LightVector:
{
byte *dst;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_Color:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (!(Flags & FGP_NOCALC))
{
if (gRenDev->m_RP.m_Frame != sFrameCalcTangents)
{
sFrameCalcTangents = gRenDev->m_RP.m_Frame;
mfCalcTangentSpaceVectors();
}
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];
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 != sFrameCalcLight)
{
sFrameCalcLight = gRenDev->m_RP.m_Frame;
sMaskLight0 = 0;
}
if (!(sMaskLight0 & (1<<gRenDev->m_RP.m_nCurLight)))
{
sMaskLight0 |= (1<<gRenDev->m_RP.m_nCurLight);
mfCalcLightVectors(dst, *Stride);
}
}
}
return dst;
}
break;
case eSrcPointer_NormLightVector:
{
byte *dst;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_Color:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (!(Flags & FGP_NOCALC))
{
if (gRenDev->m_RP.m_Frame != sFrameCalcTangents)
{
sFrameCalcTangents = gRenDev->m_RP.m_Frame;
mfCalcTangentSpaceVectors();
}
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];
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 != sFrameCalcLight)
{
sFrameCalcLight = gRenDev->m_RP.m_Frame;
sMaskLight0 = 0;
}
if (!(sMaskLight0 & (1<<gRenDev->m_RP.m_nCurLight)))
{
sMaskLight0 |= (1<<gRenDev->m_RP.m_nCurLight);
mfCalcNormLightVectors(dst, *Stride, Type);
}
}
}
return dst;
}
break;
case eSrcPointer_HalfAngleVector:
{
byte *dst;
switch (Dst)
{
case eSrcPointer_Color:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (!(Flags & FGP_NOCALC))
{
if (gRenDev->m_RP.m_Frame != sFrameCalcTangents)
{
sFrameCalcTangents = gRenDev->m_RP.m_Frame;
mfCalcTangentSpaceVectors();
}
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPAREHAV) && Dst != eSrcPointer_HalfAngleVector)
{
byte *Dst = dst;
int str = *Stride;
Vec3d *lv = gRenDev->m_RP.m_pHalfAngleVectors[gRenDev->m_RP.m_nCurLight];
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 = (byte *)Dst;
fd[0] = (byte)(lv->x * 255.0f);
fd[1] = (byte)(lv->y * 255.0f);
fd[2] = (byte)(lv->z * 255.0f);
}
}
}
if (gRenDev->m_RP.m_Frame != sFrameCalcHalfAngles)
{
sFrameCalcHalfAngles = gRenDev->m_RP.m_Frame;
sMaskLight1 = 0;
}
if (!(sMaskLight1 & (1<<gRenDev->m_RP.m_nCurLight)))
{
sMaskLight1 |= (1<<gRenDev->m_RP.m_nCurLight);
mfCalcHalfAngles(Type, dst, *Stride);
}
}
return dst;
}
break;
case eSrcPointer_LAttenuationSpec0:
{
byte *dst = NULL;
switch (Dst)
{
case eSrcPointer_Color:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELAS0) && Dst != eSrcPointer_LAttenuationSpec0)
{
byte *Dst = dst;
int str = *Stride;
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 = (byte *)Dst;
fd[0] = (byte)CLAMP(lv->x * 255.0f, 0.0f, 255.0f);
fd[1] = (byte)CLAMP(lv->y * 255.0f, 0.0f, 255.0f);
fd[2] = (byte)CLAMP(lv->z * 255.0f, 0.0f, 255.0f);
}
}
}
else
{
int StrLV;
byte *lv = (byte *)mfGetPointerCommon(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
if (dst)
mfCalcLAttenuationSpec0(dst, *Stride, lv, StrLV, Type);
}
return dst;
}
break;
case eSrcPointer_LAttenuationSpec1:
{
byte *dst = NULL;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if ((gRenDev->m_RP.m_pShader->m_Flags3 & EF3_PREPARELAS1) && Dst != eSrcPointer_LAttenuationSpec1)
{
byte *Dst = dst;
int str = *Stride;
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 = (byte *)Dst;
fd[0] = (byte)CLAMP(lv->x * 255.0f, 0.0f, 255.0f);
fd[1] = (byte)CLAMP(lv->y * 255.0f, 0.0f, 255.0f);
fd[2] = (byte)CLAMP(lv->z * 255.0f, 0.0f, 255.0f);
}
}
}
else
{
int StrLV;
byte *lv = (byte *)mfGetPointerCommon(eSrcPointer_LightVector, &StrLV, GL_FLOAT, eSrcPointer_LightVector, FGP_SRC | FGP_REAL);
if (dst)
mfCalcLAttenuationSpec1(dst, *Stride, lv, StrLV, Type);
}
return dst;
}
break;
case eSrcPointer_Detail:
{
byte *dst = NULL;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
int StrTC;
byte *tc = (byte *)mfGetPointerCommon(eSrcPointer_Tex, &StrTC, GL_FLOAT, eSrcPointer_Tex, FGP_SRC | FGP_REAL);
if (dst)
{
byte *Dst = dst;
float scale = CRenderer::CV_r_detailscale;
for (int i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, tc+=StrTC, Dst+=*Stride)
{
float *sr = (float *)tc;
float *ds = (float *)Dst;
ds[0] = sr[0] * scale;
ds[1] = sr[1] * scale;
}
}
return dst;
}
break;
case eSrcPointer_ProjectAttenFromCamera:
{
byte *dst = NULL;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (dst)
mfCalcProjectAttenFromCamera(dst, *Stride);
return dst;
}
break;
case eSrcPointer_Attenuation:
{
byte *dst;
switch (Dst)
{
case eSrcPointer_Color:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (!(Flags & FGP_NOCALC))
{
if (gRenDev->m_RP.m_Frame != sFrameCalcTangents)
{
sFrameCalcTangents = gRenDev->m_RP.m_Frame;
mfCalcTangentSpaceVectors();
}
if (gRenDev->m_RP.m_Frame != sFrameCalcAtten)
{
sFrameCalcAtten = gRenDev->m_RP.m_Frame;
sMaskLight2 = 0;
}
if (!(sMaskLight2 & (1<<gRenDev->m_RP.m_nCurLight)))
{
sMaskLight2 |= (1<<gRenDev->m_RP.m_nCurLight);
mfCalcLightAttenuation(Type, dst, *Stride);
}
}
return dst;
}
break;
case eSrcPointer_Refract:
{
byte *dst;
switch (Dst)
{
case eSrcPointer_Tex:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 0*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
case eSrcPointer_TexLM:
dst = (byte *)gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + 1*16;
*Stride = gRenDev->m_RP.m_Stride;
break;
}
if (!(Flags & FGP_NOCALC))
{
if (gRenDev->m_RP.m_Frame != sFrameCalcRefract)
{
sFrameCalcRefract = gRenDev->m_RP.m_Frame;
mfCalcRefractVectors(Type, dst, *Stride);
}
}
return dst;
}
break;
case eSrcPointer_Vert:
*Stride = gRenDev->m_RP.m_Stride;
return gRenDev->m_RP.m_Ptr.PtrB;
case eSrcPointer_Color:
*Stride = gRenDev->m_RP.m_Stride;
return gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
case eSrcPointer_Tex:
case eSrcPointer_TexLM:
*Stride = gRenDev->m_RP.m_Stride;
j = ePT - eSrcPointer_Tex;
return gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + j*16;
}
return NULL;
}