/*============================================================================= RendElement.cpp : common RE functions. Copyright (c) 2001 Crytek Studios. All Rights Reserved. Revision history: * Created by Honitch Andrey =============================================================================*/ #include "RenderPCH.h" //TArray CRendElement::m_AllREs; CRendElement CRendElement::m_RootGlobal; //=============================================================== TArray gCurLightStyles; TArray 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.SortValb.SortVal.SortVal) return 1; else return 0; #else if (a.SortVal.i.Highb.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.SortValb.SortVal.SortVal) return 1; else return 0; #else if (a.SortVal.i.Highb.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 (nSanSb) 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.SortValb.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; iSortVal.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; iSortVal.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 *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; im_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; iEF_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; im_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; im_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; im_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; iGetCamera().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; im_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; vx * 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; vx * 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; vx * 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; vx * 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; vdl->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; vdl->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; im_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; im_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; im_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<m_RP.m_nCurLight))) { sMaskLight0 |= (1<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; im_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<m_RP.m_nCurLight))) { sMaskLight0 |= (1<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; im_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; im_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<m_RP.m_nCurLight))) { sMaskLight1 |= (1<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; im_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; im_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; im_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; im_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; im_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<m_RP.m_nCurLight))) { sMaskLight2 |= (1<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; }