123
This commit is contained in:
1439
Cry3DEngine/3DEngineLight.cpp
Normal file
1439
Cry3DEngine/3DEngineLight.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1611
Cry3DEngine/3DEngineRender.cpp
Normal file
1611
Cry3DEngine/3DEngineRender.cpp
Normal file
File diff suppressed because it is too large
Load Diff
423
Cry3DEngine/3DEngineScreenEffects.cpp
Normal file
423
Cry3DEngine/3DEngineScreenEffects.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
=====================================================================
|
||||
FILE : 3dEngineScreenEffects.cpp
|
||||
DESC : Screen processing effects
|
||||
PROJ : Crytek Engine
|
||||
CODER: Tiago Sousa
|
||||
|
||||
Last Update: 09/12/2003
|
||||
TODO:
|
||||
.Clean up code...
|
||||
.Remove all SCREEN_PROCESS stuff (Set/GetParameter, etc)
|
||||
=====================================================================
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "3dEngine.h"
|
||||
#include "objman.h"
|
||||
#include "../RenderDll/Common/RendElements/CREScreenCommon.h"
|
||||
|
||||
// some helper macros
|
||||
#define GET_ACTIVEPARAMETER(pProcess) \
|
||||
*((bool*)m_pREScreenProcess->mfGetParameter((pProcess), SCREENPROCESS_ACTIVE)) \
|
||||
|
||||
#define GET_CVAR(pVar)\
|
||||
(GetConsole()->GetCVar((pVar)))\
|
||||
|
||||
// interfaces for script usage
|
||||
|
||||
// set screen mask texture
|
||||
void C3DEngine:: SetBlurMask(ITexPic *pMask)
|
||||
{
|
||||
if(!m_pBlurObj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//m_pBlurObj->SetBlurMask((STexPic*) pMask);
|
||||
}
|
||||
|
||||
// set screen mask texture
|
||||
void C3DEngine:: SetScreenMask(ITexPic *pMask)
|
||||
{
|
||||
if(!m_pScreenObj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//m_pScreenObj->SetScreenMask((STexPic*) pMask);
|
||||
}
|
||||
|
||||
// setup current screen fx
|
||||
void C3DEngine:: SetScreenFx(const char *pEffectName, int iActive)
|
||||
{
|
||||
bool bActive=iActive? 1:0;
|
||||
// to avoid an untreackable crash in mscvdll strcmp
|
||||
if (!pEffectName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcmp(pEffectName, "NightVision"))
|
||||
{
|
||||
int iActive=bActive;
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_NIGHTVISION, SCREENPROCESS_ACTIVE, &iActive);
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "HeatVision"))
|
||||
{
|
||||
int iActive=bActive;
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_HEATVISION, SCREENPROCESS_ACTIVE, &iActive);
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "ScreenBlur"))
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_ACTIVE, &bActive);
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "FlashBang"))
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_ACTIVE, &bActive);
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "ScreenFade"))
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FADE, SCREENPROCESS_ACTIVE, &bActive);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup current screen fx parameter
|
||||
void C3DEngine:: SetScreenFxParam(const char *pEffectName, const char *pEffectParam, void *pValue)
|
||||
{
|
||||
// <<TODO>> add required/missing parameters
|
||||
|
||||
// to avoid an untreackable crash in mscvdll strcmp
|
||||
if (!pEffectName || !pEffectParam)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// set parameters for screen fade
|
||||
if(!stricmp(pEffectName, "ScreenFade"))
|
||||
{
|
||||
if(!stricmp(pEffectParam, "ScreenFadeTime")) // set screen fade flag
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FADE, SCREENPROCESS_TRANSITIONTIME, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenPreFadeTime")) // set screen pre fade flag (count number of frames, before start fading)
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FADE, SCREENPROCESS_PRETRANSITIONTIME, pValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectName, "ScreenBlur")) // set parameters for screen blur
|
||||
{
|
||||
if(!stricmp(pEffectParam, "ScreenBlurAmount")) // screen blur amount
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURAMOUNT, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorRed")) // screen blur color red..
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORRED, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorGreen")) // screen blur color green..
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORGREEN, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorBlue")) // screen blur color blue..
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORBLUE, pValue);
|
||||
}
|
||||
}
|
||||
else // get parameters for flashbang
|
||||
if(!stricmp(pEffectName, "FlashBang"))
|
||||
{
|
||||
if(!stricmp(pEffectParam, "FlashBangTimeScale")) // flashbang timeout
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGTIMESCALE, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashPosX")) // flashbangflash position x
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHPOSX, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashPosY")) // flashbangflash position y
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHPOSY, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashSizeX")) // flashbangflash size x
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHSIZEX, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashSizeY")) // flashbangflash size y
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHSIZEY, pValue);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangForce")) // force flashbang after image texture creation
|
||||
{
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFORCEAFTERIMAGE, pValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int C3DEngine::GetScreenFx(const char *pEffectName)
|
||||
{
|
||||
// to avoid an untreackable crash in mscvdll strcmp
|
||||
if (!pEffectName)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!strcmp(pEffectName, "NightVision"))
|
||||
{
|
||||
bool bVal=*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_NIGHTVISION, SCREENPROCESS_ACTIVE));
|
||||
return bVal;
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "HeatVision"))
|
||||
{
|
||||
bool bVal=*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_HEATVISION, SCREENPROCESS_ACTIVE));
|
||||
return bVal;
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "ScreenBlur"))
|
||||
{
|
||||
bool bVal=*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_ACTIVE));
|
||||
return bVal;
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "FlashBang"))
|
||||
{
|
||||
bool bVal=*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_ACTIVE));
|
||||
return (int)bVal;
|
||||
}
|
||||
else
|
||||
if(!strcmp(pEffectName, "ScreenFade"))
|
||||
{
|
||||
bool bVal=*((bool*)m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FADE, SCREENPROCESS_ACTIVE));
|
||||
return bVal;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int C3DEngine::GetScreenFxParam(const char *pEffectName, const char *pEffectParam, void *&pValue)
|
||||
{
|
||||
// to avoid an untreackable crash in mscvdll strcmp
|
||||
if (!pEffectName || !pEffectParam)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get parameters for screen fade
|
||||
if(!stricmp(pEffectName, "ScreenFade"))
|
||||
{
|
||||
if(!stricmp(pEffectParam, "ScreenFadeTime")) // set screen fade flag
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FADE, SCREENPROCESS_TRANSITIONTIME);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenPreFadeTime")) // set screen pre fade flag (count number of frames, before start fading)
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FADE, SCREENPROCESS_PRETRANSITIONTIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parameter doens't exist
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectName, "ScreenBlur")) // get parameters for screen blur
|
||||
{
|
||||
if(!stricmp(pEffectParam, "ScreenBlurAmount")) // screen blur amount
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURAMOUNT);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorRed")) // screen blur color red..
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORRED);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorGreen")) // screen blur color green..
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORGREEN);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "ScreenBlurColorBlue")) // screen blur color blue..
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_BLUR, SCREENPROCESS_BLURCOLORBLUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parameter doens't exist
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectName, "FlashBang")) // get parameters for flashbang
|
||||
{
|
||||
if(!stricmp(pEffectParam, "FlashBangTimeScale")) // flashbang timeout
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGTIMESCALE);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashPosX")) // flashbangflash position x
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHPOSX);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashPosY")) // flashbangflash position y
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHPOSY);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashSizeX")) // flashbangflash size x
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHSIZEX);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangFlashSizeY")) // flashbangflash size y
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFLASHSIZEY);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangTimeOut")) // get current time out time
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGTIMEOUT);
|
||||
}
|
||||
else
|
||||
if(!stricmp(pEffectParam, "FlashBangForce")) // force flashbang after image texture creation
|
||||
{
|
||||
pValue=m_pREScreenProcess->mfGetParameter(SCREENPROCESS_FLASHBANG, SCREENPROCESS_FLASHBANGFORCEAFTERIMAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parameter doens't exist
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// parameter doens't exist
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// reset current screen effects
|
||||
void C3DEngine::ResetScreenFx(void)
|
||||
{
|
||||
if(m_pREScreenProcess)
|
||||
{
|
||||
m_pREScreenProcess->mfReset();
|
||||
}
|
||||
}
|
||||
|
||||
// process all screen space special fx's
|
||||
void C3DEngine::ProcessScreenEffects()
|
||||
{
|
||||
// don't allow this in recursive rendering..
|
||||
if(m_pObjManager->m_nRenderStackLevel!=0 || !m_pREScreenProcess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FUNCTION_PROFILER( GetSystem(), PROFILE_RENDERER );
|
||||
|
||||
// get console vars
|
||||
static ICVar *pDisableSfx=GET_CVAR("r_DisableSfx");
|
||||
static ICVar *pResetSfx=GET_CVAR("r_ResetScreenFx");
|
||||
|
||||
// reset screen effects state
|
||||
if(pResetSfx->GetIVal()!=0)
|
||||
{
|
||||
m_pREScreenProcess->mfReset();
|
||||
}
|
||||
|
||||
// disable fx's
|
||||
if(!pDisableSfx->GetIVal())
|
||||
{
|
||||
static ICVar *pNormalGlare=GET_CVAR("r_Glare");
|
||||
static ICVar *pMotionBlur=GET_CVAR("r_MotionBlur");
|
||||
static ICVar *pScreenColorTransfer=GET_CVAR("r_ScreenColorTransfer");
|
||||
static ICVar *pMotionBlurAmount=GET_CVAR("r_MotionBlurAmount");
|
||||
static ICVar *pMotionBlurDisplace=GET_CVAR("r_MotionBlurDisplace");
|
||||
static ICVar *pRenderMode=GET_CVAR("r_RenderMode");
|
||||
|
||||
// get console vars values
|
||||
int iUseMotionBlur=pMotionBlur->GetIVal();
|
||||
int iRenderMode=pRenderMode->GetIVal();
|
||||
int iUseGlare=((pNormalGlare->GetIVal()) && (iRenderMode>0));
|
||||
|
||||
// activate fx's
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_MOTIONBLUR, SCREENPROCESS_ACTIVE, &iUseMotionBlur);
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_GLARE, SCREENPROCESS_ACTIVE, &iUseGlare);
|
||||
|
||||
// cartoon render mode active ?
|
||||
bool bCartoon=0;
|
||||
if(iRenderMode==4)
|
||||
{
|
||||
bCartoon=1;
|
||||
}
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_CARTOON, SCREENPROCESS_ACTIVE, &bCartoon);
|
||||
|
||||
// get screen texture if necessary
|
||||
if(GET_ACTIVEPARAMETER(SCREENPROCESS_FLASHBANG) || GET_ACTIVEPARAMETER(SCREENPROCESS_COLORTRANSFER) ||
|
||||
GET_ACTIVEPARAMETER(SCREENPROCESS_BLUR) || GET_ACTIVEPARAMETER(SCREENPROCESS_NIGHTVISION) ||
|
||||
GET_ACTIVEPARAMETER(SCREENPROCESS_HEATVISION) || GET_ACTIVEPARAMETER(SCREENPROCESS_GLARE) ||
|
||||
GET_ACTIVEPARAMETER(SCREENPROCESS_CARTOON) ||GET_ACTIVEPARAMETER(SCREENPROCESS_MOTIONBLUR))
|
||||
{
|
||||
CCObject *pScreenObj=GetRenderer()->EF_GetObject(true, -1);
|
||||
pScreenObj->m_Matrix.SetIdentity();
|
||||
GetRenderer()->EF_AddEf(0, m_pREDummy, m_pSHScreenTexMap, NULL, pScreenObj, 0, NULL, eS_Glare);
|
||||
}
|
||||
|
||||
// process screen glare/set glare parameters
|
||||
if(GET_ACTIVEPARAMETER(SCREENPROCESS_GLARE))
|
||||
{
|
||||
IVisArea *pCurrLocation= GetVisAreaFromPos(GetViewCamera().GetPos());
|
||||
|
||||
static ICVar *pGlareQuality=GET_CVAR("r_GlareQuality");
|
||||
if(pGlareQuality->GetIVal()!=4)
|
||||
{
|
||||
if(!pCurrLocation)
|
||||
{
|
||||
pNormalGlare->Set(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
pNormalGlare->Set(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// activate motion blur
|
||||
if(GET_ACTIVEPARAMETER(SCREENPROCESS_MOTIONBLUR))
|
||||
{
|
||||
// get console variables
|
||||
float fMotionBlurAmount=pMotionBlurAmount->GetFVal();
|
||||
int iMotionBlurDisplace=pMotionBlurDisplace->GetIVal();
|
||||
|
||||
// pass parameters and activate effect
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_MOTIONBLUR, SCREENPROCESS_MOTIONBLURDISPLACE, &iMotionBlurDisplace);
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_MOTIONBLUR, SCREENPROCESS_MOTIONBLURAMOUNT, &fMotionBlurAmount);
|
||||
m_pREScreenProcess->mfSetParameter(SCREENPROCESS_MOTIONBLUR, SCREENPROCESS_MOTIONBLURTYPE, &iUseMotionBlur);
|
||||
m_pREScreenProcess->mfActivate(SCREENPROCESS_MOTIONBLUR);
|
||||
}
|
||||
}
|
||||
|
||||
CCObject *pScreenProcessObj=GetRenderer()->EF_GetObject(true, -1);
|
||||
pScreenProcessObj->m_Matrix.SetIdentity();
|
||||
GetRenderer()->EF_AddEf(0, m_pREScreenProcess, m_pSHScreenProcess, NULL, pScreenProcessObj, 0, NULL, eS_Glare);
|
||||
}
|
||||
2637
Cry3DEngine/3dEngine.cpp
Normal file
2637
Cry3DEngine/3dEngine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
510
Cry3DEngine/3dEngine.h
Normal file
510
Cry3DEngine/3dEngine.h
Normal file
@@ -0,0 +1,510 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: 3dengine.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef C3DENGINE_H
|
||||
#define C3DENGINE_H
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
class CTerrain;
|
||||
class CObjManager;
|
||||
class CRESky;
|
||||
class CPartManager;
|
||||
class CDecalManager;
|
||||
class CBFManager;
|
||||
class CryCharManager;
|
||||
struct ICryCharInstance;
|
||||
class CRainManager;
|
||||
struct CVisAreaManager;
|
||||
|
||||
struct IMatInfo;
|
||||
|
||||
// this class is used for additional view port rendering (view from camera of another player)
|
||||
struct SRenderCamera
|
||||
{
|
||||
CCamera m_Camera;
|
||||
float m_fX;
|
||||
float m_fY;
|
||||
float m_fWidth;
|
||||
float m_fHeight;
|
||||
};
|
||||
|
||||
struct SNodeInfo;
|
||||
struct DLightAmount{ CDLight * pDLight; float fAmount; };
|
||||
|
||||
class CMatMan : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CMatMan();
|
||||
~CMatMan();
|
||||
|
||||
IMatInfo* CreateMatInfo( const char *sMtlName = NULL );
|
||||
void DeleteMatInfo(IMatInfo * pMatInfo);
|
||||
void RenameMatInfo( IMatInfo *pMtl,const char *sNewName );
|
||||
IMatInfo* FindMatInfo( const char *sMtlName ) const;
|
||||
|
||||
void LoadMaterialsLibrary( const char *sMtlFile,XmlNodeRef &levelDataRoot );
|
||||
|
||||
private:
|
||||
IMatInfo* LoadMaterial( XmlNodeRef mtlNode,const char *sLibraryName,IMatInfo* pParent );
|
||||
bool LoadMaterialShader( IMatInfo *pMtl,const char *sShader,int mtlFlags,unsigned int nShaderGenMask,SInputShaderResources &sr,SLightMaterial &lm,XmlNodeRef &publicsNode );
|
||||
void ParsePublicParams( TArray<SShaderParam> ¶ms,XmlNodeRef paramsNode );
|
||||
|
||||
typedef std::set<_smart_ptr<IMatInfo> > MtlSet;
|
||||
typedef std::map<string,IMatInfo*,stl::less_stricmp<string> > MtlNameMap;
|
||||
MtlSet m_mtlSet;
|
||||
MtlNameMap m_mtlNameMap;
|
||||
};
|
||||
|
||||
struct CLightEntity : public IEntityRender, public Cry3DEngineBase
|
||||
{
|
||||
virtual const char * GetEntityClassName(void) const { return "LightEntityClass"; }
|
||||
virtual float GetScale(void) const { return 1.f; }
|
||||
virtual const char *GetName(void) const { return "LightEntityName"; }
|
||||
virtual const Vec3d &GetPos(bool) const;
|
||||
virtual const Vec3d &GetAngles(int) const;
|
||||
virtual void GetRenderBBox(Vec3d &,Vec3d &);
|
||||
virtual float GetRenderRadius(void) const;
|
||||
virtual bool DrawEntity(const SRendParams &) { return true; };
|
||||
virtual bool IsStatic(void) const { return false; };
|
||||
virtual bool IsEntityHasSomethingToRender(void) { return false; }
|
||||
virtual bool IsEntityAreasVisible(void) { return true; }
|
||||
virtual IPhysicalEntity *GetPhysics(void) const { return 0; }
|
||||
virtual void SetPhysics(IPhysicalEntity *) { }
|
||||
virtual void SetMaterial(IMatInfo *) { }
|
||||
virtual IMatInfo *GetMaterial(void) const { return 0; }
|
||||
virtual class CDLight * GetLight() { return m_pLight; }
|
||||
virtual float GetMaxViewDist();
|
||||
virtual void PreloadInstanceResources(Vec3d vPrevPortalPos, float fPrevPortalDistance, float fTime){}
|
||||
|
||||
CLightEntity();
|
||||
~CLightEntity();
|
||||
|
||||
CDLight * m_pLight;
|
||||
Vec3d m_vPos;
|
||||
};
|
||||
|
||||
struct SLevelInfo
|
||||
{
|
||||
float
|
||||
m_fSkyBoxAngle,
|
||||
m_fSkyBoxStretching,
|
||||
m_fSunHeightScale,
|
||||
m_fWaterTranspRatio,
|
||||
m_fWaterReflectRatio,
|
||||
m_fWaterBumpAmountX,
|
||||
m_fWaterBumpAmountY,
|
||||
m_fWaterBorderTranspRatio,
|
||||
m_fUnderWaterFogDistance;
|
||||
float
|
||||
m_fFogNearDist,
|
||||
m_fFogFarDist,
|
||||
m_fMaxViewDist;
|
||||
float
|
||||
m_fDefFogNearDist,
|
||||
m_fDefFogFarDist,
|
||||
m_fDefMaxViewDist;
|
||||
float m_fWorldColorRatio;
|
||||
|
||||
Vec3d m_vUnderWaterFogColor;
|
||||
Vec3d m_vFogColor;
|
||||
Vec3d m_vDefFogColor;
|
||||
Vec3d m_vSunPosition;
|
||||
Vec3d m_vWorldColorConst;
|
||||
Vec3d m_vWindForce;
|
||||
IShader *m_pSHFullScreenQuad;
|
||||
int m_nWaterBottomTexId;
|
||||
int m_nShadowSpotTexId;
|
||||
bool m_bOceanCaustics;
|
||||
};
|
||||
|
||||
struct SLevelShaders
|
||||
{
|
||||
IShader
|
||||
* m_pTerrainWaterShader,
|
||||
* m_pSunRoadShader,
|
||||
* m_pSHTerrainParticles;
|
||||
};
|
||||
|
||||
struct SRenderElements
|
||||
{
|
||||
CRESky * m_pRESky;
|
||||
//CREOutSpace * m_pREOutSpace;
|
||||
CREShadowMapGen * m_pREShadowMapGenerator;
|
||||
CREDummy * m_pREDummy;
|
||||
CRETerrainParticles * m_pRETerrainParticles;
|
||||
CRE2DQuad * m_pRE2DQuad;
|
||||
CLeafBuffer * m_pFogTopPlane;
|
||||
|
||||
// tiago: added
|
||||
CREScreenProcess * m_pREScreenProcess;
|
||||
|
||||
IShader * m_pSHDefault;
|
||||
|
||||
IShader * m_pSHScreenTexMap;
|
||||
IShader * m_pSHScreenProcess;
|
||||
IShader * m_pSHOutSpace;
|
||||
IShader * m_pSHFarTreeSprites;
|
||||
IShader * m_pSHClearStencil;
|
||||
IShader * m_pSHShadowMapGen;
|
||||
IShader * m_pSHBinocularDistortMask;
|
||||
IShader * m_pSHScreenDistort;
|
||||
IShader * m_pSHSniperDistortMask;
|
||||
IShader * m_pSHRainMap;
|
||||
|
||||
IShader * m_pSHStencil;
|
||||
IShader * m_pSHStencilState;
|
||||
IShader * m_pSHStencilStateInv;
|
||||
|
||||
IShader * m_pSHSky;
|
||||
IShader * m_pSHLensFlares;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class C3DEngine : public I3DEngine,
|
||||
public SLevelInfo,
|
||||
public SLevelShaders,
|
||||
public SRenderElements,
|
||||
public Cry3DEngineBase
|
||||
{
|
||||
// IProcess Implementation
|
||||
void SetFlags(int flags) { m_nFlags=flags; }
|
||||
int GetFlags(void) { return m_nFlags; }
|
||||
int m_nFlags;
|
||||
|
||||
public:
|
||||
|
||||
// I3DEngine interface implementation
|
||||
virtual void Enable(bool bEnable) { m_bEnabled = bEnable; };
|
||||
virtual bool Init();
|
||||
virtual void Update();
|
||||
virtual void Draw();
|
||||
virtual void ShutDown(bool bEditorMode=false);
|
||||
virtual void Release() { delete this; };
|
||||
virtual void SetLevelPath( const char * szFolderName );
|
||||
virtual bool LoadLevel(const char * szFolderName, const char * szMissionName, bool bEditorMode);
|
||||
virtual void SetCamera(const CCamera &cam, bool bToTheScreen); // The game set this camera
|
||||
virtual void DisplayInfo(float & fTextPosX, float & fTextPosY, float & fTextStepY);
|
||||
virtual void SetupDistanceFog();
|
||||
virtual IStatObj * MakeObject(const char * szFileName, const char * szGeomName = 0,
|
||||
EVertsSharing eVertsSharing = evs_ShareAndSortForCache,
|
||||
bool bLoadAdditinalInfo = true,
|
||||
bool bKeepInLocalSpace = false);
|
||||
virtual IStatObj* MakeObject();
|
||||
virtual bool ReleaseObject(IStatObj * pObject);
|
||||
virtual void RegisterEntity( IEntityRender * pEntityRS );
|
||||
virtual bool UnRegisterEntity( IEntityRender * pEntityRS );
|
||||
virtual float GetWaterLevel(const Vec3d * pvPos = NULL, Vec3d * pvFlowDir = NULL);
|
||||
virtual float GetWaterLevel(IEntityRender * pEntityRender, Vec3d * pvFlowDir = NULL);
|
||||
virtual void SpawnParticles(const ParticleParams & SpawnParticleParams);
|
||||
virtual void CreateDecal( const CryEngineDecalInfo& Decal );
|
||||
virtual void DrawTerrainDetailTextureLayers();
|
||||
virtual void DrawFarTrees();
|
||||
virtual void DrawTerrainParticles(IShader * pShader);
|
||||
virtual void SetRenderCallback(void (*pFunc)(void *pParams), void *pParams) { m_pRenderCallbackFunc = pFunc; m_pRenderCallbackParams = pParams; }
|
||||
virtual void DrawLowDetail(const int & DrawFlags);
|
||||
virtual float GetTerrainElevation(float x, float y);
|
||||
virtual float GetTerrainZ(int x, int y);
|
||||
virtual int GetHeightMapUnitSize();
|
||||
virtual int GetTerrainSize();
|
||||
virtual float GetMaxViewDist();
|
||||
virtual void ActivateLight(const char *szName,bool bActivate);
|
||||
virtual bool IsCharacterFile(const char * szCGFileName);
|
||||
virtual bool IsPointInWater(Vec3d vPos); // todo: remove it
|
||||
virtual Vec3d GetSunPosition(bool bMoveUp = true);
|
||||
virtual ICryCharInstance * MakeCharacter(const char * cid_file_name, unsigned int dwFlags = 0);
|
||||
virtual void RemoveCharacter(ICryCharInstance * pCryCharInstance);
|
||||
virtual Vec3d GetWorldColor( bool bScaled=true );
|
||||
virtual void SetWorldColor(Vec3d vColor);
|
||||
virtual void SetOutdoorAmbientColor(Vec3d vColor);
|
||||
virtual void SetWorldColorRatio(float fWorldColorRatio);
|
||||
virtual float GetWorldColorRatio();
|
||||
virtual void SetSkyBox(const char * szSkyBoxShaderName);
|
||||
virtual void OnExplosion(Vec3d vPos, Vec3 vHitDir, float fRadius, int nTexID, bool bDeformTerrain);
|
||||
virtual void SetScreenShader(const char * szShaderName);
|
||||
//! For editor
|
||||
virtual bool AddStaticObject(int nObjectID, const Vec3d & vPos, const float fScale, uchar ucBright);
|
||||
virtual bool RemoveStaticObject(int nObjectID, const Vec3d & vPos);
|
||||
virtual bool PhysicalizeStaticObject(void *pForeignData,int iForeignData,int iForeignFlags);
|
||||
virtual void RemoveAllStaticObjects();
|
||||
virtual void SetTerrainSurfaceType(int x, int y, int nType);
|
||||
virtual int GetTerrainSurfaceType(int x, int y);
|
||||
virtual void SetTerainHightMapBlock(int x1, int y1, int nSizeX, int nSizeY, ushort * TerrainBlock, ushort nUpdateMask);
|
||||
virtual int LockTerrainSectorTexture(int nSectorOriginX, int nSectorOriginY, int & nTexDim);
|
||||
virtual void SetPhysMaterialEnumerator(IPhysMaterialEnumerator * pPhysMaterialEnumerator);
|
||||
virtual IPhysMaterialEnumerator * GetPhysMaterialEnumerator();
|
||||
virtual void LoadEnvironmentSettingsFromXML(const char * szMissionName, bool bEditorMode, const char * szMissionXMLString, bool bUpdateLightingOnVegetations);
|
||||
virtual void AddDynamicLightSource(const class CDLight & LSource, IEntityRender * pEnt, int nEntityLightId=-1, const Matrix44 * pMatrix=NULL);
|
||||
virtual void ApplyForceToEnvironment(Vec3d vPos, float fRadius, float fAmountOfForce);
|
||||
virtual bool UnRegisterInAllSectors(IEntityRender * pEntityRS);
|
||||
virtual bool MakeSectorLightMap(int nSectorOriginX, int nSectorOriginY, unsigned char * pImage, int nImageSize);
|
||||
virtual void SetMaxViewDistance(float fMaxViewDistance);
|
||||
virtual float GetMaxViewDistance( );
|
||||
virtual void SetFogColor(const Vec3d& vFogColor);
|
||||
virtual void SetFogStart(const float fFogStart);
|
||||
virtual void SetFogEnd(const float fFogEnd);
|
||||
virtual Vec3d GetFogColor( );
|
||||
virtual float GetFogStart( );
|
||||
virtual float GetFogEnd( );
|
||||
virtual float GetDistanceToSectorWithWater();
|
||||
virtual void SetSkyBoxAlpha(float fAlpha);
|
||||
virtual void SetBFCount(int nCount);
|
||||
virtual int GetBFCount();
|
||||
virtual void SetGrasshopperCount(int nCount);
|
||||
virtual int GetGrasshopperCount();
|
||||
virtual Vec3d GetOutdoorAmbientColor();
|
||||
virtual Vec3d GetSunColor();
|
||||
virtual uint GetLightMaskFromPosition(const Vec3d & vPos, float fRadius);
|
||||
virtual Vec3d GetAmbientColorFromPosition(const Vec3d & vPos, float fRadius);
|
||||
virtual void ClearRenderResources(bool bEditor);
|
||||
virtual void FreeEntityRenderState(IEntityRender * pEntityRS);
|
||||
virtual IEntityRenderState * MakeEntityRenderState();
|
||||
virtual void SetGrasshopperCGF( int nSlot, IStatObj * pStatObj );
|
||||
virtual IParticleEmitter* CreateParticleEmitter();
|
||||
virtual void DeleteParticleEmitter(IParticleEmitter* pPartEmitter);
|
||||
virtual const char * GetLevelFilePath(const char * szFileName);
|
||||
virtual void MakeUnderWaterSmoothHMap(int nWaterUnitSize);
|
||||
virtual ushort * GetUnderWaterSmoothHMap(int & nDimensions);
|
||||
virtual void SetTerrainBurnedOut(int x, int y, bool bBurnedOut);
|
||||
virtual bool IsTerrainBurnedOut(int x, int y);
|
||||
virtual void UpdateDetailObjects();
|
||||
virtual int GetTerrainSectorSize();
|
||||
virtual void AddWaterSplash (Vec3d vPos, eSplashType eST, float fForce, int Id);
|
||||
virtual class IEdgeConnectivityBuilder *GetNewConnectivityBuilder( void );
|
||||
//! creates a connectivity object that can be used to deserialize the connectivity data
|
||||
virtual class IStencilShadowConnectivity *NewConnectivity();
|
||||
virtual class IEdgeConnectivityBuilder *GetNewStaticConnectivityBuilder( void );
|
||||
virtual class IEdgeDetector *GetEdgeDetector( void );
|
||||
virtual void LoadTerrainSurfacesFromXML(void * pDoc);
|
||||
virtual void EnableHeatVision(bool bEnable);
|
||||
virtual int GetTerrainTextureDim();
|
||||
virtual bool SetStatInstGroup(int nGroupId, const IStatInstGroup & siGroup);
|
||||
virtual bool GetStatInstGroup(int nGroupId, IStatInstGroup & siGroup);
|
||||
virtual void ActivatePortal(const Vec3d &vPos, bool bActivate, IEntityRender *pEntity);
|
||||
virtual void GetMemoryUsage(class ICrySizer * pSizer);
|
||||
virtual IWaterVolume * CreateWaterVolume();
|
||||
virtual void DeleteWaterVolume(IWaterVolume * pWaterVolume);
|
||||
virtual IWaterVolume * FindWaterVolumeByName(const char * szName);
|
||||
virtual IVisArea * CreateVisArea();
|
||||
virtual void DeleteVisArea(IVisArea * pVisArea);
|
||||
virtual void UpdateVisArea(IVisArea * pArea, const Vec3d * pPoints, int nCount, const char * szName, float fHeight, const Vec3d & vAmbientColor, bool bAfectedByOutLights, bool bSkyOnly, const Vec3 & vDynAmbientColor, float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors);
|
||||
virtual int GetFogVolumeIdFromBBox(const Vec3d & vBoxMin, const Vec3d & vBoxMax); // todo: remove
|
||||
virtual void ResetParticlesAndDecals( );
|
||||
virtual IEntityRender * CreateEntityRender();
|
||||
virtual IEntityRender * CreateVegetation();
|
||||
virtual void DeleteEntityRender(IEntityRender * pEntityRender);
|
||||
virtual void DrawRain();
|
||||
virtual void SetRainAmount( float fAmount );
|
||||
virtual void SetWindForce( const Vec3d & vWindForce );
|
||||
virtual float GetLightAmountForEntity(IEntityRender * pEntity, bool bOnlyVisibleLights);
|
||||
virtual float GetAmbientLightAmountForEntity(IEntityRender * pEntity);
|
||||
virtual IVisArea * GetVisAreaFromPos(const Vec3d &vPos);
|
||||
virtual bool IsVisAreasConnected(IVisArea * pArea1, IVisArea * pArea2, int nMaxReqursion, bool bSkipDisabledPortals);
|
||||
virtual ILMSerializationManager * CreateLMSerializationManager();
|
||||
void EnableOceanRendering(bool bOcean, bool bShore); // todo: remove
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Materials access.
|
||||
virtual IMatInfo* CreateMatInfo();
|
||||
virtual void DeleteMatInfo(IMatInfo * pMatInfo);
|
||||
virtual void RenameMatInfo( IMatInfo *pMtl,const char *sNewName );
|
||||
virtual IMatInfo* FindMaterial( const char *sMaterialName );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ParticleEffect
|
||||
virtual IParticleEffect* CreateParticleEffect();
|
||||
virtual void DeleteParticleEffect( IParticleEffect* pEffect );
|
||||
virtual IParticleEffect* FindParticleEffect( const char *sEffectName );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual INT_PTR AddStaticLightSource(const class CDLight & LSource, IEntityRender * pCreator, ICryCharInstance * pCryCharInstance, const char * szBoneName); //AMD Port
|
||||
virtual bool DeleteStaticLightSource(INT_PTR nLightId); //AMD Port
|
||||
virtual const list2<CDLight*> * GetStaticLightSources();
|
||||
virtual bool IsTerainHightMapModifiedByGame();
|
||||
virtual bool IsPotentiallyVisible(IEntityRender * pEntityRender, float fAdditionRadius=0 );
|
||||
virtual void UpdateBeaches();
|
||||
virtual void RestoreTerrainFromDisk();
|
||||
virtual void CheckMemoryHeap();
|
||||
virtual void RecompileBeaches();
|
||||
virtual float GetObjectsLODRatio();
|
||||
virtual float GetObjectsViewDistRatio();
|
||||
virtual bool SetMaterialFloat( char * szMatName, int nSubMatId, int nTexSlot, char * szParamName, float fValue );
|
||||
virtual void CloseTerrainTextureFile();
|
||||
virtual int GetLoadedObjectCount();
|
||||
virtual void DeleteEntityDecals(IEntityRender * pEntity);
|
||||
virtual void DeleteDecalsInRange( Vec3d vBoxMin, Vec3d vBoxMax, bool bDeleteBigTerrainDecals = true);
|
||||
virtual const void * GetShoreGeometry(int & nPosStride, int & nVertCount, int nSectorX, int nSectorY);
|
||||
virtual void OnLevelLoaded();
|
||||
virtual void LockCGFResources();
|
||||
virtual void UnlockCGFResources();
|
||||
virtual float GetObjectsMinViewDist();
|
||||
|
||||
// tiago: added
|
||||
virtual void SetBlurMask(ITexPic *pMask);
|
||||
virtual void SetScreenMask(ITexPic *pMask);
|
||||
virtual void SetScreenFx(const char *pEffectName, int iActive);
|
||||
virtual void SetScreenFxParam(const char *pEffectName, const char *pEffectParam, void *pValue);
|
||||
virtual int GetScreenFx(const char *pEffectName);
|
||||
virtual int GetScreenFxParam(const char *pEffectName, const char *pEffectParam, void *&pValue);
|
||||
virtual void ResetScreenFx(void);
|
||||
|
||||
bool SaveCGF(std::vector<IStatObj *>& pObjs);
|
||||
|
||||
int GetCurrentSpec()
|
||||
{
|
||||
if (m_pSysSpec)
|
||||
return m_pSysSpec->GetIVal();
|
||||
return 3; // very high spec.
|
||||
}
|
||||
|
||||
int GetCurrentLightSpec()
|
||||
{
|
||||
if (m_pLightQuality)
|
||||
return m_pLightQuality->GetIVal();
|
||||
return 3; // very high spec.
|
||||
}
|
||||
|
||||
public:
|
||||
C3DEngine( ISystem * pSystem );
|
||||
~C3DEngine();
|
||||
|
||||
void RenderScene(unsigned int dwDrawFlags);
|
||||
CDLight * CheckDistancesToLightSources(uint & nDLightMask, const Vec3d vObjPos, const float fObjRadius, IEntityRender * pEntityRender = 0, int nMaxLightBitsNum = 8, CDLight ** pSelectedLights = NULL, int nMaxSelectedLights = 0, Vec3d * pvSummLightAmmount = NULL);
|
||||
uint GetFullLightMask();
|
||||
bool IsOutdoorVisible();
|
||||
void RenderSkyBox(IShader *pSH);
|
||||
void RenderOutSpace();
|
||||
|
||||
// access to components
|
||||
CTerrain * GetTerrain() { return m_pTerrain; }
|
||||
CObjManager * GetObjManager() { return m_pObjManager; }
|
||||
CVars * GetCVars() { return m_pCVars; }
|
||||
CVisAreaManager * GetVisAreaManager() { return m_pVisAreaManager; }
|
||||
CMatMan * GetMatMan() { return m_pMatMan; }
|
||||
|
||||
private:
|
||||
|
||||
// misc
|
||||
CCObject *m_SunObject[8],
|
||||
*m_pBlurObj,
|
||||
*m_pScreenObj;
|
||||
|
||||
int m_nStreamingIconTexID, m_nBlackTexID;
|
||||
char m_sGetLevelFilePathTmpBuff[MAX_PATH_LENGTH];
|
||||
char m_szLevelFolder[_MAX_PATH];
|
||||
list2<DLightAmount> m_lstDL_CDTLS;
|
||||
static double m_dLoadLevelTime;
|
||||
bool m_bOcean; // todo: remove
|
||||
bool m_bShore; // todo: remove
|
||||
int m_bTerrainLightMapGenError;
|
||||
bool m_bEnabled;
|
||||
|
||||
// interfaces
|
||||
IPhysMaterialEnumerator * m_pPhysMaterialEnumerator;
|
||||
// this is the shared instance that will calculate the shadows
|
||||
// created/freed during class initialization/deinitialization
|
||||
class IEdgeDetector * m_pShadowEdgeDetector; //!< to get rid of the new/delete
|
||||
class IEdgeConnectivityBuilder * m_pConnectivityBuilder; //!< to get rid of the new/delete
|
||||
class IEdgeConnectivityBuilder * m_pStaticConnectivityBuilder;
|
||||
|
||||
// data containers
|
||||
list2<CDLight> m_lstDynLights;
|
||||
list2<CDLight> m_lstDynLightsNoLight;
|
||||
int m_nRealLightsNum;
|
||||
list2<CLightEntity*> m_lstStaticLights;
|
||||
#define MAX_LIGHTS_NUM 32
|
||||
CCamera m_arrCameraProjectors[MAX_LIGHTS_NUM];
|
||||
|
||||
// 3dengine components
|
||||
CTerrain * m_pTerrain;
|
||||
CObjManager * m_pObjManager;
|
||||
CPartManager * m_pPartManager;
|
||||
CDecalManager * m_pDecalManager;
|
||||
// CBFManager * m_pBFManager;
|
||||
CRainManager * m_pRainManager;
|
||||
CVisAreaManager* m_pVisAreaManager;
|
||||
CVars * m_pCVars;
|
||||
CMatMan * m_pMatMan;
|
||||
|
||||
ICVar* m_pSysSpec;
|
||||
ICVar* m_pLightQuality;
|
||||
|
||||
// not sorted
|
||||
|
||||
void (*m_pRenderCallbackFunc)(void *pParams);
|
||||
void *m_pRenderCallbackParams;
|
||||
|
||||
//! Saving of cgf file
|
||||
bool WriteMaterials(TArray<CHUNK_HEADER>& Chunks, TArray<IShader *>& Shaders, FILE *out, int &MatChunk);
|
||||
bool WriteNodes(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame, std::vector<IStatObj *>& pObjs);
|
||||
bool WriteMesh(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, TArray<IShader *>& Shaders, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame);
|
||||
bool WriteNodeMesh(int nNode, MESH_CHUNK_DESC *chunk, FILE *out, TArray<IShader *>& Shaders, TArray<SNodeInfo>& NI, struct CStatObj *pObj);
|
||||
bool WriteLights(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, std::vector<IStatObj *>& pObjs);
|
||||
|
||||
void DrawFullScreenQuad(IShader *pShader, bool bRectangle, EF_Sort eSort = eS_Unknown);
|
||||
|
||||
void LoadMissionSettingsFromXML(struct XDOM::IXMLDOMNode *pInputNode, bool bEditorMode, bool bUpdateLightingOnVegetations);
|
||||
char * GetXMLAttribText(XDOM::IXMLDOMNode * pInputNode, const char * szLevel0,const char * szLevel1,const char * szLevel2,const char * szDefaultValue);
|
||||
|
||||
void RegisterLightSourceInSectors(CDLight * pDynLight);
|
||||
void LightSourcesDebug();
|
||||
void RenderVolumeFogTopPlane();
|
||||
Vec3d GetTerrainSurfaceNormal(Vec3d vPos) { return m_pTerrain ? m_pTerrain->GetTerrainSurfaceNormal(vPos) : Vec3d(0,0,0); }
|
||||
|
||||
void RenderTerrainParticles();
|
||||
bool IsBoxVisibleOnTheScreen(const Vec3d & vBoxMin, const Vec3d & vBoxMax, OcclusionTestClient * pOcclusionTestClient );
|
||||
bool IsSphereVisibleOnTheScreen(const Vec3d & vPos, const float fRadius, OcclusionTestClient * pOcclusionTestClient );
|
||||
|
||||
bool IsCameraAnd3DEngineInvalid(const CCamera cam, const char * szCaller);
|
||||
|
||||
void LoadFogVolumesFromXML(XDOM::IXMLDOMDocumentPtr pDoc);
|
||||
|
||||
void UpdateScene(bool bAddStaticLights = true, bool bAlwaysAddSun = false);
|
||||
|
||||
void MakeHiResScreenShot();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SetupLightScissors(CDLight *pLight);
|
||||
|
||||
bool IsOutdoorsVisible();
|
||||
|
||||
void UpdateStaticLightSources();
|
||||
void DeleteAllStaticLightSources();
|
||||
bool LoadStaticLightSources(const char *pszFileName);
|
||||
void LoadParticleEffects( XmlNodeRef &levelDataRoot,bool bEditorMode );
|
||||
|
||||
public:
|
||||
|
||||
void UpdateLightSources();
|
||||
void PrepareLightSourcesForRendering();
|
||||
|
||||
void FreeLightSourceComponents(CDLight *pLight);
|
||||
void RemoveEntityLightSources(IEntityRender * pEntity);
|
||||
|
||||
void CheckPhysicalized(const Vec3d & vBoxMin, const Vec3d & vBoxMax);
|
||||
|
||||
list2<CDLight> * GetDynamicLightSources() { return &m_lstDynLights; }
|
||||
void ProcessScreenEffects();
|
||||
int GetRealLightsNum() { return m_nRealLightsNum; }
|
||||
void CaptureFrameBufferToFile();
|
||||
void DrawShadowSpotOnTerrain(Vec3d vPos, float fRadius);
|
||||
void SetupClearColor();
|
||||
void DrawText(float x, float y, const char * format, ...);
|
||||
};
|
||||
|
||||
#endif // C3DENGINE_H
|
||||
792
Cry3DEngine/3dEngineLoad.cpp
Normal file
792
Cry3DEngine/3dEngineLoad.cpp
Normal file
@@ -0,0 +1,792 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: 3dengineload.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Level loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_water.h"
|
||||
#include "CryStaticModel.h"
|
||||
#include "partman.h"
|
||||
#include "DecalManager.h"
|
||||
#include "bflyes.h"
|
||||
#include "detail_grass.h"
|
||||
#include "rain.h"
|
||||
#include <IXMLDOM.h>
|
||||
#include "watervolumes.h"
|
||||
#include "brush.h"
|
||||
#include "LMCompStructures.h"
|
||||
|
||||
#define LEVEL_DATA_FILE "LevelData.xml"
|
||||
#define CUSTOM_MATERIALS_FILE "Materials.xml"
|
||||
#define PARTICLES_FILE "particles.lst"
|
||||
#define EFFECTS_FOLDER "Effects"
|
||||
#define SHARED_PARTICLES_EXPLOSIONS "Explosions"
|
||||
#define SHARED_PARTICLES_WATER "Water"
|
||||
#define SHARED_PARTICLES_SMOKE "Smoke"
|
||||
#define SHARED_PARTICLES_BLOOD "Blood"
|
||||
#define SHARED_PARTICLES_BULLET "Bullet"
|
||||
#define SHARED_PARTICLES_MISC "Misc"
|
||||
#define SHARED_PARTICLES_FIRE "Fire"
|
||||
|
||||
double C3DEngine::m_dLoadLevelTime = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void C3DEngine::ClearRenderResources( bool bEditorMode )
|
||||
{
|
||||
// GetLog()->Log("\003*** Clearing render resources ***");
|
||||
|
||||
// GetSystem()->GetIAnimationSystem()-> ;
|
||||
|
||||
// ShutDown(false);
|
||||
|
||||
//if(GetRenderer())
|
||||
// GetRenderer()->FreeResources(FRR_SHADERS | FRR_TEXTURES | FRR_RESTORE);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if(m_pVisAreaManager)
|
||||
{
|
||||
UpdateLoadingScreen("Deleting VisAreaManager ...");
|
||||
delete m_pVisAreaManager;
|
||||
UpdateLoadingScreenPlus(" Ok");
|
||||
m_pVisAreaManager=0;
|
||||
}
|
||||
|
||||
if (m_pObjManager)
|
||||
{
|
||||
SAFE_DELETE( m_pObjManager->m_pCWaterVolumes );
|
||||
}
|
||||
|
||||
// delete terrain
|
||||
if(m_pTerrain)
|
||||
{
|
||||
UpdateLoadingScreen("Deleting terrain ...");
|
||||
SAFE_DELETE( m_pTerrain );
|
||||
UpdateLoadingScreenPlus(" Ok");
|
||||
}
|
||||
|
||||
// free vegetations
|
||||
if(!bEditorMode)
|
||||
{
|
||||
if (m_pObjManager)
|
||||
m_pObjManager->UnloadVegetations();
|
||||
}
|
||||
|
||||
if (m_pPartManager)
|
||||
{
|
||||
m_pPartManager->Reset();
|
||||
if (!bEditorMode)
|
||||
{
|
||||
SAFE_DELETE( m_pPartManager );
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE( m_pDecalManager );
|
||||
|
||||
// Load Materials Library from LevelData.xml
|
||||
if (!bEditorMode)
|
||||
{
|
||||
SAFE_DELETE( m_pMatMan );
|
||||
m_pMatMan = new CMatMan();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Purge destroyed physics entities.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
GetSystem()->GetIPhysicalWorld()->PurgeDeletedEntities();
|
||||
|
||||
// print warnings
|
||||
if (m_pObjManager)
|
||||
m_pObjManager->CheckObjectLeaks();
|
||||
|
||||
GetRenderer()->PreLoad();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void C3DEngine::SetLevelPath( const char * szFolderName )
|
||||
{
|
||||
// make folder path
|
||||
assert(strlen(szFolderName) < 1024);
|
||||
strcpy( m_szLevelFolder,szFolderName );
|
||||
if (strlen(m_szLevelFolder) > 0)
|
||||
{
|
||||
if (m_szLevelFolder[strlen(m_szLevelFolder)-1] != '/')
|
||||
strcat( m_szLevelFolder,"/" );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool C3DEngine::LoadLevel(const char * szFolderName, const char * szMissionName, bool bEditorMode)
|
||||
{
|
||||
AUTO_PROFILE_SECTION(GetTimer(), m_dLoadLevelTime);
|
||||
|
||||
m_bIgnoreFakeMaterialsInCGF = !bEditorMode;
|
||||
m_bEditorMode = bEditorMode;
|
||||
|
||||
GetRenderer()->MakeCurrent();
|
||||
|
||||
if(!szFolderName || !szFolderName[0])
|
||||
{ Warning( 0,0,"C3DEngine::LoadLevel: Level name is not specified"); return 0; }
|
||||
|
||||
if(!szMissionName || !szMissionName[0])
|
||||
{ Warning( 0,0,"C3DEngine::LoadLevel: Mission name is not specified"); }
|
||||
|
||||
char szMissionNameBody[256] = "NoMission";
|
||||
if(!szMissionName)
|
||||
szMissionName = szMissionNameBody;
|
||||
|
||||
SetLevelPath( szFolderName );
|
||||
|
||||
if(!bEditorMode)
|
||||
{ // check is LevelData.xml file exist
|
||||
char sMapFileName[_MAX_PATH];
|
||||
strcpy(sMapFileName,m_szLevelFolder);
|
||||
strcat(sMapFileName,LEVEL_DATA_FILE);
|
||||
if(!CXFile::IsFileExist(sMapFileName))
|
||||
{ UpdateLoadingScreen("Error: Level not found: %s", sMapFileName); return 0; }
|
||||
}
|
||||
|
||||
if(!m_pObjManager)
|
||||
m_pObjManager = new CObjManager (this);
|
||||
|
||||
if(!bEditorMode)
|
||||
{
|
||||
if(m_pVisAreaManager)
|
||||
{
|
||||
UpdateLoadingScreen("Deleting VisAreaManager ...");
|
||||
delete m_pVisAreaManager;
|
||||
UpdateLoadingScreenPlus(" Ok");
|
||||
m_pVisAreaManager=0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_pVisAreaManager)
|
||||
m_pVisAreaManager = new CVisAreaManager( );
|
||||
|
||||
assert (GetSystem()->GetIAnimationSystem());
|
||||
|
||||
if(!bEditorMode)
|
||||
{
|
||||
int nCellSize = 4;
|
||||
GetPhysicalWorld()->SetupEntityGrid(2,vectorf(0,0,0), // this call will destroy all physicalized stuff
|
||||
CTerrain::GetTerrainSize()/nCellSize,CTerrain::GetTerrainSize()/nCellSize,(float)nCellSize,(float)nCellSize);
|
||||
}
|
||||
|
||||
// cache prev terrain objects
|
||||
list2<struct IEntityRender*> lstTerrainObjects;
|
||||
if(bEditorMode && m_pTerrain)
|
||||
m_pTerrain->GetObjects(&lstTerrainObjects);
|
||||
|
||||
// delete terrain
|
||||
if(m_pTerrain)
|
||||
{
|
||||
UpdateLoadingScreen("Deleting terrain ...");
|
||||
delete m_pTerrain; m_pTerrain=0;
|
||||
UpdateLoadingScreenPlus(" Ok");
|
||||
}
|
||||
|
||||
// free vegetations
|
||||
if(!bEditorMode)
|
||||
m_pObjManager->UnloadVegetations();
|
||||
|
||||
// print level name into console
|
||||
char header[512];
|
||||
snprintf(header, sizeof(header),
|
||||
"\001---------------------- Loading level %s, mission %s ------------------------------------",
|
||||
szFolderName, szMissionName);
|
||||
header[100]=0;
|
||||
UpdateLoadingScreen(header);
|
||||
|
||||
// print warnings
|
||||
m_pObjManager->CheckObjectLeaks();
|
||||
|
||||
// create terrain
|
||||
m_pTerrain = new CTerrain( );
|
||||
m_pObjManager->m_pTerrain = m_pTerrain;
|
||||
if(m_pTerrain && !m_pTerrain->LoadTerrain(bEditorMode))
|
||||
{ // terrain not found
|
||||
delete m_pTerrain;
|
||||
m_pTerrain = 0;
|
||||
}
|
||||
|
||||
// restore prev terrain objects
|
||||
for(int i=0; i<lstTerrainObjects.Count(); i++)
|
||||
{
|
||||
lstTerrainObjects[i]->m_pSector = 0;
|
||||
Get3DEngine()->RegisterEntity(lstTerrainObjects[i]);
|
||||
}
|
||||
|
||||
lstTerrainObjects.Reset();
|
||||
|
||||
//
|
||||
m_pObjManager->m_lstVegetContainer.Reset();
|
||||
m_pObjManager->m_lstBrushContainer.Reset();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Load LevelData.xml File.
|
||||
XmlNodeRef levelDataRoot = GetSystem()->LoadXmlFile( GetLevelFilePath(LEVEL_DATA_FILE) );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Load Materials Library from LevelData.xml
|
||||
if (!bEditorMode)
|
||||
{
|
||||
delete m_pMatMan;
|
||||
m_pMatMan = new CMatMan();
|
||||
m_pMatMan->LoadMaterialsLibrary( GetLevelFilePath(CUSTOM_MATERIALS_FILE),levelDataRoot );
|
||||
}
|
||||
|
||||
{ // recreate particles and decals
|
||||
if(m_pPartManager)
|
||||
m_pPartManager->Reset();
|
||||
else
|
||||
m_pPartManager = new CPartManager();
|
||||
|
||||
delete m_pDecalManager;
|
||||
m_pDecalManager = new CDecalManager (this);
|
||||
}
|
||||
|
||||
LoadParticleEffects( levelDataRoot,bEditorMode );
|
||||
|
||||
// load leveldata.xml
|
||||
m_pTerrainWaterShader=m_pSunRoadShader=0;
|
||||
m_nWaterBottomTexId=0;
|
||||
LoadEnvironmentSettingsFromXML(szMissionName, bEditorMode, 0, true);
|
||||
|
||||
// init water if not initialized already (if no mission was found)
|
||||
if(m_pTerrain && !m_pTerrain->m_pWater)
|
||||
m_pTerrain->InitTerrainWater(bEditorMode,
|
||||
m_pTerrainWaterShader, m_nWaterBottomTexId, m_pSunRoadShader,
|
||||
m_fWaterTranspRatio, m_fWaterReflectRatio,
|
||||
m_fWaterBumpAmountX, m_fWaterBumpAmountY, m_fWaterBorderTranspRatio);
|
||||
|
||||
m_pObjManager->m_pTerrain = m_pTerrain;
|
||||
/* if (!m_pTerrain)
|
||||
{
|
||||
// [marco] Vlad check why it crashes here
|
||||
CryError("3dengine:Cannot Load terrain - report this to Vladimir Kajalin");
|
||||
}*/
|
||||
|
||||
if(m_pTerrain)
|
||||
m_pTerrain->SetObjManager(m_pObjManager);
|
||||
|
||||
m_pVisAreaManager->SetupFogVolumes(m_pTerrain);
|
||||
if(m_pObjManager->m_pCWaterVolumes)
|
||||
m_pObjManager->m_pCWaterVolumes->InitWaterVolumes();
|
||||
|
||||
if(!bEditorMode)
|
||||
{
|
||||
// load static object bodies
|
||||
m_pObjManager->LoadVegetationModels(szMissionName,bEditorMode);
|
||||
|
||||
// load lsources used for lightmaps
|
||||
#if !defined(LINUX64)//fails due to different size of CDLight (pointers have 8 bytes)
|
||||
LoadStaticLightSources(GetLevelFilePath("StatLights.dat"));
|
||||
#endif
|
||||
// bushes bodies and instances
|
||||
m_pObjManager->LoadBrushes();
|
||||
|
||||
// merge brushes grouped in the editor
|
||||
m_pObjManager->MergeBrushes();
|
||||
|
||||
// load positions of static objects, update sectors bboxes
|
||||
m_pTerrain->LoadStatObjInstances();
|
||||
}
|
||||
|
||||
// recreate bugs
|
||||
/* if(m_pTerrain)
|
||||
{
|
||||
delete m_pTerrain->m_pBugsManager;
|
||||
m_pTerrain->m_pBugsManager = new CBugsManager( );
|
||||
}*/
|
||||
|
||||
// physicalise instances of static objects and buildings
|
||||
// m_pObjManager->CreatePhysicalEntitys();
|
||||
|
||||
for(int i=0; i<m_pObjManager->m_lstBrushContainer.Count(); i++)
|
||||
{
|
||||
if (!(m_pObjManager->m_lstBrushContainer[i]->m_dwRndFlags & ERF_MERGED))
|
||||
{
|
||||
Get3DEngine()->UnRegisterEntity(m_pObjManager->m_lstBrushContainer[i]);
|
||||
Get3DEngine()->RegisterEntity(m_pObjManager->m_lstBrushContainer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<m_pObjManager->m_lstVegetContainer.Count(); i++)
|
||||
{
|
||||
Get3DEngine()->UnRegisterEntity(m_pObjManager->m_lstVegetContainer[i]);
|
||||
Get3DEngine()->RegisterEntity(m_pObjManager->m_lstVegetContainer[i]);
|
||||
}
|
||||
|
||||
if(!bEditorMode)
|
||||
{
|
||||
m_pTerrain->SortStaticInstancesBySize();
|
||||
m_pVisAreaManager->SortStaticInstancesBySize();
|
||||
}
|
||||
|
||||
if(GetCVars()->e_stream_areas)
|
||||
{ // all data can be streamed from disk now
|
||||
for(int i=0; i<m_pObjManager->m_lstBrushContainer.Count(); i++)
|
||||
delete m_pObjManager->m_lstBrushContainer[i];
|
||||
m_pObjManager->m_lstBrushContainer.Reset();
|
||||
|
||||
for(int i=0; i<m_pObjManager->m_lstVegetContainer.Count(); i++)
|
||||
delete m_pObjManager->m_lstVegetContainer[i];
|
||||
m_pObjManager->m_lstVegetContainer.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
// from now objects will be stored in the sectors
|
||||
m_pObjManager->m_lstVegetContainer.Reset();
|
||||
m_pObjManager->m_lstBrushContainer.Reset();
|
||||
}
|
||||
|
||||
// restore game state
|
||||
SetRainAmount(0);
|
||||
EnableOceanRendering(true,true);
|
||||
SetSkyBoxAlpha(1.f);
|
||||
m_pObjManager->m_bLockCGFResources = false;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void C3DEngine::LoadTerrainSurfacesFromXML(void * _pDoc)
|
||||
{
|
||||
UpdateLoadingScreen("Loading terrain detail textures ...");
|
||||
|
||||
XDOM::IXMLDOMNodeListPtr pDetTexTagList;
|
||||
XDOM::IXMLDOMNodePtr pDetTexTag;
|
||||
XDOM::IXMLDOMDocumentPtr pDoc = _pDoc ? *((XDOM::IXMLDOMDocumentPtr*)_pDoc) : (XDOM::IXMLDOMDocumentPtr)0;
|
||||
|
||||
if(!_pDoc)
|
||||
{ // load current LevelData if pDoc not specified
|
||||
pDoc = GetSystem()->CreateXMLDocument();
|
||||
if(!pDoc->load(Get3DEngine()->GetLevelFilePath(LEVEL_DATA_FILE)))
|
||||
return;
|
||||
}
|
||||
|
||||
pDetTexTagList = pDoc->getElementsByTagName("SurfaceTypes");
|
||||
if (pDetTexTagList)
|
||||
{
|
||||
pDetTexTagList->reset();
|
||||
pDetTexTag = pDetTexTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pDetTexList;
|
||||
pDetTexList = pDetTexTag->getElementsByTagName("SurfaceType");
|
||||
if (pDetTexList)
|
||||
{
|
||||
pDetTexList->reset();
|
||||
XDOM::IXMLDOMNodePtr pDetTex;
|
||||
int nId = 0;
|
||||
while (pDetTex = pDetTexList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pDetailTextureName = pDetTex->getAttribute("DetailTexture");
|
||||
XDOM::IXMLDOMNodePtr pScaleX = pDetTex->getAttribute("DetailScaleX");
|
||||
XDOM::IXMLDOMNodePtr pScaleY = pDetTex->getAttribute("DetailScaleY");
|
||||
XDOM::IXMLDOMNodePtr pProjAxis = pDetTex->getAttribute("ProjAxis");
|
||||
XDOM::IXMLDOMNodePtr pSurfaceName = pDetTex->getAttribute("Name");
|
||||
|
||||
if(pDetailTextureName) if(pScaleX) if(pScaleY) if(pSurfaceName)
|
||||
{
|
||||
m_pTerrain->SetDetailTextures(nId, pDetailTextureName->getText(),
|
||||
(float)atof(pScaleX->getText()), (float)atof(pScaleY->getText()),
|
||||
pProjAxis ? (pProjAxis->getText())[0] : 0, pSurfaceName->getText());
|
||||
}
|
||||
|
||||
nId++;
|
||||
}
|
||||
}
|
||||
|
||||
// recreate detail objects
|
||||
delete m_pTerrain->m_pDetailObjects;
|
||||
m_pTerrain->m_pDetailObjects = new CDetailGrass(pDetTexTagList);
|
||||
}
|
||||
|
||||
m_pTerrain->InitDetailTextureLayers();
|
||||
|
||||
UpdateLoadingScreenPlus(" ok");
|
||||
}
|
||||
|
||||
void C3DEngine::LoadFogVolumesFromXML(XDOM::IXMLDOMDocumentPtr pDoc)
|
||||
{
|
||||
if(!m_pTerrain)
|
||||
return;
|
||||
|
||||
m_pTerrain->m_lstFogVolumes.Clear();
|
||||
|
||||
{ // make hardcoded volume for ocean
|
||||
VolumeInfo volumeInfo;
|
||||
volumeInfo.vBoxMax = Vec3d( 1000000, 1000000, m_pTerrain->GetWaterLevel());
|
||||
volumeInfo.vBoxMin = Vec3d(-1000000, -1000000, -1000000);
|
||||
// volumeInfo.pShader = 0;
|
||||
volumeInfo.pShader = GetRenderer()->EF_LoadShader("FogLayer", eSH_World, EF_SYSTEM);
|
||||
volumeInfo.vColor = m_vUnderWaterFogColor;
|
||||
volumeInfo.fMaxViewDist = m_fUnderWaterFogDistance;
|
||||
volumeInfo.bOcean = true;
|
||||
volumeInfo.m_bCaustics = m_bOceanCaustics;
|
||||
|
||||
// add volume to list
|
||||
m_pTerrain->m_lstFogVolumes.Add(volumeInfo);
|
||||
}
|
||||
|
||||
XDOM::IXMLDOMNodeListPtr pNodeTagList;
|
||||
XDOM::IXMLDOMNodePtr pNodeTag;
|
||||
pNodeTagList = pDoc->getElementsByTagName("Objects");
|
||||
if (pNodeTagList)
|
||||
{
|
||||
pNodeTagList->reset();
|
||||
pNodeTag = pNodeTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pNodeList;
|
||||
pNodeList = pNodeTag->getElementsByTagName("Object");
|
||||
if (pNodeList)
|
||||
{
|
||||
pNodeList->reset();
|
||||
XDOM::IXMLDOMNodePtr pNode;
|
||||
while (pNode = pNodeList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pName = pNode->getAttribute("Type");
|
||||
if (pName)
|
||||
{
|
||||
if (strstr(pName->getText(),"FogVolume"))
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pAttr;
|
||||
VolumeInfo volumeInfo;
|
||||
pAttr = pNode->getAttribute("Pos");
|
||||
if(pAttr)
|
||||
{
|
||||
Vec3d vPos = StringToVector(pAttr->getText());
|
||||
|
||||
// get properties
|
||||
// XDOM::IXMLDOMNodeListPtr pObjectsTagList = pNode->getElementsByTagName("Properties");
|
||||
// if(pObjectsTagList)
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pAttr1,pAttr2,pAttr3,pAttr4,pAttr5;
|
||||
|
||||
pAttr1 = pNode->getAttribute("ViewDistance");
|
||||
if(pAttr1)
|
||||
volumeInfo.fMaxViewDist = (float)atof(pAttr1->getText());
|
||||
|
||||
pAttr1 = pNode->getAttribute("Width");
|
||||
pAttr2 = pNode->getAttribute("Length");
|
||||
pAttr3 = pNode->getAttribute("Height");
|
||||
pAttr4 = pNode->getAttribute("Shader");
|
||||
pAttr5 = pNode->getAttribute("Color");
|
||||
|
||||
if(pAttr1!=0 && pAttr2!=0 && pAttr3!=0 && pAttr4!=0 && pAttr5!=0)
|
||||
{
|
||||
Vec3d vSize((float)atof(pAttr1->getText()), (float)atof(pAttr2->getText()), (float)atof(pAttr3->getText()));
|
||||
volumeInfo.vBoxMax = vPos + Vec3d(vSize.x*0.5f, vSize.y*0.5f, vSize.z);
|
||||
volumeInfo.vBoxMin = vPos - Vec3d(vSize.x*0.5f, vSize.y*0.5f, 0);
|
||||
volumeInfo.pShader = (char*)pAttr4->getText()[0] ? GetRenderer()->EF_LoadShader((char*)pAttr4->getText(), eSH_World, EF_SYSTEM) : GetRenderer()->EF_LoadShader("FogLayer", eSH_World, EF_SYSTEM);
|
||||
volumeInfo.vColor = StringToVector(pAttr5->getText());
|
||||
|
||||
// add volume to list
|
||||
m_pTerrain->m_lstFogVolumes.Add(volumeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C3DEngine::LoadEnvironmentSettingsFromXML(const char * szMissionName, bool bEditorMode, const char * szMissionXMLString, bool bUpdateLightingOnVegetations)
|
||||
{
|
||||
if(!m_pTerrain)
|
||||
{
|
||||
Warning( 0,0,"Calling C3DEngine::LoadEnvironmentSettingsFromXML while level is not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
GetRenderer()->MakeCurrent();
|
||||
|
||||
// if xml string specified - load settings just from this string
|
||||
if(szMissionXMLString)
|
||||
{
|
||||
XDOM::IXMLDOMDocumentPtr pMissionDoc;
|
||||
pMissionDoc=GetSystem()->CreateXMLDocument();
|
||||
|
||||
// add empty <Mission> tag
|
||||
char * szMissionXMLStringWithMissionTag = new char [strlen(szMissionXMLString)+256];
|
||||
strcpy(szMissionXMLStringWithMissionTag, "<Mission>\n");
|
||||
strcat(szMissionXMLStringWithMissionTag, szMissionXMLString);
|
||||
strcat(szMissionXMLStringWithMissionTag, "</Mission>");
|
||||
|
||||
if (pMissionDoc->loadXML(szMissionXMLStringWithMissionTag))
|
||||
{
|
||||
LoadMissionSettingsFromXML(pMissionDoc, bEditorMode, bUpdateLightingOnVegetations);
|
||||
// load fog volumes (mission shared data)
|
||||
// LoadFogVolumesFromXML(pMissionDoc);
|
||||
// m_pTerrain->InitFogVolumes();
|
||||
}
|
||||
|
||||
delete [] szMissionXMLStringWithMissionTag;
|
||||
return;
|
||||
}
|
||||
|
||||
// load environment settings
|
||||
XDOM::IXMLDOMDocumentPtr pDoc = GetSystem()->CreateXMLDocument();
|
||||
|
||||
// set default values
|
||||
m_vFogColor(1,1,1);
|
||||
m_fDefMaxViewDist = m_fMaxViewDist = 1024;
|
||||
m_vDefFogColor = m_vFogColor;
|
||||
m_fDefFogNearDist = m_fFogNearDist=50;
|
||||
m_fDefFogFarDist = m_fFogFarDist = 1500;
|
||||
|
||||
//char buff[128];
|
||||
// GetCurrentDirectory(128, buff);
|
||||
|
||||
if(pDoc->load(Get3DEngine()->GetLevelFilePath(LEVEL_DATA_FILE)))
|
||||
{
|
||||
// load detail textures (mission shared data)
|
||||
LoadTerrainSurfacesFromXML(&pDoc);
|
||||
|
||||
// mission environment
|
||||
if (szMissionName && szMissionName[0])
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pMissionTagList;
|
||||
XDOM::IXMLDOMNodePtr pMissionTag;
|
||||
pMissionTagList = pDoc->getElementsByTagName("Missions");
|
||||
if (pMissionTagList)
|
||||
{
|
||||
pMissionTagList->reset();
|
||||
pMissionTag = pMissionTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pMissionList;
|
||||
pMissionList = pMissionTag->getElementsByTagName("Mission");
|
||||
if (pMissionList)
|
||||
{
|
||||
pMissionList->reset();
|
||||
XDOM::IXMLDOMNodePtr pMission;
|
||||
while (pMission = pMissionList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pName = pMission->getAttribute("Name");
|
||||
if (pName)
|
||||
{
|
||||
if (!stricmp(pName->getText(),szMissionName))
|
||||
{ // get mission XML file name and open mission file
|
||||
XDOM::IXMLDOMNodePtr pMissionFileName = pMission->getAttribute("File");
|
||||
if (pMissionFileName)
|
||||
{
|
||||
XDOM::IXMLDOMDocumentPtr pMissionDoc;
|
||||
pMissionDoc=GetSystem()->CreateXMLDocument();
|
||||
if (pMissionDoc->load(Get3DEngine()->GetLevelFilePath(pMissionFileName->getText())))
|
||||
{
|
||||
LoadMissionSettingsFromXML(pMissionDoc, bEditorMode, bUpdateLightingOnVegetations);
|
||||
|
||||
// load fog volumes (mission shared data)
|
||||
LoadFogVolumesFromXML(pMissionDoc);
|
||||
m_pTerrain->InitFogVolumes();
|
||||
|
||||
if(!bEditorMode)
|
||||
{
|
||||
if(!m_pObjManager->m_pCWaterVolumes)
|
||||
m_pObjManager->m_pCWaterVolumes = new CWaterVolumeManager( );
|
||||
m_pObjManager->m_pCWaterVolumes->LoadWaterVolumesFromXML(pMissionDoc);
|
||||
|
||||
m_pVisAreaManager->LoadVisAreaShapeFromXML(pMissionDoc);
|
||||
}
|
||||
|
||||
m_pVisAreaManager->LoadVisAreaBoxFromXML(pMissionDoc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Warning(0,0,"C3DEngine::LoadEnvironmentSettingsFromXML: Mission name is not defined");
|
||||
}
|
||||
}
|
||||
|
||||
char * C3DEngine::GetXMLAttribText(XDOM::IXMLDOMNode * pInputNode, const char * szLevel0,const char * szLevel1,const char * szLevel2,const char * szDefaultValue)
|
||||
{
|
||||
static char szResText[128];
|
||||
|
||||
strncpy(szResText,szDefaultValue,128);
|
||||
|
||||
XDOM::IXMLDOMNodeListPtr pObjectsTagList = pInputNode->getElementsByTagName(szLevel0);
|
||||
if (!pObjectsTagList)
|
||||
return szResText;
|
||||
|
||||
pObjectsTagList->reset();
|
||||
XDOM::IXMLDOMNodePtr pObjectsTag = pObjectsTagList->nextNode();
|
||||
|
||||
XDOM::IXMLDOMNodeListPtr pNodes = pObjectsTag->getElementsByTagName(szLevel1);
|
||||
if(pNodes)
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pNode;
|
||||
pNodes->reset();
|
||||
while(pNode = pNodes->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pAttr = pNode->getAttribute(szLevel2);
|
||||
if(pAttr)
|
||||
strncpy(szResText, pAttr->getText(), sizeof(szResText));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return szResText;
|
||||
}
|
||||
|
||||
void C3DEngine::LoadMissionSettingsFromXML(XDOM::IXMLDOMNode *pInputNode, bool bEditorMode, bool bUpdateLightingOnVegetations)
|
||||
{
|
||||
Vec3d vColor = StringToVector(GetXMLAttribText(pInputNode,"Environment","Fog","Color","255,255,255"));
|
||||
m_vDefFogColor[0] = m_vFogColor[0] = vColor[0]/255.f;
|
||||
m_vDefFogColor[1] = m_vFogColor[1] = vColor[1]/255.f;
|
||||
m_vDefFogColor[2] = m_vFogColor[2] = vColor[2]/255.f;
|
||||
GetRenderer()->SetClearColor(m_vFogColor);
|
||||
|
||||
// fog distance
|
||||
m_fDefFogNearDist = m_fFogNearDist= (float)atol(GetXMLAttribText(pInputNode,"Environment","Fog","Start","64"));
|
||||
m_fDefFogFarDist = m_fFogFarDist = (float)atol(GetXMLAttribText(pInputNode,"Environment","Fog","End","1500"));
|
||||
|
||||
// max view distance
|
||||
m_fDefMaxViewDist = m_fMaxViewDist = (float)atol(GetXMLAttribText(pInputNode,"Environment","Fog","ViewDistance","1024"));
|
||||
|
||||
// Shaders
|
||||
char szSkyBoxShaderName[128];
|
||||
strncpy(szSkyBoxShaderName, GetXMLAttribText(pInputNode, "Environment", "Shaders", "SkyBox", "InfRedGal"), sizeof(szSkyBoxShaderName));
|
||||
SAFE_RELEASE(m_pSHSky);
|
||||
m_pSHSky = szSkyBoxShaderName[0] ? GetRenderer()->EF_LoadShader(szSkyBoxShaderName, eSH_World) : NULL;
|
||||
|
||||
// set terrain water, sun road and bottom shaders
|
||||
char szTerrainWaterShaderName[256]="";
|
||||
strncpy(szTerrainWaterShaderName, GetXMLAttribText(pInputNode,"Environment","Shaders","Water", "terrainwater"), sizeof(szTerrainWaterShaderName));
|
||||
|
||||
m_pTerrainWaterShader = szTerrainWaterShaderName[0] ? GetRenderer()->EF_LoadShader(szTerrainWaterShaderName, eSH_World, EF_SYSTEM) : 0;
|
||||
|
||||
char szSunRoadShaderName[256]="";
|
||||
strncpy(szSunRoadShaderName, GetXMLAttribText(pInputNode,"Environment","Shaders","SunWaterRefl", "BumpSunGlow"), sizeof(szSunRoadShaderName));
|
||||
m_pSunRoadShader = szSunRoadShaderName[0] ? GetRenderer()->EF_LoadShader(szSunRoadShaderName, eSH_World, EF_SYSTEM) : 0;
|
||||
|
||||
// load water bottom texture
|
||||
char szWaterBottomTexName[256]="";
|
||||
strncpy(szWaterBottomTexName, GetXMLAttribText(pInputNode,"Environment","Ocean","BottomTexture", "terrain/water/oceanfloorcolor.bmp"),sizeof(szWaterBottomTexName));
|
||||
ITexPic * pPic = GetRenderer()->EF_LoadTexture(szWaterBottomTexName,FT_NOREMOVE,0,eTT_Base);
|
||||
m_nWaterBottomTexId = pPic->GetTextureID();
|
||||
|
||||
// load default zoom texture
|
||||
char szDefZoomTexName[256]="";
|
||||
strncpy(szDefZoomTexName, GetXMLAttribText(pInputNode, "Environment", "HeightMap", "DefaultZoomTexture", ""),sizeof(szDefZoomTexName));
|
||||
if(szDefZoomTexName[0])
|
||||
{
|
||||
pPic = GetRenderer()->EF_LoadTexture(szDefZoomTexName,FT_NOREMOVE,0,eTT_Base);
|
||||
m_pTerrain->m_nDefZoomTexId = pPic->GetTextureID();
|
||||
}
|
||||
else
|
||||
m_pTerrain->m_nDefZoomTexId = 0;
|
||||
|
||||
// Ocean
|
||||
m_pTerrain->m_fShoreSize = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","ShoreSize", "2.0"));
|
||||
m_fWaterTranspRatio = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","SurfaceTranspRatio", "1.0"));
|
||||
m_fWaterReflectRatio = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","SurfaceReflectRatio","1.0"));
|
||||
m_fWaterBumpAmountX = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","SurfaceBumpAmountX", "0.08"));
|
||||
m_fWaterBumpAmountY = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","SurfaceBumpAmountY", "0.12"));
|
||||
m_fWaterBorderTranspRatio = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","BorderTranspRatio", "0.5"));
|
||||
m_vUnderWaterFogColor = StringToVector(GetXMLAttribText(pInputNode,"Environment","Ocean","FogColor","51,90,102"))/255;
|
||||
m_fUnderWaterFogDistance = (float)atof(GetXMLAttribText(pInputNode,"Environment","Ocean","FogDistance", "8"));
|
||||
m_bOceanCaustics = atol(GetXMLAttribText(pInputNode,"Environment","Ocean","Caustics", "1"))==1;
|
||||
|
||||
m_fSkyBoxAngle = (float)atof(GetXMLAttribText(pInputNode,"Environment","EnvState","SkyBoxAngle","0.0"));
|
||||
m_fSunHeightScale = (float)atof(GetXMLAttribText(pInputNode,"Environment","EnvState","SunHeightScale","1.0"));
|
||||
m_fSkyBoxStretching = (float)atof(GetXMLAttribText(pInputNode,"Environment","EnvState","SkyBoxStretching","1.0"));
|
||||
|
||||
m_pTerrain->InitTerrainWater(bEditorMode, m_pTerrainWaterShader, m_nWaterBottomTexId, m_pSunRoadShader, m_fWaterTranspRatio, m_fWaterReflectRatio, m_fWaterBumpAmountX, m_fWaterBumpAmountY, m_fWaterBorderTranspRatio);
|
||||
|
||||
char szLensFlaresShaderName[128];
|
||||
strncpy(szLensFlaresShaderName, GetXMLAttribText(pInputNode,"Environment","Shaders","SunLensFlares","CryLight"), sizeof(szLensFlaresShaderName));
|
||||
if(szLensFlaresShaderName[0])
|
||||
m_pSHLensFlares = GetRenderer()->EF_LoadShader(szLensFlaresShaderName, eSH_World, EF_SYSTEM);
|
||||
else
|
||||
m_pSHLensFlares = NULL;
|
||||
|
||||
char szShoreShaderName[128];
|
||||
strncpy(szShoreShaderName, GetXMLAttribText(pInputNode,"Environment","Shaders","Shore", "terrainwaterbeach"), sizeof(szShoreShaderName));
|
||||
m_pTerrain->m_pSHShore = szShoreShaderName[0] ? GetRenderer()->EF_LoadShader(szShoreShaderName, eSH_World, EF_SYSTEM) : 0;
|
||||
|
||||
// State
|
||||
vColor = StringToVector(GetXMLAttribText(pInputNode,"Environment","EnvState","EnvColor","128,128,128"));
|
||||
m_vWorldColorConst = vColor/255.f;
|
||||
|
||||
// GetCVars()->e_rain_amount = strstr(GetXMLAttribText(pInputNode,"Environment","EnvState","Rain",""),"True")!=0;
|
||||
|
||||
// GetCVars()->e_bflyes = GetCVars()->e_bflyes && strstr(GetXMLAttribText(pInputNode,"Environment","EnvState","BFlyes",""),"True")!=0;
|
||||
|
||||
// set sun position
|
||||
m_vSunPosition = StringToVector(GetXMLAttribText(pInputNode,"Environment","Lighting","SunVector","0,5,-5"));
|
||||
m_vSunPosition *= -1.0f;
|
||||
m_vSunPosition.Normalize();
|
||||
|
||||
float x=m_vSunPosition.x;
|
||||
m_vSunPosition.x = m_vSunPosition.y;
|
||||
m_vSunPosition.y=x;
|
||||
|
||||
if(m_vSunPosition.x == 0 && m_vSunPosition.y == 0)
|
||||
m_vSunPosition = Vec3d(5,5,10000);
|
||||
else
|
||||
m_vSunPosition = GetNormalized(m_vSunPosition)*10000;
|
||||
|
||||
m_pObjManager->m_vOutdoorAmbientColor =
|
||||
StringToVector(GetXMLAttribText(pInputNode,"Environment","EnvState","OutdoorAmbientColor","64,64,64"))/255;
|
||||
|
||||
m_pObjManager->m_vSunColor =
|
||||
StringToVector(GetXMLAttribText(pInputNode,"Environment","EnvState","SunColor","128,128,128"))/255;
|
||||
|
||||
if(!GetISystem()->IsDedicated())
|
||||
m_pObjManager->UpdateCustomLighting( GetNormalized(GetSunPosition()) );
|
||||
|
||||
// get wind
|
||||
m_pObjManager->m_fWindForce = (float)atof(GetXMLAttribText(pInputNode,"Environment","EnvState","WindForce","0.15"));
|
||||
|
||||
// get terrain lods
|
||||
float fGeometryLodRatio = (float)atof(GetXMLAttribText(pInputNode,"Environment","HeightMap","GeometryLodRatio","1.0"));
|
||||
if(GetCVars()->e_cgf_load_lods == 0 && fGeometryLodRatio>1.f) // ised only for very high spec
|
||||
fGeometryLodRatio = 1.f+(fGeometryLodRatio-1.f)*0.5f;
|
||||
ICVar * pCVar = GetConsole()->GetCVar("e_terrain_lod_ratio");
|
||||
if(pCVar)
|
||||
pCVar->Set(fGeometryLodRatio);
|
||||
|
||||
m_pTerrain->m_fTextureLodRatio = (float)atof(GetXMLAttribText(pInputNode,"Environment","HeightMap","TextureLodRatio", "1.0"));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void C3DEngine::LoadParticleEffects( XmlNodeRef &levelDataRoot,bool bEditorMode )
|
||||
{
|
||||
if (!m_pPartManager)
|
||||
return;
|
||||
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_EXPLOSIONS );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_WATER );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_SMOKE );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_BLOOD );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_BULLET );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_MISC );
|
||||
m_pPartManager->LoadSharedParticleLibrary( EFFECTS_FOLDER,SHARED_PARTICLES_FIRE );
|
||||
|
||||
if (levelDataRoot)
|
||||
m_pPartManager->LoadParticlesLibs( EFFECTS_FOLDER,levelDataRoot );
|
||||
|
||||
CCryFile file;
|
||||
if (file.Open( GetLevelFilePath(PARTICLES_FILE),"rb" ))
|
||||
{
|
||||
m_pPartManager->LoadParticles( file );
|
||||
}
|
||||
}
|
||||
51
Cry3DEngine/Array2d.h
Normal file
51
Cry3DEngine/Array2d.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef _ARRAY2D_H_
|
||||
#define _ARRAY2D_H_
|
||||
|
||||
// Dynamic replacement for static 2d array
|
||||
template <class T> struct Array2d
|
||||
{
|
||||
Array2d()
|
||||
{
|
||||
m_nSize = 0;
|
||||
m_pData = 0;
|
||||
}
|
||||
|
||||
void GetMemoryUsage(ICrySizer*pSizer)
|
||||
{
|
||||
pSizer->AddObject (m_pData, m_nSize*m_nSize*sizeof(T));
|
||||
}
|
||||
|
||||
void Allocate(int nSize)
|
||||
{
|
||||
if(m_nSize == nSize)
|
||||
return;
|
||||
|
||||
delete m_pData;
|
||||
|
||||
m_nSize = nSize;
|
||||
m_pData = new T [nSize*nSize];
|
||||
memset(m_pData, 0, nSize*nSize*sizeof(T));
|
||||
}
|
||||
|
||||
~Array2d()
|
||||
{
|
||||
delete [] m_pData;
|
||||
}
|
||||
|
||||
T * m_pData;
|
||||
int m_nSize;
|
||||
|
||||
T * operator [] (const int & nPos) const
|
||||
{
|
||||
assert(nPos>=0 && nPos<m_nSize);
|
||||
return &m_pData[nPos*m_nSize];
|
||||
}
|
||||
|
||||
void operator = (const Array2d & other)
|
||||
{
|
||||
Allocate(other.m_nSize);
|
||||
memcpy(m_pData,other.m_pData,m_nSize*m_nSize*sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _ARRAY2D_H_
|
||||
42
Cry3DEngine/BaseObj.h
Normal file
42
Cry3DEngine/BaseObj.h
Normal file
@@ -0,0 +1,42 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: baseobj.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_)
|
||||
#define AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
class CBaseObj
|
||||
{
|
||||
public:
|
||||
CHUNK_HEADER m_ChunkHeader;
|
||||
bool m_bBinded;
|
||||
int m_nUsers;
|
||||
|
||||
CBaseObj()
|
||||
{
|
||||
memset(&m_ChunkHeader,0,sizeof(m_ChunkHeader));
|
||||
m_bBinded = false;
|
||||
m_nUsers = 0;
|
||||
}
|
||||
|
||||
virtual ~CBaseObj(){};
|
||||
virtual bool Load(CXFile *f, int pos) { return false; }
|
||||
virtual void Bind(CBaseObj **all_objects, int n_obj){}
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_BASEOBJ_H__2D817DB5_34FA_4C73_8588_867E88C9CFB3__INCLUDED_)
|
||||
889
Cry3DEngine/BasicArea.cpp
Normal file
889
Cry3DEngine/BasicArea.cpp
Normal file
@@ -0,0 +1,889 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjman.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: objects container, streaming, common part for indoor and outdoor sectors
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3DEngine.h"
|
||||
#include "meshidx.h"
|
||||
#include "watervolumes.h"
|
||||
#include "brush.h"
|
||||
#include "LMCompStructures.h"
|
||||
|
||||
void CBasicArea::SerializeArea(bool bSave)
|
||||
{
|
||||
char szFileName[256]="";
|
||||
sprintf(szFileName,"visarea_objects_%.1f_%.1f_%.1f_%.1f.cache", m_vBoxMin.x, m_vBoxMin.y, m_vBoxMax.x, m_vBoxMax.y);
|
||||
|
||||
FILE * f = GetPak()->FOpen(Get3DEngine()->GetFilePath(szFileName), bSave ? "wb" : "rb");
|
||||
if(!f)
|
||||
return;
|
||||
|
||||
if(bSave)
|
||||
{
|
||||
for(int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
EERType eType = m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetEntityRenderType();
|
||||
|
||||
if(eType == eERType_Brush || eType == eERType_Vegetation)
|
||||
{
|
||||
GetPak()->FWrite(&eType,sizeof(eType),1,f);
|
||||
|
||||
// if(m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetEntityRS())
|
||||
{
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(i)->m_pVisArea = 0;
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(i)->m_pSector = 0;
|
||||
}
|
||||
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(i)->Dephysicalize();
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(i)->Dematerialize();
|
||||
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(i)->Serialize(bSave,GetPak(),f);
|
||||
}
|
||||
}
|
||||
m_lstEntities[STATIC_ENTITIES].Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_lstEntities[STATIC_ENTITIES].Count()==0);
|
||||
m_lstEntities[STATIC_ENTITIES].Reset();
|
||||
|
||||
m_eSStatus = eSStatus_Ready;
|
||||
|
||||
while(1)
|
||||
{
|
||||
EERType eType = eERType_Unknown;
|
||||
if(GetPak()->FRead(&eType,sizeof(eType),1,f)!=1)
|
||||
break;
|
||||
|
||||
IEntityRender * pEntityRender = 0;
|
||||
if(eType == eERType_Brush)
|
||||
pEntityRender = new CBrush();
|
||||
else if(eType == eERType_Vegetation)
|
||||
pEntityRender = new CStatObjInst();
|
||||
|
||||
if(pEntityRender)
|
||||
{
|
||||
pEntityRender->Serialize(bSave,GetPak(),f);
|
||||
pEntityRender->GetEntityRS() = new IEntityRenderState;
|
||||
pEntityRender->Physicalize();
|
||||
Get3DEngine()->RegisterEntity(pEntityRender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetPak()->FClose(f);
|
||||
}
|
||||
|
||||
void CBasicArea::UnmakeAreaBrush()
|
||||
{
|
||||
for( int i=0; i<m_lstAreaBrush.Count(); i++ )
|
||||
FreeAreaBrush(m_lstAreaBrush[i]);
|
||||
|
||||
// mark all objects as unmerged
|
||||
if(m_lstAreaBrush.Count())
|
||||
for( int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES].GetAt(i);
|
||||
pEntityRender->m_dwRndFlags &= ~ERF_MERGED;
|
||||
assert(!(pEntityRender->m_dwRndFlags & ERF_MERGED));
|
||||
}
|
||||
|
||||
m_lstAreaBrush.Clear();
|
||||
}
|
||||
|
||||
void CBasicArea::DrawEntities( int nFogVolumeID, int nDLightMask,
|
||||
bool bLMapGeneration, const CCamera & EntViewCamera, Vec3d * pvAmbColor, Vec3d * pvDynAmbColor,
|
||||
VolumeInfo * pFogVolume, bool bNotAllInFrustum, float fSectorMinDist,
|
||||
CObjManager * pObjManager, bool bAllowBrushMerging, char*fake, uint nStatics)
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
if(!GetCVars()->e_objects)
|
||||
return;
|
||||
|
||||
if(GetCVars()->e_stream_areas && GetCVars()->e_stream_for_visuals && CStatObj::m_fStreamingTimePerFrame<CGF_STREAMING_MAX_TIME_PER_FRAME)
|
||||
{
|
||||
m_nLastUsedFrameId = GetFrameID();
|
||||
|
||||
if(m_eSStatus != eSStatus_Ready)
|
||||
{
|
||||
CStatObj::m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime();
|
||||
SerializeArea(false);
|
||||
CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime();
|
||||
}
|
||||
}
|
||||
|
||||
// apply zoom factor
|
||||
fSectorMinDist *= pObjManager->m_fZoomFactor;
|
||||
|
||||
// make lmask for vegetations
|
||||
int nDLightMaskNoSun = nDLightMask;
|
||||
list2<CDLight> * pSources = ((C3DEngine*)m_p3DEngine)->GetDynamicLightSources();
|
||||
for(int i=0; i<pSources->Count(); i++)
|
||||
{
|
||||
CDLight * pDynLight = pSources->Get(i);
|
||||
assert(pDynLight->m_Id == i || pDynLight->m_Id == -1);
|
||||
if(pDynLight->m_Flags & DLF_SUN)
|
||||
{
|
||||
nDLightMaskNoSun &= ~(1<<pDynLight->m_Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nStatics && m_StaticEntitiesSorted && GetCVars()->e_optimized_render_object &&
|
||||
!bLMapGeneration && pObjManager->m_fZoomFactor >= 0.99f)
|
||||
{ // render statics compiled
|
||||
const Vec3d vCamPos = EntViewCamera.GetPos();
|
||||
|
||||
const Plane PlaneR = *EntViewCamera.GetFrustumPlane(FR_PLANE_RIGHT);
|
||||
const Plane PlaneL = *EntViewCamera.GetFrustumPlane(FR_PLANE_LEFT);
|
||||
|
||||
static list2<IEntityRenderInfo*> TmpEntList; TmpEntList.Clear();
|
||||
list2<struct IEntityRender*> & SrcEntList = m_lstEntities[STATIC_ENTITIES];
|
||||
|
||||
if(GetCVars()->e_vegetation)
|
||||
{ // fill simple vegetations
|
||||
// FRAME_PROFILER( "*fill simple vegetations", GetSystem(), PROFILE_3DENGINE );
|
||||
for( int i=0; i<m_lstStatEntInfoVegetNoCastersNoVolFog.Count(); i++ )
|
||||
{
|
||||
IEntityRenderInfo & inf = m_lstStatEntInfoVegetNoCastersNoVolFog[i];
|
||||
|
||||
if(fSectorMinDist >= inf.m_fWSMaxViewDist)
|
||||
break;
|
||||
|
||||
// check max view distance sq
|
||||
const Vec3d vCamPos = EntViewCamera.GetPos();
|
||||
const float dx = vCamPos.x-inf.m_vWSCenter.x;
|
||||
const float dy = vCamPos.y-inf.m_vWSCenter.y;
|
||||
const float fEntDistanceSQ = (dx*dx+dy*dy); // must be 2d for sprites
|
||||
if(fEntDistanceSQ > inf.m_fWSMaxViewDistSQ)
|
||||
continue;
|
||||
|
||||
// early sphere test agains left and right camera planes
|
||||
if( bNotAllInFrustum &&
|
||||
PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius ||
|
||||
PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius )
|
||||
continue;
|
||||
|
||||
// get view distance
|
||||
inf.m_fEntDistance = cry_sqrtf(fEntDistanceSQ);
|
||||
assert(inf.m_fEntDistance>=0 && _finite(inf.m_fEntDistance));
|
||||
assert(inf.m_fEntDistance <= inf.m_fWSMaxViewDist);
|
||||
|
||||
TmpEntList.Add(&inf);
|
||||
}
|
||||
|
||||
// render simple vegetations
|
||||
// FRAME_PROFILER( "*render simple vegetations", GetSystem(), PROFILE_3DENGINE );
|
||||
for( int i=0; i<TmpEntList.Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = TmpEntList.GetAt(i)->m_pEntityRender;
|
||||
|
||||
if (i+1 < TmpEntList.Count())
|
||||
{ // prefech next element
|
||||
IEntityRender * pNext = TmpEntList.GetAt(i+1)->m_pEntityRender;
|
||||
cryPrefetchT0SSE(pNext);
|
||||
}
|
||||
|
||||
assert(fSectorMinDist < pEntityRender->m_fWSMaxViewDist);
|
||||
|
||||
pObjManager->RenderObjectVegetationNonCastersNoFogVolume( pEntityRender,
|
||||
nDLightMaskNoSun, EntViewCamera, bNotAllInFrustum,
|
||||
pEntityRender->m_fWSMaxViewDist, TmpEntList.GetAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
TmpEntList.Clear();
|
||||
|
||||
if(GetCVars()->e_vegetation || GetCVars()->e_brushes)
|
||||
{ // fill complex objects
|
||||
// FRAME_PROFILER( "*fill complex objects", GetSystem(), PROFILE_3DENGINE );
|
||||
for( int i=0; i<m_lstStatEntInfoOthers.Count(); i++ )
|
||||
{
|
||||
IEntityRenderInfo & inf = m_lstStatEntInfoOthers[i];
|
||||
|
||||
if(fSectorMinDist >= inf.m_fWSMaxViewDist)
|
||||
break;
|
||||
|
||||
// check max view distance sq
|
||||
const Vec3d vCamPos = EntViewCamera.GetPos();
|
||||
const float dx = vCamPos.x-inf.m_vWSCenter.x;
|
||||
const float dy = vCamPos.y-inf.m_vWSCenter.y;
|
||||
const float fEntDistanceSQ = (dx*dx+dy*dy); // must be 2d for sprites
|
||||
if(fEntDistanceSQ > inf.m_fWSMaxViewDistSQ)
|
||||
continue;
|
||||
|
||||
// early sphere test agains left and right camera planes
|
||||
if( bNotAllInFrustum &&
|
||||
PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius+TERRAIN_SECTORS_MAX_OVERLAPPING ||
|
||||
PlaneR.DistFromPlane(inf.m_vWSCenter) > inf.m_fWSRadius+TERRAIN_SECTORS_MAX_OVERLAPPING )
|
||||
continue;
|
||||
|
||||
// get view distance
|
||||
inf.m_fEntDistance = cry_sqrtf(fEntDistanceSQ);
|
||||
assert(inf.m_fEntDistance>=0 && _finite(inf.m_fEntDistance));
|
||||
assert(inf.m_fEntDistance <= inf.m_fWSMaxViewDist);
|
||||
|
||||
TmpEntList.Add(&inf);
|
||||
}
|
||||
|
||||
// render complex objects
|
||||
// FRAME_PROFILER( "*render complex objects", GetSystem(), PROFILE_3DENGINE );
|
||||
for( int i=0; i<TmpEntList.Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = TmpEntList.GetAt(i)->m_pEntityRender;
|
||||
|
||||
if (i+1 < TmpEntList.Count())
|
||||
{ // prefech next element
|
||||
IEntityRender * pNext = TmpEntList.GetAt(i+1)->m_pEntityRender;
|
||||
cryPrefetchT0SSE(pNext);
|
||||
}
|
||||
|
||||
assert(fSectorMinDist < pEntityRender->m_fWSMaxViewDist);
|
||||
|
||||
pObjManager->RenderObject( pEntityRender, nFogVolumeID,
|
||||
nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum,
|
||||
pEntityRender->m_fWSMaxViewDist, TmpEntList.GetAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nStatics && m_StaticEntitiesSorted && !bLMapGeneration)
|
||||
{
|
||||
|
||||
#ifdef VEGETATION_MEM_STATS
|
||||
static int64 t0=0,t1=0,t2=0;
|
||||
#endif // VEGETATION_MEM_STATS
|
||||
|
||||
list2<struct IEntityRender*> & EntList = m_lstEntities[STATIC_ENTITIES];
|
||||
for( int i=0; i<EntList.Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = EntList.GetAt(i);
|
||||
|
||||
if (i+1 < EntList.Count())
|
||||
{ // prefech next element
|
||||
IEntityRender * pNext = EntList.GetAt(i+1);
|
||||
cryPrefetchT0SSE(pNext);
|
||||
}
|
||||
|
||||
#ifdef VEGETATION_MEM_STATS
|
||||
if (i+1 < EntList.Count())
|
||||
{
|
||||
IEntityRender * pNext = EntList.GetAt(i+1);
|
||||
IEntityRender * pThis = EntList.GetAt(i);
|
||||
|
||||
if(pNext>pThis)
|
||||
{
|
||||
if(((int64)pNext-(int64)pThis)<=128)
|
||||
t0++;
|
||||
else
|
||||
t1++;
|
||||
}
|
||||
else
|
||||
t2++;
|
||||
}
|
||||
#endif // VEGETATION_MEM_STATS
|
||||
|
||||
if(fSectorMinDist > pEntityRender->m_fWSMaxViewDist)
|
||||
break;
|
||||
|
||||
pObjManager->RenderObject( pEntityRender, nFogVolumeID,
|
||||
nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum,
|
||||
pEntityRender->m_fWSMaxViewDist);
|
||||
}
|
||||
|
||||
#ifdef VEGETATION_MEM_STATS
|
||||
static int fr=0;
|
||||
if((GetFrameID()&63)==0 && fr!=GetFrameID())
|
||||
{
|
||||
fr=GetFrameID();
|
||||
if(t0+t1+t2)
|
||||
GetLog()->Log(
|
||||
"<128 = %.1f, >128 = %.1f, NEG = %.1f",
|
||||
0.1f*float((t0*1000/(t0+t1+t2))),
|
||||
0.1f*float((t1*1000/(t0+t1+t2))),
|
||||
0.1f*float((t2*1000/(t0+t1+t2))));
|
||||
}
|
||||
#endif // VEGETATION_MEM_STATS
|
||||
}
|
||||
else if(nStatics || GetCVars()->e_entities)
|
||||
{ // render dynamics or statics uncompiled
|
||||
assert(!m_StaticEntitiesSorted || !nStatics);
|
||||
list2<struct IEntityRender*> & EntList = m_lstEntities[nStatics];
|
||||
for( int i=0; i<EntList.Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = EntList.GetAt(i);
|
||||
pEntityRender->m_fWSMaxViewDist = pEntityRender->GetMaxViewDist();
|
||||
if(fSectorMinDist > pEntityRender->m_fWSMaxViewDist)
|
||||
continue;
|
||||
|
||||
pObjManager->RenderObject( pEntityRender, nFogVolumeID,
|
||||
nDLightMask, bLMapGeneration, EntViewCamera, pvAmbColor, pvDynAmbColor, pFogVolume, bNotAllInFrustum,
|
||||
pEntityRender->m_fWSMaxViewDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBasicArea::Unload(bool bUnloadOnlyVegetations, const Vec3d & vVegetPos)
|
||||
{
|
||||
if(bUnloadOnlyVegetations)
|
||||
{
|
||||
for(int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
EERType eType = m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetEntityRenderType();
|
||||
if(eType == eERType_Vegetation)
|
||||
{
|
||||
Vec3d vEntPos = m_lstEntities[STATIC_ENTITIES].GetAt(i)->GetPos();
|
||||
float fDist = (vVegetPos==Vec3d(0,0,0)) ? 0 : GetDist2D(vVegetPos.x,vVegetPos.y,vEntPos.x,vEntPos.y);
|
||||
if(fDist<0.01f)
|
||||
{
|
||||
int nCountBefore = m_lstEntities[STATIC_ENTITIES].Count();
|
||||
delete m_lstEntities[STATIC_ENTITIES].GetAt(i); // will also remove it from this list
|
||||
assert(m_lstEntities[STATIC_ENTITIES].Count() == (nCountBefore-1));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(m_lstEntities[STATIC_ENTITIES].Count())
|
||||
{
|
||||
EERType eType = m_lstEntities[STATIC_ENTITIES].GetAt(0)->GetEntityRenderType();
|
||||
assert(eType == eERType_Brush || eType == eERType_Vegetation);
|
||||
int nCountBefore = m_lstEntities[STATIC_ENTITIES].Count();
|
||||
|
||||
if(eType != eERType_Vegetation)
|
||||
Get3DEngine()->ReleaseObject(m_lstEntities[STATIC_ENTITIES].GetAt(0)->GetEntityStatObj(0));
|
||||
m_lstEntities[STATIC_ENTITIES].GetAt(0)->SetEntityStatObj(0,0);
|
||||
|
||||
IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES].GetAt(0); // will also remove it from this list
|
||||
delete pEntityRender; // will also remove it from this list
|
||||
|
||||
assert(m_lstEntities[STATIC_ENTITIES].Count() == (nCountBefore-1));
|
||||
}
|
||||
assert(m_lstEntities[STATIC_ENTITIES].Count()==0);
|
||||
m_eSStatus = eSStatus_Unloaded;
|
||||
}
|
||||
|
||||
UnmakeAreaBrush();
|
||||
}
|
||||
|
||||
bool CBasicArea::CheckUnload()
|
||||
{
|
||||
if(CStatObj::m_fStreamingTimePerFrame>=CGF_STREAMING_MAX_TIME_PER_FRAME)
|
||||
return (m_eSStatus == eSStatus_Ready);
|
||||
|
||||
CStatObj::m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime();
|
||||
|
||||
if(m_nLastUsedFrameId < GetFrameID() - 100)// && m_lstEntities[STATIC_ENTITIES].Count())
|
||||
{ // unload
|
||||
Unload();
|
||||
}
|
||||
|
||||
CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime();
|
||||
|
||||
return (m_eSStatus == eSStatus_Ready);
|
||||
}
|
||||
|
||||
void CBasicArea::CheckPhysicalized()
|
||||
{
|
||||
if(m_eSStatus != eSStatus_Ready)
|
||||
SerializeArea(false);
|
||||
|
||||
for(int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
m_lstEntities[STATIC_ENTITIES][i]->CheckPhysicalized();
|
||||
|
||||
m_nLastUsedFrameId = GetFrameID();
|
||||
}
|
||||
|
||||
void CBasicArea::PreloadResources(Vec3d vPrevPortalPos, float fPrevPortalDistance)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
int nFrameId = GetFrameID();
|
||||
for(int nStatic=0; nStatic<2; nStatic++)
|
||||
for( int i=0; i<m_lstEntities[nStatic].Count() && GetCurTimeSec()<(m_fPreloadStartTime+0.010f); i++ )
|
||||
{
|
||||
if((nFrameId%8) == (i%8))
|
||||
m_lstEntities[nStatic].GetAt(i)->PreloadInstanceResources(vPrevPortalPos, fPrevPortalDistance, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
void CBasicArea::UnregisterDynamicEntities()
|
||||
{
|
||||
while(m_lstEntities[DYNAMIC_ENTITIES].Count())
|
||||
{
|
||||
EERType eType = m_lstEntities[DYNAMIC_ENTITIES].GetAt(0)->GetEntityRenderType();
|
||||
assert(eType != eERType_Brush && eType != eERType_Vegetation);
|
||||
int nCountBefore = m_lstEntities[DYNAMIC_ENTITIES].Count();
|
||||
// delete m_lstEntities[DYNAMIC_ENTITIES].GetAt(0); // will also remove it from this list
|
||||
Get3DEngine()->UnRegisterEntity(m_lstEntities[DYNAMIC_ENTITIES].GetAt(0));
|
||||
assert(m_lstEntities[DYNAMIC_ENTITIES].Count() == (nCountBefore-1));
|
||||
}
|
||||
assert(m_lstEntities[DYNAMIC_ENTITIES].Count()==0);
|
||||
}
|
||||
|
||||
int __cdecl CObjManager__Cmp_EntTmpDistance(const void* v1, const void* v2);
|
||||
|
||||
void CBasicArea::SortStaticInstancesBySize(VolumeInfo * pFogVolume)
|
||||
{
|
||||
// sort lists instances in sector by size ( for rendering speed up )
|
||||
for( int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
m_lstEntities[STATIC_ENTITIES][i]->GetEntityRS()->fTmpDistance =
|
||||
-m_lstEntities[STATIC_ENTITIES][i]->GetMaxViewDist();
|
||||
|
||||
m_lstEntities[STATIC_ENTITIES][i]->m_fWSMaxViewDist = m_lstEntities[STATIC_ENTITIES][i]->GetMaxViewDist();
|
||||
}
|
||||
|
||||
// sort
|
||||
if(m_lstEntities[STATIC_ENTITIES].Count())
|
||||
qsort(m_lstEntities[STATIC_ENTITIES].GetElements(), m_lstEntities[STATIC_ENTITIES].Count(),
|
||||
sizeof(m_lstEntities[STATIC_ENTITIES][0]), CObjManager__Cmp_EntTmpDistance);
|
||||
|
||||
m_lstStaticShadowMapCasters.Clear();
|
||||
for( int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES][i];
|
||||
if(pEntityRender->GetRndFlags()&ERF_CASTSHADOWMAPS)
|
||||
m_lstStaticShadowMapCasters.Add(pEntityRender);
|
||||
}
|
||||
|
||||
m_lstStatEntInfoVegetNoCastersNoVolFog.Clear();
|
||||
m_lstStatEntInfoOthers.Clear();
|
||||
for( int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES][i];
|
||||
IEntityRenderInfo inf(pEntityRender);
|
||||
|
||||
bool bInFogVolume = false;
|
||||
if(pFogVolume)
|
||||
{ // fog is set only for outdoors
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
assert(pEntityRender->m_pSector);
|
||||
pEntityRender->GetBBox(vBoxMin,vBoxMax);
|
||||
if(pFogVolume->IntersectBBox(vBoxMin,vBoxMax))
|
||||
bInFogVolume = true;
|
||||
}
|
||||
|
||||
if( !(pEntityRender->GetRndFlags() & (ERF_CASTSHADOWMAPS|ERF_CASTSHADOWVOLUME|ERF_RECVSHADOWMAPS|ERF_SELFSHADOW)) &&
|
||||
pEntityRender->GetEntityRenderType() == eERType_Vegetation &&
|
||||
!bInFogVolume)
|
||||
m_lstStatEntInfoVegetNoCastersNoVolFog.Add(inf);
|
||||
else
|
||||
m_lstStatEntInfoOthers.Add(inf);
|
||||
}
|
||||
|
||||
m_StaticEntitiesSorted = true;
|
||||
|
||||
// swap to disk
|
||||
if(GetCVars()->e_stream_areas)
|
||||
SerializeArea(true);
|
||||
}
|
||||
|
||||
int __cdecl CBasicArea__Cmp_MatChunks(const void* v1, const void* v2)
|
||||
{
|
||||
CMatInfo * pMat1 = (CMatInfo*)v1;
|
||||
CMatInfo * pMat2 = (CMatInfo*)v2;
|
||||
|
||||
// shader
|
||||
if(pMat1->shaderItem.m_pShader->GetTemplate(-1) > pMat2->shaderItem.m_pShader->GetTemplate(-1))
|
||||
return 1;
|
||||
else if(pMat1->shaderItem.m_pShader->GetTemplate(-1) < pMat2->shaderItem.m_pShader->GetTemplate(-1))
|
||||
return -1;
|
||||
|
||||
// shader resources
|
||||
if(pMat1->shaderItem.m_pShaderResources > pMat2->shaderItem.m_pShaderResources)
|
||||
return 1;
|
||||
else if(pMat1->shaderItem.m_pShaderResources < pMat2->shaderItem.m_pShaderResources)
|
||||
return -1;
|
||||
|
||||
// lm tex id
|
||||
if(pMat1->m_Id > pMat2->m_Id)
|
||||
return 1;
|
||||
else if(pMat1->m_Id < pMat2->m_Id)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
const char * pName1 = ((*(((*(pMat1)).shaderItem).m_pShaderResources)).m_Textures)[0] ? (*(((*(((*(pMat1)).shaderItem).m_pShaderResources)).m_Textures)[0])).m_Name.c_str() : "";
|
||||
const char * pName2 = ((*(((*(pMat2)).shaderItem).m_pShaderResources)).m_Textures)[0] ? (*(((*(((*(pMat2)).shaderItem).m_pShaderResources)).m_Textures)[0])).m_Name.c_str() : "";
|
||||
|
||||
return strcmp(pName1,pName2);*/
|
||||
}
|
||||
|
||||
struct LMTexCoord
|
||||
{
|
||||
float s,t;
|
||||
};
|
||||
|
||||
void CBasicArea::MakeAreaBrush()
|
||||
{
|
||||
const Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
int nEntityId=0;
|
||||
int nNextStartId=-1;
|
||||
while(nEntityId<m_lstEntities[STATIC_ENTITIES].Count() || nNextStartId>=0)
|
||||
{
|
||||
static list2<struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F> lstVerts;lstVerts.Clear();
|
||||
static list2<LMTexCoord> lstLMTexCoords; lstLMTexCoords.Clear();
|
||||
static list2<ushort> lstIndices; lstIndices.Clear();
|
||||
static list2<ushort> lstIndicesSorted; lstIndicesSorted.Clear();
|
||||
static list2<CMatInfo> lstChunks; lstChunks.Clear();
|
||||
static list2<CMatInfo> lstChunksMerged; lstChunksMerged.Clear();
|
||||
static list2<SPipTangents> lstTangBasises; lstTangBasises.Clear();
|
||||
|
||||
Vec3d vBoxMax(-10000,-10000,-10000);
|
||||
Vec3d vBoxMin( 10000, 10000, 10000);
|
||||
|
||||
int nLMTexId=-1;
|
||||
int nHDRLMTexId=-1;
|
||||
int nLMDirTexId=-1;
|
||||
int nCurVertsNum=0;
|
||||
|
||||
if(nNextStartId>=0)
|
||||
nEntityId = nNextStartId;
|
||||
nNextStartId=-1;
|
||||
|
||||
for( ; nEntityId<m_lstEntities[STATIC_ENTITIES].Count(); nEntityId++)
|
||||
{
|
||||
IEntityRender * pEntityRender = m_lstEntities[STATIC_ENTITIES][nEntityId];
|
||||
|
||||
if( pEntityRender->m_dwRndFlags & ERF_MERGED ||
|
||||
pEntityRender->m_dwRndFlags & ERF_CASTSHADOWVOLUME ||
|
||||
pEntityRender->m_dwRndFlags & ERF_CASTSHADOWMAPS)
|
||||
continue;
|
||||
|
||||
// Vec3d vCenter = (pEntityRender->m_vWSBoxMin+pEntityRender->m_vWSBoxMax)*0.5f;
|
||||
// float fEntDistance = GetDist2D( vCamPos.x, vCamPos.y, vCenter.x, vCenter.y );
|
||||
// if(fEntDistance > pEntityRender->GetMaxViewDist())
|
||||
// continue;
|
||||
|
||||
// if(fEntDistance > GetCVars()->e_area_merging_distance)
|
||||
// continue;
|
||||
|
||||
if(nLMTexId<0)
|
||||
{
|
||||
nLMTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0;
|
||||
nHDRLMTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetHDRColorLerpTex() : 0;
|
||||
nLMDirTexId = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetDomDirectionTex() : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(nLMTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0) ||
|
||||
nLMDirTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetDomDirectionTex() : 0) ||
|
||||
nHDRLMTexId != (pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetHDRColorLerpTex() : 0))
|
||||
{
|
||||
if(nNextStartId<0)
|
||||
nNextStartId = nEntityId;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Matrix44 mat;
|
||||
mat.SetIdentity();
|
||||
mat*=0;
|
||||
IStatObj * pStatObj = pEntityRender->GetEntityStatObj(0,&mat);
|
||||
if(!pStatObj)
|
||||
continue;
|
||||
|
||||
EERType eType = pEntityRender->GetEntityRenderType();
|
||||
if(eType == eERType_Vegetation)
|
||||
{
|
||||
Matrix33diag diag = Vec3(pEntityRender->GetScale(),pEntityRender->GetScale(),pEntityRender->GetScale()); //use diag-matrix for scaling
|
||||
mathCalcMatrix(mat, pEntityRender->GetPos(), Vec3d(0,0,0),
|
||||
Vec3d(pEntityRender->GetScale(),pEntityRender->GetScale(),pEntityRender->GetScale()),
|
||||
Cry3DEngineBase::m_CpuFlags);
|
||||
}
|
||||
|
||||
if(!CBrush::IsMatrixValid(mat))
|
||||
continue;
|
||||
|
||||
CLeafBuffer * pLMLB = pEntityRender->GetLightmapTexCoord(0);
|
||||
|
||||
CLeafBuffer * pLB = pStatObj->GetLeafBuffer();
|
||||
if(!pLB->m_SecVertCount)
|
||||
continue;
|
||||
|
||||
if(nCurVertsNum + pLB->m_SecVertCount>65000)
|
||||
break;
|
||||
|
||||
int nIndCount=0;
|
||||
pLB->GetIndices(&nIndCount);
|
||||
if(nIndCount > GetCVars()->e_area_merging_max_tris_in_input_brush*3)
|
||||
continue;
|
||||
|
||||
int nInitVertCout = lstVerts.Count();
|
||||
for(int m=0; m<pLB->m_pMats->Count(); m++)
|
||||
{
|
||||
CMatInfo newMatInfo = *pLB->m_pMats->Get(m);
|
||||
|
||||
if(GetCVars()->e_materials)
|
||||
{ // Override default material
|
||||
CMatInfo * pCustMat = (CMatInfo *)pEntityRender->GetMaterial();
|
||||
if (pCustMat)
|
||||
{
|
||||
int nMatId = newMatInfo.m_nCGFMaterialID;
|
||||
if(nMatId<0)
|
||||
continue;
|
||||
|
||||
if (nMatId == 0)
|
||||
pCustMat = (CMatInfo*)pCustMat;
|
||||
else if (nMatId-1 < pCustMat->GetSubMtlCount())
|
||||
pCustMat = (CMatInfo*)pCustMat->GetSubMtl(nMatId-1);
|
||||
|
||||
newMatInfo.shaderItem = pCustMat->shaderItem;
|
||||
}
|
||||
}
|
||||
|
||||
// copy indices
|
||||
for(int i=newMatInfo.nFirstIndexId; i<newMatInfo.nFirstIndexId+newMatInfo.nNumIndices; i++)
|
||||
lstIndices.Add(pLB->GetIndices(0)[i]+nInitVertCout);
|
||||
newMatInfo.nFirstIndexId = lstIndices.Count() - newMatInfo.nNumIndices;
|
||||
|
||||
// copy verts
|
||||
int nPosStride=0;
|
||||
const byte * pPos = pLB->GetPosPtr(nPosStride,0,true);
|
||||
int nTexStride=0;
|
||||
const byte * pTex = pLB->GetUVPtr(nTexStride,0,true);
|
||||
|
||||
// get tengent basis
|
||||
int nTangStride=0;
|
||||
const byte * pTang = pLB->GetTangentPtr(nTangStride,0,true);
|
||||
int nTnormStride=0;
|
||||
const byte * pTNorm = pLB->GetTNormalPtr(nTnormStride,0,true);
|
||||
int nBNormStride=0;
|
||||
const byte * pBNorm = pLB->GetBinormalPtr(nBNormStride,0,true);
|
||||
int nColorStride=0;
|
||||
const byte * pColor = pLB->GetColorPtr(nColorStride,0,true);
|
||||
|
||||
// get LM TexCoords
|
||||
int nLMStride=0;
|
||||
const byte * pLMTexCoords = pLMLB ? pLMLB->GetPosPtr(nLMStride,0,true) : 0;
|
||||
|
||||
for(int v=newMatInfo.nFirstVertId; v<newMatInfo.nFirstVertId+newMatInfo.nNumVerts; v++)
|
||||
{
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F vert;
|
||||
|
||||
// set pos
|
||||
Vec3d vPos = *(Vec3d*)&pPos[nPosStride*v];
|
||||
vPos = mat.TransformPointOLD(vPos);
|
||||
vert.xyz = vPos;
|
||||
|
||||
// set uv
|
||||
float * pUV = (float*)&pTex[nTexStride*v];
|
||||
vert.st[0] = pUV[0];
|
||||
vert.st[1] = pUV[1];
|
||||
|
||||
vert.color.dcolor = *(DWORD*)&pColor[nColorStride*v+0];
|
||||
|
||||
// calc bbox
|
||||
vBoxMin.CheckMin(vPos);
|
||||
vBoxMax.CheckMax(vPos);
|
||||
|
||||
lstVerts.Add(vert);
|
||||
|
||||
// add tbasis
|
||||
SPipTangents basis;
|
||||
basis.m_Tangent = mat.TransformVectorOLD(*(Vec3d*)&pTang[nTangStride*v]);
|
||||
basis.m_TNormal = mat.TransformVectorOLD(*(Vec3d*)&pTNorm[nTnormStride*v]);
|
||||
basis.m_Binormal= mat.TransformVectorOLD(*(Vec3d*)&pBNorm[nBNormStride*v]);
|
||||
lstTangBasises.Add(basis);
|
||||
|
||||
// add LM texcoords
|
||||
LMTexCoord vLMTC;
|
||||
if(pLMTexCoords)
|
||||
vLMTC = *(LMTexCoord*)&pLMTexCoords[nLMStride*v];
|
||||
else
|
||||
vLMTC.s = vLMTC.t = 0;
|
||||
|
||||
lstLMTexCoords.Add(vLMTC);
|
||||
}
|
||||
|
||||
// set vert range
|
||||
newMatInfo.nFirstVertId = lstVerts.Count() - newMatInfo.nNumVerts;
|
||||
|
||||
newMatInfo.pRE = 0;
|
||||
newMatInfo.m_Id = pEntityRender->GetLightmap(0) ? pEntityRender->GetLightmap(0)->GetColorLerpTex() : 0;
|
||||
|
||||
if(newMatInfo.nNumIndices)
|
||||
{
|
||||
lstChunks.Add(newMatInfo);
|
||||
}
|
||||
else
|
||||
assert(!newMatInfo.nNumVerts);
|
||||
}
|
||||
nCurVertsNum += pLB->m_SecVertCount;
|
||||
|
||||
pEntityRender->m_dwRndFlags |= ERF_MERGED;
|
||||
}
|
||||
|
||||
CBrush * pAreaBrush = 0;
|
||||
if(!lstVerts.Count())
|
||||
{ // make empty brush - no geometry in sector
|
||||
pAreaBrush = new CBrush;
|
||||
m_lstAreaBrush.Add(pAreaBrush);
|
||||
return;
|
||||
}
|
||||
|
||||
// sort
|
||||
if(lstChunks.Count())
|
||||
qsort(lstChunks.GetElements(), lstChunks.Count(),
|
||||
sizeof(lstChunks[0]), CBasicArea__Cmp_MatChunks);
|
||||
|
||||
// merge chunks
|
||||
for(int nChunk=0; nChunk<lstChunks.Count(); nChunk++)
|
||||
{
|
||||
if(!nChunk || CBasicArea__Cmp_MatChunks(&lstChunks[nChunk], &lstChunks[nChunk-1]))
|
||||
{ // not equal materials - add new chunk
|
||||
lstChunksMerged.Add(lstChunks[nChunk]);
|
||||
lstChunksMerged.Last().nFirstIndexId = lstIndicesSorted.Count();
|
||||
lstChunksMerged.Last().nNumIndices = 0;
|
||||
|
||||
lstChunksMerged.Last().nFirstVertId = 0;
|
||||
lstChunksMerged.Last().nNumVerts = lstVerts.Count();
|
||||
}
|
||||
|
||||
// add indices
|
||||
for(int nId=lstChunks[nChunk].nFirstIndexId; nId<lstChunks[nChunk].nFirstIndexId+lstChunks[nChunk].nNumIndices; nId++)
|
||||
lstIndicesSorted.Add(lstIndices[nId]);
|
||||
|
||||
// update start/stop pos
|
||||
lstChunksMerged.Last().nNumIndices += lstChunks[nChunk].nNumIndices;
|
||||
}
|
||||
|
||||
lstChunks = lstChunksMerged;
|
||||
lstIndices = lstIndicesSorted;
|
||||
|
||||
// make leaf buffer
|
||||
CLeafBuffer * pAreaLB = GetRenderer()->CreateLeafBufferInitialized(
|
||||
lstVerts.GetElements(), lstVerts.Count(), VERTEX_FORMAT_P3F_COL4UB_TEX2F,
|
||||
lstIndices.GetElements(), lstIndices.Count(), R_PRIMV_TRIANGLES,
|
||||
"AreaLB", eBT_Static, lstChunks.Count());
|
||||
|
||||
pAreaLB->UpdateTangBuffer(lstTangBasises.GetElements());
|
||||
|
||||
for(int i=0; i<lstChunks.Count(); i++)
|
||||
{
|
||||
pAreaLB->SetChunk(lstChunks[i].GetShaderItem().m_pShader,
|
||||
lstChunks[i].nFirstVertId, lstChunks[i].nNumVerts,
|
||||
lstChunks[i].nFirstIndexId, lstChunks[i].nNumIndices, i, true);
|
||||
|
||||
assert(lstChunks[i].GetShaderItem().m_pShaderResources);
|
||||
assert(lstChunks[i].GetShaderItem().m_pShader);
|
||||
pAreaLB->m_pMats->Get(i)->shaderItem = lstChunks[i].GetShaderItem();
|
||||
|
||||
pAreaLB->m_pMats->Get(i)->shaderItem.m_pShader->AddRef();
|
||||
pAreaLB->m_pMats->Get(i)->shaderItem.m_pShaderResources->AddRef();
|
||||
}
|
||||
|
||||
// make statobj
|
||||
CStatObj * pAreaStatObj = new CStatObj();
|
||||
pAreaStatObj->m_nLoadedTrisCount = lstIndices.Count()/3;
|
||||
pAreaStatObj->SetLeafBuffer(pAreaLB);
|
||||
pAreaStatObj->SetBBoxMin(vBoxMin);
|
||||
pAreaStatObj->SetBBoxMax(vBoxMax);
|
||||
pAreaStatObj->RegisterUser();
|
||||
|
||||
// make brush
|
||||
pAreaBrush = new CBrush();
|
||||
|
||||
// if(m_pAreaBrush == (CBrush*)0x0e968358)
|
||||
// int b=0;
|
||||
|
||||
Matrix44 mat;
|
||||
mat.SetIdentity();
|
||||
pAreaBrush->SetEntityStatObj(0,pAreaStatObj,&mat);
|
||||
pAreaBrush->m_vWSBoxMin = vBoxMin;
|
||||
pAreaBrush->m_vWSBoxMax = vBoxMax;
|
||||
pAreaBrush->m_fWSRadius = vBoxMin.GetDistance(vBoxMax)*0.5f;
|
||||
|
||||
// Make leafbuffer and fill it with texture coordinates
|
||||
if(nLMTexId && (nLMDirTexId || (GetCVars()->e_light_maps_quality==0)))
|
||||
{
|
||||
RenderLMData * pLMData = new RenderLMData(GetRenderer(), nLMTexId, nHDRLMTexId, nLMDirTexId);
|
||||
pAreaBrush->SetLightmap(pLMData, (float*)lstLMTexCoords.GetElements(), lstLMTexCoords.Count(), 0);
|
||||
pLMData->AddRef();
|
||||
pAreaBrush->SetRndFlags(ERF_USELIGHTMAPS,true);
|
||||
}
|
||||
|
||||
Get3DEngine()->UnRegisterEntity(pAreaBrush);
|
||||
Get3DEngine()->RegisterEntity(pAreaBrush);
|
||||
|
||||
// find distance to the camera
|
||||
const Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
Vec3d vCenter = (pAreaBrush->m_vWSBoxMin+pAreaBrush->m_vWSBoxMax)*0.5f;
|
||||
float fEntDistance = GetDist2D( vCamPos.x, vCamPos.y, vCenter.x, vCenter.y );
|
||||
|
||||
assert(fEntDistance>=0);
|
||||
assert(_finite(fEntDistance));
|
||||
|
||||
m_lstAreaBrush.Add(pAreaBrush);
|
||||
}
|
||||
}
|
||||
|
||||
void CBasicArea::FreeAreaBrush(CBrush * pAreaBrush)
|
||||
{
|
||||
if(!pAreaBrush)
|
||||
return;
|
||||
|
||||
Get3DEngine()->UnRegisterEntity(pAreaBrush);
|
||||
|
||||
// if(m_pAreaBrush == (CBrush*)0x0e968358)
|
||||
// int b=0;
|
||||
|
||||
CStatObj * pAreaStatObj = (CStatObj *)pAreaBrush->GetEntityStatObj(0);
|
||||
if(pAreaStatObj)
|
||||
{
|
||||
pAreaBrush->SetEntityStatObj(0,0);
|
||||
pAreaStatObj->UnregisterUser();
|
||||
CLeafBuffer * pAreaLB = pAreaStatObj->GetLeafBuffer();
|
||||
pAreaStatObj->SetLeafBuffer(0);
|
||||
|
||||
GetRenderer()->DeleteLeafBuffer(pAreaLB);
|
||||
delete pAreaStatObj;
|
||||
}
|
||||
delete pAreaBrush;
|
||||
pAreaBrush=0;
|
||||
}
|
||||
|
||||
CBasicArea::~CBasicArea()
|
||||
{
|
||||
for( int i=0; i<m_lstAreaBrush.Count(); i++ )
|
||||
FreeAreaBrush(m_lstAreaBrush[i]);
|
||||
m_lstAreaBrush.Clear();
|
||||
}
|
||||
|
||||
|
||||
int CBasicArea::GetLastStaticElementIdWithInMaxViewDist(float fMaxViewDist)
|
||||
{ // use binary search to find range of elements visible on fMaxViewDist
|
||||
int nCount = m_lstEntities[STATIC_ENTITIES].Count();
|
||||
int nCurrId = m_lstEntities[STATIC_ENTITIES].Count()/2;
|
||||
for(int nJump=2; (nCount>>nJump); nJump++)
|
||||
{
|
||||
IEntityRender * pCaster = m_lstEntities[STATIC_ENTITIES][nCurrId];
|
||||
if(pCaster->m_fWSMaxViewDist<fMaxViewDist)
|
||||
nCurrId -= nCount>>nJump;
|
||||
else
|
||||
nCurrId += nCount>>nJump;
|
||||
}
|
||||
|
||||
return min(nCurrId+2,m_lstEntities[STATIC_ENTITIES].Count());
|
||||
}
|
||||
66
Cry3DEngine/BasicArea.h
Normal file
66
Cry3DEngine/BasicArea.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef _BASICAREA_H_
|
||||
#define _BASICAREA_H_
|
||||
|
||||
#define DYNAMIC_ENTITIES 0
|
||||
#define STATIC_ENTITIES 1
|
||||
|
||||
enum ESStatus
|
||||
{
|
||||
eSStatus_Unloaded,
|
||||
eSStatus_Ready
|
||||
};
|
||||
|
||||
struct IEntityRenderInfo
|
||||
{
|
||||
IEntityRenderInfo(IEntityRender*pEntityRender)
|
||||
{
|
||||
m_fWSMaxViewDist = pEntityRender->m_fWSMaxViewDist;
|
||||
m_fWSMaxViewDistSQ = pEntityRender->m_fWSMaxViewDist*pEntityRender->m_fWSMaxViewDist;
|
||||
m_vWSCenter =(pEntityRender->m_vWSBoxMin+pEntityRender->m_vWSBoxMax)*0.5f;
|
||||
m_fWSRadius = pEntityRender->m_fWSRadius;
|
||||
m_pEntityRender = pEntityRender;
|
||||
m_fEntDistance = 0;
|
||||
}
|
||||
|
||||
float m_fWSMaxViewDistSQ;
|
||||
float m_fWSMaxViewDist;
|
||||
Vec3 m_vWSCenter;
|
||||
float m_fEntDistance;
|
||||
float m_fWSRadius;
|
||||
struct IEntityRender*m_pEntityRender;
|
||||
};
|
||||
|
||||
struct CBasicArea : public Cry3DEngineBase
|
||||
{
|
||||
CBasicArea() { m_nLastUsedFrameId=0; m_eSStatus=eSStatus_Unloaded; m_vBoxMin=m_vBoxMax=m_vAreaBrushFocusPos=Vec3d(0,0,0); m_StaticEntitiesSorted=false; }
|
||||
~CBasicArea();
|
||||
|
||||
list2<struct IEntityRender*> m_lstEntities[2];
|
||||
list2<IEntityRenderInfo> m_lstStatEntInfoVegetNoCastersNoVolFog, m_lstStatEntInfoOthers;
|
||||
list2<struct IEntityRender*> m_lstStaticShadowMapCasters;
|
||||
Vec3d m_vBoxMin, m_vBoxMax;
|
||||
int m_nLastUsedFrameId;
|
||||
ESStatus m_eSStatus;
|
||||
bool m_StaticEntitiesSorted;
|
||||
|
||||
void SerializeArea(bool bSave);
|
||||
void DrawEntities(int nFogVolumeID, int nDLightMask,
|
||||
bool bLMapGeneration, const CCamera & EntViewCamera, Vec3d * pvAmbColor, Vec3d * pvDynAmbColor,
|
||||
VolumeInfo * pFogVolume, bool bNotAllInFrustum, float fSectorMinDist,
|
||||
CObjManager * pObjManager, bool bAllowBrushMerging, char*fake, uint nStatics);
|
||||
bool CheckUnload();
|
||||
void CheckPhysicalized();
|
||||
void Unload(bool bUnloadOnlyVegetations = false, const Vec3d & vPos = Vec3d(0,0,0));
|
||||
void PreloadResources(Vec3d vPrevPortalPos, float fPrevPortalDistance);
|
||||
void UnregisterDynamicEntities();
|
||||
void SortStaticInstancesBySize(VolumeInfo * pFogVolume = NULL);
|
||||
void MakeAreaBrush();
|
||||
void UnmakeAreaBrush();
|
||||
void FreeAreaBrush(class CBrush * pAreaBrush);
|
||||
int GetLastStaticElementIdWithInMaxViewDist(float fMaxViewDist);
|
||||
|
||||
list2<class CBrush *> m_lstAreaBrush;
|
||||
Vec3d m_vAreaBrushFocusPos;
|
||||
};
|
||||
|
||||
#endif // _BASICAREA_H_
|
||||
1519
Cry3DEngine/Brush.cpp
Normal file
1519
Cry3DEngine/Brush.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
Cry3DEngine/Brush.h
Normal file
120
Cry3DEngine/Brush.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef _3DENGINE_BRUSH_H_
|
||||
#define _3DENGINE_BRUSH_H_
|
||||
|
||||
#include "ObjMan.H"
|
||||
|
||||
#if defined(LINUX)
|
||||
#include "LMCompStructures.h"
|
||||
#include "platform.h"
|
||||
#else
|
||||
struct RenderLMData;
|
||||
#endif
|
||||
TYPEDEF_AUTOPTR(RenderLMData);
|
||||
|
||||
struct SLMData
|
||||
{
|
||||
SLMData() { m_pLMTCBuffer=0; }
|
||||
RenderLMData_AutoPtr m_pLMData;
|
||||
struct CLeafBuffer * m_pLMTCBuffer;
|
||||
};
|
||||
|
||||
class CBrush : public IEntityRender, public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CBrush();
|
||||
virtual ~CBrush();
|
||||
virtual const char * GetEntityClassName() const;
|
||||
virtual const Vec3d & GetPos(bool bWorldOnly = true) const;
|
||||
virtual const Vec3d & GetAngles(int realA=0) const;
|
||||
virtual float GetScale() const;
|
||||
virtual const char *GetName() const;
|
||||
virtual void GetRenderBBox( Vec3d &mins,Vec3d &maxs );
|
||||
virtual float GetRenderRadius() const;
|
||||
virtual bool HasChanged();
|
||||
virtual bool DrawEntity(const struct SRendParams & EntDrawParams);
|
||||
virtual bool IsStatic() const;
|
||||
virtual struct IStatObj * GetEntityStatObj( unsigned int nSlot, Matrix44 * pMatrix = NULL, bool bReturnOnlyVisible = false);
|
||||
virtual struct ICryCharInstance* GetEntityCharacter( unsigned int nSlot, Matrix44 * pMatrix = NULL );
|
||||
|
||||
virtual void SetEntityStatObj( unsigned int nSlot, IStatObj * pStatObj, Matrix44 * pMatrix = NULL );
|
||||
|
||||
virtual void SetLightmap(RenderLMData *pLMData, float *pTexCoords, UINT iNumTexCoords, int nLod);
|
||||
//special call from lightmap serializer/compiler to set occlusion map values
|
||||
virtual void SetLightmap(RenderLMData *pLMData, float *pTexCoords, UINT iNumTexCoords, const unsigned char cucOcclIDCount, const std::vector<std::pair<EntityId, EntityId> >& aIDs);
|
||||
|
||||
virtual bool HasLightmap(int nLod)
|
||||
{
|
||||
// only 2 conditions are valid
|
||||
//assert((m_pLMData != NULL && m_pLMTCBuffer != NULL) || (m_pLMData == NULL && m_pLMTCBuffer == NULL));
|
||||
#if !defined(LINUX64)
|
||||
if (m_arrLMData[nLod].m_pLMData == NULL || m_arrLMData[nLod].m_pLMTCBuffer == NULL)
|
||||
#else
|
||||
if (m_arrLMData[nLod].m_pLMData == 0 || m_arrLMData[nLod].m_pLMTCBuffer == 0)
|
||||
#endif
|
||||
return false; // return to avoid crash somewhere if in release mode
|
||||
return true;
|
||||
};
|
||||
virtual RenderLMData * GetLightmap(int nLod) { return m_arrLMData[nLod].m_pLMData; };
|
||||
virtual struct CLeafBuffer * GetLightmapTexCoord(int nLod) { return m_arrLMData[nLod].m_pLMTCBuffer; };
|
||||
|
||||
virtual bool IsEntityHasSomethingToRender();
|
||||
virtual bool IsEntityAreasVisible();
|
||||
virtual IPhysicalEntity* GetPhysics() const ;
|
||||
virtual void SetPhysics( IPhysicalEntity* pPhys );
|
||||
static bool IsMatrixValid(const Matrix44 & mat);
|
||||
void DeleteLMTC();
|
||||
void Dephysicalize( );
|
||||
virtual void Physicalize(bool bInstant=false);
|
||||
|
||||
//! Assign override material to this entity.
|
||||
virtual void SetMaterial( IMatInfo *pMatInfo );
|
||||
virtual void SetMaterialId( int nId ) { m_nMaterialId = nId; }
|
||||
virtual IMatInfo* GetMaterial() const;
|
||||
int GetEditorObjectId() { return m_nEditorObjectId; }
|
||||
void SetEditorObjectId(int nEditorObjectId) { m_nEditorObjectId = nEditorObjectId; }
|
||||
virtual void CheckPhysicalized();
|
||||
int DestroyPhysicalEntityCallback(IPhysicalEntity *pent);
|
||||
// int GetPhysGeomId(int nSlotId) { return m_arrPhysGeomId[nSlotId]; }
|
||||
|
||||
virtual float GetMaxViewDist();
|
||||
virtual void Serialize(bool bSave, ICryPak * pPak, FILE * f);
|
||||
virtual EERType GetEntityRenderType() { return eERType_Brush; }
|
||||
|
||||
void SetStatObjGroupId(int nStatObjInstanceGroupId) { m_nObjectTypeID = nStatObjInstanceGroupId; }
|
||||
void SetMergeId(int nId) { m_nMergeID = nId; }
|
||||
int GetMergeId() { return m_nMergeID; }
|
||||
|
||||
static list2<IStatObj*> m_lstBrushTypes;
|
||||
|
||||
void SetMatrix( Matrix44* pMatrix );
|
||||
void Dematerialize( );
|
||||
virtual int GetMemoryUsage();
|
||||
static list2<SExportedBrushMaterial> m_lstSExportedBrushMaterials;
|
||||
virtual void PreloadInstanceResources(Vec3d vPrevPortalPos, float fPrevPortalDistance, float fTime);
|
||||
|
||||
protected:
|
||||
void CalcWholeBBox();
|
||||
|
||||
Vec3d m_vPos, m_vAngles;
|
||||
float m_fScale;
|
||||
// struct IStatObj * m_pStatObj;
|
||||
Matrix44 m_Matrix;
|
||||
IPhysicalEntity * m_pPhysEnt;
|
||||
|
||||
//! Override material.
|
||||
_smart_ptr<IMatInfo> m_pMaterial;
|
||||
int m_nMaterialId;
|
||||
|
||||
#define MAX_BRUSH_LODS_NUM 3
|
||||
SLMData m_arrLMData[MAX_BRUSH_LODS_NUM];
|
||||
|
||||
int m_nEditorObjectId;
|
||||
int m_nObjectTypeID;
|
||||
int m_nMergeID;
|
||||
|
||||
//needed for occlusion maps
|
||||
// std::vector<std::pair<EntityId, EntityId> > m_vnOcclIndices;//first one is real EntityID, second one is (entity)light index in StatLights.dat
|
||||
IEntityRender * m_arrOcclusionLightOwners[4];
|
||||
};
|
||||
|
||||
#endif // _3DENGINE_BRUSH_H_
|
||||
135
Cry3DEngine/BrushLM.cpp
Normal file
135
Cry3DEngine/BrushLM.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: brushlm.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3DEngine.h"
|
||||
#include "meshidx.h"
|
||||
#include "watervolumes.h"
|
||||
#include "LMCompStructures.h"
|
||||
#include "brush.h"
|
||||
#include "IEntitySystem.h"
|
||||
|
||||
void CBrush::SetLightmap(RenderLMData *pLMData, float *pTexCoords, UINT iNumTexCoords, const unsigned char cucOcclIDCount, const std::vector<std::pair<EntityId, EntityId> >& aIDs)
|
||||
{
|
||||
assert(cucOcclIDCount <= 4);
|
||||
|
||||
memset(m_arrOcclusionLightOwners,0,sizeof(m_arrOcclusionLightOwners));
|
||||
|
||||
if(GetCVars()->e_light_maps_occlusion)
|
||||
{
|
||||
if(m_bEditorMode)
|
||||
{
|
||||
for(int i=0; i<4 && i<cucOcclIDCount; ++i)
|
||||
{
|
||||
EntityId nEntId = aIDs[i].first;
|
||||
IEntityRender * pEnt;
|
||||
if(nEntId == (EntityId)-1)
|
||||
pEnt = (IEntityRender*)-1; // sun
|
||||
else
|
||||
pEnt = GetSystem()->GetIEntitySystem()->GetEntity(nEntId);
|
||||
// assert(pEnt);
|
||||
m_arrOcclusionLightOwners[i] = pEnt;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const list2<CDLight*> * pStaticLights = Get3DEngine()->GetStaticLightSources();
|
||||
for(int i=0; (i<4) && (i<cucOcclIDCount) && (pStaticLights->Count()); ++i)
|
||||
{
|
||||
EntityId nEntId = aIDs[i].second;
|
||||
IEntityRender * pEnt;
|
||||
if(nEntId == (EntityId)-1)
|
||||
pEnt = (IEntityRender*)-1; // sun
|
||||
else
|
||||
pEnt = pStaticLights->GetAt(nEntId)->m_pOwner;
|
||||
assert(pEnt);
|
||||
m_arrOcclusionLightOwners[i] = pEnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetLightmap(pLMData, pTexCoords, iNumTexCoords, 0);
|
||||
}
|
||||
|
||||
void CBrush::SetLightmap(RenderLMData *pLMData, float *pTexCoords, UINT iNumTexCoords, int nLod)
|
||||
{
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Set a referenece of a DOT3 Lightmap object for this GLM
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
IRenderer *pIRenderer = GetRenderer();
|
||||
|
||||
assert(iNumTexCoords);
|
||||
assert(!IsBadReadPtr(pTexCoords, sizeof(float) * 2 * iNumTexCoords));
|
||||
|
||||
m_arrLMData[nLod].m_pLMData = pLMData;
|
||||
|
||||
if (m_arrLMData[nLod].m_pLMTCBuffer)
|
||||
{
|
||||
pIRenderer->DeleteLeafBuffer(m_arrLMData[nLod].m_pLMTCBuffer);
|
||||
m_arrLMData[nLod].m_pLMTCBuffer = NULL;
|
||||
}
|
||||
|
||||
IStatObj *pIStatObj = GetEntityStatObj(0, NULL);
|
||||
|
||||
if (pIStatObj == NULL)
|
||||
return;
|
||||
|
||||
if(!pIStatObj->EnableLightamapSupport())
|
||||
return;
|
||||
|
||||
CLeafBuffer *pLeafBuffer = pIStatObj->GetLeafBuffer();
|
||||
|
||||
if (pLeafBuffer == NULL)
|
||||
return;
|
||||
|
||||
// Renderer expect 2 floats
|
||||
std::vector<float> vTexCoord2;
|
||||
vTexCoord2.reserve(iNumTexCoords * 2);
|
||||
UINT i;
|
||||
for (i=0; i<iNumTexCoords; i++)
|
||||
{
|
||||
vTexCoord2.push_back(pTexCoords[i * 2 + 0]); // S
|
||||
vTexCoord2.push_back(pTexCoords[i * 2 + 1]); // T
|
||||
}
|
||||
|
||||
if (pLeafBuffer->m_SecVertCount != iNumTexCoords)
|
||||
{
|
||||
char szBuffer[1024];
|
||||
sprintf(szBuffer, "Error: CBrush::SetLightmap: Object at position (%f, %f, %f) has" \
|
||||
" texture mismatch (%i coordinates supplied, %i required)\r\n",
|
||||
GetPos().x, GetPos().y, GetPos().z,
|
||||
iNumTexCoords, pLeafBuffer->m_SecVertCount);
|
||||
Warning(0,pIStatObj->GetFileName(),szBuffer);
|
||||
// assert(pLeafBuffer->m_SecVertCount == iNumTexCoords);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make leafbuffer and fill it with texture coordinates
|
||||
m_arrLMData[nLod].m_pLMTCBuffer = GetRenderer()->CreateLeafBufferInitialized(
|
||||
&vTexCoord2[0], pLeafBuffer->m_SecVertCount, VERTEX_FORMAT_TEX2F,
|
||||
0/*pLeafBuffer->GetIndices(0)*/, 0/*pLeafBuffer->m_Indices.m_nItems*/,
|
||||
R_PRIMV_TRIANGLES, "LMapTexCoords", eBT_Static, 1, 0, NULL, NULL, false, false);
|
||||
|
||||
C3DEngine *pEng = (C3DEngine *)Get3DEngine();
|
||||
m_arrLMData[nLod].m_pLMTCBuffer->SetChunk(pEng->m_pSHDefault,
|
||||
0,pLeafBuffer->m_SecVertCount, 0,pLeafBuffer->m_Indices.m_nItems);
|
||||
}
|
||||
164
Cry3DEngine/Cry3DEngine.cpp
Normal file
164
Cry3DEngine/Cry3DEngine.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cry3dengine.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Defines the DLL entry point, implements access to other modules
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// init memory pool usage
|
||||
#ifndef GAMECUBE
|
||||
#ifndef _XBOX
|
||||
//#if !defined(LINUX)
|
||||
_ACCESS_POOL;
|
||||
//#endif//LINUX
|
||||
#endif //_XBOX
|
||||
#endif
|
||||
|
||||
|
||||
#include "3dengine.h"
|
||||
|
||||
#define MAX_ERROR_STRING 4096
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StencilShadowConnectivity.h"
|
||||
#include "StencilShadowConnectivityBuilder.h" // CStencilShadowConnectivityBuilder
|
||||
#include "StencilShadowEdgeDetector.h" // CStencilShadowEdgeDetector
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Pointer to Global ISystem.
|
||||
ISystem* GetISystem()
|
||||
{
|
||||
return Cry3DEngineBase::m_pSys;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(GAMECUBE) && !defined(PS2) && !defined(_XBOX) && !defined(LINUX)
|
||||
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
//#include <time.h>
|
||||
|
||||
I3DEngine * CreateCry3DEngine(ISystem * pSystem, const char * szInterfaceVersion)
|
||||
{/*
|
||||
__time64_t ltime1, ltime2;
|
||||
_time64( <ime1 );
|
||||
|
||||
int nElemNum = 100000*64/sizeof(float);
|
||||
unsigned short * pShorts = new unsigned short[nElemNum];
|
||||
float * pFloats = new float[nElemNum];
|
||||
|
||||
for(int t=0; t<1000; t++)
|
||||
{
|
||||
for(int i=0; i<nElemNum; i++)
|
||||
{
|
||||
pFloats[i] = 0.01f*pShorts[i];
|
||||
}
|
||||
}
|
||||
|
||||
_time64( <ime2 );
|
||||
float fTimeDif = float(ltime2 - ltime1);
|
||||
|
||||
delete [] pShorts;
|
||||
delete [] pFloats;
|
||||
|
||||
char buff[32];
|
||||
snprintf(buff,"%.2f",fTimeDif/1000);
|
||||
MessageBox(0, buff, "aa", MB_OK);
|
||||
|
||||
return 0;
|
||||
*/
|
||||
#if !defined(LINUX)
|
||||
if(strcmp(szInterfaceVersion,g3deInterfaceVersion))
|
||||
pSystem->GetIConsole()->Exit("Error: CreateCry3DEngine(): 3dengine interface version error");
|
||||
#endif
|
||||
C3DEngine * p3DEngine = new C3DEngine(pSystem);
|
||||
return p3DEngine;
|
||||
}
|
||||
|
||||
void Cry3DEngineBase::UpdateLoadingScreen(const char *command,...)
|
||||
{
|
||||
if(command)
|
||||
{
|
||||
va_list arglist;
|
||||
char buf[512];
|
||||
va_start(arglist, command);
|
||||
vsnprintf(buf, sizeof(buf), command, arglist);
|
||||
va_end(arglist);
|
||||
GetLog()->UpdateLoadingScreen(buf);
|
||||
}
|
||||
else
|
||||
GetLog()->UpdateLoadingScreen(0);
|
||||
}
|
||||
|
||||
void Cry3DEngineBase::UpdateLoadingScreenPlus(const char *command,...)
|
||||
{
|
||||
va_list arglist;
|
||||
char buf[512];
|
||||
va_start(arglist, command);
|
||||
vsnprintf(buf, sizeof(buf), command, arglist);
|
||||
va_end(arglist);
|
||||
GetLog()->UpdateLoadingScreenPlus(buf);
|
||||
}
|
||||
|
||||
//IRenderer *Cry3DEngineBase::GetRenderer()
|
||||
//{ return GetSystem()->GetIRenderer(); }
|
||||
|
||||
//ITimer *Cry3DEngineBase::GetTimer()
|
||||
//{ return GetSystem()->GetITimer(); }
|
||||
|
||||
//ILog *Cry3DEngineBase::GetLog()
|
||||
//{ return GetSystem()->GetILog(); }
|
||||
|
||||
//IPhysicalWorld *Cry3DEngineBase::GetPhysicalWorld()
|
||||
//{ return GetSystem()->GetIPhysicalWorld(); }
|
||||
|
||||
CCamera & Cry3DEngineBase::GetViewCamera()
|
||||
{ return m_pSys->GetViewCamera(); }
|
||||
|
||||
float Cry3DEngineBase::GetCurTimeSec()
|
||||
{ return (m_pSys->GetITimer()->GetCurrTime()); }
|
||||
|
||||
float Cry3DEngineBase::GetCurAsyncTimeSec()
|
||||
{ return (m_pSys->GetITimer()->GetAsyncCurTime()); }
|
||||
|
||||
//IConsole * Cry3DEngineBase::GetConsole()
|
||||
//{ return GetSystem()->GetIConsole(); }
|
||||
|
||||
//I3DEngine * Cry3DEngineBase::Get3DEngine()
|
||||
//{ return GetSystem()->GetI3DEngine(); }
|
||||
|
||||
//CVars * Cry3DEngineBase::GetCVars()
|
||||
//{ return ((C3DEngine*)GetSystem()->GetI3DEngine())->GetCVars(); }
|
||||
|
||||
CVisAreaManager * Cry3DEngineBase::GetVisAreaManager()
|
||||
{ return ((C3DEngine*)m_pSys->GetI3DEngine())->GetVisAreaManager(); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void Cry3DEngineBase::Warning( int flags,const char *file,const char *format,... )
|
||||
{
|
||||
va_list ArgList;
|
||||
char szBuffer[MAX_ERROR_STRING];
|
||||
va_start(ArgList, format);
|
||||
vsprintf(szBuffer, format, ArgList);
|
||||
va_end(ArgList);
|
||||
|
||||
// Call to validating warning of system.
|
||||
m_pSys->Warning( VALIDATOR_MODULE_3DENGINE,VALIDATOR_WARNING,flags,file,"%s",szBuffer );
|
||||
}
|
||||
|
||||
#include <CrtDebugStats.h>
|
||||
|
||||
749
Cry3DEngine/Cry3DEngine.vcproj
Normal file
749
Cry3DEngine/Cry3DEngine.vcproj
Normal file
@@ -0,0 +1,749 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="Cry3DEngine"
|
||||
ProjectGUID="{7D1FD0B0-A81D-4A7D-B399-37F8B9107D3F}"
|
||||
SccProjectName="Perforce Project"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Perforce SCM"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
OptimizeForProcessor="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CRY3DENGINE_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="0"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CRY3DENGINE_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/Cry3DEngine.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
BaseAddress="0x20000000"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CRY3DENGINE_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
BaseAddress="0x30000000"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/fp:fast
|
||||
"
|
||||
Optimization="2"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CRY3DENGINE_EXPORTS;WIN64;_AMD64_"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/xxLTCG:PGI /xxxPGD:C:\MasterCD\Bin64\Cry3DEngine.pgd"
|
||||
AdditionalDependencies="../CryCommon/fSinCos64.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="0"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
BaseAddress="0x20000000"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
OptimizeForProcessor="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CRY3DENGINE_EXPORTS;WIN64;_AMD64_"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:AMD64"
|
||||
AdditionalDependencies="../CryCommon/fSinCos64.lib"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="0"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Ini Files"
|
||||
Filter="">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="CFGLoader"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="BaseObj.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CryStaticModel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CryStaticModel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="File.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="File.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Geom.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Geom.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Helper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Helper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Light.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Light.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Meshidx.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Node.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Node.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="StatObj"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="StatObj.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjCompiler.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjConstr.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjFar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjLoad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjPhys.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjRend.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjSerialize.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjShadow.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjShadowVolumes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjStream.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Effects"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Decals"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Decal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="DecalManager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="DecalManager.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Particles"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="particle.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ParticleEffect.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ParticleEffect.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ParticleEmitter.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ParticleEmitter.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="partman.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="partman.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="partpolygon.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SpriteManager.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Rain"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="rain.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="rain.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Detail Objects"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="detail_grass.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="detail_grass.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Terrain"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="terrain.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_damage.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_det_tex.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_hmap.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_init.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_light.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_load.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_render.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_tex_pool.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terran_edit.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Sector"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="terrain_sector.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_sector.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_sector_beach.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_sector_render.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_sector_tex.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Water"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="terrain_water.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_water_quad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="WaterVolumes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="WaterVolumes.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Vegetation"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Vegetation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Vegetation.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Brush"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Brush.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Brush.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="BrushLM.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="LightMaps"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="dds.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LMSerializationManager2.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LMSerializationManager2.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ObjManager"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="ObjMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjMan.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManDraw.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManDrawEntity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManFar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManShadows.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManStreaming.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="StencilShadows"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="IndoorShadowVolumes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="IndoorVolumes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ShadowVolumeEdge.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivityBuilder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivityBuilder.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowEdgeDetector.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowEdgeDetector.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="3DEngine"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="3dEngine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineLight.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineLoad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineRender.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineScreenEffects.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MatMan.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="VisAreas"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="BasicArea.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="BasicArea.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreaMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreas.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreas.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="CVars"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="cvars.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cvars.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="CBuffer"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="cbuffer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cbuffer.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Containers"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Array2d.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Interfaces"
|
||||
Filter="">
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="Cry3DEngine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Cry3DEngineBase.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LightMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StdAfx.h">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
Cry3DEngine/Cry3DEngine.vcproj.vspscc
Normal file
10
Cry3DEngine/Cry3DEngine.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\Cry3DEngine\\Cry3DEngine.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||
}
|
||||
85
Cry3DEngine/Cry3DEngineBase.h
Normal file
85
Cry3DEngine/Cry3DEngineBase.h
Normal file
@@ -0,0 +1,85 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cry3denginebase.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Access to external stuff used by 3d engine. Most 3d engine classes
|
||||
// are derived from this base class to access other interfaces
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _Cry3DEngineBase_h_
|
||||
#define _Cry3DEngineBase_h_
|
||||
|
||||
struct ISystem;
|
||||
struct IRenderer;
|
||||
struct ILog;
|
||||
class IPhysicalWorld;
|
||||
struct ITimer;
|
||||
struct IConsole;
|
||||
struct I3DEngine;
|
||||
struct CVars;
|
||||
struct CVisAreaManager;
|
||||
|
||||
struct Cry3DEngineBase
|
||||
{
|
||||
static ISystem * m_pSys;
|
||||
static IRenderer * m_pRenderer;
|
||||
static ITimer * m_pTimer;
|
||||
static ILog * m_pLog;
|
||||
static IPhysicalWorld * m_pPhysicalWorld;
|
||||
static IConsole * m_pConsole;
|
||||
static I3DEngine * m_p3DEngine;
|
||||
static CVars * m_pCVars;
|
||||
static ICryPak * m_pCryPak;
|
||||
static int m_nRenderStackLevel;
|
||||
static int m_dwRecursionDrawFlags[2];
|
||||
static int m_nRenderFrameID;
|
||||
static bool m_bProfilerEnabled;
|
||||
static float m_fPreloadStartTime;
|
||||
|
||||
static int m_CpuFlags;
|
||||
static double m_SecondsPerCycle;
|
||||
static ESystemConfigSpec m_configSpec;
|
||||
static ESystemConfigSpec m_LightConfigSpec;
|
||||
|
||||
static bool m_bIgnoreFakeMaterialsInCGF;
|
||||
static bool m_bEditorMode;
|
||||
|
||||
static ISystem * GetSystem() { return m_pSys; }
|
||||
static IRenderer * GetRenderer() { return m_pRenderer; }
|
||||
static ITimer * GetTimer() { return m_pTimer; }
|
||||
static ILog * GetLog() { return m_pLog; }
|
||||
static IPhysicalWorld * GetPhysicalWorld() { return m_pPhysicalWorld;}
|
||||
static IConsole * GetConsole() { return m_pConsole; }
|
||||
static I3DEngine * Get3DEngine() { return m_p3DEngine; }
|
||||
static CVars * GetCVars() { return m_pCVars; }
|
||||
static CVisAreaManager* GetVisAreaManager();
|
||||
static ICryPak * GetPak() { return m_pCryPak; }
|
||||
|
||||
static int GetFrameID() { return m_nRenderFrameID; };
|
||||
|
||||
CCamera & GetViewCamera() ;
|
||||
float GetCurTimeSec();
|
||||
float GetCurAsyncTimeSec();
|
||||
void UpdateLoadingScreen(const char *command,...);
|
||||
void UpdateLoadingScreenPlus(const char *command,...);
|
||||
|
||||
// Validator warning.
|
||||
static void Warning( int flags,const char *file,const char *format,... );
|
||||
|
||||
CCObject * GetIdentityCCObject()
|
||||
{
|
||||
CCObject * pCCObject = GetRenderer()->EF_GetObject(true);
|
||||
pCCObject->m_Matrix.SetIdentity();
|
||||
return pCCObject;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _Cry3DEngineBase_h_
|
||||
605
Cry3DEngine/Cry3DEngine_XBox.vcproj
Normal file
605
Cry3DEngine/Cry3DEngine_XBox.vcproj
Normal file
@@ -0,0 +1,605 @@
|
||||
<?xml version="1.0" encoding = "windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="Cry3DEngine_XBox"
|
||||
SccProjectName=""$/Game01/Cry3DEngine", HXRAAAAA"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Microsoft Visual SourceSafe">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Xbox"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Xbox"
|
||||
OutputDirectory="Release_XBox"
|
||||
IntermediateDirectory="Release_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
ImproveFloatingPointConsistency="FALSE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="_XBOX;_LIB"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile="$(IntDir)/Cry3DEngine.pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="2"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/$Cry3DEngine.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Xbox"
|
||||
OutputDirectory="Profile"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="_XBOX;_LIB"
|
||||
StringPooling="TRUE"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Profile/Cry3DEngine.pch"
|
||||
AssemblerListingLocation=".\Profile/"
|
||||
ObjectFile=".\Profile/"
|
||||
ProgramDataBaseFileName=".\Profile/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/$Cry3DEngine.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Xbox"
|
||||
OutputDirectory="Debug_XBox"
|
||||
IntermediateDirectory="Debug_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="_DEBUG;_XBOX;_LIB"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Debug_XBox/Cry3DEngine.pch"
|
||||
AssemblerListingLocation=".\Debug_XBox/"
|
||||
ObjectFile=".\Debug_XBox/"
|
||||
ProgramDataBaseFileName=".\Debug_XBox/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/$Cry3DEngine.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="CGF Loader"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\CryStaticModel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\File.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Meshidx.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Loader_h"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\CryStaticModel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\File.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Chunks"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\Geom.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Helper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Light.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Node.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Chunks_h"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\BaseObj.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Geom.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Helper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Light.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Node.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="StatObj"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\StatObj.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StatObjConstr.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StatObjFar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StatObjPhys.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StatObjRend.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjSerialize.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StatObjShadow.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StatObjShadowVolumes.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Terrain"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\terrain.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_damage.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_det_tex.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_hmap.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_init.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_light.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_load.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_render.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_tex_pool.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terran_edit.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Sector"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\terrain_sector.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_sector.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_sector_beach.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_sector_render.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_sector_tex.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Objects Manager"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="LMSerializationManager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjMan.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManDraw.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManDrawEntity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManFar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManPhys.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManShadows.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ObjManStreaming.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="3DEngine"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\3dEngine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\3dEngine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineLight.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\3dEngineLoad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\3dEngineRender.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="3dEngineScreenEffects.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cbuffer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="cbuffer.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Effects"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\bflyes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\bugs.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\detail_grass.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rain.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Effects_h"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\bflyes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\bugs.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\detail_grass.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\rain.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Particles"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\particle.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\partman.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\partman.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="partpolygon.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="partspray.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Decals"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Decal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="DecalManager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="DecalManager.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Ini Files"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="C:\MasterCD\gamecfg.lua">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="C:\MasterCD\log.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="C:\MasterCD\playercfg.lua">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="C:\MasterCD\systemcfg.lua">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="C:\MasterCD\systemcfgoverride.lua">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="CVars"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\cvars.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cvars.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Stencil Shadows"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivityBuilder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowConnectivityBuilder.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowEdgeDetector.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StencilShadowEdgeDetector.h">
|
||||
</File>
|
||||
<Filter
|
||||
Name="other"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="IndoorShadowVolumes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="IndoorVolumes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ShadowVolumeEdge.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Interfaces"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\CryCommon\I3DEngine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\crycommon\IEntityRenderState.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\crycommon\IStatObj.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Water"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="WaterVolumes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="WaterVolumes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain_water.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="terrain_water_quad.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="VisAreas"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="BasicArea.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="BasicArea.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreaMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreas.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VisAreas.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Brush"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Brush.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Brush.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="BrushLM.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LMSerializationManager.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="LightMan"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="LightLoad.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LightMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="LightMan.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Containers"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Array2d.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\CryCommon\list2.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Vegetation"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="Vegetation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Vegetation.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Cry3DEngine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Cry3DEngineBase.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="MatMan.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\todo.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
Cry3DEngine/Cry3DEngine_XBox.vcproj.vspscc
Normal file
10
Cry3DEngine/Cry3DEngine_XBox.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\Cry3DEngine\\Cry3DEngine_XBox.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
||||
498
Cry3DEngine/CryStaticModel.cpp
Normal file
498
Cry3DEngine/CryStaticModel.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: crystaticmodel.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: load cgf file
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "CryStaticModel.h"
|
||||
|
||||
#include "baseobj.h"
|
||||
#include "node.h"
|
||||
#include "geom.h"
|
||||
#include "helper.h"
|
||||
#include "light.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
CryStaticModel::CryStaticModel()
|
||||
{
|
||||
memset( this,0,sizeof(*this) );
|
||||
}
|
||||
|
||||
CryStaticModel::~CryStaticModel()
|
||||
{
|
||||
for( int i=0; i<m_nNewObjs; i++)
|
||||
{
|
||||
CNodeCGF * pNode = (CNodeCGF*)m_ppNewObjs[i];
|
||||
delete pNode;
|
||||
}
|
||||
|
||||
if(m_ppNewObjs)
|
||||
free(m_ppNewObjs);
|
||||
m_ppNewObjs=0;
|
||||
}
|
||||
|
||||
void CryStaticModel::LoadMaterials(CXFile*f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET))
|
||||
return;
|
||||
|
||||
CHUNK_HEADER ch;
|
||||
int res = f->FRead(&ch,1,sizeof(ch));
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0746::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0746 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
me.m_New = 2;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
|
||||
me.specLevel = chunk.specLevel;
|
||||
me.specShininess = chunk.specShininess*100;
|
||||
me.opacity = chunk.opacity;
|
||||
me.selfIllum = chunk.selfIllum;
|
||||
me.flags = chunk.flags;
|
||||
if (me.flags & MTLFLAG_CRYSHADER)
|
||||
me.alpharef = chunk.alphaTest;
|
||||
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
/* //Timur[10/24/2001]
|
||||
strcpy(me.map_a, chunk.tex_a.name);
|
||||
strcpy(me.map_d, chunk.tex_d.name);
|
||||
strcpy(me.map_o, chunk.tex_o.name);
|
||||
strcpy(me.map_b, chunk.tex_b.name);
|
||||
strcpy(me.map_s, chunk.tex_s.name);
|
||||
strcpy(me.map_g, chunk.tex_g.name);
|
||||
strcpy(me.map_c, chunk.tex_c.name);
|
||||
strcpy(me.map_e, chunk.tex_rl.name);
|
||||
strcpy(me.map_rr, chunk.tex_rr.name);
|
||||
strcpy(me.map_det, chunk.tex_det.name);
|
||||
*/
|
||||
me.map_a = chunk.tex_a;
|
||||
me.map_d = chunk.tex_d;
|
||||
me.map_o = chunk.tex_o;
|
||||
me.map_b = chunk.tex_b;
|
||||
me.map_s = chunk.tex_s;
|
||||
me.map_g = chunk.tex_g;
|
||||
me.map_detail = chunk.tex_fl;
|
||||
me.map_e = chunk.tex_rl;
|
||||
me.map_subsurf = chunk.tex_subsurf;
|
||||
me.map_displ = chunk.tex_det;
|
||||
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
/* case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.children = new int [chunk.nChildren];
|
||||
int res=f->FRead(me.children,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0745::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0745 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
me.m_New = 1;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
|
||||
me.specLevel = chunk.specLevel;
|
||||
me.specShininess = chunk.specShininess*100;
|
||||
me.opacity = chunk.opacity;
|
||||
me.selfIllum = chunk.selfIllum;
|
||||
me.flags = chunk.flags;
|
||||
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
/* //Timur[10/24/2001]
|
||||
strcpy(me.map_a, chunk.tex_a.name);
|
||||
strcpy(me.map_d, chunk.tex_d.name);
|
||||
strcpy(me.map_o, chunk.tex_o.name);
|
||||
strcpy(me.map_b, chunk.tex_b.name);
|
||||
strcpy(me.map_s, chunk.tex_s.name);
|
||||
strcpy(me.map_g, chunk.tex_g.name);
|
||||
strcpy(me.map_c, chunk.tex_c.name);
|
||||
strcpy(me.map_e, chunk.tex_rl.name);
|
||||
strcpy(me.map_rr, chunk.tex_rr.name);
|
||||
strcpy(me.map_det, chunk.tex_det.name);
|
||||
*/
|
||||
me.map_a = chunk.tex_a;
|
||||
me.map_d = chunk.tex_d;
|
||||
me.map_o = chunk.tex_o;
|
||||
me.map_b = chunk.tex_b;
|
||||
me.map_s = chunk.tex_s;
|
||||
me.map_g = chunk.tex_g;
|
||||
me.map_detail = chunk.tex_c;
|
||||
me.map_e = chunk.tex_rl;
|
||||
me.map_subsurf = chunk.tex_subsurf;
|
||||
me.map_displ = chunk.tex_det;
|
||||
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
/* case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.children = new int [chunk.nChildren];
|
||||
int res=f->FRead(me.children,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ch.ChunkVersion == MTL_CHUNK_DESC_0744::VERSION)
|
||||
{
|
||||
f->FSeek(pos,SEEK_SET);
|
||||
MTL_CHUNK_DESC_0744 chunk;
|
||||
int res=f->FRead(&chunk,1,sizeof(chunk));
|
||||
if(res!=sizeof(chunk))
|
||||
return;
|
||||
|
||||
MAT_ENTITY me;
|
||||
memset(&me, 0, sizeof(MAT_ENTITY));
|
||||
me.opacity = 1.0f;
|
||||
me.alpharef = 0;
|
||||
strcpy(me.name, chunk.name);
|
||||
switch (chunk.MtlType)
|
||||
{
|
||||
case MTL_STANDARD:
|
||||
me.IsStdMat = true;
|
||||
me.col_d = chunk.col_d;
|
||||
me.col_a = chunk.col_a;
|
||||
me.col_s = chunk.col_s;
|
||||
me.Dyn_Bounce = chunk.Dyn_Bounce;
|
||||
me.Dyn_StaticFriction = chunk.Dyn_StaticFriction;
|
||||
me.Dyn_SlidingFriction = chunk.Dyn_SlidingFriction;
|
||||
strcpy(me.map_d.name, chunk.tex_d.name);
|
||||
strcpy(me.map_o.name, chunk.tex_o.name);
|
||||
strcpy(me.map_b.name, chunk.tex_b.name);
|
||||
me.nChildren = chunk.nChildren;
|
||||
|
||||
m_lstMaterials.Add(me);
|
||||
break;
|
||||
|
||||
case MTL_MULTI:
|
||||
me.IsStdMat = 0;
|
||||
me.nChildren = chunk.nChildren;
|
||||
me.m_pMaterialChildren = new int [chunk.nChildren];//leak
|
||||
int res=f->FRead(me.m_pMaterialChildren,sizeof(int),chunk.nChildren);
|
||||
if (res != chunk.nChildren)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CryStaticModel::OnLoadgeom(char * FileName, const char * szGeomName, bool bLoadMats, bool bKeepInLocalSpace)
|
||||
{
|
||||
CXFile * f = new CXFile(GetSystem()->GetIPak());
|
||||
|
||||
// preload all data
|
||||
if(!f->FLoad(FileName))
|
||||
{
|
||||
delete f; return 0;
|
||||
}
|
||||
|
||||
//read the file header
|
||||
FILE_HEADER fh;
|
||||
int res = f->FRead(&fh,sizeof(fh),1);
|
||||
if(res!=1)
|
||||
return 0;
|
||||
|
||||
if(fh.Version != GeomFileVersion)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
Warning(0,FileName,"CGF file version error: %s", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(fh.FileType != FileType_Geom)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
Warning(0,FileName,"CGF file version error: %s", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//read the chunk table
|
||||
f->FSeek(fh.ChunkTableOffset,SEEK_SET);
|
||||
int n_chunks=100000;
|
||||
res = f->FRead(&n_chunks,sizeof(n_chunks),1);
|
||||
if(res!=1)
|
||||
return 0;
|
||||
|
||||
if(n_chunks>=100000)
|
||||
{
|
||||
f->FClose(); delete f; f=0;
|
||||
Warning(0,FileName,"CGF File corrupted: %s, (n_chunks>=100000)", FileName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CHUNK_HEADER * pChunks;
|
||||
pChunks=(CHUNK_HEADER *)malloc(sizeof(CHUNK_HEADER)*n_chunks);
|
||||
assert(pChunks);
|
||||
res = f->FRead(pChunks,sizeof(CHUNK_HEADER),n_chunks);
|
||||
if(res!=n_chunks)
|
||||
return 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Create and load objects
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
m_ppNewObjs = (CBaseObj **)malloc(n_chunks*sizeof(CBaseObj*));
|
||||
memset(m_ppNewObjs,0,n_chunks*sizeof(CBaseObj*));
|
||||
|
||||
assert(m_ppNewObjs);
|
||||
m_nNewObjs=0;
|
||||
|
||||
int nGeomToLoadID = -1;
|
||||
|
||||
int i;
|
||||
for(i=0;i<n_chunks;i++)
|
||||
{
|
||||
switch(pChunks[i].ChunkType)
|
||||
{
|
||||
case ChunkType_Node:
|
||||
m_ppNewObjs[m_nNewObjs]=new CNodeCGF();
|
||||
break;
|
||||
|
||||
case ChunkType_Mesh:
|
||||
if(!szGeomName || nGeomToLoadID == i)
|
||||
m_ppNewObjs[m_nNewObjs]=new CGeom();
|
||||
break;
|
||||
|
||||
case ChunkType_Helper:
|
||||
m_ppNewObjs[m_nNewObjs]=new CHelper();
|
||||
break;
|
||||
|
||||
case ChunkType_Light:
|
||||
m_ppNewObjs[m_nNewObjs]=new CLight();
|
||||
break;
|
||||
|
||||
case ChunkType_Mtl:
|
||||
if(bLoadMats)
|
||||
LoadMaterials(f,pChunks[i].FileOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_ppNewObjs[m_nNewObjs])
|
||||
{
|
||||
m_ppNewObjs[m_nNewObjs]->Load(f,pChunks[i].FileOffset);
|
||||
|
||||
// find chunk id of needed geom
|
||||
if(pChunks[i].ChunkType == ChunkType_Node)
|
||||
if(szGeomName && strcmp(szGeomName,((CNodeCGF*)m_ppNewObjs[m_nNewObjs])->m_Chunk.name)==0)
|
||||
nGeomToLoadID = ((CNodeCGF*)m_ppNewObjs[m_nNewObjs])->m_Chunk.ObjectID;
|
||||
|
||||
m_nNewObjs++;
|
||||
}
|
||||
}
|
||||
|
||||
//Do pointer and name list bindings
|
||||
for(i=0;i<m_nNewObjs;i++)
|
||||
{
|
||||
if(!m_ppNewObjs[i])
|
||||
continue;
|
||||
m_ppNewObjs[i]->Bind(m_ppNewObjs, m_nNewObjs);
|
||||
}
|
||||
|
||||
f->FClose(); delete f; f=0;
|
||||
|
||||
if(pChunks)
|
||||
free(pChunks);
|
||||
pChunks=0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Make objects
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
list2<NAME_ENTITY> lstOtherNames;
|
||||
|
||||
for( i=0; i<m_nNewObjs; i++)
|
||||
{
|
||||
CNodeCGF * pNode = (CNodeCGF*)m_ppNewObjs[i];
|
||||
|
||||
if(pNode->m_ChunkHeader.ChunkType != ChunkType_Node)
|
||||
continue;
|
||||
|
||||
// make list of mesh names
|
||||
NAME_ENTITY geomname;
|
||||
strcpy(geomname.name, pNode->m_Chunk.name);
|
||||
lstOtherNames.Add(geomname);
|
||||
|
||||
if(!pNode->m_pObj)
|
||||
continue;
|
||||
|
||||
if(pNode->m_pObj->m_nUsers>1)
|
||||
{
|
||||
Warning( 0,FileName,"Loading of instances from cgf not supported, geom skipped: %s, %s",FileName, pNode->GetName() );
|
||||
}
|
||||
|
||||
// Accumulate this and all parent nodes transformations
|
||||
// TODO: get rid of the obsolete CryMatrix here
|
||||
|
||||
//CHANGED_BY_IVO
|
||||
//CryMatrix matNodeMatrix = pNode->m_Chunk.tm;
|
||||
Matrix44 matNodeMatrix = pNode->m_Chunk.tm;
|
||||
|
||||
for(CNodeCGF * pCurNode = pNode->m_pParent; pCurNode; pCurNode = pCurNode->m_pParent)
|
||||
//CHANGED_BY_IVO
|
||||
//matNodeMatrix = matNodeMatrix * (CryMatrix&)(pCurNode->m_Chunk.tm);
|
||||
matNodeMatrix = matNodeMatrix * (pCurNode->m_Chunk.tm);
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Mesh)
|
||||
if(pNode->m_pObj->m_nUsers<=1)
|
||||
{ // geoms
|
||||
// make list of mesh names
|
||||
NAME_ENTITY geomname;
|
||||
strcpy(geomname.name, pNode->m_Chunk.name);
|
||||
m_lstGeomNames.Add(geomname);
|
||||
lstOtherNames.DeleteLast();
|
||||
|
||||
CGeom * pGeom = (CGeom*)pNode->m_pObj;
|
||||
|
||||
// transform geometry from this node space into CGFs space
|
||||
if(!bKeepInLocalSpace)
|
||||
for(int v=0; v<pGeom->m_Chunk.nVerts; v++)
|
||||
{
|
||||
//CHANGED_BY_IVO
|
||||
//pGeom->m_pVertices[v].p = matNodeMatrix*pGeom->m_pVertices[v].p;
|
||||
//pGeom->m_pVertices[v].n = matNodeMatrix/pGeom->m_pVertices[v].n;
|
||||
pGeom->m_pVertices[v].p = matNodeMatrix.TransformPointOLD(pGeom->m_pVertices[v].p);
|
||||
pGeom->m_pVertices[v].n = matNodeMatrix.TransformVectorOLD(pGeom->m_pVertices[v].n);
|
||||
}
|
||||
|
||||
if(!szGeomName || strcmp(pNode->GetName(),szGeomName)==0)
|
||||
m_lstGeoms.Add(pGeom);
|
||||
}
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Light)
|
||||
{ // make light
|
||||
CLight * pLight = (CLight*)pNode->m_pObj;
|
||||
|
||||
LightInstance inst;
|
||||
memcpy(&inst.Chunk,&pLight->m_Chunk,sizeof(LIGHT_CHUNK_DESC));
|
||||
inst.Chunk = pLight->m_Chunk;
|
||||
|
||||
if(bKeepInLocalSpace)
|
||||
|
||||
//inst.vPos.Set(&pNode->m_Chunk.pos.x);
|
||||
inst.vPos.Set(pNode->m_Chunk.pos[0],pNode->m_Chunk.pos[1],pNode->m_Chunk.pos[2]);
|
||||
|
||||
else
|
||||
//CHANGED_BY_IVO
|
||||
//inst.vPos = Vec3d(matNodeMatrix.data[3]);
|
||||
inst.vPos = matNodeMatrix.GetTranslationOLD();
|
||||
|
||||
if(!pNode->m_pParent)
|
||||
assert( IsEquivalent(pNode->m_Chunk.pos,inst.vPos,VEC_EPSILON) );
|
||||
|
||||
strncpy(inst.szName,pNode->m_Chunk.name, sizeof(inst.szName));
|
||||
|
||||
// load proj texture
|
||||
if(inst.Chunk.szLightImage[0])
|
||||
{
|
||||
inst.pLightImage = GetRenderer()->EF_LoadTexture(inst.Chunk.szLightImage, FT_CLAMP, FT2_FORCECUBEMAP, eTT_Cubemap);
|
||||
if (!inst.pLightImage->IsTextureLoaded())
|
||||
inst.pLightImage = NULL;
|
||||
}
|
||||
else
|
||||
inst.pLightImage = NULL;
|
||||
|
||||
m_lstLights.Add(inst);
|
||||
}
|
||||
|
||||
if(pNode->m_pObj->m_ChunkHeader.ChunkType == ChunkType_Helper)
|
||||
{ // make helper
|
||||
CHelper * pHelper = (CHelper*)pNode->m_pObj;
|
||||
|
||||
HelperInstance inst;
|
||||
inst.Chunk = pHelper->m_Chunk;
|
||||
|
||||
if(bKeepInLocalSpace)
|
||||
inst.tMat.SetIdentity();
|
||||
else
|
||||
//CHANGED_BY_IVO
|
||||
//inst.tMat = Matrix(matNodeMatrix.matrix);
|
||||
inst.tMat = matNodeMatrix;
|
||||
|
||||
/*
|
||||
if(!pNode->m_pParent)
|
||||
{
|
||||
assert(inst.vPos == pNode->m_Chunk.pos);
|
||||
float dot = inst.qRot.Dot(pNode->m_Chunk.rot);
|
||||
dot=dot;
|
||||
}
|
||||
*/
|
||||
strncpy(inst.szName,pNode->m_Chunk.name, sizeof(inst.szName));
|
||||
m_lstHelpers.Add(inst);
|
||||
}
|
||||
}
|
||||
|
||||
m_lstGeomNames.AddList (lstOtherNames);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
CHelperInstance * CryStaticModel::GetHelper(const char * name)
|
||||
{
|
||||
for(int i=0; i<m_Helpers.Count(); i++)
|
||||
{
|
||||
if(!strcmp(m_Helpers[i].name,name))
|
||||
return &m_Helpers[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// this timer measures the time spent in the CGF Loader
|
||||
//double g_dTimeLoadCGF;
|
||||
71
Cry3DEngine/CryStaticModel.h
Normal file
71
Cry3DEngine/CryStaticModel.h
Normal file
@@ -0,0 +1,71 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: crystaticmodel.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: cgf file loader
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CryStaticModel_H
|
||||
#define CryStaticModel_H
|
||||
|
||||
class CBaseObj;
|
||||
class CGeom;
|
||||
|
||||
#include "../Cry3DEngine/Cry3DEngineBase.h"
|
||||
|
||||
struct LightInstance
|
||||
{
|
||||
LIGHT_CHUNK_DESC Chunk;
|
||||
Vec3d vPos;
|
||||
char szName[64];
|
||||
struct ITexPic * pLightImage;
|
||||
};
|
||||
|
||||
struct HelperInstance
|
||||
{
|
||||
HELPER_CHUNK_DESC Chunk;
|
||||
// Vec3d vPos;
|
||||
// CryQuat qRot;
|
||||
char szName[64];
|
||||
Matrix44 tMat;
|
||||
};
|
||||
|
||||
class CXFile;
|
||||
|
||||
struct CryStaticModel : public Cry3DEngineBase
|
||||
{
|
||||
CryStaticModel();
|
||||
~CryStaticModel();
|
||||
|
||||
char m_FileName[256];
|
||||
|
||||
list2<CGeom*> m_lstGeoms;
|
||||
list2<MAT_ENTITY> m_lstMaterials;
|
||||
list2<NAME_ENTITY> m_lstGeomNames;
|
||||
list2<LightInstance> m_lstLights;
|
||||
list2<HelperInstance> m_lstHelpers;
|
||||
|
||||
bool OnLoadgeom(char * filename, const char * geom_name, bool bLoadMats, bool bKeepInLocalSpace);
|
||||
|
||||
float m_fBoundingRadius;
|
||||
float m_fCenterZ;
|
||||
|
||||
void LoadMaterials(CXFile*f, int pos);
|
||||
int m_nNewObjs;
|
||||
CBaseObj ** m_ppNewObjs;
|
||||
/// static CXFile * m_pXFile;
|
||||
};
|
||||
|
||||
// timers that are used for precision very low cost profiling of load times
|
||||
// this timer measures the time spent in the CGF Loader
|
||||
//extern double g_dTimeLoadCGF;
|
||||
|
||||
#endif // CryStaticModel_H
|
||||
307
Cry3DEngine/Decal.cpp
Normal file
307
Cry3DEngine/Decal.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: decals.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: draw, create decals on the world
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "DecalManager.h"
|
||||
#include "3dengine.h"
|
||||
#include "objman.h"
|
||||
|
||||
void CDecal::Process(bool & active, IRenderer * pIRenderer, const float fCurTime, C3DEngine * p3DEngine, IShader * pShader, CCamera* pCamera, float fSortOffset)
|
||||
{
|
||||
// todo: take entity orientation into account
|
||||
m_nDynLMask = ((I3DEngine*)p3DEngine)->GetLightMaskFromPosition(m_pDecalOwner ? m_pDecalOwner->GetPos()+m_vPos : m_vPos, m_fSize);
|
||||
|
||||
uint nDynLightMask = m_nDynLMask;
|
||||
|
||||
// render StatObj decal
|
||||
if(m_pStatObj)
|
||||
{
|
||||
Render3DObject();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get decal alpha from life time
|
||||
float fLifeTime = m_fLifeEndTime - fCurTime;
|
||||
float fAlpha = fLifeTime*2;
|
||||
if(fAlpha > 1.f)
|
||||
fAlpha = 1.f;
|
||||
else if(fAlpha<0)
|
||||
{ // kill
|
||||
active=0;
|
||||
pIRenderer->DeleteLeafBuffer(m_pBigDecalLeafBuffer);
|
||||
m_pBigDecalLeafBuffer=0;
|
||||
return;
|
||||
}
|
||||
|
||||
float fSizeK;
|
||||
if(m_fGrowTime)
|
||||
fSizeK = min(1.f, cry_sqrtf((fCurTime - m_fLifeBeginTime)/m_fGrowTime));
|
||||
else
|
||||
fSizeK = 1.f;
|
||||
|
||||
// if there is owner - transform decal from owner space into world space
|
||||
if(m_pDecalOwner)
|
||||
{
|
||||
// if there is information about decal geometry - render complex decal and project texture on it
|
||||
if(m_pBigDecalLeafBuffer && m_pBigDecalLeafBuffer->m_Indices.m_nItems)
|
||||
{
|
||||
// setup transformation
|
||||
CCObject * pObj = pIRenderer->EF_GetObject(true);
|
||||
pObj->m_SortId = fSortOffset;
|
||||
|
||||
Matrix44 objMat;
|
||||
if(!m_pDecalOwner->GetEntityStatObj(m_nDecalOwnerComponentId, &objMat))
|
||||
{
|
||||
// GetLog()->Log("Error: CDecal::Process: m_nDecalOwnerComponentId is out of range: %d", m_nDecalOwnerComponentId);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
pObj->m_Matrix = objMat;
|
||||
pObj->m_ObjFlags |= FOB_TRANS_MASK;
|
||||
|
||||
p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_pDecalOwner->GetPos(),m_pDecalOwner->GetRenderRadius(),m_pDecalOwner);
|
||||
|
||||
// pIRenderer->DrawBall(objMat.GetTranslation(),1) ;
|
||||
|
||||
pObj->m_DynLMMask = nDynLightMask;
|
||||
|
||||
// somehow it's need's to be twice bigger to be same as simple decals
|
||||
float fSize2 = m_fSize*fSizeK*2.f;///m_pDecalOwner->GetScale();
|
||||
if(fSize2<0.05f)
|
||||
return;
|
||||
|
||||
// todo: transform basis into world space ?
|
||||
|
||||
// setup texgen
|
||||
// S component
|
||||
m_arrBigDecalCustomData[0] = m_vUp.x/fSize2;
|
||||
m_arrBigDecalCustomData[1] = m_vUp.y/fSize2;
|
||||
m_arrBigDecalCustomData[2] = m_vUp.z/fSize2;
|
||||
|
||||
float D0 =
|
||||
m_arrBigDecalCustomData[0]*m_vPos.x +
|
||||
m_arrBigDecalCustomData[1]*m_vPos.y +
|
||||
m_arrBigDecalCustomData[2]*m_vPos.z;
|
||||
|
||||
m_arrBigDecalCustomData[3] = -D0+0.5f;
|
||||
|
||||
// T component
|
||||
m_arrBigDecalCustomData[4] = m_vRight.x/fSize2;
|
||||
m_arrBigDecalCustomData[5] = m_vRight.y/fSize2;
|
||||
m_arrBigDecalCustomData[6] = m_vRight.z/fSize2;
|
||||
|
||||
float D1 =
|
||||
m_arrBigDecalCustomData[4]*m_vPos.x +
|
||||
m_arrBigDecalCustomData[5]*m_vPos.y +
|
||||
m_arrBigDecalCustomData[6]*m_vPos.z;
|
||||
|
||||
m_arrBigDecalCustomData[7] = -D1+0.5f;
|
||||
|
||||
// pass attenuation info
|
||||
m_arrBigDecalCustomData[8] = m_vPos.x;
|
||||
m_arrBigDecalCustomData[9] = m_vPos.y;
|
||||
m_arrBigDecalCustomData[10]= m_vPos.z;
|
||||
m_arrBigDecalCustomData[11]= m_fSize;
|
||||
|
||||
if(m_pDecalOwner->GetEntityRenderType() == eERType_Vegetation)
|
||||
{
|
||||
CObjManager * pObjManager = ((C3DEngine*)p3DEngine)->GetObjManager();
|
||||
CStatObjInst * pStatObjInst = (CStatObjInst *)m_pDecalOwner;
|
||||
CStatObj * pBody = pObjManager->m_lstStaticTypes[pStatObjInst->m_nObjectTypeID].GetStatObj();
|
||||
assert(pObjManager && pStatObjInst && pBody);
|
||||
|
||||
if(pObjManager && pStatObjInst && pBody && pStatObjInst->m_fFinalBending)
|
||||
{
|
||||
pBody->SetupBending(pObj,pStatObjInst->m_fFinalBending);
|
||||
}
|
||||
}
|
||||
|
||||
// draw complex decal using new indices and original object vertices
|
||||
m_pBigDecalLeafBuffer->SetRECustomData(m_arrBigDecalCustomData, 0, fAlpha);
|
||||
m_pBigDecalLeafBuffer->AddRenderElements(pObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
// transform decal in software from owner space into world space and render as quad
|
||||
Matrix44 objMat;
|
||||
IStatObj * pEntObject = m_pDecalOwner->GetEntityStatObj(m_nDecalOwnerComponentId, &objMat);
|
||||
assert(pEntObject);
|
||||
|
||||
Vec3d vPos = objMat.TransformPointOLD(m_vPos);
|
||||
Vec3d vRight = objMat.TransformVectorOLD(m_vRight*m_fSize/m_pDecalOwner->GetScale());
|
||||
Vec3d vUp = objMat.TransformVectorOLD(m_vUp*m_fSize/m_pDecalOwner->GetScale());
|
||||
|
||||
CDLight * pStrongestLightForTranspGeom = NULL;
|
||||
p3DEngine->CheckDistancesToLightSources(nDynLightMask,vPos,m_fSize,0,1,&pStrongestLightForTranspGeom,1);
|
||||
|
||||
UCol uCol;
|
||||
if(pStrongestLightForTranspGeom && pStrongestLightForTranspGeom->m_fRadius)
|
||||
{
|
||||
float fAtten = min(1.f,pStrongestLightForTranspGeom->m_fRadius/pStrongestLightForTranspGeom->m_Origin.GetDistance(m_vWSPos));
|
||||
float fDot = max(0,(pStrongestLightForTranspGeom->m_Origin-m_vWSPos).normalized().Dot(m_vFront));
|
||||
uCol.bcolor[0] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.r));
|
||||
uCol.bcolor[1] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.g));
|
||||
uCol.bcolor[2] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.b));
|
||||
}
|
||||
else
|
||||
uCol.dcolor = 0;
|
||||
|
||||
uCol.bcolor[3] = fastftol_positive(fAlpha*255);
|
||||
p3DEngine->GetObjManager()->AddPolygonToRenderer( m_nTexId, pShader, nDynLightMask,
|
||||
vRight*fSizeK, vUp*fSizeK, uCol, ParticleBlendType_AlphaBased, m_vAmbient, vPos,
|
||||
0,0,0,0,fSortOffset,0,0,
|
||||
m_pDecalOwner->GetEntityRenderType() == eERType_Vegetation ? (CStatObjInst*)m_pDecalOwner : NULL);
|
||||
}
|
||||
}
|
||||
else if(!m_bOnTheGround)
|
||||
{ // draw small world space decal untransformed
|
||||
CDLight * pStrongestLightForTranspGeom = NULL;
|
||||
p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_vPos,m_fSize,0,1,&pStrongestLightForTranspGeom,1);
|
||||
UCol uCol;
|
||||
if(pStrongestLightForTranspGeom && pStrongestLightForTranspGeom->m_fRadius)
|
||||
{
|
||||
float fAtten = min(1.f,pStrongestLightForTranspGeom->m_fRadius/pStrongestLightForTranspGeom->m_Origin.GetDistance(m_vWSPos));
|
||||
float fDot = max(0,(pStrongestLightForTranspGeom->m_Origin-m_vWSPos).normalized().Dot(m_vFront));
|
||||
uCol.bcolor[0] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.r));
|
||||
uCol.bcolor[1] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.g));
|
||||
uCol.bcolor[2] = uchar(min(255.f,355.f*fDot*fAtten*pStrongestLightForTranspGeom->m_Color.b));
|
||||
}
|
||||
else
|
||||
uCol.dcolor = 0;
|
||||
uCol.bcolor[3] = fastftol_positive(fAlpha*255);
|
||||
p3DEngine->GetObjManager()->AddPolygonToRenderer( m_nTexId, pShader, nDynLightMask,
|
||||
m_vRight*m_fSize*fSizeK, m_vUp*m_fSize*fSizeK, uCol, ParticleBlendType_AlphaBased, m_vAmbient, m_vPos,
|
||||
0,0,0,0,fSortOffset);
|
||||
}
|
||||
|
||||
/*{
|
||||
Vec3d vPos = m_vPos + (m_pDecalOwner ? m_pDecalOwner->GetPos() : Vec3d(0,0,0));
|
||||
pIRenderer->Draw3dBBox(vPos,vPos+m_vFront);
|
||||
}*/
|
||||
|
||||
// process life time and disable decal when needed
|
||||
// m_fLifeTime -= fFrameTime;
|
||||
if(m_fLifeEndTime<fCurTime)
|
||||
{
|
||||
active=0;
|
||||
pIRenderer->DeleteLeafBuffer(m_pBigDecalLeafBuffer);
|
||||
m_pBigDecalLeafBuffer=0;
|
||||
}
|
||||
}
|
||||
|
||||
void CDecal::Render3DObject()
|
||||
{
|
||||
// draw
|
||||
if(m_pStatObj)
|
||||
{
|
||||
Vec3d vAngles = m_vFront;
|
||||
vAngles=ConvertVectorToCameraAngles(vAngles);
|
||||
vAngles.x+=90;
|
||||
|
||||
//Matrix mat,mat1;
|
||||
//mat.Identity();
|
||||
//mat=GetRotationZYX44(-gf_DEGTORAD*vAngles)*mat; //NOTE: angles in radians and negated
|
||||
//mat1.Identity();
|
||||
//mat1=GetTranslationMat(m_vPos)*mat1;
|
||||
//mat = mat * mat1;
|
||||
|
||||
//OPTIMISED_BY_IVO
|
||||
Matrix44 mat = Matrix34::CreateRotationXYZ( Deg2Rad(vAngles), m_vPos );
|
||||
mat = GetTransposed44(mat); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
||||
|
||||
SRendParams rParms;
|
||||
rParms.pMatrix = &mat;
|
||||
rParms.dwFObjFlags |= FOB_TRANS_MASK;
|
||||
m_pStatObj->Render(rParms,Vec3(zero),0);
|
||||
}
|
||||
}
|
||||
|
||||
void CDecal::DrawBigDecalOnTerrain(C3DEngine * p3DEngine, IRenderer * pIRenderer, float fCurrTime)
|
||||
{
|
||||
// Get decal alpha from life time
|
||||
float fLifeTime = m_fLifeEndTime - fCurrTime;
|
||||
float fAlpha = fLifeTime*2;
|
||||
if(fAlpha > 1.f)
|
||||
fAlpha = 1.f;
|
||||
else if(fAlpha<0)
|
||||
return;
|
||||
|
||||
Vec3d vColor = p3DEngine->GetWorldColor();
|
||||
pIRenderer->SetMaterialColor(vColor.x,vColor.y,vColor.z,fAlpha);
|
||||
|
||||
// calc area
|
||||
int x1=int(m_vPos.x-m_fSize*0.85)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize();
|
||||
int y1=int(m_vPos.y-m_fSize*0.85)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize();
|
||||
int x2=int(m_vPos.x+CTerrain::GetHeightMapUnitSize()+m_fSize*0.85)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize();
|
||||
int y2=int(m_vPos.y+CTerrain::GetHeightMapUnitSize()+m_fSize*0.85)/CTerrain::GetHeightMapUnitSize()*CTerrain::GetHeightMapUnitSize();
|
||||
|
||||
float fSizeK;
|
||||
if(m_fGrowTime)
|
||||
fSizeK = min(1.f, cry_sqrtf((fCurrTime - m_fLifeBeginTime)/m_fGrowTime));
|
||||
else
|
||||
fSizeK = 1.f;
|
||||
|
||||
float fRadius = m_fSize*fSizeK*2.f;
|
||||
if(fRadius<0.05f)
|
||||
return;
|
||||
|
||||
// limits
|
||||
if(x1<0) x1=0;
|
||||
if(y1<0) y1=0;
|
||||
if(x2>=CTerrain::GetTerrainSize()) x2=CTerrain::GetTerrainSize();
|
||||
if(y2>=CTerrain::GetTerrainSize()) y2=CTerrain::GetTerrainSize();
|
||||
|
||||
// fill buffer and draw
|
||||
list2<struct_VERTEX_FORMAT_P3F_TEX2F> verts;
|
||||
struct_VERTEX_FORMAT_P3F_TEX2F tmp;
|
||||
|
||||
Vec3d vOffset(0,0,0);
|
||||
if(((C3DEngine*)p3DEngine)->GetObjManager())
|
||||
vOffset = (pIRenderer->GetCamera().GetPos()-m_vPos)*0.01f*((C3DEngine*)p3DEngine)->GetObjManager()->m_fZoomFactor;
|
||||
|
||||
for(int x=x1; x<x2; x+=CTerrain::GetHeightMapUnitSize())
|
||||
{
|
||||
verts.Clear();
|
||||
for(int y=y1; y<=y2; y+=CTerrain::GetHeightMapUnitSize())
|
||||
{
|
||||
tmp.xyz.x = (float)x;
|
||||
tmp.xyz.y = (float)y;
|
||||
tmp.xyz.z = p3DEngine->GetTerrainZ(x,y)+0.07f;
|
||||
tmp.st[0] = (((float)x)-m_vPos.x)/fRadius+0.5f;
|
||||
tmp.st[1] = 1.f-((((float)y)-m_vPos.y)/fRadius+0.5f);
|
||||
|
||||
tmp.xyz+=vOffset;
|
||||
verts.Add(tmp);
|
||||
|
||||
tmp.xyz.x = (float)(x+CTerrain::GetHeightMapUnitSize());
|
||||
tmp.xyz.y = (float)y;
|
||||
tmp.xyz.z = p3DEngine->GetTerrainZ((x+CTerrain::GetHeightMapUnitSize()),y)+0.07f;
|
||||
tmp.st[0] = (((float)(x+CTerrain::GetHeightMapUnitSize()))-m_vPos.x)/fRadius+0.5f;
|
||||
tmp.st[1] = 1.f-((((float)y)-m_vPos.y)/fRadius+0.5f);
|
||||
|
||||
tmp.xyz+=vOffset;
|
||||
verts.Add(tmp);
|
||||
}
|
||||
|
||||
if(verts.Count())
|
||||
{
|
||||
pIRenderer->SetTexture(m_nTexId);
|
||||
pIRenderer->SetTexClampMode(true);
|
||||
pIRenderer->DrawTriStrip(&(CVertexBuffer (&verts[0].xyz.x,VERTEX_FORMAT_P3F_TEX2F)),verts.Count());
|
||||
}
|
||||
}
|
||||
}
|
||||
715
Cry3DEngine/DecalManager.cpp
Normal file
715
Cry3DEngine/DecalManager.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: decals.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: draw, create decals on the world
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "DecalManager.h"
|
||||
#include "3dengine.h"
|
||||
#include <IStatObj.h>
|
||||
#include "ObjMan.h"
|
||||
|
||||
#define COMPLEX_DECAL_MIN_SIZE 0.1f
|
||||
|
||||
CDecalManager::CDecalManager(C3DEngine * p3DEngine)
|
||||
{
|
||||
m_nCurDecal = 0;
|
||||
memset(m_arrbActiveDecals,0,sizeof(m_arrbActiveDecals));
|
||||
m_p3DEngine = p3DEngine;
|
||||
m_pShader_ParticleLight = GetRenderer()->EF_LoadShader("ParticleLight", eSH_World, EF_SYSTEM);
|
||||
m_pShader_Decal_VP = GetRenderer()->EF_LoadShader("Decal_VP", eSH_World, EF_SYSTEM);
|
||||
m_pShader_Decal_2D_VP = GetRenderer()->EF_LoadShader("Decal_2D_VP", eSH_World, EF_SYSTEM);
|
||||
}
|
||||
|
||||
// called from the renderer, draws immideately
|
||||
void CDecalManager::DrawBigDecalsOnTerrain()
|
||||
{
|
||||
if(!GetCVars()->e_decals)
|
||||
return;
|
||||
|
||||
//GetRenderer()->ResetToDefault();
|
||||
|
||||
GetRenderer()->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
|
||||
GetRenderer()->SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture|(eCA_Constant<<3), eCA_Texture|(eCA_Constant<<3));
|
||||
GetRenderer()->SetCullMode(R_CULL_DISABLE);
|
||||
|
||||
Vec3d vColor = GetSystem()->GetI3DEngine()->GetWorldColor();//*
|
||||
|
||||
GetRenderer()->SetMaterialColor(vColor.x,vColor.y,vColor.z,1);
|
||||
|
||||
float fCurrTime = GetTimer()->GetCurrTime();
|
||||
|
||||
for(int i=0; i<DECAL_COUNT; i++)
|
||||
if(m_arrbActiveDecals[i])
|
||||
{
|
||||
if(!m_arrDecals[i].m_pStatObj && m_arrDecals[i].m_bOnTheGround)
|
||||
if( GetViewCamera().IsSphereVisibleFast( Sphere(m_arrDecals[i].m_vPos, m_arrDecals[i].m_fSize)) )
|
||||
m_arrDecals[i].DrawBigDecalOnTerrain(m_p3DEngine, GetRenderer(), fCurrTime);
|
||||
}
|
||||
|
||||
//GetRenderer()->ResetToDefault();
|
||||
}
|
||||
|
||||
bool CDecalManager::AdjustDecalPosition( CryEngineDecalInfo & DecalInfo, bool bMakeFatTest )
|
||||
{
|
||||
Matrix44 objMat, objMatInv;
|
||||
int nPartID = DecalInfo.nPartID;
|
||||
IStatObj * pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(nPartID, &objMat, true);
|
||||
while(!pEntObject && nPartID<16)
|
||||
{ // find first visible entity component
|
||||
pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(++nPartID, &objMat, true);
|
||||
}
|
||||
|
||||
if(!pEntObject || !pEntObject->GetLeafBuffer()|| nPartID>=16)
|
||||
return false;
|
||||
|
||||
// transform decal into object space
|
||||
objMatInv = objMat;
|
||||
objMatInv.Invert44();
|
||||
|
||||
// put into normal object space hit direction of projection
|
||||
Vec3d vObjSpaceHitDirection = objMatInv.TransformVectorOLD(DecalInfo.vHitDirection);
|
||||
|
||||
// put into position object space hit position
|
||||
Vec3d vObjSpacePos = objMatInv.TransformPointOLD(DecalInfo.vPos);
|
||||
|
||||
// get decal directions
|
||||
Vec3d vRi(0,0,0), vUp(0,0,0);
|
||||
if(fabs(vObjSpaceHitDirection.Dot(Vec3d(0,0,1)))>0.999f)
|
||||
{ // horiz surface
|
||||
vRi = Vec3d(0,1,0);
|
||||
vUp = Vec3d(1,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vRi = vObjSpaceHitDirection.Cross(Vec3d(0,0,1));
|
||||
vRi.Normalize();
|
||||
vUp = vObjSpaceHitDirection.Cross(vRi);
|
||||
vUp.Normalize();
|
||||
}
|
||||
|
||||
vRi*=DecalInfo.fSize;
|
||||
vUp*=DecalInfo.fSize;
|
||||
|
||||
|
||||
Vec3d vObjSpaceOutPos(0,0,0), vObjSpaceOutNormal(0,0,0), vTmp;
|
||||
CLeafBuffer * pLB = pEntObject->GetLeafBuffer();
|
||||
if( pLB && pLB->m_pSecVertBuffer && pLB->m_SecVertCount &&
|
||||
RayLeafBufferIntersection(pLB, vObjSpacePos, vObjSpaceHitDirection*0.1f, vObjSpaceOutPos, vObjSpaceOutNormal) )
|
||||
{ // now check that none of decal sides will not fly in the air
|
||||
Vec3d vDecalNormal = vObjSpaceOutNormal*DecalInfo.fSize;
|
||||
if( !bMakeFatTest || (
|
||||
RayLeafBufferIntersection(pLB, vObjSpaceOutPos+vUp, -vDecalNormal, vTmp, vTmp) &&
|
||||
RayLeafBufferIntersection(pLB, vObjSpaceOutPos-vUp, -vDecalNormal, vTmp, vTmp) &&
|
||||
RayLeafBufferIntersection(pLB, vObjSpaceOutPos+vRi, -vDecalNormal, vTmp, vTmp) &&
|
||||
RayLeafBufferIntersection(pLB, vObjSpaceOutPos-vRi, -vDecalNormal, vTmp, vTmp) ))
|
||||
{
|
||||
DecalInfo.vPos = objMat.TransformPointOLD(vObjSpaceOutPos);
|
||||
DecalInfo.vNormal = objMat.TransformVectorOLD(vObjSpaceOutNormal);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct HitPosInfo {
|
||||
HitPosInfo() { memset(this,0,sizeof(HitPosInfo)); }
|
||||
Vec3d vPos,vNormal;
|
||||
float fDistance;
|
||||
};
|
||||
|
||||
int __cdecl CDecalManager__CmpHitPos(const void* v1, const void* v2)
|
||||
{
|
||||
HitPosInfo * p1 = (HitPosInfo*)v1;
|
||||
HitPosInfo * p2 = (HitPosInfo*)v2;
|
||||
|
||||
if(p1->fDistance > p2->fDistance)
|
||||
return 1;
|
||||
else if(p1->fDistance < p2->fDistance)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CDecalManager::RayLeafBufferIntersection(CLeafBuffer * pLeafBuffer, const Vec3d & vInPos, const Vec3d & vInDir, Vec3d & vOutPos, Vec3d & vOutNormal)
|
||||
{
|
||||
// get position offset and stride
|
||||
int nPosStride = 0;
|
||||
byte * pPos = pLeafBuffer->GetPosPtr(nPosStride, 0, true);
|
||||
|
||||
// get indices
|
||||
ushort *pInds = pLeafBuffer->GetIndices(0);
|
||||
int nInds = pLeafBuffer->m_Indices.m_nItems;
|
||||
assert(nInds%3 == 0);
|
||||
|
||||
HitPosInfo arrResult[16];
|
||||
memset(arrResult,0,sizeof(arrResult));
|
||||
int nResultCount=0;
|
||||
|
||||
// find faces
|
||||
for(int i=0; i<nInds && nResultCount<16; i+=3)
|
||||
{
|
||||
// get tri vertices
|
||||
Vec3d v0 = *((Vec3d*)&pPos[nPosStride*pInds[i+0]]);
|
||||
Vec3d v1 = *((Vec3d*)&pPos[nPosStride*pInds[i+1]]);
|
||||
Vec3d v2 = *((Vec3d*)&pPos[nPosStride*pInds[i+2]]);
|
||||
|
||||
// make line triangle intersection
|
||||
Vec3d vResPos(0,0,0);
|
||||
if( Intersect::Lineseg_Triangle(Lineseg(vInPos+vInDir, vInPos-vInDir), v0, v1, v2, vResPos) ||
|
||||
Intersect::Lineseg_Triangle(Lineseg(vInPos-vInDir, vInPos+vInDir), v0, v1, v2, vResPos) )
|
||||
{
|
||||
arrResult[nResultCount].vPos = vResPos;
|
||||
arrResult[nResultCount].vNormal = (v1-v0).Cross(v2-v0);
|
||||
arrResult[nResultCount].vNormal.Normalize();
|
||||
arrResult[nResultCount].fDistance = (vInPos-vInDir).GetDistance(vResPos);
|
||||
nResultCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(nResultCount)
|
||||
{ // return closest to the shooter
|
||||
qsort(&arrResult, nResultCount, sizeof(arrResult[0]), CDecalManager__CmpHitPos);
|
||||
vOutPos = arrResult[0].vPos;
|
||||
vOutNormal = arrResult[0].vNormal;
|
||||
}
|
||||
|
||||
return nResultCount!=0;
|
||||
}
|
||||
|
||||
void CDecalManager::Spawn( CryEngineDecalInfo DecalInfo, float fMaxViewDistance, CTerrain * pTerrain )
|
||||
{
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
// DecalInfo.fLifeTime = 1000000000;
|
||||
// DecalInfo.fSize = .5f;
|
||||
// DecalInfo.m_fGrowTime = 4.f;
|
||||
// DecalInfo.nPartID = -1;
|
||||
|
||||
// do not spawn if too far
|
||||
float fZoom = m_p3DEngine->GetObjManager() ? m_p3DEngine->GetObjManager()->m_fZoomFactor : 1.f;
|
||||
float fDecalDistance = L1Distance2D(DecalInfo.vPos, vCamPos);
|
||||
if( fDecalDistance>fMaxViewDistance || fDecalDistance*fZoom>DecalInfo.fSize*ENTITY_DECAL_DIST_FACTOR*3.f )
|
||||
return;
|
||||
|
||||
/* if(DecalInfo.pDecalOwner && DecalInfo.pDecalOwner->GetEntityRenderType() == eERType_Vegetation)
|
||||
{
|
||||
CStatObjInst * pStatObjInst = (CStatObjInst*)DecalInfo.pDecalOwner;
|
||||
if(pStatObjInst->m_fFinalBending)
|
||||
return; // do not spawn on bendable vegetations
|
||||
}*/
|
||||
|
||||
// project decal to visible geoemtry
|
||||
if(DecalInfo.bAdjustPos && DecalInfo.nPartID>=0 && DecalInfo.pDecalOwner && !AdjustDecalPosition( DecalInfo, DecalInfo.fSize<=COMPLEX_DECAL_MIN_SIZE ))
|
||||
return;
|
||||
|
||||
// clamp all decal textures
|
||||
GetRenderer()->SetTexture(DecalInfo.nTid);
|
||||
GetRenderer()->SetTexClampMode(true);
|
||||
|
||||
// don't go crazy
|
||||
if(DecalInfo.fSize > 4)
|
||||
DecalInfo.fSize = 4;
|
||||
|
||||
if(DecalInfo.fSize > 1 && GetCVars()->e_decals_neighbor_max_life_time)
|
||||
{ // force near decals to fade faster
|
||||
float fCurrTime = GetTimer()->GetCurrTime();
|
||||
for(int i=0; i<DECAL_COUNT; i++)
|
||||
if(m_arrbActiveDecals[i])
|
||||
{
|
||||
if(m_arrDecals[i].m_vWSPos.GetDistance(DecalInfo.vPos) < m_arrDecals[i].m_fWSSize+DecalInfo.fSize)
|
||||
if((m_arrDecals[i]).m_fLifeBeginTime < fCurrTime-0.1f)
|
||||
if(m_arrDecals[i].m_fLifeEndTime > fCurrTime+GetCVars()->e_decals_neighbor_max_life_time)
|
||||
m_arrDecals[i].m_fLifeEndTime = fCurrTime+GetCVars()->e_decals_neighbor_max_life_time;
|
||||
}
|
||||
}
|
||||
|
||||
// loop position in array
|
||||
if(m_nCurDecal>=DECAL_COUNT)
|
||||
m_nCurDecal=0;
|
||||
|
||||
// free old LB
|
||||
GetRenderer()->DeleteLeafBuffer(m_arrDecals[m_nCurDecal].m_pBigDecalLeafBuffer);
|
||||
m_arrDecals[m_nCurDecal].m_pBigDecalLeafBuffer=0;
|
||||
|
||||
// just in case
|
||||
DecalInfo.vNormal.Normalize();
|
||||
|
||||
bool bBigDecalOnTheGround = false;
|
||||
|
||||
// remember object we need to follow
|
||||
m_arrDecals[m_nCurDecal].m_nDecalOwnerComponentId = DecalInfo.nPartID;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_vWSPos = DecalInfo.vPos;
|
||||
m_arrDecals[m_nCurDecal].m_fWSSize = DecalInfo.fSize;
|
||||
|
||||
// If owner entity and object is specified - make decal use entity geometry
|
||||
float fObjScale = 1.f;
|
||||
if(DecalInfo.pDecalOwner && DecalInfo.nPartID>=0 && DecalInfo.fSize>COMPLEX_DECAL_MIN_SIZE)
|
||||
{ // get object pointer
|
||||
Matrix44 objMat;
|
||||
IStatObj * pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(DecalInfo.nPartID, &objMat);
|
||||
if(pEntObject)
|
||||
{
|
||||
CLeafBuffer * pSourceLeafBuffer = pEntObject->GetLeafBuffer();
|
||||
|
||||
// transform decal into object space
|
||||
objMat.Invert44();
|
||||
|
||||
// put into normal object space hit direction of projection
|
||||
DecalInfo.vNormal = -objMat.TransformVectorOLD(DecalInfo.vHitDirection);
|
||||
|
||||
// put into position object space hit position
|
||||
DecalInfo.vPos = objMat.TransformPointOLD(DecalInfo.vPos);
|
||||
|
||||
// find object scale
|
||||
if(DecalInfo.pDecalOwner->GetEntityRenderType()==eERType_Vegetation)
|
||||
fObjScale = DecalInfo.pDecalOwner->GetScale();
|
||||
else
|
||||
{
|
||||
Vec3d vTest(0,0,1.f);
|
||||
vTest = objMat.TransformVectorOLD(vTest);
|
||||
fObjScale = 1.f/vTest.len();
|
||||
}
|
||||
|
||||
if(fObjScale<0.01f)
|
||||
return;
|
||||
|
||||
// transform size into object space
|
||||
DecalInfo.fSize/=fObjScale;
|
||||
|
||||
// make decal geometry
|
||||
m_arrDecals[m_nCurDecal].m_pBigDecalLeafBuffer = MakeBigDecalLeafBuffer(pSourceLeafBuffer, DecalInfo.vPos,
|
||||
DecalInfo.fSize, DecalInfo.vNormal, DecalInfo.nTid);
|
||||
|
||||
if(!m_arrDecals[m_nCurDecal].m_pBigDecalLeafBuffer)
|
||||
return; // no geometry found
|
||||
|
||||
ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(DecalInfo.nTid);
|
||||
if(pTexPic)
|
||||
{
|
||||
pTexPic->SetFilter(FILTER_LINEAR);
|
||||
pTexPic->SetClamp(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( 0,0,"CDecalManager::Spawn: nPartID points to empty object");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(DecalInfo.pDecalOwner &&
|
||||
(!DecalInfo.pDecalOwner->IsStatic() || DecalInfo.pDecalOwner->GetEntityRenderType() == eERType_Vegetation) &&
|
||||
DecalInfo.nPartID>=0)
|
||||
{ // transform decal from world space into entity space
|
||||
Matrix44 objMat;
|
||||
IStatObj * pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(DecalInfo.nPartID, &objMat);
|
||||
assert(pEntObject);
|
||||
objMat.Invert44();
|
||||
|
||||
DecalInfo.vNormal = objMat.TransformVectorOLD(DecalInfo.vNormal);
|
||||
DecalInfo.vNormal.Normalize();
|
||||
DecalInfo.vPos = objMat.TransformPointOLD(DecalInfo.vPos);
|
||||
|
||||
// find object scale
|
||||
if(DecalInfo.pDecalOwner->GetEntityRenderType()==eERType_Vegetation)
|
||||
fObjScale = DecalInfo.pDecalOwner->GetScale();
|
||||
else
|
||||
{
|
||||
Vec3d vTest(0,0,1.f);
|
||||
vTest = objMat.TransformVectorOLD(vTest);
|
||||
fObjScale = 1.f/vTest.len();
|
||||
}
|
||||
|
||||
ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(DecalInfo.nTid);
|
||||
if(pTexPic)
|
||||
{
|
||||
pTexPic->SetFilter(FILTER_LINEAR);
|
||||
pTexPic->SetClamp(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DecalInfo.fSize>COMPLEX_DECAL_MIN_SIZE && !DecalInfo.pDecalOwner &&
|
||||
(DecalInfo.vPos.z-pTerrain->GetZApr(DecalInfo.vPos.x,DecalInfo.vPos.y))<DecalInfo.fSize)
|
||||
{
|
||||
int nUnitSize = CTerrain::GetHeightMapUnitSize();
|
||||
int x1 = int(DecalInfo.vPos.x-DecalInfo.fSize)/nUnitSize*nUnitSize-nUnitSize;
|
||||
int x2 = int(DecalInfo.vPos.x+DecalInfo.fSize)/nUnitSize*nUnitSize+nUnitSize;
|
||||
int y1 = int(DecalInfo.vPos.y-DecalInfo.fSize)/nUnitSize*nUnitSize-nUnitSize;
|
||||
int y2 = int(DecalInfo.vPos.y+DecalInfo.fSize)/nUnitSize*nUnitSize+nUnitSize;
|
||||
|
||||
for(int x=x1; x<=x2; x+=CTerrain::GetHeightMapUnitSize())
|
||||
for(int y=y1; y<=y2; y+=CTerrain::GetHeightMapUnitSize())
|
||||
if(pTerrain->GetHoleSafe(x,y))
|
||||
return;
|
||||
|
||||
bBigDecalOnTheGround = true;
|
||||
|
||||
ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(DecalInfo.nTid);
|
||||
if(pTexPic)
|
||||
{
|
||||
pTexPic->SetFilter(FILTER_LINEAR);
|
||||
pTexPic->SetClamp(true);
|
||||
}
|
||||
}
|
||||
|
||||
DecalInfo.pDecalOwner = NULL;
|
||||
}
|
||||
|
||||
DecalInfo.vNormal.Normalize();
|
||||
|
||||
// spawn
|
||||
m_arrDecals[m_nCurDecal].m_vPos = DecalInfo.vPos;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_vPos += DecalInfo.vNormal*0.01f/fObjScale;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_bOnTheGround = bBigDecalOnTheGround;
|
||||
|
||||
if(fabs(DecalInfo.vNormal.Dot(Vec3d(0,0,1)))>0.999f)
|
||||
{ // horiz surface
|
||||
m_arrDecals[m_nCurDecal].m_vRight = Vec3d(0,1,0);
|
||||
m_arrDecals[m_nCurDecal].m_vUp = Vec3d(1,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_arrDecals[m_nCurDecal].m_vRight = DecalInfo.vNormal.Cross(Vec3d(0,0,1));
|
||||
m_arrDecals[m_nCurDecal].m_vRight.Normalize();
|
||||
m_arrDecals[m_nCurDecal].m_vUp = DecalInfo.vNormal.Cross(m_arrDecals[m_nCurDecal].m_vRight);
|
||||
m_arrDecals[m_nCurDecal].m_vUp.Normalize();
|
||||
}
|
||||
/*
|
||||
// check that decal will look ok here
|
||||
if(!DecalInfo.pDecalOwner && DecalInfo.fSize<=COMPLEX_DECAL_MIN_SIZE)
|
||||
{
|
||||
ray_hit hit;
|
||||
float fSize = DecalInfo.fSize*2;
|
||||
|
||||
if(GetPhysicalWorld()->RayWorldIntersection(
|
||||
DecalInfo.vPos - DecalInfo.vNormal*fSize + m_arrDecals[m_nCurDecal].m_vUp*fSize, DecalInfo.vNormal*fSize*2,
|
||||
ent_all, rwi_stop_at_pierceable,&hit,1)
|
||||
&& GetPhysicalWorld()->RayWorldIntersection(
|
||||
DecalInfo.vPos - DecalInfo.vNormal*fSize - m_arrDecals[m_nCurDecal].m_vUp*fSize, DecalInfo.vNormal*fSize*2,
|
||||
ent_all, rwi_stop_at_pierceable,&hit,1)
|
||||
&& GetPhysicalWorld()->RayWorldIntersection(
|
||||
DecalInfo.vPos - DecalInfo.vNormal*fSize + m_arrDecals[m_nCurDecal].m_vRight*fSize, DecalInfo.vNormal*fSize*2,
|
||||
ent_all, rwi_stop_at_pierceable,&hit,1)
|
||||
&& GetPhysicalWorld()->RayWorldIntersection(
|
||||
DecalInfo.vPos - DecalInfo.vNormal*fSize - m_arrDecals[m_nCurDecal].m_vRight*fSize, DecalInfo.vNormal*fSize*2,
|
||||
ent_all, rwi_stop_at_pierceable,&hit,1))
|
||||
{
|
||||
int t=0; // ok
|
||||
}
|
||||
else
|
||||
return; // position is bad
|
||||
}
|
||||
*/
|
||||
// rotate vectors
|
||||
AngleAxis rotation(DecalInfo.fAngle,DecalInfo.vNormal);
|
||||
m_arrDecals[m_nCurDecal].m_vRight = rotation*m_arrDecals[m_nCurDecal].m_vRight;
|
||||
m_arrDecals[m_nCurDecal].m_vUp = rotation*m_arrDecals[m_nCurDecal].m_vUp;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_vFront = DecalInfo.vNormal;
|
||||
m_arrDecals[m_nCurDecal].m_fSize = DecalInfo.fSize;
|
||||
m_arrDecals[m_nCurDecal].m_fLifeEndTime = GetTimer()->GetCurrTime() + DecalInfo.fLifeTime*GetCVars()->e_decals_life_time_scale;
|
||||
m_arrDecals[m_nCurDecal].m_nTexId = DecalInfo.nTid;
|
||||
m_arrDecals[m_nCurDecal].m_fAngle = DecalInfo.fAngle;
|
||||
m_arrDecals[m_nCurDecal].m_pStatObj = DecalInfo.pStatObj;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_vAmbient = Get3DEngine()->GetAmbientColorFromPosition(DecalInfo.vPos);
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_pDecalOwner = DecalInfo.pDecalOwner;
|
||||
|
||||
m_arrDecals[m_nCurDecal].m_fGrowTime = DecalInfo.m_fGrowTime;
|
||||
m_arrDecals[m_nCurDecal].m_fLifeBeginTime = GetTimer()->GetCurrTime();
|
||||
|
||||
if(DecalInfo.pStatObj)
|
||||
{
|
||||
DecalInfo.pStatObj->RegisterUser();
|
||||
CDecal tmp;
|
||||
tmp.m_vPos = DecalInfo.vPos;
|
||||
tmp.m_vFront = DecalInfo.vNormal;
|
||||
tmp.m_nTexId = DecalInfo.nTid;
|
||||
tmp.m_fSize = DecalInfo.fSize;
|
||||
m_LightHoles.Add(tmp);
|
||||
}
|
||||
|
||||
m_arrbActiveDecals[m_nCurDecal] = true;
|
||||
|
||||
m_nCurDecal++;
|
||||
}
|
||||
|
||||
void CDecalManager::SubmitLightHolesToRenderer()
|
||||
{
|
||||
if(!this)
|
||||
return;
|
||||
|
||||
for(int i=0; i<m_LightHoles.Count(); i++)
|
||||
GetRenderer()->EF_SetLightHole(m_LightHoles[i].m_vPos,
|
||||
m_LightHoles[i].m_vFront, m_LightHoles[i].m_nTexId, m_LightHoles[i].m_fSize);
|
||||
|
||||
m_LightHoles.Clear();
|
||||
}
|
||||
|
||||
void CDecalManager::Render()
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
if(!GetCVars()->e_decals || !m_p3DEngine->GetObjManager() || m_p3DEngine->GetCurrentLightSpec() < 1)
|
||||
return;
|
||||
|
||||
CCamera * pCamera = &GetViewCamera();
|
||||
Vec3d vCamPos = pCamera->GetPos();
|
||||
float fCurrTime = GetTimer()->GetCurrTime();
|
||||
IRenderer * pIRenderer = GetRenderer();
|
||||
CObjManager * pObjManager = m_p3DEngine->GetObjManager();
|
||||
float fZoom = m_p3DEngine->GetObjManager()->m_fZoomFactor;
|
||||
float fWaterLevel = m_p3DEngine->GetWaterLevel();
|
||||
|
||||
// draw
|
||||
for(int i=0; i<DECAL_COUNT; i++)
|
||||
if(m_arrbActiveDecals[i])
|
||||
{
|
||||
CDecal * pDecal = &m_arrDecals[i];
|
||||
if(L1Distance2D(vCamPos, pDecal->m_vWSPos)*fZoom < pDecal->m_fWSSize*ENTITY_DECAL_DIST_FACTOR)
|
||||
{
|
||||
float fSortOffset = pObjManager->GetSortOffset(pDecal->m_vWSPos,vCamPos,fWaterLevel);
|
||||
pDecal->Process(m_arrbActiveDecals[i], pIRenderer, fCurrTime, m_p3DEngine, m_pShader_ParticleLight, pCamera, fSortOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDecalManager::OnEntityDeleted(IEntityRender * pEntityRender)
|
||||
{
|
||||
/* if(pEntityRender && pEntityRender->GetEntityRenderType()!=eERType_Unknown)
|
||||
{ // remove all decals, can happend only during editing or level unloading
|
||||
memset(m_arrbActiveDecals,0,sizeof(m_arrbActiveDecals));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// remove decals of this entity
|
||||
for(int i=0; i<DECAL_COUNT; i++)
|
||||
if(m_arrbActiveDecals[i])
|
||||
{
|
||||
if(m_arrDecals[i].m_pDecalOwner == pEntityRender)
|
||||
{
|
||||
assert(pEntityRender->GetEntityRS());
|
||||
m_arrbActiveDecals[i] = false;
|
||||
if(m_arrDecals[i].m_pBigDecalLeafBuffer)
|
||||
{
|
||||
GetRenderer()->DeleteLeafBuffer(m_arrDecals[i].m_pBigDecalLeafBuffer);
|
||||
m_arrDecals[i].m_pBigDecalLeafBuffer=0;
|
||||
}
|
||||
m_arrDecals[i].m_pDecalOwner = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDecalManager::FillBigDecalIndices(CLeafBuffer * pLeafBuffer, Vec3d vPos, float fRadius, Vec3d vProjDir, list2<ushort> * plstIndices)
|
||||
{
|
||||
// get position offset and stride
|
||||
int nPosStride = 0, nNormStride = 0;
|
||||
byte * pPos = pLeafBuffer->GetPosPtr(nPosStride, 0, true);
|
||||
byte * pNorm = pLeafBuffer->GetNormalPtr(nNormStride, 0, true);
|
||||
|
||||
ushort *pInds = pLeafBuffer->GetIndices(0);
|
||||
int nInds = pLeafBuffer->m_Indices.m_nItems;
|
||||
|
||||
assert(nInds%3 == 0);
|
||||
|
||||
plstIndices->Clear();
|
||||
vProjDir.Normalize();
|
||||
|
||||
// Plane plane = GetPlane(vProjDir,vPos);
|
||||
|
||||
// fill decal indices
|
||||
for(int i=0; i<nInds; i+=3)
|
||||
{
|
||||
// get tri vertices
|
||||
Vec3d v0 = *((Vec3d*)&pPos[nPosStride*pInds[i+0]]);
|
||||
Vec3d v1 = *((Vec3d*)&pPos[nPosStride*pInds[i+1]]);
|
||||
Vec3d v2 = *((Vec3d*)&pPos[nPosStride*pInds[i+2]]);
|
||||
|
||||
// get tri normals
|
||||
Vec3d n0 = *((Vec3d*)&pNorm[nNormStride*pInds[i+0]]);
|
||||
Vec3d n1 = *((Vec3d*)&pNorm[nNormStride*pInds[i+1]]);
|
||||
Vec3d n2 = *((Vec3d*)&pNorm[nNormStride*pInds[i+2]]);
|
||||
|
||||
// find bbox
|
||||
Vec3d vBoxMin = v0; vBoxMin.CheckMin(v1); vBoxMin.CheckMin(v2);
|
||||
Vec3d vBoxMax = v0; vBoxMax.CheckMax(v1); vBoxMax.CheckMax(v2);
|
||||
|
||||
if(vProjDir.IsZero())
|
||||
{ // explo mode
|
||||
// get dir to triangle
|
||||
// Vec3d vCenter = (v0+v1+v2)*0.33333f;
|
||||
|
||||
// test the face
|
||||
float fDot0 = (vPos-v0).Dot(n0);
|
||||
float fDot1 = (vPos-v1).Dot(n1);
|
||||
float fDot2 = (vPos-v2).Dot(n2);
|
||||
float fTest = -0.15f;
|
||||
if(fDot0 < fTest && fDot1 < fTest && fDot2 < fTest)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get triangle normal
|
||||
Vec3d vNormal = (v1-v0).Cross(v2-v0);
|
||||
vNormal.Normalize();
|
||||
|
||||
// test the face
|
||||
if(vNormal.Dot(vProjDir)<0)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(Overlap::Sphere_AABB(Sphere(vPos, fRadius), AABB(vBoxMin,vBoxMax)))
|
||||
{
|
||||
plstIndices->Add(pInds[i+0]);
|
||||
plstIndices->Add(pInds[i+1]);
|
||||
plstIndices->Add(pInds[i+2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CLeafBuffer * CDecalManager::MakeBigDecalLeafBuffer(CLeafBuffer * pSourceLeafBuffer, Vec3d vPos, float fRadius, Vec3d vProjDir, int nTexID)
|
||||
{
|
||||
if(!pSourceLeafBuffer || pSourceLeafBuffer->m_SecVertCount==0)
|
||||
return 0;
|
||||
|
||||
// make indices of this decal
|
||||
list2<ushort> lstIndices;
|
||||
|
||||
if(pSourceLeafBuffer && pSourceLeafBuffer->m_pSecVertBuffer && pSourceLeafBuffer->m_SecVertCount)
|
||||
FillBigDecalIndices(pSourceLeafBuffer, vPos, fRadius, vProjDir, &lstIndices);
|
||||
|
||||
if(!lstIndices.Count())
|
||||
return 0;
|
||||
|
||||
// make fake vert buffer with one vertex // todo: remove this
|
||||
list2<struct_VERTEX_FORMAT_P3F_COL4UB> EmptyVertBuffer;
|
||||
EmptyVertBuffer.Add(struct_VERTEX_FORMAT_P3F_COL4UB());
|
||||
|
||||
CLeafBuffer * pLeafBuffer = GetRenderer()->CreateLeafBufferInitialized(
|
||||
EmptyVertBuffer.GetElements(), EmptyVertBuffer.Count(), VERTEX_FORMAT_P3F_COL4UB,
|
||||
lstIndices.GetElements(), lstIndices.Count(),
|
||||
R_PRIMV_TRIANGLES, "BigDecal", eBT_Static, 1, nTexID);
|
||||
|
||||
pLeafBuffer->SetVertexContainer(pSourceLeafBuffer);
|
||||
|
||||
IShader * pShader = vProjDir.IsZero() ? m_pShader_Decal_VP : m_pShader_Decal_2D_VP;
|
||||
pLeafBuffer->SetChunk(pShader, 0, pSourceLeafBuffer->m_SecVertCount, 0, lstIndices.Count());
|
||||
pLeafBuffer->SetShader(pShader,nTexID);
|
||||
|
||||
return pLeafBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
CLeafBuffer * CDecalManager::MakeBigDecalLeafBuffer(CLeafBuffer * pSourceLeafBuffer, Vec3d vPos, float fRadius, Vec3d vProjDir, int nTexID)
|
||||
{
|
||||
if(!pSourceLeafBuffer || pSourceLeafBuffer->m_SecVertCount==0)
|
||||
return 0;
|
||||
|
||||
// make indices of this decal
|
||||
list2<ushort> lstIndices;
|
||||
|
||||
if(pSourceLeafBuffer && pSourceLeafBuffer->m_pSecVertBuffer && pSourceLeafBuffer->m_SecVertCount)
|
||||
FillBigDecalIndices(pSourceLeafBuffer, vPos, fRadius, vProjDir, &lstIndices);
|
||||
|
||||
if(!lstIndices.Count())
|
||||
return 0;
|
||||
|
||||
// make fake vert buffer with one vertex // todo: remove this
|
||||
list2<struct_VERTEX_FORMAT_P3F_N> VertBuffer;
|
||||
VertBuffer.PreAllocate(pSourceLeafBuffer->m_SecVertCount);
|
||||
int nPosStride=0, nNormStride=0;
|
||||
void * pPos = pSourceLeafBuffer->GetPosPtr(nPosStride);
|
||||
void * pNorm = pSourceLeafBuffer->GetPosPtr(nNormStride);
|
||||
for(int i=0; i<pSourceLeafBuffer->m_SecVertCount; i++)
|
||||
{
|
||||
struct_VERTEX_FORMAT_P3F_N vert;
|
||||
vert.xyz = *(Vec3d*)((uchar*)pPos+nPosStride*i);
|
||||
vert.normal = *(Vec3d*)((uchar*)pNorm+nNormStride*i);
|
||||
vert.normal = vert.normal*5;
|
||||
VertBuffer.Add(vert);
|
||||
}
|
||||
|
||||
CLeafBuffer * pLeafBuffer = GetRenderer()->CreateLeafBufferInitialized(
|
||||
VertBuffer.GetElements(), VertBuffer.Count(), VERTEX_FORMAT_P3F_N,
|
||||
lstIndices.GetElements(), lstIndices.Count(),
|
||||
R_PRIMV_TRIANGLES, "BigDecal", eBT_Static, 1, nTexID);
|
||||
|
||||
pLeafBuffer->SetChunk(m_pShader_Decal_VP, 0, pSourceLeafBuffer->m_SecVertCount, 0, lstIndices.Count());
|
||||
pLeafBuffer->SetShader(m_pShader_Decal_VP,nTexID);
|
||||
|
||||
return pLeafBuffer;
|
||||
}
|
||||
*/
|
||||
void CDecalManager::GetMemoryUsage(ICrySizer*pSizer)
|
||||
{
|
||||
pSizer->Add (*this);
|
||||
pSizer->AddContainer (m_LightHoles);
|
||||
}
|
||||
|
||||
void CDecalManager::DeleteDecalsInRange( Vec3d vBoxMin, Vec3d vBoxMax, bool bDeleteBigTerrainDecals )
|
||||
{
|
||||
for(int i=0; i<DECAL_COUNT; i++)
|
||||
if(m_arrbActiveDecals[i] && !m_arrDecals[i].m_bOnTheGround)
|
||||
{
|
||||
if(!m_arrDecals[i].m_pDecalOwner &&
|
||||
m_arrDecals[i].m_vPos.x<vBoxMax.x &&
|
||||
m_arrDecals[i].m_vPos.y<vBoxMax.y &&
|
||||
m_arrDecals[i].m_vPos.z<vBoxMax.z &&
|
||||
m_arrDecals[i].m_vPos.x>vBoxMin.x &&
|
||||
m_arrDecals[i].m_vPos.y>vBoxMin.y &&
|
||||
m_arrDecals[i].m_vPos.z>vBoxMin.z )
|
||||
{
|
||||
m_arrbActiveDecals[i] = false;
|
||||
GetRenderer()->DeleteLeafBuffer(m_arrDecals[i].m_pBigDecalLeafBuffer);
|
||||
m_arrDecals[i].m_pBigDecalLeafBuffer=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
struct CDebugLine
|
||||
{
|
||||
Vec3d v0,v1;
|
||||
int nFrameId;
|
||||
};
|
||||
|
||||
list2<CDebugLine> lstDebugLines;
|
||||
|
||||
void AddDebugLine(Vec3d v0, Vec3d v1, int nFrameId)
|
||||
{
|
||||
CDebugLine l;
|
||||
l.v0 = v0;
|
||||
l.v1 = v1;
|
||||
l.nFrameId = nFrameId;
|
||||
lstDebugLines.Add(l);
|
||||
}
|
||||
|
||||
void DrawDebugLines(IRenderer*pRenderer)
|
||||
{
|
||||
for(int i=0; i<lstDebugLines.Count(); i++)
|
||||
{
|
||||
pRenderer->Draw3dPrim(lstDebugLines[i].v0,lstDebugLines[i].v1,DPRIM_LINE);
|
||||
if(pRenderer->GetFrameID()>lstDebugLines[i].nFrameId+1000)
|
||||
{
|
||||
lstDebugLines.Delete(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
86
Cry3DEngine/DecalManager.h
Normal file
86
Cry3DEngine/DecalManager.h
Normal file
@@ -0,0 +1,86 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: decalmanager.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DECAL_MANAGER
|
||||
#define DECAL_MANAGER
|
||||
|
||||
#define DECAL_COUNT (512)
|
||||
#define ENTITY_DECAL_DIST_FACTOR (200)
|
||||
|
||||
class C3DEngine;
|
||||
|
||||
class CDecal
|
||||
{
|
||||
public:
|
||||
|
||||
// cur state
|
||||
Vec3d m_vPos;
|
||||
Vec3d m_vRight, m_vUp, m_vFront;
|
||||
float m_fSize;
|
||||
Vec3d m_vWSPos;
|
||||
float m_fWSSize;
|
||||
|
||||
// life style
|
||||
float m_fLifeEndTime;
|
||||
int m_nTexId;
|
||||
float m_fAngle;
|
||||
IStatObj * m_pStatObj;
|
||||
uint m_nDynLMask;
|
||||
Vec3d m_vAmbient;
|
||||
IEntityRender * m_pDecalOwner;
|
||||
int m_nDecalOwnerComponentId;
|
||||
bool m_bOnTheGround;
|
||||
float m_fGrowTime;
|
||||
float m_fLifeBeginTime;
|
||||
|
||||
// todo: move it into separate structure
|
||||
CLeafBuffer * m_pBigDecalLeafBuffer;
|
||||
float m_arrBigDecalCustomData[16];
|
||||
|
||||
CDecal() { ZeroStruct(*this); }
|
||||
void Process(bool & active, IRenderer * pIRenderer, const float fFrameTime, C3DEngine * p3DEngine, IShader * pShader, CCamera* pCamera, float fSortOffset);
|
||||
void DrawBigDecalOnTerrain(C3DEngine * p3DEngine, IRenderer * pIRenderer, float fCurrTime);
|
||||
void Render3DObject();
|
||||
void DrawComplexDecal(IRenderer * pIRenderer);
|
||||
};
|
||||
|
||||
class CDecalManager : public Cry3DEngineBase
|
||||
{
|
||||
CDecal m_arrDecals[DECAL_COUNT];
|
||||
bool m_arrbActiveDecals[DECAL_COUNT];
|
||||
int m_nCurDecal;
|
||||
C3DEngine * m_p3DEngine;
|
||||
list2<CDecal> m_LightHoles;
|
||||
IShader * m_pShader_ParticleLight, * m_pShader_Decal_VP, * m_pShader_Decal_2D_VP;
|
||||
public:
|
||||
|
||||
CDecalManager(C3DEngine * p3DEngine);
|
||||
void Spawn(CryEngineDecalInfo Decal, float fMaxViewDistance, CTerrain * pTerrain);
|
||||
void Render();
|
||||
void SubmitLightHolesToRenderer();
|
||||
void DrawBigDecalsOnTerrain();
|
||||
void OnEntityDeleted(IEntityRender * pEntityRS);
|
||||
|
||||
// complex decals
|
||||
void FillBigDecalIndices(CLeafBuffer * pLeafBuffer, Vec3d vPos, float fRadius, Vec3d vProjDir, list2<ushort> * plstIndices);
|
||||
CLeafBuffer * MakeBigDecalLeafBuffer(CLeafBuffer * pSourceLeafBuffer, Vec3d vPos, float fRadius, Vec3d vProjDir, int nTexID);
|
||||
void GetMemoryUsage(ICrySizer*pSizer);
|
||||
void Reset() { memset(m_arrbActiveDecals,0,sizeof(m_arrbActiveDecals)); m_nCurDecal=0; }
|
||||
void DeleteDecalsInRange( Vec3d vBoxMin, Vec3d vBoxMax, bool bDeleteBigTerrainDecals);
|
||||
bool AdjustDecalPosition( CryEngineDecalInfo & DecalInfo, bool bMakeFatTest );
|
||||
bool RayLeafBufferIntersection(CLeafBuffer * pLeafBuffer, const Vec3d & vInPos, const Vec3d & vInDir, Vec3d & vOutPos, Vec3d & vOutNormal);
|
||||
};
|
||||
|
||||
#endif // DECAL_MANAGER
|
||||
314
Cry3DEngine/File.cpp
Normal file
314
Cry3DEngine/File.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: file.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: ceached file access
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#if defined(LINUX)
|
||||
#include <sys/io.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#include "File.h"
|
||||
#include "ICryPak.h"
|
||||
|
||||
ICryPak * CXFile::m_pCryPak = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CXFile::CXFile(struct ICryPak * pCryPak)
|
||||
{
|
||||
m_pCryPak = pCryPak;
|
||||
m_szFileStart=NULL;
|
||||
m_nFileSize=0;
|
||||
m_pCurrPos=0;
|
||||
m_pEndOfFile=NULL;
|
||||
m_sLoadedFileName[0]=0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FRead(void *pDest,int nSize,int nNumElems)
|
||||
{
|
||||
int nTotSize=nSize*nNumElems;
|
||||
char *pTest=m_pCurrPos+nTotSize;
|
||||
if (pTest>m_pEndOfFile)
|
||||
return (0);
|
||||
|
||||
memcpy(pDest,m_pCurrPos,nTotSize);
|
||||
m_pCurrPos+=nTotSize;
|
||||
return (nNumElems);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FSeek(int nOff,int nFrom)
|
||||
{
|
||||
if (nFrom==SEEK_SET)
|
||||
{
|
||||
m_pCurrPos=m_szFileStart+nOff;
|
||||
if (m_pCurrPos>m_pEndOfFile)
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::FClose()
|
||||
{
|
||||
if (m_szFileStart)
|
||||
{
|
||||
delete [] m_szFileStart;
|
||||
m_szFileStart=NULL;
|
||||
}
|
||||
|
||||
m_pCurrPos=NULL;
|
||||
m_nFileSize=0;
|
||||
m_pEndOfFile=NULL;
|
||||
m_sLoadedFileName[0]=0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::FLoad(const char * filename)
|
||||
{
|
||||
if(!m_szFileStart || strcmp(m_sLoadedFileName,filename)!=0)
|
||||
{
|
||||
FClose();
|
||||
m_nFileSize=LoadInMemory(filename,(void**)&m_szFileStart);
|
||||
strncpy(m_sLoadedFileName,filename,sizeof(m_sLoadedFileName));
|
||||
}
|
||||
|
||||
m_pCurrPos=m_szFileStart;
|
||||
m_pEndOfFile=m_szFileStart+m_nFileSize;
|
||||
return (m_nFileSize);
|
||||
}
|
||||
|
||||
//get filename's extension
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
char *CXFile::GetExtension(const char *filename)
|
||||
{
|
||||
char *src = (char *)filename+strlen(filename)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '.')
|
||||
{
|
||||
return (++src);
|
||||
}
|
||||
src--;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
//remove extension from filename
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::RemoveExtension(char *path)
|
||||
{
|
||||
char *src = path+strlen(path)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '.')
|
||||
{
|
||||
*src = 0; // remove extension
|
||||
return;
|
||||
}
|
||||
src--;
|
||||
}
|
||||
}
|
||||
|
||||
//replace filename extension
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::ReplaceExtension(char *path, const char *new_ext)
|
||||
{
|
||||
RemoveExtension(path);
|
||||
strcat(path,".");
|
||||
strcat(path,new_ext);
|
||||
}
|
||||
|
||||
//check if file exist
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CXFile::IsFileExist(const char *filename)
|
||||
{
|
||||
return FileExist(filename);
|
||||
}
|
||||
|
||||
//check if file exist
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CXFile::FileExist(const char *filename)
|
||||
{
|
||||
FILE * fp = m_pCryPak->FOpen(filename,"rb");
|
||||
if (!fp)
|
||||
return (false);
|
||||
m_pCryPak->FClose(fp);
|
||||
return (true);
|
||||
}
|
||||
|
||||
//get length of the file
|
||||
//return (-1) if error
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::GetLength(const char *filename)
|
||||
{
|
||||
FILE * fp = m_pCryPak->FOpen(filename,"rb");
|
||||
if (!fp)
|
||||
return (-1);
|
||||
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = m_pCryPak->FTell(fp);
|
||||
m_pCryPak->FSeek(fp, 0, SEEK_END);
|
||||
end = m_pCryPak->FTell(fp);
|
||||
m_pCryPak->FSeek(fp, pos, SEEK_SET);
|
||||
|
||||
m_pCryPak->FClose(fp);
|
||||
return (end);
|
||||
}
|
||||
|
||||
//tell if filename1 is older than masterfile
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/*bool CXFile::IsOutOfDate(const char *pFileName1,const char *pMasterFile)
|
||||
{
|
||||
|
||||
FILE * f = m_pCryPak->FOpen(pMasterFile,"rb");
|
||||
if (f)
|
||||
m_pCryPak->FClose(f);
|
||||
else
|
||||
return (false);
|
||||
|
||||
f = m_pCryPak->FOpen(pFileName1,"rb");
|
||||
if (f)
|
||||
m_pCryPak->FClose(f);
|
||||
else
|
||||
return (true);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
HANDLE status1 = CreateFile(pFileName1,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
HANDLE status2 = CreateFile(pMasterFile,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
FILETIME writetime1,writetime2;
|
||||
|
||||
GetFileTime(status1,NULL,NULL,&writetime1);
|
||||
GetFileTime(status2,NULL,NULL,&writetime2);
|
||||
|
||||
CloseHandle(status1);
|
||||
CloseHandle(status2);
|
||||
|
||||
if (CompareFileTime(&writetime1,&writetime2)==-1)
|
||||
return(true);
|
||||
|
||||
return (false);
|
||||
#else
|
||||
|
||||
return (false);
|
||||
|
||||
#endif
|
||||
|
||||
}*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/*int CXFile::GetWriteTime(const char *pFileName1)
|
||||
{
|
||||
FILE * f = m_pCryPak->FOpen(pFileName1,"rb");
|
||||
if (f)
|
||||
m_pCryPak->FClose(f);
|
||||
else
|
||||
return (0);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
HANDLE status1 = CreateFile(pFileName1,GENERIC_READ,FILE_SHARE_READ,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
|
||||
FILETIME writetime1;
|
||||
memset(&writetime1,0,sizeof(writetime1));
|
||||
|
||||
GetFileTime(status1,NULL,NULL,&writetime1);
|
||||
|
||||
CloseHandle(status1);
|
||||
|
||||
return (writetime1.dwHighDateTime + writetime1.dwLowDateTime);
|
||||
#else
|
||||
|
||||
return (0);
|
||||
|
||||
#endif
|
||||
|
||||
} */
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::GetLength(FILE *f)
|
||||
{
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = m_pCryPak->FTell(f);
|
||||
m_pCryPak->FSeek(f, 0, SEEK_END);
|
||||
end = m_pCryPak->FTell(f);
|
||||
m_pCryPak->FSeek(f, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::SafeRead(FILE *f, void *buffer, int count)
|
||||
{
|
||||
(m_pCryPak->FRead(buffer, 1, count, f) != (unsigned)count);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
int CXFile::LoadInMemory(const char *filename, void **bufferptr)
|
||||
{
|
||||
FILE *f = m_pCryPak->FOpen(filename,"rb");
|
||||
if (!f)
|
||||
return (0);
|
||||
int length = CXFile::GetLength(f);
|
||||
void *buffer = new char[length+1];
|
||||
|
||||
SafeRead(f, buffer, length);
|
||||
m_pCryPak->FClose(f);
|
||||
|
||||
char * bbp = (char *)buffer;
|
||||
bbp[length] = 0; //null terminated
|
||||
*bufferptr = buffer;
|
||||
return (length);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CXFile::GetPath(char *path)
|
||||
{
|
||||
char *src = path+strlen(path)-1;
|
||||
while (*src)
|
||||
{
|
||||
if (*src == '\\')
|
||||
{
|
||||
src++;
|
||||
*src = 0; // remove extension
|
||||
return;
|
||||
}
|
||||
src--;
|
||||
}
|
||||
}
|
||||
71
Cry3DEngine/File.h
Normal file
71
Cry3DEngine/File.h
Normal file
@@ -0,0 +1,71 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: file.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: cecahed file access
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PS2
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
#define MAX_PATH_LENGTH 512
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class CXFile
|
||||
{
|
||||
public:
|
||||
|
||||
CXFile(struct ICryPak * pCryPak);
|
||||
~CXFile() { FClose(); }
|
||||
|
||||
int FRead(void *pDest,int nSize,int nNumElems);
|
||||
static void SafeRead(FILE *f, void *buffer, int count);
|
||||
int FSeek(int nOff,int nFrom);
|
||||
int FLoad(const char *filename);
|
||||
void FClose();
|
||||
|
||||
static bool FileExist(const char *filename);
|
||||
static bool IsFileExist(const char *filename);
|
||||
//-1 if file does not exist
|
||||
static int GetLength(const char *filename);
|
||||
static int GetLength(FILE *f);
|
||||
static int LoadInMemory(const char *filename, void **bufferptr);
|
||||
|
||||
// static bool IsOutOfDate(const char *pFileName1,const char *pMasterFile);
|
||||
// static int GetWriteTime(const char *pFileName1);
|
||||
|
||||
//utils
|
||||
static void RemoveExtension (char *path);
|
||||
static void ReplaceExtension(char *path, const char *new_ext);
|
||||
static char *GetExtension (const char *filename);
|
||||
static char *GetString (FILE *fp,const char *key);
|
||||
static void GetPath(char *path);
|
||||
|
||||
//Tim code
|
||||
static void SetLanguage (const char *command=NULL);
|
||||
static char *ConvertFilename(const char *filename);
|
||||
static void SetIPack(ICryPak * pCryPak) { m_pCryPak = pCryPak; }
|
||||
|
||||
private:
|
||||
|
||||
char *m_szFileStart,*m_pCurrPos,*m_pEndOfFile;
|
||||
int m_nFileSize;
|
||||
char m_sLoadedFileName[512];
|
||||
|
||||
static struct ICryPak * m_pCryPak;
|
||||
};
|
||||
|
||||
#endif
|
||||
#else //PS2
|
||||
#include "..\CryCommon\File.h"
|
||||
#endif
|
||||
148
Cry3DEngine/Geom.cpp
Normal file
148
Cry3DEngine/Geom.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: geom.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading geometry from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Geom.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CGeom::CGeom() : CBaseObj()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
m_pVertices =NULL;
|
||||
m_pFaces =NULL;
|
||||
// m_pLinks =NULL;
|
||||
m_pUVs =NULL;
|
||||
m_sPropstr =NULL;
|
||||
// bones =NULL;
|
||||
m_pTexFaces =NULL;
|
||||
// m_pNumLinks =NULL;
|
||||
// links =NULL;
|
||||
m_pVcols =NULL;
|
||||
// BoneNames =NULL;
|
||||
}
|
||||
|
||||
CGeom::~CGeom()
|
||||
{
|
||||
/* if(links)
|
||||
{
|
||||
for(int i=0;i<m_Chunk.nVerts;i++) if(links[i]) free(links[i]);
|
||||
free(links);
|
||||
}*/
|
||||
|
||||
// if(bones) free(bones);
|
||||
if(m_pFaces) free(m_pFaces);
|
||||
if(m_pVertices)free(m_pVertices);
|
||||
if(m_pUVs) free(m_pUVs);
|
||||
if(m_sPropstr) free(m_sPropstr);
|
||||
// if(nLinks) free(nLinks);
|
||||
if(m_pVcols) free(m_pVcols);
|
||||
if(m_pTexFaces)free(m_pTexFaces);
|
||||
}
|
||||
|
||||
bool CGeom::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
if(m_ChunkHeader.ChunkType != ChunkType_Mesh || m_ChunkHeader.ChunkVersion != MESH_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
//read verts
|
||||
m_pVertices=(CryVertex*)malloc(sizeof(CryVertex)*m_Chunk.nVerts);
|
||||
assert(m_pVertices);
|
||||
res=f->FRead(m_pVertices,sizeof(CryVertex),m_Chunk.nVerts);
|
||||
if(res!=m_Chunk.nVerts) return true;
|
||||
|
||||
//read m_pFaces
|
||||
m_pFaces=(CryFace*)malloc(sizeof(CryFace)*m_Chunk.nFaces);
|
||||
assert(m_pFaces);
|
||||
res=f->FRead(m_pFaces,sizeof(CryFace),m_Chunk.nFaces);
|
||||
if(res!=m_Chunk.nFaces) return true;
|
||||
|
||||
//read tverts
|
||||
if(m_Chunk.nTVerts)
|
||||
{
|
||||
m_pUVs=(CryUV*)malloc(sizeof(CryUV)*m_Chunk.nTVerts);
|
||||
assert(m_pUVs);
|
||||
res=f->FRead(m_pUVs,sizeof(CryUV),m_Chunk.nTVerts);
|
||||
if(res!=m_Chunk.nTVerts) return true;
|
||||
|
||||
// flip tex coords (since it was flipped in max?)
|
||||
for(int t=0; t<m_Chunk.nTVerts; t++)
|
||||
m_pUVs[t].v = 1.f-m_pUVs[t].v;
|
||||
|
||||
//read Tfaces
|
||||
//if(m_Chunk.nVerts != m_Chunk.nTVerts)
|
||||
if(m_Chunk.nVerts != 12 || pos != 692)//hack to make old grass objects working
|
||||
{
|
||||
m_pTexFaces=(CryTexFace*)malloc(sizeof(CryTexFace)*m_Chunk.nFaces);
|
||||
assert(m_pTexFaces);
|
||||
|
||||
res=f->FRead(m_pTexFaces,sizeof(CryTexFace),m_Chunk.nFaces);
|
||||
if(res!=m_Chunk.nFaces) return true;
|
||||
}
|
||||
}
|
||||
|
||||
//read Vertex Colors
|
||||
if(m_Chunk.HasVertexCol)
|
||||
{
|
||||
m_pVcols=(CryIRGB *)malloc(m_Chunk.nVerts*sizeof(CryIRGB));
|
||||
assert(m_pVcols);
|
||||
|
||||
int res=f->FRead(m_pVcols, sizeof(CryIRGB), m_Chunk.nVerts);
|
||||
|
||||
/*
|
||||
for (int k=0;k<m_Chunk.nVerts;k++)
|
||||
{
|
||||
m_pVcols[k].r=255;
|
||||
m_pVcols[k].g=0;
|
||||
m_pVcols[k].b=0;
|
||||
} //k
|
||||
*/
|
||||
|
||||
|
||||
if (res!=m_Chunk.nVerts)
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pVcols=0;
|
||||
/*
|
||||
m_pVcols=(CryIRGB *)malloc(m_Chunk.nVerts*sizeof(CryIRGB));
|
||||
assert(m_pVcols);
|
||||
|
||||
for (int k=0;k<m_Chunk.nVerts;k++)
|
||||
{
|
||||
m_pVcols[k].r=255;
|
||||
m_pVcols[k].g=0;
|
||||
m_pVcols[k].b=0;
|
||||
} //k
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
return (false);
|
||||
}
|
||||
51
Cry3DEngine/Geom.h
Normal file
51
Cry3DEngine/Geom.h
Normal file
@@ -0,0 +1,51 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: geom.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_)
|
||||
#define AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "baseobj.h"
|
||||
|
||||
class CGeom : public CBaseObj
|
||||
{
|
||||
public:
|
||||
CryVertex *m_pVertices;
|
||||
CryFace *m_pFaces;
|
||||
CryUV *m_pUVs;
|
||||
CryTexFace *m_pTexFaces;
|
||||
CryIRGB *m_pVcols;
|
||||
// int *m_pNumLinks;
|
||||
// CryLink ** m_pLinks;
|
||||
|
||||
char * m_sPropstr;
|
||||
MESH_CHUNK_DESC m_Chunk;
|
||||
|
||||
CGeom();
|
||||
virtual ~CGeom();
|
||||
|
||||
//from BaseObj
|
||||
bool Load(CXFile *f, int pos);
|
||||
|
||||
MESH_CHUNK_DESC * GetChunk() { return &m_Chunk; }
|
||||
|
||||
//CGeom methods
|
||||
void Deform();
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_GEOM_H__D90B8CB0_DAA4_49C7_8D72_4A73FA38E640__INCLUDED_)
|
||||
49
Cry3DEngine/Helper.cpp
Normal file
49
Cry3DEngine/Helper.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: helper.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading helper from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Helper.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CHelper::CHelper() : CBaseObj()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CHelper::~CHelper()
|
||||
{
|
||||
}
|
||||
|
||||
bool CHelper::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Helper || m_Chunk.chdr.ChunkVersion != HELPER_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
return false;
|
||||
}
|
||||
36
Cry3DEngine/Helper.h
Normal file
36
Cry3DEngine/Helper.h
Normal file
@@ -0,0 +1,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: helper.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_)
|
||||
#define AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class CHelper : public CBaseObj
|
||||
{
|
||||
public:
|
||||
HELPER_CHUNK_DESC m_Chunk;
|
||||
|
||||
CHelper();
|
||||
virtual ~CHelper();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_HELPER_H__3A967DC3_988F_4A67_BC33_AC26573B86FA__INCLUDED_)
|
||||
157
Cry3DEngine/IndoorShadowVolumes.h
Normal file
157
Cry3DEngine/IndoorShadowVolumes.h
Normal file
@@ -0,0 +1,157 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Indoor Engine DLL source code
|
||||
//
|
||||
// File: IndoorShadowVolumes.h
|
||||
//
|
||||
// History:
|
||||
// -August 28,2001:Created by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INDOORSHADOWVOLUMES_H
|
||||
#define INDOORSHADOWVOLUMES_H
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#define FLAG_SKIP_SHADOWVOLUME 1
|
||||
|
||||
//forward declarations
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#include "IndoorVolumes.h"
|
||||
#include "I3DEngine.h" // USE_SHADOW_VERSION
|
||||
|
||||
class CDLight;
|
||||
class CRETriMeshShadow;
|
||||
class IStencilShadowConnectivity;
|
||||
|
||||
//an entire shadow volume object containing many edges and faces
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class CShadowVolObject : public CVolume
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor
|
||||
CShadowVolObject()
|
||||
{
|
||||
// m_pFaceList=NULL;
|
||||
m_pReMeshShadow=NULL;
|
||||
m_pSystemVertexBuffer=NULL;
|
||||
m_pEdgeConnectivity=0;
|
||||
m_nNumVertices=0;
|
||||
// m_nNumFaces=0;
|
||||
};
|
||||
|
||||
//! destructor
|
||||
~CShadowVolObject();
|
||||
|
||||
//!
|
||||
bool CheckInside(const Vec3d &pos,bool bWorldSpace=true)
|
||||
{
|
||||
//temporary return false...will be a cool AI game play feature to know
|
||||
//if we are in shadows
|
||||
return (false);
|
||||
}
|
||||
|
||||
//! precalculate the connectivity infos to build the object silouhette
|
||||
bool CreateConnectivityInfo( void );
|
||||
|
||||
//! create/update a vertex buffer containing the shadow volume (for static lights)
|
||||
void RebuildShadowVolumeBuffer( const CDLight &lSource, float fExtent );
|
||||
|
||||
Vec3d * GetSysVertBufer() { return m_pSystemVertexBuffer; }
|
||||
|
||||
int GetNumVertices() { return(m_nNumVertices); }
|
||||
// int GetNumFaces() { return(m_nNumFaces); }
|
||||
|
||||
// Shader RenderElements for stencil
|
||||
CRETriMeshShadow * m_pReMeshShadow; //!<
|
||||
|
||||
void CheckUnload();
|
||||
|
||||
IStencilShadowConnectivity * & GetEdgeConnectivity() { return m_pEdgeConnectivity; }
|
||||
|
||||
protected:
|
||||
|
||||
//! free the shadow volume buffers
|
||||
void FreeVertexBuffers();
|
||||
|
||||
//list of faces from source objects, its always shared from the stat obj
|
||||
// int m_nNumFaces; //!<
|
||||
// CObjFace * m_pFaceList; //!< pointer to MeshIdx faces [0..m_nNumFaces-1]
|
||||
|
||||
//list of edges...can be shared from another shadow vol object
|
||||
IStencilShadowConnectivity * m_pEdgeConnectivity; //!< stored edge connectivity for fast shadow edge extraction, could be 0, call ->Release() to free it
|
||||
|
||||
TFixedArray<unsigned short> m_arrIndices; //!<
|
||||
unsigned m_nNumVertices; //!< number of vertices in SystemBuffer
|
||||
|
||||
//!
|
||||
//! /param nNumIndices
|
||||
//! /param nNumVertices
|
||||
void PrepareShadowVolumeVertexBuffer( unsigned nNumIndices, unsigned nNumVertices );
|
||||
|
||||
//shadow volume renderer vertex buffer
|
||||
Vec3d * m_pSystemVertexBuffer;
|
||||
};
|
||||
|
||||
struct ItShadowVolume;
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
struct tShadowVolume : public ItShadowVolume
|
||||
{
|
||||
tShadowVolume()
|
||||
{
|
||||
pSvObj=NULL;
|
||||
}
|
||||
|
||||
CShadowVolObject *GetShadowVolume()
|
||||
{
|
||||
return (pSvObj);
|
||||
}
|
||||
|
||||
void SetShadowVolume(CShadowVolObject *pParmSvObj)
|
||||
{
|
||||
pSvObj=pParmSvObj;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
if (pSvObj)
|
||||
{
|
||||
delete pSvObj;
|
||||
pSvObj=NULL;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
//! get/set position
|
||||
Vec3d GetPos()
|
||||
{
|
||||
return (pSvObj->GetPos());
|
||||
}
|
||||
|
||||
void SetPos(const Vec3d &vPos)
|
||||
{
|
||||
pSvObj->SetPos(vPos);
|
||||
}
|
||||
|
||||
//! recalculate the object's silouhette, mostly for dynamic lights
|
||||
//! the light should always be in object space
|
||||
void RebuildShadowVolumeBuffer( const CDLight &lSource, float fExtent )
|
||||
{
|
||||
pSvObj->RebuildShadowVolumeBuffer(lSource, fExtent);
|
||||
}
|
||||
|
||||
Vec3d * GetSysVertBufer() { return pSvObj->GetSysVertBufer(); }
|
||||
|
||||
void CheckUnload() { pSvObj->CheckUnload(); }
|
||||
|
||||
CShadowVolObject *pSvObj;
|
||||
};
|
||||
|
||||
#endif
|
||||
151
Cry3DEngine/IndoorVolumes.h
Normal file
151
Cry3DEngine/IndoorVolumes.h
Normal file
@@ -0,0 +1,151 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek CryENGINE source code
|
||||
//
|
||||
// File: IndoorVolumes.h
|
||||
//
|
||||
// History:
|
||||
// -August 28,2001:Created by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INDOORVOLUMES_H
|
||||
#define INDOORVOLUMES_H
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#define FLAG_VOLUME_AREA 1
|
||||
#define FLAG_VOLUME_PORTAL 2
|
||||
#define FLAG_VOLUME_HULL 4
|
||||
#define FLAG_VOLUME_FOG 8
|
||||
#define FLAG_VOLUME_OBJECT 16
|
||||
#define FLAG_VOLUME_DRAWN 32
|
||||
#define FLAG_VOLUME_RECURSED 64
|
||||
#define FLAG_GEOMETRY_SHARED 128
|
||||
#define FLAG_OBJECT_VISIBLE_BY_PORTALS 256
|
||||
#define FLAG_OBJECT_PRX 512 //this object is affected by per-pixel lighting by other lights
|
||||
#define FLAG_OBJECT_PORTAL_ENTITY 1024
|
||||
#define FLAG_OBJECT_DOUBLE_PORTAL 2048
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//#define FLAG2_DRAWN (1L<<17)
|
||||
|
||||
|
||||
// this holds datas for volumes and areas
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef struct s_Container
|
||||
{
|
||||
s_Container()
|
||||
{
|
||||
pObj=NULL;
|
||||
pEnt=NULL;
|
||||
pSV=NULL;
|
||||
}
|
||||
|
||||
IStatObj *pObj;
|
||||
IPhysicalEntity *pEnt;
|
||||
class CShadowVolObject *pSV;
|
||||
}tContainer;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
typedef std::vector<tContainer> ContainerList;
|
||||
typedef std::vector<tContainer>::iterator ContainerListIt;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
typedef std::vector<IStatObj*> istatobjlist;
|
||||
typedef std::vector<IStatObj*>::iterator istatobjit;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
typedef std::vector<IPhysicalEntity*> iphysobjlist;
|
||||
typedef std::vector<IPhysicalEntity*>::iterator iphysobjit;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class CVolume : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
//constructors/destructors
|
||||
//this constructor is only for building
|
||||
CVolume()
|
||||
{
|
||||
m_dwFlags=0;
|
||||
m_nObjCount=0;
|
||||
m_vOrigin(0,0,0);
|
||||
m_vMins=SetMaxBB();
|
||||
m_vMaxs=SetMinBB();
|
||||
}
|
||||
/*
|
||||
CVolume()
|
||||
{
|
||||
m_dwFlags=0;
|
||||
m_nObjCount=0;
|
||||
m_vOrigin(0,0,0);
|
||||
m_vMins=SetMaxBB();
|
||||
m_vMaxs=SetMinBB();
|
||||
};
|
||||
*/
|
||||
virtual ~CVolume();
|
||||
|
||||
int GetFlags() { return(m_dwFlags); }
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//check if a point is inside the volume
|
||||
virtual bool CheckInside(const Vec3d &pos,bool bWorldSpace) { return(false); }
|
||||
|
||||
void RemoveGeometry(IStatObj *pSource,ContainerListIt i);
|
||||
|
||||
//void SetGeometry(IStatObj *pSource);
|
||||
//void AddGeometry(IStatObj *pSource,IPhysicalEntity *pEnt=NULL);
|
||||
void AddGeometry(tContainer tCont);
|
||||
|
||||
Vec3d GetBBoxMin(bool bWorldSpace=false)
|
||||
{
|
||||
if (bWorldSpace)
|
||||
{
|
||||
Vec3d vWorldPos=m_vOrigin+m_vMins;
|
||||
return(vWorldPos);
|
||||
}
|
||||
|
||||
return(m_vMins);
|
||||
}
|
||||
|
||||
Vec3d GetBBoxMax(bool bWorldSpace=false)
|
||||
{
|
||||
if (bWorldSpace)
|
||||
{
|
||||
Vec3d vWorldPos=m_vOrigin+m_vMaxs;
|
||||
return(vWorldPos);
|
||||
}
|
||||
return(m_vMaxs);
|
||||
}
|
||||
|
||||
//set new volume's position
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void SetPos(const Vec3d &vPos);
|
||||
Vec3d GetPos() { return (m_vOrigin); }
|
||||
|
||||
//bounding box
|
||||
Vec3d m_vMins;
|
||||
Vec3d m_vMaxs;
|
||||
|
||||
//volume flags
|
||||
int m_dwFlags;
|
||||
|
||||
//! the source geometry
|
||||
//IStatObj *m_pSource;
|
||||
int m_nObjCount;
|
||||
|
||||
ContainerList m_lstObjects;
|
||||
//istatobjlist m_lstStatObjs;
|
||||
//iphysobjlist m_lstPhysObjs;
|
||||
|
||||
protected:
|
||||
|
||||
//! volume origin
|
||||
Vec3d m_vOrigin;
|
||||
//Vec3d m_vWorldPos;
|
||||
};
|
||||
|
||||
#endif
|
||||
1066
Cry3DEngine/LMSerializationManager2.cpp
Normal file
1066
Cry3DEngine/LMSerializationManager2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
222
Cry3DEngine/LMSerializationManager2.h
Normal file
222
Cry3DEngine/LMSerializationManager2.h
Normal file
@@ -0,0 +1,222 @@
|
||||
#ifndef __LM_SERIALIZATION_MANAGER_2_H__
|
||||
#define __LM_SERIALIZATION_MANAGER_2_H__
|
||||
|
||||
#include <ILMSerializationManager.h>
|
||||
#include "LMCompStructures.h"
|
||||
#include "I3DEngine.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
class CTempFile
|
||||
{
|
||||
public:
|
||||
CTempFile(unsigned nReserve = 0)
|
||||
{
|
||||
m_arrData.reserve (nReserve);
|
||||
}
|
||||
|
||||
void WriteData (const void* pData, unsigned nSize)
|
||||
{
|
||||
if (nSize)
|
||||
{
|
||||
unsigned nOffset = m_arrData.size();
|
||||
m_arrData.resize(nOffset + nSize);
|
||||
memcpy (&m_arrData[nOffset], pData, nSize);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Write (const T& t)
|
||||
{
|
||||
WriteData (&t, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Write (const T* pT, unsigned numElements)
|
||||
{
|
||||
WriteData (pT, numElements*sizeof(T));
|
||||
}
|
||||
|
||||
unsigned GetSize() const {return m_arrData.size();}
|
||||
void SetSize (unsigned n){m_arrData.resize (n);}
|
||||
char* GetData() {return &m_arrData[0];}
|
||||
|
||||
void Clear() {m_arrData.clear();}
|
||||
void Reserve (unsigned n) {m_arrData.reserve (n);}
|
||||
void Init (unsigned nSize)
|
||||
{
|
||||
m_arrData.clear();
|
||||
m_arrData.resize (nSize);
|
||||
}
|
||||
protected:
|
||||
std::vector<char> m_arrData;
|
||||
};
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
class CLMSerializationManager2 : public Cry3DEngineBase, public ILMSerializationManager
|
||||
{
|
||||
public:
|
||||
|
||||
CLMSerializationManager2( );
|
||||
virtual ~CLMSerializationManager2();
|
||||
|
||||
// interface ILMSerializationManager ------------------------------------
|
||||
|
||||
virtual void Release() { delete this; };
|
||||
virtual bool ApplyLightmapfile( const char *pszFileName, std::vector<IEntityRender *>& vIGLMs );
|
||||
virtual bool Load(const char *pszFileName, const bool cbLoadTextures = true);
|
||||
virtual unsigned int Save(const char *pszFileName, LMGenParam rParam, const bool cbAppend = false);
|
||||
virtual void AddRawLMData(
|
||||
const DWORD indwWidth, const DWORD indwHeight, const std::vector<int>& _cGLM_IDs_UsingPatch,
|
||||
BYTE *_pColorLerp4, BYTE *_pHDRColorLerp4, BYTE *_pDomDirection3, BYTE *_pOccl2 = 0);
|
||||
virtual void AddTexCoordData(const std::vector<TexCoord2Comp>& vTexCoords, int iGLM_ID_UsingTexCoord, const DWORD indwHashValue, const std::vector<std::pair<EntityId, EntityId> >& rOcclIDs);
|
||||
virtual DWORD GetHashValue(const int iniGLM_ID_UsingTexCoord) const;
|
||||
virtual bool ExportDLights(const char *pszFileName, const CDLight **ppLights, UINT iNumLights, bool bNewZip = true) const;
|
||||
virtual bool LoadDLights(const char *pszFileName, CDLight **&ppLightsOut, UINT &iNumLightsOut) const;
|
||||
RenderLMData * CreateLightmap(const string& strDirPath, int nItem,UINT iWidth, UINT iHeight, const bool cbLoadHDRMaps, const bool cbLoadOcclMaps = false);
|
||||
|
||||
//! Create a dot3 lightmap ColorLerp / DomDirection tetxure pair
|
||||
virtual RenderLMData * CreateLightmap(const char *pszFileName, int nItem, UINT iWidth, UINT iHeight, BYTE *pColorLerp4, BYTE *pHDRColorLerp4, BYTE *pDomDirection3, BYTE *pOccl2 = 0);
|
||||
// ----------------------------------------------
|
||||
|
||||
protected:
|
||||
struct FileHeader
|
||||
{
|
||||
enum {MAGIC_NUMBER = 0x8F23123E};
|
||||
enum {VERSION = 3};
|
||||
FileHeader() { iMagicNumber = MAGIC_NUMBER;iVersion = VERSION; };
|
||||
|
||||
UINT iMagicNumber;
|
||||
UINT iVersion;
|
||||
UINT iNumLM_Pairs;
|
||||
UINT iNumTexCoordSets;
|
||||
|
||||
UINT reserved[4];
|
||||
};
|
||||
|
||||
struct LMHeader
|
||||
{
|
||||
// the dimensions of LM
|
||||
UINT iWidth;
|
||||
UINT iHeight;
|
||||
// number of GLMs using this LM
|
||||
UINT numGLMs;
|
||||
};
|
||||
|
||||
struct UVSetHeader
|
||||
{
|
||||
UINT nIdGLM;
|
||||
UINT nHashGLM;
|
||||
UINT numUVs;
|
||||
UVSetHeader() : nIdGLM(0), nHashGLM(0), numUVs(0){}
|
||||
};
|
||||
|
||||
//new version available from ver 3 on
|
||||
struct UVSetHeader3 : UVSetHeader
|
||||
{
|
||||
EntityId OcclIds[4*2]; //new: the occlusion map colour channel light id's, this corresponds to the std::pair<EntityId, EntityId>
|
||||
unsigned char ucOcclCount/*1..4*/;
|
||||
UVSetHeader3():ucOcclCount(0)
|
||||
{
|
||||
UVSetHeader::UVSetHeader();
|
||||
OcclIds[0] = OcclIds[1] = OcclIds[2] = OcclIds[3] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct RawLMData
|
||||
{
|
||||
//! /param _pColorLerp4 if !=0 this memory is copied
|
||||
//! /param _pDomDirection3 if !=0 this memory is copied
|
||||
RawLMData(const DWORD indwWidth, const DWORD indwHeight, const std::vector<int>& _vGLM_IDs_UsingPatch )
|
||||
{
|
||||
vGLM_IDs_UsingPatch = _vGLM_IDs_UsingPatch;
|
||||
m_dwWidth=indwWidth;
|
||||
m_dwHeight=indwHeight;
|
||||
m_bUseOcclMaps = false;
|
||||
};
|
||||
|
||||
enum BitmapEnum
|
||||
{
|
||||
TEX_COLOR,
|
||||
TEX_DOMDIR,
|
||||
TEX_OCCL,
|
||||
TEX_HDR
|
||||
};
|
||||
|
||||
// initializes from raw bitmaps
|
||||
void initFromBMP (BitmapEnum t, const void* pSource);
|
||||
|
||||
// initializes from files
|
||||
bool initFromDDS (BitmapEnum t, ICryPak* pPak, const string& szFileName);
|
||||
|
||||
std::vector<int> vGLM_IDs_UsingPatch; //!< vector of object ids that use this lightmap
|
||||
|
||||
// the color DDS, as is in the file
|
||||
CTempFile m_ColorLerp4;
|
||||
// the color DDS, as is in the file
|
||||
CTempFile m_HDRColorLerp4;
|
||||
// the dominant direction DDS, as is in the file
|
||||
CTempFile m_DomDirection3;
|
||||
// the occlusion map DDS, as is in the file
|
||||
CTempFile m_Occl2;
|
||||
|
||||
DWORD m_dwWidth; //!<
|
||||
DWORD m_dwHeight; //!<
|
||||
bool m_bUseOcclMaps;
|
||||
bool m_bUseHDRMaps;
|
||||
|
||||
private:
|
||||
|
||||
//! copy constructor (forbidden)
|
||||
RawLMData( const RawLMData &a ) {}
|
||||
|
||||
//! assignment operator (forbidden)
|
||||
RawLMData &operator=( const RawLMData &a ) { return(*this); }
|
||||
};
|
||||
|
||||
struct RawTexCoordData
|
||||
{
|
||||
//! default constructor (needed for std::map)
|
||||
RawTexCoordData() {}
|
||||
|
||||
RawTexCoordData( const std::vector<TexCoord2Comp>& _vTexCoords, const DWORD indwHashValue, const std::vector<std::pair<EntityId, EntityId> >& rOcclIDs )
|
||||
{
|
||||
vTexCoords = _vTexCoords;
|
||||
m_dwHashValue=indwHashValue;
|
||||
vOcclIDs = rOcclIDs;
|
||||
};
|
||||
|
||||
RawTexCoordData( const std::vector<TexCoord2Comp>& _vTexCoords, const DWORD indwHashValue )
|
||||
{
|
||||
vTexCoords = _vTexCoords;
|
||||
m_dwHashValue=indwHashValue;
|
||||
vOcclIDs.clear();
|
||||
};
|
||||
|
||||
std::vector<TexCoord2Comp> vTexCoords; //!<
|
||||
DWORD m_dwHashValue; //!< to detect changes in the lighting (for incremental recompile)
|
||||
std::vector<std::pair<EntityId, EntityId> > vOcclIDs; //!< occlusion indices corresponding to the 0..4 colour channels
|
||||
};
|
||||
|
||||
std::vector<RawLMData *> m_vLightPatches; //!< class is responsible for deleteing this
|
||||
std::map<int,RawTexCoordData> m_vTexCoords; //!<
|
||||
|
||||
// \param inpIGLMs pointer to the objects we want to assign the data(instance is not touched), 0 if we want to load it to the instance
|
||||
bool _Load( const char *pszFileName, std::vector<IEntityRender *> *inpIGLMs, const bool cbLoadTextures = true);
|
||||
|
||||
void WriteString(const char *pszStr, CTempFile& f) const
|
||||
{
|
||||
UINT iStrLen = (UINT) strlen(pszStr);
|
||||
f.Write (iStrLen);
|
||||
f.WriteData(pszStr, iStrLen);
|
||||
};
|
||||
};
|
||||
#endif // __LM_SERIALIZATION_MANAGER_H__
|
||||
49
Cry3DEngine/Light.cpp
Normal file
49
Cry3DEngine/Light.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: light.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading light source from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Light.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CLight::CLight()
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CLight::~CLight()
|
||||
{
|
||||
}
|
||||
|
||||
bool CLight::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Light || m_Chunk.chdr.ChunkVersion != LIGHT_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
|
||||
return false;
|
||||
}
|
||||
36
Cry3DEngine/Light.h
Normal file
36
Cry3DEngine/Light.h
Normal file
@@ -0,0 +1,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: light.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_)
|
||||
#define AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class CLight : public CBaseObj
|
||||
{
|
||||
public:
|
||||
LIGHT_CHUNK_DESC m_Chunk;
|
||||
|
||||
CLight();
|
||||
virtual ~CLight();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_LIGHT_H__ACF97045_6471_4C13_BC9F_F26C16A0590E__INCLUDED_)
|
||||
11
Cry3DEngine/LightLoad.cpp
Normal file
11
Cry3DEngine/LightLoad.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
|
||||
#include "lightman.h"
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159f
|
||||
#endif
|
||||
328
Cry3DEngine/LightMan.cpp
Normal file
328
Cry3DEngine/LightMan.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
// New version of light sources management - not used yet
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
|
||||
#include "lightman.h"
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159f
|
||||
#endif
|
||||
|
||||
CLightManager::CLightManager()
|
||||
{
|
||||
m_arrLights = new std::map<int, LightsSet*>;
|
||||
}
|
||||
|
||||
CLightManager::~CLightManager()
|
||||
{
|
||||
for (LightsMap::iterator it = m_arrLights->begin(); it != m_arrLights->end(); ++it)
|
||||
{ // free lights lists
|
||||
LightsSet * pCellLights = (*it).second;
|
||||
delete pCellLights;
|
||||
}
|
||||
|
||||
m_arrLights->clear();
|
||||
delete m_arrLights;
|
||||
}
|
||||
|
||||
void CLightManager::GetLightBounds(CDLight * pLight, int &min_x, int &min_y, int &max_x, int &max_y)
|
||||
{
|
||||
// find lights 2d bounds
|
||||
Vec3d vRadius(pLight->m_fRadius,pLight->m_fRadius,pLight->m_fRadius);
|
||||
Vec3d vBoxMin = pLight->m_Origin - vRadius;
|
||||
Vec3d vBoxMax = pLight->m_Origin + vRadius;
|
||||
|
||||
// get 2d bounds in sectors array
|
||||
min_x = (int)(((vBoxMin.x - 1.f)/LIGHT_GRID_SIZE));
|
||||
min_y = (int)(((vBoxMin.y - 1.f)/LIGHT_GRID_SIZE));
|
||||
max_x = (int)(((vBoxMax.x + 1.f)/LIGHT_GRID_SIZE));
|
||||
max_y = (int)(((vBoxMax.y + 1.f)/LIGHT_GRID_SIZE));
|
||||
|
||||
int nTableSize = CTerrain::GetTerrainSize()/LIGHT_GRID_SIZE;
|
||||
|
||||
if( min_x<0 ) min_x = 0; else if( min_x>=nTableSize ) min_x = nTableSize-1;
|
||||
if( min_y<0 ) min_y = 0; else if( min_y>=nTableSize ) min_y = nTableSize-1;
|
||||
if( max_x<0 ) max_x = 0; else if( max_x>=nTableSize ) max_x = nTableSize-1;
|
||||
if( max_y<0 ) max_y = 0; else if( max_y>=nTableSize ) max_y = nTableSize-1;
|
||||
}
|
||||
|
||||
void CLightManager::AddLight(CDLight * pLight)
|
||||
{
|
||||
int min_x, min_y, max_x, max_y;
|
||||
GetLightBounds(pLight, min_x, min_y, max_x, max_y);
|
||||
|
||||
int nTableSize = CTerrain::GetTerrainSize()/LIGHT_GRID_SIZE;
|
||||
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// find cell from position
|
||||
int nXY = x+y*nTableSize;
|
||||
LightsMap::iterator itTable = m_arrLights->find(nXY);
|
||||
LightsSet * pLightsSet = 0;
|
||||
if(itTable!=m_arrLights->end())
|
||||
pLightsSet = (*itTable).second;
|
||||
else
|
||||
{ // allocate new set if needed
|
||||
pLightsSet = new LightsSet;
|
||||
m_arrLights->insert(LightsMap::value_type(nXY,pLightsSet));
|
||||
}
|
||||
|
||||
// add light if not found
|
||||
LightsSet::iterator itLightsSet = pLightsSet->find(pLight);
|
||||
if(itLightsSet==pLightsSet->end())
|
||||
pLightsSet->insert(pLight);
|
||||
}
|
||||
}
|
||||
|
||||
void CLightManager::DeleteLight(CDLight*pLight)
|
||||
{
|
||||
int min_x, min_y, max_x, max_y;
|
||||
GetLightBounds(pLight, min_x, min_y, max_x, max_y);
|
||||
|
||||
int nTableSize = CTerrain::GetTerrainSize()/LIGHT_GRID_SIZE;
|
||||
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// find cell from position
|
||||
int nXY = x+y*nTableSize;
|
||||
LightsMap::iterator itTable = m_arrLights->find(nXY);
|
||||
LightsSet * pLightsSet = 0;
|
||||
if(itTable!=m_arrLights->end())
|
||||
{
|
||||
pLightsSet = (*itTable).second;
|
||||
|
||||
// delete light if found
|
||||
LightsSet::iterator itLightsSet = pLightsSet->find(pLight);
|
||||
if(itLightsSet!=pLightsSet->end())
|
||||
{
|
||||
pLightsSet->erase(itLightsSet);
|
||||
if(pLightsSet->empty())
|
||||
{
|
||||
delete pLightsSet;
|
||||
m_arrLights->erase(itTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLightManager::GetLightsAffectingBBox(const Vec3d & vBoxMin, const Vec3d & vBoxMax, LightsSet * pOutputList)
|
||||
{
|
||||
pOutputList->clear();
|
||||
|
||||
// get 2d bounds in sectors array
|
||||
int min_x = (int)(((vBoxMin.x - 1.f)/LIGHT_GRID_SIZE));
|
||||
int min_y = (int)(((vBoxMin.y - 1.f)/LIGHT_GRID_SIZE));
|
||||
int max_x = (int)(((vBoxMax.x + 1.f)/LIGHT_GRID_SIZE));
|
||||
int max_y = (int)(((vBoxMax.y + 1.f)/LIGHT_GRID_SIZE));
|
||||
|
||||
int nTableSize = CTerrain::GetTerrainSize()/LIGHT_GRID_SIZE;
|
||||
|
||||
if( min_x<0 ) min_x = 0; else if( min_x>=nTableSize ) min_x = nTableSize-1;
|
||||
if( min_y<0 ) min_y = 0; else if( min_y>=nTableSize ) min_y = nTableSize-1;
|
||||
if( max_x<0 ) max_x = 0; else if( max_x>=nTableSize ) max_x = nTableSize-1;
|
||||
if( max_y<0 ) max_y = 0; else if( max_y>=nTableSize ) max_y = nTableSize-1;
|
||||
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
// find cell from position
|
||||
int nXY = x+y*nTableSize;
|
||||
LightsMap::iterator itTable = m_arrLights->find(nXY);
|
||||
LightsSet * pLightsSet = 0;
|
||||
if(itTable!=m_arrLights->end())
|
||||
{
|
||||
pLightsSet = (*itTable).second;
|
||||
|
||||
// add lights into output list if found
|
||||
for (LightsSet::iterator it = pLightsSet->begin(); it != pLightsSet->end(); ++it)
|
||||
{
|
||||
if(pOutputList->find(*it) == pOutputList->end())
|
||||
pOutputList->insert(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern int __cdecl C3DEngine__Cmp_LightAmount(const void* v1, const void* v2);
|
||||
|
||||
int CLightManager::MakeLMaskFromPositionAndActivateLights( const Vec3d vObjPos, const float fObjRadius,
|
||||
IEntityRender * pEntityRender, int nMaxLightBitsNum, CDLight ** pSelectedLights, int nMaxSelectedLights)
|
||||
{
|
||||
Vec3d vBoxMin, vBoxMax;
|
||||
pEntityRender->GetRenderBBox(vBoxMin, vBoxMax);
|
||||
GetLightsAffectingBBox(vBoxMin, vBoxMax, &m_setTmpDL_MMFP);
|
||||
|
||||
// make list of really affecting light sources
|
||||
m_lstTmpDLA_MMFP.Clear();
|
||||
for(LightsSet::iterator itLightsSet = m_setTmpDL_MMFP.begin(); itLightsSet != m_setTmpDL_MMFP.end(); ++itLightsSet)
|
||||
{
|
||||
CDLight * pDLight = (*itLightsSet);
|
||||
if(!pDLight || pDLight->m_fRadius < 0.5f || pDLight->m_Flags & DLF_FAKE)
|
||||
continue;
|
||||
|
||||
if (pDLight->m_pShader!=0 && (pDLight->m_pShader->GetLFlags() & LMF_DISABLE))
|
||||
continue; // fake
|
||||
|
||||
if(pEntityRender && pDLight->m_Flags & DLF_LM && pEntityRender->GetRndFlags() & ERF_USELIGHTMAPS && pEntityRender->HasLightmap(0))
|
||||
{ // in case of lightmaps
|
||||
if(pDLight->m_SpecColor == Col_Black)
|
||||
continue; // ignore specular only lights if specular disabled
|
||||
|
||||
if(pDLight->m_Flags & DLF_PROJECT)
|
||||
continue; // ignore specular only lights if projector since specular projectors not supported
|
||||
}
|
||||
|
||||
if(pDLight->m_Flags & DLF_PROJECT && pEntityRender)
|
||||
{ // check projector frustum
|
||||
// use pDLight->m_TextureMatrix to construct Plane
|
||||
/*GetRenderer()->Draw3dBBox(pDLight->m_Origin, pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtX(), DPRIM_LINE);
|
||||
GetRenderer()->DrawLabel(pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtX(),1,"x");
|
||||
GetRenderer()->Draw3dBBox(pDLight->m_Origin, pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtY(), DPRIM_LINE);
|
||||
GetRenderer()->DrawLabel(pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtY(),1,"y");
|
||||
GetRenderer()->Draw3dBBox(pDLight->m_Origin, pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtZ(), DPRIM_LINE);
|
||||
GetRenderer()->DrawLabel(pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtZ(),1,"z");*/
|
||||
|
||||
if(GetCVars()->e_projector_exact_test)
|
||||
{ // test
|
||||
CCamera cam; // construct light camera
|
||||
cam.SetPos(pDLight->m_Origin);
|
||||
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, pDLight->m_fRadius, 1.0f, 0.1f);
|
||||
cam.Update();
|
||||
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pEntityRender->GetRenderBBox(vBoxMin,vBoxMax);
|
||||
if (!cam.IsAABBVisibleFast(AABB(vBoxMin,vBoxMax)))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Plane p;
|
||||
p.CalcPlane( pDLight->m_Origin, pDLight->m_Origin+pDLight->m_TextureMatrix.GetOrtY(), pDLight->m_Origin-pDLight->m_TextureMatrix.GetOrtZ() );
|
||||
if( p.DistFromPlane(vObjPos) + fObjRadius < 0 )
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// find amount of light
|
||||
float fDist = GetDistance(pDLight->m_Origin,vObjPos);
|
||||
float fLightAmount = 1.f - (fDist-fObjRadius) / (pDLight->m_fRadius);
|
||||
fLightAmount *=
|
||||
(pDLight->m_Color.r+pDLight->m_Color.g+pDLight->m_Color.b)*0.333f +
|
||||
(pDLight->m_SpecColor.r+pDLight->m_SpecColor.g+pDLight->m_SpecColor.b)*0.333f;
|
||||
|
||||
if(fLightAmount>0.05f)
|
||||
{
|
||||
// if entity is inside some area - allow lightsources only from this area
|
||||
if(pEntityRender)
|
||||
if((pDLight->m_Flags & DLF_THIS_AREA_ONLY) /*|| (pDLight->m_Flags & DLF_SUN)*/)
|
||||
{
|
||||
if(pEntityRender->GetEntityVisArea() && pDLight->m_pOwner!=(IEntityRender*)-1)
|
||||
{
|
||||
if( pDLight->m_pOwner && pDLight->m_pOwner->GetEntityRS() && pDLight->m_pOwner->m_pVisArea)
|
||||
{
|
||||
CVisArea * pLightArea = pDLight->m_pOwner->m_pVisArea;
|
||||
if(pEntityRender->GetEntityVisArea() != pLightArea)
|
||||
{ // try also portal volumes
|
||||
bool bNearFound = pEntityRender->m_pVisArea->FindVisArea(pLightArea, 1, true);
|
||||
if(!bNearFound)
|
||||
continue; // areas do not much
|
||||
}
|
||||
}
|
||||
else
|
||||
continue; // outdoor lsource
|
||||
}
|
||||
else // entity is outside
|
||||
if( pDLight->m_pOwner && pDLight->m_pOwner!=(IEntityRender*)-1 && pDLight->m_pOwner->GetEntityVisArea() && pDLight->m_pOwner!=(IEntityRender*)-1)
|
||||
continue; // indoor lsource should not affect outdoor entity
|
||||
}
|
||||
|
||||
DLightAmount la;
|
||||
la.pDLight = pDLight;
|
||||
la.fAmount = fLightAmount;
|
||||
m_lstTmpDLA_MMFP.Add(la);
|
||||
}
|
||||
}
|
||||
|
||||
int nDLightMask = 0;
|
||||
|
||||
if(!m_lstTmpDLA_MMFP.Count())
|
||||
return 0; // no lsources found
|
||||
|
||||
// sort by light amount
|
||||
qsort(&m_lstTmpDLA_MMFP[0], m_lstTmpDLA_MMFP.Count(), sizeof(m_lstTmpDLA_MMFP[0]), C3DEngine__Cmp_LightAmount);
|
||||
|
||||
// limit number of affective light sources
|
||||
for(int n=0; n<nMaxLightBitsNum && n<GetCVars()->e_max_entity_lights && n<m_lstTmpDLA_MMFP.Count(); n++)
|
||||
{
|
||||
LightsSet::iterator itLightsSet = m_setActiveLights.find(m_lstTmpDLA_MMFP[n].pDLight);
|
||||
if(itLightsSet==m_setActiveLights.end())
|
||||
{
|
||||
GetRenderer()->EF_ADDDlight(m_lstTmpDLA_MMFP[n].pDLight);
|
||||
m_setActiveLights.insert(m_lstTmpDLA_MMFP[n].pDLight);
|
||||
}
|
||||
|
||||
const int nId = m_lstTmpDLA_MMFP[n].pDLight->m_Id;
|
||||
|
||||
nDLightMask |= (1<<nId);
|
||||
|
||||
if(pSelectedLights && n<nMaxSelectedLights)
|
||||
pSelectedLights[n] = m_lstTmpDLA_MMFP[n].pDLight;
|
||||
}
|
||||
|
||||
return nDLightMask;
|
||||
}
|
||||
|
||||
void CLightManager::ClearFrameLights()
|
||||
{
|
||||
m_setActiveLights.clear();
|
||||
}
|
||||
|
||||
const Vec3d &CLightEntity::GetPos(bool) const
|
||||
{
|
||||
return m_vPos;//m_pLight->m_Origin;
|
||||
}
|
||||
|
||||
const Vec3d &CLightEntity::GetAngles(int) const
|
||||
{
|
||||
return m_pLight->m_ProjAngles;
|
||||
}
|
||||
|
||||
void CLightEntity::GetRenderBBox(Vec3d &vMin,Vec3d &vMax)
|
||||
{
|
||||
vMin = m_pLight->m_Origin - Vec3d(m_pLight->m_fRadius,m_pLight->m_fRadius,m_pLight->m_fRadius);
|
||||
vMax = m_pLight->m_Origin + Vec3d(m_pLight->m_fRadius,m_pLight->m_fRadius,m_pLight->m_fRadius);
|
||||
}
|
||||
|
||||
float CLightEntity::GetRenderRadius(void) const
|
||||
{
|
||||
return m_pLight->m_fRadius;
|
||||
}
|
||||
|
||||
float CLightEntity::GetMaxViewDist()
|
||||
{
|
||||
return GetRenderRadius()*GetCVars()->e_obj_view_dist_ratio*GetViewDistRatioNormilized();
|
||||
}
|
||||
|
||||
CLightEntity::CLightEntity()
|
||||
{
|
||||
m_pEntityRenderState = Get3DEngine()->MakeEntityRenderState();
|
||||
m_vPos.Set(0,0,0);
|
||||
}
|
||||
|
||||
CLightEntity::~CLightEntity()
|
||||
{
|
||||
Get3DEngine()->FreeEntityRenderState(this);
|
||||
((C3DEngine*)Get3DEngine())->FreeLightSourceComponents(m_pLight);
|
||||
Get3DEngine()->UnRegisterEntity(this);
|
||||
((C3DEngine*)Get3DEngine())->RemoveEntityLightSources(this);
|
||||
delete m_pLight; m_pLight = NULL;
|
||||
}
|
||||
35
Cry3DEngine/LightMan.h
Normal file
35
Cry3DEngine/LightMan.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _LIGHTMAN_H_
|
||||
#define _LIGHTMAN_H_
|
||||
|
||||
#include "Array2d.h"
|
||||
|
||||
#define LIGHT_GRID_SIZE 16
|
||||
|
||||
class CLightManager : public Cry3DEngineBase
|
||||
{
|
||||
typedef std::set<class CDLight*> LightsSet;
|
||||
typedef std::map<int, LightsSet*> LightsMap;
|
||||
|
||||
LightsMap * m_arrLights;
|
||||
|
||||
public:
|
||||
CLightManager();
|
||||
~CLightManager();
|
||||
void AddLight(CDLight*pLight);
|
||||
void DeleteLight(CDLight*pLight);
|
||||
void GetLightBounds(CDLight * pLight, int &min_x, int &min_y, int &max_x, int &max_y);
|
||||
|
||||
void GetLightsAffectingBBox(const Vec3d & vBoxMin, const Vec3d & vBoxMax, LightsSet*pOutputList);
|
||||
int MakeLMaskFromPositionAndActivateLights( const Vec3d vObjPos, const float fObjRadius,
|
||||
IEntityRender * pEntityRender, int nMaxLightBitsNum,
|
||||
CDLight ** pSelectedLights, int nMaxSelectedLights);
|
||||
|
||||
struct DLightAmount{ CDLight * pDLight; float fAmount; };
|
||||
list2<DLightAmount> m_lstTmpDLA_MMFP;
|
||||
LightsSet m_setTmpDL_MMFP;
|
||||
LightsSet m_setActiveLights;
|
||||
|
||||
void ClearFrameLights();
|
||||
};
|
||||
|
||||
#endif // _LIGHTMAN_H_
|
||||
5
Cry3DEngine/MSSCCPRJ.SCC
Normal file
5
Cry3DEngine/MSSCCPRJ.SCC
Normal file
@@ -0,0 +1,5 @@
|
||||
SCC = This is a source code control file
|
||||
|
||||
[Cry3DEngine.vcproj]
|
||||
SCC_Aux_Path = "P4SCC#perforce:1666##marcoc_code##PC018"
|
||||
SCC_Project_Name = Perforce Project
|
||||
535
Cry3DEngine/MatMan.cpp
Normal file
535
Cry3DEngine/MatMan.cpp
Normal file
@@ -0,0 +1,535 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: MatMan.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Material Manager Implementation
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "objman.h"
|
||||
#include "irenderer.h"
|
||||
|
||||
CMatMan::CMatMan( )
|
||||
{
|
||||
}
|
||||
CMatMan::~CMatMan()
|
||||
{
|
||||
int nNotUsed=0, nNotUsedParents=0;
|
||||
|
||||
for (MtlSet::iterator it = m_mtlSet.begin(); it != m_mtlSet.end(); ++it)
|
||||
{
|
||||
IMatInfo *pMtl = *it;
|
||||
SShaderItem Sh = pMtl->GetShaderItem();
|
||||
if(Sh.m_pShader)
|
||||
{
|
||||
Sh.m_pShader->Release();
|
||||
Sh.m_pShader = 0;
|
||||
}
|
||||
if(Sh.m_pShaderResources)
|
||||
{
|
||||
Sh.m_pShaderResources->Release();
|
||||
Sh.m_pShaderResources = 0;
|
||||
}
|
||||
pMtl->SetShaderItem( Sh );
|
||||
|
||||
if(!(pMtl->GetFlags()&MIF_CHILD))
|
||||
if(!(pMtl->GetFlags()&MIF_WASUSED))
|
||||
{
|
||||
GetLog()->Log("Warning: CMatMan::~CMatMan: Material was loaded but never used: %s", pMtl->GetName());
|
||||
nNotUsed += (pMtl->GetSubMtlCount()+1);
|
||||
nNotUsedParents++;
|
||||
}
|
||||
if (pMtl->GetNumRefs() > 1)
|
||||
{
|
||||
//
|
||||
GetLog()->Log("Warning: CMatMan::~CMatMan: Material %s is being referenced", pMtl->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
if(nNotUsed)
|
||||
GetLog()->Log("Warning: CMatMan::~CMatMan: %d(%d) of %d materials was not used in level",
|
||||
nNotUsedParents, nNotUsed, m_mtlSet.size());
|
||||
}
|
||||
|
||||
IMatInfo * CMatMan::CreateMatInfo( const char *sMtlName )
|
||||
{
|
||||
IMatInfo *pMatInfo = new CMatInfo;
|
||||
m_mtlSet.insert( pMatInfo );
|
||||
if (sMtlName)
|
||||
{
|
||||
pMatInfo->SetName( sMtlName );
|
||||
m_mtlNameMap[sMtlName] = pMatInfo;
|
||||
}
|
||||
return pMatInfo;
|
||||
}
|
||||
|
||||
void CMatMan::DeleteMatInfo(IMatInfo * pMatInfo)
|
||||
{
|
||||
// Delete sub materials if present.
|
||||
/* Not needed for now..
|
||||
if (pMatInfo)
|
||||
{
|
||||
CMatInfo *mtl = (CMatInfo*)pMatInfo;
|
||||
if (mtl->pSubMtls)
|
||||
{
|
||||
// Delete all sub materials.
|
||||
for (int i = 0; i < mtl->pSubMtls->size(); i++)
|
||||
{
|
||||
DeleteMatInfo( mtl->pSubMtls[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
assert( pMatInfo );
|
||||
pMatInfo->SetFlags( pMatInfo->GetFlags()|MIF_INVALID );
|
||||
m_mtlNameMap.erase( pMatInfo->GetName() );
|
||||
m_mtlSet.erase( pMatInfo );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatMan::RenameMatInfo( IMatInfo *pMtl,const char *sNewName )
|
||||
{
|
||||
assert( pMtl );
|
||||
m_mtlNameMap.erase( pMtl->GetName() );
|
||||
pMtl->SetName( sNewName );
|
||||
m_mtlNameMap[sNewName] = pMtl;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IMatInfo* CMatMan::FindMatInfo( const char *sMtlName ) const
|
||||
{
|
||||
IMatInfo *pMtl = stl::find_in_map( m_mtlNameMap,sMtlName, (IMatInfo *)NULL );
|
||||
return pMtl;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatMan::LoadMaterialsLibrary( const char *sMtlFile,XmlNodeRef &levelDataRoot )
|
||||
{
|
||||
GetLog()->UpdateLoadingScreen("\003Loading materials ...");
|
||||
|
||||
// load environment settings
|
||||
if (!levelDataRoot)
|
||||
return;
|
||||
|
||||
XmlNodeRef mtlLibs = levelDataRoot->findChild( "MaterialsLibrary" );
|
||||
if (mtlLibs)
|
||||
{
|
||||
// Enmerate material libraries.
|
||||
for (int i = 0; i < mtlLibs->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef mtlLib = mtlLibs->getChild(i);
|
||||
XmlString libraryName = mtlLib->getAttr( "Name" );
|
||||
for (int j =0; j < mtlLib->getChildCount(); j++)
|
||||
{
|
||||
XmlNodeRef mtlNode = mtlLib->getChild(j);
|
||||
LoadMaterial( mtlNode,libraryName.c_str(),0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Loading from external materials.xml file.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
mtlLibs = GetSystem()->LoadXmlFile( sMtlFile );
|
||||
if (mtlLibs)
|
||||
{
|
||||
// Enmerate material libraries.
|
||||
for (int i = 0; i < mtlLibs->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef mtlLib = mtlLibs->getChild(i);
|
||||
if (!mtlLib->isTag("Library"))
|
||||
continue;
|
||||
XmlString libraryName = mtlLib->getAttr( "Name" );
|
||||
for (int j =0; j < mtlLib->getChildCount(); j++)
|
||||
{
|
||||
XmlNodeRef mtlNode = mtlLib->getChild(j);
|
||||
LoadMaterial( mtlNode,libraryName.c_str(),0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Load level data xml.
|
||||
if (pDoc->load(Get3DEngine()->GetFilePath("LevelData.xml")))
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pLibsNode = pDoc->getElementsByTagName("MaterialsLibrary");
|
||||
if (pLibsNode)
|
||||
{
|
||||
pLibsNode->reset();
|
||||
XDOM::IXMLDOMNodePtr pLibNode;
|
||||
while (pLibNode = pLibsNode->nextNode())
|
||||
{
|
||||
// For each library.
|
||||
const char *sLibraryName = "";
|
||||
XDOM::IXMLDOMNodePtr pName = pLibNode->getAttribute("Name");
|
||||
if (pName)
|
||||
sLibraryName = pName->getText();
|
||||
/*
|
||||
// Enumerate library.
|
||||
XDOM::IXMLDOMNodeListPtr pMtlsListNode = pLibNode->getElementsByTagName("Material");
|
||||
XDOM::IXMLDOMNodePtr pMtlNode;
|
||||
pMtlsListNode->reset();
|
||||
while (pMtlNode = pMtlListNode->nextNode())
|
||||
{
|
||||
// For each material.
|
||||
LoadMaterial( pMtlNode,sLibraryName,0 );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
GetLog()->UpdateLoadingScreenPlus("\003 %d mats loaded", m_mtlSet.size());
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int texId;
|
||||
const char *name;
|
||||
} sUsedTextures[] =
|
||||
{
|
||||
{ EFTT_DIFFUSE, "Diffuse" },
|
||||
{ EFTT_GLOSS, "Specular" },
|
||||
{ EFTT_BUMP, "Bumpmap" },
|
||||
{ EFTT_NORMALMAP, "Normalmap" },
|
||||
{ EFTT_CUBEMAP, "Cubemap" },
|
||||
{ EFTT_DETAIL_OVERLAY,"Detail" },
|
||||
{ EFTT_OPACITY, "Opacity" },
|
||||
{ EFTT_DECAL_OVERLAY, "Decal" },
|
||||
{ EFTT_SUBSURFACE, "SubSurface" },
|
||||
};
|
||||
inline CFColor ToCFColor( const Vec3 &col ) { return CFColor(col); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IMatInfo* CMatMan::LoadMaterial( XmlNodeRef node,const char *sLibraryName,IMatInfo* pParent )
|
||||
{
|
||||
XmlString name,mtlName,shaderName,texmap,file;
|
||||
int mtlFlags = 0;
|
||||
unsigned int nShaderGenMask = 0;
|
||||
SInputShaderResources sr;
|
||||
SLightMaterial lm;
|
||||
|
||||
// Make new mat info.
|
||||
mtlName = node->getAttr( "Name" );
|
||||
|
||||
if (pParent)
|
||||
{
|
||||
name = XmlString(pParent->GetName());
|
||||
name += mtlName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Combine library name with item name to form a fully specified material name.
|
||||
name = sLibraryName;
|
||||
name += ".";
|
||||
name += mtlName;
|
||||
}
|
||||
|
||||
IMatInfo* pMtl = CreateMatInfo( name.c_str() );
|
||||
if (pParent)
|
||||
{
|
||||
// Add as sub material if have parent.
|
||||
pParent->AddSubMtl(pMtl);
|
||||
}
|
||||
|
||||
// Loading from Material XML node.
|
||||
shaderName = node->getAttr( "Shader" );
|
||||
if (shaderName.empty())
|
||||
{
|
||||
// Replace empty shader with NoDraw shader.
|
||||
shaderName = "NoDraw";
|
||||
}
|
||||
node->getAttr( "MtlFlags",mtlFlags );
|
||||
node->getAttr( "GenMask",nShaderGenMask );
|
||||
|
||||
// Load lighting data.
|
||||
Vec3 ambient,diffuse,specular,emissive;
|
||||
node->getAttr( "Ambient",ambient );
|
||||
node->getAttr( "Diffuse",diffuse );
|
||||
node->getAttr( "Specular",specular );
|
||||
node->getAttr( "Emissive",emissive );
|
||||
node->getAttr( "Shininess",lm.Front.m_SpecShininess );
|
||||
lm.Front.m_Ambient = ToCFColor(ambient);
|
||||
lm.Front.m_Diffuse = ToCFColor(diffuse);
|
||||
lm.Front.m_Specular = ToCFColor(specular);
|
||||
lm.Front.m_Emission = ToCFColor(emissive);
|
||||
|
||||
node->getAttr( "Opacity",sr.m_Opacity );
|
||||
node->getAttr( "AlphaTest",sr.m_AlphaRef );
|
||||
|
||||
// Load material textures.
|
||||
XmlNodeRef texturesNode = node->findChild( "Textures" );
|
||||
if (texturesNode)
|
||||
{
|
||||
for (int i = 0; i < texturesNode->getChildCount(); i++)
|
||||
{
|
||||
texmap = "";
|
||||
XmlNodeRef texNode = texturesNode->getChild(i);
|
||||
texmap = texNode->getAttr( "Map" );
|
||||
|
||||
int texId = -1;
|
||||
for (int j = 0; j < sizeof(sUsedTextures)/sizeof(sUsedTextures[0]); j++)
|
||||
{
|
||||
if (stricmp(sUsedTextures[j].name,texmap) == 0)
|
||||
{
|
||||
texId = sUsedTextures[j].texId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (texId < 0)
|
||||
continue;
|
||||
|
||||
file = "";
|
||||
file = texNode->getAttr( "File" );
|
||||
|
||||
// Correct texid found.
|
||||
sr.m_Textures[texId].m_Name = file;
|
||||
texNode->getAttr( "Amount",sr.m_Textures[texId].m_Amount );
|
||||
texNode->getAttr( "IsTileU",sr.m_Textures[texId].m_bUTile );
|
||||
texNode->getAttr( "IsTileV",sr.m_Textures[texId].m_bVTile );
|
||||
texNode->getAttr( "TexType",sr.m_Textures[texId].m_TU.m_eTexType );
|
||||
|
||||
XmlNodeRef modNode = texNode->findChild( "TexMod" );
|
||||
if (modNode)
|
||||
{
|
||||
SEfTexModificator &texm = sr.m_Textures[texId].m_TexModificator;
|
||||
|
||||
// Modificators
|
||||
modNode->getAttr( "TileU",texm.m_Tiling[0] );
|
||||
modNode->getAttr( "TileV",texm.m_Tiling[1] );
|
||||
modNode->getAttr( "OffsetU",texm.m_Offs[0] );
|
||||
modNode->getAttr( "OffsetV",texm.m_Offs[1] );
|
||||
modNode->getAttr( "TexType",sr.m_Textures[texId].m_TU.m_eTexType );
|
||||
|
||||
float f;
|
||||
modNode->getAttr( "TexMod_bTexGenProjected",texm.m_bTexGenProjected );
|
||||
modNode->getAttr( "TexMod_UOscillatorType",texm.m_eUMoveType );
|
||||
modNode->getAttr( "TexMod_VOscillatorType",texm.m_eVMoveType );
|
||||
modNode->getAttr( "TexMod_RotateType",texm.m_eRotType );
|
||||
modNode->getAttr( "TexMod_TexGenType",texm.m_eTGType );
|
||||
|
||||
if (modNode->getAttr( "RotateU",f ))
|
||||
texm.m_Rot[0] = Degr2Word(f);
|
||||
if (modNode->getAttr( "RotateV",f ))
|
||||
texm.m_Rot[1] = Degr2Word(f);
|
||||
if (modNode->getAttr( "RotateW",f ))
|
||||
texm.m_Rot[2] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_URotateRate",f ))
|
||||
texm.m_RotOscRate[0] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_VRotateRate",f ))
|
||||
texm.m_RotOscRate[1] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_WRotateRate",f ))
|
||||
texm.m_RotOscRate[2] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_URotatePhase",f ))
|
||||
texm.m_RotOscPhase[0] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_VRotatePhase",f ))
|
||||
texm.m_RotOscPhase[1] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_WRotatePhase",f ))
|
||||
texm.m_RotOscPhase[2] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_URotateAmplitude",f ))
|
||||
texm.m_RotOscAmplitude[0] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_VRotateAmplitude",f ))
|
||||
texm.m_RotOscAmplitude[1] = Degr2Word(f);
|
||||
if (modNode->getAttr( "TexMod_WRotateAmplitude",f ))
|
||||
texm.m_RotOscAmplitude[2] = Degr2Word(f);
|
||||
modNode->getAttr( "TexMod_URotateCenter",texm.m_RotOscCenter[0] );
|
||||
modNode->getAttr( "TexMod_VRotateCenter",texm.m_RotOscCenter[1] );
|
||||
modNode->getAttr( "TexMod_WRotateCenter",texm.m_RotOscCenter[2] );
|
||||
|
||||
modNode->getAttr( "TexMod_UOscillatorRate",texm.m_UOscRate );
|
||||
modNode->getAttr( "TexMod_VOscillatorRate",texm.m_VOscRate );
|
||||
modNode->getAttr( "TexMod_UOscillatorPhase",texm.m_UOscPhase );
|
||||
modNode->getAttr( "TexMod_VOscillatorPhase",texm.m_VOscPhase );
|
||||
modNode->getAttr( "TexMod_UOscillatorAmplitude",texm.m_UOscAmplitude );
|
||||
modNode->getAttr( "TexMod_VOscillatorAmplitude",texm.m_VOscAmplitude );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load sub materials.
|
||||
XmlNodeRef childsNode = node->findChild( "SubMaterials" );
|
||||
if (childsNode)
|
||||
{
|
||||
for (int i = 0; i < childsNode->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef mtlNode = childsNode->getChild(i);
|
||||
LoadMaterial( mtlNode,sLibraryName,pMtl );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Load public parameters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
XmlNodeRef publicsNode = node->findChild( "PublicParams" );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Reload shader item with new resources and shader.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
LoadMaterialShader( pMtl,shaderName.c_str(),mtlFlags,nShaderGenMask,sr,lm,publicsNode );
|
||||
|
||||
static int nTic=0;
|
||||
if((++nTic%10)==0)
|
||||
GetConsole()->TickProgressBar();
|
||||
|
||||
return pMtl;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Material flags from Editor.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum EMtlFlagsFromXml
|
||||
{
|
||||
MF_WIRE = 0x0001,
|
||||
MF_2SIDED = 0x0002,
|
||||
MF_ADDITIVE = 0x0004,
|
||||
MF_ADDITIVE_DECAL = 0x0008,
|
||||
MF_LIGHTING = 0x0010,
|
||||
MF_NOSHADOW = 0x0020,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CMatMan::LoadMaterialShader( IMatInfo *pMtl,const char *sShader,int mtlFlags,unsigned int nShaderGenMask,SInputShaderResources &sr,SLightMaterial &lm,XmlNodeRef &publicsNode )
|
||||
{
|
||||
// Mark material invalid by default.
|
||||
pMtl->SetFlags( pMtl->GetFlags()|MIF_INVALID );
|
||||
|
||||
if (mtlFlags & MF_LIGHTING)
|
||||
sr.m_LMaterial = &lm;
|
||||
else
|
||||
sr.m_LMaterial = 0;
|
||||
|
||||
if (mtlFlags & MF_NOSHADOW)
|
||||
pMtl->SetFlags( pMtl->GetFlags()|MIF_NOCASTSHADOWS );
|
||||
|
||||
sr.m_ResFlags = 0;
|
||||
if (mtlFlags & MF_WIRE)
|
||||
sr.m_ResFlags |= MTLFLAG_WIRE;
|
||||
if (mtlFlags & MF_2SIDED)
|
||||
sr.m_ResFlags |= MTLFLAG_2SIDED;
|
||||
if (mtlFlags & MF_ADDITIVE)
|
||||
sr.m_ResFlags |= MTLFLAG_ADDITIVE;
|
||||
if (mtlFlags & MF_ADDITIVE_DECAL)
|
||||
sr.m_ResFlags |= MTLFLAG_ADDITIVEDECAL;
|
||||
|
||||
/*
|
||||
sr.m_ShaderParams.clear();
|
||||
for (int i = 0; i < m_shaderParams.size(); i++)
|
||||
{
|
||||
sr.m_ShaderParams.push_back( m_shaderParams[i] );
|
||||
}
|
||||
*/
|
||||
IShader *pTemplShader = 0;
|
||||
// If we have public parameters, first load shader and parse public parameters.
|
||||
if (publicsNode)
|
||||
{
|
||||
pTemplShader = GetSystem()->GetIRenderer()->EF_LoadShader( sShader,eSH_Misc,0,nShaderGenMask );
|
||||
TArray<SShaderParam> ¶ms = pTemplShader->GetPublicParams();
|
||||
if (!params.empty())
|
||||
{
|
||||
// Parse public parameters, and assign them to source shader resources.
|
||||
ParsePublicParams( params,publicsNode );
|
||||
sr.m_ShaderParams.Reserve( params.size() );
|
||||
for (unsigned int i = 0; i < params.size(); i++)
|
||||
{
|
||||
sr.m_ShaderParams.push_back(params[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shader container name does not support '.', replace it with different character.
|
||||
char sContainerName[1024];
|
||||
strncpy( sContainerName,pMtl->GetName(),sizeof(sContainerName) );
|
||||
sContainerName[sizeof(sContainerName)-1] = 0;
|
||||
std::replace( sContainerName,sContainerName+strlen(sContainerName),'.','_' );
|
||||
|
||||
|
||||
int nQBM = 0;
|
||||
ICVar * pIVar = GetConsole()->GetCVar("r_Quality_BumpMapping");
|
||||
if(pIVar)
|
||||
nQBM = pIVar->GetIVal();
|
||||
|
||||
if ((GetSystem()->GetIRenderer()->GetFeatures() & RFT_HW_MASK) == RFT_HW_GF2 || nQBM == 0)
|
||||
{
|
||||
SLightMaterial mtl;
|
||||
sr.m_LMaterial = &mtl;
|
||||
}
|
||||
|
||||
SShaderItem shaderItem = GetSystem()->GetIRenderer()->EF_LoadShaderItem( "MaterialContainer",eSH_Misc,true,sShader,0,&sr,nShaderGenMask );
|
||||
if (!shaderItem.m_pShader)
|
||||
{
|
||||
Warning( 0,0,"Failed to load shader %s in Material %s",sShader,sContainerName );
|
||||
return false;
|
||||
}
|
||||
pMtl->SetShaderItem( shaderItem );
|
||||
// If material shader was loaded successfully mark it as valid again.
|
||||
pMtl->SetFlags( pMtl->GetFlags()&(~MIF_INVALID) );
|
||||
|
||||
if (pTemplShader)
|
||||
{
|
||||
// Release templ shader reference.
|
||||
pTemplShader->Release();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CMatMan::ParsePublicParams( TArray<SShaderParam> ¶ms,XmlNodeRef paramsNode )
|
||||
{
|
||||
// Load shader params from xml node.
|
||||
// Initialize shader params if thier number is changed.
|
||||
if (params.empty())
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < params.size(); i++)
|
||||
{
|
||||
SShaderParam *pParam = ¶ms[i];
|
||||
switch (pParam->m_Type)
|
||||
{
|
||||
case eType_BYTE:
|
||||
paramsNode->getAttr( pParam->m_Name,pParam->m_Value.m_Byte );
|
||||
break;
|
||||
case eType_SHORT:
|
||||
paramsNode->getAttr( pParam->m_Name,pParam->m_Value.m_Short );
|
||||
break;
|
||||
case eType_INT:
|
||||
paramsNode->getAttr( pParam->m_Name,pParam->m_Value.m_Int );
|
||||
break;
|
||||
case eType_FLOAT:
|
||||
paramsNode->getAttr( pParam->m_Name,pParam->m_Value.m_Float );
|
||||
break;
|
||||
//case eType_STRING:
|
||||
//paramsNode->getAttr( pParam->m_Name,pParam->m_Value.m_String );
|
||||
//break;
|
||||
case eType_FCOLOR:
|
||||
{
|
||||
Vec3 v(pParam->m_Value.m_Color[0],pParam->m_Value.m_Color[1],pParam->m_Value.m_Color[2]);
|
||||
paramsNode->getAttr( pParam->m_Name,v );
|
||||
pParam->m_Value.m_Color[0] = v.x;
|
||||
pParam->m_Value.m_Color[1] = v.y;
|
||||
pParam->m_Value.m_Color[2] = v.z;
|
||||
}
|
||||
break;
|
||||
case eType_VECTOR:
|
||||
{
|
||||
Vec3 v(pParam->m_Value.m_Vector[0],pParam->m_Value.m_Vector[1],pParam->m_Value.m_Vector[2]);
|
||||
paramsNode->getAttr( pParam->m_Name,v );
|
||||
pParam->m_Value.m_Vector[0] = v.x;
|
||||
pParam->m_Value.m_Vector[1] = v.y;
|
||||
pParam->m_Value.m_Vector[2] = v.z;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
1076
Cry3DEngine/Meshidx.cpp
Normal file
1076
Cry3DEngine/Meshidx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
Cry3DEngine/Node.cpp
Normal file
125
Cry3DEngine/Node.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: node.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading node info from cgf
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Node.h"
|
||||
#include "Geom.h"
|
||||
#include "file.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CNodeCGF::CNodeCGF() : CBaseObj()
|
||||
{
|
||||
m_pObj = NULL;
|
||||
// m_sPropStr = NULL;
|
||||
// m_ppChildren = NULL;
|
||||
// m_pnChildrenIds= NULL;
|
||||
m_pParent = NULL;
|
||||
// m_pMtl = NULL;
|
||||
// m_pConRot = NULL;
|
||||
// m_pConPos = NULL;
|
||||
// m_pConScl = NULL;
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
}
|
||||
|
||||
CNodeCGF::~CNodeCGF()
|
||||
{
|
||||
// if(m_ppChildren) free(m_ppChildren);
|
||||
// if(m_pnChildrenIds) free(m_pnChildrenIds);
|
||||
// if(m_sPropStr) free(m_sPropStr);
|
||||
}
|
||||
|
||||
bool CNodeCGF::Load(CXFile *f, int pos)
|
||||
{
|
||||
if(f->FSeek(pos,SEEK_SET)) return true;
|
||||
|
||||
int res=f->FRead(&m_Chunk,sizeof(m_Chunk),1);
|
||||
if(res!=1) return true;
|
||||
|
||||
if(m_Chunk.chdr.ChunkType != ChunkType_Node || m_Chunk.chdr.ChunkVersion != NODE_CHUNK_DESC_VERSION)
|
||||
{
|
||||
memset(&m_Chunk,0,sizeof(m_Chunk));
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ChunkHeader=m_Chunk.chdr;
|
||||
// m_NodeMatrix = m_Chunk.tm;
|
||||
|
||||
//read propstr
|
||||
/* if(m_Chunk.PropStrLen)
|
||||
{
|
||||
m_sPropStr=(char*)malloc(m_Chunk.PropStrLen+1);
|
||||
assert(m_sPropStr);
|
||||
res=f->FRead(m_sPropStr,m_Chunk.PropStrLen,1);
|
||||
m_sPropStr[m_Chunk.PropStrLen]=0;
|
||||
if(res!=1) return true;
|
||||
}*/
|
||||
|
||||
//read m_ppChildren
|
||||
/* if(m_Chunk.nChildren)
|
||||
{
|
||||
m_pnChildrenIds = (int*) malloc(m_Chunk.nChildren*sizeof(int));
|
||||
assert(m_pnChildrenIds);
|
||||
|
||||
m_ppChildren = (CNodeCGF **) malloc(m_Chunk.nChildren*sizeof(CNodeCGF*));
|
||||
assert(m_pnChildrenIds);
|
||||
memset(m_ppChildren,0,m_Chunk.nChildren*sizeof(CNodeCGF*));
|
||||
|
||||
int res=f->FRead(m_pnChildrenIds,sizeof(int),m_Chunk.nChildren);
|
||||
if(res!=m_Chunk.nChildren) return true;
|
||||
}*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CNodeCGF::Bind(CBaseObj ** all_objects, int n_obj)
|
||||
{
|
||||
if(m_bBinded)
|
||||
return;
|
||||
|
||||
for(int i=0;i<n_obj;i++)
|
||||
{
|
||||
CBaseObj * o = all_objects[i];
|
||||
if(!o || o->m_ChunkHeader.ChunkID == -1)
|
||||
continue;
|
||||
|
||||
if(o->m_ChunkHeader.ChunkID == m_Chunk.ObjectID)
|
||||
{
|
||||
m_pObj = o;
|
||||
o->m_nUsers++;
|
||||
}
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.ParentID)
|
||||
m_pParent=(CNodeCGF *)o; /*
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.MatID)
|
||||
m_pMtl=o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.pos_cont_id)
|
||||
m_pConPos=(Controller *)o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.rot_cont_id)
|
||||
m_pConRot=(Controller *)o;
|
||||
else if(o->m_ChunkHeader.ChunkID == m_Chunk.scl_cont_id)
|
||||
m_pConScl=(Controller *)o;
|
||||
|
||||
for(int j=0;j<m_Chunk.nChildren;j++)
|
||||
{
|
||||
if(o->m_ChunkHeader.ChunkID == m_pnChildrenIds[j])
|
||||
m_ppChildren[j]=(CNodeCGF *)o;
|
||||
}*/
|
||||
}
|
||||
|
||||
m_bBinded = true;
|
||||
}
|
||||
51
Cry3DEngine/Node.h
Normal file
51
Cry3DEngine/Node.h
Normal file
@@ -0,0 +1,51 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: node.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_)
|
||||
#define AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "BaseObj.h"
|
||||
|
||||
class Controller;
|
||||
|
||||
class CNodeCGF : public CBaseObj
|
||||
{
|
||||
public:
|
||||
NODE_CHUNK_DESC m_Chunk;
|
||||
// int *m_pnChildrenIds;
|
||||
|
||||
CBaseObj *m_pObj;
|
||||
/* char *m_sPropStr;
|
||||
CNodeCGF ** m_ppChildren;*/
|
||||
CNodeCGF *m_pParent;
|
||||
/*CBaseObj *m_pMtl;
|
||||
Controller *m_pConPos,*m_pConRot,*m_pConScl;*/
|
||||
// CryMatrix m_NodeMatrix;
|
||||
|
||||
CNodeCGF();
|
||||
virtual ~CNodeCGF();
|
||||
|
||||
virtual bool Load(CXFile *f, int pos);
|
||||
virtual void Bind(CBaseObj **all_objects, int n_obj);
|
||||
|
||||
char * GetName() { return m_Chunk.name; }
|
||||
float * GetMatrixData() { return m_Chunk.tm.GetData(); }
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_NODE_H__8DFD8741_DBA1_4357_9F50_8E37EA039BCB__INCLUDED_)
|
||||
922
Cry3DEngine/ObjMan.cpp
Normal file
922
Cry3DEngine/ObjMan.cpp
Normal file
@@ -0,0 +1,922 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjman.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Loading trees, buildings, ragister/unregister entities for rendering
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3DEngine.h"
|
||||
#include "meshidx.h"
|
||||
#include "watervolumes.h"
|
||||
#include "brush.h"
|
||||
#include "LMCompStructures.h"
|
||||
|
||||
double CObjManager::m_dMakeObjectTime = 0;
|
||||
double CObjManager::m_dCIndexedMesh__LoadMaterial = 0;
|
||||
double CObjManager::m_dUpdateCustomLightingSpritesAndShadowMaps = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Register / Unregister in sectors
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CObjManager::RegisterEntity( IEntityRender * pEntityRS )
|
||||
{
|
||||
if (!m_pTerrain)
|
||||
return;
|
||||
|
||||
const char * szClass = pEntityRS->GetEntityClassName();
|
||||
const char * szName = pEntityRS->GetName();
|
||||
if(!szName[0] && !szClass[0])
|
||||
return; // do not register undefined objects
|
||||
|
||||
// if(strstr(szName, "Merc"))
|
||||
// int y=0;
|
||||
|
||||
// if(strstr(szName, "Player"))
|
||||
// int y=0;
|
||||
|
||||
int nStatic = (pEntityRS->GetEntityRenderType() != eERType_Unknown);
|
||||
|
||||
// if draw near - register only in sector (0,0)
|
||||
// if current sector will not be visible - weapon will be drawn from sector (0,0)
|
||||
ICryCharInstance * cmodel = pEntityRS->GetEntityCharacter(0);
|
||||
if (cmodel && (cmodel->GetFlags() & CS_FLAG_DRAW_MODEL) && (cmodel->GetFlags() & CS_FLAG_DRAW_NEAR))
|
||||
{
|
||||
list2<IEntityRender*> * pList = &m_pTerrain->m_arrSecInfoTable[0][0]->m_lstEntities[nStatic];
|
||||
if(pList->Find(pEntityRS)<0)
|
||||
pList->Add(pEntityRS);
|
||||
pEntityRS->m_pSector = m_pTerrain->m_arrSecInfoTable[0][0];
|
||||
pEntityRS->m_pVisArea = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// find pos in sectors array
|
||||
Vec3d vBMin,vBMax;
|
||||
pEntityRS->GetRenderBBox(vBMin,vBMax);
|
||||
Vec3d vCenter = (vBMin+vBMax)*0.5f;
|
||||
/*
|
||||
if(nStatic && vBMax.z<m_pTerrain->GetZSafe(vCenter.x,vCenter.y))
|
||||
Warning(0,pEntityRS->GetName(),"%s is placed under the ground and not inside vis area: "
|
||||
"pos=%.2f,%.2f,%.2f, "
|
||||
"terrain elevation is %.2f, "
|
||||
"object name is %s",
|
||||
(pEntityRS->GetEntityRenderType()==eERType_Vegetation) ? "Vegetation" : "Brush",
|
||||
pEntityRS->GetPos().x, pEntityRS->GetPos().y, pEntityRS->GetPos().z,
|
||||
m_pTerrain->GetZSafe(vCenter.x,vCenter.y),
|
||||
pEntityRS->GetName());
|
||||
*/
|
||||
// if(strstr(szName, "Player"))
|
||||
// int y=0;
|
||||
|
||||
/*
|
||||
if(pEntityRS->GetRndFlags()&ERF_CASTSHADOWVOLUME)
|
||||
{ // adjust bbox by shadow
|
||||
Vec3d vShadowOffset = m_p3DEngine->GetSunPosition().Normalized()*pEntityRS->GetRadius();
|
||||
Vec3d vBoxMin2 = vBoxMin-vShadowOffset;
|
||||
Vec3d vBoxMax2 = vBoxMax-vShadowOffset;
|
||||
vBoxMin.CheckMin(vBoxMin2);
|
||||
vBoxMax.CheckMax(vBoxMax2);
|
||||
}
|
||||
*/
|
||||
// get 2d pos in sectors array
|
||||
int x = (int)(((vCenter.x)/CTerrain::GetSectorSize()));
|
||||
int y = (int)(((vCenter.y)/CTerrain::GetSectorSize()));
|
||||
|
||||
// if outside of the map, or too big - register in sector (0,0)
|
||||
if( vCenter.x<0 || vCenter.y<0 ||
|
||||
x<0 || x>=CTerrain::GetSectorsTableSize() || y<0 || y>=CTerrain::GetSectorsTableSize() ||
|
||||
(vBMax.x - vBMin.x)>TERRAIN_SECTORS_MAX_OVERLAPPING*2 || (vBMax.y - vBMin.y)>TERRAIN_SECTORS_MAX_OVERLAPPING*2)
|
||||
x = y = 0;
|
||||
|
||||
CSectorInfo * & pSector = pEntityRS->m_pSector;
|
||||
|
||||
if(pSector)
|
||||
UnRegisterEntity( pEntityRS );
|
||||
|
||||
pSector = m_pTerrain->m_arrSecInfoTable[x][y];
|
||||
|
||||
// add if not added
|
||||
if(pSector->m_lstEntities[nStatic].Find(pEntityRS)<0)
|
||||
pSector->m_lstEntities[nStatic].Add(pEntityRS);
|
||||
|
||||
if(nStatic && pSector)
|
||||
{
|
||||
pSector->m_vBoxMin.CheckMin(vBMin);
|
||||
pSector->m_vBoxMax.CheckMax(vBMax);
|
||||
}
|
||||
}
|
||||
|
||||
bool CObjManager::UnRegisterEntity( IEntityRender* pEntityRS )
|
||||
{
|
||||
if(!m_pTerrain)
|
||||
return false;
|
||||
|
||||
#ifdef _DEBUG
|
||||
const char * szName = pEntityRS->GetName();
|
||||
if(strstr(szName, "Player"))
|
||||
int y=0;
|
||||
#endif // _DEBUG
|
||||
|
||||
bool bFound = false;
|
||||
|
||||
int nStatic = (pEntityRS->GetEntityRenderType() != eERType_Unknown);
|
||||
|
||||
// unregister objects outside of the map and 1 person weapon
|
||||
if(m_pTerrain->m_arrSecInfoTable[0][0])
|
||||
bFound |= m_pTerrain->m_arrSecInfoTable[0][0]->m_lstEntities[nStatic].Delete(pEntityRS);
|
||||
|
||||
// unregister from sectors
|
||||
CSectorInfo * & pSector = pEntityRS->m_pSector;
|
||||
if(!pSector)
|
||||
return false;
|
||||
|
||||
// delete if found
|
||||
bFound |= pSector->m_lstEntities[nStatic].Delete(pEntityRS);
|
||||
|
||||
if(nStatic)
|
||||
{ // remove references to this entity
|
||||
pSector->m_lstStaticShadowMapCasters.Delete(pEntityRS);
|
||||
for(int i=0; i<pSector->m_lstStatEntInfoVegetNoCastersNoVolFog.Count(); i++)
|
||||
if(pSector->m_lstStatEntInfoVegetNoCastersNoVolFog[i].m_pEntityRender == pEntityRS)
|
||||
{
|
||||
pSector->m_lstStatEntInfoVegetNoCastersNoVolFog.Delete(i);
|
||||
i--;
|
||||
}
|
||||
for(int i=0; i<pSector->m_lstStatEntInfoOthers.Count(); i++)
|
||||
if(pSector->m_lstStatEntInfoOthers[i].m_pEntityRender == pEntityRS)
|
||||
{
|
||||
pSector->m_lstStatEntInfoOthers.Delete(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
pSector=0;
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load static objects
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CObjManager::LoadStaticObjectsFromXML()
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pVegetTagList;
|
||||
XDOM::IXMLDOMNodePtr pVegetTag;
|
||||
|
||||
XDOM::IXMLDOMDocumentPtr pDoc = GetSystem()->CreateXMLDocument();
|
||||
if(!pDoc->load(Get3DEngine()->GetLevelFilePath("LevelData.xml")))
|
||||
return false;
|
||||
|
||||
pVegetTagList = pDoc->getElementsByTagName("Vegetation");
|
||||
if (pVegetTagList)
|
||||
{
|
||||
pVegetTagList->reset();
|
||||
pVegetTag = pVegetTagList->nextNode();
|
||||
if (pVegetTag) // [marco] added this check - it was crashing here sometimes
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pVegetList;
|
||||
pVegetList = pVegetTag->getElementsByTagName("Object");
|
||||
if (pVegetList)
|
||||
{
|
||||
pVegetList->reset();
|
||||
XDOM::IXMLDOMNodePtr pVeget;
|
||||
int nGroupId=0;
|
||||
while (pVeget = pVegetList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pAlphaBlend = pVeget->getAttribute("AlphaBlend");
|
||||
XDOM::IXMLDOMNodePtr pBending = pVeget->getAttribute("Bending");
|
||||
XDOM::IXMLDOMNodePtr pBrightness = pVeget->getAttribute("Brightness");
|
||||
XDOM::IXMLDOMNodePtr pCastShadow = pVeget->getAttribute("CastShadow");
|
||||
XDOM::IXMLDOMNodePtr pFileName = pVeget->getAttribute("FileName");
|
||||
XDOM::IXMLDOMNodePtr pHideable = pVeget->getAttribute("Hideable");
|
||||
XDOM::IXMLDOMNodePtr pPhysNonColl = pVeget->getAttribute("PhysNonColl");
|
||||
XDOM::IXMLDOMNodePtr pIndex = pVeget->getAttribute("Index");
|
||||
XDOM::IXMLDOMNodePtr pPrecalcShadow = pVeget->getAttribute("PrecalcShadow");
|
||||
XDOM::IXMLDOMNodePtr pRecvShadow = pVeget->getAttribute("RecvShadow");
|
||||
XDOM::IXMLDOMNodePtr pSpriteDistRatio = pVeget->getAttribute("SpriteDistRatio");
|
||||
XDOM::IXMLDOMNodePtr pShadowDistRatio = pVeget->getAttribute("ShadowDistRatio");
|
||||
// XDOM::IXMLDOMNodePtr pUseLigthBit = pVeget->getAttribute("UseLigthBit");
|
||||
// XDOM::IXMLDOMNodePtr pAmbScale = pVeget->getAttribute("AmbScale");
|
||||
XDOM::IXMLDOMNodePtr pSpriteTexRes = pVeget->getAttribute("SpriteTexRes");
|
||||
XDOM::IXMLDOMNodePtr pMaxViewDistRatio= pVeget->getAttribute("MaxViewDistRatio");
|
||||
XDOM::IXMLDOMNodePtr pMaterialNode = pVeget->getAttribute("Material");
|
||||
XDOM::IXMLDOMNodePtr pBackSideLevel = pVeget->getAttribute("BackSideLevel");
|
||||
XDOM::IXMLDOMNodePtr pCalcLighting = pVeget->getAttribute("CalcLighting");
|
||||
XDOM::IXMLDOMNodePtr pUseSprites = pVeget->getAttribute("UseSprites");
|
||||
XDOM::IXMLDOMNodePtr pFadeSize = pVeget->getAttribute("FadeSize");
|
||||
XDOM::IXMLDOMNodePtr pUpdateShadowEveryFrame = pVeget->getAttribute("RealTimeShadow");
|
||||
|
||||
{
|
||||
IStatInstGroup siGroup;
|
||||
if(pAlphaBlend)
|
||||
siGroup.bUseAlphaBlending = atof(pAlphaBlend->getText()) != 0;
|
||||
if(pBending)
|
||||
siGroup.fBending = (float)atof(pBending->getText());
|
||||
if(pBrightness)
|
||||
siGroup.fBrightness = (float)atof(pBrightness->getText());
|
||||
if(pCastShadow)
|
||||
siGroup.bCastShadow = atof(pCastShadow->getText()) != 0;
|
||||
if(pRecvShadow)
|
||||
siGroup.bRecvShadow = atof(pRecvShadow->getText()) != 0;
|
||||
if(pFileName)
|
||||
siGroup.pStatObj = MakeObject(pFileName->getText(), NULL,
|
||||
evs_ShareAndSortForCache, true, false, false );
|
||||
|
||||
if(siGroup.pStatObj)
|
||||
siGroup.pStatObj->CheckValidVegetation();
|
||||
|
||||
if(siGroup.pStatObj && siGroup.pStatObj->GetLeafBuffer() && siGroup.pStatObj->GetLeafBuffer()->m_pMats && siGroup.pStatObj->GetLeafBuffer()->m_pMats->Count()>4)
|
||||
GetLog()->Log("Warning: Number of materials in distributed object is %d",
|
||||
siGroup.pStatObj->GetLeafBuffer()->m_pMats->Count());
|
||||
|
||||
if(pHideable)
|
||||
siGroup.bHideability = atof(pHideable->getText()) != 0;
|
||||
if(pPhysNonColl)
|
||||
siGroup.bPhysNonColl = atof(pPhysNonColl->getText()) != 0;
|
||||
if(pPrecalcShadow)
|
||||
siGroup.bPrecShadow = atof(pPrecalcShadow->getText()) != 0;
|
||||
if(pSpriteDistRatio)
|
||||
siGroup.fSpriteDistRatio = (float)atof(pSpriteDistRatio->getText());
|
||||
if(pShadowDistRatio)
|
||||
siGroup.fShadowDistRatio = (float)atof(pShadowDistRatio->getText());
|
||||
if(pMaxViewDistRatio)
|
||||
siGroup.fMaxViewDistRatio = (float)atof(pMaxViewDistRatio->getText());
|
||||
if(pSpriteTexRes)
|
||||
siGroup.nSpriteTexRes = (int)atoi(pSpriteTexRes->getText());
|
||||
if(pMaterialNode)
|
||||
siGroup.pMaterial = Get3DEngine()->FindMaterial( pMaterialNode->getText() );
|
||||
if(pBackSideLevel)
|
||||
siGroup.fBackSideLevel = (float)atof(pBackSideLevel->getText());
|
||||
if(pCalcLighting)
|
||||
siGroup.bCalcLighting = atof(pCalcLighting->getText()) != 0;
|
||||
if(pUseSprites)
|
||||
siGroup.bUseSprites = atof(pUseSprites->getText()) != 0;
|
||||
if(pFadeSize)
|
||||
siGroup.bFadeSize = atof(pFadeSize->getText()) != 0;
|
||||
if(pUpdateShadowEveryFrame)
|
||||
siGroup.bUpdateShadowEveryFrame = atof(pUpdateShadowEveryFrame->getText()) != 0;
|
||||
|
||||
if(siGroup.pStatObj->GetLeafBuffer() && !((CStatObj*)siGroup.pStatObj)->IsSpritesCreated() && !GetSystem()->IsDedicated())
|
||||
((CStatObj*)siGroup.pStatObj)->UpdateCustomLightingSpritesAndShadowMaps(m_vOutdoorAmbientColor, siGroup.nSpriteTexRes, siGroup.fBackSideLevel, siGroup.bCalcLighting );
|
||||
|
||||
((CStatObj*)siGroup.pStatObj)->FreeTriData(); // source geometry is needed only for stencil shadows
|
||||
|
||||
Get3DEngine()->SetStatInstGroup(nGroupId, siGroup);
|
||||
nGroupId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
IStatObj * CObjManager::GetStaticObjectByTypeID(int nTypeID)
|
||||
{
|
||||
if(nTypeID>=0 && nTypeID<m_lstStaticTypes.Count())
|
||||
return m_lstStaticTypes[nTypeID].pStatObj;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Init / Release
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
void CObjManager::LoadVegetationModels(const char *szMissionName,bool bEditorMode)
|
||||
{
|
||||
if(GetCVars()->e_vegetation)
|
||||
{
|
||||
int nCountStart = m_lstLoadedObjects.size();
|
||||
float time = GetCurAsyncTimeSec();
|
||||
LoadStaticObjectsFromXML();
|
||||
UpdateLoadingScreen("%d of %d static objects loaded in %.2f seconds",
|
||||
m_lstLoadedObjects.size()-nCountStart, m_lstLoadedObjects.size(), GetCurAsyncTimeSec()-time );
|
||||
}
|
||||
}
|
||||
|
||||
void CObjManager::UnloadVegetations()
|
||||
{
|
||||
// unload vegetation types
|
||||
for(int i=0; i<m_lstStaticTypes.Count(); i++)
|
||||
if( m_lstStaticTypes[i].GetStatObj() )
|
||||
{
|
||||
ReleaseObject( m_lstStaticTypes[i].GetStatObj() );
|
||||
memset(&m_lstStaticTypes[i], 0, sizeof(m_lstStaticTypes[i]));
|
||||
}
|
||||
m_lstStaticTypes.Clear();
|
||||
}
|
||||
|
||||
void CObjManager::CheckObjectLeaks(bool bDeleteAll)
|
||||
{
|
||||
// deleting leaked objects
|
||||
if(m_lstLoadedObjects.size()>1)
|
||||
GetLog()->Log("Warning: CObjManager::CheckObjectLeaks: %d object(s) found in memory", m_lstLoadedObjects.size());
|
||||
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
if(!(*it)->IsDefaultObject())
|
||||
{
|
||||
if((*it)->m_szGeomName[0])
|
||||
GetLog()->Log("Warning: object not deleted: %s / %s", (*it)->m_szFileName, (*it)->m_szGeomName);
|
||||
else
|
||||
GetLog()->Log("Warning: object not deleted: %s", (*it)->m_szFileName);
|
||||
}
|
||||
|
||||
if(bDeleteAll)
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
if(bDeleteAll)
|
||||
m_lstLoadedObjects.clear();
|
||||
}
|
||||
|
||||
void CObjManager::UnloadObjects()
|
||||
{
|
||||
UnloadVegetations();
|
||||
|
||||
// delete leaked objects
|
||||
CheckObjectLeaks(true);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create / delete object
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CStatObj * CObjManager::MakeObject(const char * __szFileName,
|
||||
const char * _szGeomName,
|
||||
EVertsSharing eVertsSharing,
|
||||
bool bLoadAdditinalInfo,
|
||||
bool bKeepInLocalSpace,
|
||||
bool bLoadLater)
|
||||
{
|
||||
AUTO_PROFILE_SECTION(GetTimer(), CObjManager::m_dMakeObjectTime);
|
||||
|
||||
if(!strcmp(__szFileName,"NOFILE"))
|
||||
{ // make ampty object to be filled from outside
|
||||
CStatObj * pObject = new CStatObj( );
|
||||
pObject->RegisterUser();
|
||||
m_lstLoadedObjects.insert(pObject);
|
||||
return pObject;
|
||||
}
|
||||
|
||||
assert(__szFileName && __szFileName[0]);
|
||||
|
||||
char szFileName[MAX_PATH_LENGTH];
|
||||
|
||||
// Normilize file name
|
||||
char *pszDest=szFileName;
|
||||
const char *pszSource=__szFileName;
|
||||
while (*pszSource)
|
||||
{
|
||||
if (*pszSource=='/')
|
||||
*pszDest++='\\';
|
||||
else
|
||||
*pszDest++=*pszSource;
|
||||
pszSource++;
|
||||
}
|
||||
*pszDest=0;
|
||||
|
||||
if(strstr(szFileName,".ccgf"))
|
||||
{
|
||||
int nLen = strlen(szFileName);
|
||||
strncpy(&szFileName[nLen-4],&szFileName[nLen-3],4);
|
||||
}
|
||||
|
||||
// Construct tmp object for search
|
||||
CStatObj tmp;
|
||||
strcpy(tmp.m_szFileName, szFileName);
|
||||
strcpy(tmp.m_szGeomName, _szGeomName ? _szGeomName : "");
|
||||
tmp.m_bKeepInLocalSpace = bKeepInLocalSpace;
|
||||
tmp.m_bLoadAdditinalInfo= bLoadAdditinalInfo;
|
||||
tmp.m_eVertsSharing = eVertsSharing;
|
||||
// tmp.m_bCalcLighting == s2->m_bCalcLighting);
|
||||
// tmp.m_bMakePhysics == s2->m_bMakePhysics);
|
||||
|
||||
// Try to find already loaded object
|
||||
if (!_szGeomName || !*_szGeomName || strcmp(_szGeomName,"cloth"))
|
||||
{ // [Anton] - always use new cgf for objects used for cloth simulation
|
||||
ObjectsMap::iterator it = m_lstLoadedObjects.find( &tmp );
|
||||
if (it != m_lstLoadedObjects.end())
|
||||
{
|
||||
assert( stricmp((*it)->m_szFileName, szFileName)==0 && // compare file name
|
||||
(!_szGeomName || stricmp((*it)->m_szGeomName, _szGeomName)==0)); // compare geom name
|
||||
|
||||
(*it)->RegisterUser();
|
||||
return (*it);
|
||||
}
|
||||
|
||||
// if ccfg was requested - change extension to cgf
|
||||
tmp.m_szFileName[strlen(tmp.m_szFileName)-2]=0;
|
||||
strcat(tmp.m_szFileName,"cgf");
|
||||
|
||||
// Try to find already loaded object
|
||||
it = m_lstLoadedObjects.find( &tmp );
|
||||
if (it != m_lstLoadedObjects.end())
|
||||
{
|
||||
assert( stricmp((*it)->m_szFileName, tmp.m_szFileName)==0 && // compare file name
|
||||
(!_szGeomName || stricmp((*it)->m_szGeomName, _szGeomName)==0)); // compare geom name
|
||||
|
||||
(*it)->RegisterUser();
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Load new CGF
|
||||
CStatObj * pObject = new CStatObj( );
|
||||
if(!pObject->Load(szFileName, _szGeomName, eVertsSharing, bLoadAdditinalInfo, bKeepInLocalSpace, bLoadLater))
|
||||
{
|
||||
// object not found
|
||||
// if geom name is specified - just return 0
|
||||
if(_szGeomName && _szGeomName[0])
|
||||
{
|
||||
delete pObject;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!m_pDefaultCGF)
|
||||
GetConsole()->Exit ("Error: CObjManager::MakeObject: Default object not found");
|
||||
|
||||
// return default object
|
||||
m_pDefaultCGF->RegisterUser();
|
||||
delete pObject;
|
||||
return m_pDefaultCGF;
|
||||
}
|
||||
|
||||
// now try to load lods
|
||||
pObject->LoadLowLODs(eVertsSharing,bLoadAdditinalInfo,bKeepInLocalSpace,bLoadLater);
|
||||
|
||||
// if(!bLoadLater && bGenSpritesAndShadowMap)
|
||||
// pObject->UpdateCustomLightingSpritesAndShadowMaps(m_vOutdoorAmbientColor, 0, fBackSideLevel, bCalcLighting );
|
||||
|
||||
pObject->RegisterUser();
|
||||
m_lstLoadedObjects.insert(pObject);
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
bool CObjManager::ReleaseObject(CStatObj * pObject)
|
||||
{
|
||||
// ObjectsMap::iterator it = m_lstLoadedObjects.find( pObject );
|
||||
//if (it != m_lstLoadedObjects.end())
|
||||
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
if((CStatObj*)(*it) == pObject)
|
||||
{
|
||||
assert(pObject == (CStatObj*)(*it));
|
||||
|
||||
CStatObj* p = (CStatObj*)(*it);
|
||||
|
||||
pObject->UnregisterUser();
|
||||
|
||||
if(pObject->m_nUsers<=0 && !m_bLockCGFResources)
|
||||
{
|
||||
GetLog()->Log("Object unloaded: %s %s",pObject->m_szFileName, pObject->m_szGeomName);
|
||||
m_lstLoadedObjects.erase(it);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// check that there is no other copies
|
||||
// ObjectsMap::iterator it_test = m_lstLoadedObjects.find( pObject );
|
||||
// assert(it_test == m_lstLoadedObjects.end());
|
||||
for (ObjectsMap::iterator it2 = m_lstLoadedObjects.begin(); it2 != m_lstLoadedObjects.end(); ++it2)
|
||||
assert((CStatObj*)(*it2) != pObject);
|
||||
#endif
|
||||
|
||||
delete pObject;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not found
|
||||
}
|
||||
|
||||
bool CObjManager::GetSectorBBox(list2<CStatObjInst> * stat_objects, Vec3d &sec_bbmin, Vec3d &sec_bbmax)
|
||||
{
|
||||
sec_bbmin=SetMaxBB();
|
||||
sec_bbmax=SetMinBB();
|
||||
|
||||
for( int i=0; i<stat_objects->Count(); i++ )
|
||||
{
|
||||
CStatObjInst * o = &((*stat_objects)[i]);
|
||||
|
||||
if(o->m_nObjectTypeID>=m_lstStaticTypes.Count())
|
||||
continue; // NOTE
|
||||
if(!m_lstStaticTypes[o->m_nObjectTypeID].pStatObj)
|
||||
continue; // NOTE
|
||||
|
||||
Vec3 ws_boxmin = m_lstStaticTypes[o->m_nObjectTypeID].GetStatObj()->m_vBoxMin*o->m_fScale;
|
||||
Vec3 ws_boxmax = m_lstStaticTypes[o->m_nObjectTypeID].GetStatObj()->m_vBoxMax*o->m_fScale;
|
||||
|
||||
ws_boxmin += o->m_vPos;
|
||||
ws_boxmax += o->m_vPos;
|
||||
|
||||
sec_bbmin.CheckMin(ws_boxmin);
|
||||
sec_bbmax.CheckMax(ws_boxmax);
|
||||
}
|
||||
|
||||
return stat_objects->Count()>0;
|
||||
}
|
||||
|
||||
CObjManager::CObjManager(C3DEngine * p3DEngine):
|
||||
m_pDefaultCGF (NULL)
|
||||
{
|
||||
m_p3DEngine = p3DEngine;
|
||||
m_pTerrain=0;
|
||||
m_fZoomFactor=1;
|
||||
|
||||
m_REFarTreeSprites = (CREFarTreeSprites*)GetRenderer()->EF_CreateRE(eDATA_FarTreeSprites);
|
||||
m_fWindForce = 0.15f;
|
||||
m_vOutdoorAmbientColor.Set(0,0,0);
|
||||
m_vSunColor.Set(0,0,0);
|
||||
|
||||
m_pCoverageBuffer = new CCoverageBuffer(GetRenderer());
|
||||
|
||||
m_fMaxViewDistanceScale=1.f;
|
||||
|
||||
if( GetRenderer()->GetFeatures() & RFT_OCCLUSIONTEST )
|
||||
m_pShaderOcclusionQuery = GetRenderer()->EF_LoadShader("OcclusionTest", eSH_World);
|
||||
else
|
||||
m_pShaderOcclusionQuery = 0;
|
||||
|
||||
m_pREClearStencil = (CREClearStencil*)GetRenderer()->EF_CreateRE(eDATA_ClearStencil);
|
||||
m_pCWaterVolumes = 0;
|
||||
|
||||
CStatObjInst::m_pObjManager = this;
|
||||
|
||||
// prepare default object
|
||||
m_pDefaultCGF = MakeObject("Objects\\default.cgf");
|
||||
m_pDefaultCGF->m_bDefaultObject = true;
|
||||
m_bLockCGFResources = false;
|
||||
}
|
||||
|
||||
CObjManager::~CObjManager()
|
||||
{
|
||||
// free default object
|
||||
ReleaseObject(m_pDefaultCGF);
|
||||
m_pDefaultCGF=0;
|
||||
|
||||
// free brushes
|
||||
assert(!m_lstBrushContainer.Count());
|
||||
for(int i=0; i<m_lstBrushContainer.Count(); i++)
|
||||
{
|
||||
if(m_lstBrushContainer[i]->GetEntityStatObj(0))
|
||||
ReleaseObject((CStatObj*)m_lstBrushContainer[i]->GetEntityStatObj(0));
|
||||
delete m_lstBrushContainer[i];
|
||||
}
|
||||
m_lstBrushContainer.Reset();
|
||||
|
||||
UnloadObjects();
|
||||
|
||||
assert(m_lstLoadedObjects.size() == 0);
|
||||
|
||||
m_REFarTreeSprites->Release();
|
||||
|
||||
delete m_pCoverageBuffer;
|
||||
m_pCoverageBuffer=0;
|
||||
|
||||
delete m_pCWaterVolumes;
|
||||
m_pCWaterVolumes=0;
|
||||
|
||||
m_pREClearStencil->Release();
|
||||
}
|
||||
|
||||
// update vertex lighting for satatic objects like trees
|
||||
void CObjManager::UpdateCustomLighting(const Vec3d & vLight)
|
||||
{
|
||||
GetLog()->UpdateLoadingScreen("Updating lighting on vegetations ");
|
||||
|
||||
for(int i=0; i<m_lstStaticTypes.Count(); i++)
|
||||
{
|
||||
if(m_lstStaticTypes[i].GetStatObj())
|
||||
{
|
||||
m_lstStaticTypes[i].GetStatObj()->UpdateCustomLightingSpritesAndShadowMaps(m_vOutdoorAmbientColor,
|
||||
m_lstStaticTypes[i].nSpriteTexRes, m_lstStaticTypes[i].fBackSideLevel, m_lstStaticTypes[i].bCalcLighting);
|
||||
|
||||
// if(!(i%4))
|
||||
GetLog()->UpdateLoadingScreenPlus(".");
|
||||
}
|
||||
}
|
||||
|
||||
GetLog()->UpdateLoadingScreenPlus(" done");
|
||||
}
|
||||
|
||||
// mostly xy size
|
||||
float CObjManager::GetXYRadius(int type)
|
||||
{
|
||||
if((m_lstStaticTypes.Count()<=type || !m_lstStaticTypes[type].pStatObj))
|
||||
return 0;
|
||||
|
||||
Vec3d vSize = m_lstStaticTypes[type].pStatObj->GetBoxMax() - m_lstStaticTypes[type].pStatObj->GetBoxMin();
|
||||
vSize.z *= 0.5;
|
||||
|
||||
float fRadius = m_lstStaticTypes[type].pStatObj->GetRadius();
|
||||
float fXYRadius = vSize.Length()*0.5f;
|
||||
|
||||
return fXYRadius;
|
||||
}
|
||||
|
||||
bool CObjManager::GetStaticObjectBBox(int nType, Vec3d & vBoxMin, Vec3d & vBoxMax)
|
||||
{
|
||||
if((m_lstStaticTypes.Count()<=nType || !m_lstStaticTypes[nType].pStatObj))
|
||||
return 0;
|
||||
|
||||
vBoxMin = m_lstStaticTypes[nType].pStatObj->GetBoxMin();
|
||||
vBoxMax = m_lstStaticTypes[nType].pStatObj->GetBoxMax();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CObjManager::AddPolygonToRenderer( const int nTexBindId,
|
||||
IShader * pShader,
|
||||
const int nDynLMask,
|
||||
Vec3d right,
|
||||
Vec3d up,
|
||||
const UCol & ucResCol,
|
||||
const ParticleBlendType eBlendType,
|
||||
const Vec3d & vAmbientColor,
|
||||
Vec3d vPos,
|
||||
const SColorVert * pTailVerts,
|
||||
const int nTailVertsNum,
|
||||
const byte * pTailIndices,
|
||||
const int nTailIndicesNum,
|
||||
const float fSortId,
|
||||
const int dwCCObjFlags,
|
||||
IMatInfo * pCustomMaterial,
|
||||
CStatObjInst * pStatObjInst,
|
||||
list2<struct ShadowMapLightSourceInstance> * pShadowMapCasters)
|
||||
{
|
||||
if(pStatObjInst && pStatObjInst->m_fFinalBending)
|
||||
{ // transfer decal into object space
|
||||
Matrix44 objMat;
|
||||
IStatObj * pEntObject = pStatObjInst->GetEntityStatObj(0, &objMat);
|
||||
assert(pEntObject);
|
||||
if(pEntObject)
|
||||
{
|
||||
objMat.Invert44();
|
||||
vPos = objMat.TransformPointOLD(vPos);
|
||||
right = objMat.TransformVectorOLD(right);
|
||||
up = objMat.TransformVectorOLD(up);
|
||||
}
|
||||
}
|
||||
|
||||
// set positions and tex coords
|
||||
SColorVert arrVerts[4];
|
||||
arrVerts[0].vert = (-right-up) + vPos;
|
||||
arrVerts[0].dTC[0] = 1;
|
||||
arrVerts[0].dTC[1] = 0;
|
||||
arrVerts[0].color = ucResCol;
|
||||
arrVerts[1].vert = ( right-up) + vPos;
|
||||
arrVerts[1].dTC[0] = 1;
|
||||
arrVerts[1].dTC[1] = 1;
|
||||
arrVerts[1].color = ucResCol;
|
||||
arrVerts[2].vert = ( right+up) + vPos;
|
||||
arrVerts[2].dTC[0] = 0;
|
||||
arrVerts[2].dTC[1] = 1;
|
||||
arrVerts[2].color = ucResCol;
|
||||
arrVerts[3].vert = (-right+up) + vPos;
|
||||
arrVerts[3].dTC[0] = 0;
|
||||
arrVerts[3].dTC[1] = 0;
|
||||
arrVerts[3].color = ucResCol;
|
||||
|
||||
if(nTexBindId <= 0 || nTexBindId >= 16384)
|
||||
{
|
||||
Warning( 0,0,"CObjManager::AddPolygonToRenderer: texture id is out of range: %d", nTexBindId);
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate render state
|
||||
uint nRenderState=0;
|
||||
switch(eBlendType)
|
||||
{
|
||||
case ParticleBlendType_AlphaBased:
|
||||
nRenderState = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_ALPHATEST_GREATER0;
|
||||
break;
|
||||
case ParticleBlendType_ColorBased:
|
||||
nRenderState = GS_BLSRC_ONE | GS_BLDST_ONEMINUSSRCCOL;
|
||||
break;
|
||||
case ParticleBlendType_Additive:
|
||||
nRenderState = GS_BLSRC_ONE | GS_BLDST_ONE;
|
||||
break;
|
||||
}
|
||||
|
||||
// repeated objects are free imedeately in renderer
|
||||
CCObject * pOb = GetIdentityCCObject();
|
||||
|
||||
if(pShadowMapCasters && pShadowMapCasters->Count())
|
||||
{
|
||||
pOb->m_pShadowCasters = pShadowMapCasters;
|
||||
pOb->m_ObjFlags |= FOB_INSHADOW;
|
||||
}
|
||||
|
||||
if(pStatObjInst && pStatObjInst->m_fFinalBending)
|
||||
{
|
||||
pStatObjInst->GetEntityStatObj(0,&pOb->m_Matrix);
|
||||
pOb->m_ObjFlags |= FOB_TRANS_MASK;
|
||||
CStatObj * pBody = m_lstStaticTypes[pStatObjInst->m_nObjectTypeID].GetStatObj();
|
||||
assert(pBody);
|
||||
if(pStatObjInst && pBody && pStatObjInst->m_fFinalBending)
|
||||
pBody->SetupBending(pOb,pStatObjInst->m_fFinalBending);
|
||||
}
|
||||
|
||||
pOb->m_DynLMMask = nDynLMask;
|
||||
assert(nTexBindId>0);
|
||||
pOb->m_NumCM = nTexBindId;
|
||||
pOb->m_AmbColor = vAmbientColor;
|
||||
pOb->m_RenderState = nRenderState;
|
||||
if(GetRenderer()->EF_GetHeatVision())
|
||||
pOb->m_ObjFlags |= FOB_HEATVISION;
|
||||
|
||||
pOb->m_ObjFlags |= dwCCObjFlags;
|
||||
|
||||
pOb->m_SortId = fSortId; // use m_SortId for sorting correction
|
||||
|
||||
pOb = GetRenderer()->EF_AddSpriteToScene(pShader->GetID(), 4, arrVerts, pOb);
|
||||
|
||||
if(pTailVerts && nTailVertsNum && pTailIndices && nTailIndicesNum)
|
||||
GetRenderer()->EF_AddSpriteToScene(pShader->GetID(), nTailVertsNum,
|
||||
(SColorVert*)pTailVerts, pOb, (byte*)pTailIndices, nTailIndicesNum);
|
||||
}
|
||||
|
||||
int CObjManager::GetMemoryUsage(class ICrySizer * pSizer)
|
||||
{
|
||||
int nSize = 0;
|
||||
|
||||
nSize += lstEntList_MLSMCIA.GetMemoryUsage();
|
||||
// nSize += lstStatInstList_MLSMCIA.GetMemoryUsage();
|
||||
nSize += m_lstDebugEntityList.GetMemoryUsage();
|
||||
nSize += m_lstStatEntitiesShadowMaps.GetMemoryUsage();
|
||||
nSize += m_lstFarObjects[0].GetMemoryUsage();
|
||||
nSize += m_lstFarObjects[1].GetMemoryUsage();
|
||||
|
||||
{
|
||||
for(int i=0; i<MAX_LIGHTS_NUM; i++)
|
||||
nSize += m_lstLightEntities[i].GetMemoryUsage();
|
||||
// for(int i=0; i<MAX_LIGHTS_NUM; i++)
|
||||
// nSize += m_lstShadowEntities[i].GetMemoryUsage();
|
||||
}
|
||||
|
||||
nSize += m_lstLoadedObjects.size()*sizeof(CStatObj*);
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
nSize += ((CStatObj*)(*it))->GetMemoryUsage();
|
||||
nSize += sizeof(CStatObj);
|
||||
}
|
||||
nSize += m_lstStaticTypes.GetMemoryUsage();
|
||||
// nSize += m_lstStatShadowsBuffer.GetMemoryUsage();
|
||||
// nSize += m_lstTmpEntities_MESF.GetMemoryUsage();
|
||||
nSize += m_lstTmpSectors_MELFP.GetMemoryUsage();
|
||||
// nSize += m_lstTmpStatInstList_MESF.GetMemoryUsage();
|
||||
/*
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "Brushes");
|
||||
int nSizeBrushes=0;
|
||||
nSizeBrushes += m_lstBrushContainer.GetMemoryUsage();
|
||||
nSizeBrushes += m_lstBrushContainer.Count()*sizeof(CBrush);
|
||||
pSizer->AddObject(&m_lstBrushContainer, nSizeBrushes);
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "BrushRS");
|
||||
for(int i=0; i<m_lstBrushContainer.Count(); i++)
|
||||
{
|
||||
if(m_lstBrushContainer[i]->GetEntityRS())
|
||||
pSizer->AddObject(m_lstBrushContainer[i]->GetEntityRS(), sizeof(*m_lstBrushContainer[i]->GetEntityRS()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "Veget");
|
||||
int nSizeVeg=0;
|
||||
nSizeVeg += m_lstVegetContainer.GetMemoryUsage();
|
||||
nSizeVeg += m_lstVegetContainer.Count()*sizeof(CStatObjInst);
|
||||
pSizer->AddObject(&m_lstVegetContainer, nSizeVeg);
|
||||
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "VegetRS");
|
||||
for(int i=0; i<m_lstVegetContainer.Count(); i++)
|
||||
{
|
||||
if(m_lstVegetContainer[i]->GetEntityRS())
|
||||
pSizer->AddObject(m_lstVegetContainer[i]->GetEntityRS(), sizeof(*m_lstVegetContainer[i]->GetEntityRS()));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
nSize += sizeof(CDLight);
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
void CObjManager::ReregisterEntitiesInArea(Vec3d vBoxMin, Vec3d vBoxMax)
|
||||
{
|
||||
list2<IEntityRender*> lstEntitiesInArea;
|
||||
|
||||
if(m_pTerrain)
|
||||
m_pTerrain->MoveAllEntitiesIntoList(&lstEntitiesInArea, vBoxMin, vBoxMax);
|
||||
|
||||
GetVisAreaManager()->MoveAllEntitiesIntoList(&lstEntitiesInArea, vBoxMin, vBoxMax);
|
||||
|
||||
int nChanged=0;
|
||||
for(int i=0; i<lstEntitiesInArea.Count(); i++)
|
||||
{
|
||||
IVisArea * pPrevArea = lstEntitiesInArea[i]->GetEntityVisArea();
|
||||
bool bFound = Get3DEngine()->UnRegisterEntity(lstEntitiesInArea[i]);
|
||||
|
||||
// assert(!bFound);
|
||||
|
||||
/* {
|
||||
Get3DEngine()->Un RegisterInAllSectors(lstEntitiesInArea[i]);
|
||||
|
||||
bFound = Get3DEngine()->UnRegisterEntity(lstEntitiesInArea[i]);
|
||||
|
||||
if(lstEntitiesInArea[i]->IsStatic())
|
||||
{
|
||||
CBrush * pEnt = (CBrush *)lstEntitiesInArea[i];
|
||||
Matrix mat;
|
||||
CStatObj * pStatObj = (CStatObj*)lstEntitiesInArea[i]->GetEntityStatObj(0,&mat);
|
||||
assert(CBrush::IsMatrixValid(mat));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Get3DEngine()->RegisterEntity(lstEntitiesInArea[i]);
|
||||
if(pPrevArea != lstEntitiesInArea[i]->GetEntityVisArea())
|
||||
nChanged++;
|
||||
}
|
||||
|
||||
GetLog()->Log(" CObjManager::ReregisterEntitiesInArea: %d of %d objects updated", nChanged, lstEntitiesInArea.Count());
|
||||
}
|
||||
/*
|
||||
int CObjManager::CountPhysGeomUsage(CStatObj * pStatObjToFind)
|
||||
{
|
||||
int nRes=0;
|
||||
for(int i=0; i<m_lstBrushContainer.Count(); i++)
|
||||
{
|
||||
CBrush * pBrush = m_lstBrushContainer[i];
|
||||
IStatObj * pStatObj = pBrush->GetEntityStatObj(0);
|
||||
// assert(((CStatObj*)pStatObj)->m_bStreamable);
|
||||
if(pStatObjToFind == pStatObj)
|
||||
{
|
||||
if(pBrush->GetPhysGeomId(0)>=0 || pBrush->GetPhysGeomId(1)>=0)
|
||||
nRes++;
|
||||
}
|
||||
}
|
||||
|
||||
return nRes;
|
||||
}*/
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
void CObjManager::FreeNotUsedCGFs()
|
||||
{
|
||||
assert(!m_bLockCGFResources);
|
||||
|
||||
if (!m_bLockCGFResources)
|
||||
{
|
||||
//Timur, You MUST use next here, or with erase you invalidating
|
||||
ObjectsMap::iterator next;
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); it = next)
|
||||
{
|
||||
next = it; next++;
|
||||
CStatObj* p = (CStatObj*)(*it);
|
||||
if(p->m_nUsers<=0)
|
||||
{
|
||||
GetLog()->Log("Object unloaded: %s %s",p->m_szFileName, p->m_szGeomName);
|
||||
m_lstLoadedObjects.erase(it);
|
||||
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
269
Cry3DEngine/ObjMan.h
Normal file
269
Cry3DEngine/ObjMan.h
Normal file
@@ -0,0 +1,269 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjman.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CObjManager_H
|
||||
#define CObjManager_H
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
#include "terrain_sector.h"
|
||||
|
||||
#define ENTITY_MAX_DIST_FACTOR 100
|
||||
|
||||
struct CStatObj;
|
||||
struct IIndoorBase;
|
||||
struct IEntityRender;
|
||||
struct ISystem;
|
||||
|
||||
class CStatObjInst;
|
||||
|
||||
class C3DEngine;
|
||||
struct IMatInfo;
|
||||
|
||||
#define SMC_STATICS 1
|
||||
#define SMC_DYNAMICS 2
|
||||
#define SMC_ALLOW_PASSIVE_SHADOWMAP_CASTERS 4
|
||||
|
||||
//! contains stat obj instance group properies (vegetation object properties)
|
||||
struct StatInstGroup : public IStatInstGroup
|
||||
{
|
||||
StatInstGroup() { pStatObj = 0; }
|
||||
CStatObj * GetStatObj() { return (CStatObj*)pStatObj; }
|
||||
|
||||
void SetRndFlags()
|
||||
{
|
||||
m_dwRndFlags = 0;
|
||||
if(bCastShadow)
|
||||
m_dwRndFlags |= ERF_CASTSHADOWMAPS;
|
||||
if(bRecvShadow)
|
||||
m_dwRndFlags |= ERF_RECVSHADOWMAPS;
|
||||
if(bPrecShadow)
|
||||
m_dwRndFlags |= ERF_CASTSHADOWINTOLIGHTMAP;
|
||||
if(bHideability)
|
||||
m_dwRndFlags |= ERF_HIDABLE;
|
||||
if(bPhysNonColl)
|
||||
m_dwRndFlags |= ERF_PHYS_NONCOLL;
|
||||
}
|
||||
};
|
||||
|
||||
struct SExportedBrushMaterial
|
||||
{
|
||||
int size;
|
||||
char material[64];
|
||||
};
|
||||
|
||||
class CObjManager : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CObjManager(C3DEngine * p3DEngine);
|
||||
~CObjManager();
|
||||
|
||||
void LoadVegetationModels(const char *szMissionName, bool bEditorMode);
|
||||
void UnloadObjects();
|
||||
|
||||
void DrawFarObjects(float fMaxViewDist);
|
||||
void RenderFarObjects();
|
||||
|
||||
void RegisterEntity( IEntityRender* pEntityRS );
|
||||
bool UnRegisterEntity( IEntityRender* pEntityRS );
|
||||
|
||||
CStatObj * CObjManager::MakeObject(const char * __szFileName, const char * _szGeomName=0,
|
||||
EVertsSharing eVertsSharing = evs_NoSharing,
|
||||
bool bLoadAdditinalInfo = true,
|
||||
bool bKeepInLocalSpace = false,
|
||||
bool bLoadLater = false);
|
||||
|
||||
bool ReleaseObject(CStatObj * pObject);
|
||||
|
||||
bool GetSectorBBox(list2<CStatObjInst> * stat_objects, Vec3d &sec_bbmin, Vec3d &sec_bbmax);
|
||||
|
||||
list2<StatInstGroup> m_lstStaticTypes;
|
||||
|
||||
void MakeShadowMapInstancesList(IEntityRender * pEntityRS, float obj_distance,
|
||||
list2<ShadowMapLightSourceInstance> * pLSourceInstances,
|
||||
int dwAllowedTypes, CDLight * pLight);
|
||||
|
||||
float m_fZoomFactor;
|
||||
|
||||
CTerrain * m_pTerrain;
|
||||
|
||||
void UpdateCustomLighting(const Vec3d & vLight);
|
||||
|
||||
list2<CStatObjInst*> m_lstFarObjects[2];
|
||||
|
||||
protected:
|
||||
struct string_less : public std::binary_function<CStatObj*,CStatObj*,bool>
|
||||
{
|
||||
bool operator()( CStatObj *s1,CStatObj *s2 ) const
|
||||
{
|
||||
int nFileCmpRes = stricmp(s1->m_szFileName,s2->m_szFileName);
|
||||
if(!nFileCmpRes) // if file name is the same - compare just geom names
|
||||
{
|
||||
int nObjCmpRes = stricmp(s1->m_szGeomName,s2->m_szGeomName);
|
||||
|
||||
if(nObjCmpRes==0)
|
||||
{
|
||||
if(s1->m_eVertsSharing == s2->m_eVertsSharing)
|
||||
{
|
||||
assert(s1->m_bKeepInLocalSpace == s2->m_bKeepInLocalSpace);
|
||||
// assert(s1->m_bMakePhysics == s2->m_bMakePhysics);
|
||||
// assert(s1->m_bCalcLighting == s2->m_bCalcLighting);
|
||||
return s1->m_bLoadAdditinalInfo < s2->m_bLoadAdditinalInfo;
|
||||
}
|
||||
|
||||
return s1->m_eVertsSharing < s2->m_eVertsSharing;
|
||||
}
|
||||
|
||||
return nObjCmpRes < 0;
|
||||
}
|
||||
|
||||
return nFileCmpRes < 0;
|
||||
}
|
||||
};
|
||||
typedef std::set<CStatObj*,string_less> ObjectsMap;
|
||||
ObjectsMap m_lstLoadedObjects;
|
||||
|
||||
void InitFarState();
|
||||
|
||||
CREFarTreeSprites * m_REFarTreeSprites;
|
||||
|
||||
ShadowMapFrustum * MakeEntityShadowFrustum(ShadowMapFrustum * pFrustum,
|
||||
ShadowMapLightSource * pLs, IEntityRender * pEntityRS, EShadowType nShadowType, int dwAllowedTypes);
|
||||
|
||||
list2<IEntityRender*> m_lstDebugEntityList;
|
||||
|
||||
void MakeShadowCastersList(IEntityRender * pEntityRS, list2<IEntityRender*> * pEntList,
|
||||
int dwAllowedTypes, Vec3d vLightPos, float fLightRadius);
|
||||
list2<CSectorInfo*> m_lstTmpSectors_MELFP;
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
public:
|
||||
int GetLoadedObjectCount() { return m_lstLoadedObjects.size(); }
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
|
||||
void RenderObject( IEntityRender * o,
|
||||
int nFogVolumeID, uint nDLightMask,
|
||||
bool bLMapGeneration,
|
||||
const CCamera & EntViewCamera,
|
||||
Vec3d * pvAmbColor, Vec3d * pvDynAmbColor,
|
||||
VolumeInfo * pFogVolume,
|
||||
bool bNotAllInFrustum,
|
||||
float fMaxViewDist, IEntityRenderInfo * pEntInfo = NULL);
|
||||
|
||||
float GetXYRadius(int nType);
|
||||
bool GetStaticObjectBBox(int nType, Vec3d & vBoxMin, Vec3d & vBoxMax);
|
||||
void DrawAllShadowsOnTheGroundInSector(list2<IEntityRender*> * pEntList);
|
||||
|
||||
float m_fWindForce; //!< used for bending plants
|
||||
Vec3d m_vOutdoorAmbientColor; //!<
|
||||
Vec3d m_vSunColor; //!<
|
||||
|
||||
IStatObj * GetStaticObjectByTypeID(int nTypeID);
|
||||
float GetBendingRandomFactor();
|
||||
C3DEngine * m_p3DEngine;
|
||||
|
||||
class CCoverageBuffer * m_pCoverageBuffer;
|
||||
bool IsBoxOccluded(const Vec3d & vBoxMin, const Vec3d & vBoxMax, float fDistance, OcclusionTestClient * pOcclTestVars);
|
||||
|
||||
list2<IEntityRender*> m_lstStatEntitiesShadowMaps;
|
||||
list2<IEntityRender*> m_lstEntitiesShadowSpots;
|
||||
|
||||
void RenderEntitiesShadowMapsOnTerrain(bool bLMapGeneration, class CREShadowMapGen * pREShadowMapGenerator);
|
||||
void DrawEntitiesShadowSpotsOnTerrain();
|
||||
|
||||
void AddPolygonToRenderer(const int nTexBindId,
|
||||
IShader * pShader,
|
||||
const int nDynLMask,
|
||||
Vec3d right,
|
||||
Vec3d up,
|
||||
const UCol & ucResCol,
|
||||
const ParticleBlendType eBlendType,
|
||||
const Vec3d & vAmbientColor,
|
||||
Vec3d vPos,
|
||||
const SColorVert * pTailVerts = NULL,
|
||||
const int nTailVertsNum = 0,
|
||||
const byte * pTailIndices = NULL,
|
||||
const int nTailIndicesNum = 0,
|
||||
const float fSortId = 0,
|
||||
const int dwCCObjFlags = 0,
|
||||
IMatInfo * pCustomMaterial = NULL,
|
||||
CStatObjInst * pStatObjInst = NULL,
|
||||
list2<struct ShadowMapLightSourceInstance> * pShadowMapCasters = NULL);
|
||||
|
||||
// tmp containers (replacement for local static vars)
|
||||
list2<IEntityRender*> lstEntList_MLSMCIA;
|
||||
|
||||
void RenderEntityShadowOnTerrain(IEntityRender * pEntityRS, bool bLMapGeneration, CREShadowMapGen * pREShadowMapGenerator);
|
||||
void DrawObjSpritesSorted(list2<CStatObjInst*> *pList, float fMaxViewDist, int useBending);
|
||||
void ProcessActiveShadowReceiving(IEntityRender * pEnt, float fEntDistance, CDLight * pLight, bool bLMapGeneration);
|
||||
|
||||
void SetupEntityShadowMapping( IEntityRender * pEntityRS, SRendParams * pDrawParams, bool bLMapGeneration, float fEntDistance, CDLight * pDLight );
|
||||
float m_fMaxViewDistanceScale;
|
||||
IShader * m_pShaderOcclusionQuery;
|
||||
|
||||
bool LoadStaticObjectsFromXML();
|
||||
CStatObj * m_pDefaultCGF;
|
||||
|
||||
#define MAX_LIGHTS_NUM 32
|
||||
list2<IEntityRender*> m_lstLightEntities[MAX_LIGHTS_NUM];
|
||||
|
||||
void DrawEntitiesLightPass();
|
||||
class CREClearStencil * m_pREClearStencil;
|
||||
int GetMemoryUsage(class ICrySizer * pSizer);
|
||||
|
||||
struct CWaterVolumeManager * m_pCWaterVolumes;
|
||||
float CalculateEntityShadowVolumeExtent(IEntityRender * pEntityRS, CDLight * pDLight);
|
||||
|
||||
list2<class CBrush*> m_lstBrushContainer;
|
||||
list2<class CStatObjInst*> m_lstVegetContainer;
|
||||
void LoadBrushes();
|
||||
void MergeBrushes();
|
||||
void ReregisterEntitiesInArea(Vec3d vBoxMin, Vec3d vBoxMax);
|
||||
void ProcessEntityParticles(IEntityRender * pEntityRS, float fEntDistance);
|
||||
void CheckUnload();
|
||||
void PreloadNearObjects();
|
||||
// time counters
|
||||
static double m_dMakeObjectTime;
|
||||
static double m_dCIndexedMesh__LoadMaterial;
|
||||
static double m_dUpdateCustomLightingSpritesAndShadowMaps;
|
||||
|
||||
void MakeShadowBBox(Vec3d & vBoxMin, Vec3d & vBoxMax, const Vec3d & vLightPos, float fLightRadius, float fShadowVolumeExtent);
|
||||
CFColor CalcShadowOnTerrainColor(float fAlpha, bool bLMapGeneration);
|
||||
float GetSortOffset( const Vec3d & vPos, const Vec3d & vCamPos, float fUserWaterLevel = WATER_LEVEL_UNKNOWN );
|
||||
void GetObjectsStreamingStatus(int & nReady, int & nTotalInStreaming, int & nTotal);
|
||||
bool ProcessShadowMapCasting(IEntityRender * pEnt, CDLight * pDLight);
|
||||
void UnloadVegetations();
|
||||
void CheckObjectLeaks(bool bDeleteAll = false);
|
||||
bool IsSphereAffectedByShadow(IEntityRender * pCaster, IEntityRender * pReceiver, CDLight * pLight);
|
||||
void MakeShadowCastersListInArea(CBasicArea*pArea, IEntityRender * pReceiver,
|
||||
list2<IEntityRender*> * pEntList, int dwAllowedTypes, Vec3d vLightPos, float fLightRadius);
|
||||
void PrefechObjects();
|
||||
void RequestEntityShadowMapGeneration(IEntityRender * pEntityRnd);
|
||||
bool m_bLockCGFResources;
|
||||
void FreeNotUsedCGFs();
|
||||
void RenderObjectVegetationNonCastersNoFogVolume( IEntityRender * pEntityRS,uint nDLightMask,
|
||||
const CCamera & EntViewCamera,
|
||||
bool bNotAllInFrustum, float fMaxViewDist, IEntityRenderInfo * pEntInfo);
|
||||
};
|
||||
|
||||
#endif // CObjManager_H
|
||||
213
Cry3DEngine/ObjManDraw.cpp
Normal file
213
Cry3DEngine/ObjManDraw.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjmandraw.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Draw static objects (vegetations)
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "3dengine.h"
|
||||
#include "cbuffer.h"
|
||||
|
||||
bool CObjManager::IsBoxOccluded( const Vec3d & vBoxMin, const Vec3d & vBoxMax, float fDistance, OcclusionTestClient * pOcclTestVars )
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
assert(pOcclTestVars);
|
||||
assert(fDistance>=0);
|
||||
|
||||
if(m_nRenderStackLevel)
|
||||
return pOcclTestVars->bLastResult; // return result of base level test
|
||||
|
||||
if(pOcclTestVars->nLastVisibleFrameID < GetFrameID()-1)
|
||||
{ // if was invisible last frames (because of frustum culling)
|
||||
pOcclTestVars->ucOcclusionByObjectsFrames = 0; // force to test this frame
|
||||
|
||||
if(GetCVars()->e_terrain_occlusion_culling!=2)
|
||||
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test this frame
|
||||
}
|
||||
|
||||
{ // test occlusion by objects
|
||||
if(!pOcclTestVars->ucOcclusionByObjectsFrames && fDistance>COVERAGEBUFFER_OCCLUSION_TESTERS_MIN_DISTANCE && GetCVars()->e_cbuffer)
|
||||
{ // less distance do not work because objects are sorted wrong
|
||||
if(!m_pCoverageBuffer->IsBBoxVisible(vBoxMin,vBoxMax))
|
||||
{
|
||||
pOcclTestVars->ucOcclusionByObjectsFrames = 0; // force to test next frame
|
||||
pOcclTestVars->bLastResult = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
pOcclTestVars->ucOcclusionByObjectsFrames += 4; // skip testing next frame
|
||||
}
|
||||
/*
|
||||
{ // test occl by antiportals
|
||||
if(GetVisAreaManager()->IsOccludedByOcclVolumes(vBoxMin,vBoxMax))
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
{ // test occlusion by terrain
|
||||
Vec3d vTopMax = vBoxMax;
|
||||
Vec3d vTopMin = vBoxMin; vTopMin.z = vTopMax.z;
|
||||
|
||||
const Vec3d & vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
vTopMax.CheckMin(Vec3d((float)CTerrain::GetTerrainSize(),(float)CTerrain::GetTerrainSize(),1024.f));
|
||||
vTopMin.CheckMax(Vec3d(0,0,-1024.f));
|
||||
|
||||
vTopMin.CheckMin(Vec3d((float)CTerrain::GetTerrainSize(),(float)CTerrain::GetTerrainSize(),1024.f));
|
||||
vTopMax.CheckMax(Vec3d(0,0,-1024.f));
|
||||
|
||||
if( !pOcclTestVars->ucOcclusionByTerrainFrames && GetCVars()->e_terrain_occlusion_culling )
|
||||
{
|
||||
int nMaxTestsToScip = (GetVisAreaManager()->m_pCurPortal) ? 3 : 10000;
|
||||
|
||||
// precision in meters for this object
|
||||
float fMaxStep = fDistance*GetCVars()->e_terrain_occlusion_culling_precision;
|
||||
|
||||
if( (fMaxStep < (vTopMax.x - vTopMin.x)*2.f || fMaxStep < (vTopMax.y - vTopMin.y)*2.f) &&
|
||||
// fDistance<700 &&
|
||||
vBoxMin.x != vBoxMax.x && vBoxMin.y != vBoxMax.y )
|
||||
{
|
||||
bool bOccluded = true;
|
||||
|
||||
// todo: debug this
|
||||
float dx = (vTopMax.x - vTopMin.x)*0.99999f;
|
||||
while(dx>fMaxStep)
|
||||
dx*=0.5f;
|
||||
|
||||
float dy = (vTopMax.y - vTopMin.y)*0.99999f;
|
||||
while(dy>fMaxStep)
|
||||
dy*=0.5f;
|
||||
|
||||
// todo: test only borders
|
||||
for(float x=vTopMin.x; x<=vTopMax.x; x+=dx)
|
||||
for(float y=vTopMin.y; y<=vTopMax.y; y+=dy)
|
||||
{
|
||||
if(!m_pTerrain->IsPointOccludedByTerrain(Vec3d(x, y, vTopMax.z), fDistance, vCamPos, nMaxTestsToScip))
|
||||
{
|
||||
bOccluded = false;
|
||||
x=y=1000000;//break
|
||||
}
|
||||
}
|
||||
|
||||
if(bOccluded)
|
||||
{
|
||||
if(GetCVars()->e_terrain_occlusion_culling!=2)
|
||||
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test next frame
|
||||
|
||||
pOcclTestVars->bLastResult = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3d vTopMid = (vTopMin+vTopMax)*0.5f;
|
||||
if( m_pTerrain->IsPointOccludedByTerrain(vTopMid, fDistance,vCamPos, nMaxTestsToScip))
|
||||
{
|
||||
if(GetCVars()->e_terrain_occlusion_culling!=2)
|
||||
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test next frame
|
||||
|
||||
pOcclTestVars->bLastResult = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pOcclTestVars->ucOcclusionByTerrainFrames == 0) // && GetCVars()->e_terrain_occlusion_culling==3)
|
||||
{ // randomize test time, do this only here otherwice ucOcclusionByTerrainFrames may never become 0 and next test will not happend
|
||||
static int arrRnd[16] =
|
||||
{
|
||||
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
|
||||
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
|
||||
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
|
||||
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1
|
||||
};
|
||||
|
||||
static int nRndCounter = 0;
|
||||
nRndCounter++;
|
||||
if(nRndCounter>=16)
|
||||
nRndCounter=0;
|
||||
|
||||
pOcclTestVars->ucOcclusionByTerrainFrames = arrRnd[nRndCounter]*4;
|
||||
}
|
||||
else
|
||||
pOcclTestVars->ucOcclusionByTerrainFrames += 4; // skip testing next 64 frames
|
||||
}
|
||||
|
||||
/* const Vec3d & vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
bool bCameraInBBox =
|
||||
vCamPos.x >= (vBoxMin.x-0.05f) && vCamPos.y >= (vBoxMin.y-0.05f) && vCamPos.z >= (vBoxMin.z-0.05f) &&
|
||||
vCamPos.x <= (vBoxMax.x+0.05f) && vCamPos.y <= (vBoxMax.y+0.05f) && vCamPos.z <= (vBoxMax.z+0.05f);
|
||||
|
||||
// Make test only if camera outside of the box and if feature supported
|
||||
if(fDistance>1 && !bCameraInBBox && GetCVars()->e_hw_occlusion_culling_objects && (GetRenderer()->GetFeatures() & RFT_OCCLUSIONTEST) )
|
||||
{
|
||||
// construct RE if needed
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
if(!pOcclTestVars->arrREOcclusionQuery[i])
|
||||
pOcclTestVars->arrREOcclusionQuery[i] =
|
||||
(CREOcclusionQuery *)GetRenderer()->EF_CreateRE(eDATA_OcclusionQuery);
|
||||
|
||||
pOcclTestVars->arrREOcclusionQuery[i]->m_vBoxMin = vBoxMin;
|
||||
pOcclTestVars->arrREOcclusionQuery[i]->m_vBoxMax = vBoxMax;
|
||||
}
|
||||
|
||||
int nSlotId = GetFrameID()&1;
|
||||
GetRenderer()->EF_AddEf(0, pOcclTestVars->arrREOcclusionQuery[nSlotId], m_pShaderOcclusionQuery, 0);
|
||||
|
||||
if(GetCVars()->e_hw_occlusion_culling_objects>1)
|
||||
{
|
||||
float fVis = (pOcclTestVars->arrREOcclusionQuery[!nSlotId]->m_nVisSamples >= 2);
|
||||
float fCol[] = {fVis,!fVis,1,1};
|
||||
GetRenderer()->DrawLabelEx((vBoxMin + vBoxMax)*0.5f,6, fCol, false, true, "%s",
|
||||
fVis ? "V" : "N");
|
||||
}
|
||||
|
||||
if(
|
||||
pOcclTestVars->arrREOcclusionQuery[0]->m_nVisSamples < 2 &&
|
||||
pOcclTestVars->arrREOcclusionQuery[1]->m_nVisSamples < 2 &&
|
||||
1 >= abs( pOcclTestVars->arrREOcclusionQuery[0]->m_nCheckFrame -
|
||||
pOcclTestVars->arrREOcclusionQuery[1]->m_nCheckFrame ) &&
|
||||
GetFrameID()-2 <= pOcclTestVars->arrREOcclusionQuery[0]->m_nDrawFrame &&
|
||||
GetFrameID()-2 <= pOcclTestVars->arrREOcclusionQuery[1]->m_nDrawFrame )
|
||||
{ // return true only if last test is not older than 1 frame
|
||||
pOcclTestVars->bLastResult = true;
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
pOcclTestVars->bLastResult = false;
|
||||
pOcclTestVars->nLastVisibleFrameID = GetFrameID();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CObjManager::PrefechObjects()
|
||||
{
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
CStatObj * pStatObj = (*it);
|
||||
SRendParams params;
|
||||
params.nDLightMask = 1;
|
||||
GetRenderer()->EF_StartEf();
|
||||
for(int i=0; i<3; i++)
|
||||
pStatObj->Render(params,Vec3(zero),i);
|
||||
GetRenderer()->EF_EndEf3D(0);
|
||||
}
|
||||
}
|
||||
1546
Cry3DEngine/ObjManDrawEntity.cpp
Normal file
1546
Cry3DEngine/ObjManDrawEntity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
260
Cry3DEngine/ObjManFar.cpp
Normal file
260
Cry3DEngine/ObjManFar.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjmanfar.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: draw far objects as sprites
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
void CObjManager::RenderFarObjects()
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
if (m_REFarTreeSprites && GetCVars()->e_vegetation_sprites && m_lstFarObjects[m_nRenderStackLevel].Count())
|
||||
{
|
||||
CCObject * pObj = GetRenderer()->EF_GetObject(true, -1);
|
||||
pObj->m_Matrix.SetIdentity();
|
||||
GetRenderer()->EF_AddEf(0, m_REFarTreeSprites, m_p3DEngine->m_pSHFarTreeSprites, NULL, pObj, 0, NULL,
|
||||
/*(GetViewCamera().GetPos().z<m_pTerrain->GetWaterLevel()) ? */eS_Trees /*: eS_Sprites*/
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
static _inline int Compare(CStatObjInst *& p1, CStatObjInst *& p2)
|
||||
{
|
||||
if(p1->m_fDistance > p2->m_fDistance)
|
||||
return 1;
|
||||
else
|
||||
if(p1->m_fDistance < p2->m_fDistance)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
} */
|
||||
|
||||
void CObjManager::DrawFarObjects(float fMaxViewDist)
|
||||
{
|
||||
if(!GetCVars()->e_vegetation_sprites)
|
||||
return;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// Draw all far
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
list2<CStatObjInst*> * pList = &m_lstFarObjects[m_nRenderStackLevel];
|
||||
|
||||
if (pList->Count())
|
||||
{
|
||||
IRenderer * pRenderer = GetRenderer();
|
||||
|
||||
int useBending;
|
||||
if (/*(GetRenderer()->GetFeatures() & RFT_HW_VS) &&*/ GetCVars()->e_vegetation_bending >= 2)
|
||||
useBending = 2;
|
||||
else
|
||||
if (GetCVars()->e_vegetation_bending == 1)
|
||||
useBending = 1;
|
||||
else
|
||||
useBending = 0;
|
||||
|
||||
if(useBending == 2)
|
||||
GetRenderer()->DrawObjSprites(pList, fMaxViewDist, this);
|
||||
else
|
||||
DrawObjSpritesSorted(pList, fMaxViewDist, useBending);
|
||||
}
|
||||
|
||||
for(int s=0; s<m_lstDebugEntityList.Count(); s++)
|
||||
{
|
||||
IRenderer * pRenderer = GetRenderer();
|
||||
pRenderer->ResetToDefault();
|
||||
ShadowMapLightSource * & pLsource = m_lstDebugEntityList[s]->GetEntityRS()->pShadowMapInfo->pShadowMapFrustumContainer;
|
||||
|
||||
GetRenderer()->PushMatrix();
|
||||
GetRenderer()->TranslateMatrix(m_lstDebugEntityList[s]->GetPos());
|
||||
pLsource->m_LightFrustums.Get(0)->DrawFrustum(pRenderer,m_lstDebugEntityList[s]->GetPos(),1.f);
|
||||
GetRenderer()->PopMatrix();
|
||||
|
||||
Vec3d vMin,vMax;
|
||||
m_lstDebugEntityList[s]->GetRenderBBox(vMin,vMax);
|
||||
pRenderer->Draw3dBBox(vMin,vMax);
|
||||
|
||||
pRenderer->DrawBall(m_lstDebugEntityList[s]->GetPos(),0.1f);
|
||||
|
||||
pRenderer->ResetToDefault();
|
||||
}
|
||||
|
||||
m_lstDebugEntityList.Clear();
|
||||
}
|
||||
|
||||
void CObjManager::DrawObjSpritesSorted(list2<CStatObjInst*> *pList, float fMaxViewDist, int useBending)
|
||||
{
|
||||
#if 0
|
||||
static list2<CStatObjInst*>* arrSortedInstances[8192];
|
||||
{ // fill hash table
|
||||
const Vec3d & vCamPos = GetViewCamera().GetPos();
|
||||
const float rad2deg = 180.0f/gf_PI;
|
||||
const float far_tex_angle = (FAR_TEX_ANGLE>>1);
|
||||
|
||||
for( int i=0; i<pList->Count(); i++ )
|
||||
{
|
||||
CStatObjInst * o = pList->GetAt(i);
|
||||
CStatObj * pBody = m_lstStaticTypes[o->m_nObjectTypeID].GetStatObj();
|
||||
|
||||
const float DX = o->m_vPos.x - vCamPos.x;
|
||||
const float DY = o->m_vPos.y - vCamPos.y;
|
||||
int angle(int(rad2deg*atan2( DX, DY )+far_tex_angle));
|
||||
|
||||
while(angle<0) angle+=360;
|
||||
|
||||
assert(angle>=0 && angle/FAR_TEX_ANGLE<FAR_TEX_COUNT);
|
||||
|
||||
int tid = pBody->m_arrSpriteTexID[angle/FAR_TEX_ANGLE];
|
||||
|
||||
if(tid>=4096 && tid<8192)
|
||||
{
|
||||
if(!arrSortedInstances[tid])
|
||||
arrSortedInstances[tid] = new list2<CStatObjInst*>;
|
||||
|
||||
arrSortedInstances[tid]->Add(o);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"Error: CObjManager::DrawObjSpritesSorted: Texture id is out of range: %d", tid);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pList->Clear();
|
||||
|
||||
// render sorted by texture
|
||||
IRenderer * pRenderer = GetRenderer();
|
||||
pRenderer->ResetToDefault();
|
||||
pRenderer->EnableBlend(false);
|
||||
pRenderer->EnableAlphaTest(true,0.5f);
|
||||
pRenderer->SetEnviMode(R_MODE_MODULATE);
|
||||
pRenderer->EnableDepthWrites(true);
|
||||
pRenderer->SetCullMode(R_CULL_DISABLE);
|
||||
|
||||
Vec3d vWorldCol = GetSystem()->GetI3DEngine()->GetWorldColor();
|
||||
pRenderer->SetMaterialColor(vWorldCol.x, vWorldCol.y, vWorldCol.z, 1.f);
|
||||
|
||||
float max_view_dist = fMaxViewDist;//*0.8f;
|
||||
const Vec3d & vCamPos = GetViewCamera().GetPos();
|
||||
const float rad2deg = 180.0f/gf_PI;
|
||||
const float far_tex_angle = (FAR_TEX_ANGLE>>1);
|
||||
|
||||
static int nCurrBufId = 0;
|
||||
// nCurrBufId=0;
|
||||
|
||||
for(int tid=4096; tid<8192; tid++)
|
||||
if(arrSortedInstances[tid] && arrSortedInstances[tid]->Count())
|
||||
{
|
||||
#define MAX_BUFF_NUM 128
|
||||
#define MAX_VERTS_NUM 1024
|
||||
|
||||
static CVertexBuffer * arrVideoBuffers[MAX_BUFF_NUM];
|
||||
|
||||
if(!arrVideoBuffers[0])
|
||||
for(int i=0; i<MAX_BUFF_NUM; i++)
|
||||
arrVideoBuffers[i] = pRenderer->CreateBuffer(MAX_VERTS_NUM,VERTEX_FORMAT_P3F_TEX2F,"CompiledTreeSprites",true);
|
||||
|
||||
static SVertexStream Inds;
|
||||
if (!Inds.m_VData)
|
||||
pRenderer->CreateIndexBuffer(&Inds, NULL, MAX_VERTS_NUM*3/2);
|
||||
|
||||
// Lock the index buffer
|
||||
pRenderer->UpdateIndexBuffer(&Inds, NULL, 0, false);
|
||||
ushort *pInds = (ushort *)Inds.m_VData;
|
||||
|
||||
pRenderer->UpdateBuffer(arrVideoBuffers[nCurrBufId],0,0,true);
|
||||
|
||||
for(int i=0; i<arrSortedInstances[tid]->Count(); i++)
|
||||
{
|
||||
CStatObjInst * o = arrSortedInstances[tid]->GetAt(i);
|
||||
CStatObj * pBody = m_lstStaticTypes[o->m_nObjectTypeID].GetStatObj();
|
||||
|
||||
float max_dist = o->m_fMaxDist;
|
||||
|
||||
// note: move into sort by size
|
||||
if(max_dist>max_view_dist)
|
||||
max_dist=max_view_dist;
|
||||
|
||||
const float alpha = min(1.f,(1.f-(o->m_fDistance*m_fZoomFactor)/(max_dist))*8.f);
|
||||
const float brigh = /*0.6666f + 0.3333f*o->m_bBright*/CHAR_TO_FLOAT*o->m_ucBright;
|
||||
|
||||
const float DX = o->m_vPos.x - vCamPos.x;
|
||||
const float DY = o->m_vPos.y - vCamPos.y;
|
||||
|
||||
// pRenderer->SetMaterialColor(vWorldColor.x*brigh, vWorldColor.y*brigh, vWorldColor.z*brigh, alpha);
|
||||
|
||||
const float fSpriteScaleV = o->m_fScale*pBody->GetRadiusVert()*1.035f*alpha;
|
||||
const float fSpriteScaleH = o->m_fScale*pBody->GetRadiusHors()*m_fZoomFactor*1.050f*alpha;
|
||||
Vec3d vPos = o->m_vPos + pBody->GetCenter()*o->m_fScale;
|
||||
/*
|
||||
float fBending;
|
||||
if (useBending)
|
||||
fBending = (o->m_fCurrentBending)*pBody->m_fBending;
|
||||
else
|
||||
fBending = 0;
|
||||
*/
|
||||
struct_VERTEX_FORMAT_P3F_TEX2F * pVerts = (struct_VERTEX_FORMAT_P3F_TEX2F*)(arrVideoBuffers[nCurrBufId])->m_VS[VSF_GENERAL].m_VData;
|
||||
|
||||
assert(i*6 + 5 < (MAX_VERTS_NUM*3/2));
|
||||
assert(i*4 + 3 < MAX_VERTS_NUM);
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_TEX2F VertQuad[4];
|
||||
|
||||
float dy = DX*fSpriteScaleH/o->m_fDistance;
|
||||
float dx = DY*fSpriteScaleH/o->m_fDistance;
|
||||
float dz = fSpriteScaleV;
|
||||
|
||||
VertQuad[0].s = -1;
|
||||
VertQuad[0].t = 0;
|
||||
VertQuad[0].x = -dx+vPos.x; VertQuad[0].y = dy+vPos.y; VertQuad[0].z = -dz+vPos.z;
|
||||
VertQuad[1].s = 0;
|
||||
VertQuad[1].t = 0;
|
||||
VertQuad[1].x = dx+vPos.x; VertQuad[1].y = -dy+vPos.y; VertQuad[1].z = -dz+vPos.z;
|
||||
VertQuad[2].s = 0;
|
||||
VertQuad[2].t = 1;
|
||||
VertQuad[2].x = dx+vPos.x; VertQuad[2].y = -dy+vPos.y; VertQuad[2].z = dz+vPos.z;
|
||||
VertQuad[3].s = -1;
|
||||
VertQuad[3].t = 1;
|
||||
VertQuad[3].x = -dx+vPos.x; VertQuad[3].y = dy+vPos.y; VertQuad[3].z = dz+vPos.z;
|
||||
|
||||
memcpy(&pVerts[i*4], VertQuad, sizeof(VertQuad));
|
||||
pInds[i*6 + 0] = i*4 + 0;
|
||||
pInds[i*6 + 1] = i*4 + 1;
|
||||
pInds[i*6 + 2] = i*4 + 2;
|
||||
|
||||
pInds[i*6 + 3] = i*4 + 0;
|
||||
pInds[i*6 + 4] = i*4 + 2;
|
||||
pInds[i*6 + 5] = i*4 + 3;
|
||||
}
|
||||
|
||||
// Unlock the index buffer
|
||||
pRenderer->UpdateIndexBuffer(&Inds, NULL, 0, true);
|
||||
pRenderer->SetTexture(tid);
|
||||
pRenderer->DrawBuffer(arrVideoBuffers[nCurrBufId],&Inds,arrSortedInstances[tid]->Count()*6,0,R_PRIMV_TRIANGLES);
|
||||
|
||||
nCurrBufId++;
|
||||
if(nCurrBufId>=MAX_BUFF_NUM)
|
||||
nCurrBufId=0;
|
||||
|
||||
arrSortedInstances[tid]->Clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
22
Cry3DEngine/ObjManPhys.cpp
Normal file
22
Cry3DEngine/ObjManPhys.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjmanphys.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Physicalize static objects (trees, structures)
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
360
Cry3DEngine/ObjManShadows.cpp
Normal file
360
Cry3DEngine/ObjManShadows.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjmanshadows.cpp
|
||||
// Version: v1.00
|
||||
// Created: 2/6/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Shadow casters/reseivers relations
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "3dengine.h"
|
||||
#include <AABBSV.h>
|
||||
|
||||
#define MIN_SHADOW_CASTER_VIEW_DIST 16
|
||||
|
||||
void CObjManager::MakeShadowCastersListInArea(CBasicArea*pArea, IEntityRender * pReceiver, list2<IEntityRender*> * pEntList, int dwAllowedTypes, Vec3d vLightPos, float fLightRadius)
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
bool bCmpCasterReceiverDistances = !(GetRenderer()->GetFeatures() & (RFT_DEPTHMAPS | RFT_SHADOWMAP_SELFSHADOW));
|
||||
|
||||
Shadowvolume ResShadowVolume;
|
||||
{
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pReceiver->GetBBox(vBoxMin,vBoxMax);
|
||||
AABB aabbReceiver(vBoxMin,vBoxMax+Vec3d(0.01f,0.01f,0.01f));
|
||||
NAABB_SV::AABB_ReceiverShadowVolume(vLightPos, aabbReceiver, ResShadowVolume);//, min(fDistFromLsToCaster+pCaster->GetRenderRadius()*4, fLightRadius));
|
||||
}
|
||||
|
||||
float fDistFromLsToReceiver = GetDistance(vLightPos, pReceiver->GetPos());
|
||||
|
||||
int nStaticsAllowed = int(GetCVars()->e_shadow_maps_from_static_objects>0);
|
||||
for(int nStatic=0; nStatic<=nStaticsAllowed; nStatic++)
|
||||
{
|
||||
list2<struct IEntityRender*> * pList = &pArea->m_lstEntities[nStatic];
|
||||
if(nStatic && pArea->m_StaticEntitiesSorted && !(dwAllowedTypes&SMC_ALLOW_PASSIVE_SHADOWMAP_CASTERS))
|
||||
pList = &pArea->m_lstStaticShadowMapCasters;
|
||||
|
||||
for(int e=0; e<pList->Count(); e++)
|
||||
{
|
||||
IEntityRender * pCaster = (*pList)[e];
|
||||
|
||||
if (e+1 < pList->Count())
|
||||
{
|
||||
IEntityRender * pNext = (*pList)[e+1];
|
||||
cryPrefetchT0SSE(pNext);
|
||||
}
|
||||
|
||||
if(pCaster->m_fWSMaxViewDist<MIN_SHADOW_CASTER_VIEW_DIST)
|
||||
{
|
||||
if(!nStatic || !pArea->m_StaticEntitiesSorted)
|
||||
continue;
|
||||
else
|
||||
break; // break in sorted list
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
const char * szClass = pCaster->GetEntityClassName();
|
||||
const char * szName = pCaster->GetName();
|
||||
#endif // _DEBUG
|
||||
|
||||
int dwRndFlags = pCaster->GetRndFlags();
|
||||
|
||||
bool bTakeThisOne = false;
|
||||
{ // take only allowed active shadow casters
|
||||
if((pCaster->IsStatic() && (dwAllowedTypes & SMC_STATICS )) ||
|
||||
(!pCaster->IsStatic() && (dwAllowedTypes & SMC_DYNAMICS)) )
|
||||
{
|
||||
if(dwAllowedTypes&SMC_ALLOW_PASSIVE_SHADOWMAP_CASTERS)
|
||||
bTakeThisOne = true;
|
||||
else
|
||||
if(dwRndFlags & ERF_CASTSHADOWMAPS && pCaster->GetEntityRS()->pShadowMapInfo)
|
||||
{
|
||||
ShadowMapLightSource * pFrustumContainer = pCaster->GetShadowMapFrustumContainer();
|
||||
if( pFrustumContainer && pFrustumContainer->m_LightFrustums.Count() && pFrustumContainer->m_LightFrustums.Get(0)->pLs )
|
||||
bTakeThisOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bTakeThisOne && pCaster != pReceiver && !(dwRndFlags&ERF_HIDDEN) && (!pCaster->GetLight() || pCaster->GetContainer()))
|
||||
{
|
||||
float fDistFromLsToCaster = GetDistance(vLightPos, pCaster->GetPos());
|
||||
if(bCmpCasterReceiverDistances)
|
||||
if(fDistFromLsToReceiver < fDistFromLsToCaster)
|
||||
continue;
|
||||
|
||||
if(fDistFromLsToReceiver - fDistFromLsToCaster > pCaster->GetRenderRadius()*4+pReceiver->GetRenderRadius())
|
||||
continue;
|
||||
|
||||
// check if caster is in receiver frustum
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pCaster->GetBBox(vBoxMin,vBoxMax);
|
||||
AABB aabbCaster(vBoxMin,vBoxMax+Vec3d(0.01f,0.01f,0.01f));
|
||||
bool bIntersect = NAABB_SV::Is_AABB_In_ShadowVolume(ResShadowVolume, aabbCaster);
|
||||
if(bIntersect && pEntList->Find(pCaster)<0)
|
||||
pEntList->Add(pCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CObjManager::MakeShadowCastersList(IEntityRender * pReceiver, list2<IEntityRender*> * pEntList, int dwAllowedTypes, Vec3d vLightPos, float fLightRadius)
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
assert(vLightPos.len()>1); // world space pos required
|
||||
|
||||
pEntList->Clear();
|
||||
|
||||
if(pReceiver->m_pVisArea && pReceiver->IsEntityAreasVisible())
|
||||
MakeShadowCastersListInArea(pReceiver->m_pVisArea, pReceiver, pEntList, dwAllowedTypes, vLightPos, fLightRadius);
|
||||
else
|
||||
{ // make list of sectors around
|
||||
// find 2d bounds in sectors array
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pReceiver->GetBBox(vBoxMin,vBoxMax);
|
||||
|
||||
// get 2d bounds in sectors array
|
||||
int min_x = (int)(((vBoxMin.x - 16.f)/CTerrain::GetSectorSize()));
|
||||
int min_y = (int)(((vBoxMin.y - 16.f)/CTerrain::GetSectorSize()));
|
||||
int max_x = (int)(((vBoxMax.x + 16.f)/CTerrain::GetSectorSize()));
|
||||
int max_y = (int)(((vBoxMax.y + 16.f)/CTerrain::GetSectorSize()));
|
||||
|
||||
// limit bounds
|
||||
if(min_x<0) min_x=0; else if(min_x>=CTerrain::GetSectorsTableSize()) min_x=CTerrain::GetSectorsTableSize()-1;
|
||||
if(min_y<0) min_y=0; else if(min_y>=CTerrain::GetSectorsTableSize()) min_y=CTerrain::GetSectorsTableSize()-1;
|
||||
if(max_x<0) max_x=0; else if(max_x>=CTerrain::GetSectorsTableSize()) max_x=CTerrain::GetSectorsTableSize()-1;
|
||||
if(max_y<0) max_y=0; else if(max_y>=CTerrain::GetSectorsTableSize()) max_y=CTerrain::GetSectorsTableSize()-1;
|
||||
|
||||
m_lstTmpSectors_MELFP.Clear();
|
||||
m_lstTmpSectors_MELFP.Add(m_pTerrain->m_arrSecInfoTable[0][0]);
|
||||
for(int x=min_x; x<=max_x && x>=0 && x<=CTerrain::GetTerrainSize(); x++)
|
||||
for(int y=min_y; y<=max_y && y>=0 && y<=CTerrain::GetTerrainSize(); y++)
|
||||
{
|
||||
CSectorInfo * pSectorInfo = m_pTerrain->m_arrSecInfoTable[x][y];
|
||||
|
||||
// check if sector cast shadow to the receiver
|
||||
if(m_lstTmpSectors_MELFP.Find(pSectorInfo)<0 && pSectorInfo)
|
||||
{
|
||||
Shadowvolume sv;
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pReceiver->GetBBox(vBoxMin,vBoxMax);
|
||||
AABB aabbReceiver(vBoxMin,vBoxMax);
|
||||
AABB aabbCaster(pSectorInfo->m_vBoxMin,pSectorInfo->m_vBoxMax);
|
||||
aabbCaster.max.z += 0.01f;
|
||||
NAABB_SV::AABB_ShadowVolume(vLightPos, aabbCaster, sv, fLightRadius);
|
||||
bool bIntersect = NAABB_SV::Is_AABB_In_ShadowVolume(sv, aabbReceiver);
|
||||
if(bIntersect)
|
||||
m_lstTmpSectors_MELFP.Add(pSectorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// make list of entities
|
||||
for(int s=0; s<m_lstTmpSectors_MELFP.Count(); s++)
|
||||
MakeShadowCastersListInArea(m_lstTmpSectors_MELFP[s], pReceiver, pEntList, dwAllowedTypes, vLightPos, fLightRadius);
|
||||
}
|
||||
}
|
||||
|
||||
void CObjManager::MakeShadowMapInstancesList( IEntityRender * pReceiver, float obj_distance,
|
||||
list2<ShadowMapLightSourceInstance> * pLSourceInstances, int dwAllowedTypes, CDLight * pLight)
|
||||
{
|
||||
if(!GetCVars()->e_shadow_maps || obj_distance > pReceiver->GetRenderRadius()*32)
|
||||
return;
|
||||
|
||||
// get entities in area
|
||||
lstEntList_MLSMCIA.Clear();
|
||||
if(dwAllowedTypes)
|
||||
MakeShadowCastersList(pReceiver, &lstEntList_MLSMCIA, dwAllowedTypes, pLight->m_Origin, pLight->m_fRadius);
|
||||
lstEntList_MLSMCIA.Delete(pReceiver);
|
||||
|
||||
// add this entity if self shadowing allowed
|
||||
if( GetCVars()->e_shadow_maps_self_shadowing &&
|
||||
pReceiver->GetRndFlags() & ERF_SELFSHADOW &&
|
||||
GetRenderer()->GetFeatures() & (RFT_DEPTHMAPS | RFT_SHADOWMAP_SELFSHADOW))
|
||||
lstEntList_MLSMCIA.InsertBefore(pReceiver,0);
|
||||
|
||||
// make list of shadow casters
|
||||
for(int e=0; e<lstEntList_MLSMCIA.Count(); e++)
|
||||
{
|
||||
const char * szClass = lstEntList_MLSMCIA[e]->GetEntityClassName();
|
||||
const char * szName = lstEntList_MLSMCIA[e]->GetName();
|
||||
|
||||
if( !lstEntList_MLSMCIA[e]->GetShadowMapFrustumContainer() ||
|
||||
!lstEntList_MLSMCIA[e]->GetShadowMapFrustumContainer()->m_LightFrustums.Count() ||
|
||||
!(lstEntList_MLSMCIA[e]->GetRndFlags()&ERF_CASTSHADOWMAPS) )
|
||||
continue;
|
||||
|
||||
ShadowMapLightSourceInstance LightSourceInfo;
|
||||
LightSourceInfo.m_pLS = lstEntList_MLSMCIA[e]->GetShadowMapFrustumContainer();
|
||||
LightSourceInfo.m_vProjTranslation = lstEntList_MLSMCIA[e]->GetPos();
|
||||
LightSourceInfo.m_fProjScale = lstEntList_MLSMCIA[e]->GetScale();
|
||||
Vec3d vThisEntityPos = pReceiver->GetPos();
|
||||
LightSourceInfo.m_fDistance = GetDistance(vThisEntityPos,lstEntList_MLSMCIA[e]->GetPos()) - lstEntList_MLSMCIA[e]->GetRenderRadius()/3;
|
||||
LightSourceInfo.m_pReceiver = pReceiver;
|
||||
if(!LightSourceInfo.m_pLS->m_LightFrustums.Count())// || !LightSourceInfo.m_pLS->m_LightFrustums[0].depth_tex_id)
|
||||
continue;
|
||||
pLSourceInstances->Add(LightSourceInfo);
|
||||
}
|
||||
|
||||
// select only closest
|
||||
pLSourceInstances->SortByDistanceMember(true,1);
|
||||
while(pLSourceInstances->Count()>GetCVars()->e_shadow_maps_max_casters_per_object)
|
||||
pLSourceInstances->DeleteLast();
|
||||
}
|
||||
|
||||
ShadowMapFrustum * CObjManager::MakeEntityShadowFrustum(ShadowMapFrustum * pFrustum,
|
||||
ShadowMapLightSource * pLs, IEntityRender * pEnt, EShadowType nShadowType, int dwAllowedTypes)
|
||||
{
|
||||
Vec3d vMin,vMax;
|
||||
pEnt->GetBBox(vMin,vMax);
|
||||
|
||||
Vec3d visual_center = (vMin+vMax)*0.5f - pEnt->GetPos();
|
||||
float model_radius = GetDistance(vMax,vMin) * 0.5f;
|
||||
|
||||
float model_radiusXY = GetDistance(Vec3d(vMax.x,vMax.y,0),Vec3d(vMin.x,vMin.y,0)) * 0.5f;
|
||||
|
||||
pFrustum->target = visual_center;
|
||||
Vec3d dir = pFrustum->target - pLs->vSrcPos;
|
||||
|
||||
float dist = dir.Length();
|
||||
|
||||
pFrustum->ProjRatio = model_radiusXY/model_radius;
|
||||
if(pFrustum->ProjRatio>1.f)
|
||||
pFrustum->ProjRatio=1.f;
|
||||
|
||||
pFrustum->FOV = (float)RAD2DEG(cry_atanf((model_radius+0.25f)/dist))*1.9f;
|
||||
if(pFrustum->FOV>120.f)
|
||||
pFrustum->FOV=120.f;
|
||||
|
||||
pFrustum->min_dist = dist - (model_radius + ((dwAllowedTypes&SMC_ALLOW_PASSIVE_SHADOWMAP_CASTERS) ? 32 : 0));
|
||||
|
||||
if(pFrustum->min_dist<0.25)
|
||||
pFrustum->min_dist=0.25;
|
||||
|
||||
pFrustum->max_dist = dist + ((dwAllowedTypes&SMC_ALLOW_PASSIVE_SHADOWMAP_CASTERS) ? -0.75f : model_radius);
|
||||
|
||||
pFrustum->pLs = pLs;
|
||||
|
||||
pFrustum->shadow_type = nShadowType;
|
||||
|
||||
// make entities list
|
||||
if(pFrustum->pEntityList)
|
||||
pFrustum->pEntityList->Clear();
|
||||
else
|
||||
pFrustum->pEntityList = new list2<IEntityRender*>;
|
||||
|
||||
if(dwAllowedTypes)
|
||||
MakeShadowCastersList(pEnt, pFrustum->pEntityList, dwAllowedTypes, pLs->vSrcPos+pEnt->GetPos(), pLs->fRadius);
|
||||
else
|
||||
pFrustum->pEntityList->Add(pEnt);
|
||||
|
||||
return pFrustum;
|
||||
}
|
||||
|
||||
static int Cmp_Shadow_Size(const void* v1, const void* v2)
|
||||
{
|
||||
CStatObjInst* p1 = *((CStatObjInst**)(v1));
|
||||
CStatObjInst* p2 = *((CStatObjInst**)(v2));
|
||||
|
||||
if(p1->m_fScale > p2->m_fScale)
|
||||
return -1;
|
||||
else if(p1->m_fScale < p2->m_fScale)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cdecl CObjManager_Cmp_EntSize(const void* v1, const void* v2)
|
||||
{
|
||||
IEntityRender* p1 = *((IEntityRender**)(v1));
|
||||
IEntityRender* p2 = *((IEntityRender**)(v2));
|
||||
|
||||
if(p1->GetRenderRadius() > p2->GetRenderRadius())
|
||||
return -1;
|
||||
else if(p1->GetRenderRadius() < p2->GetRenderRadius())
|
||||
return 1;
|
||||
|
||||
return (p1>p2) ? 1 : -1;
|
||||
}
|
||||
|
||||
void CObjManager::DrawAllShadowsOnTheGroundInSector(list2<IEntityRender*> * pEntList)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Draw entity shadows
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
GetRenderer()->ResetToDefault();
|
||||
GetRenderer()->ClearDepthBuffer();
|
||||
GetRenderer()->ClearColorBuffer(Vec3d(1,1,1));
|
||||
GetRenderer()->SetClearColor(Vec3d(1,1,1));
|
||||
|
||||
// sort by size to draw small shadows last or skip them
|
||||
if(pEntList && pEntList->Count())
|
||||
qsort(&(*pEntList)[0], (*pEntList).Count(), sizeof((*pEntList)[0]), CObjManager_Cmp_EntSize);
|
||||
|
||||
GetRenderer()->EF_StartEf();
|
||||
int nRealCout=0;
|
||||
for( int i=0; i<pEntList->Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEnt = (*pEntList)[i];
|
||||
|
||||
if(!(pEnt->GetRndFlags() & ERF_HIDDEN))
|
||||
if(pEnt->GetRndFlags() & ERF_CASTSHADOWINTOLIGHTMAP)
|
||||
if(!pEnt->GetEntityVisArea())
|
||||
{
|
||||
assert(m_nRenderStackLevel == 0);
|
||||
pEnt->SetDrawFrame(-100,m_nRenderStackLevel);
|
||||
|
||||
int nFlags = pEnt->GetRndFlags();
|
||||
pEnt->SetRndFlags(nFlags|ERF_CASTSHADOWMAPS|ERF_RECVSHADOWMAPS);
|
||||
pEnt->SetRndFlags(ERF_CASTSHADOWINTOLIGHTMAP,false);
|
||||
|
||||
int nRealLightsNum = ((C3DEngine*)Get3DEngine())->GetRealLightsNum();
|
||||
assert(nRealLightsNum==1);
|
||||
RenderObject(pEnt,0,1,true,GetViewCamera(),NULL,0,0,false,pEnt->GetMaxViewDist());
|
||||
RenderEntitiesShadowMapsOnTerrain(true, 0);
|
||||
|
||||
// increase frame id to help shadow map menager in renderer
|
||||
unsigned short * pPtr2FrameID = (unsigned short *)GetRenderer()->EF_Query(EFQ_Pointer2FrameID);
|
||||
if(pPtr2FrameID)
|
||||
(*pPtr2FrameID)++;
|
||||
|
||||
pEnt->SetRndFlags(nFlags);
|
||||
|
||||
nRealCout++;
|
||||
if((GetRenderer()->GetType() == R_GL_RENDERER) && nRealCout>=64) // maximum number of shadow maps in frame is limited in ogl to MAX_DYNAMIC_SHADOW_MAPS_COUNT
|
||||
break;
|
||||
}
|
||||
}
|
||||
GetRenderer()->EF_EndEf3D(SHDF_SORT);
|
||||
|
||||
// free shadow pass leafbuffers
|
||||
for( int i=0; i<pEntList->Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEnt = (*pEntList)[i];
|
||||
IEntityRenderState * pEntRendState = pEnt->m_pEntityRenderState;
|
||||
if(pEntRendState && pEntRendState->pShadowMapInfo && pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList)
|
||||
{
|
||||
for(int i=0; i<pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList->Count(); i++)
|
||||
{
|
||||
if(pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList->GetAt(i))
|
||||
{
|
||||
GetRenderer()->DeleteLeafBuffer(pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList->GetAt(i));
|
||||
pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList->GetAt(i)=0;
|
||||
}
|
||||
}
|
||||
delete pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList;
|
||||
pEntRendState->pShadowMapInfo->pShadowMapLeafBuffersList=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
120
Cry3DEngine/ObjManStreaming.cpp
Normal file
120
Cry3DEngine/ObjManStreaming.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjman.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Loading trees, buildings, ragister/unregister entities for rendering
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3DEngine.h"
|
||||
#include "meshidx.h"
|
||||
#include "watervolumes.h"
|
||||
#include "brush.h"
|
||||
#include "LMCompStructures.h"
|
||||
|
||||
void CObjManager::PreloadNearObjects()
|
||||
{
|
||||
// if(!GetCVars()->e_stream_cgf)
|
||||
return;
|
||||
|
||||
CVisAreaManager * pVisAreaManager = GetVisAreaManager();
|
||||
// CVisArea * pVisArea = pVisAreaManager->m_pCurArea ? pVisAreaManager->m_pCurArea : pVisAreaManager->m_pCurPortal;
|
||||
if(CStatObj::m_fStreamingTimePerFrame<CGF_STREAMING_MAX_TIME_PER_FRAME)// && pVisArea)
|
||||
{ // mark this and neighbor sectors
|
||||
/* pVisArea->MarkForStreaming();
|
||||
CVisArea * areaArray[8]={0,0,0,0,0,0,0,0};
|
||||
int nCount = pVisArea->GetVisAreaConnections((IVisArea **)&areaArray,8);
|
||||
for(int n=0; n<nCount; n++)
|
||||
areaArray[n]->MarkForStreaming();
|
||||
*/
|
||||
// load marked objects
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
if((*it)->m_bUseStreaming && !(*it)->GetLeafBuffer() && (*it)->m_nMarkedForStreamingFrameId > GetFrameID()+10)
|
||||
{ // streaming
|
||||
CStatObj::m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime();
|
||||
bool bRes = (*it)->Load((*it)->m_szFileName, (*it)->m_szGeomName[0] ? (*it)->m_szGeomName : 0,
|
||||
(*it)->m_eVertsSharing, (*it)->m_bLoadAdditinalInfo, (*it)->m_bKeepInLocalSpace, false);
|
||||
(*it)->m_bUseStreaming=true;
|
||||
CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime();
|
||||
}
|
||||
|
||||
if(CStatObj::m_fStreamingTimePerFrame>CGF_STREAMING_MAX_TIME_PER_FRAME)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CObjManager::CheckUnload()
|
||||
{
|
||||
if(GetCVars()->e_stream_cgf)
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
CStatObj * pStatObj = (*it);
|
||||
if(pStatObj->m_bUseStreaming && pStatObj->GetLeafBuffer() &&
|
||||
max(pStatObj->m_nLastRendFrameId, pStatObj->m_nMarkedForStreamingFrameId) < GetFrameID()-100)
|
||||
{
|
||||
int p;
|
||||
for(p=0; p<2; p++)
|
||||
{ // check is phys geometry still in use
|
||||
phys_geometry * pPhysGeom = pStatObj->GetPhysGeom(p);
|
||||
if(pPhysGeom && pPhysGeom->nRefCount>1)
|
||||
break;
|
||||
}
|
||||
|
||||
if(p==2)
|
||||
{
|
||||
pStatObj->ShutDown();
|
||||
pStatObj->Init();
|
||||
GetLog()->Log("Unloaded: %s", pStatObj->m_szFileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(GetFrameID()%32==0)
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
if((*it)->GetLeafBuffer() && (*it)->GetShadowVolume())
|
||||
(*it)->GetShadowVolume()->CheckUnload();
|
||||
}
|
||||
}
|
||||
|
||||
void CObjManager::GetObjectsStreamingStatus(int & nReady, int & nTotalInStreaming, int & nTotal)
|
||||
{
|
||||
nReady=nTotalInStreaming=nTotal=0;
|
||||
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
|
||||
{
|
||||
nTotal++;
|
||||
if((*it)->m_bUseStreaming)
|
||||
{
|
||||
nTotalInStreaming++;
|
||||
if((*it)->GetLeafBuffer())
|
||||
{
|
||||
CStatObj * p = (*it);
|
||||
nReady++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CStatObj * p = (*it);
|
||||
p=p;
|
||||
p->m_szFileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
395
Cry3DEngine/ParticleEffect.cpp
Normal file
395
Cry3DEngine/ParticleEffect.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: particleeffect.cpp
|
||||
// Version: v1.00
|
||||
// Created: 10/7/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ParticleEffect.h"
|
||||
#include "ParticleEmitter.h"
|
||||
#include "PartMan.h"
|
||||
#include "3DEngine.h"
|
||||
#include "ISound.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CParticleEffect::CParticleEffect( CPartManager *pPartManager )
|
||||
{
|
||||
assert( pPartManager );
|
||||
m_pPartManager = pPartManager;
|
||||
m_bLoaded = false;
|
||||
m_bEnabled = true;
|
||||
|
||||
m_soundVolume = 100;
|
||||
m_soundMinRadius = 1;
|
||||
m_soundMaxRadius = 10;
|
||||
m_bSoundLoop = true;
|
||||
m_bOnEverySpawn = false;
|
||||
|
||||
m_bAnimatedTexture[0] = false;
|
||||
m_bAnimatedTexture[1] = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CParticleEffect::~CParticleEffect()
|
||||
{
|
||||
UnloadResources();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetName( const char *sName )
|
||||
{
|
||||
m_pPartManager->RenameEffect( this,sName );
|
||||
|
||||
m_name = sName;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetTexture( int process,const char *s )
|
||||
{
|
||||
if (m_texture[process] != s)
|
||||
{
|
||||
UnloadResources(false);
|
||||
m_texture[process] = s;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetGeometry( int process,const char *s )
|
||||
{
|
||||
if (m_geometry[process] != s)
|
||||
{
|
||||
UnloadResources(false);
|
||||
m_geometry[process] = s;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CParticleEffect::GetChildCount() const
|
||||
{
|
||||
return (int)m_childs.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEffect* CParticleEffect::GetChild( int index ) const
|
||||
{
|
||||
assert( index >= 0 && index < (int)m_childs.size() );
|
||||
return m_childs[index];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::AddChild( IParticleEffect *pEffect )
|
||||
{
|
||||
assert( pEffect );
|
||||
m_childs.push_back(pEffect);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::RemoveChild( IParticleEffect *pEffect )
|
||||
{
|
||||
assert( pEffect );
|
||||
stl::find_and_erase( m_childs,pEffect );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::ClearChilds()
|
||||
{
|
||||
m_childs.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::InsertChild( int slot,IParticleEffect *pEffect )
|
||||
{
|
||||
if (slot < 0)
|
||||
slot = 0;
|
||||
if (slot > (int)m_childs.size())
|
||||
slot = (int)m_childs.size();
|
||||
|
||||
assert( pEffect );
|
||||
m_childs.insert( m_childs.begin() + slot,pEffect );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CParticleEffect::FindChild( IParticleEffect *pEffect ) const
|
||||
{
|
||||
for (int i = 0; i < (int)m_childs.size(); i++)
|
||||
{
|
||||
if (m_childs[i] == pEffect)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::LoadResources( bool bRecursive )
|
||||
{
|
||||
if (m_bLoaded)
|
||||
return;
|
||||
m_bLoaded = true;
|
||||
|
||||
for (int i = 0; i < NUM_PARTICLE_PROCESSES; i++)
|
||||
{
|
||||
if (!m_material[i].empty() && !m_pMaterials[i])
|
||||
AssignMaterial( i );
|
||||
|
||||
bool bNeedAnimatedTex = m_particleParams[i].nTexAnimFramesCount > 0;
|
||||
// First unload what is loaded.
|
||||
if (m_particleParams[i].nTexId != 0)
|
||||
{
|
||||
GetRenderer()->RemoveTexture( m_particleParams[i].nTexId );
|
||||
m_particleParams[i].nTexId = 0;
|
||||
if(m_particleParams[i].pAnimTex)
|
||||
GetRenderer()->RemoveAnimatedTexture(m_particleParams[i].pAnimTex);
|
||||
m_particleParams[i].pAnimTex = 0;
|
||||
}
|
||||
if (m_particleParams[i].pStatObj)
|
||||
{
|
||||
Get3DEngine()->ReleaseObject( m_particleParams[i].pStatObj );
|
||||
m_particleParams[i].pStatObj = 0;
|
||||
}
|
||||
|
||||
// Load textures.
|
||||
if (!m_texture[i].empty())
|
||||
{
|
||||
if (bNeedAnimatedTex)
|
||||
{
|
||||
int texid = GetRenderer()->LoadAnimatedTexture( m_texture[i].c_str(),m_particleParams[i].nTexAnimFramesCount );
|
||||
m_particleParams[i].nTexId = texid;
|
||||
m_particleParams[i].pAnimTex = GetRenderer()->GetAnimTexInfoFromId(texid);
|
||||
if(!m_particleParams[i].pAnimTex)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"ParticleEffect %s, Use Invalid Animated Texture Id %d",m_name.c_str(),texid );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(NULL_RENDERER)
|
||||
m_particleParams[i].nTexId = 0;
|
||||
#else
|
||||
m_particleParams[i].nTexId = GetRenderer()->LoadTexture( m_texture[i].c_str() );
|
||||
#endif
|
||||
m_particleParams[i].pAnimTex = 0;
|
||||
}
|
||||
m_bAnimatedTexture[i] = bNeedAnimatedTex;
|
||||
}
|
||||
// Load geometry.
|
||||
if (!m_geometry[i].empty())
|
||||
{
|
||||
m_particleParams[i].pStatObj = Get3DEngine()->MakeObject( m_geometry[i].c_str() );
|
||||
}
|
||||
}
|
||||
if (bRecursive)
|
||||
{
|
||||
for (int i = 0; i < (int)m_childs.size(); i++)
|
||||
{
|
||||
IParticleEffect *pChild = m_childs[i];
|
||||
((CParticleEffect*)pChild)->LoadResources( bRecursive );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::UnloadResources( bool bRecursive )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
return;
|
||||
m_bLoaded = false;
|
||||
|
||||
for (int i = 0; i < NUM_PARTICLE_PROCESSES; i++)
|
||||
{
|
||||
if (m_particleParams[i].nTexId != 0)
|
||||
{
|
||||
GetRenderer()->RemoveTexture( m_particleParams[i].nTexId );
|
||||
m_particleParams[i].nTexId = 0;
|
||||
if(m_particleParams[i].pAnimTex)
|
||||
GetRenderer()->RemoveAnimatedTexture(m_particleParams[i].pAnimTex);
|
||||
m_particleParams[i].pAnimTex = 0;
|
||||
}
|
||||
if (m_particleParams[i].pStatObj)
|
||||
{
|
||||
Get3DEngine()->ReleaseObject( m_particleParams[i].pStatObj );
|
||||
m_particleParams[i].pStatObj = 0;
|
||||
}
|
||||
}
|
||||
if (bRecursive)
|
||||
{
|
||||
for (int i = 0; i < (int)m_childs.size(); i++)
|
||||
{
|
||||
IParticleEffect *pChild = m_childs[i];
|
||||
((CParticleEffect*)pChild)->UnloadResources( bRecursive );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetSoundParams( const SoundParams ¶ms )
|
||||
{
|
||||
m_sound = params.szSound;
|
||||
m_soundVolume = params.volume;
|
||||
m_soundMinRadius = params.minRadius;
|
||||
m_soundMaxRadius = params.maxRadius;
|
||||
m_bSoundLoop = params.bLoop;
|
||||
m_bOnEverySpawn = params.bOnEverySpawn;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::GetSoundParams( SoundParams ¶ms ) const
|
||||
{
|
||||
params.szSound = m_sound.c_str();
|
||||
params.volume = m_soundVolume;
|
||||
params.minRadius = m_soundMinRadius;
|
||||
params.maxRadius = m_soundMaxRadius;
|
||||
params.bLoop = m_bSoundLoop;
|
||||
params.bOnEverySpawn = m_bOnEverySpawn;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::Spawn( const Vec3 &pos,const Vec3 &dir,float fScale )
|
||||
{
|
||||
if (m_bEnabled)
|
||||
{
|
||||
// Spawn emitter for this particle.
|
||||
if (!IsResourcesLoaded())
|
||||
{
|
||||
LoadResources();
|
||||
}
|
||||
if (m_particleParams[1].nCount > 0)
|
||||
{
|
||||
m_particleParams[0].pChild = &m_particleParams[1];
|
||||
}
|
||||
else
|
||||
m_particleParams[0].pChild = 0;
|
||||
|
||||
m_particleParams[0].pEntity = 0;
|
||||
m_particleParams[1].pEntity = 0;
|
||||
|
||||
// Spawn particle system emitter.
|
||||
CParticleEmitter *pEmitter = new CParticleEmitter(m_pPartManager);
|
||||
pEmitter->m_bPermament = false;
|
||||
pEmitter->AssignEffect( this,false );
|
||||
pEmitter->SetPos( pos,dir,fScale );
|
||||
}
|
||||
// Spawn child effects.
|
||||
for (int i = 0; i < (int)m_childs.size(); i++)
|
||||
{
|
||||
m_childs[i]->Spawn( pos,dir,fScale );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CParticleEffect::PrepareSpawn( const Vec3 &pos )
|
||||
{
|
||||
if (!m_bEnabled)
|
||||
return false;
|
||||
|
||||
if (!IsResourcesLoaded())
|
||||
{
|
||||
LoadResources();
|
||||
}
|
||||
|
||||
/*
|
||||
// Play sound if not looped.
|
||||
if (!m_bSoundLoop && !m_sound.empty())
|
||||
{
|
||||
ISound *pSound = GetSystem()->GetISoundSystem()->LoadSound( m_sound.c_str(),FLAG_SOUND_3D );
|
||||
if (pSound)
|
||||
{
|
||||
pSound->SetVolume( (int)m_soundVolume );
|
||||
pSound->SetMinMaxDistance( m_soundMinRadius,m_soundMaxRadius );
|
||||
pSound->SetPosition(pos);
|
||||
pSound->Play();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Init child process pointer.
|
||||
if (m_particleParams[1].nCount > 0)
|
||||
m_particleParams[0].pChild = &m_particleParams[1];
|
||||
else
|
||||
m_particleParams[0].pChild = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CParticleEffect::IsResourcesLoaded()
|
||||
{
|
||||
bool bAnimatedTex0 = m_particleParams[0].nTexAnimFramesCount > 0;
|
||||
bool bAnimatedTex1 = m_particleParams[1].nTexAnimFramesCount > 0;
|
||||
if (bAnimatedTex0 != m_bAnimatedTexture[0] || bAnimatedTex1 != m_bAnimatedTexture[1])
|
||||
{
|
||||
UnloadResources(false);
|
||||
}
|
||||
|
||||
return m_bLoaded;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetMaterial( int process,IMatInfo *pMaterial )
|
||||
{
|
||||
assert( process >= 0 && process < NUM_PARTICLE_PROCESSES );
|
||||
m_pMaterials[process] = pMaterial;
|
||||
if (pMaterial)
|
||||
pMaterial->SetFlags(pMaterial->GetFlags()|MIF_WASUSED);
|
||||
m_particleParams[process].pMaterial = pMaterial;
|
||||
if (pMaterial)
|
||||
{
|
||||
m_material[process] = pMaterial->GetName();
|
||||
}
|
||||
else
|
||||
m_material[process] = "";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::SetMaterialName( int process,const char *sMtlName )
|
||||
{
|
||||
assert( process >= 0 && process < NUM_PARTICLE_PROCESSES );
|
||||
m_material[process] = sMtlName;
|
||||
AssignMaterial( process );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* CParticleEffect::GetMaterialName( int process ) const
|
||||
{
|
||||
assert( process >= 0 && process < NUM_PARTICLE_PROCESSES );
|
||||
return m_material[process].c_str();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEffect::AssignMaterial( int process )
|
||||
{
|
||||
assert( process >= 0 && process < NUM_PARTICLE_PROCESSES );
|
||||
IMatInfo *pMtl = 0;
|
||||
if (m_material[process].empty())
|
||||
{
|
||||
pMtl = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMtl = Get3DEngine()->FindMaterial( m_material[process].c_str() );
|
||||
if (!pMtl)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"ParticleEffect %s material assign failed, Material %s not found",m_name.c_str(),m_material[process].c_str() );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(pMtl)
|
||||
pMtl->SetFlags(pMtl->GetFlags()|MIF_WASUSED);
|
||||
m_pMaterials[process] = pMtl;
|
||||
m_particleParams[process].pMaterial = pMtl;
|
||||
}
|
||||
143
Cry3DEngine/ParticleEffect.h
Normal file
143
Cry3DEngine/ParticleEffect.h
Normal file
@@ -0,0 +1,143 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: ParticleEffect.h
|
||||
// Version: v1.00
|
||||
// Created: 10/7/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __particleeffect_h__
|
||||
#define __particleeffect_h__
|
||||
#pragma once
|
||||
|
||||
#include "I3DEngine.h"
|
||||
|
||||
class CPartManager;
|
||||
class CParticleEmitter;
|
||||
|
||||
/*! CParticleEffect implements IParticleEffect interface and contain all components necesarry to
|
||||
to create particluar effect with particles.
|
||||
*/
|
||||
class CParticleEffect : public IParticleEffect, public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CParticleEffect( CPartManager *pPartManager );
|
||||
~CParticleEffect();
|
||||
|
||||
virtual void Spawn( const Vec3 &pos,const Vec3 &dir,float fScale=1.0f );
|
||||
|
||||
virtual void SetName( const char *sName );
|
||||
virtual const char* GetName() { return m_name.c_str(); };
|
||||
|
||||
virtual void SetEnabled( bool bEnabled ) { m_bEnabled = bEnabled; };
|
||||
virtual bool IsEnabled() const { return m_bEnabled; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Child particle systems.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual int GetChildCount() const;
|
||||
//! Get sub Particles child by index.
|
||||
virtual IParticleEffect* GetChild( int index ) const;
|
||||
//! Adds a new sub Particles.
|
||||
virtual void AddChild( IParticleEffect *pEffect );
|
||||
//! Remove specific sub Particles
|
||||
virtual void RemoveChild( IParticleEffect *pEffect );
|
||||
//! Remove all sub Particles.
|
||||
virtual void ClearChilds();
|
||||
//! Insert sub particles in between other child particles.
|
||||
virtual void InsertChild( int slot,IParticleEffect *pEffect );
|
||||
//! Find slot where sub Particles stored.
|
||||
//! @retun slot index if Particles found, -1 if Particles not found.
|
||||
virtual int FindChild( IParticleEffect *pEffect ) const;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ParticleParams& GetParticleParams( int process ) { return m_particleParams[process]; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//virtual EffectParams& GetEffectParams() { return m_effectParams; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Texture and Geometry.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* GetTexture( int process ) const { return m_texture[process].c_str(); };
|
||||
const char* GetGeometry( int process ) const { return m_geometry[process].c_str(); };
|
||||
void SetTexture( int process,const char *s );
|
||||
void SetGeometry( int process,const char *s );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Materials
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetMaterial( int process,IMatInfo *pMaterial );
|
||||
IMatInfo* GetMaterial( int process ) const { return m_pMaterials[process]; };
|
||||
virtual void SetMaterialName( int process,const char *sMtlName );
|
||||
virtual const char* GetMaterialName( int process ) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Load resources, required by this particle effect (Textures and geometry).
|
||||
void LoadResources( bool bRecursive = true );
|
||||
//! Unload resources, required by this particle effect (Textures and geometry).
|
||||
void UnloadResources( bool bRecursive = true );
|
||||
//! Check if resources are loaded.
|
||||
bool IsResourcesLoaded();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sound parameters.
|
||||
//! Set Sound parameters for this particle effect.
|
||||
virtual void SetSoundParams( const SoundParams ¶ms );
|
||||
//! Get Sound parameters for this particle effect.
|
||||
virtual void GetSoundParams( SoundParams ¶ms ) const;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Called to initialize effect just before particles spawned..
|
||||
//! @return true if can spawn, false if cannot spawn this effect.
|
||||
bool PrepareSpawn( const Vec3 &pos );
|
||||
|
||||
private:
|
||||
void AssignMaterial( int process );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
String m_name;
|
||||
|
||||
//! When enabled this particle system will be spawned.
|
||||
bool m_bEnabled;
|
||||
//! Indicated whenever this effect was already loaded.
|
||||
mutable bool m_bLoaded;
|
||||
|
||||
//! Particle primary and child system spawning parameters.
|
||||
ParticleParams m_particleParams[NUM_PARTICLE_PROCESSES];
|
||||
String m_texture[NUM_PARTICLE_PROCESSES];
|
||||
String m_geometry[NUM_PARTICLE_PROCESSES];
|
||||
String m_material[NUM_PARTICLE_PROCESSES];
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Materials.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
_smart_ptr<IMatInfo> m_pMaterials[NUM_PARTICLE_PROCESSES];
|
||||
|
||||
bool m_bAnimatedTexture[NUM_PARTICLE_PROCESSES];
|
||||
|
||||
//EffectParams m_effectParams;
|
||||
|
||||
//! Array of sub materials.
|
||||
std::vector<IParticleEffect_AutoPtr> m_childs;
|
||||
|
||||
//! Creating particle manager.
|
||||
CPartManager* m_pPartManager;
|
||||
|
||||
//! Effect's sound parameters.
|
||||
String m_sound;
|
||||
float m_soundVolume;
|
||||
float m_soundMinRadius;
|
||||
float m_soundMaxRadius;
|
||||
bool m_bSoundLoop;
|
||||
bool m_bOnEverySpawn;
|
||||
};
|
||||
|
||||
#endif //__particleeffect_h__
|
||||
403
Cry3DEngine/ParticleEmitter.cpp
Normal file
403
Cry3DEngine/ParticleEmitter.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: particleemitter.cpp
|
||||
// Version: v1.00
|
||||
// Created: 18/7/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "ParticleEmitter.h"
|
||||
#include "partman.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CParticleEmitter::~CParticleEmitter()
|
||||
{
|
||||
if (m_bActive)
|
||||
OnActivate(false);
|
||||
ReleaseParams();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::ReleaseParams()
|
||||
{
|
||||
if (m_pParams && m_pParams->pStatObj)
|
||||
m_pParams->pStatObj->UnregisterUser();
|
||||
if (m_pChildParams && m_pChildParams->pStatObj)
|
||||
m_pChildParams->pStatObj->UnregisterUser();
|
||||
|
||||
if (m_pParams && m_bOwnParams)
|
||||
{
|
||||
delete m_pParams;
|
||||
}
|
||||
if (m_pChildParams && m_bOwnParams)
|
||||
{
|
||||
delete m_pChildParams;
|
||||
}
|
||||
|
||||
m_pParams = 0;
|
||||
m_pChildParams = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetParams( const ParticleParams ¶ms )
|
||||
{
|
||||
ReleaseParams();
|
||||
|
||||
m_bOwnParams = true;
|
||||
m_pParams = new ParticleParams;
|
||||
|
||||
float fCurTime = m_pPartManager->GetParticlesTime();
|
||||
m_startTime = fCurTime + params.fSpawnDelay.GetVariantValue();
|
||||
SetLifeTime(params.fEmitterLifeTime.GetVariantValue());
|
||||
m_spawnPeriod = params.fSpawnPeriod;
|
||||
m_lastActiveTime = m_startTime;
|
||||
m_lastSpawnTime = -100000.0f; // Force to spawn first time.
|
||||
|
||||
*m_pParams = params;
|
||||
m_pParams->pChild = 0;
|
||||
if (params.pChild != NULL && params.pChild->nCount > 0)
|
||||
{
|
||||
m_pChildParams = new ParticleParams;
|
||||
m_pParams->pChild = m_pChildParams;
|
||||
*m_pChildParams = *params.pChild;
|
||||
}
|
||||
m_pMaterial = params.pMaterial;
|
||||
m_pSpawnerEntity = params.pEntity;
|
||||
m_pos = params.vPosition;
|
||||
m_dir = params.vDirection;
|
||||
m_bbox.min = m_bbox.max = m_pos;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Keep object from suddenly deleting.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_pParams && m_pParams->pStatObj)
|
||||
m_pParams->pStatObj->RegisterUser();
|
||||
if (m_pChildParams && m_pChildParams->pStatObj)
|
||||
m_pChildParams->pStatObj->RegisterUser();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InitTexture( m_pParams );
|
||||
if (m_pChildParams)
|
||||
InitTexture( m_pChildParams );
|
||||
|
||||
CalculateWaterLevel();
|
||||
}
|
||||
|
||||
void CParticleEmitter::InitTexture( ParticleParams *pParams )
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Initialize texure ids.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (pParams->nTexAnimFramesCount>1 && pParams->nTexId)
|
||||
{
|
||||
AnimTexInfo *p = Cry3DEngineBase::GetRenderer()->GetAnimTexInfoFromId(pParams->nTexId);
|
||||
if(!p)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Cry3DEngineBase::Warning( 0,0,"Invalid Animated Texture Id %d for Particles",pParams->nTexId );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
pParams->pAnimTex = p;
|
||||
}
|
||||
else if(!pParams->nTexId && !pParams->pStatObj)
|
||||
{
|
||||
pParams->nTexId = m_pPartManager->GetGlowTexID();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetEffect( IParticleEffect *pEffect )
|
||||
{
|
||||
AssignEffect( pEffect,true );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::AssignEffect( IParticleEffect *pEffect,bool bChildEffects )
|
||||
{
|
||||
ReleaseParams();
|
||||
m_bOwnParams = false;
|
||||
|
||||
m_pEffect = pEffect;
|
||||
m_pParams = &m_pEffect->GetParticleParams(0);
|
||||
ParticleParams& childParams = m_pEffect->GetParticleParams(1);
|
||||
|
||||
float fCurTime = m_pPartManager->GetParticlesTime();
|
||||
m_startTime = fCurTime + m_pParams->fSpawnDelay.GetVariantValue();
|
||||
SetLifeTime(m_pParams->fEmitterLifeTime.GetVariantValue());
|
||||
m_spawnPeriod = m_pParams->fSpawnPeriod;
|
||||
m_lastActiveTime = m_startTime;
|
||||
m_lastSpawnTime = -100000.0f; // Force to spawn first time.
|
||||
|
||||
if (m_pParams->pChild)
|
||||
{
|
||||
m_pChildParams = m_pParams->pChild;
|
||||
}
|
||||
else if (childParams.nCount > 0)
|
||||
{
|
||||
m_pChildParams = &childParams;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Keep object from suddenly deleting.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_pParams && m_pParams->pStatObj)
|
||||
m_pParams->pStatObj->RegisterUser();
|
||||
if (m_pChildParams && m_pChildParams->pStatObj)
|
||||
m_pChildParams->pStatObj->RegisterUser();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Not needed. m_pMaterial = m_pParams->pMaterial;
|
||||
m_pSpawnerEntity = m_pParams->pEntity;
|
||||
m_pos = m_pParams->vPosition;
|
||||
m_dir = m_pParams->vDirection;
|
||||
m_bbox.min = m_bbox.max = m_pos;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Play looped sound for this particle emitter.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Create child effects
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (bChildEffects && pEffect->GetChildCount() > 0)
|
||||
{
|
||||
for (int i = 0; i < pEffect->GetChildCount(); i++)
|
||||
{
|
||||
// Create child emitter.
|
||||
CParticleEmitter *pEmitter = new CParticleEmitter(m_pPartManager);
|
||||
pEmitter->m_bChildEmitter = true;
|
||||
pEmitter->m_bPermament = true;
|
||||
m_childEmitters.push_back( pEmitter );
|
||||
CParticleEffect *pChildEffect = (CParticleEffect*)pEffect->GetChild(i);
|
||||
pEmitter->SetEffect(pChildEffect);
|
||||
pEmitter->m_bbox.min = pEmitter->m_bbox.max = m_pos;
|
||||
// If uncommented Sounds of child emitters not playing then..
|
||||
// pEmitter->m_bActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::UpdateChildSpawnTimes( float fCurrTime )
|
||||
{
|
||||
for (int i = 0; i < (int)m_childEmitters.size(); i++)
|
||||
{
|
||||
CParticleEmitter *pEmitter = m_childEmitters[i];
|
||||
if (pEmitter && pEmitter->m_pParams)
|
||||
{
|
||||
pEmitter->m_bActiveChild = true;
|
||||
pEmitter->m_startTime = fCurrTime + pEmitter->m_pParams->fSpawnDelay.GetVariantValue();
|
||||
pEmitter->SetLifeTime(pEmitter->m_pParams->fEmitterLifeTime.GetVariantValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const ParticleParams& CParticleEmitter::GetParams() const
|
||||
{
|
||||
return *m_pParams;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetPos( const Vec3 &vPos,const Vec3 &vDir,float fScale )
|
||||
{
|
||||
bool bPosChanged = false;
|
||||
if (m_pos != vPos)
|
||||
bPosChanged = true;
|
||||
m_pos = vPos;
|
||||
m_dir = vDir;
|
||||
m_fScale = fScale;
|
||||
m_lastActiveTime = m_pPartManager->GetParticlesTime();
|
||||
|
||||
if (bPosChanged)
|
||||
{
|
||||
if (!m_bActive)
|
||||
{
|
||||
m_bbox.min = vPos;
|
||||
m_bbox.max = vPos;
|
||||
}
|
||||
|
||||
if (m_pSound)
|
||||
{
|
||||
// Update sound position.
|
||||
m_pSound->SetPosition( m_pos + m_pParams->vPositionOffset );
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)m_childEmitters.size(); i++)
|
||||
{
|
||||
CParticleEmitter *pEmitter = m_childEmitters[i];
|
||||
if (pEmitter)
|
||||
{
|
||||
pEmitter->SetPos(vPos,vDir,fScale);
|
||||
}
|
||||
}
|
||||
|
||||
CalculateWaterLevel();
|
||||
}
|
||||
|
||||
if (!m_bChildEmitter)
|
||||
{
|
||||
// Make sure this emitter is active.
|
||||
m_pPartManager->ActivateEmitter( this );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetSpawnPeriod( float fSpawnPeriod )
|
||||
{
|
||||
m_spawnPeriod = fSpawnPeriod;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetLifeTime( float fLifeTime )
|
||||
{
|
||||
m_endTime = m_startTime + max(fLifeTime,0);
|
||||
m_bUseEndTime=true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetUnlimitedLife()
|
||||
{
|
||||
m_bUseEndTime=false; // Unlimited life time.
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetEntity( IEntityRender *pEntity )
|
||||
{
|
||||
m_pSpawnerEntity = pEntity;
|
||||
|
||||
CalculateWaterLevel();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::SetMaterial( IMatInfo *pMaterial )
|
||||
{
|
||||
m_pMaterial = pMaterial;
|
||||
m_pShader = NULL;
|
||||
if (m_pMaterial)
|
||||
{
|
||||
IShader *pContainerShader = m_pMaterial->GetShaderItem().m_pShader;
|
||||
m_pShader = pContainerShader->GetTemplate(-1);
|
||||
}
|
||||
|
||||
if(m_pMaterial)
|
||||
m_pMaterial->SetFlags(m_pMaterial->GetFlags()|MIF_WASUSED);
|
||||
}
|
||||
|
||||
void CParticleEmitter::CalculateWaterLevel()
|
||||
{
|
||||
// remember water level to avoid calculating it for each particle
|
||||
if(m_pSpawnerEntity)
|
||||
m_fWaterLevel = Cry3DEngineBase::Get3DEngine()->GetWaterLevel(m_pSpawnerEntity);
|
||||
else
|
||||
m_fWaterLevel = Cry3DEngineBase::Get3DEngine()->GetWaterLevel(&m_pos);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::OnActivate( bool bActive )
|
||||
{
|
||||
if (bActive == m_bActive)
|
||||
return;
|
||||
|
||||
m_bActive = bActive;
|
||||
if (bActive)
|
||||
{
|
||||
// Effect is activated.
|
||||
// Play sound if have.
|
||||
ISoundSystem *pISoundSystem = GetISystem()->GetISoundSystem();
|
||||
#if !defined(LINUX64)
|
||||
if (pISoundSystem != NULL && m_pEffect != NULL)
|
||||
#else
|
||||
if (pISoundSystem != 0 && m_pEffect != 0)
|
||||
#endif
|
||||
{
|
||||
// Check if effect needs to play sounds.
|
||||
IParticleEffect::SoundParams soundParams;
|
||||
m_pEffect->GetSoundParams( soundParams );
|
||||
if (strlen(soundParams.szSound) > 0)
|
||||
{
|
||||
int nSndFlags = FLAG_SOUND_3D | FLAG_SOUND_RADIUS | FLAG_SOUND_OCCLUSION;
|
||||
if (soundParams.bLoop && m_bPermament)
|
||||
{
|
||||
m_bLoopSound = true;
|
||||
nSndFlags |= FLAG_SOUND_LOOP;
|
||||
}
|
||||
else
|
||||
m_bLoopSound = false;
|
||||
|
||||
m_pSound = pISoundSystem->LoadSound( soundParams.szSound,nSndFlags );
|
||||
#if !defined(LINUX64)
|
||||
if (m_pSound != NULL && !soundParams.bOnEverySpawn)
|
||||
#else
|
||||
if (m_pSound != 0 && !soundParams.bOnEverySpawn)
|
||||
#endif
|
||||
{
|
||||
PlaySound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Effect is deactivated.
|
||||
if (m_pSound != 0 && m_bLoopSound)
|
||||
{
|
||||
m_pSound->Stop();
|
||||
m_pSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Activate/deactivate childs.
|
||||
for (int i = 0; i < (int)m_childEmitters.size(); i++)
|
||||
{
|
||||
CParticleEmitter *pEmitter = m_childEmitters[i];
|
||||
if (pEmitter)
|
||||
{
|
||||
pEmitter->OnActivate( bActive );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::PlaySound()
|
||||
{
|
||||
if (!m_pEffect || !m_pSound)
|
||||
return;
|
||||
|
||||
IParticleEffect::SoundParams soundParams;
|
||||
m_pEffect->GetSoundParams( soundParams );
|
||||
|
||||
m_pSound->SetVolume( (int)soundParams.volume );
|
||||
m_pSound->SetMinMaxDistance( soundParams.minRadius,soundParams.maxRadius );
|
||||
Vec3 vOffset = m_pParams->vPositionOffset;
|
||||
m_pSound->SetPosition( m_pos + vOffset );
|
||||
m_pSound->Play();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Called when particles are spawned.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CParticleEmitter::OnSpawnParticles( bool bChildProcess )
|
||||
{
|
||||
#if !defined(LINUX64)
|
||||
if (!bChildProcess && m_pSound != NULL && m_pEffect != NULL)
|
||||
#else
|
||||
if (!bChildProcess && m_pSound != 0 && m_pEffect != 0)
|
||||
#endif
|
||||
{
|
||||
IParticleEffect::SoundParams soundParams;
|
||||
m_pEffect->GetSoundParams( soundParams );
|
||||
if (soundParams.bOnEverySpawn)
|
||||
{
|
||||
PlaySound();
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Cry3DEngine/ParticleEmitter.h
Normal file
127
Cry3DEngine/ParticleEmitter.h
Normal file
@@ -0,0 +1,127 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: particleemitter.h
|
||||
// Version: v1.00
|
||||
// Created: 18/7/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __particleemitter_h__
|
||||
#define __particleemitter_h__
|
||||
#pragma once
|
||||
|
||||
#include <ISound.h>
|
||||
|
||||
/*! Temporary emitter position for ParticleEffects.
|
||||
*/
|
||||
class CParticleEmitter : public IParticleEmitter
|
||||
{
|
||||
public:
|
||||
uint m_bOwnParams : 1; //!< True if particle created its own particle params.
|
||||
uint m_bActive : 1; //!< True when this emitter is active.
|
||||
uint m_bActiveChild : 1; //!< True when child emitter is active.
|
||||
uint m_bPermament : 1; //!< True when this emitter is permament (temporary emitters not added to particle manager).
|
||||
uint m_bLoopSound : 1; //!< True when playing looped sound.
|
||||
uint m_bVisible : 1; //!< True if emitter is visible.
|
||||
uint m_bUseEndTime : 1; //!< True if m_endTime is used
|
||||
uint m_bChildEmitter : 1; //!< True if this child emitter (Only with permament parent emitter).
|
||||
|
||||
//! Position of the emitter.
|
||||
Vec3 m_pos;
|
||||
//! Direction of the emitter.
|
||||
Vec3 m_dir;
|
||||
//! Scale for particles at this emitter.
|
||||
float m_fScale;
|
||||
//! When this emitter must be activated.
|
||||
float m_startTime;
|
||||
//! When this emitter must be killed. (only used when m_bUseEndTime is true)
|
||||
float m_endTime;
|
||||
//! How often to spawn particles, time in seconds between 2 successing spawns.
|
||||
float m_spawnPeriod;
|
||||
// Last time when particles where spawned.
|
||||
float m_lastSpawnTime;
|
||||
//! Pointer to particle params. (ParticleEffect).
|
||||
ParticleParams *m_pParams;
|
||||
//! Pointer to child params of this emitter.
|
||||
ParticleParams *m_pChildParams;
|
||||
//! Notify time when position was last set on this emitter.
|
||||
float m_lastActiveTime;
|
||||
//! Particle effect used for this emitter.
|
||||
IParticleEffect_AutoPtr m_pEffect;
|
||||
//! Owner particle manager.
|
||||
class CPartManager *m_pPartManager;
|
||||
//! Override material for this emitter.
|
||||
_smart_ptr<IMatInfo> m_pMaterial;
|
||||
//! Entity who controls this emitter.
|
||||
IEntityRender *m_pSpawnerEntity;
|
||||
//! Custom shader from material.
|
||||
_smart_ptr<IShader> m_pShader;
|
||||
//! Bounding box.
|
||||
AABB m_bbox;
|
||||
//! Water level in position of emitter. Used to avoid calculating it for each particle.
|
||||
float m_fWaterLevel;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
std::vector<_smart_ptr<CParticleEmitter> > m_childEmitters;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particle emitter looped sound.
|
||||
_smart_ptr<ISound> m_pSound;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CParticleEmitter( CPartManager *pPartManager ) : m_pos(0,0,0),m_dir(0,0,0)
|
||||
{
|
||||
m_pPartManager = pPartManager;
|
||||
m_pSpawnerEntity = NULL;
|
||||
m_startTime = m_endTime = m_lastActiveTime = m_spawnPeriod = m_lastSpawnTime = 0;
|
||||
m_pParams = 0;
|
||||
m_pChildParams = 0;
|
||||
m_bOwnParams = false;
|
||||
m_fScale = 1;
|
||||
m_bActive = false;
|
||||
m_bActiveChild = false;
|
||||
m_bPermament = false;
|
||||
m_bVisible = true;
|
||||
m_fWaterLevel = WATER_LEVEL_UNKNOWN;
|
||||
m_bLoopSound = false;
|
||||
m_bUseEndTime=false;
|
||||
m_bChildEmitter = false;
|
||||
}
|
||||
~CParticleEmitter();
|
||||
void ReleaseParams();
|
||||
void UpdateChildSpawnTimes( float fCurrTime );
|
||||
// Only when not effect.
|
||||
void InitTexture( ParticleParams *pParams );
|
||||
|
||||
void AssignEffect( IParticleEffect *pEffect,bool bChildEffects );
|
||||
|
||||
void CalculateWaterLevel();
|
||||
void OnActivate( bool bActive );
|
||||
void OnSpawnParticles( bool bChildProcess );
|
||||
void PlaySound();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IParticleEmitter interface implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetParams( const ParticleParams ¶ms );
|
||||
virtual void SetEffect( IParticleEffect *pEffect );
|
||||
virtual const ParticleParams& GetParams() const;
|
||||
virtual void SetPos( const Vec3 &vPos,const Vec3 &vDir,float fScale );
|
||||
virtual void SetSpawnPeriod( float fSpawnPeriod );
|
||||
virtual void SetLifeTime( const float fLifeTime );
|
||||
virtual void SetUnlimitedLife();
|
||||
virtual void SetEntity( IEntityRender *pEntity );
|
||||
virtual void SetMaterial( IMatInfo *pMaterial );
|
||||
};
|
||||
|
||||
#endif // __particleemitter_h__
|
||||
|
||||
491
Cry3DEngine/SaveCFG.cpp
Normal file
491
Cry3DEngine/SaveCFG.cpp
Normal file
@@ -0,0 +1,491 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: savecfg.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2002 by Andrey
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: cgf file writer
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "CryStaticModel.h"
|
||||
#include "statobj.h"
|
||||
#include "MeshIdx.h"
|
||||
|
||||
bool C3DEngine::WriteMaterials(TArray<CHUNK_HEADER>& Chunks, TArray<IShader *>& Shaders, FILE *out, int &MatChunk)
|
||||
{
|
||||
CHUNK_HEADER ch;
|
||||
|
||||
// the type and version of the material chunk
|
||||
typedef MTL_CHUNK_DESC_0745 MTL_CHUNK_TYPE;
|
||||
|
||||
MTL_CHUNK_TYPE chunk;
|
||||
memset (&chunk, 0, sizeof(chunk));
|
||||
int Offs = ftell(out);
|
||||
|
||||
ch.ChunkType = ChunkType_Mtl;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
MatChunk = ch.ChunkID;
|
||||
ch.ChunkVersion = MTL_CHUNK_TYPE::VERSION;
|
||||
ch.FileOffset = Offs;
|
||||
Offs += sizeof(chunk) + sizeof(int) * Shaders.Num();
|
||||
Chunks.AddElem(ch);
|
||||
int i=0;
|
||||
for (i=0; i<Shaders.Num(); i++)
|
||||
{
|
||||
ch.ChunkType = ChunkType_Mtl;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
ch.ChunkVersion = MTL_CHUNK_TYPE::VERSION;
|
||||
ch.FileOffset = Offs;
|
||||
Offs += sizeof(chunk);
|
||||
Chunks.AddElem(ch);
|
||||
}
|
||||
|
||||
chunk.chdr = Chunks[MatChunk];
|
||||
chunk.MtlType = MTL_MULTI;
|
||||
strcpy(chunk.name, "Multi");
|
||||
chunk.nChildren = Shaders.Num();
|
||||
fwrite(&chunk, 1, sizeof(chunk), out);
|
||||
for (i=0; i<Shaders.Num(); i++)
|
||||
{
|
||||
int nn = MatChunk+i;
|
||||
fwrite(&nn, 1, sizeof(int), out);
|
||||
}
|
||||
/*for (i=0; i<Shaders.Num(); i++)
|
||||
{
|
||||
memset(&chunk, 0, sizeof(chunk));
|
||||
chunk.chdr = Chunks[MatChunk+i+1];
|
||||
chunk.MtlType = MTL_STANDARD;
|
||||
IShader *sh = Shaders[i];
|
||||
strcpy(chunk.name, sh->GetName());
|
||||
if (sh->GetTemplates())
|
||||
{
|
||||
SEfTemplates *eft = sh->GetTemplates();
|
||||
for (int j=0; j<16; j++)
|
||||
{
|
||||
if (!eft->m_TexInfo[j].m_Name.empty())
|
||||
{
|
||||
switch (j)
|
||||
{
|
||||
case EFTT_DECAL:
|
||||
strcpy(chunk.tex_d.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_BUMP:
|
||||
case EFTT_DSDTBUMP:
|
||||
strcpy(chunk.tex_b.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_GLOSS:
|
||||
strcpy(chunk.tex_g.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_OPACITY:
|
||||
strcpy(chunk.tex_o.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_ENVIRONMENT:
|
||||
case EFTT_REFLECTION:
|
||||
strcpy(chunk.tex_rl.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_REFRACTION:
|
||||
strcpy(chunk.tex_rr.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_CUBEMAP:
|
||||
strcpy(chunk.tex_c.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_SPECULAR:
|
||||
strcpy(chunk.tex_s.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
case EFTT_DETAIL:
|
||||
strcpy(chunk.tex_det.name, eft->m_TexInfo[j].m_Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
strcpy(chunk.tex_d.name, chunk.name);
|
||||
chunk.Dyn_Bounce = 1;
|
||||
chunk.Dyn_StaticFriction = 1;
|
||||
chunk.Dyn_SlidingFriction = 1;
|
||||
chunk.nChildren = -1;
|
||||
fwrite(&chunk, 1, sizeof(chunk), out);
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SNodeInfo
|
||||
{
|
||||
int bGlobals;
|
||||
int Sector;
|
||||
CStatObj *pObj;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
bool C3DEngine::WriteNodes(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame, std::vector<IStatObj *>& pObjs)
|
||||
{
|
||||
CHUNK_HEADER ch;
|
||||
int numMeshs = 0;
|
||||
NODE_CHUNK_DESC nd;
|
||||
SNodeInfo ni;
|
||||
int i;
|
||||
|
||||
NI.Free();
|
||||
ExpFrame++;
|
||||
|
||||
int nChildren;
|
||||
|
||||
std::vector<IStatObj*>::iterator n;
|
||||
for (n=pObjs.begin();n!=pObjs.end();n++)
|
||||
{
|
||||
IStatObj *io = (*n);
|
||||
CStatObj *co = (CStatObj *)io;
|
||||
|
||||
memset(&nd, 0, sizeof(NODE_CHUNK_DESC));
|
||||
strcpy(nd.name, co->m_szGeomName);
|
||||
nd.tm.SetIdentity();
|
||||
nd.scl = Vec3(1.0,1.0,1.0);
|
||||
nd.MatID = MatChunk;
|
||||
nd.ObjectID = numMeshs++;
|
||||
int nnd = Nodes.Num();
|
||||
Nodes.AddElem(nd);
|
||||
ni.bGlobals = 1;
|
||||
ni.pObj = co;
|
||||
strcpy(ni.name, nd.name);
|
||||
NI.AddElem(ni);
|
||||
nChildren = 0;
|
||||
Nodes[nnd].nChildren = nChildren;
|
||||
}
|
||||
|
||||
memset(&ch, 0, sizeof(CHUNK_HEADER));
|
||||
int no = Chunks.Num() + Nodes.Num();
|
||||
for (i=0; i<Nodes.Num(); i++)
|
||||
{
|
||||
Nodes[i].ObjectID += no;
|
||||
ch.ChunkType = ChunkType_Node;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
ch.ChunkVersion = NODE_CHUNK_DESC_VERSION;
|
||||
ch.FileOffset = ftell(out);
|
||||
Nodes[i].chdr = ch;
|
||||
Chunks.AddElem(ch);
|
||||
fwrite(&Nodes[i], sizeof(NODE_CHUNK_DESC), 1, out);
|
||||
for (int j=0; j<Nodes[i].nChildren; j++)
|
||||
{
|
||||
int nn = Nodes[i].chdr.ChunkID+1+j;
|
||||
fwrite(&nn, sizeof(int), 1, out);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C3DEngine::WriteNodeMesh(int nNode, MESH_CHUNK_DESC *chunk, FILE *out, TArray<IShader *>& Shaders, TArray<SNodeInfo>& NI, CStatObj *pObj)
|
||||
{
|
||||
TArray<CryVertex> Verts;
|
||||
TArray<CryFace> Faces;
|
||||
TArray<CryUV> UVs;
|
||||
TArray<CryTexFace> TFaces;
|
||||
TArray<CryIRGB> Colors;
|
||||
int i, j;
|
||||
|
||||
SNodeInfo *ni = &NI[nNode];
|
||||
|
||||
CIndexedMesh *pMesh = pObj->GetTriData();
|
||||
|
||||
for (i=0; i<pMesh->m_nFaceCount; i++)
|
||||
{
|
||||
CryFace fc;
|
||||
CryTexFace tf;
|
||||
|
||||
fc.v0 = pMesh->m_pFaces[i].v[0];
|
||||
fc.v1 = pMesh->m_pFaces[i].v[1];
|
||||
fc.v2 = pMesh->m_pFaces[i].v[2];
|
||||
|
||||
tf.t0 = pMesh->m_pFaces[i].t[0];
|
||||
tf.t1 = pMesh->m_pFaces[i].t[1];
|
||||
tf.t2 = pMesh->m_pFaces[i].t[2];
|
||||
|
||||
int ns = pMesh->m_pFaces[i].shader_id;
|
||||
IShader *sh = pMesh->m_lstMatTable[ns].shaderItem.m_pShader;
|
||||
for (j=0; j<Shaders.Num(); j++)
|
||||
{
|
||||
if (!stricmp(sh->GetName(), Shaders[j]->GetName()))
|
||||
break;
|
||||
}
|
||||
assert (j != Shaders.Num());
|
||||
fc.MatID = j;
|
||||
fc.SmGroup = 0;
|
||||
Faces.AddElem(fc);
|
||||
TFaces.AddElem(tf);
|
||||
}
|
||||
|
||||
for (i=0; i<pMesh->m_nVertCount; i++)
|
||||
{
|
||||
CryVertex vr;
|
||||
CryIRGB rgb;
|
||||
|
||||
vr.p[0] = pMesh->m_pVerts[i].x * 100.0f;
|
||||
vr.p[1] = pMesh->m_pVerts[i].y * 100.0f;
|
||||
vr.p[2] = pMesh->m_pVerts[i].z * 100.0f;
|
||||
|
||||
vr.n[0] = pMesh->m_pNorms[i].x;
|
||||
vr.n[1] = pMesh->m_pNorms[i].y;
|
||||
vr.n[2] = pMesh->m_pNorms[i].z;
|
||||
|
||||
rgb.r = pMesh->m_pColor[i].r;
|
||||
rgb.g = pMesh->m_pColor[i].g;
|
||||
rgb.b = pMesh->m_pColor[i].b;
|
||||
|
||||
Verts.AddElem(vr);
|
||||
Colors.AddElem(rgb);
|
||||
}
|
||||
|
||||
for (i=0; i<pMesh->m_nCoorCount; i++)
|
||||
{
|
||||
CryUV uv;
|
||||
|
||||
uv.u = pMesh->m_pCoors[i].s;
|
||||
uv.v = pMesh->m_pCoors[i].t;
|
||||
|
||||
UVs.AddElem(uv);
|
||||
}
|
||||
|
||||
chunk->nFaces = Faces.Num();
|
||||
chunk->nTVerts = UVs.Num();
|
||||
chunk->nVerts = Verts.Num();
|
||||
chunk->VertAnimID = 0;
|
||||
|
||||
if (Colors.Num())
|
||||
chunk->HasVertexCol = 1;
|
||||
else
|
||||
chunk->HasVertexCol = 0;
|
||||
|
||||
fwrite(chunk, 1, sizeof(MESH_CHUNK_DESC), out);
|
||||
|
||||
fwrite(&Verts[0], sizeof(CryVertex), chunk->nVerts, out);
|
||||
fwrite(&Faces[0], sizeof(CryFace), chunk->nFaces, out);
|
||||
fwrite(&UVs[0], sizeof(CryUV), chunk->nTVerts, out);
|
||||
fwrite(&TFaces[0], sizeof(CryTexFace), chunk->nFaces, out);
|
||||
if (chunk->HasVertexCol)
|
||||
fwrite(&Colors[0], sizeof(CryIRGB), chunk->nVerts, out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C3DEngine::WriteMesh(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, TArray<IShader *>& Shaders, FILE *out, TArray<SNodeInfo>& NI, int& MatChunk, int& ExpFrame)
|
||||
{
|
||||
MESH_CHUNK_DESC chunk;
|
||||
CHUNK_HEADER ch;
|
||||
|
||||
ExpFrame++;
|
||||
for (int i=0; i<Nodes.Num(); i++)
|
||||
{
|
||||
NODE_CHUNK_DESC *nd = &Nodes[i];
|
||||
SNodeInfo *ni = &NI[i];
|
||||
ch.ChunkType = ChunkType_Mesh;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
ch.ChunkVersion = GeomFileVersion;
|
||||
ch.FileOffset = ftell(out);
|
||||
Chunks.AddElem(ch);
|
||||
|
||||
chunk.chdr = ch;
|
||||
chunk.HasBoneInfo = 0;
|
||||
chunk.HasVertexCol = 0;
|
||||
|
||||
WriteNodeMesh(i, &chunk, out, Shaders, NI, ni->pObj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C3DEngine::WriteLights(TArray<CHUNK_HEADER>& Chunks, TArray<NODE_CHUNK_DESC>& Nodes, FILE *out, std::vector<IStatObj *>& pObjs)
|
||||
{
|
||||
LIGHT_CHUNK_DESC lcd;
|
||||
CHUNK_HEADER ch;
|
||||
NODE_CHUNK_DESC nd;
|
||||
|
||||
std::vector<IStatObj*>::iterator n;
|
||||
for (n=pObjs.begin();n!=pObjs.end();n++)
|
||||
{
|
||||
IStatObj *io = (*n);
|
||||
CStatObj *co = (CStatObj *)io;
|
||||
// CIndexedMesh *im = co->GetTriData();
|
||||
for (int j=0; j<co->m_lstLSources.Count(); j++)
|
||||
{
|
||||
CDLight *dl = &co->m_lstLSources[j];
|
||||
|
||||
memset(&lcd, 0, sizeof(LIGHT_CHUNK_DESC));
|
||||
memset(&ch, 0, sizeof(CHUNK_HEADER));
|
||||
memset(&nd, 0, sizeof(NODE_CHUNK_DESC));
|
||||
int no = Chunks.Num();
|
||||
|
||||
ch.ChunkType = ChunkType_Node;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
ch.ChunkVersion = NODE_CHUNK_DESC_VERSION;
|
||||
ch.FileOffset = ftell(out);
|
||||
Chunks.AddElem(ch);
|
||||
|
||||
nd.chdr = ch;
|
||||
nd.ObjectID = Chunks.Num();
|
||||
if (dl->m_Name)
|
||||
strcpy(nd.name, dl->m_Name);
|
||||
else
|
||||
nd.name[0] = 0;
|
||||
Vec3d Org;
|
||||
/* if (dl->m_OrigLight)
|
||||
Org = dl->m_OrigLight->m_Origin;
|
||||
else
|
||||
Org = dl->m_Origin;
|
||||
*/ nd.pos.x = Org[0] * 100.0f;
|
||||
nd.pos.y = Org[1] * 100.0f;
|
||||
nd.pos.z = Org[2] * 100.0f;
|
||||
|
||||
nd.tm.SetIdentity();
|
||||
nd.tm[3][0] = nd.pos.x;
|
||||
nd.tm[3][1] = nd.pos.y;
|
||||
nd.tm[3][2] = nd.pos.z;
|
||||
|
||||
nd.scl = Vec3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
fwrite(&nd, sizeof(NODE_CHUNK_DESC), 1, out);
|
||||
|
||||
|
||||
// Light
|
||||
ch.ChunkType = ChunkType_Light;
|
||||
ch.ChunkID = Chunks.Num();
|
||||
ch.ChunkVersion = LIGHT_CHUNK_DESC_VERSION;
|
||||
ch.FileOffset = ftell(out);
|
||||
Chunks.AddElem(ch);
|
||||
|
||||
lcd.chdr = ch;
|
||||
lcd.intens = dl->m_fRadius * 100.0f;
|
||||
if (lcd.intens <= 0)
|
||||
lcd.intens = 500;
|
||||
lcd.attenEnd = lcd.intens;
|
||||
UCol col;
|
||||
col.dcolor = dl->m_Color.GetTrue();
|
||||
lcd.color.r = col.bcolor[0];
|
||||
lcd.color.g = col.bcolor[1];
|
||||
lcd.color.b = col.bcolor[2];
|
||||
lcd.vDirection = dl->m_ProjAngles;
|
||||
lcd.fallsize = dl->m_fLightFrustumAngle;
|
||||
if (dl->m_pLightImage)
|
||||
{
|
||||
strcpy(lcd.szLightImage, dl->m_pLightImage->GetName());
|
||||
lcd.type = LT_OMNI;
|
||||
}
|
||||
else
|
||||
if (dl->m_Flags & DLF_DIRECTIONAL)
|
||||
lcd.type = LT_DIRECT;
|
||||
else
|
||||
if (dl->m_Flags & DLF_POINT)
|
||||
{
|
||||
lcd.useAtten = true;
|
||||
lcd.type = LT_OMNI;
|
||||
}
|
||||
fwrite(&lcd, sizeof(LIGHT_CHUNK_DESC), 1, out);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C3DEngine::SaveCGF(std::vector<IStatObj *>& pObjs)
|
||||
{
|
||||
TArray<CHUNK_HEADER> Chunks;
|
||||
TArray<NODE_CHUNK_DESC> Nodes;
|
||||
TArray<IShader *> Shaders;
|
||||
TArray<SNodeInfo> NI;
|
||||
int ExpFrame = 0;
|
||||
char fName[1024];
|
||||
int res;
|
||||
int i, j;
|
||||
int MatChunk;
|
||||
|
||||
if (pObjs.empty())
|
||||
return false;
|
||||
IStatObj *io = pObjs.front();
|
||||
CStatObj *so = (CStatObj *)io;
|
||||
|
||||
// Remove extension
|
||||
char *in = so->m_szFileName;
|
||||
char *o = fName;
|
||||
char c;
|
||||
|
||||
while (*in)
|
||||
{
|
||||
if (*in=='.')
|
||||
{
|
||||
c = in[1];
|
||||
if (c!='.' && c!='/' && c!='\\')
|
||||
break;
|
||||
}
|
||||
*o++ = *in++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
// Add default extension
|
||||
strcat(fName, ".cgf");
|
||||
FILE *out = fxopen(fName, "wb");
|
||||
if (!out)
|
||||
return false;
|
||||
|
||||
FILE_HEADER hd;
|
||||
strcpy(hd.Signature, FILE_SIGNATURE);
|
||||
hd.Version = GeomFileVersion;
|
||||
hd.FileType = FileType_Geom;
|
||||
|
||||
//write the header
|
||||
res = fwrite(&hd, sizeof(hd), 1, out);
|
||||
if(res != 1)
|
||||
return false;
|
||||
|
||||
std::vector<IStatObj*>::iterator n;
|
||||
for (n=pObjs.begin();n!=pObjs.end();n++)
|
||||
{
|
||||
IStatObj *io = (*n);
|
||||
CStatObj *co = (CStatObj *)io;
|
||||
CLeafBuffer *lb = co->GetLeafBuffer();
|
||||
|
||||
// Prepare shaders for write
|
||||
for (i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
IShader *e = (*lb->m_pMats)[i].shaderItem.m_pShader;
|
||||
if (!e)
|
||||
continue;
|
||||
for (j=0; j<Shaders.Num(); j++)
|
||||
{
|
||||
if (!stricmp(e->GetName(), Shaders[j]->GetName()))
|
||||
break;
|
||||
}
|
||||
if (j == Shaders.Num())
|
||||
Shaders.AddElem(e);
|
||||
}
|
||||
}
|
||||
|
||||
WriteMaterials(Chunks, Shaders, out, MatChunk);
|
||||
WriteNodes(Chunks, Nodes, out, NI, MatChunk, ExpFrame, pObjs);
|
||||
WriteMesh(Chunks, Nodes, Shaders, out, NI, MatChunk, ExpFrame);
|
||||
Nodes.Free();
|
||||
WriteLights(Chunks, Nodes, out, pObjs);
|
||||
|
||||
hd.ChunkTableOffset = ftell(out);
|
||||
int nn = Chunks.Num();
|
||||
fwrite(&nn, sizeof(int), 1, out);
|
||||
for (i=0; i<Chunks.Num(); i++)
|
||||
{
|
||||
fwrite(&Chunks[i], sizeof(CHUNK_HEADER), 1, out);
|
||||
}
|
||||
fseek(out, 0, SEEK_SET);
|
||||
fwrite(&hd, sizeof(hd), 1, out);
|
||||
|
||||
fclose (out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================================
|
||||
128
Cry3DEngine/ShadowVolumeEdge.h
Normal file
128
Cry3DEngine/ShadowVolumeEdge.h
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Indoor Engine DLL source code
|
||||
//
|
||||
// File: ShadowVolumeEdge.h
|
||||
//
|
||||
// History:
|
||||
// -September 29,2001:Created by Marco Corbetta
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SHADOWVOLEDGE_H
|
||||
#define SHADOWVOLEDGE_H
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//TODO: Move into Irenderer.h when changing that file it will not cause
|
||||
//the entire workspace to be recompiled
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#define FLAG_FALSE_EDGE_SILOHUETTE 1
|
||||
#define FLAG_IN_SURFACE_CONTACT_V0 2
|
||||
#define FLAG_IN_SURFACE_CONTACT_V1 4
|
||||
#define FLAG_BLACK_FACE 8
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
struct CObjFace;
|
||||
class CShadowVolEdge;
|
||||
|
||||
//this is put into a structure and allocated if necessary to
|
||||
//save memory
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
struct tAddEdgeInfo
|
||||
{
|
||||
|
||||
tAddEdgeInfo()
|
||||
{
|
||||
m_dwFlags=0;
|
||||
}
|
||||
|
||||
//! shadow plane + 4 volume edges plane's equation
|
||||
Plane m_Planes[1];
|
||||
|
||||
//! silhouette direction
|
||||
Vec3d m_vUp;
|
||||
|
||||
/*! since the edge is shared by more than 1 face, i have to keep
|
||||
the right vectors here and not in the face
|
||||
each face has vright information for both points of the edge
|
||||
original vectors */
|
||||
Vec3d m_vRight1[2];
|
||||
Vec3d m_vRight2[2];
|
||||
|
||||
//! after interpolation,based on the faces lit by light
|
||||
Vec3d m_vRightInterp1[2];
|
||||
Vec3d m_vRightInterp2[2];
|
||||
float m_fDist1[2];
|
||||
float m_fDist2[2];
|
||||
|
||||
//! extruded edge (1 face only-in and out)
|
||||
Vec3d m_vExtrOut[2];
|
||||
Vec3d m_vExtrIn[2];
|
||||
//center of the projected edge
|
||||
Vec3d m_vCenter;
|
||||
|
||||
std::vector<CShadowVolEdge*> m_lstConnectedEdges1;
|
||||
std::vector<CShadowVolEdge*> m_lstConnectedEdges2;
|
||||
|
||||
unsigned char m_dwFlags;
|
||||
};
|
||||
|
||||
//shadow volume edge,used to build static or dynamic silouhette
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class CShadowVolEdge
|
||||
{
|
||||
public:
|
||||
CShadowVolEdge()
|
||||
{
|
||||
m_pFace1=NULL;
|
||||
m_pFace2=NULL;
|
||||
m_nVNum0=m_nVNum1=0;
|
||||
m_pAddEdge=NULL;
|
||||
}
|
||||
|
||||
~CShadowVolEdge()
|
||||
{
|
||||
if (m_pAddEdge)
|
||||
{
|
||||
delete [] m_pAddEdge;
|
||||
m_pAddEdge=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//check if the point is on the extent of the shadow volume edge
|
||||
bool PointOnEdge(const Vec3d &vPoint);
|
||||
//clip with planes formed with the edges
|
||||
bool ClipAdditionalEdge(Vec3d &vP1,Vec3d &vP2);
|
||||
//to call once the edges and face plane are defined
|
||||
void CreateAdditionalPlanes();
|
||||
*/
|
||||
|
||||
//! orginal ednpoints of the silouhette edge
|
||||
Vec3d m_vecV0;
|
||||
Vec3d m_vecV1;
|
||||
|
||||
//! for dynamic models, to quick access modified vertices
|
||||
int m_nVNum0;
|
||||
int m_nVNum1;
|
||||
|
||||
//! projected edge
|
||||
//Vec3d m_vecEv0,m_vecEv1,m_vecEv2,m_vecEv3;
|
||||
Vec3d m_vecEv[4];
|
||||
//! the two faces the edge belongs to
|
||||
CObjFace *m_pFace1;
|
||||
CObjFace *m_pFace2;
|
||||
|
||||
tAddEdgeInfo *m_pAddEdge;
|
||||
};
|
||||
|
||||
typedef std::vector<CShadowVolEdge *>::iterator connedgeit;
|
||||
|
||||
#endif //shadowvoledge
|
||||
410
Cry3DEngine/SpriteManager.cpp
Normal file
410
Cry3DEngine/SpriteManager.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: spritemanager.cpp
|
||||
// Version: v1.00
|
||||
// Created: 18/7/2003 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History: Created by Vladimir
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "partman.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
//#include "ParticleEffect.h"
|
||||
#include "3dEngine.h"
|
||||
|
||||
CSpriteManager::CSpriteManager( CPartManager *pPartManager )
|
||||
{
|
||||
m_nMaxSpritesCount = min(16384, max(16,GetCVars()->e_particles_max_count));
|
||||
m_arrSprites = new CSprite[m_nMaxSpritesCount];
|
||||
|
||||
m_nCurSpritesCount=0;
|
||||
memset(m_arrSprites,0,sizeof(CSprite)*m_nMaxSpritesCount);
|
||||
|
||||
m_pSystem = GetSystem();
|
||||
m_p3DEngine = Get3DEngine();
|
||||
m_pVisAreaManager = GetVisAreaManager();
|
||||
m_pObjManager = ((C3DEngine*)m_p3DEngine)->GetObjManager();
|
||||
m_pPartManager = pPartManager;
|
||||
}
|
||||
|
||||
CSpriteManager::~CSpriteManager()
|
||||
{
|
||||
delete [] m_arrSprites;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CSpriteManager::Spawn( CParticleEmitter &emitter,bool bChildProcess )
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
// make sprites
|
||||
ParticleParams &Params = (!bChildProcess) ? *emitter.m_pParams : *emitter.m_pParams->pChild;
|
||||
|
||||
if(!_finite(Params.vPosition.x) || !_finite(Params.vPosition.y) || !_finite(Params.vPosition.z))
|
||||
{
|
||||
// GetLog()->Log("Warning: CSpriteManager::Spawn: Particle emitter position is undefined");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/* if(GetCVars()->e_particles_debug==1)
|
||||
{
|
||||
Params.fSpeed = Params.fSpeed / 10;
|
||||
Params.fLifeTime = Params.fLifeTime*10;
|
||||
Params.vGravity/=10;
|
||||
}*/
|
||||
|
||||
/*
|
||||
if (Params.fScale != 1.0f && Params.fScale > 0)
|
||||
{
|
||||
float fScale = Params.fScale;
|
||||
// Adjust particle parameters by scale.
|
||||
Params.fSize = Params.fSize*fScale;
|
||||
Params.fPosRandomOffset *= fScale;
|
||||
Params.vGravity *= fScale;
|
||||
Params.vPositionOffset *= fScale;
|
||||
Params.vRandomPositionOffset *= fScale;
|
||||
Params.fSizeSpeed *= fScale;
|
||||
Params.fSpeed = Params.fSpeed*fScale;
|
||||
Params.fTailLenght *= fScale;
|
||||
Params.fTurbulenceSize *= fScale;
|
||||
//Params.fTurbulenceSpeed *= fScale;
|
||||
if (Params.pChild)
|
||||
{
|
||||
Params.pChild->fSize = Params.pChild->fSize*fScale;
|
||||
Params.pChild->fPosRandomOffset *= fScale;
|
||||
Params.pChild->vGravity *= fScale;
|
||||
Params.pChild->vPositionOffset *= fScale;
|
||||
Params.pChild->vRandomPositionOffset *= fScale;
|
||||
Params.pChild->fSizeSpeed *= fScale;
|
||||
Params.pChild->fSpeed = Params.pChild->fSpeed*fScale;
|
||||
Params.pChild->fTailLenght *= fScale;
|
||||
Params.pChild->fTurbulenceSize *= fScale;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
float fCurrTime = m_pPartManager->GetParticlesTime();
|
||||
int nCount = max(1,int(Params.nCount*GetCVars()->e_particles_lod));
|
||||
|
||||
// pass Params structure to CPartSpray::Spawn() nCount times
|
||||
for(int i=0; i < nCount; i++)
|
||||
{
|
||||
if(m_nCurSpritesCount>=m_nMaxSpritesCount)
|
||||
break;
|
||||
|
||||
CSprite * pSprite = &m_arrSprites[m_nCurSpritesCount];
|
||||
|
||||
// spawn one sprite
|
||||
SpawnParticle( emitter,bChildProcess,fCurrTime,pSprite );
|
||||
m_nCurSpritesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSpriteManager::SpawnParticle( CParticleEmitter &emitter,bool bChildProcess,float fCurrTime,CParticle *pPart )
|
||||
{
|
||||
if (!bChildProcess)
|
||||
pPart->m_pParams = emitter.m_pParams;
|
||||
else
|
||||
pPart->m_pParams = emitter.m_pParams->pChild;
|
||||
|
||||
ParticleParams &Params = *pPart->m_pParams;
|
||||
|
||||
// Params.nParticleFlags |= PART_FLAG_LINEPARTICLE;
|
||||
//Params.vDirection = Vec3d(0,100,0);
|
||||
|
||||
//pPart->m_pVisArea = m_pVisAreaManager->GetVisAreaFromPos(Params.vPosition);
|
||||
|
||||
pPart->m_pEmitter = &emitter;
|
||||
pPart->m_pEmitter->AddRef();
|
||||
|
||||
// Get scale for this particle.
|
||||
float fScale = emitter.m_fScale;
|
||||
pPart->m_fScale = fScale;
|
||||
|
||||
pPart->m_nParticleFlags = Params.nParticleFlags;
|
||||
if (Params.eBlendType == ParticleBlendType_Additive)
|
||||
{
|
||||
pPart->m_nParticleFlags |= CParticle::PARTICLE_COLOR_BASED | CParticle::PARTICLE_ADDITIVE;
|
||||
}
|
||||
else if (Params.eBlendType == ParticleBlendType_ColorBased)
|
||||
{
|
||||
pPart->m_nParticleFlags |= CParticle::PARTICLE_COLOR_BASED;
|
||||
}
|
||||
if (Params.nParticleFlags & PART_FLAG_RIGIDBODY)
|
||||
{
|
||||
// Also set no offset flag.
|
||||
Params.nParticleFlags |= PART_FLAG_NO_OFFSET;
|
||||
}
|
||||
|
||||
if (Params.nTexAnimFramesCount > 1)
|
||||
pPart->m_nParticleFlags |= CParticle::PARTICLE_ANIMATED_TEXTURE;
|
||||
|
||||
// calculate focus and dir
|
||||
if(Params.nParticleFlags & PART_FLAG_LINEPARTICLE)
|
||||
pPart->m_vDelta = Params.vDirection;
|
||||
else if(Params.nParticleFlags & PART_FLAG_FOCUS_PLANE)
|
||||
{
|
||||
// Distribute particles on plane.
|
||||
Vec3 dir = Params.vDirection;
|
||||
if(Params.nParticleFlags & PART_FLAG_SPEED_IN_GRAVITY_DIRECTION)
|
||||
{
|
||||
dir = -Params.vGravity;
|
||||
if (dir.IsZero()) dir = Vec3(0,0,1);
|
||||
dir.Normalize();
|
||||
}
|
||||
Vec3 n1 = Vec3(0,1,0);
|
||||
if (n1 == dir)
|
||||
n1 = Vec3(1,0,0);
|
||||
n1 = dir.Cross(n1);
|
||||
Vec3 n2 = dir.Cross(n1);
|
||||
Matrix33 tm;
|
||||
tm.SetMatFromVectors( dir,n1,n2 );
|
||||
|
||||
Vec3d vPartDir(2.0f*rnd()-1.0f,2.0f*rnd()-1.0f,2.0f*rnd()-1.0f);
|
||||
float focus = max(0,min(1,Params.fFocus));
|
||||
vPartDir.x *= focus;
|
||||
vPartDir.Normalize();
|
||||
vPartDir = tm * vPartDir;
|
||||
vPartDir *= Params.fSpeed.GetVariantValue();
|
||||
|
||||
pPart->m_vDelta = vPartDir*fScale;
|
||||
}
|
||||
else if(Params.nParticleFlags & PART_FLAG_SPEED_IN_GRAVITY_DIRECTION)
|
||||
{
|
||||
Vec3d vGravityDir = -Params.vGravity;
|
||||
Vec3d vPartDir(rnd()-0.5f,rnd()-0.5f,rnd()-0.5f);
|
||||
if (vPartDir.IsZero()) vPartDir = Vec3(0,0,1);
|
||||
if (vGravityDir.IsZero())
|
||||
vGravityDir = Vec3(0,0,-1);
|
||||
else
|
||||
vGravityDir.Normalize();
|
||||
vPartDir.Normalize();
|
||||
vPartDir += vGravityDir*Params.fFocus;
|
||||
vPartDir.Normalize();
|
||||
vPartDir *= Params.fSpeed.GetVariantValue();/* * (0.75f+0.5f*rnd());*/
|
||||
pPart->m_vDelta = vPartDir*fScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3d vPartDir(rnd()-0.5f,rnd()-0.5f,rnd()-0.5f);
|
||||
vPartDir.Normalize();
|
||||
vPartDir += Params.vDirection*Params.fFocus;
|
||||
vPartDir.Normalize();
|
||||
vPartDir *= Params.fSpeed.GetVariantValue();/* * (0.75f+0.5f*rnd());*/
|
||||
pPart->m_vDelta = vPartDir*fScale;
|
||||
}
|
||||
|
||||
// do not move water waves in vertical direction
|
||||
if(Params.nParticleFlags & PART_FLAG_HORIZONTAL)
|
||||
pPart->m_vDelta.z = 0;
|
||||
|
||||
// set params
|
||||
if(Params.nParticleFlags & PART_FLAG_SPACELOOP)
|
||||
{
|
||||
pPart->m_vPos = Params.vPosition + Vec3d(rnd()-0.5f,rnd()-0.5f,rnd()-0.5f)*32;
|
||||
/*
|
||||
float fModX = fabs(Params.vDirection.x);
|
||||
float fModY = fabs(Params.vDirection.y);
|
||||
float fModZ = fabs(Params.vDirection.z);
|
||||
|
||||
if(fModX>fModY && fModX>fModZ)
|
||||
pPart->m_vPos.x = Params.vPosition.x + (Params.vDirection.x>0 ? -Params.vSpaceLoopBoxSize.x : Params.vSpaceLoopBoxSize.x);
|
||||
else if(fModY>fModX && fModY>fModZ)
|
||||
pPart->m_vPos.y = Params.vPosition.y + (Params.vDirection.y>0 ? -Params.vSpaceLoopBoxSize.y : Params.vSpaceLoopBoxSize.y);
|
||||
else
|
||||
pPart->m_vPos.z = Params.vPosition.z + (Params.vDirection.z>0 ? -Params.vSpaceLoopBoxSize.z : Params.vSpaceLoopBoxSize.z);*/
|
||||
}
|
||||
else if(Params.fPosRandomOffset)
|
||||
{ // random offset
|
||||
Vec3d vOffset(rnd()-0.5f,rnd()-0.5f,rnd()-0.5f);
|
||||
vOffset *= (Params.fPosRandomOffset*2)*fScale;
|
||||
pPart->m_vPos = Params.vPosition + vOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPart->m_vPos = Params.vPosition;
|
||||
}
|
||||
|
||||
if (!Params.vRandomPositionOffset.IsZero())
|
||||
{
|
||||
Vec3 vrnd;
|
||||
vrnd.x = (2.0f*rnd()-1.0f) * Params.vRandomPositionOffset.x;
|
||||
vrnd.y = (2.0f*rnd()-1.0f) * Params.vRandomPositionOffset.y;
|
||||
vrnd.z = (2.0f*rnd()-1.0f) * Params.vRandomPositionOffset.z;
|
||||
pPart->m_vPos += vrnd*fScale;
|
||||
}
|
||||
pPart->m_vPos += Params.vPositionOffset*fScale;
|
||||
|
||||
pPart->m_fSizeOriginal = Params.fSize.GetVariantValue()*fScale;
|
||||
pPart->m_fSize = pPart->m_fSizeOriginal;
|
||||
pPart->m_vAngles = Params.vInitAngles.GetVariantValue();
|
||||
pPart->m_vRotation = Params.vRotation.GetVariantValue();
|
||||
|
||||
pPart->m_fLifeTime = Params.fLifeTime.GetVariantValue();
|
||||
pPart->m_fSpawnTime = fCurrTime;
|
||||
|
||||
if (Params.fTailLenght)
|
||||
{
|
||||
pPart->m_nTailSteps = Params.nTailSteps;
|
||||
if (pPart->m_nTailSteps <= 0)
|
||||
pPart->m_nTailSteps = 8; // Default steps.
|
||||
if (pPart->m_nTailSteps > 16)
|
||||
pPart->m_nTailSteps = 16; // Max steps (Renderer cant do more).
|
||||
// init history stack
|
||||
pPart->m_fTrailCurPos = 1.0f;
|
||||
pPart->m_pArrvPosHistory = new Vec3[pPart->m_nTailSteps];
|
||||
for(int t=0; t < pPart->m_nTailSteps; t++)
|
||||
pPart->m_pArrvPosHistory[t] = Params.vPosition;
|
||||
}
|
||||
|
||||
// init physical particle if requested
|
||||
if(Params.bRealPhysics /* && GetCVars()->e_particles_allow_physics */)
|
||||
pPart->Physicalize( Params,m_pSystem->GetIPhysicalWorld() );
|
||||
|
||||
pPart->m_fChildSpawnLastTime = fCurrTime;
|
||||
|
||||
// set statobj
|
||||
// if(Params.pStatObj)
|
||||
// Params.pStatObj->RegisterUser(); // prevent object deleting
|
||||
|
||||
// get ambient color
|
||||
Vec3d vAmbientColor = m_p3DEngine->GetAmbientColorFromPosition(Params.vPosition);
|
||||
Vec3d vWorldColor = Get3DEngine()->GetWorldColor();
|
||||
vAmbientColor.x *= vWorldColor.x;
|
||||
vAmbientColor.y *= vWorldColor.y;
|
||||
vAmbientColor.z *= vWorldColor.z;
|
||||
vAmbientColor.CheckMin(Vec3d(1,1,1));
|
||||
|
||||
pPart->m_cAmbientColor = pPart->Vec2Color(vAmbientColor);
|
||||
|
||||
//pPart->m_nDynLightMask = 0;//pSystem->GetI3DEngine()->GetLightMaskFromPosition(Params.vPosition);
|
||||
|
||||
//float fSize = pPart->m_fSize;
|
||||
//pPart->m_nFogVolumeId = m_p3DEngine->GetFogVolumeIdFromBBox(
|
||||
//Params.vPosition-Vec3d(fSize,fSize,fSize),
|
||||
//Params.vPosition+Vec3d(fSize,fSize,fSize));
|
||||
if (Params.pMaterial)
|
||||
{
|
||||
pPart->m_pMaterial = Params.pMaterial;
|
||||
}
|
||||
else
|
||||
pPart->m_pMaterial = emitter.m_pMaterial;
|
||||
pPart->m_pSpawnerEntity = emitter.m_pSpawnerEntity;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSpriteManager::Render(CObjManager * pObjManager, CTerrain * pTerrain, int nRecursionLevel, CPartManager * pPartManager, IShader * pPartLightShader)
|
||||
{
|
||||
// update max sprites count if console variable changed
|
||||
if(m_nMaxSpritesCount != min(16384, max(16,GetCVars()->e_particles_max_count)))
|
||||
{
|
||||
m_nMaxSpritesCount = min(16384, max(16,GetCVars()->e_particles_max_count));
|
||||
delete [] m_arrSprites;
|
||||
m_arrSprites = new CSprite[m_nMaxSpritesCount];
|
||||
memset(m_arrSprites,0,sizeof(CSprite)*m_nMaxSpritesCount);
|
||||
m_nCurSpritesCount=0;
|
||||
}
|
||||
|
||||
// get orientation for billboard particles
|
||||
Matrix44 mat;
|
||||
mat.SetIdentity();
|
||||
GetRenderer()->GetModelViewMatrix(mat.GetData());
|
||||
Vec3d vRight,vUp,vFront;
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//vRight(mat.cell(0), mat.cell(4), mat.cell(8));
|
||||
//vUp (mat.cell(1), mat.cell(5), mat.cell(9));
|
||||
//vFront(mat.cell(2), mat.cell(6), mat.cell(10));
|
||||
vRight = GetNormalized(mat.GetColumn(0));
|
||||
vUp = GetNormalized(mat.GetColumn(1));
|
||||
vFront = GetNormalized(mat.GetColumn(2));
|
||||
|
||||
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
CCamera * pCamera = &GetViewCamera();
|
||||
CVars * pCVars = GetCVars();
|
||||
|
||||
PartProcessParams ProcParams;
|
||||
|
||||
ProcParams.fCurTime = pPartManager->GetParticlesTime();;
|
||||
ProcParams.fFrameTime = pPartManager->GetParticlesFrameTime();
|
||||
ProcParams.vRight=vRight;
|
||||
ProcParams.vUp=vUp;
|
||||
ProcParams.vFront=vFront;
|
||||
ProcParams.pIRenderer=GetRenderer();
|
||||
ProcParams.pObjManager=pObjManager;
|
||||
ProcParams.pTerrain=pTerrain;
|
||||
ProcParams.pPhysicalWorld=GetPhysicalWorld();
|
||||
ProcParams.pCamera=pCamera;
|
||||
ProcParams.pVertBufChunk=0;
|
||||
ProcParams.pSystem = GetSystem();
|
||||
ProcParams.p3DEngine = (C3DEngine*)m_p3DEngine;
|
||||
ProcParams.pPartManager = pPartManager;
|
||||
ProcParams.vCamPos = pCamera->GetPos();
|
||||
|
||||
for( int i=0; i<m_nCurSpritesCount && i<m_nMaxSpritesCount; i++)
|
||||
{
|
||||
bool bActive = true;
|
||||
|
||||
CSprite *pSprite = &m_arrSprites[i];
|
||||
|
||||
if(!nRecursionLevel)
|
||||
{
|
||||
bActive = pSprite->Update(ProcParams);
|
||||
//Vec3 vsz = Vec3(pSprite->m_fSize,pSprite->m_fSize,pSprite->m_fSize);
|
||||
//pSprite->m_pEmitter->m_bbox.Add( pSprite->m_vPos - vsz );
|
||||
//pSprite->m_pEmitter->m_bbox.Add( pSprite->m_vPos + vsz );
|
||||
}
|
||||
|
||||
if (!nRecursionLevel || (!(pSprite->m_nParticleFlags & PART_FLAG_HORIZONTAL)) )
|
||||
{
|
||||
bool bVisible = false;
|
||||
if(pSprite->m_nParticleFlags & PART_FLAG_LINEPARTICLE)
|
||||
{ // find bbox
|
||||
Vec3d vBoxMin = pSprite->m_vPos;
|
||||
Vec3d vBoxMax = pSprite->m_vPos;
|
||||
vBoxMin.CheckMin(pSprite->m_vPos + pSprite->m_vDelta);
|
||||
vBoxMax.CheckMax(pSprite->m_vPos + pSprite->m_vDelta);
|
||||
vBoxMin -= Vec3d(pSprite->m_fSize,pSprite->m_fSize,pSprite->m_fSize);
|
||||
vBoxMax += Vec3d(pSprite->m_fSize,pSprite->m_fSize,pSprite->m_fSize);
|
||||
bVisible = pCamera->IsAABBVisibleFast( AABB(vBoxMin,vBoxMax) );
|
||||
}
|
||||
else
|
||||
bVisible = pCamera->IsSphereVisibleFast( Sphere(pSprite->m_vPos,pSprite->m_fSize) );
|
||||
|
||||
if ( bVisible && (!(pSprite->m_nParticleFlags & PART_FLAG_SPACELIMIT) || bActive))
|
||||
pSprite->Render( ProcParams,pPartLightShader );
|
||||
}
|
||||
|
||||
if (!bActive)
|
||||
{ // remove
|
||||
pSprite->DeActivateParticle(GetPhysicalWorld());
|
||||
|
||||
if(i < m_nCurSpritesCount-1)
|
||||
{
|
||||
m_arrSprites[i] = m_arrSprites[m_nCurSpritesCount-1];
|
||||
memset(&m_arrSprites[m_nCurSpritesCount-1],0,sizeof(m_arrSprites[m_nCurSpritesCount-1]));
|
||||
}
|
||||
m_nCurSpritesCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
284
Cry3DEngine/StatObj.h
Normal file
284
Cry3DEngine/StatObj.h
Normal file
@@ -0,0 +1,284 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobj.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STAT_OBJ_H
|
||||
#define STAT_OBJ_H
|
||||
|
||||
const int FAR_TEX_COUNT = 24; // number of sprites per object
|
||||
const int FAR_TEX_ANGLE = (360/FAR_TEX_COUNT);
|
||||
const int FAR_TEX_SIZE = 64;
|
||||
|
||||
class CIndexedMesh;
|
||||
class CCObject;
|
||||
|
||||
#include "../Cry3DEngine/Cry3DEngineBase.h"
|
||||
#include "list2.h"
|
||||
|
||||
struct CStatObjSV;
|
||||
struct ItShadowVolume;
|
||||
|
||||
#include "istatobj.h"
|
||||
#include "istreamengine.h"
|
||||
|
||||
#define STATOBJ_EFT_PLANT (EFT_USER_FIRST+1)
|
||||
#define STATOBJ_EFT_PLANT_IN_SHADOW (EFT_USER_FIRST+2)
|
||||
|
||||
#define CGF_STREAMING_MAX_TIME_PER_FRAME 0.01f
|
||||
|
||||
struct CStatObj : public Cry3DEngineBase, public IStreamCallback, public IStatObj
|
||||
{
|
||||
CStatObj();
|
||||
~CStatObj();
|
||||
|
||||
CIndexedMesh * m_pTriData;
|
||||
CIndexedMesh * GetTriData() { return m_pTriData; }
|
||||
|
||||
int m_nLoadedTrisCount;
|
||||
const Vec3d GetCenter() { return m_vBoxCenter; }
|
||||
inline float GetRadius() { return m_fObjectRadius; }
|
||||
|
||||
char m_szFolderName[256];
|
||||
char m_szFileName [256];
|
||||
char m_szGeomName [256];
|
||||
|
||||
bool m_bDefaultObject;
|
||||
bool m_bOpenEdgesTested;
|
||||
|
||||
TArray<int> m_lstShaderTemplates;
|
||||
TArray <SShaderParam> m_ShaderParams;
|
||||
|
||||
uint m_arrSpriteTexID[FAR_TEX_COUNT];
|
||||
|
||||
float m_fObjectRadius;
|
||||
|
||||
void CalcRadiuses();
|
||||
|
||||
public:
|
||||
|
||||
// Loader
|
||||
bool Load(const char * szFileName, const char * szGeomName, enum EVertsSharing eVertsSharing,
|
||||
bool bLoadAdditinalInfo, bool bKeepInLocalSpace, bool bUseStreaming = false,
|
||||
bool bMakePhysics = true);
|
||||
|
||||
//! Returns script material name
|
||||
virtual const char * GetScriptMaterialName(int Id=-1);
|
||||
|
||||
virtual void Render(const SRendParams & rParams, const Vec3& t, int nLodLevel=0);
|
||||
|
||||
//virtual void RenderModel(const RenderParams *pParams);
|
||||
|
||||
// renders the shadow volumes of this whole object (together with attachments if any)
|
||||
// the implementation may or may not implement the limit lod functionality: if it does,
|
||||
// it will render the specified or lower LOD
|
||||
virtual void RenderShadowVolumes(const SRendParams *pParams,int nLimitLod = -1);
|
||||
|
||||
//! Refresh object ( reload shaders or/and object geometry )
|
||||
virtual void Refresh(int nFlags);
|
||||
|
||||
virtual bool SetShaderTemplate(int nTemplate, const char *TemplName, const char *ShaderName, bool bOnlyRegister=false, int * pnNewTemplateId = NULL);
|
||||
virtual void SetShaderFloat(const char *Name, float Val);
|
||||
//virtual void SetRefractFactor(float fRefr) { m_fRefractFactor = fRefr; }
|
||||
//! Sets color parameter
|
||||
virtual void SetColor(const char *Name, float fR, float fG, float fB, float fA);
|
||||
|
||||
//! set shadow volume
|
||||
ItShadowVolume *GetShadowVolume() { return (m_pSvObj);}
|
||||
|
||||
//! get shadow volume
|
||||
void SetShadowVolume(ItShadowVolume *pSvObj) { m_pSvObj=pSvObj;}
|
||||
|
||||
protected:
|
||||
void Physicalize();
|
||||
|
||||
void CreateModelFarImages(int nTexRes);
|
||||
|
||||
CLeafBuffer * m_pLeafBuffer;
|
||||
ItShadowVolume *m_pSvObj;
|
||||
int m_dwFlags,m_dwFlags2;
|
||||
|
||||
public:
|
||||
|
||||
CLeafBuffer * GetLeafBuffer() { return m_pLeafBuffer; };
|
||||
void SetLeafBuffer( CLeafBuffer *buf ) { m_pLeafBuffer = buf; };
|
||||
|
||||
Vec3d m_vBoxMin, m_vBoxMax, m_vBoxCenter;
|
||||
bool m_bPhysicsExistInCompiledFile;
|
||||
|
||||
Vec3d m_vPhysBoxMin[4], m_vPhysBoxMax[4];
|
||||
list2<Vec3d> m_lstProxyVerts[4];
|
||||
list2<int> m_lstProxyInds[4];
|
||||
list2<unsigned char> m_lstProxyFaceMaterials[4];
|
||||
|
||||
#define MAX_PHYS_GEOMS_IN_CGF 4
|
||||
phys_geometry * m_arrPhysGeomInfo[MAX_PHYS_GEOMS_IN_CGF];
|
||||
phys_geometry * GetPhysGeom(int n = 0) { return m_arrPhysGeomInfo[n]; }
|
||||
|
||||
const char *GetFolderName() { return (m_szFolderName); }
|
||||
const char *GetFileName() { return (m_szFileName); }
|
||||
const char *GetGeoName() { return (m_szGeomName); }
|
||||
bool IsSameObject(const char * szFileName, const char * szGeomName);
|
||||
|
||||
//set object's min/max bbox
|
||||
void SetBBoxMin(const Vec3d &vBBoxMin) { m_vBoxMin=vBBoxMin; }
|
||||
void SetBBoxMax(const Vec3d &vBBoxMax) { m_vBoxMax=vBBoxMax; }
|
||||
Vec3d GetBoxMin() { return m_vBoxMin; }
|
||||
Vec3d GetBoxMax() { return m_vBoxMax; }
|
||||
void GetBBox(Vec3d& Mins, Vec3d& Maxs)
|
||||
{
|
||||
Mins = m_vBoxMin;
|
||||
Maxs = m_vBoxMax;
|
||||
}
|
||||
|
||||
int m_nUsers; // reference counter
|
||||
|
||||
ShadowMapLightSource * m_pSMLSource;
|
||||
|
||||
void MakeShadowMaps(const Vec3d vSunPos);
|
||||
|
||||
protected:
|
||||
void MakeLeafBuffer(bool bSortAndShareVerts);
|
||||
|
||||
void PrepareShadowMaps(const Vec3d & obj_pos, ShadowMapLightSource * pLSource);
|
||||
|
||||
public:
|
||||
int GetAllocatedBytes();
|
||||
|
||||
void SetCurDynMask(int nCurDynMask);
|
||||
|
||||
int FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash);
|
||||
void CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices);
|
||||
|
||||
virtual Vec3d GetHelperPos(const char * szHelperName);
|
||||
virtual const char *GetHelperById(int nId, Vec3d & vPos, Matrix44 * pMat, int * pnType);
|
||||
virtual const Matrix44 * GetHelperMatrixByName(const char * szHelperName);
|
||||
|
||||
virtual void UpdateCustomLightingSpritesAndShadowMaps(Vec3d vStatObjAmbientColor, int nTexRes, float fBackSideLevel, bool bCalcLighting);
|
||||
|
||||
float m_fRadiusHors;
|
||||
float m_fRadiusVert;
|
||||
|
||||
float & GetRadiusVert() { return m_fRadiusVert; }
|
||||
float & GetRadiusHors() { return m_fRadiusHors; }
|
||||
|
||||
virtual void RegisterUser();
|
||||
virtual void UnregisterUser();
|
||||
|
||||
virtual bool IsDefaultObject() { return (m_bDefaultObject); }
|
||||
virtual bool MakeObjectPicture(unsigned char * pRGBAData, int nWidth);
|
||||
|
||||
#define MAX_STATOBJ_LODS_NUM 3
|
||||
CStatObj * m_arrpLowLODs[MAX_STATOBJ_LODS_NUM];
|
||||
void LoadLowLODs(EVertsSharing eVertsSharing, bool bLoadAdditinalInfo, bool bKeepInLocalSpace, bool bLoadLater);
|
||||
int m_nLoadedLodsNum;
|
||||
|
||||
bool IsSpritesCreated() { return m_arrSpriteTexID[0]>0; }
|
||||
float GetDistFromPoint(const Vec3d & vPoint);
|
||||
int GetLoadedTrisCount() { return m_nLoadedTrisCount; }
|
||||
int GetRenderTrisCount();
|
||||
|
||||
list2<Vec3d> m_lstOcclVolVerts;
|
||||
list2<int> m_lstOcclVolInds;
|
||||
|
||||
virtual bool GetOcclusionVolume(list2<Vec3d> * & plstOcclVolVerts, list2<int> * & plstOcclVolInds)
|
||||
{
|
||||
plstOcclVolVerts = &m_lstOcclVolVerts;
|
||||
plstOcclVolInds = &m_lstOcclVolInds;
|
||||
|
||||
return m_lstOcclVolInds.Count() >= 3;
|
||||
}
|
||||
list2<struct StatHelperInfo> m_lstHelpers;
|
||||
list2<CDLight> m_lstLSources;
|
||||
bool Serialize(int & nPos, uchar * pSerBuf, bool bSave, char * szFolderName);
|
||||
|
||||
virtual void FreeTriData();
|
||||
virtual const CDLight * GetLightSources(int nId);
|
||||
void RenderDebugInfo(const SRendParams & rParams, const class CCObject * pObj);
|
||||
void DrawMatrix(const Matrix44 & pMat);
|
||||
|
||||
//! Release method.
|
||||
void Release() { delete this; }
|
||||
void GetMemoryUsage(class ICrySizer* pSizer);
|
||||
int GetMemoryUsage();
|
||||
void SpawnParticles( ParticleParams & SpawnParticleParams, const Matrix44 & matWorldSpace, bool bOnlyUpLookingFaces );
|
||||
|
||||
// connectivity object that gets pre-computed for each model once and then
|
||||
// used to extract edge topology by the stencil shadowing module
|
||||
class IStencilShadowConnectivity* m_pStencilShadowConnectivity;
|
||||
// returns the cached connectivity object for stencil shadows
|
||||
class IStencilShadowConnectivity* getStencilShadowConnectivity( );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// builds the connectivity object for stencil shadows
|
||||
// PARAMETERS:
|
||||
// iEdgeBuilder - the builder to use to create the connectivity info
|
||||
// pbCastShadow - the array of flags, 1 flag per 1 material, if the flag is true, then this material casts shadow, otherwise not
|
||||
// numMaterials - number of items in the pbCastShadow array
|
||||
void ShutDown();
|
||||
void Init();
|
||||
void PhysicalizeCompiled();
|
||||
bool CompileInNeeded();
|
||||
|
||||
// loading state
|
||||
EVertsSharing m_eVertsSharing;
|
||||
bool m_bLoadAdditinalInfo;
|
||||
bool m_bKeepInLocalSpace;
|
||||
int m_nLastRendFrameId;
|
||||
int m_nMarkedForStreamingFrameId;
|
||||
bool m_bUseStreaming;
|
||||
bool m_bMakePhysics;
|
||||
static float m_fStreamingTimePerFrame;
|
||||
int m_nSpriteTexRes;
|
||||
float m_fBackSideLevel;
|
||||
bool m_bCalcLighting;
|
||||
static ItShadowVolume * MakeConnectivityInfo(CIndexedMesh * pMesh, const Vec3d & vOrigin, CStatObj * pStatObj);
|
||||
ItShadowVolume * MakeConnectivityInfoFromCompiledData(void * pStream, int & nPos, CStatObj * pStatObj);
|
||||
|
||||
bool CheckValidVegetation();
|
||||
bool EnableLightamapSupport();
|
||||
void CheckLoaded();
|
||||
IStatObj * GetLodObject(int nLodLevel);
|
||||
void StreamOnProgress (IReadStream* pStream);
|
||||
void StreamOnComplete (IReadStream* pStream, unsigned nError);
|
||||
|
||||
void StreamCCGF(bool bFinishNow);
|
||||
enum ECCGFStreamingStatus
|
||||
{
|
||||
ecss_NotLoaded,
|
||||
ecss_LoadingInProgress,
|
||||
ecss_Ready,
|
||||
ecss_LoadingError,
|
||||
ecss_GeomNotFound,
|
||||
} m_eCCGFStreamingStatus;
|
||||
|
||||
IReadStreamPtr m_pReadStream;
|
||||
|
||||
bool LoadUncompiled(const char * szFileName,
|
||||
const char * szGeomName,
|
||||
EVertsSharing eVertsSharing,
|
||||
bool bLoadAdditinalInfo,
|
||||
bool bKeepInLocalSpace,
|
||||
bool bLoadLater,
|
||||
bool bMakePhysics);
|
||||
void MakeCompiledFileName(char * szCompiledFileName, int nMaxLen);
|
||||
int m_bCompilingNotAllowed;
|
||||
void ProcessStreamOnCompleteError();
|
||||
|
||||
bool IsPhysicsExist();
|
||||
void PreloadResources(float fDist, float fTime, int dwFlags);
|
||||
void InitCompiledLightSource(CDLight * pDLight);
|
||||
void SetupBending(CCObject * pObj, float fBending);
|
||||
bool IsSphereOverlap(const Sphere& sSphere);
|
||||
};
|
||||
|
||||
#endif // STAT_OBJ_H
|
||||
166
Cry3DEngine/StatObjCompiler.cpp
Normal file
166
Cry3DEngine/StatObjCompiler.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "irenderer.h"
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
bool CStatObj::CompileInNeeded()
|
||||
{
|
||||
if(!GetCVars()->e_ccgf_make_if_not_found)
|
||||
return true;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
char szCompiledFileName[MAX_PATH_LENGTH];
|
||||
MakeCompiledFileName(szCompiledFileName,MAX_PATH_LENGTH);
|
||||
|
||||
CCGFHeader fileHeader;
|
||||
// read header from compiled first
|
||||
FILE * f = GetSystem()->GetIPak()->FOpen(szCompiledFileName, "rb");
|
||||
if(f)
|
||||
{
|
||||
int nReaded = GetSystem()->GetIPak()->FRead(&fileHeader, 1, sizeof(fileHeader), f);
|
||||
assert(nReaded == sizeof(CCGFHeader));
|
||||
GetSystem()->GetIPak()->FClose(f);
|
||||
}
|
||||
|
||||
// get date of source file
|
||||
FILE* fTmp = GetSystem()->GetIPak()->FOpen(m_szFileName, "rb");
|
||||
if (!fTmp)
|
||||
return false;
|
||||
|
||||
FILETIME ftSourceFileTime = GetSystem()->GetIPak()->GetModificationTime(fTmp);
|
||||
GetSystem()->GetIPak()->FClose(fTmp);
|
||||
if(ftSourceFileTime.dwHighDateTime == 0 && ftSourceFileTime.dwLowDateTime == 0)
|
||||
return false; // source file not found
|
||||
|
||||
#ifdef _DEBUG
|
||||
HANDLE _dbg_h = CreateFile (m_szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||||
FILETIME _dbg_ft = {0,0};
|
||||
if (_dbg_h != INVALID_HANDLE_VALUE)
|
||||
GetFileTime (_dbg_h, &_dbg_ft, NULL, &_dbg_ft);
|
||||
|
||||
SYSTEMTIME _dbg_st1, _dbg_st2;
|
||||
FileTimeToSystemTime(&fileHeader.SourceFileTime, &_dbg_st1);
|
||||
FileTimeToSystemTime(&ftSourceFileTime, &_dbg_st2);
|
||||
#endif
|
||||
|
||||
// compare date of source file and date of source file used to build this ccgf
|
||||
if(!CompareFileTime(&fileHeader.SourceFileTime, &ftSourceFileTime))
|
||||
if(!strcmp(fileHeader.szVersion,CCGF_FILE_VERSION))
|
||||
if(fileHeader.nStructuresCheckSummm == CCGFHeader::GetStructuresCheckSummm())
|
||||
{
|
||||
if(!fileHeader.nDataSize)
|
||||
{
|
||||
assert(m_szGeomName[0]);
|
||||
return false; // geom name was specified but not found in source sgf during compilation (valid state)
|
||||
}
|
||||
|
||||
return true; // no recompilation required
|
||||
}
|
||||
|
||||
// make command for execution
|
||||
char szRemoteCmdLine[512];
|
||||
snprintf(szRemoteCmdLine, sizeof(szRemoteCmdLine),
|
||||
RC_EXECUTABLE " \"%s\" /GeomName=%s /Stripify=%d /LoadAdditinalInfo=%d /KeepInLocalSpace=%d /StaticCGF=1 /refresh",
|
||||
m_szFileName, m_szGeomName,
|
||||
int(m_eVertsSharing==evs_ShareAndSortForCache), int(m_bLoadAdditinalInfo), int(m_bKeepInLocalSpace)
|
||||
);
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
si.dwX = 100;
|
||||
si.dwY = 100;
|
||||
si.dwFlags = STARTF_USEPOSITION;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory( &pi, sizeof(pi) );
|
||||
|
||||
// Start the child process.
|
||||
GetLog()->UpdateLoadingScreen("Executing " RC_EXECUTABLE " for %s", m_szFileName);
|
||||
GetLog()->Log("\004Command line: %s", szRemoteCmdLine);
|
||||
|
||||
if( !CreateProcess( NULL, // No module name (use command line).
|
||||
szRemoteCmdLine, // Command line.
|
||||
NULL, // Process handle not inheritable.
|
||||
NULL, // Thread handle not inheritable.
|
||||
FALSE, // Set handle inheritance to FALSE.
|
||||
GetCVars()->e_ccgf_make_if_not_found == 2 ? 0 : CREATE_NO_WINDOW, // No creation flags.
|
||||
NULL, // Use parent's environment block.
|
||||
NULL/*szFolderName*/, // Set starting directory.
|
||||
&si, // Pointer to STARTUPINFO structure.
|
||||
&pi ) // Pointer to PROCESS_INFORMATION structure.
|
||||
)
|
||||
{
|
||||
GetSystem()->Error( "CreateProcess failed: %s", szRemoteCmdLine);
|
||||
}
|
||||
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
|
||||
// check compiled file
|
||||
f = GetSystem()->GetIPak()->FOpen(szCompiledFileName, "rb");
|
||||
if(f)
|
||||
{
|
||||
int nReaded = GetSystem()->GetIPak()->FRead(&fileHeader, 1, sizeof(fileHeader), f);
|
||||
GetSystem()->GetIPak()->FClose(f);
|
||||
if(nReaded == sizeof(CCGFHeader))
|
||||
{
|
||||
if( ftSourceFileTime.dwHighDateTime == fileHeader.SourceFileTime.dwHighDateTime &&
|
||||
ftSourceFileTime.dwLowDateTime == fileHeader.SourceFileTime.dwLowDateTime)
|
||||
{
|
||||
if(strcmp(fileHeader.szVersion,CCGF_FILE_VERSION))
|
||||
GetSystem()->Error(" " RC_EXECUTABLE " version error\n"
|
||||
"File produced by resource compiler has wrong version [%s]\n"
|
||||
"Must be [%s]\n"
|
||||
"File name is %s",
|
||||
fileHeader.szVersion, CCGF_FILE_VERSION, szCompiledFileName);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetSystem()->Error(" " RC_EXECUTABLE " execution error\n"
|
||||
"File produced by resource compiler has time stamp different from source file time\n"
|
||||
"File name is %s", szCompiledFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
GetSystem()->Error(" " RC_EXECUTABLE " execution error\n"
|
||||
"Resource compiler was not able to produce CCGF file\n"
|
||||
"File name is %s", szCompiledFileName);
|
||||
|
||||
return false;
|
||||
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
620
Cry3DEngine/StatObjConstr.cpp
Normal file
620
Cry3DEngine/StatObjConstr.cpp
Normal file
@@ -0,0 +1,620 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: creation
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
#include <irenderer.h>
|
||||
#include <CrySizer.h>
|
||||
#include "objman.h"
|
||||
|
||||
float CStatObj::m_fStreamingTimePerFrame=0;
|
||||
|
||||
void CStatObj::FreeTriData()
|
||||
{
|
||||
delete m_pTriData;
|
||||
m_pTriData=0;
|
||||
}
|
||||
|
||||
const char * CStatObj::GetScriptMaterialName(int Id)
|
||||
{
|
||||
CLeafBuffer *lb = m_pLeafBuffer;
|
||||
if (Id < 0)
|
||||
{
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
if ((*lb->m_pMats)[i].sScriptMaterial[0])
|
||||
return (*lb->m_pMats)[i].sScriptMaterial;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
if (Id < lb->m_pMats->Count() && (*lb->m_pMats)[Id].sScriptMaterial[0])
|
||||
return (*lb->m_pMats)[Id].sScriptMaterial;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CStatObj::CalcRadiuses()
|
||||
{
|
||||
m_vBoxCenter = (m_vBoxMax+m_vBoxMin)*0.5f;
|
||||
m_fObjectRadius = GetDistance(m_vBoxMin, m_vBoxMax)*0.5f;
|
||||
float dxh = (float)max( fabs(GetBoxMax().x), fabs(GetBoxMin().x));
|
||||
float dyh = (float)max( fabs(GetBoxMax().y), fabs(GetBoxMin().y));
|
||||
m_fRadiusHors = (float)cry_sqrtf(dxh*dxh+dyh*dyh);
|
||||
m_fRadiusVert = (GetBoxMax().z - GetBoxMin().z)*0.5f;// never change this
|
||||
}
|
||||
|
||||
CStatObj::CStatObj( )
|
||||
{
|
||||
m_nUsers = 0; // referense counter
|
||||
m_bOpenEdgesTested = false;
|
||||
|
||||
m_eVertsSharing=evs_NoSharing;
|
||||
m_bLoadAdditinalInfo=false;
|
||||
m_bKeepInLocalSpace=false;
|
||||
m_bUseStreaming=false;
|
||||
m_bMakePhysics=false;
|
||||
m_nSpriteTexRes=0;
|
||||
|
||||
ZeroStruct( m_szFolderName );
|
||||
ZeroStruct( m_szFileName );
|
||||
ZeroStruct( m_szGeomName );
|
||||
|
||||
m_pStencilShadowConnectivity=0;
|
||||
|
||||
m_nLastRendFrameId = 0;
|
||||
m_nMarkedForStreamingFrameId = 0;
|
||||
m_fBackSideLevel = 1.f;
|
||||
m_bCalcLighting = false;
|
||||
|
||||
memset(m_arrpLowLODs,0,sizeof(m_arrpLowLODs));
|
||||
m_nLoadedLodsNum=1;
|
||||
|
||||
m_bPhysicsExistInCompiledFile=false;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void CStatObj::Init()
|
||||
{
|
||||
m_pTriData = 0;
|
||||
m_nLoadedTrisCount = 0;
|
||||
m_fObjectRadius = 0;
|
||||
m_fRadiusHors = 0;
|
||||
m_fRadiusVert = 0;
|
||||
m_pSvObj=NULL;
|
||||
m_dwFlags=m_dwFlags2=0;
|
||||
|
||||
ZeroStruct( m_arrSpriteTexID );
|
||||
|
||||
m_vBoxMin.Set(0,0,0);
|
||||
m_vBoxMax.Set(0,0,0);
|
||||
m_vBoxCenter.Set(0,0,0);
|
||||
memset(m_arrPhysGeomInfo, 0, sizeof(m_arrPhysGeomInfo));
|
||||
|
||||
m_pSMLSource = 0;
|
||||
|
||||
m_pLeafBuffer = 0;
|
||||
|
||||
m_bDefaultObject=false;
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
m_arrpLowLODs[i]->Init();
|
||||
|
||||
m_eCCGFStreamingStatus = ecss_NotLoaded;
|
||||
m_pReadStream=0;
|
||||
m_bCompilingNotAllowed=0;
|
||||
}
|
||||
|
||||
CStatObj::~CStatObj()
|
||||
{
|
||||
ShutDown();
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
delete m_arrpLowLODs[i];
|
||||
}
|
||||
|
||||
void CStatObj::ShutDown()
|
||||
{
|
||||
// assert (IsHeapValid());
|
||||
m_pReadStream=0;
|
||||
|
||||
if(m_pTriData)
|
||||
m_pTriData->FreeLMInfo();
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
delete m_pTriData;
|
||||
m_pTriData = 0;
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
for(int n=0; n<2; n++)
|
||||
if(m_arrPhysGeomInfo[n])
|
||||
GetPhysicalWorld()->GetGeomManager()->UnregisterGeometry(m_arrPhysGeomInfo[n]);
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
if(m_pSMLSource && m_pSMLSource->m_LightFrustums.Count() && m_pSMLSource->m_LightFrustums[0].pModelsList)
|
||||
delete m_pSMLSource->m_LightFrustums[0].pModelsList;
|
||||
delete m_pSMLSource;
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
if(m_pLeafBuffer && !m_pLeafBuffer->m_bMaterialsWasCreatedInRenderer)
|
||||
{
|
||||
for (int i=0; i<(*m_pLeafBuffer->m_pMats).Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = m_pLeafBuffer->m_pMats->Get(i);
|
||||
if(mi->pRE)
|
||||
mi->pRE->Release();
|
||||
if (mi->shaderItem.m_pShader)
|
||||
mi->shaderItem.m_pShader->Release();
|
||||
if (mi->shaderItem.m_pShaderResources)
|
||||
mi->shaderItem.m_pShaderResources->Release();
|
||||
}
|
||||
delete m_pLeafBuffer->m_pMats;
|
||||
m_pLeafBuffer->m_pMats=0;
|
||||
}
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
|
||||
// assert (IsHeapValid());
|
||||
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
if(m_arrSpriteTexID[i])
|
||||
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
|
||||
|
||||
if (m_pSvObj)
|
||||
{
|
||||
// assert (IsHeapValid());
|
||||
m_pSvObj->Release();
|
||||
m_pSvObj=NULL;
|
||||
}
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
{
|
||||
if(m_arrpLowLODs[i])
|
||||
m_arrpLowLODs[i]->ShutDown();
|
||||
}
|
||||
|
||||
m_ShaderParams.Free();
|
||||
|
||||
// free light source smart pointers
|
||||
for(int i=0; i<m_lstLSources.Count(); i++)
|
||||
{
|
||||
m_lstLSources[i].m_pLightImage = NULL;
|
||||
m_lstLSources[i].m_pShader = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void CStatObj::BuildOcTree()
|
||||
{
|
||||
if(!m_pTriData->m_nFaceCount || m_pTriData->m_nFaceCount<=2)
|
||||
return;
|
||||
|
||||
CBox parent_box( m_pTriData->m_vBoxMin, m_pTriData->m_vBoxMax );
|
||||
parent_box.max += 0.01f;
|
||||
parent_box.min +=-0.01f;
|
||||
|
||||
CObjFace ** allFaces = new CObjFace *[m_pTriData->m_nFaceCount];
|
||||
|
||||
for(int f=0; f<m_pTriData->m_nFaceCount; f++)
|
||||
{
|
||||
m_pTriData->m_pFaces[f].m_vCenter =
|
||||
(Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[0]].x) +
|
||||
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[1]].x) +
|
||||
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[2]].x))/3.f;
|
||||
|
||||
allFaces[f] = &m_pTriData->m_pFaces[f];
|
||||
}
|
||||
|
||||
const int max_tris_in_leaf = 2000;
|
||||
const float leaf_min_size = stricmp(m_szGeomName,"sector_0") ? 16.f : 32.f;
|
||||
|
||||
text_to_log(" Generating octree ... ");
|
||||
m_pOcTree = new octree_node( &parent_box, allFaces, triData->m_nFaceCount, triData, leaf_min_size, max_tris_in_leaf, 2);
|
||||
text_to_log_plus("%d leafs created", octree_node::static_current_leaf_id);
|
||||
m_pOcTree->update_bbox(triData);
|
||||
|
||||
delete [] allFaces;
|
||||
}*/
|
||||
|
||||
//float M akeBuffersTime = 0;
|
||||
|
||||
void CStatObj::MakeLeafBuffer(bool bSortAndShareVerts)
|
||||
{
|
||||
if(GetSystem()->IsDedicated())
|
||||
return;
|
||||
|
||||
assert(!m_pLeafBuffer);
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBuffer(eBT_Static,"StatObj");
|
||||
|
||||
m_pLeafBuffer->m_pMats = new list2<CMatInfo>;
|
||||
m_pLeafBuffer->m_pMats->AddList(m_pTriData->m_lstMatTable);
|
||||
|
||||
if(bSortAndShareVerts)
|
||||
bSortAndShareVerts=bSortAndShareVerts;
|
||||
|
||||
if(m_pTriData->m_nFaceCount)
|
||||
m_pLeafBuffer->CreateBuffer(m_pTriData, bSortAndShareVerts, true, //false,);
|
||||
m_pTriData->m_lstGeomNames.Count()>0 && strstr(m_pTriData->m_lstGeomNames[0],"cloth")!=0);
|
||||
|
||||
// remove materials without geometry
|
||||
if(m_bIgnoreFakeMaterialsInCGF)
|
||||
if(m_pLeafBuffer && !m_pLeafBuffer->m_bMaterialsWasCreatedInRenderer)
|
||||
{
|
||||
for (int i=0; i<(*m_pLeafBuffer->m_pMats).Count(); i++)
|
||||
{
|
||||
CMatInfo *mi = m_pLeafBuffer->m_pMats->Get(i);
|
||||
if(!mi->pRE || !mi->nNumIndices || !mi->nNumVerts)
|
||||
{
|
||||
if (mi->shaderItem.m_pShader)
|
||||
mi->shaderItem.m_pShader->Release();
|
||||
if (mi->shaderItem.m_pShaderResources)
|
||||
mi->shaderItem.m_pShaderResources->Release();
|
||||
m_pLeafBuffer->m_pMats->Delete(i);
|
||||
|
||||
if(i<m_lstShaderTemplates.Num())
|
||||
m_lstShaderTemplates.DelElem(i);
|
||||
i--;
|
||||
}
|
||||
else
|
||||
mi->pRE->m_pChunk = mi;
|
||||
}
|
||||
}
|
||||
|
||||
int nDeleted = m_pTriData->m_lstMatTable.Count() - m_pLeafBuffer->m_pMats->Count();
|
||||
if(nDeleted)
|
||||
CryLogComment(" %d not used material slots removed", nDeleted);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CStatObj::GetAllocatedBytes()
|
||||
{
|
||||
int size = sizeof(*this) + m_pTriData ? m_pTriData->GetAllocatedBytes() : 0;
|
||||
|
||||
// for(int i=0; i<MAX_TREE_LEAFS_NUM; i++)
|
||||
{
|
||||
size += m_pLeafBuffer->GetAllocatedBytes(false);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
Vec3d CStatObj::GetHelperPos(const char * szHelperName)
|
||||
{
|
||||
for(int i=0; i<m_lstHelpers.Count(); i++)
|
||||
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
|
||||
return m_lstHelpers[i].tMat.GetTranslationOLD();
|
||||
|
||||
return Vec3d(0,0,0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const Matrix44 * CStatObj::GetHelperMatrixByName(const char * szHelperName)
|
||||
{
|
||||
for(int i=0; i<m_lstHelpers.Count(); i++)
|
||||
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
|
||||
return &(m_lstHelpers[i].tMat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
const char *CStatObj::GetHelperById(int nId, Vec3d & vPos, Matrix44* pMat, int * pnType)
|
||||
{
|
||||
if ( nId >= m_lstHelpers.Count() || nId<0 )
|
||||
return (NULL);
|
||||
|
||||
vPos = m_lstHelpers[nId].tMat.GetTranslationOLD();
|
||||
|
||||
if(pnType)
|
||||
*pnType = m_lstHelpers[nId].nType;
|
||||
|
||||
if(pMat)
|
||||
*pMat = m_lstHelpers[nId].tMat;
|
||||
|
||||
return (m_lstHelpers[nId].sName);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CStatObj::GetHelper(int id, char * szHelperName, int nMaxHelperNameSize, Vec3d * pPos, Vec3d * pRot)
|
||||
{
|
||||
if(id<0 || id>=triData->m_Helpers.Count())
|
||||
return false;
|
||||
|
||||
strncpy(szHelperName, triData->m_Helpers[id].name, nMaxHelperNameSize);
|
||||
*pPos = triData->m_Helpers[id].pos;
|
||||
*pRot = triData->m_Helpers[id].rot;
|
||||
return true;
|
||||
} */
|
||||
|
||||
void CStatObj::UpdateCustomLightingSpritesAndShadowMaps(Vec3d vStatObjAmbientColor, int nTexRes, float fBackSideLevel, bool bCalcLighting)
|
||||
{
|
||||
AUTO_PROFILE_SECTION(GetTimer(), CObjManager::m_dUpdateCustomLightingSpritesAndShadowMaps);
|
||||
|
||||
m_nSpriteTexRes = nTexRes;
|
||||
m_fBackSideLevel = fBackSideLevel;
|
||||
m_bCalcLighting = bCalcLighting;
|
||||
Vec3d vLight = GetSystem()->GetI3DEngine()->GetSunPosition();
|
||||
vLight.Normalize();
|
||||
// Vec3d vColor = GetSystem()->GetI3DEngine()->GetWorldColor();
|
||||
float fSize = m_vBoxMax.z - m_vBoxMin.z;
|
||||
|
||||
// update lighting for full lod and lower lods
|
||||
if(m_pLeafBuffer)
|
||||
m_pLeafBuffer->UpdateCustomLighting( m_fBackSideLevel, vStatObjAmbientColor, vLight, bCalcLighting );
|
||||
|
||||
int nLowestLod=0;
|
||||
for(int nLodLevel=1; nLodLevel<MAX_STATOBJ_LODS_NUM; nLodLevel++)
|
||||
if(m_arrpLowLODs[nLodLevel])
|
||||
{
|
||||
if(m_arrpLowLODs[nLodLevel]->GetLeafBuffer())
|
||||
{
|
||||
m_arrpLowLODs[nLodLevel]->GetLeafBuffer()->UpdateCustomLighting( m_fBackSideLevel, vStatObjAmbientColor, vLight, bCalcLighting );
|
||||
nLowestLod = nLodLevel;
|
||||
}
|
||||
}
|
||||
|
||||
// make sprites
|
||||
if(nLowestLod)
|
||||
{
|
||||
// clear sprites in full lod
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
if(m_arrSpriteTexID[i])
|
||||
{
|
||||
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
|
||||
m_arrSpriteTexID[i]=0;
|
||||
}
|
||||
|
||||
// make new sprites in low lod
|
||||
m_arrpLowLODs[nLowestLod]->CreateModelFarImages(nTexRes); // use lowest lod if present
|
||||
|
||||
// move sprite id from low inro into full lod
|
||||
memcpy(m_arrSpriteTexID, m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, sizeof(m_arrSpriteTexID));
|
||||
memset(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, 0, sizeof(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID));
|
||||
m_nSpriteTexRes = m_arrpLowLODs[nLowestLod]->m_nSpriteTexRes;
|
||||
}
|
||||
else
|
||||
CreateModelFarImages(nTexRes);
|
||||
|
||||
|
||||
MakeShadowMaps(vLight);
|
||||
|
||||
// if(m_pTriData && !m_pTriData->m_lstLSources.Count())
|
||||
// FreeTriData();
|
||||
}
|
||||
|
||||
/*
|
||||
const char * CStatObj::GetPhysMaterialName(int nMatID)
|
||||
{
|
||||
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
|
||||
return m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CStatObj::SetPhysMaterialName(int nMatID, const char * szPhysMatName)
|
||||
{
|
||||
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
|
||||
{
|
||||
strncpy(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat, szPhysMatName, sizeof(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
void CStatObj::RegisterUser()
|
||||
{
|
||||
m_nUsers++;
|
||||
}
|
||||
|
||||
void CStatObj::UnregisterUser()
|
||||
{
|
||||
m_nUsers--;
|
||||
}
|
||||
|
||||
float CStatObj::GetDistFromPoint(const Vec3d & vPoint)
|
||||
{
|
||||
float fMinDist = 4096;
|
||||
for(int v=0; v<m_pTriData->m_nVertCount; v++)
|
||||
{
|
||||
float fDist = GetDistance(m_pTriData->m_pVerts[v],vPoint);
|
||||
if(fDist < fMinDist)
|
||||
fMinDist = fDist;
|
||||
}
|
||||
|
||||
return fMinDist;
|
||||
}
|
||||
|
||||
bool CStatObj::IsSameObject(const char * szFileName, const char * szGeomName)
|
||||
{
|
||||
// cmp object names
|
||||
if (szGeomName)
|
||||
{
|
||||
// [Anton] - always use new cgf for objects used for cloth simulation
|
||||
if (*szGeomName && stricmp(szGeomName,"cloth") == 0)
|
||||
return false;
|
||||
|
||||
if(stricmp(szGeomName,m_szGeomName)!=0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Normilize file name
|
||||
char szFileNameNorm[MAX_PATH_LENGTH]="";
|
||||
char *pszDest = szFileNameNorm;
|
||||
const char *pszSource = szFileName;
|
||||
while (*pszSource)
|
||||
{
|
||||
if (*pszSource=='/')
|
||||
*pszDest++='\\';
|
||||
else
|
||||
*pszDest++=*pszSource;
|
||||
pszSource++;
|
||||
}
|
||||
*pszDest=0;
|
||||
|
||||
// cmp file names
|
||||
if(stricmp(szFileNameNorm,m_szFileName)!=0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStatObj::GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,GetMemoryUsage());
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
int CStatObj::GetMemoryUsage()
|
||||
{
|
||||
int nSize=0;
|
||||
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
nSize += m_arrpLowLODs[i]->GetMemoryUsage();
|
||||
|
||||
nSize += m_lstHelpers.GetMemoryUsage();
|
||||
nSize += m_lstLSources.GetMemoryUsage();
|
||||
nSize += m_lstOcclVolInds.GetMemoryUsage();
|
||||
nSize += m_lstOcclVolVerts.GetMemoryUsage();
|
||||
nSize += m_lstShaderTemplates.GetMemoryUsage();
|
||||
nSize += m_pSMLSource ? sizeof(*m_pSMLSource) : 0;
|
||||
nSize += m_pSvObj ? m_pSvObj->GetMemoryUsage() : 0;
|
||||
nSize += m_pTriData ? m_pTriData->GetMemoryUsage() : 0;
|
||||
nSize += m_ShaderParams.GetMemoryUsage() + m_ShaderParams.Num()*sizeof(SShaderParam);
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
bool CStatObj::CheckValidVegetation()
|
||||
{
|
||||
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats)
|
||||
for(int i=0; i<m_pLeafBuffer->m_pMats->Count(); i++)
|
||||
{
|
||||
CMatInfo * pMatInfo = m_pLeafBuffer->m_pMats->Get(i);
|
||||
IShader * pShader = pMatInfo->shaderItem.m_pShader;
|
||||
if(!pShader || !pMatInfo->nNumIndices)
|
||||
continue;
|
||||
|
||||
pShader = pShader->GetTemplate(0);
|
||||
|
||||
const char * pTemplateName = pShader->GetName();
|
||||
char buff[64];
|
||||
strncpy(buff, pTemplateName, sizeof(buff)); buff[sizeof(buff)-1]=0;
|
||||
strlwr(buff);
|
||||
if( !strstr(buff,"templplants") &&
|
||||
!strstr(buff,"nodraw") &&
|
||||
!strstr(buff,"templdecal_vcolors") &&
|
||||
!strstr(buff,"templdecalalphatest_vcolors"))
|
||||
{
|
||||
#if !defined(LINUX)//don't worry, we won't render anything under linux
|
||||
Warning( 0,m_szFileName,"CStatObj::CheckValidVegetation: Shader template is undefined or can not be used for vegetations: %s [%s]",
|
||||
pTemplateName, m_szFileName);
|
||||
// return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStatObj::EnableLightamapSupport()
|
||||
{
|
||||
assert(m_eVertsSharing == evs_NoSharing);
|
||||
|
||||
if(m_eVertsSharing == evs_NoSharing)
|
||||
return true;
|
||||
/*
|
||||
GetLog()->Log("Activating lightamap support for %s", m_szFileName);
|
||||
|
||||
m_eVertsSharing = evs_NoSharing;
|
||||
|
||||
Refresh(FRO_GEOMETRY);
|
||||
*/
|
||||
return false;//!m_bDefaultObject;
|
||||
}
|
||||
|
||||
IStatObj * CStatObj::GetLodObject(int nLodLevel)
|
||||
{
|
||||
if(nLodLevel<1)
|
||||
return this;
|
||||
|
||||
if(nLodLevel<3)
|
||||
return (IStatObj *)m_arrpLowLODs[nLodLevel];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CStatObj::IsPhysicsExist()
|
||||
{
|
||||
return m_bPhysicsExistInCompiledFile || GetPhysGeom(0) || GetPhysGeom(1) || GetPhysGeom(2);
|
||||
}
|
||||
|
||||
int CStatObj::GetRenderTrisCount()
|
||||
{
|
||||
int nCount=0;
|
||||
if(GetLeafBuffer())
|
||||
GetLeafBuffer()->GetIndices(&nCount);
|
||||
|
||||
return nCount/3;
|
||||
}
|
||||
|
||||
bool CStatObj::IsSphereOverlap(const Sphere& sSphere)
|
||||
{
|
||||
if(m_pLeafBuffer && Overlap::Sphere_AABB(sSphere,AABB(m_vBoxMin,m_vBoxMax)))
|
||||
{ // if inside bbox
|
||||
int nInds = 0, nPosStride=0;
|
||||
ushort *pInds = m_pLeafBuffer->GetIndices(&nInds);
|
||||
const byte * pPos = m_pLeafBuffer->GetPosPtr(nPosStride,0,true);
|
||||
|
||||
if(pInds && pPos)
|
||||
for(int i=0; (i+2)<nInds; i+=3)
|
||||
{ // test all triangles of water surface strip
|
||||
Vec3d v0 = *(Vec3d*)&pPos[nPosStride*pInds[i+0]];
|
||||
Vec3d v1 = *(Vec3d*)&pPos[nPosStride*pInds[i+1]];
|
||||
Vec3d v2 = *(Vec3d*)&pPos[nPosStride*pInds[i+2]];
|
||||
Vec3d vBoxMin = v0; vBoxMin.CheckMin(v1); vBoxMin.CheckMin(v2);
|
||||
Vec3d vBoxMax = v0; vBoxMax.CheckMax(v1); vBoxMax.CheckMax(v2);
|
||||
|
||||
if( Overlap::Sphere_AABB(sSphere,AABB(vBoxMin,vBoxMax)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
48
Cry3DEngine/StatObjFar.cpp
Normal file
48
Cry3DEngine/StatObjFar.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjfar.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: making sprites for object
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
|
||||
void CStatObj::CreateModelFarImages(int nTexRes)
|
||||
{
|
||||
if(!nTexRes)
|
||||
nTexRes = FAR_TEX_SIZE;
|
||||
|
||||
nTexRes /= (1<<GetCVars()->e_vegetation_sprites_texres);
|
||||
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
{
|
||||
GetRenderer()->ResetToDefault();
|
||||
|
||||
if(m_arrSpriteTexID[i])
|
||||
{
|
||||
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
|
||||
m_arrSpriteTexID[i]=0;
|
||||
}
|
||||
|
||||
m_arrSpriteTexID[i] = GetRenderer()->MakeSprite(18.f, nTexRes,
|
||||
i*FAR_TEX_ANGLE+90.f, this, 0, m_arrSpriteTexID[i]);
|
||||
}
|
||||
|
||||
GetRenderer()->ResetToDefault();
|
||||
}
|
||||
|
||||
bool CStatObj::MakeObjectPicture(unsigned char * pRGBAData, int nWidth)
|
||||
{
|
||||
int nTid = GetRenderer()->MakeSprite(m_vBoxMax.z, nWidth,45,this,pRGBAData,0);
|
||||
return nTid>0;
|
||||
}
|
||||
269
Cry3DEngine/StatObjLoad.cpp
Normal file
269
Cry3DEngine/StatObjLoad.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
|
||||
void CStatObj::Refresh(int nFlags)
|
||||
{
|
||||
if(nFlags & FRO_GEOMETRY)
|
||||
{
|
||||
bool bSpritesWasCreated = IsSpritesCreated();
|
||||
ShutDown();
|
||||
Init();
|
||||
bool bRes = Load(m_szFileName, m_szGeomName[0] ? m_szGeomName : 0, m_eVertsSharing,
|
||||
m_bLoadAdditinalInfo, m_bKeepInLocalSpace, false);
|
||||
|
||||
LoadLowLODs(m_eVertsSharing, m_bLoadAdditinalInfo, m_bKeepInLocalSpace, false);
|
||||
|
||||
if(bRes && bSpritesWasCreated)
|
||||
{
|
||||
Vec3d vColor = Get3DEngine()->GetAmbientColorFromPosition(Vec3d(-1000,-1000,-1000));
|
||||
UpdateCustomLightingSpritesAndShadowMaps( vColor, m_nSpriteTexRes, m_fBackSideLevel, m_bCalcLighting );
|
||||
}
|
||||
|
||||
if(!bRes)
|
||||
{ // load default in case of error
|
||||
ShutDown();
|
||||
Init();
|
||||
Load("Objects\\default.cgf", 0, m_eVertsSharing, m_bLoadAdditinalInfo, m_bKeepInLocalSpace);
|
||||
m_bDefaultObject = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (nFlags & (FRO_TEXTURES | FRO_SHADERS))
|
||||
{
|
||||
CLeafBuffer *lb = m_pLeafBuffer;
|
||||
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
IShader *e = (*lb->m_pMats)[i].shaderItem.m_pShader;
|
||||
if (e && (*lb->m_pMats)[i].pRE && (*lb->m_pMats)[i].nNumIndices)
|
||||
e->Reload(nFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CStatObj::Load(const char * szFileName, const char * szGeomName,
|
||||
EVertsSharing eVertsSharing,
|
||||
bool bLoadAdditinalInfo,
|
||||
bool bKeepInLocalSpace,
|
||||
bool bUseStreaming,
|
||||
bool bMakePhysics)
|
||||
{
|
||||
// Tick progress bar if we are now loading a level.
|
||||
GetConsole()->TickProgressBar();
|
||||
|
||||
if(!szFileName[0])
|
||||
GetSystem()->Error("CStatObj::Load: szFileName not specified");
|
||||
|
||||
if(!GetCVars()->e_ccgf_load)
|
||||
return LoadUncompiled(szFileName, szGeomName, eVertsSharing, bLoadAdditinalInfo, bKeepInLocalSpace, false, bMakePhysics);
|
||||
|
||||
// remember file loading parameters
|
||||
m_eVertsSharing = eVertsSharing;
|
||||
m_bLoadAdditinalInfo = bLoadAdditinalInfo;
|
||||
m_bKeepInLocalSpace = bKeepInLocalSpace;
|
||||
m_bMakePhysics = bMakePhysics;
|
||||
|
||||
// remember names
|
||||
strcpy(m_szFileName,szFileName);
|
||||
strcpy(m_szGeomName, szGeomName && szGeomName[0] ? szGeomName : "");
|
||||
strcpy(m_szFolderName,szFileName);
|
||||
while(m_szFolderName[0])
|
||||
{ // make folder name
|
||||
if(m_szFolderName[strlen(m_szFolderName)-1] == '\\' || m_szFolderName[strlen(m_szFolderName)-1] == '/')
|
||||
{ m_szFolderName[strlen(m_szFolderName)-1]=0; break; }
|
||||
m_szFolderName[strlen(m_szFolderName)-1]=0;
|
||||
}
|
||||
|
||||
// Create compiled file if needed
|
||||
// This checks will slowdown loading but allows to avoid complex processing of errors during streaming
|
||||
if(!CompileInNeeded())
|
||||
return false; // unable to build file
|
||||
|
||||
// do not stream subobjects
|
||||
if(bUseStreaming && !m_szGeomName[0])
|
||||
{
|
||||
Init();
|
||||
|
||||
// define fake bbox
|
||||
m_vBoxMin = Vec3d(-1.f,-1.f,-1.f);
|
||||
m_vBoxMax = Vec3d( 1.f, 1.f, 1.f);
|
||||
m_vBoxCenter = Vec3d(0,0,0);
|
||||
m_fRadiusHors = m_fRadiusVert = 1.f;
|
||||
|
||||
m_nLoadedTrisCount = 0;
|
||||
m_bUseStreaming = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// load compiled file
|
||||
StreamCCGF(true);
|
||||
m_bUseStreaming = false;
|
||||
return m_eCCGFStreamingStatus == ecss_Ready;
|
||||
}
|
||||
|
||||
bool CStatObj::LoadUncompiled(const char * szFileName,
|
||||
const char * szGeomName,
|
||||
EVertsSharing eVertsSharing,
|
||||
bool bLoadAdditinalInfo,
|
||||
bool bKeepInLocalSpace,
|
||||
bool bLoadLater,
|
||||
bool bMakePhysics)
|
||||
{
|
||||
if(!szFileName[0])
|
||||
GetSystem()->Error("CStatObj::LoadUncompiled: szFileName not specified");
|
||||
|
||||
m_eVertsSharing = eVertsSharing;
|
||||
m_bLoadAdditinalInfo = bLoadAdditinalInfo;
|
||||
m_bKeepInLocalSpace = bKeepInLocalSpace;
|
||||
m_bUseStreaming = false;
|
||||
m_bMakePhysics = bMakePhysics;
|
||||
|
||||
// make folder name
|
||||
strcpy(m_szFolderName,szFileName);
|
||||
while(m_szFolderName[0])
|
||||
{
|
||||
if(m_szFolderName[strlen(m_szFolderName)-1] == '\\' || m_szFolderName[strlen(m_szFolderName)-1] == '/')
|
||||
{ m_szFolderName[strlen(m_szFolderName)-1]=0; break; }
|
||||
m_szFolderName[strlen(m_szFolderName)-1]=0;
|
||||
}
|
||||
|
||||
// remember file and geom names
|
||||
strcpy(m_szFileName, szFileName);
|
||||
strcpy(m_szGeomName, szGeomName && szGeomName[0] ? szGeomName : "");
|
||||
|
||||
// load uncompiled
|
||||
m_nLoadedTrisCount = 0;
|
||||
m_pTriData = new CIndexedMesh( GetSystem(), szFileName, (szGeomName && szGeomName[0]) ? szGeomName : 0, &m_nLoadedTrisCount, bLoadAdditinalInfo, bKeepInLocalSpace, m_bIgnoreFakeMaterialsInCGF );
|
||||
if(!m_nLoadedTrisCount)
|
||||
return false;
|
||||
|
||||
// copy helpers
|
||||
m_lstHelpers.AddList(*m_pTriData->GetHelpers());
|
||||
|
||||
// copy lsources
|
||||
for(int i=0; i<m_pTriData->GetLightSourcesList()->Count(); i++)
|
||||
{
|
||||
m_lstLSources.Add(*m_pTriData->GetLightSourcesList()->GetAt(i));
|
||||
if(m_lstLSources.Last().m_pShader)
|
||||
m_lstLSources.Last().m_pShader->AddRef();
|
||||
if(m_lstLSources.Last().m_pLightImage)
|
||||
m_lstLSources.Last().m_pLightImage->AddRef();
|
||||
}
|
||||
|
||||
// set bbox and rediuses
|
||||
m_vBoxMin = m_pTriData->m_vBoxMin;
|
||||
m_vBoxMax = m_pTriData->m_vBoxMax;
|
||||
CalcRadiuses();
|
||||
|
||||
if(bMakePhysics)
|
||||
Physicalize(); // can remove some indices/faces
|
||||
|
||||
// create vert buffers
|
||||
MakeLeafBuffer(eVertsSharing==evs_ShareAndSortForCache);
|
||||
|
||||
for (int i=0; m_pLeafBuffer && m_pLeafBuffer->m_pMats && i<m_pLeafBuffer->m_pMats->Count(); i++)
|
||||
m_lstShaderTemplates.Add(-1);
|
||||
|
||||
if(!GetCVars()->e_stencil_shadows)
|
||||
FreeTriData(); // source geometry is needed only for stencil shadows
|
||||
else if(GetCVars()->e_stencil_shadows_build_on_load)
|
||||
{
|
||||
if (!GetShadowVolume())
|
||||
{
|
||||
if(m_pTriData)
|
||||
{
|
||||
SetShadowVolume(CStatObj::MakeConnectivityInfo(m_pTriData, Vec3d(0,0,0), this));
|
||||
FreeTriData(); // source geometry is needed only for stencil shadows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStatObj::LoadLowLODs(EVertsSharing eVertsSharing,bool bLoadAdditinalInfo,bool bKeepInLocalSpace, bool bLoadLater)
|
||||
{
|
||||
m_nLoadedLodsNum = 1;
|
||||
|
||||
if(!GetCVars()->e_cgf_load_lods)
|
||||
return;
|
||||
|
||||
for(int nLodLevel=1; nLodLevel<MAX_STATOBJ_LODS_NUM; nLodLevel++)
|
||||
{
|
||||
// make lod file name
|
||||
char sLodFileName[512];
|
||||
strncpy(sLodFileName, m_szFileName, sizeof(m_szFileName));
|
||||
sLodFileName[strlen(sLodFileName)-4]=0;
|
||||
strcat(sLodFileName,"_lod");
|
||||
char sLodNum[8];
|
||||
ltoa(nLodLevel,sLodNum,10);
|
||||
strcat(sLodFileName,sLodNum);
|
||||
strcat(sLodFileName,".cgf");
|
||||
|
||||
// try to load
|
||||
FILE * fp = GetSystem()->GetIPak()->FOpen(sLodFileName,"r");
|
||||
bool bRes = false;
|
||||
if(fp)
|
||||
{
|
||||
if(!m_arrpLowLODs[nLodLevel])
|
||||
m_arrpLowLODs[nLodLevel] = new CStatObj( );
|
||||
bRes = m_arrpLowLODs[nLodLevel]->Load(sLodFileName, m_szGeomName, eVertsSharing, bLoadAdditinalInfo, bKeepInLocalSpace, bLoadLater, false);
|
||||
GetSystem()->GetIPak()->FClose(fp);
|
||||
}
|
||||
|
||||
if(!bRes)
|
||||
{
|
||||
delete m_arrpLowLODs[nLodLevel];
|
||||
m_arrpLowLODs[nLodLevel]=0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_arrpLowLODs[nLodLevel]->m_nLoadedTrisCount > m_nLoadedTrisCount / 1.5f)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning(0, sLodFileName,
|
||||
"CStatObj::LoadLowLODs: Low lod model contains too many polygons comparing to full LOD model [%d agains %d], there is no sense to use it",
|
||||
m_arrpLowLODs[nLodLevel]->m_nLoadedTrisCount, m_nLoadedTrisCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_nLoadedLodsNum++;
|
||||
}
|
||||
}
|
||||
|
||||
void CStatObj::PreloadResources(float fDist, float fTime, int dwFlags)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
if(GetLeafBuffer())
|
||||
GetRenderer()->EF_PrecacheResource(GetLeafBuffer(),fDist,fTime,0);
|
||||
|
||||
if(m_arrSpriteTexID[0])
|
||||
for(int i=0; i<FAR_TEX_COUNT; i++)
|
||||
{
|
||||
if(m_arrSpriteTexID[i])
|
||||
{
|
||||
ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(m_arrSpriteTexID[i]);
|
||||
if(pTexPic)
|
||||
GetRenderer()->EF_PrecacheResource(pTexPic, 0, 1.f, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
498
Cry3DEngine/StatObjPhys.cpp
Normal file
498
Cry3DEngine/StatObjPhys.cpp
Normal file
@@ -0,0 +1,498 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjphys.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: make physical representation
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Buffer optimizer
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int CStatObj::FindInPosBuffer(const Vec3d & opt, Vec3d * _vbuff, int _vcount, list2<int> * pHash)
|
||||
{
|
||||
for(int i=0; i<pHash->Count(); i++)
|
||||
{
|
||||
if(
|
||||
IsEquivalent(*((Vec3d*)(&_vbuff[(*pHash)[i]].x)), *((Vec3d*)(&opt.x)), VEC_EPSILON)
|
||||
)
|
||||
return (*pHash)[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CStatObj::CompactPosBuffer(Vec3d * _vbuff, int * _vcount, list2<int> * pindices)
|
||||
{
|
||||
int before = *_vcount; assert(before);
|
||||
if(!before)
|
||||
GetConsole()->Exit("Error: CStatObj::CompactPosBuffer: Input vertex count is zero");
|
||||
|
||||
Vec3d * tmp_buff = new Vec3d[*_vcount];
|
||||
int tmp_count = 0;
|
||||
|
||||
pindices->Clear();
|
||||
|
||||
list2<int> pos_hash_table[256];//[256];
|
||||
|
||||
for(uint v=0; v<(uint)(*_vcount); v++)
|
||||
{
|
||||
list2<int> * pHash = &pos_hash_table[(unsigned char)(_vbuff[v].x*100)];//[(unsigned char)(_vbuff[v].y*100)];
|
||||
int find = FindInPosBuffer( _vbuff[v], tmp_buff, tmp_count, pHash);
|
||||
if(find<0)
|
||||
{
|
||||
tmp_buff[tmp_count] = _vbuff[v];
|
||||
pindices->Add(tmp_count);
|
||||
|
||||
pos_hash_table[(unsigned char)(_vbuff[v].x*100)]/*[(unsigned char)(_vbuff[v].y*100)]*/.Add(tmp_count);
|
||||
|
||||
tmp_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int u = (uint)find;
|
||||
pindices->Add(u);
|
||||
}
|
||||
}
|
||||
|
||||
* _vcount = tmp_count;
|
||||
memcpy( _vbuff, tmp_buff, tmp_count*sizeof(Vec3d));
|
||||
|
||||
delete [] tmp_buff;
|
||||
}
|
||||
|
||||
// This function prepares 3 additional meshes:
|
||||
// usual physical representation(mat_phys or bounce koeff),
|
||||
// obstruct physical representation(mat_obstruct)
|
||||
// and occlusion volume(mat_occl).
|
||||
// Register physical stuff in physics engine.
|
||||
void CStatObj::Physicalize()
|
||||
{
|
||||
bool bShowINfo = (m_pTriData->m_nFaceCount>10000);
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Creating buffer for physics ...");
|
||||
|
||||
// get phys material id's from game code
|
||||
IPhysMaterialEnumerator * pPhysMaterialEnumerator = Get3DEngine()->GetPhysMaterialEnumerator();
|
||||
|
||||
// special mat id's
|
||||
int nPhysMatID = -1;
|
||||
list2<int> arrObstrMatIDs;
|
||||
int nOcclMatID = -1;
|
||||
list2<int> arrLeavesMatIDs;
|
||||
|
||||
for(int m=0; m<m_pTriData->m_lstMatTable.Count(); m++)
|
||||
{
|
||||
// get phys material id's from game code
|
||||
if(pPhysMaterialEnumerator)
|
||||
m_pTriData->m_lstMatTable[m].nGamePhysMatId = pPhysMaterialEnumerator->EnumPhysMaterial(m_pTriData->m_lstMatTable[m].sScriptMaterial);
|
||||
|
||||
// find phys material id
|
||||
if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_phys"))
|
||||
{ assert(nPhysMatID<0); nPhysMatID = m; }
|
||||
|
||||
// find obstruct material id
|
||||
else if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_obstruct"))
|
||||
{ arrObstrMatIDs.Add(m); }
|
||||
|
||||
// find obstruct material id
|
||||
else if (pPhysMaterialEnumerator &&
|
||||
!pPhysMaterialEnumerator->IsCollidable(m_pTriData->m_lstMatTable[m].nGamePhysMatId) &&
|
||||
!(m_pTriData->m_lstMatTable[m].m_Flags & MIF_PHYSIC))
|
||||
{ arrLeavesMatIDs.Add(m); }
|
||||
|
||||
// find occlusion material id
|
||||
else if(strstr(m_pTriData->m_lstMatTable[m].sScriptMaterial,"mat_occl"))
|
||||
{ assert(nOcclMatID<0); nOcclMatID = m; }
|
||||
}
|
||||
|
||||
#define MESH_PHYSIC 0
|
||||
#define MESH_OBSTRUCT 1
|
||||
#define MESH_LEAVES 2
|
||||
#define MESH_OCCLUSION 3
|
||||
|
||||
for(int nMesh = 0; nMesh<=3; nMesh++)
|
||||
{ // fill physics indices
|
||||
list2<int> lstPhysIndices;
|
||||
list2<unsigned char> lstFaceMaterials;
|
||||
|
||||
if(nMesh == MESH_PHYSIC)
|
||||
{ // find all physicalized faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( ((m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].m_Flags & MIF_PHYSIC) && nPhysMatID<0) ||
|
||||
m_pTriData->m_pFaces[i].shader_id == nPhysMatID )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nPhysMatID)
|
||||
{ // remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OBSTRUCT)
|
||||
{ // find all obstruct faces
|
||||
if(arrObstrMatIDs.Count())
|
||||
{ // find all obstruct faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( arrObstrMatIDs.Find(m_pTriData->m_pFaces[i].shader_id)>=0 )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(arrObstrMatIDs.Find(m_pTriData->m_pFaces[i].shader_id)>=0)
|
||||
{
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_LEAVES)
|
||||
{ // find all obstruct faces
|
||||
if(arrLeavesMatIDs.Count())
|
||||
{ // find all obstruct faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( arrLeavesMatIDs.Find(m_pTriData->m_pFaces[i].shader_id)>=0 )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OCCLUSION)
|
||||
{
|
||||
if(nOcclMatID>=0)
|
||||
{ // find all occlusion faces
|
||||
for(int i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nOcclMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lstPhysIndices.Count())
|
||||
{
|
||||
Vec3d * pExVerts;
|
||||
int nInitVertCount;
|
||||
|
||||
if (m_pTriData->m_lstGeomNames.Count()>0 && strstr(m_pTriData->m_lstGeomNames[0],"cloth")!=0)
|
||||
{
|
||||
pExVerts = m_pTriData->m_pVerts;
|
||||
nInitVertCount = m_pTriData->m_nVertCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExVerts = new Vec3d[lstPhysIndices.Count()];
|
||||
|
||||
for(int i=0; i<lstPhysIndices.Count();i++)
|
||||
pExVerts[i] = m_pTriData->m_pVerts[lstPhysIndices[i]];
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Compacting buffer ...");
|
||||
|
||||
nInitVertCount = lstPhysIndices.Count();
|
||||
CompactPosBuffer(pExVerts, &nInitVertCount, &lstPhysIndices);
|
||||
}
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreen(" Creating OBB tree ...");
|
||||
|
||||
if(GetPhysicalWorld() && (nMesh==MESH_PHYSIC || nMesh==MESH_OBSTRUCT || nMesh==MESH_LEAVES) && nInitVertCount>2)
|
||||
{
|
||||
int nPhysTris = lstPhysIndices.Count()/3;
|
||||
if(GetCVars()->e_check_number_of_physicalized_polygons &&
|
||||
nPhysTris > 100+m_pTriData->m_nFaceCount/2)
|
||||
{
|
||||
#if !defined(LINUX) //does not matter in dedicated server mode
|
||||
GetLog()->Log("Physicalized geometry contains too many polygons(%d of %d), for CGF: %s",
|
||||
nPhysTris, m_pTriData->m_nFaceCount, GetFileName() );
|
||||
GetLog()->Log(" Number of physicalized tris is more than 100 + number of all tris divided by 2");
|
||||
#endif
|
||||
}
|
||||
|
||||
IGeomManager *pGeoman = GetPhysicalWorld()->GetGeomManager();
|
||||
Vec3d ptmin=pExVerts[0],ptmax=pExVerts[0],sz;
|
||||
for(int i=1;i<nInitVertCount;i++)
|
||||
{
|
||||
ptmin.x = min(ptmin.x,pExVerts[i].x);
|
||||
ptmax.x = max(ptmax.x,pExVerts[i].x);
|
||||
ptmin.y = min(ptmin.y,pExVerts[i].y);
|
||||
ptmax.y = max(ptmax.y,pExVerts[i].y);
|
||||
ptmin.z = min(ptmin.z,pExVerts[i].z);
|
||||
ptmax.z = max(ptmax.z,pExVerts[i].z);
|
||||
}
|
||||
int nMinTrisPerNode=2, nMaxTrisPerNode=4;
|
||||
sz = ptmax-ptmin;
|
||||
int flags = mesh_multicontact1 | mesh_uchar_ids;
|
||||
float tol = 0.05f;
|
||||
flags |= lstPhysIndices.Count()<=60 ? mesh_SingleBB : mesh_OBB|mesh_AABB;
|
||||
if (strstr(m_szGeomName,"wheel"))
|
||||
{
|
||||
flags |= mesh_approx_cylinder;
|
||||
tol = 1.0f;
|
||||
} else
|
||||
flags |= mesh_approx_box | mesh_approx_sphere | mesh_approx_cylinder;
|
||||
if (lstPhysIndices.Count()<600 && max(max(sz.x,sz.y),sz.z)>6) // make more dense OBBs for large (wrt terrain grid) objects
|
||||
nMinTrisPerNode = nMaxTrisPerNode = 1;
|
||||
assert(nMesh<MAX_PHYS_GEOMS_IN_CGF);
|
||||
m_arrPhysGeomInfo[nMesh] = pGeoman->RegisterGeometry(pGeoman->CreateMesh((vectorf*)&pExVerts[0], &lstPhysIndices[0],
|
||||
(short*)&lstFaceMaterials[0], lstPhysIndices.Count()/3, flags, true, true, tol, nMinTrisPerNode,nMaxTrisPerNode, 2.5f));
|
||||
if (lstFaceMaterials.Count()>0)
|
||||
m_arrPhysGeomInfo[nMesh]->surface_idx = lstFaceMaterials[0];
|
||||
}
|
||||
|
||||
if(nOcclMatID>=0 && nMesh==MESH_OCCLUSION)
|
||||
{
|
||||
m_lstOcclVolVerts.AddList(pExVerts,nInitVertCount);
|
||||
m_lstOcclVolInds.AddList(lstPhysIndices);
|
||||
}
|
||||
|
||||
if (pExVerts!=m_pTriData->m_pVerts)
|
||||
delete [] pExVerts;
|
||||
}
|
||||
}
|
||||
|
||||
if(bShowINfo)
|
||||
GetLog()->UpdateLoadingScreenPlus("ok");
|
||||
|
||||
#undef MESH_PHYSIC
|
||||
#undef MESH_OBSTRUCT
|
||||
#undef MESH_OCCLUSION
|
||||
#undef MESH_LEAVES
|
||||
}
|
||||
|
||||
void CStatObj::PhysicalizeCompiled()
|
||||
{
|
||||
// if(bShowINfo)
|
||||
// GetLog()->UpdateLoadingScreen(" Creating buffer for physics ...");
|
||||
|
||||
// get phys material id's from game code
|
||||
IPhysMaterialEnumerator * pPhysMaterialEnumerator = Get3DEngine()->GetPhysMaterialEnumerator();
|
||||
{
|
||||
for(int i=0; pPhysMaterialEnumerator && i<m_pLeafBuffer->m_pMats->Count(); i++)
|
||||
(*m_pLeafBuffer->m_pMats)[i].nGamePhysMatId = pPhysMaterialEnumerator->EnumPhysMaterial((*m_pLeafBuffer->m_pMats)[i].sScriptMaterial);
|
||||
}
|
||||
|
||||
// find mat id's
|
||||
int nPhysMatID = -1;
|
||||
int nObstrMatID = -1;
|
||||
int nOcclMatID = -1;
|
||||
|
||||
#define MESH_PHYSIC 0
|
||||
#define MESH_OBSTRUCT 1
|
||||
#define MESH_OCCLUSION 3
|
||||
|
||||
for(int nMesh = 0; nMesh<=3; nMesh++)
|
||||
{ // fill physics indices
|
||||
|
||||
// list2<int> & lstPhysIndices =
|
||||
// list2<unsigned char> & lstFaceMaterials;
|
||||
|
||||
// for(int i=0; i<3; i++)
|
||||
// {
|
||||
/* m_lstProxyVerts[nMesh];
|
||||
list2<int> & lstPhysIndices = m_lstProxyInds[nMesh].LoadFromBuffer(pSerBuf,nPos);
|
||||
LoadBuffer(m_vPhysBoxMin[i], sizeof(m_vPhysBoxMin[i]), pSerBuf, nPos);
|
||||
LoadBuffer(m_vPhysBoxMin[i], sizeof(m_vPhysBoxMin[i]), pSerBuf, nPos);*/
|
||||
// }
|
||||
|
||||
/*
|
||||
if(nMesh == MESH_PHYSIC)
|
||||
{ // find all physicalized faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if( ((m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].m_Flags & MIF_PHYSIC) && nPhysMatID<0) ||
|
||||
m_pTriData->m_pFaces[i].shader_id == nPhysMatID )
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nPhysMatID)
|
||||
{ // remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OBSTRUCT)
|
||||
{ // find all obstruct faces
|
||||
if(nObstrMatID>=0)
|
||||
{ // find all obstruct faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nObstrMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(nMesh == MESH_OCCLUSION)
|
||||
{
|
||||
if(nOcclMatID>=0)
|
||||
{ // find all occlusion faces
|
||||
for(i=0; i<m_pTriData->m_nFaceCount; i++)
|
||||
{
|
||||
if(m_pTriData->m_pFaces[i].shader_id == nOcclMatID)
|
||||
{
|
||||
for(int v=0; v<3; v++)
|
||||
lstPhysIndices.Add(m_pTriData->m_pFaces[i].v[v]);
|
||||
|
||||
lstFaceMaterials.Add(m_pTriData->m_lstMatTable[m_pTriData->m_pFaces[i].shader_id].nGamePhysMatId);
|
||||
|
||||
// remove face from list (it's not needed for rendering)
|
||||
if(m_pTriData->m_nFaceCount>1)
|
||||
m_pTriData->m_pFaces[i] = m_pTriData->m_pFaces[m_pTriData->m_nFaceCount-1];
|
||||
m_pTriData->m_nFaceCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
list2<int> & lstPhysIndices = m_lstProxyInds[nMesh];//.LoadFromBuffer(pSerBuf,nPos);
|
||||
// LoadBuffer(m_vPhysBoxMin[i], sizeof(m_vPhysBoxMin[i]), pSerBuf, nPos);
|
||||
// LoadBuffer(m_vPhysBoxMin[i], sizeof(m_vPhysBoxMin[i]), pSerBuf, nPos);
|
||||
|
||||
if(lstPhysIndices.Count())
|
||||
{
|
||||
Vec3d * pExVerts = &m_lstProxyVerts[nMesh][0];
|
||||
// if(bShowINfo)
|
||||
// GetLog()->UpdateLoadingScreen(" Creating OBB tree ...");
|
||||
|
||||
if(GetPhysicalWorld() && (nMesh==MESH_PHYSIC || nMesh==MESH_OBSTRUCT))
|
||||
{
|
||||
int nPhysTris = lstPhysIndices.Count()/3;
|
||||
int nFaceCount = 0;
|
||||
m_pLeafBuffer->GetIndices(&nFaceCount);
|
||||
nFaceCount/=3;
|
||||
if(GetCVars()->e_check_number_of_physicalized_polygons &&
|
||||
nPhysTris > 100+nFaceCount/2)
|
||||
{
|
||||
#if !defined(LINUX) //does not matter in dedicated server mode
|
||||
GetLog()->Log("Physicalized geometry contains too many polygons(%d of %d), for CGF: %s",
|
||||
nPhysTris, nFaceCount, GetFileName() );
|
||||
GetLog()->Log(" Number of physicalized tris is more than 100 + number of all tris divided by 2");
|
||||
#endif
|
||||
}
|
||||
|
||||
list2<unsigned char> & lstFaceMaterials = m_lstProxyFaceMaterials[nMesh];
|
||||
|
||||
// remap shader id to game mat id
|
||||
for(int f=0; f<lstFaceMaterials.Count(); f++)
|
||||
{
|
||||
CMatInfo * pMat = m_pLeafBuffer->m_pMats->Get(lstFaceMaterials[f]);
|
||||
lstFaceMaterials[f] = pMat->nGamePhysMatId;
|
||||
}
|
||||
|
||||
IGeomManager *pGeoman = GetPhysicalWorld()->GetGeomManager();
|
||||
Vec3d & ptmin = m_vPhysBoxMin[nMesh];
|
||||
Vec3d & ptmax = m_vPhysBoxMax[nMesh];
|
||||
|
||||
int nMinTrisPerNode=2, nMaxTrisPerNode=4;
|
||||
Vec3d sz = ptmax - ptmin;
|
||||
int flags = mesh_multicontact1 | mesh_uchar_ids;
|
||||
float tol = 0.05f;
|
||||
flags |= lstPhysIndices.Count()<=60 ? mesh_SingleBB : mesh_OBB|mesh_AABB;
|
||||
if (strstr(m_szGeomName,"wheel"))
|
||||
{
|
||||
flags |= mesh_approx_cylinder;
|
||||
tol = 1.0f;
|
||||
} else
|
||||
flags |= mesh_approx_box | mesh_approx_sphere | mesh_approx_cylinder;
|
||||
if (lstPhysIndices.Count()<600 && max(max(sz.x,sz.y),sz.z)>6) // make more dense OBBs for large (wrt terrain grid) objects
|
||||
nMinTrisPerNode = nMaxTrisPerNode = 1;
|
||||
assert(!m_arrPhysGeomInfo[nMesh]);
|
||||
m_arrPhysGeomInfo[nMesh] = pGeoman->RegisterGeometry(pGeoman->CreateMesh((vectorf*)&pExVerts[0], &lstPhysIndices[0],
|
||||
(short*)&lstFaceMaterials[0], lstPhysIndices.Count()/3, flags, true, true, tol, nMinTrisPerNode,nMaxTrisPerNode, 2.5f));
|
||||
assert(m_arrPhysGeomInfo[nMesh]->nRefCount == 1);
|
||||
if (lstFaceMaterials.Count()>0)
|
||||
m_arrPhysGeomInfo[nMesh]->surface_idx = lstFaceMaterials[0];
|
||||
}
|
||||
|
||||
if(nOcclMatID>=0 && nMesh==MESH_OCCLUSION)
|
||||
{
|
||||
m_lstOcclVolVerts.AddList(m_lstProxyVerts[nMesh]);
|
||||
m_lstOcclVolInds.AddList(lstPhysIndices);
|
||||
}
|
||||
|
||||
// delete [] pExVerts;
|
||||
}
|
||||
/*else if(lstPhysIndices.Count())
|
||||
{
|
||||
Warning(0,GetFileName(),"CStatObj::Physicalize: proxy geometry contains more than 200 polygons - skipped, for CGF: %s",GetFileName() );
|
||||
}*/
|
||||
|
||||
m_lstProxyInds[nMesh].Reset();
|
||||
m_lstProxyVerts[nMesh].Reset();
|
||||
m_lstProxyFaceMaterials[nMesh].Reset();
|
||||
}
|
||||
|
||||
// if(bShowINfo)
|
||||
// GetLog()->UpdateLoadingScreenPlus("ok");
|
||||
|
||||
#undef MESH_PHYSIC
|
||||
#undef MESH_OBSTRUCT
|
||||
#undef MESH_OCCLUSION
|
||||
}
|
||||
599
Cry3DEngine/StatObjRend.cpp
Normal file
599
Cry3DEngine/StatObjRend.cpp
Normal file
@@ -0,0 +1,599 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjrend.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: prepare and add render element into renderer
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
#include "LMCompStructures.h"
|
||||
|
||||
#include "MeshIdx.h"
|
||||
#include "visareas.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CStatObj::SetShaderTemplate(int nTemplate, const char *TemplName, const char *ShaderName, bool bOnlyRegister, int * pnNewTemplateId)
|
||||
{
|
||||
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
m_arrpLowLODs[i]->SetShaderTemplate(nTemplate, TemplName, ShaderName, bOnlyRegister);
|
||||
|
||||
CLeafBuffer *lb = m_pLeafBuffer;
|
||||
if (!lb || (lb->m_pMats->Count() != m_lstShaderTemplates.Num()))
|
||||
return false;
|
||||
if (!ShaderName)
|
||||
{
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
IShader * e = (*lb->m_pMats)[i].shaderItem.m_pShader;
|
||||
SRenderShaderResources *sr = (*lb->m_pMats)[i].shaderItem.m_pShaderResources;
|
||||
|
||||
if (e && (*lb->m_pMats)[i].pRE && (*lb->m_pMats)[i].nNumIndices)
|
||||
{
|
||||
if(nTemplate < EFT_USER_FIRST && nTemplate >= 0)
|
||||
e->AddTemplate(sr, nTemplate, NULL, false);
|
||||
else
|
||||
if (TemplName && TemplName[0])
|
||||
{
|
||||
if (nTemplate <= EFT_USER_FIRST)
|
||||
nTemplate = EFT_USER_FIRST + 1;
|
||||
e->AddTemplate(sr, nTemplate, TemplName, false);
|
||||
}
|
||||
if (!bOnlyRegister)
|
||||
m_lstShaderTemplates[i] = nTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
if(pnNewTemplateId)
|
||||
*pnNewTemplateId = nTemplate;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool bRes = false;
|
||||
for (int i=0; i<m_lstShaderTemplates.Num(); i++)
|
||||
{
|
||||
if (!lb->m_pMats->Get(i)->shaderItem.m_pShader)
|
||||
continue;
|
||||
if (!stricmp(ShaderName, lb->m_pMats->Get(i)->shaderItem.m_pShader->GetName()))
|
||||
{
|
||||
SRenderShaderResources *sr = (*lb->m_pMats)[i].shaderItem.m_pShaderResources;
|
||||
bRes = true;
|
||||
if(nTemplate < EFT_USER_FIRST && nTemplate >= 0)
|
||||
lb->m_pMats->Get(i)->shaderItem.m_pShader->AddTemplate(sr, nTemplate);
|
||||
else
|
||||
if (TemplName && TemplName[0])
|
||||
lb->m_pMats->Get(i)->shaderItem.m_pShader->AddTemplate(sr, nTemplate, TemplName);
|
||||
m_lstShaderTemplates[i] = nTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
if(bRes && pnNewTemplateId)
|
||||
*pnNewTemplateId = nTemplate;
|
||||
|
||||
return bRes;
|
||||
}
|
||||
|
||||
void CStatObj::SetShaderFloat(const char *Name, float Val)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<MAX_STATOBJ_LODS_NUM; i++)
|
||||
if(m_arrpLowLODs[i])
|
||||
m_arrpLowLODs[i]->SetShaderFloat(Name, Val);
|
||||
|
||||
char name[128];
|
||||
|
||||
strcpy(name, Name);
|
||||
strlwr(name);
|
||||
for (i=0; i<m_ShaderParams.Num(); i++)
|
||||
{
|
||||
if (!strcmp(name, m_ShaderParams[i].m_Name))
|
||||
break;
|
||||
}
|
||||
if (i == m_ShaderParams.Num())
|
||||
{
|
||||
SShaderParam pr;
|
||||
strncpy(pr.m_Name, name, 32);
|
||||
m_ShaderParams.AddElem(pr);
|
||||
}
|
||||
m_ShaderParams[i].m_Type = eType_FLOAT;
|
||||
m_ShaderParams[i].m_Value.m_Float = Val;
|
||||
}
|
||||
|
||||
void CStatObj::SetColor(const char *Name, float fR, float fG, float fB, float fA)
|
||||
{
|
||||
}
|
||||
|
||||
void CStatObj::SetupBending(CCObject * pObj, float fBending)
|
||||
{
|
||||
pObj->m_fBending = fBending;
|
||||
|
||||
Vec3d vObjPos = pObj->GetTranslation();
|
||||
|
||||
SWaveForm2 *pWF[2];
|
||||
pObj->AddWaves(pWF);
|
||||
SWaveForm2 *wf = pWF[0];
|
||||
wf->m_Level = 0.000f; // between 0.001 and 0.1
|
||||
wf->m_Freq = 1.0f/m_fRadiusVert/8.0f+0.2f; // between 0.001 and 0.1
|
||||
wf->m_Phase = vObjPos.x/8.0f;
|
||||
wf->m_Amp = 0.002f;
|
||||
|
||||
wf = pWF[1];
|
||||
wf->m_Level = 0.000f; // between 0.001 and 0.1
|
||||
wf->m_Freq = 1.0f/m_fRadiusVert/7.0f+0.2f; // between 0.001 and 0.1
|
||||
wf->m_Phase = vObjPos.y/8.0f;
|
||||
wf->m_Amp = 0.002f;
|
||||
|
||||
pObj->m_ObjFlags |= FOB_BENDED;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CStatObj::Render(const SRendParams & rParams, const Vec3& t, int nLodLevel)
|
||||
{
|
||||
IRenderer * pRend = GetRenderer();
|
||||
|
||||
m_nLastRendFrameId = GetFrameID();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Process LODs
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (nLodLevel >= m_nLoadedLodsNum)
|
||||
nLodLevel = m_nLoadedLodsNum-1;
|
||||
|
||||
if (nLodLevel && m_arrpLowLODs[nLodLevel] && nLodLevel<m_nLoadedLodsNum && GetCVars()->e_cgf_load_lods)
|
||||
{
|
||||
m_arrpLowLODs[nLodLevel]->Render(rParams,Vec3(zero),0);
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Load object if not loaded
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(m_bUseStreaming && GetCVars()->e_stream_cgf)
|
||||
StreamCCGF(false);
|
||||
|
||||
// if(m_bUseStreaming && m_fStreamingTimePerFrame<CGF_STREAMING_MAX_TIME_PER_FRAME)
|
||||
// if(GetCVars()->e_stream_cgf && GetCVars()->e_stream_for_visuals)
|
||||
// CheckLoaded();
|
||||
|
||||
if(!m_pLeafBuffer || !m_nLoadedTrisCount)
|
||||
return; // object not loaded yet
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Specifiy transformation
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCObject * pObj;
|
||||
pObj = pRend->EF_GetObject(true, -1);
|
||||
|
||||
pObj->m_fDistanceToCam = rParams.fSQDistance;
|
||||
|
||||
if (!rParams.pMatrix)
|
||||
mathCalcMatrix(pObj->m_Matrix, rParams.vPos, rParams.vAngles, Vec3d(rParams.fScale,rParams.fScale,rParams.fScale), Cry3DEngineBase::m_CpuFlags);
|
||||
else
|
||||
pObj->m_Matrix = *rParams.pMatrix;
|
||||
|
||||
pObj->m_SortId = rParams.fCustomSortOffset;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Set flags
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pObj->m_ObjFlags |= rParams.dwFObjFlags;
|
||||
pObj->m_fHeatFactor = rParams.fHeatAmount;
|
||||
|
||||
pObj->m_AmbColor = rParams.vAmbientColor;
|
||||
assert(pObj->m_AmbColor.x>=0 && pObj->m_AmbColor.x<=1.f);
|
||||
assert(pObj->m_AmbColor.y>=0 && pObj->m_AmbColor.y<=1.f);
|
||||
assert(pObj->m_AmbColor.z>=0 && pObj->m_AmbColor.z<=1.f);
|
||||
|
||||
if (GetCVars()->e_shadow_maps)
|
||||
pObj->m_pShadowCasters = rParams.pShadowMapCasters;
|
||||
else
|
||||
pObj->m_pShadowCasters=0;
|
||||
|
||||
// if (rParams.dwFlags & RPF_DRAWNEAR)
|
||||
// pObj->m_ObjFlags |= FOB_NEAREST;
|
||||
|
||||
if (pObj->m_pShadowCasters)
|
||||
pObj->m_ObjFlags |= FOB_INSHADOW;
|
||||
|
||||
pObj->m_Color = CFColor(
|
||||
rParams.vColor.x,
|
||||
rParams.vColor.y,
|
||||
rParams.vColor.z,
|
||||
rParams.fAlpha);
|
||||
|
||||
if (rParams.pShaderParams && rParams.pShaderParams->Num())
|
||||
pObj->m_ShaderParams = rParams.pShaderParams;
|
||||
else
|
||||
if (m_ShaderParams.Num())
|
||||
pObj->m_ShaderParams = &m_ShaderParams;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Process bending
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (rParams.fBending)
|
||||
SetupBending(pObj, rParams.fBending);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Add LOCAL lsources
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int dwDynMaskLocal = 0;
|
||||
for(int i=0; i<m_lstLSources.Count(); i++)
|
||||
if(m_lstLSources[i].m_Flags & DLF_LOCAL)
|
||||
if( ((m_lstLSources[i].m_Flags & DLF_HEATSOURCE) && pRend->EF_GetHeatVision()) ||
|
||||
((m_lstLSources[i].m_Flags & DLF_LIGHTSOURCE)&& !pRend->EF_GetHeatVision()))
|
||||
if(rParams.fDistance < 256)
|
||||
{
|
||||
if (rParams.pMatrix)
|
||||
{
|
||||
m_lstLSources[i].m_Origin =
|
||||
rParams.pMatrix->TransformPointOLD(m_lstLSources[i].m_vObjectSpacePos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//Matrix objMat;
|
||||
//objMat.Identity();
|
||||
//objMat=GetTranslationMat(rParams.vPos)*objMat;
|
||||
//objMat=GetRotationZYX44(-gf_DEGTORAD*rParams.vAngles)*objMat; //NOTE: angles in radians and negated
|
||||
//objMat=GetScale33( Vec3d(rParams.fScale,rParams.fScale,rParams.fScale) )*objMat;
|
||||
|
||||
//OPTIMISED_BY_IVO
|
||||
Matrix33diag diag = Vec3d(rParams.fScale,rParams.fScale,rParams.fScale); //use diag-matrix for scaling
|
||||
Matrix34 rt34 = Matrix34::CreateRotationXYZ(gf_DEGTORAD*rParams.vAngles, rParams.vPos ); //set scaling and translation in one function call
|
||||
Matrix44 objMat = rt34*diag; //optimised concatenation: m34*diag
|
||||
objMat = GetTransposed44(objMat); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
||||
|
||||
m_lstLSources[i].m_Origin = objMat.TransformPointOLD(m_lstLSources[i].m_vObjectSpacePos);
|
||||
}
|
||||
|
||||
pRend->EF_ADDDlight (&m_lstLSources[i]);
|
||||
if(m_lstLSources[i].m_Id>=0)
|
||||
dwDynMaskLocal |= (1<<m_lstLSources[i].m_Id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Add helpers
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
int i;
|
||||
for (i=0; i<m_lstHelpers.Count(); i++)
|
||||
{
|
||||
HelperInfo *pHI = &m_lstHelpers[i];
|
||||
if (pHI->m_pShader)
|
||||
{
|
||||
CCObject * pObject = pRend->EF_GetObject(true);
|
||||
Matrix matr;
|
||||
if (pObj->m_ObjFlags & FOB_USEMATRIX)
|
||||
matr = pObj->m_Matrix;
|
||||
else
|
||||
{
|
||||
matr.Identity();
|
||||
matr.Translate(pObj->m_Trans);
|
||||
matr.Rotate(pObj->m_Angs);
|
||||
if (pObj->m_Scale != 1.0f)
|
||||
matr.ScaleMatrix(pObj->m_Scale, pObj->m_Scale, pObj->m_Scale);
|
||||
}
|
||||
pObject->m_Trans = matr.TransformPoint(pHI->vPos);
|
||||
pObject->m_Color = Col_White;
|
||||
pObject->m_Angs = Vec3d(0,0,0);
|
||||
for (int nr=0; nr<pHI->m_pShader->GetREs()->Num(); nr++)
|
||||
{
|
||||
pRend->EF_AddEf(0, pHI->m_pShader->GetREs()->Get(nr), pHI->m_pShader, pObject, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
pObj->m_DynLMMask = rParams.nDLightMask;
|
||||
pObj->m_DynLMMask |= dwDynMaskLocal;
|
||||
|
||||
#ifdef _DEBUG
|
||||
int nCount = 0;
|
||||
for(int i=0; i<32; i++)
|
||||
{
|
||||
if(pObj->m_DynLMMask & (1<<i))
|
||||
nCount++;
|
||||
}
|
||||
if(nCount>16)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"Warning: CStatObj::Render: no more than 16 lsources can be requested");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if(rParams.pLightMapInfo)
|
||||
{
|
||||
// set object lmaps and texture coordinates
|
||||
pObj->m_pLMTCBufferO = rParams.pLMTCBuffer;
|
||||
pObj->m_nLMId = rParams.pLightMapInfo->GetColorLerpTex();
|
||||
pObj->m_nLMDirId = rParams.pLightMapInfo->GetDomDirectionTex();
|
||||
pObj->m_nHDRLMId = rParams.pLightMapInfo->GetHDRColorLerpTex();
|
||||
pObj->m_nOcclId = rParams.pLightMapInfo->GetOcclTex();
|
||||
*(DWORD*)pObj->m_OcclLights = *(DWORD*)rParams.arrOcclusionLightIds;
|
||||
}
|
||||
|
||||
/* if(!m_nRenderStackLevel)
|
||||
{
|
||||
pObj->m_nScissorX1 = rParams.nScissorX1;
|
||||
pObj->m_nScissorY1 = rParams.nScissorY1;
|
||||
pObj->m_nScissorX2 = rParams.nScissorX2;
|
||||
pObj->m_nScissorY2 = rParams.nScissorY2;
|
||||
}*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Add render elements
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IMatInfo * pMaterial = NULL;
|
||||
if (GetCVars()->e_materials && !m_bDefaultObject)
|
||||
pMaterial = rParams.pMaterial;
|
||||
|
||||
bool bNotCurArea = false;
|
||||
|
||||
if(GetCVars()->e_overlay_geometry >= 2)
|
||||
{
|
||||
bNotCurArea = (!rParams.pCaller || !GetVisAreaManager() ||
|
||||
((CVisArea *)rParams.pCaller->GetEntityVisArea() && !((CVisArea *)rParams.pCaller->GetEntityVisArea())->
|
||||
FindVisArea((CVisArea *)GetVisAreaManager()->m_pCurArea,1, true)));
|
||||
|
||||
SetShaderFloat("offset", 0);
|
||||
}
|
||||
else if(GetCVars()->e_overlay_geometry < 2 )
|
||||
m_ShaderParams.SetNum(0);
|
||||
|
||||
if(GetCVars()->e_debug_lights!=1.f)
|
||||
m_pLeafBuffer->Render(rParams,pObj,m_lstShaderTemplates,GetCVars()->e_overlay_geometry,bNotCurArea,pMaterial, false);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Print debug info
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (GetCVars()->e_vegetation_debug)
|
||||
RenderDebugInfo(rParams, pObj);
|
||||
|
||||
if(GetCVars()->e_debug_lights)
|
||||
if(!(rParams.dwFObjFlags & FOB_LIGHTPASS || rParams.dwFObjFlags & FOB_FOGPASS))
|
||||
m_pLeafBuffer->RenderDebugLightPass(pObj->m_Matrix, pObj->m_DynLMMask, GetCVars()->e_debug_lights);
|
||||
}
|
||||
/*
|
||||
void CStatObj::RenderLeafBuffer(const SRendParams & rParams, CCObject * pObj)
|
||||
{
|
||||
// static int nAll=0,nUsed=0;
|
||||
|
||||
int nSortValue = rParams.bDrawNear ? eS_Nearest : rParams.nSortValue;
|
||||
|
||||
for (int i=0; i<m_pLeafBuffer->m_pMats->Count(); i++)
|
||||
{
|
||||
CMatInfo * pMat = m_pLeafBuffer->m_pMats->Get(i);
|
||||
CRendElement * pREOcLeaf = pMat->pRE;
|
||||
|
||||
// nAll++;
|
||||
|
||||
// Override default material
|
||||
if (rParams.pMaterial && GetCVars()->e_materials && !m_bDefaultObject)
|
||||
{
|
||||
int nMatId = pMat->m_nCGFMaterialID;
|
||||
if(nMatId<0)
|
||||
{
|
||||
// assert(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assume that the root material is the first material, sub materials start from index 1.
|
||||
if (nMatId == 0)
|
||||
pMat = (CMatInfo*)rParams.pMaterial;
|
||||
else if (nMatId-1 < rParams.pMaterial->GetSubMtlCount())
|
||||
{
|
||||
pMat = (CMatInfo*)rParams.pMaterial->GetSubMtl(nMatId-1);
|
||||
}
|
||||
}
|
||||
|
||||
IShader * e = pMat->shaderItem.m_pShader;
|
||||
SRenderShaderResources* sr = pMat->shaderItem.m_pShaderResources;
|
||||
|
||||
// assert(e && pREOcLeaf);
|
||||
|
||||
if (pREOcLeaf && e)
|
||||
{
|
||||
// nUsed++;
|
||||
|
||||
int nTempl = rParams.nShaderTemplate;
|
||||
if (nTempl == -2 && i<m_lstShaderTemplates.Num())
|
||||
nTempl = m_lstShaderTemplates[i];
|
||||
|
||||
if(rParams.pfCustomData)
|
||||
{
|
||||
assert(!pREOcLeaf->m_CustomData);
|
||||
pREOcLeaf->m_CustomData = rParams.pfCustomData;
|
||||
}
|
||||
|
||||
if (rParams.nShaderTemplate>0)
|
||||
e->AddTemplate(sr, (int)rParams.nShaderTemplate,NULL);
|
||||
|
||||
if(rParams.dwFObjFlags & FOB_FOGPASS)
|
||||
if(e->GetTemplate(-1)->GetFlags() & EF_OVERLAY)
|
||||
continue; // skip overlays during fog pass - it will be fogged by base geometry fog pass
|
||||
|
||||
bool bTransparent = pMat->shaderItem.IsTransparent();
|
||||
IShader * pShader = rParams.pStateShader;
|
||||
|
||||
if(bTransparent)
|
||||
{
|
||||
if((rParams.dwFlags & RPF_LIGHTPASS) || (rParams.dwFObjFlags & FOB_FOGPASS) || (nTempl == EFT_INVLIGHT))
|
||||
continue;
|
||||
|
||||
if(nSortValue==eS_FogShader)
|
||||
nSortValue=eS_FogShader_Trans;
|
||||
|
||||
if(!GetCVars()->e_overlay_geometry)
|
||||
if(e->GetTemplate(-1)->GetFlags() & EF_OVERLAY)
|
||||
continue;
|
||||
|
||||
if(GetCVars()->e_overlay_geometry >= 2 && e->GetTemplate(-1)->GetFlags() & EF_OVERLAY)
|
||||
{
|
||||
if(!rParams.pCaller || !GetVisAreaManager() ||
|
||||
((CVisArea *)rParams.pCaller->GetEntityVisArea() && !((CVisArea *)rParams.pCaller->GetEntityVisArea())->
|
||||
FindVisArea((CVisArea *)GetVisAreaManager()->m_pCurArea,1, true)))
|
||||
continue;
|
||||
|
||||
if(GetCVars()->e_overlay_geometry == 2)
|
||||
{
|
||||
if(int(GetTimer()->GetCurrTime()*5)&1)
|
||||
pShader = GetRenderer()->EF_LoadShader("NoZTestState", eSH_World, EF_SYSTEM );
|
||||
}
|
||||
else
|
||||
pShader = GetRenderer()->EF_LoadShader("ZTestGreaterState", eSH_World, EF_SYSTEM );
|
||||
|
||||
SetShaderFloat("offset", 0);
|
||||
}
|
||||
else if(GetCVars()->e_overlay_geometry < 2 )
|
||||
m_ShaderParams.SetNum(0);
|
||||
}
|
||||
|
||||
if( rParams.bRenderIntoShadowMap && (pMat->m_Flags & MIF_NOCASTSHADOWS) )
|
||||
continue;
|
||||
|
||||
if( nSortValue == EFSLIST_STENCIL && bTransparent )
|
||||
GetRenderer()->EF_AddEf(rParams.nFogVolumeID, pREOcLeaf, e, sr, pObj, nTempl, pShader, 0);
|
||||
else
|
||||
GetRenderer()->EF_AddEf(rParams.nFogVolumeID, pREOcLeaf, e, sr, pObj, nTempl, pShader, nSortValue);
|
||||
}
|
||||
} //i
|
||||
}*/
|
||||
|
||||
void CStatObj::RenderDebugInfo(const SRendParams & rParams, const CCObject * pObj)
|
||||
{
|
||||
IRenderer * pRend = GetRenderer();
|
||||
|
||||
// bbox
|
||||
pRend->SetMaterialColor(0,1,1,0.5f);
|
||||
pRend->Draw3dBBox(m_vBoxMin*rParams.fScale+rParams.vPos,
|
||||
m_vBoxMax*rParams.fScale+rParams.vPos);
|
||||
|
||||
// scaled bbox (frustum culling check)
|
||||
if(GetCVars()->e_vegetation_debug==2)
|
||||
{
|
||||
pRend->SetMaterialColor(1,0,1,0.5f);
|
||||
pRend->Draw3dBBox(m_vBoxMin*rParams.fScale*1.5f+rParams.vPos,
|
||||
m_vBoxMax*rParams.fScale*1.5f+rParams.vPos);
|
||||
}
|
||||
|
||||
{ // cgf's name and tris num
|
||||
char szName[512];
|
||||
strncpy(szName,m_szFileName,sizeof(szName));
|
||||
while(strstr(szName,"\\"))
|
||||
strcpy(szName, szName+1);
|
||||
float color[4] = {0,1,1,1};
|
||||
pRend->DrawLabelEx(rParams.vPos/*+GetCenter()*rParams.fScale*/,
|
||||
0.75f,color,false,true,"%s(%d tris, %d mats)", szName, m_nLoadedTrisCount,
|
||||
(m_pLeafBuffer && m_pLeafBuffer->m_pMats) ? m_pLeafBuffer->m_pMats->Count() : 0);
|
||||
}
|
||||
|
||||
// helpers
|
||||
for( int i=0; i<m_lstHelpers.Count(); i++)
|
||||
{
|
||||
StatHelperInfo *pHI = &m_lstHelpers[i];
|
||||
|
||||
// make object matrix
|
||||
Matrix44 tMat;
|
||||
tMat = pObj->m_Matrix;
|
||||
|
||||
// draw axes
|
||||
DrawMatrix(tMat);
|
||||
|
||||
tMat = tMat*pHI->tMat;
|
||||
|
||||
Vec3d vTrans = tMat.GetTranslationOLD();
|
||||
|
||||
float color[4] = {1,1,0,1};
|
||||
|
||||
// text
|
||||
pRend->DrawLabelEx(vTrans, 0.75f, color, false, true, "%s", pHI->sName);
|
||||
|
||||
// draw axes
|
||||
DrawMatrix(tMat);
|
||||
}
|
||||
}
|
||||
|
||||
void CStatObj::DrawMatrix(const Matrix44 & tMat)
|
||||
{
|
||||
IRenderer * pRend = GetRenderer();
|
||||
|
||||
Vec3d vTrans = tMat.GetTranslationOLD();
|
||||
|
||||
float color[] = {1,1,1,1};
|
||||
|
||||
//CHANGED_BY_IVO
|
||||
pRend->SetMaterialColor(1,0,0,0);
|
||||
//pRend->Draw3dBBox( vTrans, vTrans+0.05f*Vec3d(tMat.m_values[0]), true );
|
||||
//pRend->DrawLabelEx(vTrans+0.05f*Vec3d(tMat.m_values[0]), 0.75f,color,false,true,"x");
|
||||
pRend->Draw3dBBox( vTrans, vTrans+0.05f*tMat.GetOrtX(), true );
|
||||
pRend->DrawLabelEx(vTrans+0.05f*tMat.GetOrtX(), 0.75f,color,false,true,"x");
|
||||
|
||||
pRend->SetMaterialColor(0,1,0,0);
|
||||
//pRend->Draw3dBBox( vTrans, vTrans+0.05f*Vec3d(tMat.m_values[1]), true );
|
||||
//pRend->DrawLabelEx(vTrans+0.05f*Vec3d(tMat.m_values[1]), 0.75f,color,false,true,"y");
|
||||
pRend->Draw3dBBox( vTrans, vTrans+0.05f*tMat.GetOrtY(), true );
|
||||
pRend->DrawLabelEx(vTrans+0.05f*tMat.GetOrtY(), 0.75f,color,false,true,"y");
|
||||
|
||||
pRend->SetMaterialColor(0,0,1,0);
|
||||
//pRend->Draw3dBBox( vTrans, vTrans+0.05f*Vec3d(tMat.m_values[2]), true );
|
||||
//pRend->DrawLabelEx(vTrans+0.05f*Vec3d(tMat.m_values[2]), 0.75f,color,false,true,"z");
|
||||
pRend->Draw3dBBox( vTrans, vTrans+0.05f*tMat.GetOrtZ(), true );
|
||||
pRend->DrawLabelEx(vTrans+0.05f*tMat.GetOrtZ(), 0.75f,color,false,true,"z");
|
||||
}
|
||||
|
||||
const CDLight * CStatObj::GetLightSources(int nId)
|
||||
{
|
||||
if(nId>=0 && nId<m_lstLSources.Count())
|
||||
return &m_lstLSources[nId];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CStatObj::SpawnParticles( ParticleParams & SpawnParticleParams, const Matrix44 & matWorldSpace, bool bOnlyUpLookingFaces )
|
||||
{
|
||||
// select random vertex
|
||||
int n=rand() % m_pLeafBuffer->m_SecVertCount;
|
||||
// int n = int(rnd()*m_pLeafBuffer->m_SecVertCount);
|
||||
// while(n>=m_pLeafBuffer->m_SecVertCount)
|
||||
// n = int(rnd()*m_pLeafBuffer->m_SecVertCount);
|
||||
|
||||
// access pos and normal
|
||||
int nPosStride = 0, nNormStride = 0;
|
||||
byte * arrPos = m_pLeafBuffer->GetPosPtr(nPosStride);
|
||||
byte * arrNor = m_pLeafBuffer->GetNormalPtr(nNormStride);
|
||||
Vec3d * pPos = (Vec3d*)&arrPos[n*nPosStride];
|
||||
Vec3d * pNorm = (Vec3d*)&arrNor[n*nNormStride];
|
||||
|
||||
// transform
|
||||
Vec3d vWSPos = matWorldSpace.TransformPointOLD(*pPos);
|
||||
|
||||
Vec3d vWSNorm = matWorldSpace.TransformVectorOLD(*pNorm);
|
||||
//Vec3d vWSNorm = GetTransposed44(matWorldSpace)*(*pNorm);
|
||||
|
||||
// spawn
|
||||
if(!bOnlyUpLookingFaces || vWSNorm.z>0.25f)
|
||||
{
|
||||
Get3DEngine()->SpawnParticles(SpawnParticleParams);
|
||||
SpawnParticleParams.vPosition = vWSPos;
|
||||
SpawnParticleParams.vDirection = (SpawnParticleParams.vDirection+vWSNorm)*0.5f;
|
||||
}
|
||||
}
|
||||
118
Cry3DEngine/StatObjSerialize.cpp
Normal file
118
Cry3DEngine/StatObjSerialize.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "serializebuffer.h"
|
||||
#include "objman.h"
|
||||
|
||||
bool CStatObj::Serialize(int & nPos, uchar * pSerBuf, bool bSave, char * szFolderName)
|
||||
{
|
||||
char szSignature[16];
|
||||
if(!LoadBuffer(szSignature, 8, pSerBuf, nPos) || strcmp(szSignature,"StatObj"))
|
||||
return false;
|
||||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
m_lstProxyVerts[i].LoadFromBuffer(pSerBuf,nPos);
|
||||
m_lstProxyInds[i].LoadFromBuffer(pSerBuf,nPos);
|
||||
LoadBuffer(m_vPhysBoxMin[i], sizeof(m_vPhysBoxMin[i]), pSerBuf, nPos);
|
||||
LoadBuffer(m_vPhysBoxMax[i], sizeof(m_vPhysBoxMax[i]), pSerBuf, nPos);
|
||||
m_lstProxyFaceMaterials[i].LoadFromBuffer(pSerBuf,nPos);
|
||||
}
|
||||
|
||||
LoadBuffer(&m_vBoxMin, sizeof(m_vBoxMin), pSerBuf, nPos);
|
||||
LoadBuffer(&m_vBoxMax, sizeof(m_vBoxMax), pSerBuf, nPos);
|
||||
|
||||
assert(m_pSvObj == 0x00000000);
|
||||
|
||||
m_lstHelpers.LoadFromBuffer(pSerBuf,nPos);
|
||||
m_lstLSources.LoadFromBuffer(pSerBuf,nPos);
|
||||
|
||||
// parse name and and load light shader if needed
|
||||
for(int i=0; i<m_lstLSources.Count(); i++)
|
||||
InitCompiledLightSource(&m_lstLSources[i]);
|
||||
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBuffer(eBT_Static,"CompiledStatObj");
|
||||
m_pLeafBuffer->Serialize(nPos, pSerBuf, bSave, m_szFolderName, m_szFileName, CObjManager::m_dCIndexedMesh__LoadMaterial);
|
||||
|
||||
SetShadowVolume(CStatObj::MakeConnectivityInfoFromCompiledData(pSerBuf, nPos, this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStatObj::InitCompiledLightSource(CDLight * pDLight)
|
||||
{
|
||||
char *shName = NULL;
|
||||
char *str;
|
||||
char name[128];
|
||||
char nameTgt[128];
|
||||
strncpy(name, pDLight->m_Name, sizeof(name));
|
||||
str = strstr(name, "->");
|
||||
if (str)
|
||||
{
|
||||
name[str-name] = 0;
|
||||
strncpy(nameTgt, &str[2], sizeof(nameTgt));
|
||||
}
|
||||
else
|
||||
nameTgt[0] = 0;
|
||||
if(str=strchr(name, '('))
|
||||
{
|
||||
name[str-name] = 0;
|
||||
shName = &name[str-name+1];
|
||||
if(str=strchr(shName, ')'))
|
||||
shName[str-shName] = 0;
|
||||
}
|
||||
|
||||
// strcpy(pDLight->m_Name, name);
|
||||
|
||||
if (nameTgt[0])
|
||||
{
|
||||
// strcpy(pDLight->m_TargetName, nameTgt);
|
||||
}
|
||||
pDLight->m_Flags &= ~(DLF_LIGHTSOURCE | DLF_HEATSOURCE);
|
||||
if (!pDLight->Parse())
|
||||
pDLight->m_Flags |= DLF_LIGHTSOURCE;
|
||||
else
|
||||
{
|
||||
if (!strncmp(pDLight->m_Name, "local_hs", 8))
|
||||
{
|
||||
pDLight->m_fDirectFactor = 0;
|
||||
pDLight->m_Flags |= DLF_LOCAL;
|
||||
}
|
||||
}
|
||||
if (shName)
|
||||
{
|
||||
pDLight->m_pShader = GetRenderer()->EF_LoadShader(shName, eSH_Misc);
|
||||
if (pDLight->m_pShader!=0 && (pDLight->m_pShader->GetFlags() & EF_NOTFOUND))
|
||||
{
|
||||
pDLight->m_pShader->Release();
|
||||
pDLight->m_pShader = NULL;
|
||||
pDLight->m_Flags |= DLF_FAKE;
|
||||
#if !defined(LINUX)
|
||||
Warning(0,m_szFileName,
|
||||
"Error: CIndexedMesh::MakeLightSources: Shader %s not found for lsource %s",
|
||||
shName, pDLight->m_Name);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pDLight->m_pShader!=0 && (pDLight->m_pShader->GetLFlags() & LMF_DISABLE))
|
||||
pDLight->m_Flags |= DLF_FAKE;
|
||||
}
|
||||
|
||||
pDLight->MakeBaseParams();
|
||||
}
|
||||
95
Cry3DEngine/StatObjShadow.cpp
Normal file
95
Cry3DEngine/StatObjShadow.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjshadow.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: shadow maps
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "StatObj.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
|
||||
void CStatObj::PrepareShadowMaps(const Vec3d & obj_pos, ShadowMapLightSource * pLSource)
|
||||
{
|
||||
if(!GetCVars()->e_shadow_maps)
|
||||
return;
|
||||
|
||||
// reset frustums
|
||||
int f;
|
||||
for(f=0; f<pLSource->m_LightFrustums.Count(); f++)
|
||||
{ delete pLSource->m_LightFrustums[f].pModelsList; pLSource->m_LightFrustums[f].pModelsList=0; }
|
||||
pLSource->m_LightFrustums.Reset();
|
||||
|
||||
{ // define new frustum
|
||||
ShadowMapFrustum new_lof;
|
||||
// memset(&new_lof,0,sizeof(ShadowMapFrustum));
|
||||
|
||||
new_lof.pModelsList = new list2<IStatObj*>;
|
||||
new_lof.pModelsList->PreAllocate(128);
|
||||
|
||||
list2<IStatObj*> so;
|
||||
so.Add(this);
|
||||
|
||||
ShadowMapFrustum * lof = GetRenderer()->MakeShadowMapFrustum(&new_lof, pLSource, obj_pos+GetCenter()/*Vec3d(0,0,GetCenterZ())*/, &so, EST_DEPTH_BUFFER);
|
||||
|
||||
lof->pOwnerGroup = this;
|
||||
|
||||
if(lof)
|
||||
{
|
||||
pLSource->m_LightFrustums.Add(*lof);
|
||||
}
|
||||
|
||||
// this lists are in another object now
|
||||
new_lof.pModelsList=0;
|
||||
new_lof.pEntityList=0;
|
||||
}
|
||||
|
||||
int nTexSize = GetCVars()->e_max_shadow_map_size;
|
||||
while(nTexSize > GetRadius()*200)
|
||||
nTexSize/=2;
|
||||
|
||||
if(nTexSize<16)
|
||||
nTexSize=16; // in case of error
|
||||
|
||||
pLSource->m_LightFrustums[f].nTexSize = nTexSize;
|
||||
|
||||
// make depth textures
|
||||
//for( f=0; f<pLSource->m_LightFrustums.Count(); f++)
|
||||
// GetRenderer()->PrepareDepthMap(&pLSource->m_LightFrustums[f], true);
|
||||
}
|
||||
|
||||
void CStatObj::MakeShadowMaps(const Vec3d vSunPos)
|
||||
{
|
||||
if(m_pSMLSource)
|
||||
{
|
||||
for(int f=0; f<m_pSMLSource->m_LightFrustums.Count(); f++)
|
||||
{
|
||||
if(m_pSMLSource->m_LightFrustums[f].depth_tex_id)
|
||||
{
|
||||
// shadow maps can be deleted only on smaps pool destruction
|
||||
// GetRenderer()->RemoveTexture(m_pSMLSource->m_LightFrustums[f].depth_tex_id);
|
||||
m_pSMLSource->m_LightFrustums[f].depth_tex_id=0;
|
||||
}
|
||||
}
|
||||
m_pSMLSource->m_LightFrustums.Reset();
|
||||
}
|
||||
|
||||
delete m_pSMLSource;
|
||||
m_pSMLSource = new ShadowMapLightSource;
|
||||
memset(m_pSMLSource,0,sizeof(ShadowMapLightSource));
|
||||
|
||||
m_pSMLSource->fRadius = 500000;
|
||||
|
||||
m_pSMLSource->vSrcPos = GetNormalized(vSunPos)*10000;//0;
|
||||
|
||||
if(GetCVars()->e_shadow_maps)
|
||||
PrepareShadowMaps(Vec3d(0,0,0), m_pSMLSource);
|
||||
}
|
||||
649
Cry3DEngine/StatObjShadowVolumes.cpp
Normal file
649
Cry3DEngine/StatObjShadowVolumes.cpp
Normal file
@@ -0,0 +1,649 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjshadow.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: shadow maps
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "meshidx.h"
|
||||
#include <IEdgeConnectivityBuilder.h> // IEdgeConnectivityBuilder
|
||||
#include "StencilShadowConnectivity.h"
|
||||
#include "IndoorVolumes.h"
|
||||
#include "IndoorShadowVolumes.h"
|
||||
#include "CRETriMeshShadow.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
ItShadowVolume * CStatObj::MakeConnectivityInfo(CIndexedMesh * pMesh, const Vec3d & vOrigin, CStatObj * pStatObj)
|
||||
{
|
||||
//if it doestn exists yet, create one
|
||||
tShadowVolume * ptSvObj = new tShadowVolume;
|
||||
ptSvObj->pSvObj = new CShadowVolObject( );
|
||||
|
||||
for (int i=0; i<pMesh->m_nFaceCount; i++)
|
||||
{
|
||||
CObjFace *cf=&pMesh->m_pFaces[i];
|
||||
|
||||
for (int v=0; v<3; v++)
|
||||
{
|
||||
cf->m_Vecs[v].x=pMesh->m_pVerts[pMesh->m_pFaces[i].v[v]].x;
|
||||
cf->m_Vecs[v].y=pMesh->m_pVerts[pMesh->m_pFaces[i].v[v]].y;
|
||||
cf->m_Vecs[v].z=pMesh->m_pVerts[pMesh->m_pFaces[i].v[v]].z;
|
||||
} //v
|
||||
|
||||
//calc plane equation
|
||||
cf->m_Plane.CalcPlane(cf->m_Vecs[2],cf->m_Vecs[1],cf->m_Vecs[0]);
|
||||
} //i
|
||||
|
||||
//set the same light area geometry
|
||||
tContainer tCont;
|
||||
tCont.pObj = pStatObj;
|
||||
tCont.pSV=NULL;
|
||||
//ptSvObj->pSvObj->AddGeometry(this);
|
||||
ptSvObj->pSvObj->AddGeometry(tCont);
|
||||
//mark the geometry as shared
|
||||
ptSvObj->pSvObj->m_dwFlags|=FLAG_GEOMETRY_SHARED;
|
||||
//set the position of the shadow volumes
|
||||
ptSvObj->pSvObj->SetPos(/*pParams->*/vOrigin);
|
||||
//precalc edges
|
||||
if(!ptSvObj->pSvObj->CreateConnectivityInfo())
|
||||
{ // delete empty objects
|
||||
ptSvObj->Release();
|
||||
ptSvObj=NULL;
|
||||
}
|
||||
|
||||
|
||||
//assign to the istatobj
|
||||
return (ptSvObj);
|
||||
}
|
||||
|
||||
ItShadowVolume * CStatObj::MakeConnectivityInfoFromCompiledData(void * pStream, int & nPos, CStatObj * pStatObj)
|
||||
{
|
||||
//if it doestn exists yet, create one
|
||||
tShadowVolume * ptSvObj = new tShadowVolume;
|
||||
ptSvObj->pSvObj = new CShadowVolObject( );
|
||||
|
||||
tContainer tCont;
|
||||
tCont.pObj = pStatObj;
|
||||
tCont.pSV=NULL;
|
||||
//ptSvObj->pSvObj->AddGeometry(this);
|
||||
ptSvObj->pSvObj->AddGeometry(tCont);
|
||||
//mark the geometry as shared
|
||||
ptSvObj->pSvObj->m_dwFlags|=FLAG_GEOMETRY_SHARED;
|
||||
//set the position of the shadow volumes
|
||||
ptSvObj->pSvObj->SetPos(Vec3d(0,0,0));
|
||||
|
||||
IEdgeConnectivityBuilder * iBuilder = Get3DEngine()->GetNewConnectivityBuilder();
|
||||
ptSvObj->pSvObj->GetEdgeConnectivity() = iBuilder->ConstructConnectivity();
|
||||
nPos += ptSvObj->pSvObj->GetEdgeConnectivity()->Serialize(false,&((byte*)pStream)[nPos],1000000, NULL);//GetLog());
|
||||
|
||||
return (ptSvObj);
|
||||
}
|
||||
|
||||
// NOTE: Current implementation doesn't take the limit LOD parameter into account
|
||||
void CStatObj::RenderShadowVolumes(const SRendParams *pParams, int nLimitLod)
|
||||
{
|
||||
// assert(pParams->lSource);
|
||||
|
||||
CDLight tTempLight;
|
||||
tTempLight = *(pParams->pShadowVolumeLightSource);
|
||||
|
||||
Matrix44 tInvRot;
|
||||
|
||||
if(pParams->pMatrix)
|
||||
{
|
||||
tInvRot=*pParams->pMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
//tInvRot.Identity();
|
||||
//tInvRot=GetTranslationMat(pParams->vPos)*tInvRot;
|
||||
//tInvRot=GetRotationZYX44(-pParams->vAngles*gf_DEGTORAD)*tInvRot; //NOTE: angles in radians and negated
|
||||
|
||||
//OPTIMISED_BY_IVO
|
||||
tInvRot = Matrix34::CreateRotationXYZ(pParams->vAngles*gf_DEGTORAD, pParams->vPos ); //set scaling and translation in one function call
|
||||
tInvRot = GetTransposed44(tInvRot); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
||||
|
||||
}
|
||||
tInvRot.Invert44();
|
||||
|
||||
Vec3d vPos=tInvRot.TransformPointOLD(tTempLight.m_Origin);
|
||||
tTempLight.m_vObjectSpacePos=vPos;
|
||||
|
||||
/*
|
||||
{
|
||||
char str[256];
|
||||
|
||||
snprintf(str,"'%s' %p (%.2f %.2f %.2f) (%.2f %.2f %.2f)\n",pParams->lSource->m_Name,this,
|
||||
tTempLight.m_Origin.x,tTempLight.m_Origin.y,tTempLight.m_Origin.z,
|
||||
vPos.x,vPos.y,vPos.z);
|
||||
|
||||
OutputDebugString(str);
|
||||
}
|
||||
*/
|
||||
|
||||
//FIXME: move this code in the conn. info calculation
|
||||
//assign vertices and calc planes
|
||||
CIndexedMesh *pMesh = GetTriData();
|
||||
|
||||
if (!GetShadowVolume())
|
||||
{
|
||||
if(pMesh)
|
||||
{
|
||||
SetShadowVolume(CStatObj::MakeConnectivityInfo(pMesh, Vec3d(0,0,0)/* pParams->vOrigin*/, this));
|
||||
FreeTriData(); // source geometry is needed only for stencil shadows
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
ItShadowVolume *ptSvObj=GetShadowVolume();
|
||||
CShadowVolObject *pSvObj=ptSvObj->GetShadowVolume();
|
||||
|
||||
IStencilShadowConnectivity* pConnectivity = pSvObj->GetEdgeConnectivity();
|
||||
if(!pParams->pShadowVolumeLightSource || !pConnectivity)
|
||||
return;
|
||||
|
||||
if (/*!pSvObj->GetNumFaces() && */!pConnectivity->IsStandalone())
|
||||
return;
|
||||
|
||||
if(!m_bOpenEdgesTested && pConnectivity->numOrphanEdges())
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning(0,m_szFileName,"%d open edges found during shadow volume calculations for %s %s",
|
||||
pConnectivity->numOrphanEdges(), m_szFileName, m_szGeomName );
|
||||
#endif
|
||||
m_bOpenEdgesTested = true;
|
||||
}
|
||||
|
||||
//GetRenderer()->Draw3dBBox(Vec3d(vPos.x-0.5f,vPos.y-0.5f,vPos.z-0.5f),Vec3d(vPos.x+0.5f,vPos.y+0.5f,vPos.z+0.5f));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//this will be done in RE right before rendering
|
||||
//pSvObj->CalculateDynamicShadowVolume(tTempLight);
|
||||
//pSvObj->CreateDynamicShadowVolumeBuffer();
|
||||
|
||||
if(!pSvObj->m_pReMeshShadow)
|
||||
pSvObj->m_pReMeshShadow = (CRETriMeshShadow *)GetRenderer()->EF_CreateRE(eDATA_TriMeshShadow);
|
||||
|
||||
// draw shadow volumes
|
||||
if(pSvObj->m_pReMeshShadow)
|
||||
{
|
||||
// get the object
|
||||
CCObject *pObj;
|
||||
pObj = GetRenderer()->EF_GetObject(true);
|
||||
pObj->m_DynLMMask = pParams->nDLightMask;
|
||||
/* if(!m_nRenderStackLevel)
|
||||
{
|
||||
pObj->m_nScissorX1 = pParams->nScissorX1;
|
||||
pObj->m_nScissorY1 = pParams->nScissorY1;
|
||||
pObj->m_nScissorX2 = pParams->nScissorX2;
|
||||
pObj->m_nScissorY2 = pParams->nScissorY2;
|
||||
}*/
|
||||
|
||||
// the translation is in the object, otherwise we get z-fighting
|
||||
// with the shaders
|
||||
// hh unused pSvObj->m_pReMeshShadow->m_vOrigin = Vec3d(0,0,0);
|
||||
|
||||
if (pParams->pMatrix)
|
||||
pObj->m_Matrix = *pParams->pMatrix;
|
||||
else
|
||||
mathCalcMatrix(pObj->m_Matrix, pParams->vPos, pParams->vAngles, Vec3d(1,1,1), Cry3DEngineBase::m_CpuFlags);
|
||||
pObj->m_ObjFlags |= FOB_TRANS_MASK;
|
||||
|
||||
//assign shadow volume resources
|
||||
//allow the calculation to be done right before rendering
|
||||
pSvObj->m_pReMeshShadow->m_pSvObj = ptSvObj;
|
||||
pSvObj->m_pReMeshShadow->m_nCurrInst = -1;
|
||||
pObj->m_CustomData = pParams->pCaller;
|
||||
pObj->m_TempVars[0] = pParams->fShadowVolumeExtent;
|
||||
|
||||
IShader * pEff = ((C3DEngine*)Get3DEngine())->m_pSHStencil;
|
||||
GetRenderer()->EF_AddEf(0, (CRendElement *)pSvObj->m_pReMeshShadow , pEff, NULL, pObj, -1, NULL, pParams->nSortValue);
|
||||
}
|
||||
}
|
||||
|
||||
CVolume::~CVolume()
|
||||
{
|
||||
for (ContainerListIt i=m_lstObjects.begin();i!=m_lstObjects.end();)
|
||||
{
|
||||
RemoveGeometry(NULL,i);
|
||||
i=m_lstObjects.begin();
|
||||
} //i
|
||||
|
||||
m_lstObjects.clear(); //for the sake of clarity
|
||||
}
|
||||
|
||||
bool CShadowVolObject::CreateConnectivityInfo( void )
|
||||
{
|
||||
//IStatObj *ob=m_lstStatObjs[0]; assert(ob);
|
||||
IStatObj *ob=m_lstObjects[0].pObj;
|
||||
assert(ob);
|
||||
CIndexedMesh *pMesh=ob->GetTriData();
|
||||
|
||||
if (!pMesh)
|
||||
return false; // to prevent crash, this could be if the file versions are changing)
|
||||
|
||||
//list of faces is shared from statobj
|
||||
CObjFace * pFaceList = pMesh->m_pFaces;
|
||||
int nNumFaces=pMesh->m_nFaceCount;
|
||||
Vec3d *pVert=pMesh->m_pVerts;
|
||||
|
||||
IEdgeConnectivityBuilder * iBuilder = Get3DEngine()->GetNewStaticConnectivityBuilder();
|
||||
|
||||
assert(iBuilder);
|
||||
|
||||
iBuilder->ReserveForTriangles(nNumFaces,pMesh->m_nVertCount);
|
||||
|
||||
for(int i=0;i<nNumFaces;i++)
|
||||
{
|
||||
CObjFace *cf = &pFaceList[i];
|
||||
|
||||
if(cf->m_dwFlags & FLAG_SKIP_SHADOWVOLUME)
|
||||
continue;
|
||||
|
||||
// with welding
|
||||
unsigned short a=cf->v[0],b=cf->v[1],c=cf->v[2];
|
||||
iBuilder->AddTriangleWelded(a,b,c,pVert[a],pVert[b],pVert[c]);
|
||||
}
|
||||
|
||||
m_pEdgeConnectivity=iBuilder->ConstructConnectivity();
|
||||
|
||||
DWORD dwVertCount=0,dwTriCount=0;
|
||||
if(m_pEdgeConnectivity)
|
||||
{
|
||||
m_pEdgeConnectivity->GetStats(dwVertCount,dwTriCount);
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
char str[256];
|
||||
snprintf(str, sizeof(str), "StencilEdgeConnectivity Indoor Stats %p: %d/%d Vertices %d/%d Faces\n",m_pEdgeConnectivity,dwVertCount,pMesh->m_nVertCount,dwTriCount,nNumFaces);
|
||||
OutputDebugString(str);
|
||||
#endif*/
|
||||
}
|
||||
|
||||
return dwVertCount && dwTriCount;
|
||||
}
|
||||
|
||||
void CVolume::SetPos(const Vec3d &vPos)
|
||||
{
|
||||
m_vOrigin=vPos;
|
||||
|
||||
pe_params_pos par_pos;
|
||||
par_pos.pos=vPos;
|
||||
|
||||
//for (iphysobjit i=m_lstPhysObjs.begin();i!=m_lstPhysObjs.end();i++)
|
||||
for (ContainerListIt i=m_lstObjects.begin();i!=m_lstObjects.end();i++)
|
||||
{
|
||||
IPhysicalEntity *pEnt=(*i).pEnt;
|
||||
if (pEnt)
|
||||
pEnt->SetParams(&par_pos);
|
||||
} //i
|
||||
}
|
||||
|
||||
void CVolume::AddGeometry(tContainer tCont)
|
||||
{
|
||||
m_vMins.CheckMin(tCont.pObj->GetBoxMin());
|
||||
m_vMaxs.CheckMax(tCont.pObj->GetBoxMax());
|
||||
|
||||
/*
|
||||
m_lstStatObjs.push_back(pSource);
|
||||
|
||||
if (pEnt)
|
||||
m_lstPhysObjs.push_back(pEnt);
|
||||
*/
|
||||
|
||||
m_lstObjects.push_back(tCont);
|
||||
|
||||
m_nObjCount++;
|
||||
}
|
||||
|
||||
|
||||
CShadowVolObject::~CShadowVolObject()
|
||||
{
|
||||
|
||||
/* //do not delete 'cause the source is a cstatobj
|
||||
if (m_pFaceList)
|
||||
{
|
||||
delete [] m_pFaceList;
|
||||
m_pFaceList=NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if(m_pEdgeConnectivity)
|
||||
{
|
||||
m_pEdgeConnectivity->Release();
|
||||
m_pEdgeConnectivity=0;
|
||||
}
|
||||
|
||||
FreeVertexBuffers();
|
||||
}
|
||||
|
||||
void CShadowVolObject::FreeVertexBuffers()
|
||||
{
|
||||
if (m_pSystemVertexBuffer)
|
||||
{
|
||||
delete [] m_pSystemVertexBuffer;
|
||||
m_pSystemVertexBuffer=0;
|
||||
}
|
||||
|
||||
if (m_pReMeshShadow)
|
||||
{
|
||||
m_pReMeshShadow->Release();
|
||||
m_pReMeshShadow=NULL;
|
||||
}
|
||||
|
||||
/*if (m_pReMeshAdditionalShadow)
|
||||
{
|
||||
//FIXME:Move deallocation into renderelements
|
||||
if (m_pReMeshAdditionalShadow->m_pShadowVolEdgesList)
|
||||
{
|
||||
//those edges are shared!
|
||||
//delete [] m_pReMeshAdditionalShadow->m_pShadowVolEdgesList;
|
||||
m_pReMeshAdditionalShadow->m_pShadowVolEdgesList=NULL;
|
||||
}
|
||||
|
||||
m_pReMeshAdditionalShadow->Release();
|
||||
m_pReMeshAdditionalShadow=NULL;
|
||||
}*/
|
||||
|
||||
m_nNumVertices=0;
|
||||
}
|
||||
|
||||
void CShadowVolObject::CheckUnload()
|
||||
{
|
||||
if(m_pReMeshShadow)
|
||||
m_pReMeshShadow->mfCheckUnload();
|
||||
}
|
||||
|
||||
void CShadowVolObject::RebuildShadowVolumeBuffer( const CDLight &lSource, float fReadyShadowVolumeExtent ) // lSource has to be object relative
|
||||
{
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4311 )
|
||||
#endif
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
if(!m_pEdgeConnectivity || (/*!m_nNumFaces && */!m_pEdgeConnectivity->IsStandalone()))
|
||||
{
|
||||
// PrepareShadowVolumeVertexBuffer(0,0);
|
||||
return;
|
||||
}
|
||||
|
||||
//! M.M. for debugging stencil shadows (0 is default, use !=0 to force reacalculation of indoor stencil shadow volumes)
|
||||
|
||||
IEdgeDetector * iEdgeDetector = Get3DEngine()->GetEdgeDetector();
|
||||
|
||||
Vec3d vObjectSpaceLight=lSource.m_vObjectSpacePos;
|
||||
Vec3d vWorldSpaceLight=lSource.m_Origin;
|
||||
|
||||
// baustelle
|
||||
IStatObj *ob=m_lstObjects[0].pObj;
|
||||
CIndexedMesh *pMesh=ob->GetTriData();
|
||||
|
||||
assert(m_pEdgeConnectivity->IsStandalone());
|
||||
|
||||
if (m_pEdgeConnectivity->IsStandalone())
|
||||
{
|
||||
iEdgeDetector->BuildSilhuetteFromPos(m_pEdgeConnectivity, vObjectSpaceLight, NULL);
|
||||
}
|
||||
/*else
|
||||
{
|
||||
unsigned *pTriOriBitfield=iEdgeDetector->getOrientationBitfield(m_nNumFaces);
|
||||
|
||||
for(int nFace = 0; nFace < m_nNumFaces;)
|
||||
{
|
||||
unsigned nOrientBit = 1;
|
||||
|
||||
do
|
||||
{
|
||||
CObjFace *cf=&m_pFaceList[nFace];
|
||||
|
||||
if (cf->m_dwFlags & FLAG_SKIP_SHADOWVOLUME)//! transparent surfaces don't cast shadows
|
||||
{
|
||||
nFace++;
|
||||
continue;
|
||||
}
|
||||
|
||||
float dist1=cf->m_Plane.DistFromPlane(vObjectSpaceLight);
|
||||
|
||||
if(dist1>0)
|
||||
*pTriOriBitfield |= nOrientBit;
|
||||
nOrientBit <<= 1;
|
||||
}
|
||||
while (((++nFace) < m_nNumFaces) && (nOrientBit) != 0);
|
||||
|
||||
++pTriOriBitfield;
|
||||
}
|
||||
if(!pMesh)
|
||||
return; // to prevent crash, this could be if the file versions are changing
|
||||
|
||||
iEdgeDetector->BuildSilhuetteFromBitfield(m_pEdgeConnectivity,pMesh->m_pVerts);
|
||||
}*/
|
||||
|
||||
unsigned nNumIndices = iEdgeDetector->numShadowVolumeIndices();
|
||||
unsigned nNumVertices = iEdgeDetector->numShadowVolumeVertices();
|
||||
|
||||
// float fShadowVolumeExtent=20.0f;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// [5/12/2002] Marco's NOTE: removed this part, because to allow shadows to cross
|
||||
// portals, we should not check for the object being inside/outside the
|
||||
// area / so the check is now unified like for outdoors
|
||||
|
||||
// extend as little as possible to save fill rate M.M. *********************************************************************** Start
|
||||
// I have to be in indoor otherwise shadow volumes doesn't make sense
|
||||
// to prevent crash, but this should never be - without this info I assume a big value would do it
|
||||
if(inpArea)
|
||||
{
|
||||
Vec3d vMinObjBBox=GetBBoxMin(true),vMaxObjBBox=GetBBoxMax(true);
|
||||
|
||||
// debugging
|
||||
// GetRenderer()->Draw3dBBox(vMinObjBBox,vMaxObjBBox);
|
||||
|
||||
// if the lightsource is inside the object, use big value
|
||||
// - it's dangerous to extrude too much (althougth extrude to infinity is theoretical possible)
|
||||
|
||||
// calculate the minimum extrusion level (to get the object bounding box extruded outside of the room)
|
||||
fShadowVolumeExtent = inpArea->CalculateMinimumShadowExtrusion(vWorldSpaceLight,vMinObjBBox,vMaxObjBBox);
|
||||
|
||||
// assert(fShadowVolumeExtent>=1.0f);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
// calculate optimal extent for outdoor entity
|
||||
// todo take into account object scale
|
||||
//Vec3d vMinObjBBox=GetBBoxMin(true),vMaxObjBBox=GetBBoxMax(true);
|
||||
/* Vec3d vMinObjBBox=GetBBoxMin(),vMaxObjBBox=GetBBoxMax();
|
||||
|
||||
Vec3d vObjCenter = (vMinObjBBox+vMaxObjBBox)*0.5;
|
||||
float fObjRadius = (vMaxObjBBox-vMinObjBBox).Length()*0.5f;
|
||||
float fObjLightDist = GetDistance(vObjectSpaceLight, vObjCenter) - fObjRadius;
|
||||
|
||||
if(fObjLightDist<0.01f)
|
||||
fObjLightDist=0.01f;
|
||||
|
||||
fShadowVolumeExtent = lSource.m_fRadius/fObjLightDist;
|
||||
|
||||
if(fShadowVolumeExtent<1.f)
|
||||
fShadowVolumeExtent=1.f;
|
||||
else if(fShadowVolumeExtent>20.f)
|
||||
fShadowVolumeExtent=20.f;*/
|
||||
}
|
||||
// extend as little as possible to save fill rate M.M. *********************************************************************** End
|
||||
|
||||
PrepareShadowVolumeVertexBuffer(nNumIndices, nNumVertices);
|
||||
|
||||
if (nNumVertices > 1 && nNumIndices > 1)
|
||||
{
|
||||
// m_arrIndices.reinit(n)
|
||||
iEdgeDetector->meshShadowVolume (vObjectSpaceLight, fReadyShadowVolumeExtent, (Vec3d *)m_pSystemVertexBuffer, &m_arrIndices[0]);
|
||||
|
||||
CRETriMeshShadow::ShadVolInstanceInfo * pSVI = &m_pReMeshShadow->m_arrLBuffers[m_pReMeshShadow->m_nCurrInst];
|
||||
|
||||
if( pSVI->pVB && pSVI->pVB->m_SecVertCount == (int)m_nNumVertices &&
|
||||
pSVI->pVB->m_Indices.m_nItems == (int)nNumIndices )
|
||||
{
|
||||
pSVI->pVB->UpdateSysIndices(nNumIndices ? &m_arrIndices[0] : 0, nNumIndices);
|
||||
pSVI->pVB->UpdateSysVertices(m_pSystemVertexBuffer,m_nNumVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pSVI->pVB)
|
||||
GetRenderer()->DeleteLeafBuffer(pSVI->pVB);
|
||||
|
||||
// hack: todo: make m_arrIndices list2
|
||||
pSVI->pVB = GetRenderer()->CreateLeafBufferInitialized(
|
||||
m_pSystemVertexBuffer, m_nNumVertices, VERTEX_FORMAT_P3F,
|
||||
&m_arrIndices[0], nNumIndices, R_PRIMV_TRIANGLES, "ShadowVolume", eBT_Dynamic, 1 , 0, 0, this);
|
||||
assert(m_nNumVertices && nNumIndices);
|
||||
pSVI->pVB->SetChunk(0,0,m_nNumVertices,0,nNumIndices);
|
||||
assert((*(pSVI->pVB)).m_pMats->Count());
|
||||
}
|
||||
|
||||
/*
|
||||
if(!pSVI->pVB)
|
||||
pSVI->pVB = GetRenderer()->CreateBuffer(m_nNumVertices, VERTEX_FORMAT_P3F,
|
||||
&pSVI->plstIndices->GetAt(0), pSVI->plstIndices->Count(), "InstanceShadowVolume");
|
||||
|
||||
GetRenderer()->UpdateBuffer(pSVI->pVB, m_pSystemVertexBuffer, m_nNumVertices,true);
|
||||
GetRenderer()->UpdateIndices(pSVI->pVB, &m_arrIndices[0], m_arrIndices.size());
|
||||
*/
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
for (unsigned i = 0; i < nNumIndices; ++i)
|
||||
assert(m_arrIndices[i] < nNumVertices);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
m_pReMeshShadow->m_vOrigin=rParams->vPos;
|
||||
m_pReMeshShadow->m_vAngles=rParams->vAngles;
|
||||
|
||||
|
||||
//get the effect object from the renderer
|
||||
CCObject *pObj = renderer->EF_GetObject(true);
|
||||
|
||||
pObj->m_Trans = rParams->vPos;
|
||||
pObj->m_Angs = rParams->vAngles;
|
||||
pObj->m_Scale = 1.0f;
|
||||
|
||||
m_pReMeshShadow->m_nNumIndices = nNumIndices;
|
||||
m_pReMeshShadow->mfCheckUpdate();
|
||||
//renderer->UpdateBuffer (m_pRenShadowVolumeBuffer, m_pMemShadowVolumeBuffer, nNumVertices, true, 0);
|
||||
renderer->UpdateBuffer(m_pRenShadowVolumeLBuffer->m_pVertexBuffer,m_pMemShadowVolumeBuffer,nNumVertices,true);
|
||||
renderer->UpdateIndices(m_pRenShadowVolumeLBuffer->m_pVertexBuffer,&m_arrIndices[0],nNumIndices);
|
||||
renderer->EF_AddEf(0, (CRendElement *)m_pReMeshShadow , rParams->pEff, pObj, -1, NULL, rParams->nSortValue);
|
||||
*/
|
||||
|
||||
// m_pReMeshShadow->m_nNumIndices = nNumIndices;
|
||||
// m_pReMeshShadow->mfCheckUpdate(0); // call before update, to make sure video buffer is there
|
||||
|
||||
// assert(m_pRenShadowVolumeLBuffer);
|
||||
// assert(m_pRenShadowVolumeLBuffer->m_pVertexBuffer);
|
||||
|
||||
// GetRenderer()->UpdateBuffer(m_pRenShadowVolumeLBuffer->m_pVertexBuffer,pSystemBuffer,nNumVertices,true);
|
||||
// GetRenderer()->UpdateIndices(m_pRenShadowVolumeLBuffer->m_pVertexBuffer,&m_arrIndices[0],nNumIndices);
|
||||
// m_pRenShadowVolumeLBuffer->m_UpdateVBufferMask &= ~1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i=0;
|
||||
}
|
||||
}
|
||||
|
||||
void CVolume::RemoveGeometry(IStatObj *pSource,ContainerListIt it/* =NULL */)
|
||||
{
|
||||
ContainerListIt i = m_lstObjects.end();
|
||||
if (it!=m_lstObjects.end())
|
||||
i=it;
|
||||
else
|
||||
{
|
||||
for (ContainerListIt it2=m_lstObjects.begin();it2!=m_lstObjects.end();it2++)
|
||||
{
|
||||
tContainer tempCont=(*it2);
|
||||
if (tempCont.pObj==pSource)
|
||||
{
|
||||
i=it2;
|
||||
break;
|
||||
}
|
||||
} //it2
|
||||
}
|
||||
|
||||
if (i!=m_lstObjects.end())
|
||||
{
|
||||
tContainer tempCont=(*i);
|
||||
|
||||
IStatObj *pSource=tempCont.pObj;
|
||||
if (pSource && (!(m_dwFlags & FLAG_GEOMETRY_SHARED)))
|
||||
Get3DEngine()->ReleaseObject(pSource);
|
||||
|
||||
IPhysicalEntity *pEnt=(tempCont.pEnt);
|
||||
if (pEnt)
|
||||
GetPhysicalWorld()->DestroyPhysicalEntity(pEnt);
|
||||
|
||||
m_lstObjects.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the resources for rendering shadow volumes
|
||||
// This include:
|
||||
// index and vertex in-memory arrays
|
||||
// render object (m_pReMeshShadow, m_pRenShadowVolumeBuffer, whatever support they need)
|
||||
void CShadowVolObject::PrepareShadowVolumeVertexBuffer( unsigned nNumIndices, unsigned nNumVertices )
|
||||
{
|
||||
if (!nNumIndices || !nNumVertices)
|
||||
return;
|
||||
|
||||
bool bRecreate = false;
|
||||
|
||||
// Realloc index in-mem buffer
|
||||
if (m_arrIndices.size() < nNumIndices)
|
||||
{
|
||||
m_arrIndices.reinit(nNumIndices);
|
||||
bRecreate = true;
|
||||
}
|
||||
|
||||
// Realloc vertex in-mem buffer
|
||||
if (m_nNumVertices < nNumVertices)
|
||||
{
|
||||
m_nNumVertices = nNumVertices;
|
||||
bRecreate = true;
|
||||
}
|
||||
|
||||
if (bRecreate)
|
||||
{
|
||||
if (m_pSystemVertexBuffer)
|
||||
{
|
||||
delete [] m_pSystemVertexBuffer;
|
||||
m_pSystemVertexBuffer=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_pReMeshShadow); // should be called from inside this object
|
||||
// m_pReMeshShadow = (CRETriMeshShadow *)GetRenderer()->EF_CreateRE(eDATA_TriMeshShadow);
|
||||
|
||||
if(!m_pSystemVertexBuffer)
|
||||
{
|
||||
assert(m_nNumVertices);
|
||||
m_pSystemVertexBuffer = new Vec3d[m_nNumVertices];
|
||||
assert(m_pSystemVertexBuffer);
|
||||
}
|
||||
}
|
||||
211
Cry3DEngine/StatObjStream.cpp
Normal file
211
Cry3DEngine/StatObjStream.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjconstr.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: loading
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "MeshIdx.h"
|
||||
#include "../RenderDll/Common/shadow_renderer.h"
|
||||
#include <irenderer.h>
|
||||
#include <CrySizer.h>
|
||||
|
||||
|
||||
void CStatObj::StreamOnProgress (IReadStream* pStream)
|
||||
{
|
||||
}
|
||||
|
||||
void CStatObj::ProcessStreamOnCompleteError()
|
||||
{ // file was not loaded successfully
|
||||
m_eCCGFStreamingStatus = ecss_NotLoaded;
|
||||
|
||||
// try to rebuild compiled file if not tryed yet
|
||||
/* if(!m_bCompilingNotAllowed)
|
||||
{
|
||||
char szCompiledFileName[MAX_PATH_LENGTH];
|
||||
MakeCompiledFileName(szCompiledFileName,MAX_PATH_LENGTH);
|
||||
bool bCompRes = CompileObject(szCompiledFileName, m_szFileName, m_szGeomName,
|
||||
m_eVertsSharing, m_bLoadAdditinalInfo, m_bKeepInLocalSpace);
|
||||
|
||||
// load new compiled file
|
||||
if(bCompRes)
|
||||
{
|
||||
m_bCompilingNotAllowed=1;
|
||||
StreamCCGF(true);
|
||||
m_bCompilingNotAllowed=0;
|
||||
}
|
||||
|
||||
if(m_eCCGFStreamingStatus == ecss_Ready)
|
||||
return; // success
|
||||
}
|
||||
else if(strstr(m_szFileName,"Objects\\default.cgf"))
|
||||
GetSystem()->Error("Error loading default object");
|
||||
|
||||
// still error - make nice default object
|
||||
m_eCCGFStreamingStatus = ecss_NotLoaded;
|
||||
Load("Objects\\default.cgf","",evs_NoSharing,false,false,false,false);
|
||||
assert( m_eCCGFStreamingStatus == ecss_Ready);
|
||||
m_bDefaultObject=true;*/
|
||||
|
||||
assert(0);
|
||||
GetSystem()->Error("Error loading CCGF for: %s", m_szFileName);
|
||||
}
|
||||
|
||||
void CStatObj::StreamOnComplete(IReadStream* pStream, unsigned nError)
|
||||
{
|
||||
m_pReadStream = 0;
|
||||
|
||||
if(pStream->IsError())
|
||||
{ // file was not loaded successfully
|
||||
ProcessStreamOnCompleteError();
|
||||
return;
|
||||
}
|
||||
|
||||
// load header
|
||||
CCGFHeader * pFileHeader = (CCGFHeader *)pStream->GetBuffer();
|
||||
#if !defined(LINUX)
|
||||
assert(pFileHeader->nDataSize == pStream->GetBytesRead()-sizeof(CCGFHeader));
|
||||
#endif
|
||||
|
||||
if(!pFileHeader->nDataSize)
|
||||
{ // should happend only in case of sync loading
|
||||
assert(m_szGeomName[0]);
|
||||
m_eCCGFStreamingStatus = ecss_GeomNotFound;
|
||||
return; // geom name was specified but not found in source sgf during compilation
|
||||
}
|
||||
|
||||
int nChecksum = CCGFHeader::GetStructuresCheckSummm();
|
||||
if(pFileHeader->nStructuresCheckSummm != nChecksum)
|
||||
{
|
||||
m_eCCGFStreamingStatus = ecss_LoadingError;
|
||||
GetConsole()->Exit("Error: CStatObj::StreamOnComplete: version of " RC_EXECUTABLE " is not compatible with engine: %s", m_szFileName);
|
||||
return; // geom name was specified but not found in source sgf during compilation
|
||||
}
|
||||
|
||||
// load data
|
||||
uchar * pData = ((uchar *)pStream->GetBuffer()+sizeof(CCGFHeader));
|
||||
int nPos=0;
|
||||
Serialize(nPos, pData, false, m_szFolderName);
|
||||
assert(nPos == pFileHeader->nDataSize);
|
||||
|
||||
// original tris count
|
||||
m_nLoadedTrisCount = pFileHeader->nFacesInCGFNum;
|
||||
assert(m_nLoadedTrisCount);
|
||||
|
||||
m_bPhysicsExistInCompiledFile = (pFileHeader->dwFlags & CCGFHF_PHYSICS_EXIST);
|
||||
|
||||
// get bbox
|
||||
m_vBoxMin = pFileHeader->vBoxMin;
|
||||
m_vBoxMax = pFileHeader->vBoxMax;
|
||||
CalcRadiuses();
|
||||
|
||||
PhysicalizeCompiled();
|
||||
|
||||
m_eCCGFStreamingStatus = ecss_Ready;
|
||||
|
||||
if(GetCVars()->e_stream_cgf)
|
||||
GetLog()->Log("CStatObj::StreamOnComplete: %s", m_szFileName);
|
||||
}
|
||||
|
||||
void CStatObj::StreamCCGF(bool bFinishNow)
|
||||
{
|
||||
// if(strstr(m_szFileName,"de_bind.cgf"))
|
||||
// int t=0;
|
||||
|
||||
if(m_eCCGFStreamingStatus != ecss_NotLoaded)
|
||||
return;
|
||||
|
||||
char szCompiledFileName[MAX_PATH_LENGTH];
|
||||
MakeCompiledFileName(szCompiledFileName,MAX_PATH_LENGTH);
|
||||
|
||||
if(bFinishNow)
|
||||
GetLog()->UpdateLoadingScreen("\003Load compiled object: %s", szCompiledFileName);
|
||||
else
|
||||
GetLog()->UpdateLoadingScreen("\003Start streaming compiled object: %s", szCompiledFileName);
|
||||
|
||||
// start streaming
|
||||
StreamReadParams params;
|
||||
params.dwUserData = 0;
|
||||
params.nSize = 0;
|
||||
params.pBuffer = NULL;
|
||||
params.nLoadTime = 10000;
|
||||
params.nMaxLoadTime = 10000;
|
||||
params.nFlags |= SRP_FLAGS_ASYNC_PROGRESS;
|
||||
|
||||
m_eCCGFStreamingStatus = ecss_LoadingInProgress;
|
||||
m_pReadStream = m_pSys->GetStreamEngine()->StartRead("3DEngine", szCompiledFileName, this, ¶ms);
|
||||
|
||||
if(bFinishNow)
|
||||
m_pReadStream->Wait();
|
||||
}
|
||||
|
||||
void CStatObj::CheckLoaded()
|
||||
{
|
||||
if(!m_bUseStreaming)
|
||||
return;
|
||||
|
||||
m_nMarkedForStreamingFrameId = GetFrameID()+100;
|
||||
|
||||
if(m_eCCGFStreamingStatus == ecss_NotLoaded)
|
||||
{ // load now
|
||||
assert(m_bUseStreaming == true);
|
||||
m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime();
|
||||
bool bRes = Load(m_szFileName, m_szGeomName[0] ? m_szGeomName : 0, m_eVertsSharing,
|
||||
m_bLoadAdditinalInfo, m_bKeepInLocalSpace, false, m_bMakePhysics);
|
||||
m_bUseStreaming = true;
|
||||
m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime();
|
||||
}
|
||||
else if(m_eCCGFStreamingStatus == ecss_LoadingInProgress)
|
||||
{ // finish now
|
||||
m_pReadStream->Wait();
|
||||
}
|
||||
else
|
||||
{ // object is ready
|
||||
assert(m_eCCGFStreamingStatus == ecss_Ready);
|
||||
assert(m_pLeafBuffer && m_nLoadedTrisCount);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
void CStatObj::MakeCompiledFileName(char * szCompiledFileName, int nMaxLen)
|
||||
{
|
||||
// make ccgf name
|
||||
char szFileNameNoExt[512]="";
|
||||
strcpy(szFileNameNoExt,m_szFileName);
|
||||
|
||||
// remove extension
|
||||
for(int i=strlen(szFileNameNoExt)-1; i>0; i--) if(szFileNameNoExt[i]=='.')
|
||||
{ szFileNameNoExt[i]=0; break; }
|
||||
|
||||
// replace slashes in geom name
|
||||
char szGeomName[sizeof(m_szGeomName)]="";
|
||||
strncpy(szGeomName,m_szGeomName,sizeof(szGeomName));
|
||||
int nLen = strlen(szGeomName);
|
||||
for(int i=0; i<nLen; i++)
|
||||
if (szGeomName[i]=='/' || szGeomName[i]=='\\')
|
||||
szGeomName[i] = '_';
|
||||
|
||||
_snprintf(szCompiledFileName, nMaxLen,
|
||||
"%s\\%s_%s_%d_%d_%d.ccgf",
|
||||
CCGF_CACHE_DIR_NAME, szFileNameNoExt, szGeomName,
|
||||
int(m_eVertsSharing == evs_ShareAndSortForCache), (int)m_bLoadAdditinalInfo, (int)m_bKeepInLocalSpace);
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
19
Cry3DEngine/StdAfx.cpp
Normal file
19
Cry3DEngine/StdAfx.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: stdafx.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Description: source file that includes just the standard includes
|
||||
// Cry3DEngine.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
214
Cry3DEngine/StdAfx.h
Normal file
214
Cry3DEngine/StdAfx.h
Normal file
@@ -0,0 +1,214 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: stdafx.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_STDAFX_H__8B93AD4E_EE86_4127_9BED_37AC6D0F978B__INCLUDED_3DENGINE)
|
||||
#define AFX_STDAFX_H__8B93AD4E_EE86_4127_9BED_37AC6D0F978B__INCLUDED_3DENGINE
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// THIS MUST BE AT THE VERY BEGINING OF STDAFX.H FILE.
|
||||
// Disable STL threading support, (makes STL faster)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define _NOTHREADS
|
||||
#define _STLP_NO_THREADS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#ifdef GAMECUBE
|
||||
#include "GCDefines.h"
|
||||
#endif
|
||||
|
||||
// Insert your headers here
|
||||
#ifndef GAMECUBE
|
||||
#ifndef _XBOX
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// enable memory pool usage
|
||||
#ifndef GAMECUBE
|
||||
#define USE_NEWPOOL
|
||||
#include <CryMemoryManager.h>
|
||||
#endif
|
||||
|
||||
#ifndef uchar
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#if defined(PS2) || defined(GAMECUBE)
|
||||
using std::min;
|
||||
using std::max;
|
||||
#endif
|
||||
|
||||
#ifndef __forceinline
|
||||
#define __forceinline inline
|
||||
#endif
|
||||
|
||||
#if !defined(min) && !defined(LINUX)
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define ZeroStruct( t ) { memset( &t,0,sizeof(t) ); }
|
||||
|
||||
#define MAX_PATH_LENGTH 512
|
||||
|
||||
#ifndef stricmp
|
||||
inline int __cdecl stricmp(const char *dst, const char *src)
|
||||
{
|
||||
int f,l;
|
||||
do
|
||||
{
|
||||
if ( ((f=(unsigned char)(*(dst++))) >= 'A') && (f<='Z'))
|
||||
f -= ('A' - 'a');
|
||||
|
||||
if ( ((l=(unsigned char)(*(src++))) >= 'A') && (l<='Z'))
|
||||
l -= ('A' - 'a');
|
||||
} while ( f && (f == l) );
|
||||
|
||||
return(f - l);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef strnicmp
|
||||
inline int __cdecl strnicmp (const char * first, const char * last, size_t count)
|
||||
{
|
||||
int f,l;
|
||||
if ( count )
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( ((f=(unsigned char)(*(first++))) >= 'A') && (f<='Z') )
|
||||
f -= 'A' - 'a';
|
||||
|
||||
if ( ((l=(unsigned char)(*(last++))) >= 'A') && (l<='Z'))
|
||||
l -= 'A' - 'a';
|
||||
} while ( --count && f && (f == l) );
|
||||
|
||||
return( f - l );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include <ITimer.h>
|
||||
#include <IProcess.h>
|
||||
#include "Cry_Math.h"
|
||||
#include "Cry_XOptimise.h"
|
||||
#include <Cry_Camera.h>
|
||||
#include <ILog.h>
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
#include <IPhysics.h>
|
||||
#include <IRenderer.h>
|
||||
#include <IEntityRenderState.h>
|
||||
#include <I3DEngine.h>
|
||||
#include <IGame.h>
|
||||
#include <icryanimation.h>
|
||||
#include <icrypak.h>
|
||||
#include <CryFile.h>
|
||||
|
||||
class IPhysicalWorld;
|
||||
struct IEntityRender;
|
||||
|
||||
#if defined(WIN32) && defined(_DEBUG)
|
||||
|
||||
#include <crtdbg.h>
|
||||
#define DEBUG_NEW_NORMAL_CLIENTBLOCK(file, line) new(_NORMAL_BLOCK, file, line)
|
||||
#define new DEBUG_NEW_NORMAL_CLIENTBLOCK( __FILE__, __LINE__)
|
||||
|
||||
// memman
|
||||
#define calloc(s,t) _calloc_dbg(s, t, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
|
||||
#endif // defined(WIN32) && defined(_DEBUG)
|
||||
|
||||
|
||||
//#include <StlDbgAlloc.h>
|
||||
|
||||
#include "TArrays.h"
|
||||
|
||||
#include "Cry_Math.h"
|
||||
#include "CryHeaders.h"
|
||||
|
||||
#include "Cry3DEngineBase.h"
|
||||
#include "file.h"
|
||||
#include <float.h>
|
||||
|
||||
#include "TArrays.h"
|
||||
#include "list2.h"
|
||||
#include "terrain.h"
|
||||
#include "cvars.h"
|
||||
#include "crysizer.h"
|
||||
#include "StlUtils.h"
|
||||
|
||||
inline float L1Distance2D(const Vec3 &v0, const Vec3 &v1) { return max(Ffabs(v0.x-v1.x),Ffabs(v0.y-v1.y)); }
|
||||
|
||||
inline float GetDist2D(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float xm = (x1-x2);
|
||||
float ym = (y1-y2);
|
||||
return cry_sqrtf(xm*xm + ym*ym);
|
||||
}
|
||||
|
||||
#if !defined(LINUX) //than it does already exist
|
||||
inline int vsnprintf(char * buf, int size, const char * format, va_list & args)
|
||||
{
|
||||
int res = _vsnprintf(buf, size, format, args);
|
||||
assert(res>=0 && res<size); // just to know if there was problems in past
|
||||
buf[size-1]=0;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline int snprintf(char * buf, int size, const char * format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start(arglist, format);
|
||||
int res = vsnprintf(buf, size, format, arglist);
|
||||
va_end(arglist);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__8B93AD4E_EE86_4127_9BED_37AC6D0F978B__INCLUDED_3DENGINE)
|
||||
805
Cry3DEngine/StencilShadowConnectivity.h
Normal file
805
Cry3DEngine/StencilShadowConnectivity.h
Normal file
@@ -0,0 +1,805 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CryEngine Source code
|
||||
//
|
||||
// File:StencilShadowConnectivity.h
|
||||
// Declaration of class CStencilShadowConnectivity
|
||||
//
|
||||
// History:
|
||||
// -:Created by Sergiy Migdalskiy <sergiy@crytek.de>
|
||||
// 08/30/2002 include .cpp in header files, move to CryCommon, use in Cry3DEngine (Martin Mittring)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// class CStencilShadowConnectivity
|
||||
//
|
||||
// This is pre-computed data for a model that's gonna cast stencil
|
||||
// shadows, and whose vertices may change position ****, but the topology
|
||||
// cannot change.
|
||||
//
|
||||
// Ok, to put it clear: for each model, you need one instance of this
|
||||
// class initialized once. The model is allowed to deform, but is not
|
||||
// allowed to change topology (add or remove faces as well as re-assign
|
||||
// face vertices or even change face orientation).
|
||||
//
|
||||
// NOTE: The class is optimized for use with manifold geometry.
|
||||
// This means you have to provide a model with unified normals and non-
|
||||
// exploded triangles.
|
||||
//
|
||||
//
|
||||
// IMPLEMENTATION NOTES should be in
|
||||
// StencilShadowConnectivity.cpp
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef _STENCIL_SHADOW_CONNECTIVITY_HDR_
|
||||
#define _STENCIL_SHADOW_CONNECTIVITY_HDR_
|
||||
|
||||
#include <IEdgeConnectivityBuilder.h> // IStencilShadowConnectivity
|
||||
|
||||
// the empty connectivity info:
|
||||
class CStencilShadowConnectivityNull:public IStencilShadowConnectivity
|
||||
{
|
||||
public:
|
||||
|
||||
//! don't forget to call Release for freeing the memory resources
|
||||
virtual void Release( void ) {delete this;}
|
||||
|
||||
//! to keep the interface small and the access fast
|
||||
//! /return pointer to the internal memory representation (only used within module 3DEngine)
|
||||
const virtual CStencilShadowConnectivity *GetInternalRepresentation( void ) const {return NULL;}
|
||||
|
||||
//! for debugging and profiling
|
||||
//! /param outVertexCount
|
||||
//! /param outTriangleCount
|
||||
virtual void GetStats( DWORD &outVertexCount, DWORD &outTriangleCount ) {outVertexCount = outTriangleCount = 0;}
|
||||
|
||||
//! Memorize the vertex buffer in this connectivity object. This is needed if a static object doesn't need this info
|
||||
virtual void SetVertices(const Vec3d* pVertices, unsigned numVertices) {assert(0);}
|
||||
|
||||
//! Serializes this object to the given memory block; if it's NULL, only returns
|
||||
//! the number of bytes required. If it's not NULL, returns the number of bytes written
|
||||
//! (0 means error, insufficient space)
|
||||
virtual unsigned Serialize (bool bSave, void* pStream, unsigned nSize, IMiniLog* pWarningLog = NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Calculates the size of this object
|
||||
virtual void GetMemoryUsage (ICrySizer* pSizer) {}
|
||||
|
||||
#ifdef WIN32
|
||||
//! /param szFilename filename with path (or relative) and extension
|
||||
//! /return true=success, false otherwise
|
||||
virtual bool DebugConnectivityInfo( const char *szFilename ){}
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
class CStencilShadowConnectivity : public IStencilShadowConnectivity
|
||||
{
|
||||
public:
|
||||
|
||||
//! number of vertices in the array referenced by the mesh
|
||||
//! /return vertex count
|
||||
unsigned numVertices() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
|
||||
//! number of edges in the array of edges
|
||||
//! /return edge count
|
||||
unsigned numEdges() const
|
||||
{
|
||||
return m_numEdges;
|
||||
}
|
||||
|
||||
//! number of orphaned (open) edges
|
||||
//! /return orphaned (open) count
|
||||
virtual unsigned numOrphanEdges() const
|
||||
{
|
||||
return m_numOrphanEdges;
|
||||
}
|
||||
|
||||
//! total number of faces
|
||||
//! /return face count
|
||||
unsigned numFaces ()const
|
||||
{
|
||||
return m_numFaces;
|
||||
}
|
||||
|
||||
// -----------------
|
||||
|
||||
// This is the basic edge representation: two vertex indices.
|
||||
// This is capable of being sorted.
|
||||
struct BasicEdge
|
||||
{
|
||||
//! default constructor
|
||||
BasicEdge () {}
|
||||
|
||||
//! constructor
|
||||
//! /param nV0 start vertex index
|
||||
//! /param nV1 end vertex index
|
||||
BasicEdge (vindex nV0, vindex nV1)
|
||||
{
|
||||
m_nVertex[0] = nV0;
|
||||
m_nVertex[1] = nV1;
|
||||
}
|
||||
|
||||
//! start and end vertex index of the edge
|
||||
vindex m_nVertex[2];
|
||||
|
||||
// alphabet sorting implementation
|
||||
//! /param rEdge right side of the operator term
|
||||
inline bool operator < (const BasicEdge& rEdge)const
|
||||
{
|
||||
if (m_nVertex[0] < rEdge.m_nVertex[0])
|
||||
return true;
|
||||
else
|
||||
if (m_nVertex[0] == rEdge.m_nVertex[0])
|
||||
return m_nVertex[1] < rEdge.m_nVertex[1];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//! get teh start or end vertex index
|
||||
//! /param nIndex 0/1
|
||||
inline unsigned operator [] (int nIndex)const
|
||||
{
|
||||
assert(nIndex==0 || nIndex==1);
|
||||
return m_nVertex[nIndex];
|
||||
}
|
||||
|
||||
//! copy the basic edge, designed for ancestors
|
||||
//! /param beEdge
|
||||
void setBasicEdge (const BasicEdge& beEdge)
|
||||
{
|
||||
m_nVertex[0] = beEdge.m_nVertex[0];
|
||||
m_nVertex[1] = beEdge.m_nVertex[1];
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
// connection of the edge to the face: may contain, depending on the implementation,
|
||||
// the face index, pointer to it, vertex, pointer to it
|
||||
struct EdgeFace
|
||||
{
|
||||
//! default constructor
|
||||
EdgeFace (){}
|
||||
|
||||
//! constructor
|
||||
//! /param nFace face index
|
||||
//! /param nVertex vertex index
|
||||
EdgeFace (vindex nFace, vindex nVertex): m_nFace(nFace), m_nVertex(nVertex) {}
|
||||
|
||||
//! /return face index
|
||||
inline vindex getFaceIndex ()const {return m_nFace;}
|
||||
|
||||
//! /return vertex index
|
||||
inline vindex getVertexIndex() const {return m_nVertex;}
|
||||
|
||||
vindex m_nFace; //!< face index
|
||||
vindex m_nVertex; //!< face vertex
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
// This is a primary connectivity edge data structure:
|
||||
// the basic edge (start and end vertices, inherited from BasicEdge)
|
||||
// and the opposite face edges
|
||||
class Edge: public BasicEdge
|
||||
{
|
||||
//! this and opposite face 3rd vertex.
|
||||
//! in "this" face, the edge goes CCW (natural) direction [0],
|
||||
//! and in "opposite" face it goes CW (reverse) direction [1]
|
||||
EdgeFace m_Face[2];
|
||||
|
||||
public:
|
||||
|
||||
//! default constructor
|
||||
Edge () {}
|
||||
|
||||
//! constructor
|
||||
//! /param be edge datastructure
|
||||
//! /param ef0 in this triangle the edge goes CCW (natural) direction
|
||||
//! /param ef1 in this triangle the edge goes CW (reverse) direction
|
||||
Edge (const BasicEdge& be, const EdgeFace& ef0, const EdgeFace& ef1):
|
||||
BasicEdge(be)
|
||||
{
|
||||
m_Face[0] = ef0;
|
||||
m_Face[1] = ef1;
|
||||
}
|
||||
|
||||
//! /param nFace 0/1
|
||||
//! /return reference to the face data structure
|
||||
const EdgeFace& getFace(int nFace) const
|
||||
{
|
||||
assert(nFace==0 || nFace==1);
|
||||
|
||||
return m_Face[nFace];
|
||||
}
|
||||
|
||||
//! /param nFace 0/1
|
||||
//! /param ef reference to the edge datastructure
|
||||
void setFace (int nFace, const EdgeFace& ef)
|
||||
{
|
||||
assert(nFace==0 || nFace==1);
|
||||
|
||||
m_Face[nFace] = ef;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
// orphan edge - an edge with only one face attached to it (boundary)
|
||||
class OrphanEdge: public BasicEdge
|
||||
{
|
||||
EdgeFace m_Face; //!<
|
||||
|
||||
public:
|
||||
//! default constructor
|
||||
OrphanEdge () {}
|
||||
|
||||
// constructor
|
||||
OrphanEdge (const BasicEdge& be, const EdgeFace& ef):
|
||||
BasicEdge (be),
|
||||
m_Face (ef)
|
||||
{}
|
||||
|
||||
const EdgeFace& getFace()const {return m_Face;}
|
||||
void setFace (const EdgeFace& ef) {m_Face = ef;}
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
// face - 3 vertices
|
||||
class Face
|
||||
{
|
||||
public:
|
||||
vindex m_nVertex[3]; //!<
|
||||
|
||||
//! default constructur
|
||||
Face () {}
|
||||
|
||||
//! constructor
|
||||
//! /param nV0 first vertex index
|
||||
//! /param nV1 second vertex index
|
||||
//! /param nV2 thired vertex index
|
||||
Face (vindex nV0, vindex nV1, vindex nV2)
|
||||
{
|
||||
m_nVertex[0] = nV0;
|
||||
m_nVertex[1] = nV1;
|
||||
m_nVertex[2] = nV2;
|
||||
}
|
||||
|
||||
//! get the index of one triangle vertex
|
||||
//! /param nVtx 0/1/2
|
||||
//! /return index of that triangle vertex
|
||||
const vindex getVertex (int nVtx) const
|
||||
{
|
||||
assert(nVtx==0 || nVtx==1 || nVtx==2);
|
||||
|
||||
return m_nVertex[nVtx];
|
||||
}
|
||||
|
||||
//! set the index of one triangle vertex
|
||||
//! /param nVtx 0/1/2
|
||||
//! /param nIndex index of the triangle vertex no <nVtx>
|
||||
void setVertex (int nVtx, vindex nIndex)
|
||||
{
|
||||
assert(nVtx==0 || nVtx==1 || nVtx==2);
|
||||
|
||||
m_nVertex[nVtx] = nIndex;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------
|
||||
|
||||
//! /aparam nEdge 0..m_numEdges-1
|
||||
//! /return the nEdge'th edge
|
||||
const Edge& getEdge (int nEdge)const
|
||||
{
|
||||
assert(m_pEdges);
|
||||
assert(nEdge>=0);
|
||||
assert((unsigned)nEdge<m_numEdges);
|
||||
|
||||
return m_pEdges[nEdge];
|
||||
}
|
||||
|
||||
// returns the nEdge's orphaned edge
|
||||
//! /param nEdge 0..m_numOrphanEdges-1
|
||||
//! /return
|
||||
const OrphanEdge& getOrphanEdge(int nEdge)const
|
||||
{
|
||||
assert(m_pOrphanEdges);
|
||||
assert(nEdge>=0);
|
||||
assert((unsigned)nEdge<m_numOrphanEdges);
|
||||
|
||||
return m_pOrphanEdges[nEdge];
|
||||
}
|
||||
|
||||
//! returns the nFace's face
|
||||
//! /param 0..m_numFaces-1
|
||||
//! /return reference to the face
|
||||
const Face& getFace (int nFace) const
|
||||
{
|
||||
assert(m_pFaces);
|
||||
assert(nFace>=0);
|
||||
assert((unsigned)nFace<m_numFaces);
|
||||
|
||||
return m_pFaces[nFace];
|
||||
}
|
||||
|
||||
// copies the array of referred faces into internal array
|
||||
// this is specially optimized for faster cooperation with the Builder
|
||||
// The number of faces is determined from the earlier given edges, so
|
||||
// NOTE: becareful to call the SetOrphanEdges BEFORE THIS FUNCTION
|
||||
// DO NOT call twice, this is only designed to be called once after construction
|
||||
void SetFaces (const std::vector<Face>& arrFaces)
|
||||
{
|
||||
assert (!m_pFaces && m_numFaces <= arrFaces.size());
|
||||
if (!arrFaces.empty())
|
||||
{
|
||||
m_pFaces = new Face[m_numFaces = arrFaces.size()];
|
||||
for (unsigned i = 0; i < m_numFaces; ++i)
|
||||
m_pFaces[i] = arrFaces[i];
|
||||
}
|
||||
}
|
||||
|
||||
// destruct the object (it's only constructed by the Builder)
|
||||
// the virtual ensures that the function releases the object in the same module where it was allocated:
|
||||
// because the VTable was also allocated in the same module
|
||||
virtual void Release ()
|
||||
{
|
||||
assert(this);
|
||||
// this is a counterpart to the new that's called within the
|
||||
// CStencilShadowConnectivityBuilder::ConstructConnectivity() method
|
||||
delete this;
|
||||
}
|
||||
|
||||
const virtual CStencilShadowConnectivity *GetInternalRepresentation( void ) const
|
||||
{
|
||||
return(this);
|
||||
}
|
||||
|
||||
|
||||
// from IStencilShadowConnectivity
|
||||
virtual bool DebugConnectivityInfo( const char *szFilename )
|
||||
{
|
||||
// used only for debugging
|
||||
FILE *out=fopen(szFilename,"w");
|
||||
if(!out)return(false);
|
||||
|
||||
fprintf(out,"%d Edges:\n",m_numEdges);
|
||||
for(unsigned i=0;i<m_numEdges;i++)
|
||||
{
|
||||
fprintf(out," face={%d,%d}, vertex={%d,%d}\n",
|
||||
(m_pEdges[i].getFace(0)).getFaceIndex(),
|
||||
(m_pEdges[i].getFace(1)).getFaceIndex(),
|
||||
m_pEdges[i].m_nVertex[0],
|
||||
m_pEdges[i].m_nVertex[1]);
|
||||
}
|
||||
|
||||
fprintf(out,"%d OrphanEdges:\n",m_numOrphanEdges);
|
||||
for(unsigned i=0;i<m_numOrphanEdges;i++)
|
||||
#if !defined(LINUX)
|
||||
fprintf(out," face={%d}, vertex={%d,%d}\n",m_pOrphanEdges[i].getFace(),m_pOrphanEdges[i].m_nVertex[0],m_pOrphanEdges[i].m_nVertex[1]);
|
||||
#else
|
||||
fprintf(out,", vertex={%d,%d}\n",m_pOrphanEdges[i].m_nVertex[0],m_pOrphanEdges[i].m_nVertex[1]);//face info does not compile, no time to make it more correct here
|
||||
#endif//LINUX
|
||||
|
||||
fprintf(out,"%d Vertices:\n",m_numVertices);
|
||||
|
||||
fprintf(out,"Faces:\n",m_numFaces);
|
||||
for(unsigned i=0;i<m_numFaces;i++)
|
||||
fprintf(out," vertex indices={%d,%d,%d}\n",m_pFaces[i].getVertex(0),m_pFaces[i].getVertex(1),m_pFaces[i].getVertex(2));
|
||||
|
||||
fclose(out);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
//! constructor, only makes an empty object that's good for deserializing only
|
||||
CStencilShadowConnectivity ()
|
||||
{
|
||||
m_numEdges = m_numOrphanEdges = m_numVertices = m_numFaces = 0;
|
||||
m_pOrphanEdges = NULL;
|
||||
m_pFaces = NULL;
|
||||
m_pEdges = NULL;
|
||||
m_pPlanes = NULL;
|
||||
m_pVertices = NULL;
|
||||
}
|
||||
|
||||
struct Plane
|
||||
{
|
||||
Vec3d vNormal;
|
||||
float fDistance;
|
||||
|
||||
Plane(){}
|
||||
Plane (const Vec3d& v0, const Vec3d& v1, const Vec3d& v2)
|
||||
{
|
||||
vNormal = (v1-v0)^(v2-v0);
|
||||
fDistance = (v0*vNormal);
|
||||
}
|
||||
float apply (const Vec3d& v)const
|
||||
{
|
||||
return vNormal * v - fDistance;
|
||||
}
|
||||
};
|
||||
|
||||
//! Calculates the size of this object
|
||||
void GetMemoryUsage(ICrySizer* pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,Serialize (true, NULL,0));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor is only called within 3DEngine
|
||||
//! /param pEdges - array of nNumEdges edges
|
||||
//! /param nNumEdges
|
||||
CStencilShadowConnectivity( const std::vector<Edge>& arrEdges)
|
||||
{
|
||||
m_pOrphanEdges=NULL;
|
||||
m_pFaces=NULL;
|
||||
m_numOrphanEdges=0;
|
||||
|
||||
// find the max vertex index to put it into m_nVertices
|
||||
m_numVertices = 0;
|
||||
m_numFaces = 0;
|
||||
for (std::vector<Edge>::const_iterator it = arrEdges.begin(); it != arrEdges.end(); ++it)
|
||||
{
|
||||
UseBasicEdge (*it);
|
||||
UseEdgeFace (it->getFace(0));
|
||||
UseEdgeFace (it->getFace(1));
|
||||
}
|
||||
|
||||
m_numEdges = arrEdges.size();
|
||||
if(m_numEdges)
|
||||
{
|
||||
m_pEdges = new Edge[m_numEdges];
|
||||
for (unsigned i = 0; i < m_numEdges; ++i)
|
||||
m_pEdges[i] = arrEdges[i];
|
||||
}
|
||||
else
|
||||
m_pEdges=0;
|
||||
|
||||
m_pPlanes = NULL;
|
||||
m_pVertices = NULL;
|
||||
}
|
||||
|
||||
void SetPlanes (const Plane* pPlanes, unsigned numPlanes)
|
||||
{
|
||||
if (m_pPlanes)
|
||||
delete [] m_pPlanes;
|
||||
if (pPlanes)
|
||||
{
|
||||
assert (numPlanes >= m_numFaces);
|
||||
m_pPlanes = new Plane[m_numFaces];
|
||||
memcpy (m_pPlanes, pPlanes, sizeof(Plane) * m_numFaces);
|
||||
}
|
||||
else
|
||||
m_pPlanes = NULL;
|
||||
}
|
||||
|
||||
void SetVertices(const Vec3d* pVertices, unsigned numVertices)
|
||||
{
|
||||
if (m_pVertices)
|
||||
delete[]m_pVertices;
|
||||
if (pVertices)
|
||||
{
|
||||
assert (numVertices >= m_numVertices);
|
||||
m_pVertices = new Vec3d[m_numVertices];
|
||||
memcpy (m_pVertices, pVertices, sizeof(Vec3d)*m_numVertices);
|
||||
}
|
||||
else
|
||||
m_pVertices = NULL;
|
||||
}
|
||||
|
||||
// remaps all vertex indices and memorizes the passed "new" vertex array (in new indexation)
|
||||
void SetRemapVertices (const vindex*pMap, unsigned numMapEntries, const Vec3d* pNewVertices, unsigned numNewVertices)
|
||||
{
|
||||
if (m_pVertices)
|
||||
delete[]m_pVertices;
|
||||
assert (pNewVertices);
|
||||
// we collected information about the vertices before . The number of used vertices is in
|
||||
// m_numVertices. We assume the passed new vertex map can not make this number larger, because
|
||||
// its sole purpose is optimization of number of vertex indices used (for storing the vertex info inside)
|
||||
assert (numNewVertices <= m_numVertices);
|
||||
m_numVertices = numNewVertices;
|
||||
m_pVertices = new Vec3d[numNewVertices];
|
||||
memcpy (m_pVertices, pNewVertices, sizeof(Vec3d)*numNewVertices);
|
||||
|
||||
remapVertexIndices (pMap, numMapEntries);
|
||||
}
|
||||
|
||||
|
||||
// can be destructed only from within Release()
|
||||
virtual ~CStencilShadowConnectivity(void)
|
||||
{
|
||||
if (m_pEdges) delete[] m_pEdges;
|
||||
if (m_pOrphanEdges) delete[] m_pOrphanEdges;
|
||||
if (m_pFaces) delete[] m_pFaces;
|
||||
if (m_pPlanes) delete[] m_pPlanes;
|
||||
if (m_pVertices) delete[] m_pVertices;
|
||||
}
|
||||
|
||||
|
||||
// makes sure that the given vertex index fits into the range 0..m_nVertices
|
||||
// by expanding (increasing) m_nVertices
|
||||
void UseVertex(vindex nVertex)
|
||||
{
|
||||
if (nVertex >= m_numVertices)
|
||||
m_numVertices = nVertex + 1;
|
||||
}
|
||||
|
||||
// makes sure that the given face index fits into the range 0..m_nFaces
|
||||
// by expanding (increasing) m_nFaces
|
||||
void UseFace (vindex nFace)
|
||||
{
|
||||
if (nFace >= m_numFaces)
|
||||
m_numFaces = nFace + 1;
|
||||
}
|
||||
|
||||
// copies the list of orphaned edges into internal array
|
||||
// this is specially optimized for faster cooperation with the Builder
|
||||
// DO NOT call twice, this is only designed to be called once after construction
|
||||
typedef std::map<BasicEdge, EdgeFace> OrphanEdgeMap;
|
||||
|
||||
|
||||
// copies the list of orphaned edges into internal array
|
||||
// this is specially optimized for faster cooperation with the Builder
|
||||
// DO NOT call twice, this is only designed to be called once after construction
|
||||
void SetOrphanEdges (const OrphanEdgeMap& mapOrphanEdge)
|
||||
{
|
||||
m_numOrphanEdges = mapOrphanEdge.size();
|
||||
|
||||
m_pOrphanEdges = new OrphanEdge[m_numOrphanEdges];
|
||||
|
||||
OrphanEdge* pEdge = m_pOrphanEdges;
|
||||
|
||||
// copy the content of the orphan edge map into the array
|
||||
for (OrphanEdgeMap::const_iterator it = mapOrphanEdge.begin(); it != mapOrphanEdge.end(); ++it)
|
||||
{
|
||||
pEdge->setBasicEdge (it->first);
|
||||
pEdge->setFace (it->second);
|
||||
|
||||
UseBasicEdge (*pEdge);
|
||||
UseEdgeFace (pEdge->getFace());
|
||||
|
||||
++pEdge;
|
||||
}
|
||||
}
|
||||
|
||||
// makes sure that the vertices/faces referenced by the edge are in account by the m_numFaces and m_numVertices
|
||||
void UseBasicEdge (const BasicEdge& beEdge)
|
||||
{
|
||||
UseVertex(beEdge[0]);
|
||||
UseVertex(beEdge[1]);
|
||||
}
|
||||
|
||||
// makes sure that the vertices/faces referenced by the edge are in account by the m_numFaces and m_numVertices
|
||||
void UseEdgeFace (const EdgeFace& efEdge)
|
||||
{
|
||||
UseFace (efEdge.getFaceIndex());
|
||||
UseVertex(efEdge.getVertexIndex());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! for debugging and profiling
|
||||
//! /param outVertexCount
|
||||
//! /param outTriangleCount
|
||||
virtual void GetStats( DWORD &outVertexCount, DWORD &outTriangleCount )
|
||||
{
|
||||
outVertexCount=m_numVertices;
|
||||
outTriangleCount=m_numFaces;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// the version of the stream
|
||||
enum {g_nSerialVersion = 2};
|
||||
|
||||
//! Deserializes this object. Returns the number of bytes read. 0 means error
|
||||
//! pWarningLog is used to put warnings about deserialized connectivity
|
||||
unsigned Deserialize (void *pStream, unsigned nSize, IMiniLog* pWarningLog = NULL)
|
||||
{
|
||||
unsigned* pHeader = (unsigned*)pStream;
|
||||
|
||||
if (nSize < 5 * sizeof(unsigned))
|
||||
return 0; // we should have the header in place
|
||||
|
||||
if (*(pHeader++) != g_nSerialVersion) // version is incompatible
|
||||
return 0;
|
||||
|
||||
m_numEdges = *(pHeader++);
|
||||
m_numOrphanEdges = *(pHeader++);
|
||||
m_numVertices = *(pHeader++);
|
||||
m_numFaces = *(pHeader++);
|
||||
unsigned numPlanes = *(pHeader++);
|
||||
assert (numPlanes == 0 || numPlanes == m_numFaces);
|
||||
unsigned numVertices = *(pHeader++);
|
||||
assert (numVertices == 0 || numVertices == m_numVertices);
|
||||
|
||||
unsigned nRequiredSize =
|
||||
sizeof(unsigned) +
|
||||
sizeof(m_numEdges) + m_numEdges * sizeof(Edge) +
|
||||
sizeof(m_numOrphanEdges) + m_numOrphanEdges * sizeof(OrphanEdge) +
|
||||
sizeof(m_numVertices) +
|
||||
sizeof(m_numFaces) + m_numFaces * sizeof(Face) +
|
||||
sizeof(numPlanes) + numPlanes * sizeof(Plane)+
|
||||
sizeof(numVertices) + numVertices * sizeof(Vec3d);
|
||||
|
||||
if(m_pEdges) delete[] m_pEdges;
|
||||
if(m_pOrphanEdges) delete[] m_pOrphanEdges;
|
||||
if(m_pFaces) delete[] m_pFaces;
|
||||
if(m_pPlanes) delete[] m_pPlanes;
|
||||
if (m_pVertices) delete []m_pVertices;
|
||||
|
||||
if (nSize < nRequiredSize)
|
||||
{
|
||||
m_pEdges = NULL;
|
||||
m_pOrphanEdges = NULL;
|
||||
m_pFaces = NULL;
|
||||
|
||||
m_numEdges = 0;
|
||||
m_numOrphanEdges = 0;
|
||||
m_numVertices = 0;
|
||||
m_numFaces = 0;
|
||||
|
||||
// incompatible stream
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_pEdges = new Edge [m_numEdges];
|
||||
m_pOrphanEdges = new OrphanEdge [m_numOrphanEdges];
|
||||
m_pFaces = new Face [m_numFaces];
|
||||
m_pPlanes = numPlanes?new Plane[numPlanes]:NULL;
|
||||
m_pVertices = numVertices?new Vec3d[numVertices]:NULL;
|
||||
|
||||
Edge* pEdgeData = (Edge*)pHeader;
|
||||
memcpy (m_pEdges, pEdgeData, m_numEdges*sizeof(Edge));
|
||||
OrphanEdge* pOrphanEdgeData = (OrphanEdge*)(pEdgeData + m_numEdges);
|
||||
memcpy (m_pOrphanEdges, pOrphanEdgeData, m_numOrphanEdges*sizeof(OrphanEdge));
|
||||
Face* pFaceData = (Face*)(pOrphanEdgeData + m_numOrphanEdges);
|
||||
memcpy (m_pFaces, pFaceData, m_numFaces * sizeof(Face));
|
||||
|
||||
Plane* pPlanes = (Plane*)(pFaceData+m_numFaces);
|
||||
if (numPlanes)
|
||||
memcpy (m_pPlanes, pPlanes, numPlanes* sizeof(Plane));
|
||||
|
||||
Vec3d* pVertices = (Vec3d*)(pPlanes + numPlanes);
|
||||
if (numVertices)
|
||||
memcpy (m_pVertices, pVertices, sizeof(Vec3d)*numVertices);
|
||||
|
||||
#if !defined(LINUX)
|
||||
if (m_numOrphanEdges && pWarningLog)
|
||||
pWarningLog->LogWarning("Connectivity warning: there are %d open edges (%d closed, %d faces, %d planes, %d vertices)", m_numOrphanEdges, m_numEdges, m_numFaces, numPlanes, numVertices);
|
||||
#endif
|
||||
return nRequiredSize;
|
||||
}
|
||||
|
||||
|
||||
//! Serializes this object to the given memory block; if it's NULL, only returns
|
||||
//! the number of bytes required. If it's not NULL, returns the number of bytes written
|
||||
//! (0 means error, insufficient space)
|
||||
unsigned Serialize (bool bSave, void* pStream, unsigned nSize, IMiniLog* pWarningLog = NULL)
|
||||
{
|
||||
if (!bSave)
|
||||
return Deserialize (pStream, nSize, pWarningLog);
|
||||
|
||||
// calculate the required size of the buffer
|
||||
unsigned
|
||||
numPlanes = m_pPlanes?m_numFaces:0,
|
||||
numVertices = m_pVertices?m_numVertices:0,
|
||||
nRequiredSize =
|
||||
sizeof(unsigned) +
|
||||
sizeof(m_numEdges) + m_numEdges * sizeof(Edge) +
|
||||
sizeof(m_numOrphanEdges) + m_numOrphanEdges * sizeof(OrphanEdge) +
|
||||
sizeof(m_numVertices) +
|
||||
sizeof(m_numFaces) + m_numFaces * sizeof(Face) +
|
||||
sizeof(numPlanes) + numPlanes * sizeof(Plane)+
|
||||
sizeof(numVertices) + numVertices * sizeof(Vec3d);
|
||||
|
||||
if (pStream)
|
||||
{
|
||||
if (nSize < nRequiredSize)
|
||||
return 0; // insufficient space in the pStream buffer
|
||||
|
||||
unsigned* pHeader = (unsigned*)pStream;
|
||||
*(pHeader++) = g_nSerialVersion; // version of the stream
|
||||
*(pHeader++) = m_numEdges;
|
||||
*(pHeader++) = m_numOrphanEdges;
|
||||
*(pHeader++) = m_numVertices;
|
||||
*(pHeader++) = m_numFaces;
|
||||
*(pHeader++) = numPlanes;
|
||||
*(pHeader++) = numVertices;
|
||||
|
||||
Edge* pEdgeData = (Edge*)pHeader;
|
||||
memcpy (pEdgeData, m_pEdges, m_numEdges*sizeof(Edge));
|
||||
OrphanEdge* pOrphanEdgeData = (OrphanEdge*)(pEdgeData + m_numEdges);
|
||||
memcpy (pOrphanEdgeData, m_pOrphanEdges, m_numOrphanEdges*sizeof(OrphanEdge));
|
||||
Face* pFaceData = (Face*)(pOrphanEdgeData + m_numOrphanEdges);
|
||||
memcpy (pFaceData, m_pFaces, m_numFaces * sizeof(Face));
|
||||
Plane* pPlanes = (Plane*)(pFaceData+m_numFaces);
|
||||
if (m_pPlanes)
|
||||
memcpy (pPlanes, m_pPlanes, numPlanes * sizeof(Plane));
|
||||
Vec3d* pVertices = (Vec3d*)(pPlanes+numPlanes);
|
||||
if (m_pVertices)
|
||||
memcpy (pVertices, m_pVertices, numVertices * sizeof(Vec3d));
|
||||
}
|
||||
|
||||
return nRequiredSize;
|
||||
}
|
||||
|
||||
// the plane equation, x*n+d == 0
|
||||
bool hasPlanes() const {return m_pPlanes != NULL;}
|
||||
const Plane&getPlane (unsigned i)const {assert(i<m_numFaces && m_pPlanes);return m_pPlanes[i];}
|
||||
|
||||
const Vec3d* getVertices() const {return m_pVertices;}
|
||||
|
||||
bool IsStandalone() const {return m_pPlanes != NULL && m_pVertices!= NULL;}
|
||||
|
||||
void remapVertexIndices(const vindex*pMap, unsigned nMapSize)
|
||||
{
|
||||
unsigned i;
|
||||
#define REMAP(X) assert((X) < nMapSize);\
|
||||
(X) = pMap[X];\
|
||||
assert ((vindex)(X) != (vindex)-1 && (X) < m_numVertices)
|
||||
|
||||
for(i=0;i<m_numEdges;i++)
|
||||
{
|
||||
REMAP(m_pEdges[i].m_nVertex[0]);
|
||||
REMAP(m_pEdges[i].m_nVertex[1]);
|
||||
}
|
||||
for(i=0;i<m_numOrphanEdges;i++)
|
||||
{
|
||||
REMAP(m_pOrphanEdges[i].m_nVertex[0]);
|
||||
REMAP(m_pOrphanEdges[i].m_nVertex[1]);
|
||||
}
|
||||
for(i=0;i<m_numFaces;i++)
|
||||
{
|
||||
REMAP(m_pFaces[i].m_nVertex[0]);
|
||||
REMAP(m_pFaces[i].m_nVertex[1]);
|
||||
REMAP(m_pFaces[i].m_nVertex[2]);
|
||||
}
|
||||
#undef REMAP
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
friend class CStencilShadowConnectivityBuilder;
|
||||
friend class CStencilShadowStaticConnectivityBuilder;
|
||||
|
||||
// the array of normal edges (with two adjacent faces)
|
||||
unsigned m_numEdges; //!<
|
||||
Edge* m_pEdges; //!<
|
||||
|
||||
// the array of orphaned edges (with only one face attached)
|
||||
unsigned m_numOrphanEdges; //!<
|
||||
OrphanEdge* m_pOrphanEdges; //!<
|
||||
|
||||
|
||||
private:
|
||||
// number of vertices in the array referenced by the mesh
|
||||
unsigned m_numVertices; //!<
|
||||
|
||||
// the faces
|
||||
unsigned m_numFaces; //!< number of faces in the array referenced by the mesh
|
||||
Face* m_pFaces; //!<
|
||||
Plane* m_pPlanes; //!< if not NULL, then use these normals instead of computing them on the fly; 1 face - 1 normal
|
||||
Vec3d* m_pVertices;
|
||||
};
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _STENCIL_SHADOW_CONNECTIVITY_HDR_
|
||||
279
Cry3DEngine/StencilShadowConnectivityBuilder.cpp
Normal file
279
Cry3DEngine/StencilShadowConnectivityBuilder.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#include "stdafx.h" // precompiled header
|
||||
#include "StencilShadowConnectivity.h"
|
||||
#include "StencilShadowConnectivityBuilder.h"
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
// creates an empty mesh connectivity
|
||||
CStencilShadowConnectivityBuilder::CStencilShadowConnectivityBuilder( void )
|
||||
#ifdef DEBUG_STD_CONTAINERS
|
||||
:m_mapSingleEdges("CStencilShadowConnectivityBuilder.SingleEdges")
|
||||
,m_vDoubleEdges ("CStencilShadowConnectivityBuilder.DoubleEdges")
|
||||
,m_vFaces("CStencilShadowConnectivityBuilder.Faces")
|
||||
,m_mVertexWelder("CStencilShadowConnectivityBuilder.VertexWelder")
|
||||
#endif
|
||||
{
|
||||
Reinit();
|
||||
}
|
||||
|
||||
CStencilShadowConnectivityBuilder::~CStencilShadowConnectivityBuilder( void )
|
||||
{
|
||||
}
|
||||
|
||||
void CStencilShadowConnectivityBuilder::Reinit( void )
|
||||
{
|
||||
m_mapSingleEdges.clear();
|
||||
m_vDoubleEdges.clear();
|
||||
m_vFaces.clear();
|
||||
m_mVertexWelder.clear();
|
||||
m_dwNumUncompressedVertices=0;
|
||||
// m_fWeldTolerance = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// adds a single triangle to the mesh
|
||||
// the tirangle is defined by three vertices, in counter-clockwise order
|
||||
// these vertex indices will be used later when accessing the array of
|
||||
// deformed character/model vertices to determine the shadow volume boundary
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowConnectivityBuilder::AddTriangle( unsigned short nV0, unsigned short nV1, unsigned short nV2 )
|
||||
{
|
||||
unsigned nNumFaces = m_vFaces.size();
|
||||
AddNewEdge (BasicEdge(nV0, nV1), EdgeFace(nNumFaces, nV2));
|
||||
AddNewEdge (BasicEdge(nV1, nV2), EdgeFace(nNumFaces, nV0));
|
||||
AddNewEdge (BasicEdge(nV2, nV0), EdgeFace(nNumFaces, nV1));
|
||||
m_vFaces.push_back(Face (nV0, nV1, nV2));
|
||||
}
|
||||
|
||||
|
||||
// this will try to find a close match to the given vertex, and
|
||||
// if found, return its index (the actual index of the vertex that's very close or
|
||||
// coincide with v in space). Otherwise, creates a new vertex reference in the map
|
||||
// and returns the index nNewVertex
|
||||
unsigned CStencilShadowConnectivityBuilder::WeldVertex (const Vec3d& v, unsigned nNewVertex)
|
||||
{
|
||||
// The easiest way: just find it directly
|
||||
VertexWelderMap::iterator it;
|
||||
it = m_mVertexWelder.find(v);
|
||||
if (it != m_mVertexWelder.end())
|
||||
return it->second;
|
||||
else
|
||||
{
|
||||
/*
|
||||
// scan and find some very close vertex
|
||||
if (m_fWeldTolerance > 0)
|
||||
for (it = m_mVertexWelder.begin(); it != m_mVertexWelder.end(); ++it)
|
||||
{
|
||||
if ((it->first-v).len2() < m_fWeldTolerance)
|
||||
return it->second;
|
||||
}
|
||||
*/
|
||||
m_mVertexWelder.insert (VertexWelderMap::value_type(v, nNewVertex));
|
||||
return nNewVertex;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Adds the triangle with the given vertex indices and vertex coordinates
|
||||
// to the list of triangles that will cast shadows. Welds the vertices based on their
|
||||
// coordinates
|
||||
void CStencilShadowConnectivityBuilder::AddTriangleWelded(
|
||||
unsigned short nV0, unsigned short nV1, unsigned short nV2,
|
||||
const Vec3d &vV0, const Vec3d &vV1, const Vec3d &vV2 )
|
||||
{
|
||||
nV0=WeldVertex(vV0,nV0);
|
||||
nV1=WeldVertex(vV1,nV1);
|
||||
nV2=WeldVertex(vV2,nV2);
|
||||
|
||||
AddTriangle(nV0,nV1,nV2);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// add a new edge, if there is no complementary single edge;
|
||||
// otherwise, withdraw the edge from the list of single edges and add to double edges
|
||||
// PARAMETERS:
|
||||
// edge - start and end vertices of the edge going CCW along the face
|
||||
// efFace - the opposite vertex/face the edge belongs to
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowConnectivityBuilder::AddNewEdge (BasicEdge eEdge, EdgeFace efFace)
|
||||
{
|
||||
// first, try to find the complementary
|
||||
BasicEdge eComplementary (eEdge[1], eEdge[0]);
|
||||
|
||||
SingleEdgeMap::iterator itComplementary = m_mapSingleEdges.find (eComplementary);
|
||||
|
||||
if (itComplementary == m_mapSingleEdges.end())
|
||||
{
|
||||
// complementeary edge not found. Add a new single edge
|
||||
|
||||
m_mapSingleEdges.insert (SingleEdgeMap::value_type(eEdge, efFace));
|
||||
|
||||
// nVEdgeG for nFaceVertex[1] is unknown and doesn't matter at the moment
|
||||
}
|
||||
else
|
||||
{
|
||||
// we found the complementary edge
|
||||
Edge edgeNewDouble (eComplementary, itComplementary->second, efFace);
|
||||
|
||||
m_vDoubleEdges.push_back (edgeNewDouble);
|
||||
|
||||
m_mapSingleEdges.erase (itComplementary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// constructs/compiles the optimum representation of the connectivity
|
||||
// to be used in run-time
|
||||
// WARNING: use Release method to dispose the connectivity object
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
IStencilShadowConnectivity *CStencilShadowConnectivityBuilder::ConstructConnectivity( void )
|
||||
{
|
||||
CStencilShadowConnectivity* pConnectivity = new CStencilShadowConnectivity(m_vDoubleEdges);
|
||||
|
||||
assert(pConnectivity); // low memeory?
|
||||
|
||||
pConnectivity->SetOrphanEdges(m_mapSingleEdges);
|
||||
pConnectivity->SetFaces(m_vFaces);
|
||||
|
||||
// find all the used vertices
|
||||
FaceArray::const_iterator pFace = m_vFaces.begin();
|
||||
DWORD nFaceCount = m_vFaces.size();
|
||||
|
||||
#if 0
|
||||
// test for serialization function
|
||||
unsigned nBufSize = pConnectivity->Serialize(true, NULL, 0);
|
||||
void* pBuf = malloc (nBufSize);
|
||||
unsigned nSaved = pConnectivity->Serialize(true, pBuf, nBufSize);
|
||||
assert (nSaved == nBufSize);
|
||||
pConnectivity->Release();
|
||||
pConnectivity = new CStencilShadowConnectivity ();
|
||||
unsigned nLoaded = pConnectivity->Serialize(false, pBuf, nBufSize);
|
||||
assert (nLoaded == nBufSize);
|
||||
free (pBuf);
|
||||
#endif
|
||||
|
||||
return((IStencilShadowConnectivity *)pConnectivity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// returns the number of single (with no pair faces found) or orphaned edges
|
||||
unsigned CStencilShadowConnectivityBuilder::numOrphanedEdges ()const
|
||||
{
|
||||
return(m_mapSingleEdges.size());
|
||||
}
|
||||
|
||||
//! Returns the list of faces for orphaned edges into the given buffer;
|
||||
//! For each orphaned edge, one face will be returned; some faces may be duplicated
|
||||
void CStencilShadowConnectivityBuilder::getOrphanedEdgeFaces (unsigned* pBuffer)
|
||||
{
|
||||
for (SingleEdgeMap::iterator it = m_mapSingleEdges.begin(); it != m_mapSingleEdges.end(); ++it)
|
||||
*(pBuffer++) = it->second.m_nFace;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// reserves space for the given number of triangles that are to be added
|
||||
void CStencilShadowConnectivityBuilder::ReserveForTriangles( unsigned nNumTriangles, unsigned innNumVertices )
|
||||
{
|
||||
m_vDoubleEdges.reserve(nNumTriangles*3/2);
|
||||
m_vFaces.reserve(nNumTriangles);
|
||||
|
||||
m_dwNumUncompressedVertices=innNumVertices;
|
||||
}
|
||||
|
||||
|
||||
CStencilShadowStaticConnectivityBuilder::CStencilShadowStaticConnectivityBuilder()
|
||||
#ifdef DEBUG_STD_CONTAINERS
|
||||
: m_vPlanes("CStencilShadowStaticConnectivityBuilder.Planes")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
CStencilShadowStaticConnectivityBuilder::~CStencilShadowStaticConnectivityBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
// reserves space for the given number of triangles that are to be added
|
||||
void CStencilShadowStaticConnectivityBuilder::ReserveForTriangles( unsigned nNumTriangles, unsigned innNumVertices )
|
||||
{
|
||||
CStencilShadowConnectivityBuilder::ReserveForTriangles (nNumTriangles, innNumVertices);
|
||||
m_vPlanes.reserve (nNumTriangles);
|
||||
}
|
||||
|
||||
//! return to the state right after construction
|
||||
void CStencilShadowStaticConnectivityBuilder::Reinit( void )
|
||||
{
|
||||
CStencilShadowConnectivityBuilder::Reinit();
|
||||
m_vPlanes.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Adds the triangle with the given vertex indices and vertex coordinates
|
||||
// to the list of triangles that will cast shadows. Welds the vertices based on their
|
||||
// coordinates. Calculates and remembers the normals for each triangle
|
||||
void CStencilShadowStaticConnectivityBuilder::AddTriangleWelded(
|
||||
vindex nV0, vindex nV1, vindex nV2,
|
||||
const Vec3d &vV0, const Vec3d &vV1, const Vec3d &vV2 )
|
||||
{
|
||||
CStencilShadowConnectivityBuilder::AddTriangleWelded (nV0, nV1, nV2, vV0, vV1, vV2);
|
||||
m_vPlanes.push_back(Plane (vV0,vV1,vV2));
|
||||
}
|
||||
|
||||
// constructs/compiles the optimum representation of the connectivity
|
||||
// to be used in run-time
|
||||
// WARNING: use Release method to dispose the connectivity object
|
||||
//! /param inpVertexBuf vertex position buffer to check for solvable open edges (2 vertices with same position)
|
||||
//! /return interface pointer, could be 0
|
||||
class IStencilShadowConnectivity *CStencilShadowStaticConnectivityBuilder::ConstructConnectivity ()
|
||||
{
|
||||
if (m_vPlanes.empty())
|
||||
return new CStencilShadowConnectivity();
|
||||
|
||||
CStencilShadowConnectivity * pConnectivity = (CStencilShadowConnectivity *)CStencilShadowConnectivityBuilder::ConstructConnectivity()->GetInternalRepresentation();
|
||||
pConnectivity->SetPlanes(&m_vPlanes[0], m_vPlanes.size());
|
||||
|
||||
SetVertices (pConnectivity);
|
||||
return pConnectivity;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WARNING: This is only to be called when the whole construction process
|
||||
// is finished, to modify already created connectivity
|
||||
// Goes through all vertices used by the connectivity and constructs a continuous
|
||||
// array out of them; reindexes the vertices in the connectivity object
|
||||
// to use these vertices; puts the new vertex array into the connectivity object
|
||||
void CStencilShadowStaticConnectivityBuilder::SetVertices (CStencilShadowConnectivity * pConnectivity)
|
||||
{
|
||||
// scan through all used vertices and put them into continuous array
|
||||
std::vector<Vec3d> arrNewVertices; // the vertices array in new indexation
|
||||
std::vector<CStencilShadowConnectivity::vindex> arrOldToNewMap; // the mapping old->new indexation
|
||||
arrNewVertices.reserve (pConnectivity->numVertices());
|
||||
arrOldToNewMap.resize (pConnectivity->numVertices(),-1);
|
||||
for (VertexWelderMap::const_iterator it = m_mVertexWelder.begin(); it != m_mVertexWelder.end(); ++it)
|
||||
{
|
||||
#if 1
|
||||
// this will remap the vertex indices
|
||||
arrOldToNewMap[it->second] = arrNewVertices.size();
|
||||
arrNewVertices.push_back(it->first);
|
||||
#else
|
||||
// this will not change indexation
|
||||
arrOldToNewMap[it->second] = it->second;
|
||||
if (arrNewVertices.size() <= it->second)
|
||||
arrNewVertices.resize (it->second+1, Vec3d(0,0,0));
|
||||
arrNewVertices[it->second] = it->first;
|
||||
#endif
|
||||
}
|
||||
|
||||
// now renumber the vertices
|
||||
pConnectivity->SetRemapVertices(&arrOldToNewMap[0], arrOldToNewMap.size(), &arrNewVertices[0], arrNewVertices.size());
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
210
Cry3DEngine/StencilShadowConnectivityBuilder.h
Normal file
210
Cry3DEngine/StencilShadowConnectivityBuilder.h
Normal file
@@ -0,0 +1,210 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CryEngine Source code
|
||||
//
|
||||
// File:StencilShadowConnectivityBuilder.h
|
||||
// Declaration of class CStencilShadowConnectivityBuilder
|
||||
//
|
||||
// History:
|
||||
// -:Created by Sergiy Migdalskiy <sergiy@crytek.de>
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// class CStencilShadowConnectivityBuilder
|
||||
//
|
||||
// This class is used to pre-compute the data for a model that's gonna cast stencil
|
||||
// shadows, and whose vertices may change position, but the topology
|
||||
// cannot change.
|
||||
//
|
||||
// Ok, to put it clear: for each model, you need one instance of
|
||||
// class CStencilShadowConnectivity. To create that instance, use
|
||||
// this class: create an object, push the mesh of the model into it,
|
||||
// then ask this class to give out the CStencilShadowConnectivity.
|
||||
//
|
||||
// CStencilShadowConnectivity is build for maximum run-time performance and
|
||||
// minimal memory footprint, whilst this class is build for convenient
|
||||
// pre-calculations and flexibility.
|
||||
//
|
||||
// The model is allowed to deform, but is not
|
||||
// allowed to change topology (add or remove faces as well as re-assign
|
||||
// face vertices or even change face orientation).
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION NOTES should be in
|
||||
// StencilShadowConnectivityBuilder.cpp
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef _STENCIL_SHADOW_CONNECTIVITY_BUILDER_HDR_
|
||||
#define _STENCIL_SHADOW_CONNECTIVITY_BUILDER_HDR_
|
||||
|
||||
// the connectivity class is required for the declarations
|
||||
// of the Face, Edge, EdgeFace and BasicEdge structures which are common for both
|
||||
// the builder and the built class
|
||||
#include "IEdgeConnectivityBuilder.h" // IEdgeConnectivityBuilder
|
||||
#include "StencilShadowConnectivity.h" // CStencilShadowConnectivity
|
||||
|
||||
#include <map> // STL map<>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
class CStencilShadowConnectivityBuilder : public IEdgeConnectivityBuilder
|
||||
{
|
||||
public:
|
||||
typedef IStencilShadowConnectivity::vindex vindex;
|
||||
//! default constructor
|
||||
//! creates an empty mesh connectivity
|
||||
CStencilShadowConnectivityBuilder(void);
|
||||
|
||||
//! destructor
|
||||
virtual ~CStencilShadowConnectivityBuilder(void);
|
||||
|
||||
//! return to the state right after construction
|
||||
virtual void Reinit( void );
|
||||
|
||||
// sets the maximum distance between two points that are allowed to be welded
|
||||
//virtual void SetWeldTolerance (float fTolerance) {m_fWeldTolerance = fTolerance*fTolerance;}
|
||||
|
||||
// reserves space for the given number of triangles that are to be added
|
||||
//! /param nNumTriangles 0..
|
||||
//! /param innNumVertices 0..
|
||||
virtual void ReserveForTriangles( unsigned nNumTriangles, unsigned innNumVertices );
|
||||
|
||||
// adds a single triangle to the mesh
|
||||
// the triangle is defined by three vertices, in counter-clockwise order
|
||||
// these vertex indices will be used later when accessing the array of
|
||||
// deformed character/model vertices to determine the shadow volume boundary
|
||||
//! /param nV0 vertex index one 0..0xffff
|
||||
//! /param nV1 vertex index two 0..0xffff
|
||||
//! /param nV2 vertex index three 0..0xffff
|
||||
//! /param inpVertexPos pointer to the vertex array (to remove vertices on same position)
|
||||
virtual void AddTriangle( vindex nV0, vindex nV1, vindex nV2 );
|
||||
|
||||
//!
|
||||
//! /param nV0 vertex index one 0..0xffff
|
||||
//! /param nV1 vertex index two 0..0xffff
|
||||
//! /param nV2 vertex index three 0..0xffff
|
||||
//! /param vV0 original vertex one position
|
||||
//! /param vV1 original vertex two position
|
||||
//! /param vV2 original vertex three position
|
||||
//! slower but with the auto weld feature (if there are vertices with the same position your result is smaller and therefore faster)
|
||||
virtual void AddTriangleWelded( vindex nV0, vindex nV1, vindex nV2, const Vec3d &vV0, const Vec3d &vV1, const Vec3d &vV2 );
|
||||
|
||||
// constructs/compiles the optimum representation of the connectivity
|
||||
// to be used in run-time
|
||||
// WARNING: use Release method to dispose the connectivity object
|
||||
//! /param inpVertexBuf vertex position buffer to check for solvable open edges (2 vertices with same position)
|
||||
//! /return interface pointer, could be 0
|
||||
virtual class IStencilShadowConnectivity *ConstructConnectivity( void );
|
||||
|
||||
// returns the number of single (with no pair faces found) or orphaned edges
|
||||
// /return 0..
|
||||
virtual unsigned numOrphanedEdges ()const;
|
||||
|
||||
//! Returns the list of faces for orphaned edges into the given buffer;
|
||||
//! For each orphaned edge, one face will be returned; some faces may be duplicated
|
||||
virtual void getOrphanedEdgeFaces (unsigned* pBuffer);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// for the descriptions of the following shared structures, refer to
|
||||
// File:StencilShadowConnectivity.h
|
||||
typedef CStencilShadowConnectivity::BasicEdge BasicEdge;
|
||||
typedef CStencilShadowConnectivity::Edge Edge;
|
||||
typedef CStencilShadowConnectivity::EdgeFace EdgeFace;
|
||||
typedef CStencilShadowConnectivity::Face Face;
|
||||
|
||||
// map of single edges - edge with only one face attached
|
||||
typedef std::map<BasicEdge, EdgeFace> SingleEdgeMap;
|
||||
SingleEdgeMap m_mapSingleEdges; //!<
|
||||
|
||||
// array of double-edges - edges with both faces attached/found
|
||||
typedef std::vector<Edge> DoubleEdgeArray;
|
||||
DoubleEdgeArray m_vDoubleEdges; //!<
|
||||
|
||||
// triangles added (used to extract index to reference edge to faces, and keep the topology)
|
||||
typedef std::vector<Face> FaceArray;
|
||||
FaceArray m_vFaces; //!<
|
||||
DWORD m_dwNumUncompressedVertices; //!<
|
||||
|
||||
// helper to get order for Vec3d
|
||||
struct CVec3dOrder: public std::binary_function< Vec3d, Vec3d, bool>
|
||||
{
|
||||
bool operator() ( const Vec3d &a, const Vec3d &b ) const
|
||||
{
|
||||
// first sort by x
|
||||
if(a.x<b.x)return(true);
|
||||
if(a.x>b.x)return(false);
|
||||
|
||||
// then by y
|
||||
if(a.y<b.y)return(true);
|
||||
if(a.y>b.y)return(false);
|
||||
|
||||
// then by z
|
||||
if(a.z<b.z)return(true);
|
||||
if(a.z>b.z)return(false);
|
||||
|
||||
return(false);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<Vec3d,unsigned,CVec3dOrder> VertexWelderMap;
|
||||
VertexWelderMap m_mVertexWelder; //!< used for AddTriangleWelded
|
||||
|
||||
// this will try to find a close match to the given vertex, and
|
||||
// if found, return its index (the actual index of the vertex that's very close or
|
||||
// coincide with v in space). Otherwise, creates a new vertex reference in the map
|
||||
// and returns the index nNewVertex
|
||||
unsigned WeldVertex (const Vec3d& v, unsigned nNewVertex);
|
||||
|
||||
//float m_fWeldTolerance;
|
||||
// this is 1 + the max index of the vertex in the original mesh vertex array, that
|
||||
// is used by the currently being built connectivity
|
||||
//unsigned m_numOrigMeshVerticesUsed; // this is unneeded because connectivity calculates this itself
|
||||
protected:
|
||||
|
||||
// adds a new single edge, or finds an adjacent edge and puts the double-edge on record
|
||||
// add a new edge, if there is no complementary single edge;
|
||||
// otherwise, withdraw the edge from the list of single edges and add to double edges
|
||||
//! /param eEdge
|
||||
//! /param efFace
|
||||
void AddNewEdge (BasicEdge eEdge, EdgeFace efFace);
|
||||
};
|
||||
|
||||
// this is the builder of connectivity that can be used for static objects
|
||||
// (with non-changing face normals)
|
||||
class CStencilShadowStaticConnectivityBuilder :public CStencilShadowConnectivityBuilder
|
||||
{
|
||||
public:
|
||||
CStencilShadowStaticConnectivityBuilder();
|
||||
virtual ~CStencilShadowStaticConnectivityBuilder();
|
||||
void AddTriangleWelded( vindex nV0, vindex nV1, vindex nV2, const Vec3d &vV0, const Vec3d &vV1, const Vec3d &vV2 );
|
||||
//! return to the state right after construction
|
||||
virtual void Reinit( void );
|
||||
|
||||
// reserves space for the given number of triangles that are to be added
|
||||
//! /param nNumTriangles 0..
|
||||
//! /param innNumVertices 0..
|
||||
virtual void ReserveForTriangles( unsigned nNumTriangles, unsigned innNumVertices );
|
||||
|
||||
// constructs/compiles the optimum representation of the connectivity
|
||||
// to be used in run-time
|
||||
// WARNING: use Release method to dispose the connectivity object
|
||||
//! /param inpVertexBuf vertex position buffer to check for solvable open edges (2 vertices with same position)
|
||||
//! /return interface pointer, could be 0
|
||||
virtual class IStencilShadowConnectivity *ConstructConnectivity( void );
|
||||
protected:
|
||||
// WARNING: This is only to be called when the whole construction process
|
||||
// is finished, to modify already created connectivity
|
||||
// Goes through all vertices used by the connectivity and constructs a continuous
|
||||
// array out of them; reindexes the vertices in the connectivity object
|
||||
// to use these vertices; puts the new vertex array into the connectivity object
|
||||
void SetVertices (CStencilShadowConnectivity * pConnectivity);
|
||||
|
||||
typedef CStencilShadowConnectivity::Plane Plane;
|
||||
std::vector<Plane> m_vPlanes;
|
||||
};
|
||||
|
||||
#endif // _STENCIL_SHADOW_CONNECTIVITY_BUILDER_HDR_
|
||||
496
Cry3DEngine/StencilShadowEdgeDetector.cpp
Normal file
496
Cry3DEngine/StencilShadowEdgeDetector.cpp
Normal file
@@ -0,0 +1,496 @@
|
||||
#include "stdafx.h"
|
||||
#include "StencilShadowConnectivity.h"
|
||||
#include "StencilShadowEdgeDetector.h"
|
||||
|
||||
CStencilShadowEdgeDetector::CStencilShadowEdgeDetector():
|
||||
m_pConnectivity(NULL),
|
||||
m_pModelVertices(NULL)
|
||||
{
|
||||
m_bBitFieldIsSet=false;
|
||||
}
|
||||
|
||||
// Re-construct the whole object
|
||||
// Use this object to reuse the EdgeDetector object multiple times for different
|
||||
// connectivities and vertices. This can save on reallocating internal arrays this object uses at run time
|
||||
void CStencilShadowEdgeDetector::reinit (
|
||||
const IStencilShadowConnectivity* pConnectivity,
|
||||
const Vec3d* pDeformedVertices
|
||||
)
|
||||
{
|
||||
assert(pConnectivity);
|
||||
|
||||
m_pConnectivity = pConnectivity->GetInternalRepresentation();
|
||||
m_pModelVertices = pDeformedVertices;
|
||||
|
||||
if (!m_pModelVertices || m_pConnectivity->IsStandalone())
|
||||
m_pModelVertices = m_pConnectivity->getVertices();
|
||||
|
||||
assert (pDeformedVertices);
|
||||
|
||||
m_arrShadowEdges.clear();
|
||||
m_arrShadowFaces.clear();
|
||||
m_numShadowEdgeVertices = 0;
|
||||
}
|
||||
|
||||
CStencilShadowEdgeDetector::~CStencilShadowEdgeDetector(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// fills in the internal array of faces and vertices
|
||||
// - detected shadow faces for the given light source and model
|
||||
void CStencilShadowEdgeDetector::detectShadowFaces ()
|
||||
{
|
||||
assert(m_pConnectivity);
|
||||
if(!m_pConnectivity)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning(0,0,"CStencilShadowEdgeDetector::detectShadowFaces: !m_pConnectivity");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_arrFaceOrientations.empty())
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning(0,0,"CStencilShadowEdgeDetector::detectShadowFaces: m_arrFaceOrientations.empty()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!m_arrFaceOrientations.empty());
|
||||
|
||||
// scan all faces and fill the backfacing ones
|
||||
unsigned nNumFaces = m_pConnectivity->numFaces();
|
||||
|
||||
unsigned* pFaceOrientBits = m_arrFaceOrientations.begin();
|
||||
for (unsigned nFace = 0; nFace < nNumFaces; ++pFaceOrientBits)
|
||||
{
|
||||
unsigned nOrientBit = 1;
|
||||
do
|
||||
{
|
||||
if ((*pFaceOrientBits & nOrientBit) == 0)
|
||||
{
|
||||
// the face is back-facing the light
|
||||
const CStencilShadowConnectivity::Face& face = m_pConnectivity->getFace(nFace);
|
||||
// revert orientation of the face 'cause the volumizer expects light-facing capping faces
|
||||
AddFace(face.getVertex(0), face.getVertex(2), face.getVertex(1));
|
||||
}
|
||||
}
|
||||
while (((++nFace) < nNumFaces) && (nOrientBit <<= 1) != 0);
|
||||
}
|
||||
|
||||
m_bBitFieldIsSet=true;
|
||||
}
|
||||
|
||||
|
||||
// returns true if the given face faces the light, and false otherwise
|
||||
bool CStencilShadowEdgeDetector::IsFaceTurnedToLight (unsigned nFace, const Vec3d& vLight)
|
||||
{
|
||||
assert(m_pModelVertices);
|
||||
assert(m_pConnectivity);
|
||||
assert(nFace>=0 && nFace<m_pConnectivity->numFaces());
|
||||
|
||||
|
||||
if (m_pConnectivity->hasPlanes())
|
||||
return m_pConnectivity->getPlane(nFace).apply (vLight) > 0;
|
||||
|
||||
|
||||
const CStencilShadowConnectivity::Face& face = m_pConnectivity->getFace(nFace);
|
||||
|
||||
DWORD dwIndex[3]={ face.getVertex(0),
|
||||
face.getVertex(1),
|
||||
face.getVertex(2) };
|
||||
|
||||
const Vec3d& vFaceV0 = m_pModelVertices[dwIndex[0]];
|
||||
|
||||
Vec3d vNormal = (m_pModelVertices[dwIndex[1]] - vFaceV0) ^ (m_pModelVertices[dwIndex[2]] - vFaceV0);
|
||||
|
||||
return vNormal * (vLight - vFaceV0) > 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Calculates all face orientations into the bit array
|
||||
// PARAMETERS:
|
||||
// vLight - position of the light source to detect the edges for
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowEdgeDetector::computeFaceOrientations (Vec3d vLight)
|
||||
{
|
||||
unsigned nModelNumFaces = m_pConnectivity->numFaces();
|
||||
|
||||
// mask that masks out the bits that address the bit in an unsigned
|
||||
//const nBitIndexMask = (sizeof(m_arrFaceOrientations[0])*8) - 1;
|
||||
|
||||
// number of unsigneds to allocate in the bit array
|
||||
unsigned nBitarraySize = (nModelNumFaces + 31u) >> 5;
|
||||
if (m_arrFaceOrientations.size() < nBitarraySize)
|
||||
m_arrFaceOrientations.reinit(nBitarraySize);
|
||||
|
||||
memset (m_arrFaceOrientations.begin(), 0, nBitarraySize * 4); // neccessary because we set only the 1 bits
|
||||
|
||||
// scan through all faces, in packets of 32 faces, and pack the orientations into
|
||||
// bit array with 32-bit portions
|
||||
unsigned nNumFaces = m_pConnectivity->numFaces();
|
||||
unsigned* pFaceOrientBits = m_arrFaceOrientations.begin();
|
||||
for (unsigned nFace = 0; nFace < nNumFaces; ++pFaceOrientBits)
|
||||
{
|
||||
unsigned nOrientBit = 1;
|
||||
do
|
||||
{
|
||||
if (IsFaceTurnedToLight (nFace, vLight))
|
||||
*pFaceOrientBits |= nOrientBit;
|
||||
}
|
||||
while (((++nFace) < nNumFaces) && (nOrientBit <<= 1) != 0);
|
||||
}
|
||||
|
||||
m_bBitFieldIsSet=true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// fills in the internal array of edges and vertices with appropriate data
|
||||
// call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
// - detected shadow edges for the given light source and model
|
||||
// ALGORITHM:
|
||||
// scans each edge and determines signs of volumes formed with this edge and light source
|
||||
// on one hand and the opposite vertex on the other hand
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowEdgeDetector::detectShadowEdges( void )
|
||||
{
|
||||
assert(m_bBitFieldIsSet); // call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
|
||||
// number of vertices in the original model
|
||||
unsigned nModelNumVertices = m_pConnectivity->numVertices();
|
||||
|
||||
//
|
||||
// for each edge, insert it into m_arrShadowEdges if it's boundary;
|
||||
// insert it in reverse order if it's reverse-boundary
|
||||
// insert the vertex/-ices into the m_arrVertices array if necessary
|
||||
//
|
||||
// TODO: perhaps an optimization is possible, if we detect adjacent edges
|
||||
// and then render triangle strips without indices
|
||||
//
|
||||
|
||||
unsigned nEdge;
|
||||
unsigned nEdgeCount = m_pConnectivity->numEdges();
|
||||
for (nEdge = 0; nEdge < nEdgeCount; ++nEdge)
|
||||
{
|
||||
// this is the edge to check against being boundary
|
||||
const CStencilShadowConnectivity::Edge& rEdge = m_pConnectivity->getEdge(nEdge);
|
||||
|
||||
// check the edge
|
||||
switch (CheckEdgeType (
|
||||
rEdge.getFace(0).getFaceIndex(),
|
||||
rEdge.getFace(1).getFaceIndex()
|
||||
))
|
||||
{
|
||||
case nET_Boundary:
|
||||
AddEdge (rEdge[0], rEdge[1]);
|
||||
break;
|
||||
case nET_ReverseBoundary:
|
||||
AddEdge (rEdge[1], rEdge[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now check the orphan edges
|
||||
nEdgeCount = m_pConnectivity->numOrphanEdges();
|
||||
for (nEdge = 0; nEdge < nEdgeCount; ++nEdge)
|
||||
{
|
||||
// this is the edge to check against being boundary
|
||||
const CStencilShadowConnectivity::OrphanEdge& rEdge = m_pConnectivity->getOrphanEdge(nEdge);
|
||||
|
||||
// check the edge
|
||||
switch (CheckOrphanEdgeType (
|
||||
rEdge.getFace().getFaceIndex()
|
||||
))
|
||||
{
|
||||
case nET_Boundary:
|
||||
AddEdge (rEdge[0], rEdge[1]);
|
||||
break;
|
||||
case nET_ReverseBoundary:
|
||||
AddEdge (rEdge[1], rEdge[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_bBitFieldIsSet=false;
|
||||
|
||||
m_numShadowEdgeVertices = m_pConnectivity->numVertices();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Adds the given shadow edge to the list of boundary edges
|
||||
// PARAMETERS:
|
||||
// nVertex[2] - indices of the edge vertices in the m_pModelVertices
|
||||
// array (and in g_arrModelVtxIdxMap).
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowEdgeDetector::AddEdge( vindex nVertex0, vindex nVertex1 )
|
||||
{
|
||||
// add to the list of edges
|
||||
m_arrShadowEdges.push_back(nVertex0);
|
||||
m_arrShadowEdges.push_back(nVertex1);
|
||||
}
|
||||
|
||||
|
||||
// adds the given shadow face, in the order that is passed
|
||||
void CStencilShadowEdgeDetector::AddFace( vindex nVertex0, vindex nVertex1, vindex nVertex2 )
|
||||
{
|
||||
// add to the list of faces
|
||||
m_arrShadowFaces.push_back(nVertex0);
|
||||
m_arrShadowFaces.push_back(nVertex1);
|
||||
m_arrShadowFaces.push_back(nVertex2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// checks the edge type by the face indices: assumes that the face orientation bits have been calculated already
|
||||
CStencilShadowEdgeDetector::EdgeTypeEnum
|
||||
CStencilShadowEdgeDetector::CheckEdgeType (unsigned nFace0, unsigned nFace1)
|
||||
{
|
||||
assert(m_arrFaceOrientations.size());
|
||||
|
||||
if ((m_arrFaceOrientations[nFace0>>5]&(1<<(nFace0&0x1F))) == 0)
|
||||
{
|
||||
// the primary edge face is culled against the light
|
||||
if ((m_arrFaceOrientations[nFace1>>5]&(1<<(nFace1&0x1F))) == 0)
|
||||
{
|
||||
// the opposite face is culled against the light,
|
||||
// both are back-facing the light
|
||||
return nET_Interior;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the opposite face is facing the light
|
||||
// we've got the rev-boundary edge
|
||||
return nET_ReverseBoundary;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the primary edge face is facing the light
|
||||
if ((m_arrFaceOrientations[nFace1>>5]&(1<<(nFace1&0x1F))) == 0)
|
||||
{
|
||||
// the opposite face is culled against the light,
|
||||
// we've got the boundary edge
|
||||
return nET_Boundary;
|
||||
}
|
||||
else
|
||||
{
|
||||
// both are facing the light
|
||||
return nET_Exterior;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CStencilShadowEdgeDetector::EdgeTypeEnum
|
||||
CStencilShadowEdgeDetector::CheckOrphanEdgeType (unsigned nFace0)
|
||||
{
|
||||
assert(m_arrFaceOrientations.size());
|
||||
|
||||
if ((m_arrFaceOrientations[nFace0>>5]&(1<<(nFace0&0x1F))) == 0)
|
||||
{
|
||||
// the primary edge face is culled against the light
|
||||
|
||||
// we can either ignore the face and return nET_Interior
|
||||
// or we can pretend we have a complementary face - so that the face casts
|
||||
// the shadow with both its sides. then, return nET_ReverseBoundary
|
||||
|
||||
return nET_Interior;
|
||||
//return nET_ReverseBoundary;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the primary edge face is facing the light
|
||||
// since we don't have any neighbor to check, pretend as if the neighbor were back-facing the light
|
||||
return nET_Boundary;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
const CStencilShadowEdgeDetector::vindex *CStencilShadowEdgeDetector::getShadowEdgeArray( unsigned &outiNumEdges ) const
|
||||
{
|
||||
outiNumEdges=m_arrShadowEdges.size()/2;
|
||||
|
||||
if(!outiNumEdges)return(0);
|
||||
|
||||
return(&m_arrShadowEdges[0]);
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
void CStencilShadowEdgeDetector::BuildSilhuetteFromPos( const IStencilShadowConnectivity* pConnectivity, const Vec3d &invLightPos,
|
||||
const Vec3d* inpDeformedVertices )
|
||||
{
|
||||
assert(pConnectivity);
|
||||
|
||||
m_pConnectivity = pConnectivity->GetInternalRepresentation();
|
||||
m_pModelVertices = m_pConnectivity->getVertices();
|
||||
if ( !pConnectivity->IsStandalone())
|
||||
{
|
||||
if (!m_pModelVertices)
|
||||
m_pModelVertices = inpDeformedVertices;
|
||||
}
|
||||
|
||||
assert(m_pModelVertices);
|
||||
|
||||
m_arrShadowEdges.clear();
|
||||
m_arrShadowFaces.clear();
|
||||
m_numShadowEdgeVertices = 0;
|
||||
|
||||
computeFaceOrientations(invLightPos);
|
||||
|
||||
detectShadowEdges(); // call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
detectShadowFaces();
|
||||
|
||||
// assert(m_bBitFieldIsSet);
|
||||
if(!m_bBitFieldIsSet)
|
||||
Warning(0,0,"CStencilShadowEdgeDetector::BuildSilhuetteFromPos: !m_bBitFieldIsSet");
|
||||
}
|
||||
|
||||
|
||||
void CStencilShadowEdgeDetector::BuildSilhuetteFromBitfield( const IStencilShadowConnectivity* pConnectivity, const Vec3d* inpVertices )
|
||||
{
|
||||
assert(pConnectivity);
|
||||
|
||||
assert(m_bBitFieldIsSet); // call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
|
||||
m_pConnectivity = pConnectivity->GetInternalRepresentation();
|
||||
m_pModelVertices = m_pConnectivity->getVertices();
|
||||
if (!m_pModelVertices)
|
||||
m_pModelVertices = inpVertices;
|
||||
|
||||
assert(m_pModelVertices);
|
||||
|
||||
m_arrShadowEdges.clear();
|
||||
m_arrShadowFaces.clear();
|
||||
m_numShadowEdgeVertices = 0;
|
||||
|
||||
// triangle orientation bitfield has to be provided by calling getOrientationBitfield
|
||||
detectShadowEdges(); // call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
detectShadowFaces();
|
||||
|
||||
assert(m_bBitFieldIsSet); // call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
}
|
||||
|
||||
|
||||
//!
|
||||
unsigned *CStencilShadowEdgeDetector::getOrientationBitfield( int iniNumTriangles )
|
||||
{
|
||||
assert(iniNumTriangles);
|
||||
|
||||
// mask that masks out the bits that address the bit in an unsigned
|
||||
//const nBitIndexMask = (sizeof(m_arrFaceOrientations[0])*8) - 1;
|
||||
|
||||
// number of unsigneds to allocate in the bit array
|
||||
unsigned nBitarraySize = (iniNumTriangles + 31u) >> 5;
|
||||
if (m_arrFaceOrientations.size() < nBitarraySize)
|
||||
m_arrFaceOrientations.reinit(nBitarraySize);
|
||||
|
||||
m_bBitFieldIsSet=true;
|
||||
|
||||
memset (m_arrFaceOrientations.begin(), 0, nBitarraySize * 4); // neccessary because we set only the 1 bits
|
||||
|
||||
return(m_arrFaceOrientations.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// make up the shadow volume
|
||||
// constructs the shadow volume mesh, and puts the mesh definition into the
|
||||
// vertex buffer (vertices that define the mesh) and index buffer (triple
|
||||
// integers defining the triangular faces, counterclockwise order)
|
||||
// The size of the vertex buffer must be at least numVertices()
|
||||
// The size of the index buffer must be at least numIndices()
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void CStencilShadowEdgeDetector::meshShadowVolume( Vec3d vLight, float fFactor, Vec3d* outpVertexBuf, unsigned short* pIndexBuf )
|
||||
{
|
||||
assert(outpVertexBuf);
|
||||
|
||||
// The Algorithm
|
||||
// We have the edges and their vertex array in m_pShadowEdges
|
||||
// For each edge, we generate a quad (2 trianges), out of the pair of vertices defining the edge:
|
||||
// take the vertex, move it away from the light (this makes up the far vertex), this will define an extruded edge -- our actual quad
|
||||
|
||||
// 1. scan through all shadow edges, insert corresponding generated vertex indices into the index buffer;
|
||||
// 2. scan through all vertices, generate far vertices (for each near vertex, there's a far vertex), fill in the vertex buffer
|
||||
unsigned nNumVerts;
|
||||
unsigned i;
|
||||
|
||||
nNumVerts = numShadowVolumeVertices()/2;
|
||||
const Vec3d* pVertices = m_pModelVertices;
|
||||
|
||||
// go thougth all compressed vertices
|
||||
{
|
||||
Vec3d vLightFac=(1.0f-fFactor)*vLight; // optimized a little
|
||||
|
||||
for(i=0;i<nNumVerts;++i)
|
||||
{
|
||||
const Vec3d& vPos = pVertices[i];
|
||||
outpVertexBuf[i] = vPos;
|
||||
outpVertexBuf[nNumVerts+i] = vPos*fFactor + vLightFac; // == (vPos - vLight) * fFactor + vLight
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned short* pIndex = pIndexBuf;
|
||||
unsigned nNumEdges;
|
||||
const unsigned short* pEdgeArray = getShadowEdgeArray(nNumEdges);
|
||||
|
||||
// fill in the shadow volume quads (extruded vertices)
|
||||
for (i = 0; i < nNumEdges; ++i)
|
||||
{
|
||||
unsigned short Edge1=*pEdgeArray++,Edge2=*pEdgeArray++;
|
||||
|
||||
assert (Edge1 < nNumVerts);
|
||||
assert (Edge2 < nNumVerts);
|
||||
|
||||
*(pIndex++) = Edge2;
|
||||
*(pIndex++) = Edge1;
|
||||
*(pIndex++) = Edge1 + nNumVerts;
|
||||
|
||||
*(pIndex++) = Edge1 + nNumVerts;
|
||||
*(pIndex++) = Edge2 + nNumVerts;
|
||||
*(pIndex++) = Edge2;
|
||||
}
|
||||
|
||||
if(m_arrShadowFaces.empty())
|
||||
return; // vlad: otherwise crash
|
||||
|
||||
// fill in the shadow volume caps
|
||||
unsigned nFaceIndices;
|
||||
const unsigned short* pFaceIndex = getShadowFaceIndices(nFaceIndices);
|
||||
const unsigned short* pFaceIndexEnd = pFaceIndex + nFaceIndices;
|
||||
// fill the near cap
|
||||
memcpy (pIndex, pFaceIndex, sizeof(*pFaceIndex)*nFaceIndices);
|
||||
|
||||
pIndex += nFaceIndices;
|
||||
|
||||
// fill the far cap
|
||||
|
||||
for (; pFaceIndex < pFaceIndexEnd; pFaceIndex += 3)
|
||||
{
|
||||
// for each face..
|
||||
assert (pFaceIndex[0] < nNumVerts);
|
||||
assert (pFaceIndex[1] < nNumVerts);
|
||||
assert (pFaceIndex[2] < nNumVerts);
|
||||
|
||||
*(pIndex++) = pFaceIndex[0] + nNumVerts;
|
||||
*(pIndex++) = pFaceIndex[2] + nNumVerts;
|
||||
*(pIndex++) = pFaceIndex[1] + nNumVerts;
|
||||
}
|
||||
|
||||
assert(numShadowVolumeVertices()==nNumVerts*2);
|
||||
assert(numShadowVolumeIndices()==(int)(pIndex-pIndexBuf));
|
||||
}
|
||||
199
Cry3DEngine/StencilShadowEdgeDetector.h
Normal file
199
Cry3DEngine/StencilShadowEdgeDetector.h
Normal file
@@ -0,0 +1,199 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CryEngine Source code
|
||||
//
|
||||
// File:StencilShadowEdgeDetector.h
|
||||
// Declaration of class CStencilShadowEdgeDetector
|
||||
//
|
||||
// History:
|
||||
// -:Created by Sergiy Migdalskiy <sergiy@crytek.de>
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// class CStencilShadowEdgeDetector
|
||||
// AUTHOR: Sergiy Migdalskiy <sergiy@crytek.de>
|
||||
//
|
||||
// This is run-time (temporary, non-persistent) class that's used to construct
|
||||
// the optimized shadow volume (optimized means only with the necessary boundary
|
||||
// edges) for a concrete deformed model/character instance
|
||||
//
|
||||
// It ACCEPTS a Connectivity instance that must be pre-computed on per-model
|
||||
// basis, and an array of deformed vertices.
|
||||
// It OUTPUTS (constructs, prepares) a set of edges in the form prepared for
|
||||
// fast construction of efficient shadow volume render data (vertex buffer)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef _STENCIL_SHADOW_EDGE_DETECTOR_HDR_
|
||||
#define _STENCIL_SHADOW_EDGE_DETECTOR_HDR_
|
||||
|
||||
#include "StencilShadowConnectivity.h" // CStencilShadowConnectivity
|
||||
#include "IEdgeConnectivityBuilder.h" // IEdgeDetector
|
||||
#include "Cry3DEngineBase.h"
|
||||
|
||||
class CStencilShadowEdgeDetector : public IEdgeDetector, public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
|
||||
//! default constructor
|
||||
CStencilShadowEdgeDetector();
|
||||
|
||||
//! destructor
|
||||
~CStencilShadowEdgeDetector(void);
|
||||
|
||||
// Re-construct the whole object
|
||||
// Use this object to reuse the EdgeDetector object multiple times for different
|
||||
// connectivities and vertices. This can save on reallocating internal arrays this object uses at run time
|
||||
// /param pConnectivity, must not be 0 - don't use if there is nothing to do
|
||||
// /param pDeformedVertices, must not be 0 - don't use if there is nothing to do
|
||||
void reinit ( const IStencilShadowConnectivity* pConnectivity, const Vec3d* pDeformedVertices );
|
||||
|
||||
//! /param pConnectivity must not be 0
|
||||
//! /param invLightPos in ???-space (World or Object)
|
||||
//! /param pDeformedVertices must not be 0
|
||||
virtual void BuildSilhuetteFromPos( const IStencilShadowConnectivity* pConnectivity, const Vec3d &invLightPos, const Vec3d* pDeformedVertices );
|
||||
|
||||
//! /param iniNumTriangles the size it should have, must not be 0 - don't use if there is nothing to do
|
||||
//! /return pointer to the cleared (set to zero) bitfield where each bit represents the orientation of one triangle
|
||||
virtual unsigned *getOrientationBitfield( int iniNumTriangles );
|
||||
|
||||
//!
|
||||
//! /param pConnectivity must not be 0 - don't use if there is nothing to do
|
||||
//! /param inpVertices must not be 0 - don't use if there is nothing to do
|
||||
virtual void BuildSilhuetteFromBitfield( const IStencilShadowConnectivity* pConnectivity, const Vec3d* inpVertices );
|
||||
|
||||
//! returns a pointer to the the given shadow edges (array of 2 integers, defining the vertex indices)
|
||||
//! /param
|
||||
//! /return
|
||||
virtual const vindex *getShadowEdgeArray( unsigned &outiNumEdges ) const;
|
||||
|
||||
|
||||
|
||||
//! number of vertices used to define the detected shadow edges
|
||||
//! (at least nSE+1, at most nSE*2, where nSE is the number of shadow edges)
|
||||
//! This may be less than total number of vertices since the edges may use less
|
||||
//! vertices than faces
|
||||
//! /return
|
||||
_inline unsigned numShadowEdgeVertices() const
|
||||
{
|
||||
return m_numShadowEdgeVertices;
|
||||
}
|
||||
|
||||
|
||||
// number of vertices required to define the shadow volume,
|
||||
// use this to determine the size of vertex buffer passed to meshShadowVolume (2*used vertices because of capping)
|
||||
virtual unsigned numShadowVolumeVertices( void ) const
|
||||
{
|
||||
assert(m_pConnectivity);
|
||||
|
||||
return(m_pConnectivity->numVertices()*2);
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( push ) //AMD Port
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
|
||||
// pointer to the triplets defining shadow faces
|
||||
virtual const vindex* getShadowFaceIndices( unsigned &outCount ) const
|
||||
{
|
||||
outCount=m_arrShadowFaces.size();
|
||||
|
||||
return &m_arrShadowFaces[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// number of indices required to define the shadow volume,
|
||||
// use this to determine the size of index buffer passed to meshShadowVolume
|
||||
// this is always a dividend of 3
|
||||
virtual unsigned numShadowVolumeIndices()const
|
||||
{
|
||||
// each shadow edge requires 6 indices to define the shadow volume:
|
||||
// it defines one quad => 2 triangles => 6 vertex references
|
||||
unsigned numShadowEdges=m_arrShadowEdges.size()/2;
|
||||
unsigned numShadowFaceIndices =m_arrShadowFaces.size();
|
||||
|
||||
return(numShadowEdges*6 + numShadowFaceIndices*2);
|
||||
}
|
||||
|
||||
#ifdef WIN64
|
||||
#pragma warning( pop ) //AMD Port
|
||||
#endif
|
||||
|
||||
//! fills in the internal array of edges and vertices with appropriate data
|
||||
//! call computeFaceOrientations(vLight) before or create the triangle orientation bitfield yourself
|
||||
//! - detected shadow edges for the given light source and model
|
||||
void detectShadowEdges();
|
||||
|
||||
//! fills in the internal array of faces and vertices
|
||||
//! - detected shadow faces for the given light source and model
|
||||
void detectShadowFaces ();
|
||||
|
||||
|
||||
//! calculates all face orientations into the bit array
|
||||
//! /param invLight position of the light source in ???-space (World or Object)
|
||||
void computeFaceOrientations (Vec3d invLight);
|
||||
|
||||
|
||||
|
||||
// make up the shadow volume
|
||||
// constructs the shadow volume mesh, and puts the mesh definition into the
|
||||
// vertex buffer (vertices that define the mesh) and index buffer (triple
|
||||
// integers defining the triangular faces, counterclockwise order)
|
||||
// The size of the vertex buffer must be at least numVertices()
|
||||
// The size of the index buffer must be at least numIndices()
|
||||
virtual void meshShadowVolume (Vec3d vLight, float fFactor, Vec3d* outpVertexBuf, unsigned short* pIndexBuf );
|
||||
|
||||
protected:
|
||||
const CStencilShadowConnectivity* m_pConnectivity; //!<
|
||||
const Vec3d* m_pModelVertices; //!<
|
||||
|
||||
|
||||
// number of vertices used to define edges
|
||||
unsigned m_numShadowEdgeVertices;
|
||||
|
||||
// array of shadow edges, referring to the vertices in m_vVertices
|
||||
// Now, edges are defined by pairs of integers. This may change in the future
|
||||
std::vector <vindex> m_arrShadowEdges;
|
||||
|
||||
// array of shadow faces, referring to the vertices in m_vVertices
|
||||
std::vector <vindex> m_arrShadowFaces;
|
||||
|
||||
// returns true if the given face faces the light, and false otherwise
|
||||
bool IsFaceTurnedToLight( unsigned nFace, const Vec3d& vLight );
|
||||
|
||||
// adds the given shadow edge to the list of boundary edges
|
||||
//! /param nVertex0 0..
|
||||
//! /param nVertex1 0..
|
||||
void AddEdge (vindex nVertex0, vindex nVertex1);
|
||||
|
||||
// adds the given shadow face, in the order that is passed
|
||||
//! /param nVertex0 0..
|
||||
//! /param nVertex1 0..
|
||||
//! /param nVertex2 0..
|
||||
void AddFace (vindex nVertex0, vindex nVertex1, vindex nVertex2);
|
||||
|
||||
// checks whether the given edge is boundary or reverse boundary
|
||||
enum EdgeTypeEnum {
|
||||
nET_Boundary, // normal boundary edge
|
||||
nET_ReverseBoundary, // internal boundary edge, needs reversing before insertion into the edge list
|
||||
nET_Exterior, // visible to the light surface interior edge
|
||||
nET_Interior // invisible to the light surface interior edge
|
||||
};
|
||||
|
||||
//! checks the edge type by the face indices: assumes that the face orientation bits have been calculated already
|
||||
//! /param nFace0
|
||||
//! /param nFace1
|
||||
EdgeTypeEnum CheckEdgeType (unsigned nFace0, unsigned nFace1);
|
||||
|
||||
//! /param nFace0
|
||||
EdgeTypeEnum CheckOrphanEdgeType (unsigned nFace0);
|
||||
|
||||
// face orientation bit array: for each face, there's a bit, which is 1 if it's facing the light and 0 otherwise
|
||||
TFixedArray<unsigned> m_arrFaceOrientations;
|
||||
|
||||
bool m_bBitFieldIsSet; //! for debugging purpose
|
||||
};
|
||||
|
||||
#endif
|
||||
697
Cry3DEngine/Vegetation.cpp
Normal file
697
Cry3DEngine/Vegetation.cpp
Normal file
@@ -0,0 +1,697 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjman.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Loading trees, buildings, ragister/unregister entities for rendering
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3DEngine.h"
|
||||
|
||||
void CStatObjInst::Serialize(bool bSave, ICryPak * pPak, FILE * f)
|
||||
{
|
||||
if(bSave)
|
||||
pPak->FWrite(this,sizeof(*this),1,f);
|
||||
else
|
||||
pPak->FRead(this,sizeof(*this),1,f);
|
||||
}
|
||||
|
||||
// Bending
|
||||
static float CStatObjInst__sSpline(float x)
|
||||
{
|
||||
float fX = fabsf(x);
|
||||
|
||||
if(fX > 2.0f)
|
||||
return 0;
|
||||
if(fX > 1.0f)
|
||||
return (2.0f-fX)*(2.0f-fX)*(2.0f-fX)/6.0f;
|
||||
return 2.0f/3.0f-fX*fX+0.5f*fX*fX*fX;
|
||||
}
|
||||
|
||||
float CStatObjInst::Interpolate(float& pprev, float& prev, float& next, float& nnext, float ppweight, float pweight, float nweight, float nnweight)
|
||||
{
|
||||
return pprev*ppweight + prev*pweight + next*nweight + nnext*nnweight;
|
||||
}
|
||||
|
||||
float CStatObjInst::GetBendingRandomFactor()
|
||||
{ // calculate random
|
||||
static float sInterpValues[16] = {1.2f,1.0f,1.1f,0.8f,0.5f,0.7f,1.0f,1.3f,0.66f,0.8f,0.7f,0.9f,1.1f,1.4f,1.1f,1.3f};
|
||||
|
||||
float time = GetTimer()->GetCurrTime() * 0.666f;
|
||||
int itime = fastftol_positive(time);
|
||||
float pprev = sInterpValues[(itime-1)&15];
|
||||
float prev = sInterpValues[(itime)&15];
|
||||
float next = sInterpValues[(itime+1)&15];
|
||||
float nnext = sInterpValues[(itime+2)&15];
|
||||
|
||||
float ppweight = CStatObjInst__sSpline(time-itime+1.0f);
|
||||
float pweight = CStatObjInst__sSpline(time-itime+0.0f);
|
||||
float nweight = CStatObjInst__sSpline(time-itime-1.0f);
|
||||
float nnweight = CStatObjInst__sSpline(time-itime-2.0f);
|
||||
return Interpolate(pprev, prev, next, nnext, ppweight, pweight, nweight, nnweight);
|
||||
}
|
||||
|
||||
bool CStatObjInst::DrawEntity(const struct SRendParams & _EntDrawParams)
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
// if(!GetCVars()->e_vegetation)
|
||||
// return false;
|
||||
|
||||
const Vec3d & vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
float fDistance = m_arrfDistance[m_pObjManager->m_nRenderStackLevel];
|
||||
|
||||
/*
|
||||
// calculate distance
|
||||
float fPrevDist0 = m_fDistance0;
|
||||
m_fDistance = GetDist2D( vCamPos.x, vCamPos.y, m_vPos.x, m_vPos.y )*m_pObjManager->m_fZoomFactor;
|
||||
if(!m_pObjManager->m_nRenderStackLevel) // remember to be able to restore this value after reqursion drawing
|
||||
m_fDistance0 = m_fDistance;*/
|
||||
|
||||
// float fMaxViewDist = GetMaxViewDist();
|
||||
|
||||
/* if(fDistance > fMaxViewDist)//*m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].f MaxViewDistRatio*GetCVars()->e_lod_ratio)
|
||||
{
|
||||
m_ucAngleSlotId = 255;
|
||||
return false;
|
||||
}*/
|
||||
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
if(!pBody)
|
||||
return false;
|
||||
|
||||
// Vec3d vBoxMin = pBody->m_vBoxMin*m_fScale+m_vPos;
|
||||
//Vec3d vBoxMax = pBody->m_vBoxMax*m_fScale+m_vPos;
|
||||
/* assert(!_EntDrawParams.bAllInFrustum || cam.IsBoxVisible(vBoxMin,vBoxMax)); // test of bAllInFrustum flag
|
||||
|
||||
if( bNotAllIN && !cam.IsBoxVisibleFast( vBoxMin, vBoxMax)) // NOTE: bNotAllIN can work wrong
|
||||
{
|
||||
m_ucAngleSlotId = 255;
|
||||
return;
|
||||
}*/
|
||||
|
||||
// int nLastVisibleFrameID = m_OcclTestVars.nLastVisibleFrameID;
|
||||
//assert(m_pObjManager->m_nRenderStackLevel || nLastVisibleFrameID != GetFrameID());
|
||||
|
||||
// recursion is handeled inside IsBoxOccluded()
|
||||
// if(m_pObjManager->IsBoxOccluded(vBoxMin, vBoxMax, m_fDistance, &m_OcclTestVars))
|
||||
// return;
|
||||
|
||||
// calculate switch to sprite distance
|
||||
float near_far_dist = (18.f * pBody->GetRadiusVert() * m_fScale)
|
||||
* max(0.5f,m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fSpriteDistRatio)
|
||||
+ 0.2f*(float)fabs((m_vPos.z + pBody->GetCenter().z*m_fScale) - vCamPos.z);
|
||||
/*
|
||||
static float fAverageSpriteDistRatio = 0.5f;
|
||||
fAverageSpriteDistRatio += m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fSpriteDistRatio;//(fAverageSpriteDistRatio + m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fSpriteDistRatio)*0.5f;
|
||||
if(m_nStatObjNumPerFrame%10000==0)
|
||||
GetLog()->Log("m_nStatObjNumPerFrame = %.4f",fAverageSpriteDistRatio/m_nStatObjNumPerFrame);
|
||||
*/
|
||||
near_far_dist *= GetCVars()->e_vegetation_sprites_distance_ratio;
|
||||
|
||||
int nDynMask = _EntDrawParams.nDLightMask;
|
||||
|
||||
// remove sun bit
|
||||
list2<CDLight> * pSources = ((C3DEngine*)m_p3DEngine)->GetDynamicLightSources();
|
||||
for(int i=0; i<pSources->Count(); i++)
|
||||
{
|
||||
CDLight * pDynLight = pSources->Get(i);
|
||||
assert(pDynLight->m_Id == i || pDynLight->m_Id == -1);
|
||||
if(pDynLight->m_Flags & DLF_SUN)
|
||||
{
|
||||
nDynMask &= ~(1<<pDynLight->m_Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(near_far_dist < GetCVars()->e_vegetation_sprites_min_distance)
|
||||
near_far_dist = GetCVars()->e_vegetation_sprites_min_distance;
|
||||
|
||||
// m_nStatObjNumPerFrame++;
|
||||
|
||||
// fade out bending amount
|
||||
if(!m_pObjManager->m_nRenderStackLevel && m_fCurrentBending > 0)
|
||||
m_fCurrentBending -= GetTimer()->GetFrameTime()*0.25f;
|
||||
if(m_fCurrentBending < 0)
|
||||
m_fCurrentBending = 0;
|
||||
|
||||
// calculate exact dynamic light mask
|
||||
/* uint nThisDynLightMaskNoSun = nDynLightMaskNoSun;
|
||||
if(nThisDynLightMaskNoSun)
|
||||
{
|
||||
m_pObjManager->m_p3DEngine->CheckDistancesToLightSources(nThisDynLightMaskNoSun,
|
||||
pBody->GetCenter()*m_fScale+m_vPos, pBody->GetRadius()*m_fScale);
|
||||
if(nThisDynLightMaskNoSun) // increase sprite distance if object affected by dynamic light
|
||||
near_far_dist *= 2.5f;
|
||||
}*/
|
||||
|
||||
|
||||
// detect lod switch soon
|
||||
const float fLodSwitchCountDown = GetCVars()->e_vegetation_sprites_slow_switch ?
|
||||
min(1.f, fabsf(fDistance - near_far_dist)/(near_far_dist*0.33f)) : 1.f;
|
||||
|
||||
if(!m_pObjManager->m_nRenderStackLevel)
|
||||
{ // calculate bending amount
|
||||
if(m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fBending)
|
||||
{
|
||||
float fBending = GetBendingRandomFactor() * m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fBending;
|
||||
m_fFinalBending = min(1.5f, 2.5f*(m_fCurrentBending + m_pObjManager->m_fWindForce)*fBending) / (pBody->GetRadiusVert()*m_fScale) * 1.8f;
|
||||
m_fFinalBending *= fLodSwitchCountDown;
|
||||
}
|
||||
else
|
||||
m_fFinalBending = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if(pBody->m_bStreamable && CStatObj::m_fStreamingTimePerFrame<CGF_STREAMING_MAX_TIME_PER_FRAME)
|
||||
if(!pBody->GetLeafBuffer() || !pBody->m_nLoadedTrisCount)
|
||||
if(GetCVars()->e_stream_cgf && GetCVars()->e_stream_for_visuals)
|
||||
{ // streaming
|
||||
CStatObj::m_fStreamingTimePerFrame -= GetTimer()->GetAsyncCurTime();
|
||||
bool bRes = pBody->Load(
|
||||
pBody->m_szFileName,
|
||||
pBody->m_szGeomName[0] ? pBody->m_szGeomName : 0,
|
||||
pBody->m_eVertsSharing,
|
||||
pBody->m_bLoadAdditinalInfo,
|
||||
pBody->m_bKeepInLocalSpace, false);
|
||||
pBody->m_bStreamable=true;*/
|
||||
/*
|
||||
if(pBody->GetLeafBuffer() && !((CStatObj*)pBody)->IsSpritesCreated())
|
||||
((CStatObj*)pBody)->UpdateCustomLightingSpritesAndShadowMaps(
|
||||
m_pObjManager->m_vOutdoorAmbientColor,
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].nSpriteTexRes,
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fBackSideLevel,
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bCalcLighting );
|
||||
*/
|
||||
/* CStatObj::m_fStreamingTimePerFrame += GetTimer()->GetAsyncCurTime();
|
||||
}
|
||||
|
||||
|
||||
pBody->m_nLastRendFrameId = GetFrameID();
|
||||
*/
|
||||
|
||||
// do we need only 3d version
|
||||
bool bUse3DOnly(!m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bUseSprites || nDynMask);
|
||||
|
||||
// detect intersection with fog volume, note: use only center
|
||||
// todo: do not calculate every frame and merge all if(!m_pObjManager->m_nRenderStackLevel) stuff
|
||||
/* if(!m_pObjManager->m_nRenderStackLevel)
|
||||
{
|
||||
if(pFogVolume && pFogVolume->InsideBBox((vBoxMin+vBoxMax)*0.5f))
|
||||
m_nFogVolumeID = pFogVolume->nRendererVolumeID;
|
||||
else
|
||||
m_nFogVolumeID = 0;
|
||||
}*/
|
||||
|
||||
// render object in 3d
|
||||
if( bUse3DOnly || fDistance < near_far_dist )
|
||||
{
|
||||
SRendParams rParms;
|
||||
|
||||
// set sort offset
|
||||
rParms.fCustomSortOffset = m_pObjManager->GetSortOffset(m_vPos,vCamPos);
|
||||
|
||||
rParms.nFogVolumeID = m_nFogVolumeID;
|
||||
|
||||
if(GetRenderer()->EF_GetHeatVision())
|
||||
{
|
||||
rParms.nShaderTemplate = EFT_HEATVISION;
|
||||
rParms.vAmbientColor = Vec3d(0.1f, 0.1f, 0.1f);
|
||||
}
|
||||
else
|
||||
rParms.vAmbientColor = _EntDrawParams.vAmbientColor;
|
||||
|
||||
rParms.vPos = m_vPos;
|
||||
rParms.fScale = m_fScale;
|
||||
rParms.nDLightMask = nDynMask;
|
||||
rParms.nStrongestDLightMask = nDynMask & _EntDrawParams.nStrongestDLightMask;
|
||||
|
||||
// bending
|
||||
// if (useBending == 2)
|
||||
rParms.fBending = m_fFinalBending;
|
||||
|
||||
// fade heat amount
|
||||
rParms.fHeatAmount = min(2.f*(1.f - fDistance/near_far_dist),1.f);
|
||||
|
||||
// set alpha blend
|
||||
if( m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bUseAlphaBlending )
|
||||
{
|
||||
rParms.nSortValue = eS_TerrainDetailObjects;
|
||||
if(m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bUseSprites)
|
||||
{ // set fixed alpha
|
||||
rParms.fAlpha = 0.99f;
|
||||
}
|
||||
else
|
||||
{ // fade alpha on distance
|
||||
// float fAlpha = 1.f - fDistance / (fMaxViewDist);//*m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fMaxViewDistRati o);
|
||||
// rParms.fAlpha = min(0.99f,fAlpha*3);
|
||||
rParms.fAlpha = min(0.99f,_EntDrawParams.fAlpha);
|
||||
}
|
||||
|
||||
// entire object will use alpha blending so lets use only one light for it
|
||||
rParms.nDLightMask = rParms.nStrongestDLightMask;
|
||||
}
|
||||
else
|
||||
{ // no alpha blend
|
||||
rParms.fAlpha = 1.f;
|
||||
rParms.nSortValue = 0;
|
||||
}
|
||||
|
||||
if(!GetCVars()->e_vegetation_debug)
|
||||
{ // ignore editor colors per instance
|
||||
rParms.vColor = Vec3d(CHAR_TO_FLOAT,CHAR_TO_FLOAT,CHAR_TO_FLOAT)*max((float)m_ucBright,32.f);
|
||||
rParms.vColor *= m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fBrightness;
|
||||
rParms.vColor.CheckMin(Vec3d(1,1,1));
|
||||
}
|
||||
|
||||
// use custom position when render into shadowmap
|
||||
if(_EntDrawParams.dwFObjFlags & FOB_RENDER_INTO_SHADOWMAP)
|
||||
rParms.vPos = _EntDrawParams.vPos;
|
||||
|
||||
// assign custom template
|
||||
rParms.nShaderTemplate = _EntDrawParams.nShaderTemplate;
|
||||
|
||||
// Assign ovverride material.
|
||||
rParms.pMaterial = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].pMaterial;
|
||||
|
||||
// before switching into sprite - orient 3d object to much sprite image
|
||||
Matrix44 objMatrix;
|
||||
if(fLodSwitchCountDown<1.f && !m_pObjManager->m_nRenderStackLevel && !bUse3DOnly)
|
||||
{
|
||||
CStatObj * pBodyLow = pBody;
|
||||
if(pBody->m_nLoadedLodsNum && pBody->m_arrpLowLODs[pBody->m_nLoadedLodsNum-1])
|
||||
pBodyLow = pBody->m_arrpLowLODs[pBody->m_nLoadedLodsNum-1];
|
||||
|
||||
const float rad2deg = 180.0f/3.14159f;
|
||||
const float far_tex_angle = (360.f/FAR_TEX_COUNT/2);
|
||||
float DX = m_vPos.x + pBodyLow->GetCenter().x*m_fScale - vCamPos.x;
|
||||
float DY = m_vPos.y + pBodyLow->GetCenter().y*m_fScale - vCamPos.y;
|
||||
float DZ = m_vPos.z + pBodyLow->GetCenter().z*m_fScale - vCamPos.z;
|
||||
float fRealAngle = rad2deg*cry_atan2f( DX, DY );
|
||||
while(fRealAngle<0) fRealAngle+=360;
|
||||
while(fRealAngle>=360) fRealAngle-=360;
|
||||
assert(fRealAngle>=0 && fRealAngle<360.f);
|
||||
float fNewAngle = (float)int(fRealAngle/FAR_TEX_ANGLE+0.5f)*FAR_TEX_ANGLE;
|
||||
/* if(fPrevDist0 >= m_fDistance0 &&
|
||||
m_ucAngleSlotId!=255 &&
|
||||
nLastVisibleFrameID == GetFrameID()-1) // if camera move closer - continue to use last sprite angle
|
||||
fNewAngle = (float)int(m_ucAngleSlotId)*FAR_TEX_ANGLE;
|
||||
else*/
|
||||
m_ucAngleSlotId = int(fRealAngle/FAR_TEX_ANGLE+0.5f);
|
||||
|
||||
float fDiffAngle = fNewAngle - fRealAngle;
|
||||
while(fDiffAngle > 180)
|
||||
fDiffAngle-=360;
|
||||
while(fDiffAngle <= -180)
|
||||
fDiffAngle+=360;
|
||||
|
||||
// assert(fDiffAngle<=0.5f*FAR_TEX_ANGLE); // can fail if we continue to use sprite angle
|
||||
|
||||
float fAngle1 = fDiffAngle*(1.f-fLodSwitchCountDown);
|
||||
float fAngle2 = cry_atanf(DZ/fDistance)*gf_RADTODEG*(1.f-fLodSwitchCountDown);
|
||||
|
||||
objMatrix.SetIdentity();
|
||||
objMatrix=GetTranslationMat(rParms.vPos+pBodyLow->GetCenter()*m_fScale)*objMatrix;
|
||||
|
||||
objMatrix=Matrix44::CreateRotationZYX(-gf_DEGTORAD*Vec3d(0,0,-fRealAngle))*objMatrix; //NOTE: angles in radians and negated
|
||||
objMatrix=Matrix44::CreateRotationZYX(-gf_DEGTORAD*Vec3d(fAngle2,0,0))*objMatrix; //NOTE: angles in radians and negated
|
||||
objMatrix=Matrix44::CreateRotationZYX( gf_DEGTORAD*Vec3d(0,0,-fRealAngle))*objMatrix; //NOTE: angles in radians and negated
|
||||
|
||||
|
||||
objMatrix = Matrix44::CreateRotationZYX(-gf_DEGTORAD*Vec3d(0,0,fAngle1))*objMatrix; //NOTE: angles in radians and negated
|
||||
objMatrix = GetTranslationMat(-pBodyLow->GetCenter()*m_fScale)*objMatrix;
|
||||
objMatrix = Matrix33::CreateScale( Vec3d(rParms.fScale,rParms.fScale,rParms.fScale) )*objMatrix;
|
||||
rParms.pMatrix = &objMatrix;
|
||||
rParms.dwFObjFlags |= FOB_TRANS_MASK;
|
||||
}
|
||||
else
|
||||
rParms.dwFObjFlags |= FOB_TRANS_TRANSLATE | FOB_TRANS_SCALE;
|
||||
|
||||
rParms.pShadowMapCasters = _EntDrawParams.pShadowMapCasters;
|
||||
rParms.dwFObjFlags |= (_EntDrawParams.dwFObjFlags & ~FOB_TRANS_MASK);
|
||||
|
||||
// calculate lod and render the object
|
||||
int nLod = max(0,(int)(fDistance*GetLodRatioNormilized()/(GetCVars()->e_obj_lod_ratio*GetRenderRadius())));
|
||||
pBody->Render( rParms, Vec3(zero), nLod );//int(fDistance/near_far_dist*pBody->m_nLoadedLodsNum*pBody->m_nLoadedLodsNum) );
|
||||
|
||||
/*{ // speed test, render tree directly without shader pipeline - no speed difference
|
||||
GetRenderer()->PushMatrix();
|
||||
GetRenderer()->TranslateMatrix(rParms.vPos);
|
||||
GetRenderer()->EnableAlphaTest(true,0.5f);
|
||||
GetRenderer()->SetCullMode(R_CULL_NONE);
|
||||
CLeafBuffer *lb = pBody->GetLeafBuffer();
|
||||
for (int i=0; i<lb->m_pMats->Count(); i++)
|
||||
{
|
||||
CMatInfo * pMatInfo = &(*lb->m_pMats)[i];
|
||||
IShader * e = (*lb->m_pMats)[i].pShader;
|
||||
GetRenderer()->SetTexture(e->GetTexId());
|
||||
GetRenderer()->DrawBuffer(lb->m_pVertexBuffer, &lb->m_Indices[pMatInfnFirstIndexId], pMatInfnNumIndices, 0);
|
||||
}
|
||||
|
||||
GetRenderer()->PopMatrix();
|
||||
}*/
|
||||
|
||||
// add object occlusion volume to the coverage buffer
|
||||
if( fDistance<COVERAGEBUFFER_OCCLUDERS_MAX_DISTANCE &&
|
||||
GetCVars()->e_cbuffer && pBody->GetLoadedTrisCount()==12 )
|
||||
{
|
||||
Vec3d vTopMax = m_vPos + pBody->m_vBoxMax*m_fScale;
|
||||
Vec3d vTopMin = m_vPos + pBody->m_vBoxMin*m_fScale;
|
||||
m_pObjManager->m_pCoverageBuffer->AddBBox(vTopMin,vTopMax,vCamPos-m_vPos);
|
||||
}
|
||||
}
|
||||
else // process sprite
|
||||
if( !bUse3DOnly && fDistance > near_far_dist)
|
||||
{ // add to the list of far objects
|
||||
if(m_pObjManager->m_lstFarObjects[m_pObjManager->m_nRenderStackLevel].Count()<16384)
|
||||
{
|
||||
if(!m_pObjManager->m_nRenderStackLevel)
|
||||
{
|
||||
if(fLodSwitchCountDown<1.f)
|
||||
{
|
||||
float DZ = m_vPos.z + pBody->GetCenter().z*m_fScale - vCamPos.z;
|
||||
float fAngle2 = -cry_atanf(DZ/fDistance)*(1.f-fLodSwitchCountDown);
|
||||
fAngle2 = max(0,min(1,(fAngle2+0.5f)));
|
||||
m_ucLodAngle = uchar(fAngle2*255.f);
|
||||
}
|
||||
else
|
||||
m_ucLodAngle = 127;
|
||||
}
|
||||
|
||||
m_pObjManager->m_lstFarObjects[m_pObjManager->m_nRenderStackLevel].Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CObjManager * CStatObjInst::m_pObjManager = 0;
|
||||
Vec3d CStatObjInst::m_vAngles(0,0,0);
|
||||
|
||||
void CStatObjInst::GetRenderBBox(Vec3d & vBoxMin,Vec3d & vBoxMax)
|
||||
{
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
if(pBody)
|
||||
{
|
||||
vBoxMin = pBody->m_vBoxMin*m_fScale+m_vPos;
|
||||
vBoxMax = pBody->m_vBoxMax*m_fScale+m_vPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
vBoxMin = m_vPos-Vec3d(1,1,1);
|
||||
vBoxMax = m_vPos+Vec3d(1,1,1);
|
||||
}
|
||||
}
|
||||
|
||||
float CStatObjInst::GetRenderRadius(void) const
|
||||
{
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
if(pBody)
|
||||
return pBody->GetRadius()*m_fScale;
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IStatObj * CStatObjInst::GetEntityStatObj( unsigned int nSlot, Matrix44 * pMatrix, bool bReturnOnlyVisible )
|
||||
{
|
||||
if(pMatrix)
|
||||
{
|
||||
Matrix33diag diag = Vec3d( GetScale(),GetScale(),GetScale() ); //use diag-matrix for scaling
|
||||
Matrix34 rt34 = Matrix34::CreateRotationXYZ(gf_DEGTORAD*GetAngles(1), GetPos(true) ); //set scaling and translation in one function call
|
||||
Matrix44 mat1 = rt34*diag; //optimised concatenation: m34*diag
|
||||
*pMatrix = GetTransposed44(mat1); //TODO: remove this after E3 and use Matrix34 instead of Matrix44
|
||||
}
|
||||
|
||||
return m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
}
|
||||
|
||||
CStatObj* CStatObjInst::GetStatObj() const
|
||||
{
|
||||
return m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
}
|
||||
|
||||
float CStatObjInst::GetMaxViewDist()
|
||||
{
|
||||
if (GetStatObj())
|
||||
return max(GetCVars()->e_obj_min_view_dist, GetStatObj()->GetRadius()*m_fScale*GetCVars()->e_obj_view_dist_ratio*GetViewDistRatioNormilized());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float CStatObjInst::GetViewDistRatioNormilized()
|
||||
{
|
||||
assert(GetStatObj());
|
||||
return m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].fMaxViewDistRatio;
|
||||
}
|
||||
|
||||
void CStatObjInst::Physicalize( bool bInstant )
|
||||
{
|
||||
assert(m_nObjectTypeID>=0);
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
if(!pBody || !pBody->IsPhysicsExist())
|
||||
return;
|
||||
|
||||
bool bHideability = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bHideability;
|
||||
bool bPhysNonColl = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bPhysNonColl;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Not create instance if no physical geometry.
|
||||
if(!pBody->m_arrPhysGeomInfo[0])
|
||||
if(!(pBody->m_arrPhysGeomInfo[1] && bHideability))
|
||||
if(!(pBody->m_arrPhysGeomInfo[2] && bPhysNonColl))
|
||||
return;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!GetCVars()->e_on_demand_physics)
|
||||
bInstant = true;
|
||||
|
||||
/*
|
||||
if( m_pObjManager->m_lstStaticTypes[nObjectTypeID].fSpriteDistRatio == 0 )
|
||||
return; // do not phys 'sprite only' trees
|
||||
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[nObjectTypeID].GetStatObj();
|
||||
bool bHideability = m_pObjManager->m_lstStaticTypes[nObjectTypeID].bHideability;
|
||||
|
||||
if(pBody && pBody->GetRadius()*m_fScale < 1.f && pBody->GetRadius())
|
||||
return;
|
||||
*/
|
||||
if (!bInstant)
|
||||
{
|
||||
pe_status_placeholder spc;
|
||||
if (m_pPhysEnt && m_pPhysEnt->GetStatus(&spc) && spc.pFullEntity)
|
||||
GetSystem()->GetIPhysicalWorld()->DestroyPhysicalEntity(spc.pFullEntity);
|
||||
|
||||
pe_params_bbox pbb;
|
||||
pbb.BBox[0] = m_vWSBoxMin;
|
||||
pbb.BBox[1] = m_vWSBoxMax;
|
||||
pe_params_foreign_data pfd;
|
||||
pfd.pForeignData = this;
|
||||
pfd.iForeignData = 1;
|
||||
|
||||
if (!m_pPhysEnt)
|
||||
m_pPhysEnt = GetSystem()->GetIPhysicalWorld()->CreatePhysicalPlaceholder(PE_STATIC,&pbb);
|
||||
else
|
||||
m_pPhysEnt->SetParams(&pbb);
|
||||
m_pPhysEnt->SetParams(&pfd);
|
||||
return;
|
||||
}
|
||||
|
||||
pBody->CheckLoaded();
|
||||
|
||||
// create new
|
||||
pe_params_pos par_pos;
|
||||
if (!m_pPhysEnt)
|
||||
{
|
||||
m_pPhysEnt = GetSystem()->GetIPhysicalWorld()->CreatePhysicalEntity(PE_STATIC,NULL,this,1);
|
||||
if(!m_pPhysEnt)
|
||||
return;
|
||||
}
|
||||
else if (bInstant) // this is on-demand creation, so entity pointer is automatically put into the placeholder
|
||||
GetSystem()->GetIPhysicalWorld()->CreatePhysicalEntity(PE_STATIC,5.0f);
|
||||
|
||||
pe_action_remove_all_parts remove_all;
|
||||
m_pPhysEnt->Action(&remove_all);
|
||||
|
||||
pe_geomparams params;
|
||||
// collidable
|
||||
if(pBody->m_arrPhysGeomInfo[0])
|
||||
m_pPhysEnt->AddGeometry(pBody->m_arrPhysGeomInfo[0], ¶ms);
|
||||
|
||||
params.flags = geom_colltype_ray;
|
||||
|
||||
// obstruct
|
||||
if(pBody->m_arrPhysGeomInfo[1] && bHideability)
|
||||
m_pPhysEnt->AddGeometry(pBody->m_arrPhysGeomInfo[1], ¶ms);
|
||||
|
||||
// leaves
|
||||
if(pBody->m_arrPhysGeomInfo[2] && bPhysNonColl)
|
||||
m_pPhysEnt->AddGeometry(pBody->m_arrPhysGeomInfo[2], ¶ms);
|
||||
|
||||
if(bHideability)
|
||||
{
|
||||
pe_params_foreign_data foreignData;
|
||||
m_pPhysEnt->GetParams(&foreignData);
|
||||
foreignData.iForeignFlags |= PFF_HIDABLE;
|
||||
m_pPhysEnt->SetParams(&foreignData);
|
||||
}
|
||||
|
||||
par_pos.pos = m_vPos;
|
||||
par_pos.q.SetRotationXYZ( Vec3(0.f,0.f,0.f) );
|
||||
par_pos.scale = m_fScale;
|
||||
m_pPhysEnt->SetParams(&par_pos);
|
||||
}
|
||||
|
||||
CStatObjInst::~CStatObjInst()
|
||||
{
|
||||
Dephysicalize( );
|
||||
// Get3DEngine()->UnRegisterEntity(this);
|
||||
Get3DEngine()->FreeEntityRenderState(this);
|
||||
|
||||
if(GetEntityRS() && GetEntityRS()->pShadowMapInfo)
|
||||
GetEntityRS()->pShadowMapInfo->pShadowMapFrustumContainer = 0; // here was a pointer structure allocated in CStatObj
|
||||
}
|
||||
|
||||
void CStatObjInst::Dematerialize( )
|
||||
{
|
||||
}
|
||||
|
||||
void CStatObjInst::Dephysicalize( )
|
||||
{
|
||||
// delete old physics
|
||||
if(m_pPhysEnt)
|
||||
GetSystem()->GetIPhysicalWorld()->DestroyPhysicalEntity(m_pPhysEnt);
|
||||
m_pPhysEnt=0;
|
||||
}
|
||||
|
||||
int CStatObjInst::GetMemoryUsage()
|
||||
{
|
||||
return sizeof(*this) + (m_pEntityRenderState ? sizeof(*m_pEntityRenderState) : 0);
|
||||
}
|
||||
|
||||
unsigned int CStatObjInst::GetRndFlags()
|
||||
{
|
||||
assert(m_nObjectTypeID>=0 && m_nObjectTypeID<m_pObjManager->m_lstStaticTypes.Count());
|
||||
return m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].m_dwRndFlags;
|
||||
}
|
||||
|
||||
void CStatObjInst::SetRndFlags(unsigned int dwFlags)
|
||||
{
|
||||
assert(m_nObjectTypeID>=0 && m_nObjectTypeID<m_pObjManager->m_lstStaticTypes.Count());
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].m_dwRndFlags = dwFlags;
|
||||
}
|
||||
|
||||
void CStatObjInst::SetRndFlags(unsigned int dwFlags, bool bEnable)
|
||||
{
|
||||
assert(m_nObjectTypeID>=0 && m_nObjectTypeID<m_pObjManager->m_lstStaticTypes.Count());
|
||||
|
||||
if(bEnable)
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].m_dwRndFlags |= dwFlags;
|
||||
else
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].m_dwRndFlags &= ~dwFlags;
|
||||
}
|
||||
|
||||
/*
|
||||
ShadowMapFrustum * CStatObjInst::GetShadowMapFrustum()
|
||||
{
|
||||
if(m_nObjectTypeID<0 && m_nObjectTypeID>=m_pObjManager->m_lstStaticTypes.Count())
|
||||
return 0;
|
||||
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
|
||||
if(pBody && pBody->m_pSMLSource && pBody->m_pSMLSource->m_LightFrustums.Count())
|
||||
return &(pBody->m_pSMLSource->m_LightFrustums[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
struct ShadowMapLightSource * CStatObjInst::GetShadowMapFrustumContainer()
|
||||
{
|
||||
if(m_nObjectTypeID<0 && m_nObjectTypeID >= m_pObjManager->m_lstStaticTypes.Count())
|
||||
return 0;
|
||||
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
|
||||
if(pBody)
|
||||
return pBody->m_pSMLSource;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
list2<ShadowMapLightSourceInstance> * CStatObjInst::GetShadowMapCasters()
|
||||
{
|
||||
if(!m_pEntityRenderState || !m_pEntityRenderState->pShadowMapInfo)
|
||||
return 0;
|
||||
|
||||
if(!m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters || !m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters->Count())
|
||||
{
|
||||
if(m_nObjectTypeID<0 && m_nObjectTypeID >= m_pObjManager->m_lstStaticTypes.Count())
|
||||
return 0;
|
||||
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
|
||||
if(!m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters)
|
||||
m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters = new list2<ShadowMapLightSourceInstance>;
|
||||
else
|
||||
m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters->Clear();
|
||||
|
||||
ShadowMapLightSourceInstance LightSourceInfo;
|
||||
LightSourceInfo.m_pLS = pBody->m_pSMLSource;
|
||||
LightSourceInfo.m_vProjTranslation = m_vPos;
|
||||
LightSourceInfo.m_fProjScale = m_fScale;
|
||||
LightSourceInfo.m_fDistance = 0;
|
||||
m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters->Add(LightSourceInfo);
|
||||
}
|
||||
|
||||
// update shadow every frame for nice shadow animations
|
||||
if(GetCVars()->e_vegetation_update_shadow_every_frame && !m_nRenderStackLevel)
|
||||
if(m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].bUpdateShadowEveryFrame)
|
||||
if(float fMaxShadowDist = GetRenderRadius()*GetCVars()->e_shadow_maps_view_dist_ratio)
|
||||
{
|
||||
float fDistFade = m_arrfDistance[m_nRenderStackLevel]/fMaxShadowDist;
|
||||
float fBending = m_fFinalBending * (1.f-fDistFade);
|
||||
if(fDistFade<0.3333f)
|
||||
{
|
||||
CStatObj * pBody = m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj();
|
||||
if(pBody && pBody->m_pSMLSource && pBody->m_pSMLSource->GetShadowMapFrustum())
|
||||
{
|
||||
pBody->m_pSMLSource->GetShadowMapFrustum()->bUpdateRequested = true;
|
||||
if(fBending > pBody->m_pSMLSource->GetShadowMapFrustum()->m_fBending)
|
||||
pBody->m_pSMLSource->GetShadowMapFrustum()->m_fBending = fBending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_pEntityRenderState->pShadowMapInfo->pShadowMapCasters;
|
||||
}
|
||||
|
||||
void CStatObjInst::PreloadInstanceResources(Vec3d vPrevPortalPos, float fPrevPortalDistance, float fTime)
|
||||
{
|
||||
if(!GetEntityStatObj(0) || !GetEntityStatObj(0)->GetLeafBuffer())
|
||||
return;
|
||||
|
||||
float fDist = fPrevPortalDistance + m_vPos.GetDistance(vPrevPortalPos);
|
||||
|
||||
float fMaxViewDist = GetMaxViewDist();
|
||||
if(fDist<fMaxViewDist && fDist<GetViewCamera().GetZMax())
|
||||
GetEntityStatObj(0)->PreloadResources(fDist,fTime,0);
|
||||
}
|
||||
|
||||
const char *CStatObjInst::GetName() const
|
||||
{
|
||||
return (m_nObjectTypeID>=0 && m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj() )?
|
||||
m_pObjManager->m_lstStaticTypes[m_nObjectTypeID].GetStatObj()->GetFileName() : "StatObjNotSet";
|
||||
}
|
||||
88
Cry3DEngine/Vegetation.h
Normal file
88
Cry3DEngine/Vegetation.h
Normal file
@@ -0,0 +1,88 @@
|
||||
//! Info about instance of static object (trees, rocks),
|
||||
//! Every sector contain list of such structures
|
||||
class CStatObjInst : public IEntityRender, public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
Vec3d m_vPos;
|
||||
float m_fScale;
|
||||
float m_fCurrentBending;
|
||||
float m_fFinalBending;
|
||||
IPhysicalEntity * m_pPhysEnt;
|
||||
uchar m_nObjectTypeID;
|
||||
uchar m_ucBright;
|
||||
uchar m_ucLodAngle;
|
||||
uchar m_ucAngleSlotId;
|
||||
|
||||
static CObjManager * m_pObjManager;
|
||||
static Vec3d m_vAngles;
|
||||
|
||||
CStatObjInst()
|
||||
{
|
||||
m_nObjectTypeID=0;
|
||||
m_ucBright=0;
|
||||
m_ucLodAngle=0;
|
||||
m_ucAngleSlotId=0;
|
||||
m_vPos.Set(0,0,0);
|
||||
m_fScale=0;
|
||||
m_fCurrentBending=0;
|
||||
m_fFinalBending=0;
|
||||
m_pPhysEnt=0;
|
||||
}
|
||||
|
||||
virtual ~CStatObjInst();
|
||||
|
||||
void Init( const Vec3d vPos, const int nObjectTypeID, const uchar ucBright, const float fScale )
|
||||
{
|
||||
assert(nObjectTypeID<256);
|
||||
m_vPos = vPos;
|
||||
m_nObjectTypeID = nObjectTypeID;
|
||||
m_ucBright = ucBright;
|
||||
m_fScale = fScale;
|
||||
m_fCurrentBending=0;
|
||||
m_fFinalBending=0;
|
||||
m_pPhysEnt = 0;
|
||||
m_ucLodAngle = 127;
|
||||
m_ucAngleSlotId = 255;
|
||||
}
|
||||
|
||||
void SetStatObjGroupId(int nStatObjInstanceGroupId) { m_nObjectTypeID = nStatObjInstanceGroupId; }
|
||||
|
||||
const char *GetEntityClassName(void) const { return "StatObjInst"; }
|
||||
const Vec3d &GetPos(bool) const { return m_vPos; }
|
||||
const Vec3d &GetAngles(int) const { return m_vAngles; }
|
||||
float GetScale(void) const { return m_fScale; }
|
||||
const char *GetName(void) const;
|
||||
void GetRenderBBox(Vec3d &,Vec3d &);
|
||||
float GetRenderRadius(void) const;
|
||||
bool DrawEntity(const SRendParams & rendParams);
|
||||
bool IsStatic(void) const { return true; }
|
||||
bool IsEntityHasSomethingToRender(void) { return true; }
|
||||
bool IsEntityAreasVisible(void) { return true; }
|
||||
IPhysicalEntity *GetPhysics(void) const { return m_pPhysEnt; }
|
||||
void SetPhysics(IPhysicalEntity * pPhysEnt) { m_pPhysEnt = pPhysEnt; }
|
||||
void SetMaterial(IMatInfo *) {}
|
||||
IMatInfo *GetMaterial(void) const { return 0; }
|
||||
|
||||
// bool DrawEntity(const struct SRendParams & _EntDrawParams);//bool bNotAllIN, const CCamera & cam, int nDynLightMaskNoSun, struct VolumeInfo * pFogVolume);
|
||||
float GetBendingRandomFactor();
|
||||
float Interpolate(float& pprev, float& prev, float& next, float& nnext, float ppweight, float pweight, float nweight, float nnweight);
|
||||
void Physicalize( bool bInstant = false );
|
||||
|
||||
virtual float GetMaxViewDist();
|
||||
IStatObj * GetEntityStatObj( unsigned int nSlot, Matrix44 * pMatrix = NULL, bool bReturnOnlyVisible = false);
|
||||
CStatObj *GetStatObj() const;
|
||||
|
||||
virtual void Serialize(bool bSave, ICryPak * pPak, FILE * f);
|
||||
virtual EERType GetEntityRenderType() { return eERType_Vegetation; }
|
||||
void Dephysicalize( );
|
||||
void Dematerialize( );
|
||||
virtual int GetMemoryUsage();
|
||||
|
||||
virtual unsigned int GetRndFlags(); // get flags from StatObjGroup
|
||||
virtual void SetRndFlags(unsigned int dwFlags); // there is no flags in the instance
|
||||
virtual void SetRndFlags(unsigned int dwFlags, bool bEnable); // there is no flags in the instance
|
||||
virtual struct ShadowMapLightSource * GetShadowMapFrustumContainer();
|
||||
virtual list2<struct ShadowMapLightSourceInstance> * GetShadowMapCasters();
|
||||
virtual void PreloadInstanceResources(Vec3d vPrevPortalPos, float fPrevPortalDistance, float fTime);
|
||||
virtual float GetViewDistRatioNormilized();
|
||||
};
|
||||
1468
Cry3DEngine/VisAreaMan.cpp
Normal file
1468
Cry3DEngine/VisAreaMan.cpp
Normal file
File diff suppressed because it is too large
Load Diff
935
Cry3DEngine/VisAreas.cpp
Normal file
935
Cry3DEngine/VisAreas.cpp
Normal file
@@ -0,0 +1,935 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: statobjmandraw.cpp
|
||||
// Version: v1.00
|
||||
// Created: 18/12/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Visibility areas
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "terrain_sector.h"
|
||||
#include "3dengine.h"
|
||||
#include "cbuffer.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
void CVisArea::Update(const Vec3d * pPoints, int nCount, const char * szName, float fHeight, const Vec3d & vAmbientColor, bool bAfectedByOutLights, bool bSkyOnly, const Vec3d & vDynAmbientColor, float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors)
|
||||
{
|
||||
strncpy(m_sName, szName, sizeof(m_sName));
|
||||
strlwr(m_sName);
|
||||
|
||||
m_fHeight = fHeight;
|
||||
m_vAmbColor = vAmbientColor;
|
||||
m_vDynAmbColor = vDynAmbientColor;
|
||||
m_bAfectedByOutLights = bAfectedByOutLights;
|
||||
m_bSkyOnly = bSkyOnly;
|
||||
m_fViewDistRatio = fViewDistRatio;
|
||||
m_bDoubleSide = bDoubleSide;
|
||||
// m_bUseDeepness = bUseDeepness;
|
||||
m_bUseInIndoors = bUseInIndoors;
|
||||
|
||||
m_lstShapePoints.PreAllocate(nCount,nCount);
|
||||
|
||||
if(nCount)
|
||||
memcpy(&m_lstShapePoints[0], pPoints, sizeof(Vec3d)*nCount);
|
||||
|
||||
// update bbox
|
||||
m_vBoxMax=SetMinBB();
|
||||
m_vBoxMin=SetMaxBB();
|
||||
|
||||
for(int i=0; i<nCount; i++)
|
||||
{
|
||||
m_vBoxMax.CheckMax(pPoints[i]);
|
||||
m_vBoxMin.CheckMin(pPoints[i]);
|
||||
|
||||
m_vBoxMax.CheckMax(pPoints[i]+Vec3d(0,0,m_fHeight));
|
||||
m_vBoxMin.CheckMin(pPoints[i]+Vec3d(0,0,m_fHeight));
|
||||
}
|
||||
|
||||
UpdateGeometryBBox();
|
||||
}
|
||||
|
||||
#define PORTAL_GEOM_BBOX_EXTENT 3.f
|
||||
|
||||
void CVisArea::UpdateGeometryBBox()
|
||||
{
|
||||
m_vGeomBoxMax = m_vBoxMax;
|
||||
m_vGeomBoxMin = m_vBoxMin;
|
||||
|
||||
if(IsPortal())
|
||||
{ // fix for big objects passing portal
|
||||
m_vGeomBoxMax+=Vec3d(PORTAL_GEOM_BBOX_EXTENT,PORTAL_GEOM_BBOX_EXTENT,PORTAL_GEOM_BBOX_EXTENT);
|
||||
m_vGeomBoxMin-=Vec3d(PORTAL_GEOM_BBOX_EXTENT,PORTAL_GEOM_BBOX_EXTENT,PORTAL_GEOM_BBOX_EXTENT);
|
||||
}
|
||||
|
||||
for(int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
if(m_lstEntities[STATIC_ENTITIES][i]->IsStatic())
|
||||
{
|
||||
Vec3d vEntBoxMin,vEntBoxMax;
|
||||
m_lstEntities[STATIC_ENTITIES][i]->GetRenderBBox(vEntBoxMin,vEntBoxMax);
|
||||
m_vGeomBoxMin.CheckMin(vEntBoxMin);
|
||||
m_vGeomBoxMax.CheckMax(vEntBoxMax);
|
||||
}
|
||||
}
|
||||
|
||||
void CVisArea::MarkForStreaming()
|
||||
{
|
||||
for(int i=0; i<m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
{
|
||||
if(m_lstEntities[STATIC_ENTITIES][i]->GetEntityStatObj(0))
|
||||
{
|
||||
((CStatObj*)m_lstEntities[STATIC_ENTITIES][i]->GetEntityStatObj(0))->m_nMarkedForStreamingFrameId = GetFrameID()+100;
|
||||
// m_lstEntities[STATIC_ENTITIES][i]->CheckPhysicalized();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CVisArea::CVisArea(bool bLoadedAsAreaBox)
|
||||
{
|
||||
m_vGeomBoxMin=m_vGeomBoxMax=m_vBoxMin=m_vBoxMax=Vec3d(0,0,0);
|
||||
m_sName[0]=0;
|
||||
m_nRndFrameId=-1;
|
||||
m_bActive=true;
|
||||
m_nFogVolumeId=0;
|
||||
m_fHeight=0;
|
||||
m_vAmbColor(0,0,0);
|
||||
m_vDynAmbColor(0,0,0);
|
||||
m_bLoadedAsAreaBox = bLoadedAsAreaBox;
|
||||
m_vConnNormals[0]=m_vConnNormals[1]=Vec3d(0,0,0);
|
||||
m_bAfectedByOutLights = false;
|
||||
m_fDistance=0;
|
||||
m_bSkyOnly=false;
|
||||
m_pOcclCamera=0;
|
||||
m_fViewDistRatio = 100.f;
|
||||
m_bDoubleSide = true;
|
||||
// m_bUseDeepness = false;
|
||||
m_bUseInIndoors = false;
|
||||
memset(m_arrvActiveVerts,0,sizeof(m_arrvActiveVerts));
|
||||
}
|
||||
|
||||
CVisArea::~CVisArea()
|
||||
{
|
||||
Unload();
|
||||
UnregisterDynamicEntities();
|
||||
delete m_pOcclCamera;
|
||||
m_pOcclCamera=0;
|
||||
|
||||
/*
|
||||
for(int nStatic=0; nStatic<2; nStatic++)
|
||||
for(int i=0; i<m_lstEntities[nStatic].Count(); i++)
|
||||
if(m_lstEntities[nStatic][i]->m_pVisArea==this)
|
||||
m_lstEntities[nStatic][i]->m_pVisArea=0;
|
||||
*/
|
||||
}
|
||||
|
||||
bool InsidePolygon(Vec3 *polygon,int N,Vec3 p)
|
||||
{
|
||||
int counter = 0;
|
||||
int i;
|
||||
double xinters;
|
||||
Vec3 p1,p2;
|
||||
|
||||
p1 = polygon[0];
|
||||
for (i=1;i<=N;i++) {
|
||||
p2 = polygon[i % N];
|
||||
if (p.y > min(p1.y,p2.y)) {
|
||||
if (p.y <= max(p1.y,p2.y)) {
|
||||
if (p.x <= max(p1.x,p2.x)) {
|
||||
if (p1.y != p2.y) {
|
||||
xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
|
||||
if (p1.x == p2.x || p.x <= xinters)
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p1 = p2;
|
||||
}
|
||||
|
||||
if (counter % 2 == 0)
|
||||
return(false);
|
||||
else
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool CVisArea::IsPointInsideVisArea(const Vec3d & vPos)
|
||||
{
|
||||
if(Overlap::Point_AABB(vPos, m_vBoxMin, m_vBoxMax))
|
||||
if(InsidePolygon(&m_lstShapePoints[0], m_lstShapePoints.Count(), vPos))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CVisArea::FindVisArea(IVisArea * pAnotherArea, int nMaxReqursion, bool bSkipDisabledPortals)
|
||||
{ // todo: avoid going into parent
|
||||
if(pAnotherArea == this)
|
||||
return true;
|
||||
|
||||
if(nMaxReqursion>0)
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
if(!bSkipDisabledPortals || m_lstConnections[p]->IsActive())
|
||||
if(m_lstConnections[p]->FindVisArea(pAnotherArea, nMaxReqursion-1, bSkipDisabledPortals))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CVisArea::PreloadVisArea(int nMaxReqursion, bool * pbOutdoorFound, CVisArea * pParentToAvoid, Vec3d vPrevPortalPos, float fPrevPortalDistance)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
if(IsPortal())
|
||||
{
|
||||
fPrevPortalDistance += vPrevPortalPos.GetDistance((m_vBoxMin+m_vBoxMax)*0.5f);
|
||||
vPrevPortalPos = (m_vBoxMin+m_vBoxMax)*0.5f;
|
||||
}
|
||||
|
||||
PreloadResources(vPrevPortalPos, fPrevPortalDistance);
|
||||
|
||||
if(IsConnectedToOutdoor())
|
||||
*pbOutdoorFound = true;
|
||||
|
||||
if(nMaxReqursion>0)
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
if(m_lstConnections[p] != pParentToAvoid)
|
||||
if(GetCurTimeSec()>(m_fPreloadStartTime+0.010f)||
|
||||
m_lstConnections[p]->PreloadVisArea(nMaxReqursion-1, pbOutdoorFound, this, vPrevPortalPos, fPrevPortalDistance))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CVisArea::GetVisFrameId()
|
||||
{
|
||||
return m_nRndFrameId;
|
||||
}
|
||||
|
||||
bool CVisArea::IsConnectedToOutdoor()
|
||||
{
|
||||
if(IsPortal()) // check if this portal has just one conection
|
||||
return m_lstConnections.Count()==1;
|
||||
|
||||
// find portals with just one conection
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
{
|
||||
CVisArea * pPortal = m_lstConnections[p];
|
||||
if(pPortal->m_lstConnections.Count()==1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Is2dLinesIntersect(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4)
|
||||
{
|
||||
float ua = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
|
||||
float ub = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
|
||||
return ua>0 && ua<1 && ub>0 && ub<1;
|
||||
}
|
||||
|
||||
Vec3d CVisArea::GetConnectionNormal(CVisArea * pPortal)
|
||||
{
|
||||
// if(strstr(pPortal->m_sName,"ab09_portal11"))
|
||||
// int t=0;
|
||||
|
||||
assert(m_lstShapePoints.Count()>=3);
|
||||
// find side of shape intersecting with portal
|
||||
int nIntersNum = 0;
|
||||
Vec3d arrNormals[2]={Vec3d(0,0,0),Vec3d(0,0,0)};
|
||||
for(int v=0; v<m_lstShapePoints.Count(); v++)
|
||||
{
|
||||
nIntersNum=0;
|
||||
arrNormals[0]=Vec3d(0,0,0);
|
||||
arrNormals[1]=Vec3d(0,0,0);
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count(); p++)
|
||||
{
|
||||
const Vec3d & v0 = m_lstShapePoints[v];
|
||||
const Vec3d & v1 = m_lstShapePoints[(v+1)%m_lstShapePoints.Count()];
|
||||
const Vec3d & p0 = pPortal->m_lstShapePoints[p];
|
||||
const Vec3d & p1 = pPortal->m_lstShapePoints[(p+1)%pPortal->m_lstShapePoints.Count()];
|
||||
|
||||
if(Is2dLinesIntersect(v0.x,v0.y,v1.x,v1.y,p0.x,p0.y,p1.x,p1.y))
|
||||
{
|
||||
Vec3d vNormal = GetNormalized(v0-v1).Cross(Vec3d(0,0,1.f));
|
||||
if(nIntersNum<2)
|
||||
arrNormals[nIntersNum++] = (IsShapeClockwise()) ? -vNormal : vNormal;
|
||||
}
|
||||
}
|
||||
|
||||
if(nIntersNum==2)
|
||||
break;
|
||||
}
|
||||
|
||||
if(nIntersNum == 2 &&
|
||||
//IsEquivalent(arrNormals[0] == arrNormals[1])
|
||||
IsEquivalent(arrNormals[0],arrNormals[1],VEC_EPSILON)
|
||||
)
|
||||
return arrNormals[0];
|
||||
|
||||
{
|
||||
int nBottomPoints=0;
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count() && p<4; p++)
|
||||
if(IsPointInsideVisArea(pPortal->m_lstShapePoints[p]))
|
||||
nBottomPoints++;
|
||||
|
||||
int nUpPoints=0;
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count() && p<4; p++)
|
||||
if(IsPointInsideVisArea(pPortal->m_lstShapePoints[p]+Vec3d(0,0,pPortal->m_fHeight)))
|
||||
nUpPoints++;
|
||||
|
||||
if(nBottomPoints==0 && nUpPoints==4)
|
||||
return Vec3d(0,0,1);
|
||||
|
||||
if(nBottomPoints==4 && nUpPoints==0)
|
||||
return Vec3d(0,0,-1);
|
||||
}
|
||||
|
||||
return Vec3d(0,0,0);
|
||||
}
|
||||
|
||||
bool CVisArea::UpdatePortalCameraScissor(CCamera & cam, list2<Vec3d> * lstVerts, bool bMergeFrustums)
|
||||
{
|
||||
IRenderer * pRend = GetRenderer();
|
||||
CVars * pCVars = GetCVars();
|
||||
|
||||
Vec3d arrScreenSpacePos[8];
|
||||
memset(arrScreenSpacePos,0,sizeof(arrScreenSpacePos));
|
||||
for(int i=0; i<lstVerts->Count() && i<8; i++)
|
||||
{ // result is in range from 0 to 100
|
||||
const Vec3d & v3d = lstVerts->GetAt(i);
|
||||
|
||||
if(pCVars->e_portals == 4)
|
||||
pRend->Draw3dBBox(v3d-Vec3d(0.1f,0.1f,0.1f),v3d+Vec3d(0.1f,0.1f,0.1f));
|
||||
|
||||
pRend->ProjectToScreen(v3d.x, v3d.y, v3d.z,
|
||||
&arrScreenSpacePos[i].x, &arrScreenSpacePos[i].y, &arrScreenSpacePos[i].z);
|
||||
|
||||
arrScreenSpacePos[i].x = arrScreenSpacePos[i].x*pRend->GetWidth()/100.f;
|
||||
arrScreenSpacePos[i].y = arrScreenSpacePos[i].y*pRend->GetHeight()/100.f;
|
||||
}
|
||||
|
||||
// find 2d bounds in screen space
|
||||
Vec3d vMin2d = arrScreenSpacePos[0], vMax2d = arrScreenSpacePos[0];
|
||||
for(int i=0; i<lstVerts->Count() && i<8; i++)
|
||||
{
|
||||
if(arrScreenSpacePos[i].x < vMin2d.x)
|
||||
vMin2d.x = arrScreenSpacePos[i].x;
|
||||
if(arrScreenSpacePos[i].x > vMax2d.x)
|
||||
vMax2d.x = arrScreenSpacePos[i].x;
|
||||
if(arrScreenSpacePos[i].y < vMin2d.y)
|
||||
vMin2d.y = arrScreenSpacePos[i].y;
|
||||
if(arrScreenSpacePos[i].y > vMax2d.y)
|
||||
vMax2d.y = arrScreenSpacePos[i].y;
|
||||
}
|
||||
|
||||
vMin2d.x = max(vMin2d.x,0);
|
||||
vMin2d.y = max(vMin2d.y,0);
|
||||
vMax2d.x = min(vMax2d.x,GetRenderer()->GetWidth());
|
||||
vMax2d.y = min(vMax2d.y,GetRenderer()->GetHeight());
|
||||
|
||||
if(vMax2d.x <= vMin2d.x || vMax2d.y < vMin2d.y)
|
||||
return false;
|
||||
|
||||
assert(vMin2d.x>=0 && vMin2d.x<=GetRenderer()->GetWidth());
|
||||
assert(vMin2d.y>=0 && vMin2d.y<=GetRenderer()->GetHeight());
|
||||
assert(vMax2d.x>=0 && vMax2d.x<=GetRenderer()->GetWidth());
|
||||
assert(vMax2d.y>=0 && vMax2d.y<=GetRenderer()->GetHeight());
|
||||
|
||||
cam.m_ScissorInfo.x1 = ushort(vMin2d.x);
|
||||
cam.m_ScissorInfo.y1 = ushort(vMin2d.y);
|
||||
cam.m_ScissorInfo.x2 = ushort(vMax2d.x);
|
||||
cam.m_ScissorInfo.y2 = ushort(vMax2d.y);
|
||||
|
||||
if(GetCVars()->e_scissor_debug)
|
||||
{
|
||||
float color[] = {1,0,0,1};
|
||||
pRend->Draw2dLabel(vMax2d.x, vMax2d.y, 2 , color, false, "br");
|
||||
pRend->Draw2dLabel(vMin2d.x, vMax2d.y, 2 , color, false, "bl");
|
||||
pRend->Draw2dLabel(vMax2d.x, vMin2d.y, 2 , color, false, "tr");
|
||||
pRend->Draw2dLabel(vMin2d.x, vMin2d.y, 2 , color, false, "tl");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVisArea::UpdatePortalCameraPlanes(CCamera & cam, Vec3d * pVerts, bool bMergeFrustums)
|
||||
{ // todo: do also take into account GetViewCamera()
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
Plane plane;
|
||||
|
||||
plane.CalcPlane(pVerts[0],pVerts[1],pVerts[2]);
|
||||
cam.SetFrustumPlane(FR_PLANE_NEAR, plane);
|
||||
|
||||
plane = *GetViewCamera().GetFrustumPlane(FR_PLANE_FAR);
|
||||
cam.SetFrustumPlane(FR_PLANE_FAR, plane);
|
||||
|
||||
plane.CalcPlane(vCamPos,pVerts[2],pVerts[3]); // update plane only if it reduces fov
|
||||
if(!bMergeFrustums || plane.n.Dot(cam.GetFrustumPlane(FR_PLANE_LEFT)->n)<
|
||||
cam.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam.GetFrustumPlane(FR_PLANE_LEFT)->n))
|
||||
cam.SetFrustumPlane(FR_PLANE_RIGHT, plane);
|
||||
|
||||
plane.CalcPlane(vCamPos,pVerts[0],pVerts[1]); // update plane only if it reduces fov
|
||||
if(!bMergeFrustums || plane.n.Dot(cam.GetFrustumPlane(FR_PLANE_RIGHT)->n)<
|
||||
cam.GetFrustumPlane(FR_PLANE_LEFT)->n.Dot(cam.GetFrustumPlane(FR_PLANE_RIGHT)->n))
|
||||
cam.SetFrustumPlane(FR_PLANE_LEFT, plane);
|
||||
|
||||
plane.CalcPlane(vCamPos,pVerts[3],pVerts[0]); // update plane only if it reduces fov
|
||||
if(!bMergeFrustums || plane.n.Dot(cam.GetFrustumPlane(FR_PLANE_TOP)->n)<
|
||||
cam.GetFrustumPlane(FR_PLANE_BOTTOM)->n.Dot(cam.GetFrustumPlane(FR_PLANE_TOP)->n))
|
||||
cam.SetFrustumPlane(FR_PLANE_BOTTOM, plane);
|
||||
|
||||
plane.CalcPlane(vCamPos,pVerts[1],pVerts[2]); // update plane only if it reduces fov
|
||||
if(!bMergeFrustums || plane.n.Dot(cam.GetFrustumPlane(FR_PLANE_BOTTOM)->n)<
|
||||
cam.GetFrustumPlane(FR_PLANE_TOP)->n.Dot(cam.GetFrustumPlane(FR_PLANE_BOTTOM)->n))
|
||||
cam.SetFrustumPlane(FR_PLANE_TOP, plane);
|
||||
|
||||
Vec3d arrvPortVertsCamSpace[4];
|
||||
for(int i=0; i<4; i++)
|
||||
arrvPortVertsCamSpace[i] = pVerts[i]-cam.GetPos();
|
||||
cam.SetFrustumVertices(arrvPortVertsCamSpace);
|
||||
|
||||
if(GetCVars()->e_portals==4)
|
||||
{
|
||||
float farrColor[4] = {1,1,1,1};
|
||||
// GetRenderer()->SetMaterialColor(1,1,1,1);
|
||||
GetRenderer()->Draw3dBBox(pVerts[0],pVerts[1],DPRIM_LINE);
|
||||
GetRenderer()->DrawLabelEx(pVerts[0],1,farrColor,false,true,"0");
|
||||
GetRenderer()->Draw3dBBox(pVerts[1],pVerts[2],DPRIM_LINE);
|
||||
GetRenderer()->DrawLabelEx(pVerts[1],1,farrColor,false,true,"1");
|
||||
GetRenderer()->Draw3dBBox(pVerts[2],pVerts[3],DPRIM_LINE);
|
||||
GetRenderer()->DrawLabelEx(pVerts[2],1,farrColor,false,true,"2");
|
||||
GetRenderer()->Draw3dBBox(pVerts[3],pVerts[0],DPRIM_LINE);
|
||||
GetRenderer()->DrawLabelEx(pVerts[3],1,farrColor,false,true,"3");
|
||||
}
|
||||
}
|
||||
|
||||
int __cdecl CVisAreaManager__CmpDistToPortal(const void* v1, const void* v2);
|
||||
|
||||
void CVisArea::DrawVolume(CObjManager * pObjManager, int nReqursionLevel,
|
||||
CCamera CurCamera, CVisArea * pParent, CVisArea * pCurPortal,
|
||||
bool * pbOutdoorVisible, list2<CCamera> * plstOutPortCameras, bool * pbSkyVisible)
|
||||
{
|
||||
IRenderer * pRenderer = GetRenderer();
|
||||
|
||||
// mark as rendered
|
||||
if(!pObjManager->m_nRenderStackLevel)
|
||||
m_nRndFrameId = GetFrameID();
|
||||
|
||||
// get area light mask
|
||||
Vec3d vCenter = (m_vBoxMin+m_vBoxMax)*0.5f;
|
||||
float fRadius = (m_vBoxMax-m_vBoxMin).Length()*0.5f;
|
||||
int nDLMask = Get3DEngine()->GetLightMaskFromPosition(vCenter, fRadius);
|
||||
|
||||
// todo: prepare flag once
|
||||
bool bThisIsPortal = strstr(m_sName,"portal") != 0;
|
||||
|
||||
// remove sun bit if it not allowed on exit portal geometry
|
||||
if(!bThisIsPortal || !m_bAfectedByOutLights || m_lstConnections.Count()!=1)
|
||||
for(int nId=0; nId<32; nId++)
|
||||
{
|
||||
if(nDLMask & (1<<nId))
|
||||
{
|
||||
CDLight * pDLight = (CDLight*)pRenderer->EF_Query(EFQ_LightSource, nId);
|
||||
if(pDLight && pDLight->m_Flags & DLF_SUN)
|
||||
{
|
||||
nDLMask = nDLMask & ~(1<<nId);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!pObjManager->m_nRenderStackLevel) // light scissor can not be shared between reqursion levels because same CDlight objects are used
|
||||
if(pDLight && pDLight->m_Flags & DLF_THIS_AREA_ONLY && pDLight->m_pOwner)
|
||||
if(pDLight->m_pOwner->GetEntityVisArea() == this)
|
||||
{
|
||||
if(!pDLight->m_sWidth || pDLight->m_sWidth == (CurCamera.m_ScissorInfo.x2-CurCamera.m_ScissorInfo.x1))
|
||||
{ // first time - set
|
||||
pDLight->m_sX = CurCamera.m_ScissorInfo.x1;
|
||||
pDLight->m_sY = CurCamera.m_ScissorInfo.y1;
|
||||
pDLight->m_sWidth = CurCamera.m_ScissorInfo.x2-CurCamera.m_ScissorInfo.x1;
|
||||
pDLight->m_sHeight = CurCamera.m_ScissorInfo.y2-CurCamera.m_ScissorInfo.y1;
|
||||
}
|
||||
else
|
||||
{ // not first time - merge
|
||||
int nMaxX = max(pDLight->m_sX + pDLight->m_sWidth, CurCamera.m_ScissorInfo.x2);
|
||||
int nMaxY = max(pDLight->m_sY + pDLight->m_sHeight, CurCamera.m_ScissorInfo.y2);
|
||||
pDLight->m_sX = min(pDLight->m_sX, CurCamera.m_ScissorInfo.x1);
|
||||
pDLight->m_sY = min(pDLight->m_sY, CurCamera.m_ScissorInfo.y1);
|
||||
pDLight->m_sWidth = nMaxX - pDLight->m_sX;
|
||||
pDLight->m_sHeight = nMaxY - pDLight->m_sY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render area statics
|
||||
DrawEntities( m_nFogVolumeId, nDLMask, 0, CurCamera,
|
||||
m_lstShapePoints.Count() ? &m_vAmbColor : 0, m_lstShapePoints.Count() ? &m_vDynAmbColor : 0,
|
||||
NULL, true, 0, pObjManager,
|
||||
IsPointInsideVisArea(GetViewCamera().GetPos()), "", STATIC_ENTITIES);
|
||||
|
||||
// render area entities
|
||||
DrawEntities( m_nFogVolumeId, nDLMask, 0, CurCamera,
|
||||
m_lstShapePoints.Count() ? &m_vAmbColor : 0, m_lstShapePoints.Count() ? &m_vDynAmbColor : 0,
|
||||
NULL, true, 0, pObjManager,
|
||||
IsPointInsideVisArea(GetViewCamera().GetPos()), "", DYNAMIC_ENTITIES);
|
||||
|
||||
// limit recursion and portal activity
|
||||
if(!nReqursionLevel || !m_bActive)
|
||||
return;
|
||||
|
||||
if( bThisIsPortal && m_lstConnections.Count()==1 && // detect entrance
|
||||
!IsPointInsideVisArea(GetViewCamera().GetPos()) && // detect camera in outdoors
|
||||
!CurCamera.IsAABBVisibleFast( AABB(m_vGeomBoxMin,m_vGeomBoxMax) )) // if invisible
|
||||
return; // stop recursion
|
||||
|
||||
bool bScisorValid = true;
|
||||
|
||||
// prepare new camera for next areas
|
||||
if(bThisIsPortal && m_lstConnections.Count() && (this!=pCurPortal || !pCurPortal->IsPointInsideVisArea(CurCamera.GetPos())))
|
||||
{
|
||||
Vec3d vPortNorm = (!pParent || pParent == m_lstConnections[0] || m_lstConnections.Count()==1) ?
|
||||
m_vConnNormals[0] : m_vConnNormals[1];
|
||||
|
||||
// exit/entrance portal has only one normal in direction to outdoors, so flip it to the camera
|
||||
if(m_lstConnections.Count()==1 && !pParent)
|
||||
vPortNorm = -vPortNorm;
|
||||
|
||||
// back face check
|
||||
Vec3d vPortToCamDir = CurCamera.GetPos() - (m_vBoxMin+m_vBoxMax)*0.5f;
|
||||
if(vPortToCamDir.Dot(vPortNorm)<0)
|
||||
return;
|
||||
|
||||
if(!m_bDoubleSide)
|
||||
if(vPortToCamDir.Dot(m_vConnNormals[0])<0)
|
||||
return;
|
||||
|
||||
Vec3d arrPortVerts[4];
|
||||
Vec3d arrPortVertsOtherSide[4];
|
||||
bool barrPortVertsOtherSideValid = false;
|
||||
if(pParent && !IsEquivalent(vPortNorm,Vec3d(0,0,0),VEC_EPSILON) && vPortNorm.z)
|
||||
{ // up/down portal
|
||||
int nEven = IsShapeClockwise();
|
||||
if(vPortNorm.z>0)
|
||||
nEven=!nEven;
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
arrPortVerts[i] = m_lstShapePoints[nEven ? (3-i) : i]+Vec3d(0,0,m_fHeight)*(vPortNorm.z>0);
|
||||
arrPortVertsOtherSide[i] = m_lstShapePoints[nEven ? (3-i) : i]+Vec3d(0,0,m_fHeight)*(vPortNorm.z<0);
|
||||
}
|
||||
barrPortVertsOtherSideValid = true;
|
||||
}
|
||||
else if(!IsEquivalent(vPortNorm,Vec3d(0,0,0),VEC_EPSILON) && vPortNorm.z==0)
|
||||
{ // basic portal
|
||||
Vec3d arrInAreaPoint[2]={Vec3d(0,0,0),Vec3d(0,0,0)};
|
||||
int arrInAreaPointId[2]={-1,-1};
|
||||
int nInAreaPointCounter=0;
|
||||
// find 2 points of portal in this area (or in this outdoors)
|
||||
for(int i=0; i<m_lstShapePoints.Count() && nInAreaPointCounter<2; i++)
|
||||
{
|
||||
Vec3d vTestPoint = m_lstShapePoints[i]+Vec3d(0,0,m_fHeight*0.5f);
|
||||
CVisArea * pAnotherArea = m_lstConnections[0];
|
||||
if((pParent && (pParent->IsPointInsideVisArea(vTestPoint))) ||
|
||||
(!pParent && (!pAnotherArea->IsPointInsideVisArea(vTestPoint))) )
|
||||
{
|
||||
arrInAreaPointId[nInAreaPointCounter] = i;
|
||||
arrInAreaPoint[nInAreaPointCounter++] = m_lstShapePoints[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(nInAreaPointCounter==2)
|
||||
{ // success, take into account volume and portal shape versts order
|
||||
int nEven = IsShapeClockwise();
|
||||
if(arrInAreaPointId[1]-arrInAreaPointId[0] != 1)
|
||||
nEven = !nEven;
|
||||
|
||||
arrPortVerts[0] = arrInAreaPoint[nEven];
|
||||
arrPortVerts[1] = arrInAreaPoint[nEven]+Vec3d(0,0,m_fHeight);
|
||||
arrPortVerts[2] = arrInAreaPoint[!nEven]+Vec3d(0,0,m_fHeight);
|
||||
arrPortVerts[3] = arrInAreaPoint[!nEven];
|
||||
|
||||
nEven = !nEven;
|
||||
|
||||
arrPortVertsOtherSide[0] = arrInAreaPoint[nEven];
|
||||
arrPortVertsOtherSide[1] = arrInAreaPoint[nEven]+Vec3d(0,0,m_fHeight);
|
||||
arrPortVertsOtherSide[2] = arrInAreaPoint[!nEven]+Vec3d(0,0,m_fHeight);
|
||||
arrPortVertsOtherSide[3] = arrInAreaPoint[!nEven];
|
||||
barrPortVertsOtherSideValid = true;
|
||||
}
|
||||
else
|
||||
{ // something wrong
|
||||
Warning(0,0,"CVisArea::DrawVolume: Invalid portal: %s", m_sName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(!pParent && vPortNorm.z==0 && m_lstConnections.Count()==1)
|
||||
{ // basic entrance portal
|
||||
Vec3d vBorder = GetNormalized(vPortNorm.Cross(Vec3d(0,0,1.f)))*fRadius;
|
||||
arrPortVerts[0] = vCenter - Vec3d(0,0,1.f)*fRadius - vBorder;
|
||||
arrPortVerts[1] = vCenter + Vec3d(0,0,1.f)*fRadius - vBorder;
|
||||
arrPortVerts[2] = vCenter + Vec3d(0,0,1.f)*fRadius + vBorder;
|
||||
arrPortVerts[3] = vCenter - Vec3d(0,0,1.f)*fRadius + vBorder;
|
||||
}
|
||||
else if(!pParent && vPortNorm.z!=0 && m_lstConnections.Count()==1)
|
||||
{ // up/down entrance portal
|
||||
Vec3d vBorder = GetNormalized(vPortNorm.Cross(Vec3d(0,1,0.f)))*fRadius;
|
||||
arrPortVerts[0] = vCenter - Vec3d(0,1,0.f)*fRadius + vBorder;
|
||||
arrPortVerts[1] = vCenter + Vec3d(0,1,0.f)*fRadius + vBorder;
|
||||
arrPortVerts[2] = vCenter + Vec3d(0,1,0.f)*fRadius - vBorder;
|
||||
arrPortVerts[3] = vCenter - Vec3d(0,1,0.f)*fRadius - vBorder;
|
||||
}
|
||||
else
|
||||
{ // something wrong or areabox portal - use simple solution
|
||||
if(
|
||||
//vPortNorm == Vec3d(0,0,0)
|
||||
IsEquivalent(vPortNorm,Vec3d(0,0,0),VEC_EPSILON)
|
||||
)
|
||||
vPortNorm = GetNormalized((vCenter - GetViewCamera().GetPos()));
|
||||
|
||||
Vec3d vBorder = GetNormalized(vPortNorm.Cross(Vec3d(0,0,1.f)))*fRadius;
|
||||
arrPortVerts[0] = vCenter - Vec3d(0,0,1.f)*fRadius - vBorder;
|
||||
arrPortVerts[1] = vCenter + Vec3d(0,0,1.f)*fRadius - vBorder;
|
||||
arrPortVerts[2] = vCenter + Vec3d(0,0,1.f)*fRadius + vBorder;
|
||||
arrPortVerts[3] = vCenter - Vec3d(0,0,1.f)*fRadius + vBorder;
|
||||
}
|
||||
|
||||
if(GetCVars()->e_portals==4) // make color reqursion dependent
|
||||
GetRenderer()->SetMaterialColor(1,1,pObjManager->m_nRenderStackLevel==0,1);
|
||||
|
||||
CCamera camParent = CurCamera;
|
||||
UpdatePortalCameraPlanes(CurCamera, arrPortVerts, vPortNorm.z==0);
|
||||
|
||||
static list2<Vec3d> lstPortVertsClipped; // Timur, keep this list static so it is not reallocated every time.
|
||||
lstPortVertsClipped.Clear();
|
||||
lstPortVertsClipped.AddList(arrPortVerts, 4);
|
||||
ClipPortalVerticesByCameraFrustum(&lstPortVertsClipped, camParent);
|
||||
|
||||
bScisorValid = UpdatePortalCameraScissor(CurCamera, &lstPortVertsClipped, vPortNorm.z==0);
|
||||
|
||||
if(bScisorValid && barrPortVertsOtherSideValid)
|
||||
{
|
||||
Vec3d vOtherSizeBoxMax = SetMinBB();
|
||||
Vec3d vOtherSizeBoxMin = SetMaxBB();
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
vOtherSizeBoxMin.CheckMin(arrPortVertsOtherSide[i]-Vec3d(0.01f,0.01f,0.01f));
|
||||
vOtherSizeBoxMax.CheckMax(arrPortVertsOtherSide[i]+Vec3d(0.01f,0.01f,0.01f));
|
||||
}
|
||||
|
||||
bScisorValid = CurCamera.IsAABBVisible_exact(AABB(vOtherSizeBoxMin,vOtherSizeBoxMax));
|
||||
}
|
||||
|
||||
if(bScisorValid && pParent && m_lstConnections.Count()==1)
|
||||
{ // set this camera for outdoor
|
||||
if(nReqursionLevel>=1)
|
||||
{
|
||||
if(!m_bSkyOnly)
|
||||
{
|
||||
if(plstOutPortCameras)
|
||||
{
|
||||
plstOutPortCameras->Add(CurCamera);
|
||||
plstOutPortCameras->Last().m_pPortal = this;
|
||||
}
|
||||
if(pbOutdoorVisible)
|
||||
*pbOutdoorVisible = true;
|
||||
}
|
||||
else if(pbSkyVisible)
|
||||
*pbSkyVisible = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// sort portals by distance
|
||||
if(!bThisIsPortal && m_lstConnections.Count())
|
||||
{
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
{
|
||||
CVisArea * pNeibVolume = m_lstConnections[p];
|
||||
pNeibVolume->m_fDistance = CurCamera.GetPos().GetDistance((pNeibVolume->m_vBoxMin+pNeibVolume->m_vBoxMax)*0.5f);
|
||||
}
|
||||
|
||||
qsort(&m_lstConnections[0], m_lstConnections.Count(),
|
||||
sizeof(m_lstConnections[0]), CVisAreaManager__CmpDistToPortal);
|
||||
}
|
||||
|
||||
float fZoomFactor = 0.2f+0.8f*(RAD2DEG(CurCamera.GetFov())/90.f);
|
||||
|
||||
// recurse to connetions
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
{
|
||||
CVisArea * pNeibVolume = m_lstConnections[p];
|
||||
if(pNeibVolume != pParent)
|
||||
{
|
||||
if(!bThisIsPortal)
|
||||
{ // skip far portals
|
||||
float fRadius = (pNeibVolume->m_vBoxMax-pNeibVolume->m_vBoxMin).Length()*0.5f;
|
||||
if(pNeibVolume->m_fDistance*fZoomFactor > fRadius*pNeibVolume->m_fViewDistRatio)
|
||||
continue;
|
||||
}
|
||||
|
||||
if((bScisorValid || m_lstConnections.Count()==1) && (bThisIsPortal || CurCamera.IsAABBVisibleFast( AABB(pNeibVolume->m_vGeomBoxMin,pNeibVolume->m_vGeomBoxMax) )))
|
||||
pNeibVolume->DrawVolume(pObjManager, nReqursionLevel-1, CurCamera, this, pCurPortal, pbOutdoorVisible, plstOutPortCameras, pbSkyVisible);
|
||||
else
|
||||
pNeibVolume->DrawVolume_NotThisAreaOnlyLights(pObjManager, nReqursionLevel-1, CurCamera, this, pCurPortal, pbOutdoorVisible, plstOutPortCameras, pbSkyVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! return list of visareas connected to specified visarea (can return portals and sectors)
|
||||
int CVisArea::GetRealConnections(IVisArea ** pAreas, int nMaxConnNum, bool bSkipDisabledPortals)
|
||||
{
|
||||
int nOut = 0;
|
||||
for(int nArea=0; nArea<m_lstConnections.Count(); nArea++)
|
||||
{
|
||||
if(nOut<nMaxConnNum)
|
||||
pAreas[nOut] = (IVisArea*)m_lstConnections[nArea];
|
||||
nOut++;
|
||||
}
|
||||
return nOut;
|
||||
}
|
||||
|
||||
//! return list of sectors conected to specified sector or portal (returns sectors only)
|
||||
// todo: change the way it returns data
|
||||
int CVisArea::GetVisAreaConnections(IVisArea ** pAreas, int nMaxConnNum, bool bSkipDisabledPortals)
|
||||
{
|
||||
int nOut = 0;
|
||||
if(IsPortal())
|
||||
{
|
||||
/* for(int nArea=0; nArea<m_lstConnections.Count(); nArea++)
|
||||
{
|
||||
if(nOut<nMaxConnNum)
|
||||
pAreas[nOut] = (IVisArea*)m_lstConnections[nArea];
|
||||
nOut++;
|
||||
}*/
|
||||
return min(nMaxConnNum,GetRealConnections(pAreas, nMaxConnNum, bSkipDisabledPortals));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int nPort=0; nPort<m_lstConnections.Count(); nPort++)
|
||||
{
|
||||
CVisArea * pPortal = m_lstConnections[nPort];
|
||||
assert(pPortal->IsPortal());
|
||||
for(int nArea=0; nArea<pPortal->m_lstConnections.Count(); nArea++)
|
||||
{
|
||||
if(pPortal->m_lstConnections[nArea]!=this)
|
||||
if(!bSkipDisabledPortals || pPortal->IsActive())
|
||||
{
|
||||
if(nOut<nMaxConnNum)
|
||||
pAreas[nOut] = (IVisArea*)pPortal->m_lstConnections[nArea];
|
||||
nOut++;
|
||||
break; // take first valid connection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return min(nMaxConnNum,nOut);
|
||||
}
|
||||
|
||||
bool CVisArea::IsPortalValid()
|
||||
{
|
||||
if(m_lstConnections.Count()>2 || m_lstConnections.Count()==0)
|
||||
return false;
|
||||
|
||||
for(int i=0; i<m_lstConnections.Count(); i++)
|
||||
if(IsEquivalent(m_vConnNormals[i],Vec3d(0,0,0),VEC_EPSILON))
|
||||
return false;
|
||||
|
||||
if(m_lstConnections.Count()>1)
|
||||
if( m_vConnNormals[0].Dot(m_vConnNormals[1])>-0.99f )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CVisArea::IsPortalIntersectAreaInValidWay(CVisArea * pPortal)
|
||||
{
|
||||
const Vec3d & v1Min = pPortal->m_vBoxMin;
|
||||
const Vec3d & v1Max = pPortal->m_vBoxMax;
|
||||
const Vec3d & v2Min = m_vBoxMin;
|
||||
const Vec3d & v2Max = m_vBoxMax;
|
||||
|
||||
if(v1Max.x>v2Min.x && v2Max.x>v1Min.x)
|
||||
if(v1Max.y>v2Min.y && v2Max.y>v1Min.y)
|
||||
if(v1Max.z>v2Min.z && v2Max.z>v1Min.z)
|
||||
{
|
||||
// vertical portal
|
||||
for(int v=0; v<m_lstShapePoints.Count(); v++)
|
||||
{
|
||||
int nIntersNum=0;
|
||||
bool arrIntResult[4] = { 0,0,0,0 };
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count() && p<4; p++)
|
||||
{
|
||||
const Vec3d & v0 = m_lstShapePoints[v];
|
||||
const Vec3d & v1 = m_lstShapePoints[(v+1)%m_lstShapePoints.Count()];
|
||||
const Vec3d & p0 = pPortal->m_lstShapePoints[p];
|
||||
const Vec3d & p1 = pPortal->m_lstShapePoints[(p+1)%pPortal->m_lstShapePoints.Count()];
|
||||
|
||||
if(Is2dLinesIntersect(v0.x,v0.y,v1.x,v1.y,p0.x,p0.y,p1.x,p1.y))
|
||||
{
|
||||
nIntersNum++;
|
||||
arrIntResult[p] = true;
|
||||
}
|
||||
}
|
||||
if(nIntersNum==2 && arrIntResult[0]==arrIntResult[2] && arrIntResult[1]==arrIntResult[3])
|
||||
return true;
|
||||
}
|
||||
|
||||
// horisontal portal
|
||||
{
|
||||
int nBottomPoints=0, nUpPoints=0;
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count() && p<4; p++)
|
||||
if(IsPointInsideVisArea(pPortal->m_lstShapePoints[p]))
|
||||
nBottomPoints++;
|
||||
|
||||
for(int p=0; p<pPortal->m_lstShapePoints.Count() && p<4; p++)
|
||||
if(IsPointInsideVisArea(pPortal->m_lstShapePoints[p]+Vec3d(0,0,pPortal->m_fHeight)))
|
||||
nUpPoints++;
|
||||
|
||||
if(nBottomPoints==0 && nUpPoints==4)
|
||||
return true;
|
||||
|
||||
if(nBottomPoints==4 && nUpPoints==0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CVisArea::IsPortal()
|
||||
{
|
||||
bool bThisIsPortal = strstr(m_sName,"portal") != 0;
|
||||
return bThisIsPortal;
|
||||
}
|
||||
/*
|
||||
void CVisArea::SetTreeId(int nTreeId)
|
||||
{
|
||||
if(m_nTreeId == nTreeId)
|
||||
return;
|
||||
|
||||
m_nTreeId = nTreeId;
|
||||
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
m_lstConnections[p]->SetTreeId(nTreeId);
|
||||
}
|
||||
*/
|
||||
bool CVisArea::IsShapeClockwise()
|
||||
{
|
||||
float fClockWise =
|
||||
(m_lstShapePoints[0].x-m_lstShapePoints[1].x)*(m_lstShapePoints[2].y-m_lstShapePoints[1].y)-
|
||||
(m_lstShapePoints[0].y-m_lstShapePoints[1].y)*(m_lstShapePoints[2].x-m_lstShapePoints[1].x);
|
||||
|
||||
return fClockWise>0;
|
||||
}
|
||||
|
||||
void CVisArea::DrawAreaBoundsIntoCBuffer(CCoverageBuffer * pCBuffer)
|
||||
{
|
||||
if(m_lstShapePoints.Count()!=4)
|
||||
return;
|
||||
|
||||
Vec3d arrVerts[8];
|
||||
int arrIndices[24];
|
||||
|
||||
int v=0;
|
||||
int i=0;
|
||||
for(int p=0; p<4 && p<m_lstShapePoints.Count(); p++)
|
||||
{
|
||||
arrVerts[v++] = m_lstShapePoints[p];
|
||||
arrVerts[v++] = m_lstShapePoints[p] + Vec3d(0,0,m_fHeight);
|
||||
|
||||
arrIndices[i++] = (p*2+0)%8;
|
||||
arrIndices[i++] = (p*2+1)%8;
|
||||
arrIndices[i++] = (p*2+2)%8;
|
||||
arrIndices[i++] = (p*2+3)%8;
|
||||
arrIndices[i++] = (p*2+2)%8;
|
||||
arrIndices[i++] = (p*2+1)%8;
|
||||
}
|
||||
|
||||
Matrix44 mat;
|
||||
mat.SetIdentity();
|
||||
pCBuffer->AddMesh(arrVerts,8,arrIndices,24,&mat);
|
||||
}
|
||||
|
||||
void CVisArea::ClipPortalVerticesByCameraFrustum(list2<Vec3d> * pPolygon, const CCamera & cam)
|
||||
{
|
||||
CCoverageBuffer::ClipPolygon(pPolygon, *cam.GetFrustumPlane(FR_PLANE_RIGHT));
|
||||
CCoverageBuffer::ClipPolygon(pPolygon, *cam.GetFrustumPlane(FR_PLANE_LEFT));
|
||||
CCoverageBuffer::ClipPolygon(pPolygon, *cam.GetFrustumPlane(FR_PLANE_TOP));
|
||||
CCoverageBuffer::ClipPolygon(pPolygon, *cam.GetFrustumPlane(FR_PLANE_BOTTOM));
|
||||
}
|
||||
|
||||
void CVisArea::GetMemoryUsage(ICrySizer*pSizer)
|
||||
{
|
||||
pSizer->AddContainer(m_lstEntities[STATIC_ENTITIES]);
|
||||
pSizer->AddContainer(m_lstEntities[DYNAMIC_ENTITIES]);
|
||||
|
||||
int nSize=0;
|
||||
for(int nStatic=0; nStatic<2; nStatic++)
|
||||
for(int i=0; i<m_lstEntities[nStatic].Count(); i++)
|
||||
nSize += m_lstEntities[nStatic][i]->GetMemoryUsage();
|
||||
|
||||
pSizer->AddObject(this,sizeof(*this)+nSize);
|
||||
}
|
||||
|
||||
void CVisArea::DrawVolume_NotThisAreaOnlyLights(CObjManager * pObjManager, int nReqursionLevel, CCamera CurCamera, CVisArea * pParent, CVisArea * pCurPortal, bool * pbOutdoorVisible, list2<CCamera> * plstOutPortCameras, bool * pbSkyVisible)
|
||||
{
|
||||
if(!pParent)
|
||||
return;
|
||||
|
||||
IRenderer * pRenderer = GetRenderer();
|
||||
|
||||
// mark as rendered
|
||||
m_nRndFrameId = GetFrameID();
|
||||
|
||||
// render lsources
|
||||
{
|
||||
for( int i=0; i<m_lstEntities[DYNAMIC_ENTITIES].Count(); i++ )
|
||||
{
|
||||
IEntityRender * pEntityRender = m_lstEntities[DYNAMIC_ENTITIES].GetAt(i);
|
||||
CDLight * pLight = pEntityRender->GetLight();
|
||||
if(pLight && !(pLight->m_Flags & DLF_THIS_AREA_ONLY))
|
||||
{ // process light sources
|
||||
Vec3d vBoxMin,vBoxMax;
|
||||
pEntityRender->GetRenderBBox(vBoxMin,vBoxMax);
|
||||
if( AABB(pParent->m_vBoxMin,pParent->m_vBoxMax).IsIntersectBox( AABB(vBoxMin,vBoxMax)))
|
||||
pObjManager->RenderObject( pEntityRender, 0, 0, false, CurCamera, 0, 0, 0, true,
|
||||
pEntityRender->GetMaxViewDist());
|
||||
}
|
||||
else if(pEntityRender->GetRndFlags() & ERF_DONOTCHECKVIS)
|
||||
{ // process 1p weapon
|
||||
pEntityRender->m_fWSMaxViewDist = pEntityRender->GetMaxViewDist();
|
||||
uint nDLightMask = ((C3DEngine*)Get3DEngine())->GetFullLightMask();
|
||||
pObjManager->RenderObject( pEntityRender, m_nFogVolumeId,
|
||||
nDLightMask, false, CurCamera, &m_vAmbColor, &m_vDynAmbColor, 0, true,
|
||||
pEntityRender->m_fWSMaxViewDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo: prepare flag once
|
||||
bool bThisIsPortal = strstr(m_sName,"portal") != 0;
|
||||
|
||||
if(bThisIsPortal && nReqursionLevel>0)
|
||||
{ // recurse to not rendered connetions
|
||||
for(int p=0; p<m_lstConnections.Count(); p++)
|
||||
{
|
||||
CVisArea * pNeibVolume = m_lstConnections[p];
|
||||
if(pNeibVolume != pParent)
|
||||
{
|
||||
pNeibVolume->DrawVolume_NotThisAreaOnlyLights(pObjManager, nReqursionLevel-1, CurCamera, this, pCurPortal, pbOutdoorVisible, plstOutPortCameras, pbSkyVisible);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Cry3DEngine/VisAreas.h
Normal file
129
Cry3DEngine/VisAreas.h
Normal file
@@ -0,0 +1,129 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: visareas.h
|
||||
// Version: v1.00
|
||||
// Created: 18/12/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: visibility areas header
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VisArea_H
|
||||
#define VisArea_H
|
||||
|
||||
#include "basicarea.h"
|
||||
|
||||
struct CVisArea : public CBasicArea, public IVisArea
|
||||
{
|
||||
// editor interface
|
||||
virtual void Update(const Vec3d * pPoints, int nCount, const char * szName, float fHeight, const Vec3d & vAmbientColor, bool bAfectedByOutLights, bool bSkyOnly, const Vec3d & vDynAmbientColor, float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors);
|
||||
|
||||
CVisArea(bool bLoadedAsAreaBox);
|
||||
~CVisArea();
|
||||
bool IsPointInsideVisArea(const Vec3d & vPos);
|
||||
bool FindVisArea(IVisArea * pAnotherArea, int nMaxReqursion, bool bSkipDisabledPortals);
|
||||
int GetVisFrameId();
|
||||
Vec3d GetConnectionNormal(CVisArea * pPortal);
|
||||
void DrawVolume(CObjManager * pObjManager, int nReqursionLevel, CCamera CurCamera, CVisArea * pParent, CVisArea * pCurPortal, bool * pbOutdoorVisible, list2<CCamera> * plstOutPortCameras, bool * pbSkyVisible);
|
||||
void DrawVolume_NotThisAreaOnlyLights(CObjManager * pObjManager, int nReqursionLevel, CCamera CurCamera, CVisArea * pParent, CVisArea * pCurPortal, bool * pbOutdoorVisible, list2<CCamera> * plstOutPortCameras, bool * pbSkyVisible);
|
||||
void UpdatePortalCameraPlanes(CCamera & cam, Vec3d * pVerts, bool bMergeFrustums);
|
||||
bool UpdatePortalCameraScissor(CCamera & cam, list2<Vec3d> * lstVerts, bool bMergeFrustums);
|
||||
int GetVisAreaConnections(IVisArea ** pAreas, int nMaxConnNum, bool bSkipDisabledPortals = false);
|
||||
int GetRealConnections(IVisArea ** pAreas, int nMaxConnNum, bool bSkipDisabledPortals = false);
|
||||
bool IsPortalValid();
|
||||
bool IsPortalIntersectAreaInValidWay(CVisArea * pPortal);
|
||||
bool IsPortal();
|
||||
bool IsShapeClockwise();
|
||||
bool IsAfectedByOutLights() { return m_bAfectedByOutLights; }
|
||||
bool IsActive() { return m_bActive; }
|
||||
void UpdateGeometryBBox();
|
||||
void MarkForStreaming();
|
||||
void DrawAreaBoundsIntoCBuffer(CCoverageBuffer * pCBuffer);
|
||||
void ClipPortalVerticesByCameraFrustum(list2<Vec3d> * pPolygon, const CCamera & cam);
|
||||
void GetMemoryUsage(ICrySizer*pSizer);
|
||||
bool IsConnectedToOutdoor();
|
||||
const char * GetName() { return m_sName; }
|
||||
bool PreloadVisArea(int nMaxReqursion, bool * pbOutdoorFound, CVisArea * pParentToAvoid, Vec3d vPrevPortalPos, float fPrevPortalDistance);
|
||||
|
||||
Vec3d m_vGeomBoxMin, m_vGeomBoxMax;
|
||||
char m_sName[32];
|
||||
list2<CVisArea*> m_lstConnections;
|
||||
Vec3d m_vConnNormals[2];
|
||||
int m_nRndFrameId;
|
||||
bool m_bActive;
|
||||
int m_nFogVolumeId;
|
||||
list2<Vec3d> m_lstShapePoints;
|
||||
float m_fHeight;
|
||||
Vec3d m_vAmbColor, m_vDynAmbColor;
|
||||
bool m_bLoadedAsAreaBox;
|
||||
bool m_bAfectedByOutLights;
|
||||
float m_fDistance;
|
||||
bool m_bSkyOnly;
|
||||
float m_fViewDistRatio;
|
||||
bool m_bDoubleSide;
|
||||
// bool m_bUseDeepness;
|
||||
CCamera * m_pOcclCamera;
|
||||
OcclusionTestClient m_OcclState;
|
||||
Vec3d m_arrvActiveVerts[4];
|
||||
bool m_bUseInIndoors;
|
||||
};
|
||||
|
||||
struct CVisAreaManager : public Cry3DEngineBase
|
||||
{
|
||||
CVisArea * m_pCurArea, * m_pCurPortal;
|
||||
list2<CVisArea * > m_lstActiveEntransePortals;
|
||||
|
||||
list2<CVisArea*> m_lstVisAreas;
|
||||
list2<CVisArea*> m_lstPortals;
|
||||
list2<CVisArea*> m_lstOcclAreas;
|
||||
list2<CVisArea*> m_lstActiveOcclVolumes;
|
||||
list2<CVisArea*> m_lstIndoorActiveOcclVolumes;
|
||||
bool m_bOutdoorVisible;
|
||||
bool m_bSkyVisible;
|
||||
list2<CCamera> m_lstOutdoorPortalCameras;
|
||||
|
||||
CVisAreaManager();
|
||||
~CVisAreaManager();
|
||||
void SetCurAreas(CObjManager * pObjManager);
|
||||
void LoadVisAreaBoxFromXML(XDOM::IXMLDOMDocumentPtr pDoc);
|
||||
void PortalsDrawDebug();
|
||||
bool IsEntityVisible(IEntityRender * pEntityRS);
|
||||
bool IsOutdoorAreasVisible();
|
||||
bool IsSkyVisible();
|
||||
CVisArea * CreateVisArea();
|
||||
bool DeleteVisArea(CVisArea * pVisArea);
|
||||
bool SetEntityArea(IEntityRender* pEntityRS);
|
||||
void Render(class CObjManager * pObjManager);
|
||||
bool UnRegisterEntity(IEntityRender* pEntityRS);
|
||||
void ActivatePortal(const Vec3d &vPos, bool bActivate, IEntityRender *pEntity);
|
||||
void SetupFogVolumes(CTerrain * pTerrain);
|
||||
void LoadVisAreaShapeFromXML(XDOM::IXMLDOMDocumentPtr pDoc);
|
||||
void UpdateVisArea(CVisArea * pArea, const Vec3d * pPoints, int nCount, const char * szName, float fHeight, const Vec3d & vAmbientColor, bool bAfectedByOutLights, bool bSkyOnly, CTerrain*pTerrain, const Vec3 & vDynAmbientColor, float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors);
|
||||
void UpdateConnections();
|
||||
void MoveAllEntitiesIntoList(list2<IEntityRender*> * plstVisAreasEntities, const Vec3d & vBoxMin, const Vec3d & vBoxMax);
|
||||
IVisArea * GetVisAreaFromPos(const Vec3d &vPos);
|
||||
// void DefineTrees();
|
||||
bool IsEntityVisAreaVisible(IEntityRender * pEnt, bool nCheckNeighbors);
|
||||
void SetAreaFogVolume(CTerrain * pTerrain, CVisArea * pVisArea);
|
||||
void MakeActiveEntransePortalsList(const CCamera & CurCamera, list2<CVisArea *> & lstActiveEntransePortals, CVisArea * pThisPortal, CObjManager * pObjManager);
|
||||
void MergeCameras(CCamera & cam, const CCamera & camPlus);
|
||||
void DrawOcclusionAreasIntoCBuffer(CCoverageBuffer * pCBuffer);
|
||||
bool IsValidVisAreaPointer(CVisArea * pVisArea);
|
||||
void SortStaticInstancesBySize();
|
||||
void CheckUnload();
|
||||
int m_nLoadedSectors;
|
||||
void GetStreamingStatus(int & nLoadedSectors, int & nTotalSectors);
|
||||
void GetMemoryUsage(ICrySizer*pSizer);
|
||||
bool UnRegisterInAllSectors(IEntityRender * pEntityRS);
|
||||
bool PreloadResources();
|
||||
bool IsOccludedByOcclVolumes(Vec3d vBoxMin, Vec3d vBoxMax, bool bCheckOnlyIndoorVolumes = false);
|
||||
void Preceche(CObjManager * pObjManager);
|
||||
void GetObjectsAround(Vec3d vExploPos, float fExploRadius, list2<IEntityRender*> * pEntList);
|
||||
};
|
||||
|
||||
#endif // VisArea_H
|
||||
784
Cry3DEngine/WaterVolumes.cpp
Normal file
784
Cry3DEngine/WaterVolumes.cpp
Normal file
@@ -0,0 +1,784 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: objmanWaterVolumes.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Loading water volumes, prepare water geometry
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "watervolumes.h"
|
||||
#include "visareas.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
// Shader params ids.
|
||||
enum {
|
||||
SHP_WATER_FLOW_POS
|
||||
};
|
||||
|
||||
CWaterVolumeManager::CWaterVolumeManager( )
|
||||
{
|
||||
// Add Water Flow Pos shader parameter.
|
||||
SShaderParam pr;
|
||||
pr.m_Type = eType_FLOAT;
|
||||
pr.m_Value.m_Float = 0;
|
||||
strcpy( pr.m_Name, "WaterFlowPos" );
|
||||
m_shaderParams.Reserve(1);
|
||||
m_shaderParams.AddElem(pr);
|
||||
}
|
||||
|
||||
void CWaterVolumeManager::LoadWaterVolumesFromXML(XDOM::IXMLDOMDocumentPtr pDoc)
|
||||
{
|
||||
// reset old data
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
m_lstWaterVolumes[i]->m_lstPoints.Reset();
|
||||
GetRenderer()->DeleteLeafBuffer(m_lstWaterVolumes[i]->m_pLeafBuffer);
|
||||
m_lstWaterVolumes[i]->m_pLeafBuffer=0;
|
||||
delete m_lstWaterVolumes[i];
|
||||
}
|
||||
m_lstWaterVolumes.Reset();
|
||||
|
||||
// fill list of volumes of shape points
|
||||
XDOM::IXMLDOMNodeListPtr pNodeTagList;
|
||||
XDOM::IXMLDOMNodePtr pNodeTag;
|
||||
pNodeTagList = pDoc->getElementsByTagName("Objects");
|
||||
if (pNodeTagList)
|
||||
{
|
||||
pNodeTagList->reset();
|
||||
pNodeTag = pNodeTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pNodeList;
|
||||
pNodeList = pNodeTag->getElementsByTagName("Object");
|
||||
if (pNodeList)
|
||||
{
|
||||
pNodeList->reset();
|
||||
XDOM::IXMLDOMNodePtr pNode;
|
||||
while (pNode = pNodeList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pType = pNode->getAttribute("Type");
|
||||
if (pType)
|
||||
{
|
||||
if (strstr(pType->getText(),"WaterVolume"))
|
||||
{
|
||||
CWaterVolume * pNewVolume = new CWaterVolume( GetRenderer() );
|
||||
m_lstWaterVolumes.Add(pNewVolume);
|
||||
m_lstWaterVolumes.Last()->m_vBoxMax=SetMinBB();
|
||||
m_lstWaterVolumes.Last()->m_vBoxMin=SetMaxBB();
|
||||
|
||||
XDOM::IXMLDOMNodePtr pAttr0,pAttr1,pAttr2,pAttr3,pAttr4,pMatAttr;
|
||||
|
||||
pAttr0 = pNode->getAttribute("Pos");
|
||||
pAttr1 = pNode->getAttribute("Width");
|
||||
pAttr2 = pNode->getAttribute("Height");
|
||||
pAttr3 = pNode->getAttribute("Name");
|
||||
pAttr4 = pNode->getAttribute("GroupId");
|
||||
pMatAttr = pNode->getAttribute("Material");
|
||||
|
||||
if (pMatAttr)
|
||||
{
|
||||
IMatInfo *pMatInfo = GetSystem()->GetI3DEngine()->FindMaterial( pMatAttr->getText() );
|
||||
if (pMatInfo)
|
||||
pNewVolume->SetMaterial( pMatInfo );
|
||||
}
|
||||
|
||||
// set shader
|
||||
XDOM::IXMLDOMNodePtr pAttr5 = pNode->getAttribute("WaterShader");
|
||||
if(pAttr5)
|
||||
pNewVolume->m_pShader = pAttr5->getText()[0] ? GetRenderer()->EF_LoadShader(pAttr5->getText(), eSH_World, EF_SYSTEM) : NULL;
|
||||
|
||||
// set tesselation
|
||||
XDOM::IXMLDOMNodePtr pAttrTriMinSize = pNode->getAttribute("TriMinSize");
|
||||
XDOM::IXMLDOMNodePtr pAttrTriMaxSize = pNode->getAttribute("TriMaxSize");
|
||||
float fTriMaxSize = pAttrTriMaxSize ? (float)atof(pAttrTriMaxSize->getText()) : 8.f;
|
||||
if(pAttrTriMinSize)
|
||||
pNewVolume->SetTriSizeLimits((float)atof(pAttrTriMinSize->getText()), fTriMaxSize);
|
||||
|
||||
// set flow speed
|
||||
XDOM::IXMLDOMNodePtr pAttr6 = pNode->getAttribute("WaterSpeed");
|
||||
if(pAttr6)
|
||||
pNewVolume->m_fFlowSpeed = (float)atof(pAttr6->getText());
|
||||
|
||||
// set AffectToVolFog
|
||||
XDOM::IXMLDOMNodePtr pAffectToVolFog = pNode->getAttribute("AffectToVolFog");
|
||||
if(pAffectToVolFog)
|
||||
pNewVolume->m_bAffectToVolFog = atoi(pAffectToVolFog->getText())!=0;
|
||||
|
||||
// load vertices
|
||||
if(pAttr0!=0 && pAttr1!=0 && pAttr2!=0 && pAttr3!=0 && pAttr4!=0)
|
||||
{
|
||||
pNewVolume->SetName(pAttr3->getText());
|
||||
|
||||
pNewVolume->m_fHeight = (float)atof(pAttr2->getText());
|
||||
|
||||
XDOM::IXMLDOMNodeListPtr pNodeTagList;
|
||||
XDOM::IXMLDOMNodePtr pNodeTag;
|
||||
pNodeTagList = pNode->getElementsByTagName("Points");
|
||||
if (pNodeTagList)
|
||||
{
|
||||
pNodeTagList->reset();
|
||||
pNodeTag = pNodeTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pNodeList;
|
||||
pNodeList = pNodeTag->getElementsByTagName("Point");
|
||||
if (pNodeList)
|
||||
{
|
||||
pNodeList->reset();
|
||||
XDOM::IXMLDOMNodePtr pNode;
|
||||
while (pNode = pNodeList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pPos = pNode->getAttribute("Pos");
|
||||
if (pPos)
|
||||
{
|
||||
Vec3d vPos = StringToVector(pPos->getText());
|
||||
m_lstWaterVolumes.Last()->m_lstPoints.Add(vPos);
|
||||
m_lstWaterVolumes.Last()->m_vBoxMax.CheckMax(vPos);
|
||||
m_lstWaterVolumes.Last()->m_vBoxMin.CheckMin(vPos);
|
||||
}
|
||||
}
|
||||
|
||||
if( GetDistance(m_lstWaterVolumes.Last()->m_lstPoints.Last(), m_lstWaterVolumes.Last()->m_lstPoints[0])>0.1f )
|
||||
m_lstWaterVolumes.Last()->m_lstPoints.Add(Vec3d(m_lstWaterVolumes.Last()->m_lstPoints[0]));
|
||||
|
||||
m_lstWaterVolumes.Last()->UpdateVisArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MidVert(const struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & v1, const struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & v2, struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & vRes)
|
||||
{
|
||||
vRes.xyz = 0.5f*v1.xyz + 0.5f*v2.xyz;
|
||||
|
||||
vRes.normal = 0.5f*v1.normal + 0.5f*v2.normal;
|
||||
|
||||
vRes.color.bcolor[0] = uchar(0.5f*v1.color.bcolor[0] + 0.5f*v2.color.bcolor[0]);
|
||||
vRes.color.bcolor[1] = uchar(0.5f*v1.color.bcolor[1] + 0.5f*v2.color.bcolor[1]);
|
||||
vRes.color.bcolor[2] = uchar(0.5f*v1.color.bcolor[2] + 0.5f*v2.color.bcolor[2]);
|
||||
vRes.color.bcolor[3] = uchar(0.5f*v1.color.bcolor[3] + 0.5f*v2.color.bcolor[3]);
|
||||
|
||||
vRes.st[0] = 0.5f*v1.st[0] + 0.5f*v2.st[0];
|
||||
vRes.st[1] = 0.5f*v1.st[1] + 0.5f*v2.st[1];
|
||||
}
|
||||
|
||||
bool CWaterVolume::TesselateFace(list2<struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> & lstVerts, list2<ushort> & lstIndices, int nFacePos, list2<Vec3d> & lstDirections)
|
||||
{
|
||||
int n0 = lstIndices[nFacePos+0];
|
||||
int n1 = lstIndices[nFacePos+1];
|
||||
int n2 = lstIndices[nFacePos+2];
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & v0 = lstVerts[n0];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & v1 = lstVerts[n1];
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F & v2 = lstVerts[n2];
|
||||
|
||||
// get edge lengts
|
||||
float fDist01 = v0.xyz.GetDistance(v1.xyz);
|
||||
float fDist12 = v1.xyz.GetDistance(v2.xyz);
|
||||
float fDist20 = v2.xyz.GetDistance(v0.xyz);
|
||||
|
||||
float fMaxDist = max(max(fDist01,fDist12), fDist20);
|
||||
float fCameraDist=200;
|
||||
|
||||
if(fMaxDist == fDist01)
|
||||
fCameraDist = GetSquaredDistance(GetViewCamera().GetPos(), (v0.xyz+v1.xyz)*0.5f);
|
||||
else if(fMaxDist == fDist12)
|
||||
fCameraDist = GetSquaredDistance(GetViewCamera().GetPos(), (v1.xyz+v2.xyz)*0.5f);
|
||||
else if(fMaxDist == fDist20)
|
||||
fCameraDist = GetSquaredDistance(GetViewCamera().GetPos(), (v2.xyz+v0.xyz)*0.5f);
|
||||
else
|
||||
assert(0);
|
||||
|
||||
if(fMaxDist<m_fTriMaxSize)
|
||||
{
|
||||
if(fMaxDist<fCameraDist/25 && m_fTriMinSize<8.f)
|
||||
return false;
|
||||
|
||||
if(fMaxDist<m_fTriMinSize)
|
||||
return false;
|
||||
}
|
||||
|
||||
// delete old face
|
||||
// lstIndices.Delete(nFacePos,3);
|
||||
lstIndices.DeleteFastUnsorted(nFacePos,3);
|
||||
|
||||
int nNewIndex = lstVerts.Count();
|
||||
|
||||
// tesselate longest
|
||||
if(fDist01>fDist12 && fDist01>fDist20)
|
||||
{ // 01
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F v01;
|
||||
MidVert(v0, v1, v01);
|
||||
|
||||
lstVerts.Add(v01);
|
||||
lstDirections.Add((lstDirections[n0]+lstDirections[n1]).GetNormalized());
|
||||
|
||||
lstIndices.Add(n0);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n2);
|
||||
|
||||
lstIndices.Add(n2);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n1);
|
||||
}
|
||||
else
|
||||
if(fDist12>fDist01 && fDist12>fDist20)
|
||||
{ // 12
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F v12;
|
||||
MidVert(v1, v2, v12);
|
||||
|
||||
lstVerts.Add(v12);
|
||||
lstDirections.Add((lstDirections[n1]+lstDirections[n2]).GetNormalized());
|
||||
|
||||
lstIndices.Add(n1);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n0);
|
||||
|
||||
lstIndices.Add(n0);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n2);
|
||||
}
|
||||
else
|
||||
if(fDist20>fDist12 && fDist20>fDist01)
|
||||
{ // 20
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F v20;
|
||||
MidVert(v2, v0, v20);
|
||||
|
||||
lstVerts.Add(v20);
|
||||
lstDirections.Add((lstDirections[n2]+lstDirections[n0]).GetNormalized());
|
||||
|
||||
lstIndices.Add(n2);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n1);
|
||||
|
||||
lstIndices.Add(n1);
|
||||
lstIndices.Add(nNewIndex);
|
||||
lstIndices.Add(n0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWaterVolume::TesselateStrip(list2<struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> & lstVerts, list2<ushort> & lstIndices, list2<Vec3d> & lstDirections)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
lstIndices.Clear();
|
||||
|
||||
for(int i=0; i<lstVerts.Count()-2; i++)
|
||||
{
|
||||
if(i&1)
|
||||
{
|
||||
lstIndices.Add(i+2);
|
||||
lstIndices.Add(i+1);
|
||||
lstIndices.Add(i+0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lstIndices.Add(i+0);
|
||||
lstIndices.Add(i+1);
|
||||
lstIndices.Add(i+2);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<lstIndices.Count() && i<10000; i+=3)
|
||||
if(TesselateFace(lstVerts, lstIndices, i, lstDirections))
|
||||
i-=3;
|
||||
}
|
||||
|
||||
void CWaterVolumeManager::InitWaterVolumes()
|
||||
{
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
m_lstWaterVolumes[i]->CheckForUpdate(false);
|
||||
}
|
||||
|
||||
void CWaterVolume::CheckForUpdate(bool bMakeLowestLod)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
Vec3d vCenter = (m_vBoxMin + m_vBoxMax) * 0.5f;
|
||||
float fRadius = (m_vBoxMin - vCenter).Length();
|
||||
|
||||
if( m_fTriMinSize != m_fPrevTriMinSize || m_fTriMaxSize != m_fPrevTriMaxSize ||
|
||||
((m_vCurrentCamPos.GetDistance(GetViewCamera().GetPos())>2 && (m_fTriMinSize<m_fTriMaxSize))))
|
||||
{ // force to rebuild water volume geometry
|
||||
m_vCurrentCamPos = GetViewCamera().GetPos();
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
}
|
||||
|
||||
if(!m_pLeafBuffer )
|
||||
if( m_pShader )
|
||||
if( m_lstPoints.Count() > 3 )
|
||||
if( GetDistance(m_lstPoints.Last(),m_lstPoints[0]) < 1.f )
|
||||
{
|
||||
m_fPrevTriMaxSize = m_fTriMaxSize;
|
||||
m_fPrevTriMinSize = m_fTriMinSize;
|
||||
|
||||
m_vCurrentCamPos = GetViewCamera().GetPos();
|
||||
// make verts strip list
|
||||
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F tmp;
|
||||
list2<struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> lstVertices;
|
||||
m_lstDirections.Clear();
|
||||
|
||||
Vec3d vNormal = (m_lstPoints[1]-m_lstPoints[0]).Cross(m_lstPoints[2]-m_lstPoints[0]);
|
||||
|
||||
for(int p=0; p<m_lstPoints.Count()/2; p++)
|
||||
{
|
||||
int p2 = m_lstPoints.Count() - p - 2;
|
||||
|
||||
if(p>=p2)
|
||||
break;
|
||||
|
||||
// first
|
||||
tmp.xyz = m_lstPoints[p]+m_vWaterLevelOffset;
|
||||
|
||||
tmp.normal = Vec3(0.f, 0.f, 1.f);
|
||||
|
||||
tmp.st[0] = (float)p;
|
||||
tmp.st[1] = 0.f;
|
||||
tmp.color.dcolor = -1;
|
||||
|
||||
lstVertices.Add(tmp);
|
||||
|
||||
// calc water move direction in this point
|
||||
Vec3d vDir1 = (p+1>=p2) ? (m_lstPoints[p] - m_lstPoints[p-1]) : (m_lstPoints[p+1] - m_lstPoints[p]);
|
||||
m_lstDirections.Add(GetNormalized(vDir1));
|
||||
|
||||
// second
|
||||
tmp.xyz = m_lstPoints[p2]+m_vWaterLevelOffset;
|
||||
tmp.st[0] = (float)p;
|
||||
tmp.st[1] = 1.f;
|
||||
|
||||
lstVertices.Add(tmp);
|
||||
|
||||
Vec3d vDir2 = (p+1>=p2) ? (m_lstPoints[p2] - m_lstPoints[p2+1]) : (m_lstPoints[p2-1] - m_lstPoints[p2]);
|
||||
m_lstDirections.Add(GetNormalized(vDir2));
|
||||
}
|
||||
|
||||
// Tesselate to alllow nice reflections
|
||||
list2<ushort> lstIndices;
|
||||
TesselateStrip(lstVertices, lstIndices, m_lstDirections);
|
||||
|
||||
// for(int i=0; i<lstVertices.Count(); i++)
|
||||
// GetRenderer()->DrawLabel(Vec3d(lstVertices[i].x,lstVertices[i].y,lstVertices[i].z),4,"%d", i);
|
||||
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBufferInitialized(
|
||||
lstVertices.GetElements(), lstVertices.Count(), VERTEX_FORMAT_P3F_N_COL4UB_TEX2F,
|
||||
lstIndices.GetElements(), lstIndices.Count(), R_PRIMV_TRIANGLES,
|
||||
"WaterVolume", eBT_Static);
|
||||
|
||||
m_pLeafBuffer->SetChunk(m_pShader,
|
||||
0,lstVertices.Count(), 0,lstIndices.Count());
|
||||
|
||||
m_pLeafBuffer->m_pMats->Get(0)->m_vCenter = vCenter;
|
||||
m_pLeafBuffer->m_pMats->Get(0)->m_fRadius = fRadius;
|
||||
|
||||
m_pLeafBuffer->m_vBoxMin = m_vBoxMin;
|
||||
m_pLeafBuffer->m_vBoxMax = m_vBoxMax;
|
||||
}
|
||||
}
|
||||
|
||||
void CWaterVolumeManager::RenderWaterVolumes(bool bOutdoorVisible)
|
||||
{
|
||||
if(!GetCVars()->e_water_volumes || m_nRenderStackLevel)
|
||||
return;
|
||||
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
CWaterVolume * pWaterVolumes = m_lstWaterVolumes[i];
|
||||
|
||||
// check vis
|
||||
if(!GetViewCamera().IsAABBVisibleFast( AABB(pWaterVolumes->m_vBoxMin,pWaterVolumes->m_vBoxMax)))
|
||||
continue;
|
||||
|
||||
if(GetFrameID()%32==0) // hack
|
||||
pWaterVolumes->UpdateVisArea();
|
||||
|
||||
if(m_lstWaterVolumes[i]->m_lstVisAreas.Count())
|
||||
{ // water in indoors
|
||||
if(!m_lstWaterVolumes[i]->IsWaterVolumeAreasVisible())
|
||||
continue; // water area not visible
|
||||
}
|
||||
else if(!bOutdoorVisible)
|
||||
continue; // water area (outdoor) not visible
|
||||
|
||||
// create geometry if not ready
|
||||
m_lstWaterVolumes[i]->CheckForUpdate(false);
|
||||
|
||||
if(!m_lstWaterVolumes[i]->m_pLeafBuffer)
|
||||
continue;
|
||||
|
||||
m_lstWaterVolumes[i]->m_nLastRndFrame = GetFrameID();
|
||||
|
||||
// draw debug
|
||||
if(GetCVars()->e_water_volumes==2)
|
||||
{
|
||||
int nPosStride=0;
|
||||
byte * pPos = (byte *)m_lstWaterVolumes[i]->m_pLeafBuffer->GetPosPtr(nPosStride);
|
||||
|
||||
for(int p=0; p<m_lstWaterVolumes[i]->m_pLeafBuffer->m_SecVertCount; p++)
|
||||
{
|
||||
Vec3d vPos = *(Vec3d*)&pPos[p*nPosStride];
|
||||
GetRenderer()->SetMaterialColor(p==0, p!=0, 0.0f, 1);
|
||||
GetRenderer()->Draw3dBBox(vPos-Vec3d(0.2f,0.2f,0.2f), vPos+Vec3d(0.2f,0.2f,0.2f));
|
||||
GetRenderer()->DrawLabel(vPos,2,"%d",p);
|
||||
GetRenderer()->Draw3dBBox(vPos+Vec3d(0,0,0.1f), vPos+m_lstWaterVolumes[i]->m_lstDirections[p]+Vec3d(0,0,0.1f),DPRIM_LINE);
|
||||
}
|
||||
|
||||
GetRenderer()->SetMaterialColor(1, 1, 0, 1);
|
||||
GetRenderer()->Draw3dBBox(pWaterVolumes->m_vBoxMin,pWaterVolumes->m_vBoxMax);
|
||||
}
|
||||
|
||||
// draw volume geometry
|
||||
CCObject * pObject = GetRenderer()->EF_GetObject(true);
|
||||
|
||||
// Assign water flow pos shader param to dynamic object.
|
||||
m_shaderParams[SHP_WATER_FLOW_POS].m_Value.m_Float = -m_lstWaterVolumes[i]->m_fFlowSpeed * GetCurTimeSec();
|
||||
pObject->m_ShaderParams = &m_shaderParams;
|
||||
|
||||
pObject->m_Matrix.SetIdentity();
|
||||
|
||||
// object should have some translation to simplify reflections processing in the renderer
|
||||
pObject->m_Matrix.SetTranslationOLD(Vec3d(0,0,0.025f));
|
||||
pObject->m_ObjFlags |= FOB_TRANS_TRANSLATE;
|
||||
|
||||
uint nDynMask = 0;
|
||||
if(m_lstWaterVolumes[i]->m_lstVisAreas.Count())
|
||||
{
|
||||
nDynMask = (uint)-1;
|
||||
|
||||
// remove sun
|
||||
for(int nId=0; nId<32; nId++)
|
||||
{
|
||||
if(nDynMask & (1<<nId))
|
||||
{
|
||||
CDLight * pDLight = (CDLight*)GetRenderer()->EF_Query(EFQ_LightSource, nId);
|
||||
if(pDLight && pDLight->m_Flags & DLF_SUN)
|
||||
{
|
||||
nDynMask = nDynMask & ~(1<<nId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float fRadius = (m_lstWaterVolumes[i]->m_vBoxMax-m_lstWaterVolumes[i]->m_vBoxMin).len()*0.5f;
|
||||
Vec3d vCenter = (m_lstWaterVolumes[i]->m_vBoxMin+m_lstWaterVolumes[i]->m_vBoxMax)*0.5f;
|
||||
((C3DEngine*)Get3DEngine())->CheckDistancesToLightSources(nDynMask,vCenter,fRadius);
|
||||
}
|
||||
else
|
||||
nDynMask=0;
|
||||
|
||||
pObject->m_Color.a = 0.99f;
|
||||
m_lstWaterVolumes[i]->m_pLeafBuffer->AddRenderElements(pObject, nDynMask, -1, 0,
|
||||
(GetViewCamera().GetPos().z>Get3DEngine()->GetWaterLevel()) ? eS_SeeThrough : eS_Water,
|
||||
m_lstWaterVolumes[i]->m_pMaterial);
|
||||
|
||||
m_lstWaterVolumes[i]->m_pLeafBuffer->m_vBoxMax = m_lstWaterVolumes[i]->m_pLeafBuffer->m_vBoxMin = GetViewCamera().GetPos();
|
||||
}
|
||||
|
||||
// release old
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
CWaterVolume * pWaterVolumes = m_lstWaterVolumes[i];
|
||||
if(pWaterVolumes->m_pLeafBuffer && m_lstWaterVolumes[i]->m_nLastRndFrame < GetFrameID()-100)
|
||||
{
|
||||
m_lstWaterVolumes[i]->CheckForUpdate(true);
|
||||
// GetRenderer()->DeleteLeafBuffer(pWaterVolumes->m_pLeafBuffer);
|
||||
// pWaterVolumes->m_pLeafBuffer=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float CWaterVolumeManager::GetWaterVolumeLevelFor2DPoint(const Vec3d & vPos, Vec3d * pvFlowDir)
|
||||
{
|
||||
float fResLevel = WATER_LEVEL_UNKNOWN;
|
||||
|
||||
// check all volumes bboxes
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
CWaterVolume * pWaterVolumes = m_lstWaterVolumes[i];
|
||||
Vec3d vBoxMin2d = pWaterVolumes->m_vBoxMin;
|
||||
Vec3d vBoxMax2d = pWaterVolumes->m_vBoxMax;
|
||||
vBoxMin2d.z=WATER_LEVEL_UNKNOWN;
|
||||
vBoxMax2d.z=1024;
|
||||
|
||||
if(!pWaterVolumes->m_pLeafBuffer)
|
||||
pWaterVolumes->CheckForUpdate(true);
|
||||
|
||||
if(pWaterVolumes->m_pLeafBuffer && Overlap::Point_AABB(vPos,vBoxMin2d,vBoxMax2d))
|
||||
{ // if inside bbox
|
||||
int nInds = 0;
|
||||
ushort *pInds = pWaterVolumes->m_pLeafBuffer->GetIndices(&nInds);
|
||||
int nPosStride=0;
|
||||
const byte * pPos = pWaterVolumes->m_pLeafBuffer->GetPosPtr(nPosStride,0,true);
|
||||
for(int i=0; (i+2)<nInds; i+=3)
|
||||
{ // test all triangles of water surface strip
|
||||
Vec3d v0 = *(Vec3d*)&pPos[nPosStride*pInds[i+0]];
|
||||
Vec3d v1 = *(Vec3d*)&pPos[nPosStride*pInds[i+1]];
|
||||
Vec3d v2 = *(Vec3d*)&pPos[nPosStride*pInds[i+2]];
|
||||
v0.z = v1.z = v2.z = 0; // make triangle 2d
|
||||
Vec3d vPos2d(vPos.x,vPos.y,0);
|
||||
if(Overlap::PointInTriangle( vPos2d, v0,v1,v2,Vec3d(0,0,1.f)))
|
||||
{ // triangle found
|
||||
Plane plane;
|
||||
plane.CalcPlane( // calc plane using real vertices
|
||||
*(Vec3d*)&pPos[nPosStride*pInds[i+0]],
|
||||
*(Vec3d*)&pPos[nPosStride*pInds[i+1]],
|
||||
*(Vec3d*)&pPos[nPosStride*pInds[i+2]]);
|
||||
float fDist = plane.DistFromPlane(vPos);
|
||||
float fDot = plane.n.Dot(Vec3d(0,0,1.f));
|
||||
if(fDot>0)
|
||||
fDist = -fDist;
|
||||
|
||||
// check bottom bounds
|
||||
if(pWaterVolumes->m_fHeight && fDist > -pWaterVolumes->m_fHeight)
|
||||
continue;
|
||||
|
||||
if(GetCVars()->e_water_volumes==2)
|
||||
{
|
||||
GetLog()->Log("CameraLevel=%.2f, WaterVolumeLevel=%.2f %d",
|
||||
GetViewCamera().GetPos().z, fDist, GetFrameID());
|
||||
Vec3d vPos = vPos2d+Vec3d(0,0,fDist);
|
||||
// GetRenderer()->Draw3dBBox(vPos-Vec3d(0.05f,0.05f,0.05f),vPos+Vec3d(0.05f,0.05f,0.05f),DPRIM_SOLID_SPHERE);
|
||||
|
||||
}
|
||||
|
||||
if(pvFlowDir)
|
||||
{
|
||||
// todo: calculate the barycentric coordinates of the triangle
|
||||
/* float b0 = (v1.x - v0.x) * (v2.y - v0.y) - (v2.x - v0.x) * (v1.y - v0.y);
|
||||
float b1 = ( v1.x * v2.y - v2.x * v1.y ) / b0 ;
|
||||
float b2 = ( v2.x * v0.y - v0.x * v2.y ) / b0 ;
|
||||
float b3 = ( v0.x * v1.y - v1.x * v0.y ) / b0 ;
|
||||
Vec3d vReconstructed = b1 * v0 + b2 * v1 + b3 * v2;
|
||||
vReconstructed=vReconstructed;*/
|
||||
|
||||
float fDist0 = GetDistance(vPos2d,v0);
|
||||
float fDist1 = GetDistance(vPos2d,v1);
|
||||
float fDist2 = GetDistance(vPos2d,v2);
|
||||
float fSumm = fDist0 + fDist1 + fDist2;
|
||||
fDist0 /= fSumm;
|
||||
fDist1 /= fSumm;
|
||||
fDist2 /= fSumm;
|
||||
|
||||
*pvFlowDir = pWaterVolumes->m_lstDirections[pInds[i+0]]*(1.f-fDist0)+
|
||||
pWaterVolumes->m_lstDirections[pInds[i+1]]*(1.f-fDist1)+
|
||||
pWaterVolumes->m_lstDirections[pInds[i+2]]*(1.f-fDist2);
|
||||
|
||||
if(GetCVars()->e_water_volumes==2)
|
||||
GetRenderer()->Draw3dBBox(vPos, vPos+*pvFlowDir, DPRIM_LINE);
|
||||
|
||||
*pvFlowDir *= pWaterVolumes->m_fFlowSpeed;
|
||||
}
|
||||
|
||||
if( (vPos.z+fDist) > fResLevel )
|
||||
fResLevel = (vPos.z+fDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fResLevel;
|
||||
}
|
||||
|
||||
IWaterVolume * CWaterVolumeManager::CreateWaterVolume()
|
||||
{
|
||||
CWaterVolume * pNewVolume = new CWaterVolume( GetRenderer() );
|
||||
m_lstWaterVolumes.Add(pNewVolume);
|
||||
return pNewVolume;
|
||||
}
|
||||
|
||||
void CWaterVolumeManager::DeleteWaterVolume(IWaterVolume * pWaterVolume)
|
||||
{
|
||||
GetRenderer()->DeleteLeafBuffer(((CWaterVolume*)pWaterVolume)->m_pLeafBuffer);
|
||||
((CWaterVolume*)pWaterVolume)->m_pLeafBuffer=0;
|
||||
delete pWaterVolume;
|
||||
m_lstWaterVolumes.Delete((CWaterVolume*)pWaterVolume);
|
||||
}
|
||||
|
||||
void CWaterVolumeManager::UpdateWaterVolumeVisAreas()
|
||||
{
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
m_lstWaterVolumes[i]->UpdateVisArea();
|
||||
}
|
||||
|
||||
void CWaterVolume::UpdatePoints(const Vec3d * pPoints, int nCount, float fHeight)
|
||||
{
|
||||
m_lstPoints.PreAllocate(nCount+1,nCount);
|
||||
|
||||
m_fHeight = fHeight;
|
||||
|
||||
if(nCount)
|
||||
{
|
||||
memcpy(&m_lstPoints[0], pPoints, sizeof(Vec3d)*nCount);
|
||||
if( GetDistance(m_lstPoints.Last(), m_lstPoints[0])>0.1f )
|
||||
m_lstPoints.Add(m_lstPoints[0]); // loop
|
||||
}
|
||||
|
||||
// update bbox
|
||||
m_vBoxMax = SetMinBB();
|
||||
m_vBoxMin = SetMaxBB();
|
||||
|
||||
for(int i=0; i<nCount; i++)
|
||||
{
|
||||
m_vBoxMax.CheckMax(pPoints[i]);
|
||||
m_vBoxMin.CheckMin(pPoints[i]);
|
||||
}
|
||||
|
||||
// remake leaf buffer
|
||||
m_pRenderer->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
|
||||
UpdateVisArea();
|
||||
}
|
||||
|
||||
void CWaterVolume::SetShader(const char * szShaderName)
|
||||
{
|
||||
if(szShaderName[0])
|
||||
m_pShader = m_pRenderer->EF_LoadShader(szShaderName,eSH_World, EF_SYSTEM);
|
||||
else
|
||||
m_pShader = NULL;//m_pRenderer->EF_LoadShader("default",eSH_World, EF_SYSTEM);
|
||||
|
||||
// remake leaf buffer
|
||||
m_pRenderer->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
}
|
||||
|
||||
CWaterVolumeManager::~CWaterVolumeManager()
|
||||
{
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
CWaterVolume * pWaterVolume = m_lstWaterVolumes[i];
|
||||
GetRenderer()->DeleteLeafBuffer(pWaterVolume->m_pLeafBuffer);
|
||||
pWaterVolume->m_pLeafBuffer=0;
|
||||
delete pWaterVolume;
|
||||
}
|
||||
m_lstWaterVolumes.Reset();
|
||||
}
|
||||
|
||||
void CWaterVolume::UpdateVisArea()
|
||||
{
|
||||
m_lstVisAreas.Clear();
|
||||
|
||||
if(!m_lstPoints.Count())
|
||||
return;
|
||||
|
||||
// scan water volume bbox for vis areas
|
||||
const float dx = (m_vBoxMax.x - m_vBoxMin.x)/int(m_vBoxMax.x - m_vBoxMin.x) + 0.1f;
|
||||
const float dy = (m_vBoxMax.y - m_vBoxMin.y)/int(m_vBoxMax.y - m_vBoxMin.y) + 0.1f;
|
||||
// const float dz = (m_vBoxMax.z - m_vBoxMin.z)/int(m_vBoxMax.z - m_vBoxMin.z) + 0.1f;
|
||||
|
||||
float z = (m_vBoxMin.z+m_vBoxMax.z)*0.5f;
|
||||
for(float x = m_vBoxMin.x; x<=m_vBoxMax.x; x+=dx*5)
|
||||
for(float y = m_vBoxMin.y; y<=m_vBoxMax.y; y+=dy*5)
|
||||
// for(float z = m_vBoxMin.z; z<=m_vBoxMax.z; z+=dz)
|
||||
{
|
||||
CVisArea * pVisArea = (CVisArea *)Get3DEngine()->GetVisAreaFromPos(Vec3d(x,y,z));
|
||||
if(pVisArea && m_lstVisAreas.Find(pVisArea)<0)
|
||||
{
|
||||
m_lstVisAreas.Add(pVisArea);
|
||||
if(m_bAffectToVolFog)
|
||||
UpdateVisAreaFogVolumeLevel(pVisArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWaterVolume::UpdateVisAreaFogVolumeLevel(CVisArea*pVisArea)
|
||||
{
|
||||
CTerrain * pTerrain = ((C3DEngine*)Get3DEngine())->GetTerrain();
|
||||
int f;
|
||||
for(f=0; f<pTerrain->m_lstFogVolumes.Count(); f++)
|
||||
if(pTerrain->m_lstFogVolumes[f].nRendererVolumeID == pVisArea->m_nFogVolumeId)
|
||||
break;
|
||||
|
||||
if(f<pTerrain->m_lstFogVolumes.Count())
|
||||
{
|
||||
VolumeInfo * pFogVolume = &pTerrain->m_lstFogVolumes[f];
|
||||
pFogVolume->vBoxMax.z = m_vBoxMax.z;
|
||||
GetRenderer()->EF_RegisterFogVolume(pFogVolume->fMaxViewDist,pFogVolume->vBoxMax.z,pFogVolume->vColor,pFogVolume->nRendererVolumeID, pFogVolume->m_bCaustics);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CWaterVolume::SetMaterial( IMatInfo *pMatInfo )
|
||||
{
|
||||
m_pMaterial = pMatInfo;
|
||||
|
||||
if(m_pMaterial)
|
||||
m_pMaterial->SetFlags(m_pMaterial->GetFlags()|MIF_WASUSED);
|
||||
}
|
||||
|
||||
IMatInfo * CWaterVolume::GetMaterial()
|
||||
{
|
||||
return m_pMaterial;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IWaterVolume * CWaterVolumeManager::FindWaterVolumeByName(const char * szName)
|
||||
{
|
||||
for(int i=0; i<m_lstWaterVolumes.Count(); i++)
|
||||
{
|
||||
CWaterVolume * pWaterVolume = m_lstWaterVolumes[i];
|
||||
if(!stricmp(pWaterVolume->m_szName, szName))
|
||||
return pWaterVolume;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CWaterVolume::SetPositionOffset(const Vec3d & vNewOffset)
|
||||
{
|
||||
m_vWaterLevelOffset = vNewOffset;
|
||||
|
||||
m_vBoxMax = SetMinBB();
|
||||
m_vBoxMin = SetMaxBB();
|
||||
|
||||
for(int p=0; p<m_lstPoints.Count(); p++)
|
||||
{
|
||||
Vec3d vPos = m_lstPoints[p] + m_vWaterLevelOffset;
|
||||
m_vBoxMax.CheckMax(vPos);
|
||||
m_vBoxMin.CheckMin(vPos);
|
||||
}
|
||||
|
||||
m_vBoxMax.z += 0.01f;
|
||||
m_vBoxMin.z -= 0.01f;
|
||||
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
|
||||
UpdateVisArea();
|
||||
}
|
||||
|
||||
bool CWaterVolume::IsWaterVolumeAreasVisible()
|
||||
{
|
||||
assert(m_lstVisAreas.Count());
|
||||
|
||||
// water in indoors
|
||||
int v;
|
||||
for(v=0; v<m_lstVisAreas.Count(); v++)
|
||||
if(abs(((CVisArea*)m_lstVisAreas[v])->m_nRndFrameId - GetFrameID())<2)
|
||||
break; // water area is visible
|
||||
|
||||
return v<m_lstVisAreas.Count();
|
||||
}
|
||||
|
||||
void CWaterVolume::SetTriSizeLimits(float fTriMinSize, float fTriMaxSize)
|
||||
{
|
||||
m_fTriMinSize = max(0.25f,min(fTriMinSize, 8));
|
||||
m_fTriMaxSize = max(0.25f,min(fTriMaxSize, 8));
|
||||
// remake leaf buffer
|
||||
m_pRenderer->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
}
|
||||
81
Cry3DEngine/WaterVolumes.h
Normal file
81
Cry3DEngine/WaterVolumes.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef CWaterVolumeManager_H
|
||||
#define CWaterVolumeManager_H
|
||||
|
||||
class CWaterVolume : public IWaterVolume, public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CWaterVolume(IRenderer * pRenderer)
|
||||
{
|
||||
m_pRenderer = pRenderer; m_pLeafBuffer = 0; m_pShader = 0;
|
||||
m_fFlowSpeed = 0;
|
||||
m_bAffectToVolFog = false;
|
||||
m_fTriMaxSize = m_fTriMinSize = 8.f;
|
||||
m_fPrevTriMaxSize = m_fPrevTriMinSize = 0;
|
||||
m_fHeight = 0; m_vCurrentCamPos.Set(0,0,0); m_nLastRndFrame=0;
|
||||
m_szName[0] = 0;
|
||||
m_vWaterLevelOffset.Set(0,0,0);
|
||||
}
|
||||
void UpdatePoints(const Vec3d * pPoints, int nCount, float fHeight);
|
||||
void SetFlowSpeed(float fSpeed) { m_fFlowSpeed = fSpeed; }
|
||||
void SetAffectToVolFog(bool bAffectToVolFog) { m_bAffectToVolFog = bAffectToVolFog; }
|
||||
void SetTriSizeLimits(float fTriMinSize, float fTriMaxSize);
|
||||
void SetShader(const char * szShaderName);
|
||||
void SetMaterial( IMatInfo *pMatInfo );
|
||||
void SetName(const char * szName)
|
||||
{
|
||||
strncpy(m_szName,szName,64);
|
||||
}
|
||||
void SetPositionOffset(const Vec3d & vNewOffset);
|
||||
IMatInfo * GetMaterial();
|
||||
void UpdateVisArea();
|
||||
void CheckForUpdate(bool bMakeLowestLod);
|
||||
bool IsWaterVolumeAreasVisible();
|
||||
void TesselateStrip(list2<struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> & lstVerts, list2<ushort> & lstIndices, list2<Vec3d> & lstDirections);
|
||||
bool TesselateFace(list2<struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> & lstVerts, list2<ushort> & lstIndices, int nFacePos, list2<Vec3d> & lstDirections);
|
||||
void UpdateVisAreaFogVolumeLevel(CVisArea*pVisArea);
|
||||
|
||||
list2<Vec3d> m_lstPoints;
|
||||
Vec3d m_vWaterLevelOffset;
|
||||
list2<Vec3d> m_lstDirections;
|
||||
CLeafBuffer * m_pLeafBuffer;
|
||||
Vec3d m_vBoxMin, m_vBoxMax;
|
||||
IRenderer * m_pRenderer;
|
||||
IShader * m_pShader;
|
||||
char m_szName[64];
|
||||
float m_fHeight;
|
||||
float m_fTriMinSize, m_fTriMaxSize;
|
||||
float m_fPrevTriMaxSize, m_fPrevTriMinSize;
|
||||
|
||||
_smart_ptr<IMatInfo> m_pMaterial;
|
||||
|
||||
float m_fFlowSpeed;
|
||||
bool m_bAffectToVolFog;
|
||||
list2<struct IVisArea *> m_lstVisAreas;
|
||||
Vec3d m_vCurrentCamPos;
|
||||
int m_nLastRndFrame;
|
||||
};
|
||||
|
||||
struct CWaterVolumeManager : public Cry3DEngineBase
|
||||
{
|
||||
CWaterVolumeManager( );
|
||||
~CWaterVolumeManager();
|
||||
void LoadWaterVolumesFromXML(XDOM::IXMLDOMDocumentPtr pDoc);
|
||||
|
||||
list2<CWaterVolume*> m_lstWaterVolumes;
|
||||
|
||||
void InitWaterVolumes();
|
||||
void RenderWaterVolumes(bool bOutdoorVisible);
|
||||
float GetWaterVolumeLevelFor2DPoint(const Vec3d & vPos, Vec3d * pvFlowDir);
|
||||
|
||||
IWaterVolume * CreateWaterVolume();
|
||||
void DeleteWaterVolume(IWaterVolume * pWaterVolume);
|
||||
void UpdateWaterVolumeVisAreas();
|
||||
|
||||
IWaterVolume * FindWaterVolumeByName(const char * szName);
|
||||
|
||||
private:
|
||||
// Local shader param.
|
||||
TArray<SShaderParam> m_shaderParams;
|
||||
};
|
||||
|
||||
#endif // CWaterVolumeManager_H
|
||||
354
Cry3DEngine/bflyes.cpp
Normal file
354
Cry3DEngine/bflyes.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bflyes.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: draw volume with bflyes right in front of the camera
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
/*
|
||||
#include "bflyes.h"
|
||||
|
||||
Cry_Butterfly::Cry_Butterfly()
|
||||
{
|
||||
ZeroStruct(*this);
|
||||
|
||||
m_vPos.x = rn()*BF_RANGE*2;
|
||||
m_vPos.y = rn()*BF_RANGE*2;
|
||||
|
||||
m_fHigh = 1;
|
||||
|
||||
m_fLifeSpeed = 1;// + rn()/2;
|
||||
m_fSize = 1;// + rn();
|
||||
// m_fLifeSpeed = 1.f/m_fSize/2;
|
||||
|
||||
m_fSize *= 0.75f;
|
||||
|
||||
{
|
||||
static int _X_ = 0;
|
||||
static int _Y_ = 0;
|
||||
_Y_++;
|
||||
if(_Y_>3)
|
||||
{
|
||||
_Y_=0;
|
||||
_X_=!_X_;
|
||||
}
|
||||
|
||||
m_vCurWingPos.x = 0.25f*(_Y_);
|
||||
m_vCurWingPos.y = 0.25f*(2+_X_);
|
||||
}
|
||||
}
|
||||
|
||||
bool Cry_Butterfly::IsPointInvalid(const Vec3d & pos)
|
||||
{
|
||||
// if(pTerrain->GetZSafe(fastftol(pos.x),fastftol(pos.y)) < pTerrain->GetWaterLevel())
|
||||
// return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Cry_Butterfly::Render(ITimer * pITimer, IRenderer * pIRenderer, const Vec3d & vCamPos, const bool & bEven, const Vec3d & vColor, struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pVertBufChunk, CTerrain * pTerrain )
|
||||
{
|
||||
Vec3d start_pos = m_vPos;
|
||||
|
||||
{ // bf space loop
|
||||
if((m_vPos.x-vCamPos.x)>BF_RANGE)
|
||||
{
|
||||
while((m_vPos.x-vCamPos.x)>BF_RANGE)
|
||||
m_vPos.x-=BF_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.x+=BF_RANGEx2;
|
||||
}
|
||||
|
||||
if((vCamPos.x-m_vPos.x)>BF_RANGE)
|
||||
{
|
||||
while((vCamPos.x-m_vPos.x)>BF_RANGE)
|
||||
m_vPos.x+=BF_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.x-=BF_RANGEx2;
|
||||
}
|
||||
|
||||
if((m_vPos.y-vCamPos.y)>BF_RANGE)
|
||||
{
|
||||
while((m_vPos.y-vCamPos.y)>BF_RANGE)
|
||||
m_vPos.y-=BF_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.y+=BF_RANGEx2;
|
||||
}
|
||||
|
||||
if((vCamPos.y-m_vPos.y)>BF_RANGE)
|
||||
{
|
||||
while((vCamPos.y-m_vPos.y)>BF_RANGE)
|
||||
m_vPos.y+=BF_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.y-=BF_RANGEx2;
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
//m_vPos!=start_pos
|
||||
!IsEquivalent(m_vPos,start_pos,VEC_EPSILON)
|
||||
)
|
||||
m_fHigh = 0.5; // sit in the ea fix
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// AI
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
m_fAngle += m_fAngleDelta*fBFPerformanceFactor;
|
||||
m_fHigh += m_fHightDelta*fBFPerformanceFactor/15;
|
||||
|
||||
if(bEven)
|
||||
{
|
||||
m_fAngleDelta += rn();
|
||||
Limit(&m_fAngleDelta,-3,3);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fHightDelta += rn();
|
||||
Limit(&m_fHightDelta,-1,1);
|
||||
}
|
||||
|
||||
Limit(&m_fHigh, -0.25,5);
|
||||
|
||||
bool water = pTerrain->GetZApr(m_vPos.x,m_vPos.y) < pTerrain->GetWaterLevel();
|
||||
if(water && m_fHigh<0.2f)
|
||||
m_fHigh=0.2f;
|
||||
|
||||
if(m_fHigh>GROUND_LEVEL)
|
||||
{ // fly
|
||||
if(m_fHigh<0.1f)
|
||||
m_fHigh=0.1f;
|
||||
|
||||
float rad = (m_fAngle-90) * (gf_PI/180);
|
||||
|
||||
Vec2 D; // the cosine and sine, y is guaranteed to follow x
|
||||
CosSin(rad, &D.x);
|
||||
|
||||
m_vPos.x += D.x*fBFPerformanceFactor*0.05f*m_fLifeSpeed;
|
||||
m_vPos.y += D.y*fBFPerformanceFactor*0.05f*m_fLifeSpeed;
|
||||
|
||||
m_vPos.z = pTerrain->GetZApr(m_vPos.x,m_vPos.y);
|
||||
if(m_vPos.z < pTerrain->GetWaterLevel())
|
||||
m_vPos.z = pTerrain->GetWaterLevel();
|
||||
m_vPos.z += m_fHigh;
|
||||
}
|
||||
// else
|
||||
// pos.z += (pTerrain->GetZApr(pos.x,pos.y)+0.1f-pos.z)/100;
|
||||
}
|
||||
|
||||
if(m_vPos.x>0 && m_vPos.y>0 && m_vPos.x<CTerrain::GetTerrainSize() && m_vPos.y<CTerrain::GetTerrainSize() &&
|
||||
m_vPos.z < (pTerrain->GetWaterLevel()+82) )// !IsPointInFuncZone(m_vPos.x,m_vPos.y))
|
||||
{
|
||||
struct {float c, s;}
|
||||
WingPos;
|
||||
|
||||
CosSin(m_fWingPos, &WingPos.c);
|
||||
float c = WingPos.c;
|
||||
float s = WingPos.s;
|
||||
|
||||
float wspeed = (1.1f*(float)fabs(c) + 0.25f)*(m_fLifeSpeed+m_fHightDelta*0.2f)/(1.f+(m_fHigh<GROUND_LEVEL)*7.f);
|
||||
|
||||
if(m_bMoveDir)
|
||||
m_fWingPos += fBFPerformanceFactor*wspeed;
|
||||
else
|
||||
m_fWingPos -= fBFPerformanceFactor*wspeed;
|
||||
|
||||
if(m_fWingPos> 1.2f) // up wind pos
|
||||
m_bMoveDir = 0;
|
||||
else if(m_fWingPos < ((m_fHigh<GROUND_LEVEL) ? 0.2f : -1.0f)) // down wind pos
|
||||
m_bMoveDir = 1;
|
||||
|
||||
float sh = 1;//0.5f + 0.5f*pTerrain->IsOnTheLight(fastftol(m_vPos.x),fastftol(m_vPos.y));
|
||||
|
||||
uchar r = uchar(vColor[0]*sh);
|
||||
uchar g = uchar(vColor[1]*sh);
|
||||
uchar b = uchar(vColor[2]*sh);
|
||||
|
||||
// pIRenderer->RotateMatrix(-10,1,0,0);
|
||||
|
||||
float R = 0.175f*m_fSize;
|
||||
|
||||
float
|
||||
x1=0 +m_vCurWingPos.x,
|
||||
x2=0.125f +m_vCurWingPos.x,
|
||||
x3=0.25f +m_vCurWingPos.x;
|
||||
float
|
||||
y1=1.f-(0 +m_vCurWingPos.y),
|
||||
y2=1.f-(0.125f +m_vCurWingPos.y),
|
||||
y3=1.f-(0.25f +m_vCurWingPos.y);
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F data[6] =
|
||||
{
|
||||
{-c*R, -R, R*s , r,g,b,255, x1, y3},
|
||||
{-c*R, R, R*s , r,g,b,255, x1, y1},
|
||||
{ 0, -R, -R*s/3, r,g,b,255, x2, y3},
|
||||
{ 0, R, -R*s/3, r,g,b,255, x2, y1},
|
||||
{ c*R, -R, R*s , r,g,b,255, x3, y3},
|
||||
{ c*R, R, R*s , r,g,b,255, x3, y1}
|
||||
};
|
||||
|
||||
if(m_fHigh<GROUND_LEVEL)
|
||||
data[2].z = data[3].z = 0;
|
||||
|
||||
float rad = DEG2RAD(m_fAngle);
|
||||
struct {float c,s;} radCS;
|
||||
CosSin (rad, &radCS.c);
|
||||
float fCos = radCS.c;// (float)cos(rad);
|
||||
float fSin = radCS.s;// (float)sin(rad);
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pData = data;
|
||||
for(int i=0; i<6; i++)
|
||||
{
|
||||
float x = fCos*pData->x - fSin*pData->y;
|
||||
float y = fSin*pData->x + fCos*pData->y;
|
||||
|
||||
pData->x = x;
|
||||
pData->y = y;
|
||||
|
||||
pData->x+=m_vPos.x;
|
||||
pData->y+=m_vPos.y;
|
||||
pData->z+=m_vPos.z;
|
||||
|
||||
pData++;
|
||||
}
|
||||
|
||||
memcpy(pVertBufChunk,data,sizeof(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(pVertBufChunk,0,sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F)*6);
|
||||
}
|
||||
}
|
||||
|
||||
CBFManager::CBFManager()
|
||||
{
|
||||
m_pBFArray = new Cry_Butterfly[MAX_BF_COUNT];
|
||||
m_Indixes.Reset();
|
||||
GetRenderer()->CreateIndexBuffer(&m_Indixes, NULL, MAX_BF_COUNT*12);
|
||||
GetRenderer()->UpdateIndexBuffer(&m_Indixes, NULL, 0, false);
|
||||
ushort *pInds = (ushort *)m_Indixes.m_VData;
|
||||
m_nTexID = 0;
|
||||
m_pVideoBuffer = 0;
|
||||
|
||||
int i=0;
|
||||
for(int b=0; b<MAX_BF_COUNT; b++)
|
||||
{
|
||||
// 1st wing
|
||||
pInds[i++] = b*6;
|
||||
pInds[i++] = b*6+1;
|
||||
pInds[i++] = b*6+2;
|
||||
|
||||
pInds[i++] = b*6+1;
|
||||
pInds[i++] = b*6+2;
|
||||
pInds[i++] = b*6+3;
|
||||
|
||||
// 2nd
|
||||
pInds[i++] = b*6+2;
|
||||
pInds[i++] = b*6+3;
|
||||
pInds[i++] = b*6+4;
|
||||
|
||||
pInds[i++] = b*6+3;
|
||||
pInds[i++] = b*6+4;
|
||||
pInds[i++] = b*6+5;
|
||||
// assert(i<BF_COUNT*12);
|
||||
}
|
||||
GetRenderer()->UpdateIndexBuffer(&m_Indixes, NULL, 0, true);
|
||||
|
||||
m_pVideoBuffer = GetRenderer()->CreateBuffer(MAX_BF_COUNT*6,VERTEX_FORMAT_P3F_COL4UB_TEX2F, "BFlyes");
|
||||
m_nCurrentObjectsCount = 0;
|
||||
}
|
||||
|
||||
CBFManager::~CBFManager()
|
||||
{
|
||||
delete [] m_pBFArray;
|
||||
GetRenderer()->ReleaseIndexBuffer(&m_Indixes);
|
||||
GetRenderer()->ReleaseBuffer(m_pVideoBuffer);
|
||||
}
|
||||
|
||||
void CBFManager::Render(CTerrain * pTerrain)
|
||||
{
|
||||
if(!GetCVars()->e_bflyes || m_nCurrentObjectsCount==0)
|
||||
return;
|
||||
|
||||
IRenderer * rend = GetRenderer();
|
||||
rend->ResetToDefault();
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
float terr_z = pTerrain->GetZSafe(vCamPos.x,vCamPos.y);
|
||||
if(terr_z<pTerrain->GetWaterLevel())
|
||||
terr_z = pTerrain->GetWaterLevel();
|
||||
|
||||
if(vCamPos.z > terr_z+48)
|
||||
return;
|
||||
|
||||
rend->SetMaterialColor(1,1,1,1);
|
||||
rend->SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture|(eCA_Constant<<3), eCA_Texture|(eCA_Constant<<3));
|
||||
rend->SetState(GS_ALPHATEST_GEQUAL64 | GS_DEPTHWRITE);
|
||||
rend->SetCullMode(R_CULL_DISABLE);
|
||||
|
||||
int tex_type;
|
||||
if(!m_nTexID)
|
||||
m_nTexID = rend->LoadTexture("Textures\\bfly.jpg", &tex_type);
|
||||
// else
|
||||
// GetCVars()->e_bflyes = false;
|
||||
|
||||
rend->SetTexture(m_nTexID);
|
||||
|
||||
Matrix44 mat;
|
||||
rend->GetModelViewMatrix(mat.GetData());
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//m_vForward(-mat.cell(2), -mat.cell(6), -mat.cell(10));
|
||||
m_vForward = -mat.GetColumn(2);
|
||||
|
||||
m_vForward.Normalize();
|
||||
|
||||
Vec3d vFocusPos = vCamPos + m_vForward*BF_CAMERA_SHIFT;
|
||||
|
||||
Vec3d vColor = GetSystem()->GetI3DEngine()->GetWorldColor();//*
|
||||
// GetSystem()->GetI3DEngine()->GetWorldBrightnes();
|
||||
|
||||
vColor.x*=255;
|
||||
vColor.y*=255;
|
||||
vColor.z*=255;
|
||||
|
||||
// wait for fence
|
||||
GetRenderer()->UpdateBuffer(m_pVideoBuffer,0,0,false);
|
||||
|
||||
for(int i=0; i<m_nCurrentObjectsCount && i<MAX_BF_COUNT; i++)
|
||||
m_pBFArray[i].Render(GetTimer(), GetRenderer(), vFocusPos, m_bEven, vColor, &((struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F*)m_pVideoBuffer->m_VS[VSF_GENERAL].m_VData)[i*6], pTerrain);
|
||||
|
||||
m_bEven =! m_bEven;
|
||||
|
||||
GetRenderer()->DrawBuffer(m_pVideoBuffer,&m_Indixes,m_nCurrentObjectsCount*12,0,R_PRIMV_TRIANGLES);
|
||||
|
||||
rend->ResetToDefault();
|
||||
}
|
||||
|
||||
|
||||
void CBFManager::KillBF(const Vec3d & vExploPos, const float fRadius)
|
||||
{
|
||||
for(int i=0; i<MAX_BF_COUNT; i++)
|
||||
{
|
||||
if(fabs(m_pBFArray[i].m_vPos.x - vExploPos.x)<fRadius)
|
||||
if(fabs(m_pBFArray[i].m_vPos.y - vExploPos.y)<fRadius)
|
||||
if(fabs(m_pBFArray[i].m_vPos.z - vExploPos.z)<fRadius)
|
||||
{
|
||||
m_pBFArray[i].m_vPos.x = m_pBFArray[i].m_vPos.x + m_vForward.x*BF_CAMERA_SHIFT;
|
||||
m_pBFArray[i].m_vPos.y = m_pBFArray[i].m_vPos.y + m_vForward.y*BF_CAMERA_SHIFT;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
74
Cry3DEngine/bflyes.h
Normal file
74
Cry3DEngine/bflyes.h
Normal file
@@ -0,0 +1,74 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bflyes.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
#ifndef _BFLIES_H
|
||||
#define _BFLIES_H
|
||||
|
||||
|
||||
|
||||
#define MAX_BF_COUNT 256
|
||||
#define BF_RANGE 16
|
||||
const int BF_RANGEx2 = BF_RANGE*2;
|
||||
const int BF_CAMERA_SHIFT = BF_RANGE-1;
|
||||
|
||||
#define rn() ((((float)rand())/RAND_MAX)-0.5f)
|
||||
#define fBFPerformanceFactor (pITimer->GetFrameTime()*40)
|
||||
|
||||
#define GROUND_LEVEL 0.1f
|
||||
|
||||
class Cry_Butterfly
|
||||
{
|
||||
float m_fWingPos,m_fAngle,m_fAngleDelta,m_fHigh,m_fHightDelta,m_fLifeSpeed,m_fSize;
|
||||
Vec3d m_vCurWingPos;
|
||||
bool m_bMoveDir;
|
||||
|
||||
inline void Limit(float * val, float min, float max)
|
||||
{
|
||||
if(*val > max) *val = max;
|
||||
else if(*val < min) *val = min;
|
||||
}
|
||||
|
||||
bool IsPointInvalid(const Vec3d & pos);
|
||||
|
||||
public:
|
||||
Cry_Butterfly();
|
||||
void Render(ITimer * pITimer, IRenderer * pIRenderer, const Vec3d & vCamPos, const bool & bEven, const Vec3d & vColor, struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pVertBufChunk, CTerrain * pTerrain );
|
||||
|
||||
Vec3d m_vPos;
|
||||
};
|
||||
|
||||
class CBFManager : public Cry3DEngineBase
|
||||
{
|
||||
Cry_Butterfly * m_pBFArray;
|
||||
CVertexBuffer * m_pVideoBuffer;
|
||||
SVertexStream m_Indixes;
|
||||
int m_nTexID;
|
||||
bool m_bEven;
|
||||
Vec3d m_vForward;
|
||||
int m_nCurrentObjectsCount;
|
||||
|
||||
public:
|
||||
CBFManager();
|
||||
void Render(CTerrain * pTerrain);
|
||||
~CBFManager();
|
||||
void KillBF(const Vec3d & vExploPos, const float fRadius);
|
||||
void SetCount(int nCount) { m_nCurrentObjectsCount = min(nCount, MAX_BF_COUNT); }
|
||||
int GetCount() { return m_nCurrentObjectsCount; }
|
||||
int GetMemoryUsage() { return sizeof(Cry_Butterfly)*MAX_BF_COUNT + sizeof(ushort)*MAX_BF_COUNT; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
*/
|
||||
684
Cry3DEngine/cbuffer.cpp
Normal file
684
Cry3DEngine/cbuffer.cpp
Normal file
@@ -0,0 +1,684 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cbuffer.cpp
|
||||
// Version: v1.00
|
||||
// Created: 30/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Occlusion (coverage) buffer
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "cbuffer.h"
|
||||
|
||||
void CCoverageBuffer::TransformPoint(float out[4], const float m[16], const float in[4])
|
||||
{
|
||||
#define M(row,col) m[col*4+row]
|
||||
out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
|
||||
out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
|
||||
out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
|
||||
out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
|
||||
#undef M
|
||||
}
|
||||
|
||||
void CCoverageBuffer::MatMul4( float *product, const float *a, const float *b )
|
||||
{
|
||||
#define A(row,col) a[(col<<2)+row]
|
||||
#define B(row,col) b[(col<<2)+row]
|
||||
#define P(row,col) product[(col<<2)+row]
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
float ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
|
||||
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
|
||||
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
|
||||
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
|
||||
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
|
||||
}
|
||||
#undef A
|
||||
#undef B
|
||||
#undef P
|
||||
}
|
||||
|
||||
CCoverageBuffer::Point2d CCoverageBuffer::ProjectToScreen(const float & x, const float & y, const float & z)
|
||||
{
|
||||
Point2d res; float res_z;
|
||||
|
||||
float _in[4], out[4];
|
||||
_in[0] = x;
|
||||
_in[1] = y;
|
||||
_in[2] = z;
|
||||
_in[3] = 1.0;
|
||||
|
||||
TransformPoint(out, m_matCombined, _in);
|
||||
|
||||
if (out[3] == 0.0)
|
||||
res.x = res.y = -1000; // mark vertex as bad - skip this triangle
|
||||
else
|
||||
{
|
||||
res.x = out[0] / out[3];
|
||||
res.y = out[1] / out[3];
|
||||
res_z = out[2] / out[3];
|
||||
|
||||
res.x = m_matViewPort[0] + (1.f + res.x) * m_matViewPort[2] * 0.5f;
|
||||
res.y = m_matViewPort[1] + (1.f + res.y) * m_matViewPort[3] * 0.5f;
|
||||
|
||||
res_z = (1.f + res_z) * 0.5f;
|
||||
|
||||
if( res_z < 0 || res_z > 1 )
|
||||
res_z=res_z;//res.x = res.y = -1000; // mark vertex as bad - skip this triangle
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void CCoverageBuffer::AddBBox(const Vec3d & mins, const Vec3d & maxs, const Vec3d & vDirToCamera)
|
||||
{
|
||||
Vec3d arrVerts3d[8] =
|
||||
{
|
||||
Vec3d(mins.x,mins.y,mins.z),
|
||||
Vec3d(mins.x,maxs.y,mins.z),
|
||||
Vec3d(maxs.x,mins.y,mins.z),
|
||||
Vec3d(maxs.x,maxs.y,mins.z),
|
||||
Vec3d(mins.x,mins.y,maxs.z),
|
||||
Vec3d(mins.x,maxs.y,maxs.z),
|
||||
Vec3d(maxs.x,mins.y,maxs.z),
|
||||
Vec3d(maxs.x,maxs.y,maxs.z)
|
||||
};
|
||||
|
||||
Point2d arrVerts[8] =
|
||||
{ // transform into screen space
|
||||
ProjectToScreen(mins.x,mins.y,mins.z),
|
||||
ProjectToScreen(mins.x,maxs.y,mins.z),
|
||||
ProjectToScreen(maxs.x,mins.y,mins.z),
|
||||
ProjectToScreen(maxs.x,maxs.y,mins.z),
|
||||
ProjectToScreen(mins.x,mins.y,maxs.z),
|
||||
ProjectToScreen(mins.x,maxs.y,maxs.z),
|
||||
ProjectToScreen(maxs.x,mins.y,maxs.z),
|
||||
ProjectToScreen(maxs.x,maxs.y,maxs.z)
|
||||
};
|
||||
|
||||
// find 2d bounds in screen space
|
||||
Point2d min2d = arrVerts[0], max2d = arrVerts[0];
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
if(arrVerts[i].x < min2d.x)
|
||||
min2d.x = arrVerts[i].x;
|
||||
if(arrVerts[i].x > max2d.x)
|
||||
max2d.x = arrVerts[i].x;
|
||||
if(arrVerts[i].y < min2d.y)
|
||||
min2d.y = arrVerts[i].y;
|
||||
if(arrVerts[i].y > max2d.y)
|
||||
max2d.y = arrVerts[i].y;
|
||||
}
|
||||
|
||||
// adjust 2d bounds to make it 1 pixel smaler
|
||||
min2d.x += 1;
|
||||
min2d.y += 1;
|
||||
max2d.x -= 1;
|
||||
max2d.y -= 1;
|
||||
|
||||
// adjust 2d vertices
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
if(arrVerts[i].x < min2d.x)
|
||||
arrVerts[i].x = min2d.x;
|
||||
if(arrVerts[i].x > max2d.x)
|
||||
arrVerts[i].x = max2d.x;
|
||||
if(arrVerts[i].y < min2d.y)
|
||||
arrVerts[i].y = min2d.y;
|
||||
if(arrVerts[i].y > max2d.y)
|
||||
arrVerts[i].y = max2d.y;
|
||||
}
|
||||
|
||||
// render only front faces of box
|
||||
if(vDirToCamera.x>0)
|
||||
{
|
||||
ScanTriangleWithCliping(arrVerts[2],arrVerts[3],arrVerts[6],arrVerts3d[2],arrVerts3d[3],arrVerts3d[6]);
|
||||
ScanTriangleWithCliping(arrVerts[6],arrVerts[3],arrVerts[7],arrVerts3d[6],arrVerts3d[3],arrVerts3d[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScanTriangleWithCliping(arrVerts[1],arrVerts[0],arrVerts[4],arrVerts3d[1],arrVerts3d[0],arrVerts3d[4]);
|
||||
ScanTriangleWithCliping(arrVerts[1],arrVerts[4],arrVerts[5],arrVerts3d[1],arrVerts3d[4],arrVerts3d[5]);
|
||||
}
|
||||
|
||||
if(vDirToCamera.y>0)
|
||||
{
|
||||
ScanTriangleWithCliping(arrVerts[3],arrVerts[1],arrVerts[7],arrVerts3d[3],arrVerts3d[1],arrVerts3d[7]);
|
||||
ScanTriangleWithCliping(arrVerts[7],arrVerts[1],arrVerts[5],arrVerts3d[7],arrVerts3d[1],arrVerts3d[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScanTriangleWithCliping(arrVerts[0],arrVerts[2],arrVerts[4],arrVerts3d[0],arrVerts3d[2],arrVerts3d[4]);
|
||||
ScanTriangleWithCliping(arrVerts[4],arrVerts[2],arrVerts[6],arrVerts3d[4],arrVerts3d[2],arrVerts3d[6]);
|
||||
}
|
||||
}
|
||||
|
||||
void CCoverageBuffer::AddMesh(const Vec3d * arrVerts3dOS, int nVertCount, const int * pIndices, int nIndCount, Matrix44* pTranRotMatrix)
|
||||
{
|
||||
FUNCTION_PROFILER( GetISystem(),PROFILE_3DENGINE );
|
||||
m_arrVerts3dWS_AddMesh.Clear();
|
||||
m_arrVerts3dWS_AddMesh.PreAllocate(nVertCount,nVertCount);
|
||||
|
||||
m_arrVerts_AddMesh.Clear();
|
||||
m_arrVerts_AddMesh.PreAllocate(nVertCount,nVertCount);
|
||||
|
||||
// transform vertices
|
||||
for(int i=0; i<nVertCount; i++)
|
||||
{
|
||||
m_arrVerts3dWS_AddMesh[i] = pTranRotMatrix->TransformPointOLD(arrVerts3dOS[i]);
|
||||
m_arrVerts_AddMesh[i] = ProjectToScreen(m_arrVerts3dWS_AddMesh[i].x,m_arrVerts3dWS_AddMesh[i].y,m_arrVerts3dWS_AddMesh[i].z);
|
||||
}
|
||||
/*
|
||||
// find 2d bounds in screen space
|
||||
Point2d min2d = m_arrVerts_AddMesh[0], max2d = m_arrVerts_AddMesh[0];
|
||||
for(int i=0; i<nVertCount; i++)
|
||||
{
|
||||
if(m_arrVerts_AddMesh[i].x < min2d.x)
|
||||
min2d.x = m_arrVerts_AddMesh[i].x;
|
||||
if(m_arrVerts_AddMesh[i].x > max2d.x)
|
||||
max2d.x = m_arrVerts_AddMesh[i].x;
|
||||
if(m_arrVerts_AddMesh[i].y < min2d.y)
|
||||
min2d.y = m_arrVerts_AddMesh[i].y;
|
||||
if(m_arrVerts_AddMesh[i].y > max2d.y)
|
||||
max2d.y = m_arrVerts_AddMesh[i].y;
|
||||
}
|
||||
|
||||
// adjust 2d bounds to make it 1 pixel smaler
|
||||
min2d.x += 1;
|
||||
min2d.y += 1;
|
||||
max2d.x -= 1;
|
||||
max2d.y -= 1;
|
||||
|
||||
// adjust 2d vertices
|
||||
for(int i=0; i<nVertCount; i++)
|
||||
{
|
||||
if(m_arrVerts_AddMesh[i].x < min2d.x)
|
||||
m_arrVerts_AddMesh[i].x = min2d.x;
|
||||
if(m_arrVerts_AddMesh[i].x > max2d.x)
|
||||
m_arrVerts_AddMesh[i].x = max2d.x;
|
||||
if(m_arrVerts_AddMesh[i].y < min2d.y)
|
||||
m_arrVerts_AddMesh[i].y = min2d.y;
|
||||
if(m_arrVerts_AddMesh[i].y > max2d.y)
|
||||
m_arrVerts_AddMesh[i].y = max2d.y;
|
||||
}
|
||||
*/
|
||||
// render tris
|
||||
for(int i=0; i<nIndCount; i+=3)
|
||||
{
|
||||
assert(pIndices[i+0]<nVertCount);
|
||||
assert(pIndices[i+1]<nVertCount);
|
||||
assert(pIndices[i+2]<nVertCount);
|
||||
/*
|
||||
float x1 = arrVerts[pIndices[i+0]].x;
|
||||
float y1 = arrVerts[pIndices[i+0]].y;
|
||||
float x2 = arrVerts[pIndices[i+1]].x;
|
||||
float y2 = arrVerts[pIndices[i+1]].y;
|
||||
float x3 = arrVerts[pIndices[i+2]].x;
|
||||
float y3 = arrVerts[pIndices[i+2]].y;
|
||||
|
||||
float fDot = (x1-x2)*(y3-y2)-(y1-y2)*(x3-x2);
|
||||
|
||||
if(fDot<0)*/
|
||||
ScanTriangleWithCliping(
|
||||
m_arrVerts_AddMesh[pIndices[i+0]],
|
||||
m_arrVerts_AddMesh[pIndices[i+1]],
|
||||
m_arrVerts_AddMesh[pIndices[i+2]],
|
||||
m_arrVerts3dWS_AddMesh[pIndices[i+0]],
|
||||
m_arrVerts3dWS_AddMesh[pIndices[i+1]],
|
||||
m_arrVerts3dWS_AddMesh[pIndices[i+2]]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CCoverageBuffer::IsBBoxVisible(const Vec3d & mins, const Vec3d & maxs)
|
||||
{
|
||||
if(!m_nTrisInBuffer)
|
||||
return true;
|
||||
|
||||
Point2d verts[8] =
|
||||
{ // transform into screen space
|
||||
// todo: check only front faces
|
||||
ProjectToScreen(mins.x,mins.y,mins.z),
|
||||
ProjectToScreen(mins.x,maxs.y,mins.z),
|
||||
ProjectToScreen(maxs.x,mins.y,mins.z),
|
||||
ProjectToScreen(maxs.x,maxs.y,mins.z),
|
||||
ProjectToScreen(mins.x,mins.y,maxs.z),
|
||||
ProjectToScreen(mins.x,maxs.y,maxs.z),
|
||||
ProjectToScreen(maxs.x,mins.y,maxs.z),
|
||||
ProjectToScreen(maxs.x,maxs.y,maxs.z)
|
||||
};
|
||||
|
||||
// find 2d bounds to use it as 2d quad
|
||||
Point2d min2d = verts[0], max2d = verts[0];
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
if(verts[i].x < min2d.x)
|
||||
min2d.x = verts[i].x;
|
||||
if(verts[i].x > max2d.x)
|
||||
max2d.x = verts[i].x;
|
||||
if(verts[i].y < min2d.y)
|
||||
min2d.y = verts[i].y;
|
||||
if(verts[i].y > max2d.y)
|
||||
max2d.y = verts[i].y;
|
||||
}
|
||||
|
||||
if(min2d.x<-900 || min2d.y<-900 || max2d.x<-900 || max2d.y<-900)
|
||||
return true; // object intersect near plane
|
||||
|
||||
// make it little bigger to be sure that it's bigger than 1 pixel
|
||||
min2d.x -= 0.25f;
|
||||
min2d.y -= 0.25f;
|
||||
max2d.x += 0.25f;
|
||||
max2d.y += 0.25f;
|
||||
|
||||
return IsQuadVisible(min2d, max2d);
|
||||
}
|
||||
|
||||
bool CCoverageBuffer::__IsSphereVisible(const Vec3d & vCenter, float fRadius, float fDistance)
|
||||
{
|
||||
if(!m_nTrisInBuffer)
|
||||
return true;
|
||||
|
||||
Point2d Center2d = ProjectToScreen(vCenter.x,vCenter.y,vCenter.z);
|
||||
float fRadius2d = fRadius * COVERAGEBUFFER_SIZE / fDistance / 2;
|
||||
|
||||
// find 2d quad
|
||||
Point2d min2d(Center2d.x-fRadius2d, Center2d.y-fRadius2d*0.5f);
|
||||
Point2d max2d(Center2d.x+fRadius2d, Center2d.y+fRadius2d*0.5f);
|
||||
|
||||
return IsQuadVisible(min2d, max2d);
|
||||
}
|
||||
|
||||
bool CCoverageBuffer::IsQuadVisible(const Point2d & min2d, const Point2d & max2d)
|
||||
{
|
||||
// make ints
|
||||
int x1 = fastfround(min2d.x);
|
||||
int y1 = fastfround(min2d.y);
|
||||
int x2 = fastfround(max2d.x);
|
||||
int y2 = fastfround(max2d.y);
|
||||
|
||||
// clip quads by screen bounds and reject quads totaly outside of the screen
|
||||
if(x1<0)
|
||||
x1=0;
|
||||
else if(x1>=COVERAGEBUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
if(y1<0)
|
||||
y1=0;
|
||||
else if(y1>=COVERAGEBUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
if(x2<0)
|
||||
return false;
|
||||
else if(x2>=COVERAGEBUFFER_SIZE)
|
||||
x2=COVERAGEBUFFER_SIZE-1;
|
||||
|
||||
if(y2<0)
|
||||
return false;
|
||||
else if(y2>=COVERAGEBUFFER_SIZE)
|
||||
y2=COVERAGEBUFFER_SIZE-1;
|
||||
|
||||
// check each pixel inside this quad, if some pixel is zero - quad is visible
|
||||
for(int x=x1; x<=x2; x++)
|
||||
for(int y=y1; y<=y2; y++)
|
||||
if(!m_Buffer[x][y])
|
||||
return true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CCoverageBuffer::IsPixelVisible(int nScreenX, int nScreenY)
|
||||
{
|
||||
if(!m_nTrisInBuffer)
|
||||
return true;
|
||||
|
||||
nScreenX = nScreenX*COVERAGEBUFFER_SIZE/m_pRenderer->GetWidth();
|
||||
nScreenY = nScreenY*COVERAGEBUFFER_SIZE/m_pRenderer->GetHeight();
|
||||
|
||||
if(nScreenX<0 || nScreenX>=COVERAGEBUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
if(nScreenY<0 || nScreenY>=COVERAGEBUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
return (!m_Buffer[nScreenX][nScreenY]);
|
||||
}
|
||||
|
||||
void CCoverageBuffer::DrawDebug(int nStep)
|
||||
{ // project buffer to the screen
|
||||
if(!nStep)
|
||||
return;
|
||||
|
||||
m_pRenderer->Set2DMode(true,COVERAGEBUFFER_SIZE,COVERAGEBUFFER_SIZE);
|
||||
|
||||
for(int x=0; x<COVERAGEBUFFER_SIZE; x+=nStep)
|
||||
for(int y=0; y<COVERAGEBUFFER_SIZE; y+=nStep)
|
||||
if(m_Buffer[x][y])
|
||||
m_pRenderer->DrawPoint((float)x,COVERAGEBUFFER_SIZE-(float)y,0,1);
|
||||
|
||||
m_pRenderer->Set2DMode(false,COVERAGEBUFFER_SIZE,COVERAGEBUFFER_SIZE);
|
||||
}
|
||||
|
||||
void CCoverageBuffer::ScanLine(int x1, int x2, int y, float & dxdyl, float & dxdyr)
|
||||
{
|
||||
if(y<0 || y>=COVERAGEBUFFER_SIZE)
|
||||
return;
|
||||
|
||||
// if we reach left border - stop changing line start x
|
||||
if(x1<0)
|
||||
{
|
||||
// dxdyl = 0;
|
||||
x1 = 0;
|
||||
}
|
||||
|
||||
// if we reach right border - stop changing line stop x
|
||||
if(x2>=COVERAGEBUFFER_SIZE)
|
||||
{
|
||||
// dxdyr = 0;
|
||||
x2 = COVERAGEBUFFER_SIZE-1;
|
||||
}
|
||||
|
||||
// draw line
|
||||
for(int x = x1; x <= x2; x++)
|
||||
{
|
||||
assert(x>=0 && x<COVERAGEBUFFER_SIZE);
|
||||
m_Buffer[x][y]=1;
|
||||
}
|
||||
}
|
||||
|
||||
// return number of vertices to add
|
||||
int CCoverageBuffer::ClipEdge(const Vec3d & v1, const Vec3d & v2, const Plane & ClipPlane, Vec3d & vRes1, Vec3d & vRes2)
|
||||
{
|
||||
float d1 = -ClipPlane.DistFromPlane(v1);
|
||||
float d2 = -ClipPlane.DistFromPlane(v2);
|
||||
if(d1<0 && d2<0)
|
||||
return 0; // all clipped = do not add any vertices
|
||||
|
||||
if(d1>=0 && d2>=0)
|
||||
{
|
||||
vRes1 = v2;
|
||||
return 1; // both not clipped - add second vertex
|
||||
}
|
||||
|
||||
// calc new vertex
|
||||
Vec3d vIntersectionPoint = v1 + (v2-v1)*(Ffabs(d1)/(Ffabs(d2)+Ffabs(d1)));
|
||||
float fNewDist = -ClipPlane.DistFromPlane(vIntersectionPoint);
|
||||
assert(fabs(fNewDist)<0.01f);
|
||||
|
||||
if(d1>=0 && d2<0)
|
||||
{ // from vis to no vis
|
||||
vRes1 = vIntersectionPoint;
|
||||
return 1;
|
||||
}
|
||||
else if(d1<0 && d2>=0)
|
||||
{ // from novis to vis
|
||||
vRes1 = vIntersectionPoint;
|
||||
vRes2 = v2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CCoverageBuffer::ClipPolygon(list2<Vec3d> * pPolygon, const Plane & ClipPlane)
|
||||
{
|
||||
static list2<Vec3d> PolygonOut; // Keep this list static to not perform reallocation every time.
|
||||
PolygonOut.Clear();
|
||||
// clip edges, make list ov new vertices
|
||||
for(int i=0; i<pPolygon->Count(); i++)
|
||||
{
|
||||
Vec3d vNewVert1(0,0,0), vNewVert2(0,0,0);
|
||||
if(int nNewVertNum = ClipEdge(pPolygon->GetAt(i), pPolygon->GetAt((i+1)%pPolygon->Count()), ClipPlane, vNewVert1, vNewVert2))
|
||||
{
|
||||
PolygonOut.Add(vNewVert1);
|
||||
if(nNewVertNum>1)
|
||||
PolygonOut.Add(vNewVert2);
|
||||
}
|
||||
}
|
||||
|
||||
// check result
|
||||
for(int i=0; i<PolygonOut.Count(); i++)
|
||||
{
|
||||
float d1 = -ClipPlane.DistFromPlane(PolygonOut.GetAt(i));
|
||||
assert(d1>=-0.01f);
|
||||
}
|
||||
|
||||
assert(PolygonOut.Count()==0 || PolygonOut.Count() >= 3);
|
||||
|
||||
//Timur, optimizes memory allocation here.
|
||||
pPolygon->Clear();
|
||||
pPolygon->AddList( PolygonOut );
|
||||
//*pPolygon = PolygonOut;
|
||||
}
|
||||
|
||||
void CCoverageBuffer::ScanTriangleWithCliping(Point2d p1,Point2d p2,Point2d p3,
|
||||
const Vec3d & v1,const Vec3d & v2,const Vec3d & v3)
|
||||
{
|
||||
if(IsEquivalent(v1,v2,VEC_EPSILON) || IsEquivalent(v1,v3,VEC_EPSILON) || IsEquivalent(v2,v3,VEC_EPSILON))
|
||||
return; // skip degenerative triangles
|
||||
|
||||
// test if clipping needed
|
||||
// todo: try to clip all triangles without this test (cache transformed vertices)
|
||||
bool bClipingNeeded = false;
|
||||
for(int p=0; p<6 ;p++)
|
||||
{
|
||||
float d1 = -m_Planes[p].DistFromPlane(v1);
|
||||
float d2 = -m_Planes[p].DistFromPlane(v2);
|
||||
float d3 = -m_Planes[p].DistFromPlane(v3);
|
||||
if(d1<0 || d2<0 || d3<0)
|
||||
{
|
||||
bClipingNeeded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bClipingNeeded)
|
||||
{ // just use already calculated 2d points
|
||||
ScanTriangle(p1,p2,p3);
|
||||
return;
|
||||
}
|
||||
|
||||
// make polygon
|
||||
list2<Vec3d> arrTriangle;
|
||||
arrTriangle.Clear();
|
||||
|
||||
arrTriangle.Add(v1);
|
||||
arrTriangle.Add(v2);
|
||||
arrTriangle.Add(v3);
|
||||
|
||||
assert(
|
||||
!IsEquivalent(v1,v2,VEC_EPSILON) &&
|
||||
!IsEquivalent(v1,v3,VEC_EPSILON) &&
|
||||
!IsEquivalent(v2,v3,VEC_EPSILON)
|
||||
);
|
||||
|
||||
|
||||
// clip polygon
|
||||
for(int p=0; p<6 ;p++)
|
||||
{
|
||||
ClipPolygon(&arrTriangle, m_Planes[p]);
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
for(int i=1; i<arrTriangle.Count(); i++)
|
||||
{
|
||||
if(
|
||||
IsEquivalent(arrTriangle.GetAt(i),arrTriangle.GetAt(i-1),VEC_EPSILON)
|
||||
)
|
||||
{
|
||||
arrTriangle.Delete(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
assert(arrTriangle.Count()<8);
|
||||
|
||||
// scan
|
||||
if(arrTriangle.Count()>2 && arrTriangle.Count()<8)
|
||||
{
|
||||
Point2d arrVerts[8];
|
||||
|
||||
for( int i=0; i<arrTriangle.Count(); i++ )
|
||||
{ // transform into screen space
|
||||
arrVerts[i] = ProjectToScreen(arrTriangle[i].x, arrTriangle[i].y, arrTriangle[i].z);
|
||||
|
||||
assert(arrVerts[i].x>-100);
|
||||
assert(arrVerts[i].y>-100);
|
||||
assert(arrVerts[i].x< 200);
|
||||
assert(arrVerts[i].y< 200);
|
||||
}
|
||||
|
||||
ScanTriangle(arrVerts[0],arrVerts[1],arrVerts[2]);
|
||||
|
||||
if(arrTriangle.Count()>3)
|
||||
ScanTriangle(arrVerts[0],arrVerts[2],arrVerts[3]);
|
||||
|
||||
if(arrTriangle.Count()>4)
|
||||
ScanTriangle(arrVerts[0],arrVerts[3],arrVerts[4]);
|
||||
|
||||
if(arrTriangle.Count()>5)
|
||||
ScanTriangle(arrVerts[0],arrVerts[4],arrVerts[5]);
|
||||
|
||||
if(arrTriangle.Count()>6)
|
||||
ScanTriangle(arrVerts[0],arrVerts[5],arrVerts[6]);
|
||||
|
||||
if(arrTriangle.Count()>7)
|
||||
ScanTriangle(arrVerts[0],arrVerts[6],arrVerts[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void CCoverageBuffer::ScanTriangle(Point2d p1,Point2d p2,Point2d p3)
|
||||
{
|
||||
// back face culling // todo: move one level up
|
||||
float fDot = (p1.x-p2.x)*(p3.y-p2.y)-(p1.y-p2.y)*(p3.x-p2.x);
|
||||
if(fDot>0)
|
||||
return;
|
||||
|
||||
// make ints
|
||||
p1.x = (float)fastfround(p1.x);
|
||||
p1.y = (float)fastfround(p1.y);
|
||||
p2.x = (float)fastfround(p2.x);
|
||||
p2.y = (float)fastfround(p2.y);
|
||||
p3.x = (float)fastfround(p3.x);
|
||||
p3.y = (float)fastfround(p3.y);
|
||||
|
||||
// sort vertices by y
|
||||
if(p2.y<p3.y)
|
||||
{
|
||||
Point2d tmp = p2;
|
||||
p2 = p3;
|
||||
p3 = tmp;
|
||||
}
|
||||
|
||||
if(p1.y<p2.y)
|
||||
{
|
||||
Point2d tmp = p1;
|
||||
p1 = p2;
|
||||
p2 = tmp;
|
||||
}
|
||||
|
||||
if(p2.y<p3.y)
|
||||
{
|
||||
Point2d tmp = p2;
|
||||
p2 = p3;
|
||||
p3 = tmp;
|
||||
}
|
||||
|
||||
{ // draw top part
|
||||
Point2d vLeft = (p1-p3);
|
||||
Point2d vRight = (p1-p2);
|
||||
|
||||
float dxdyl = vLeft.x /vLeft.y;
|
||||
float dxdyr = vRight.x/vRight.y;
|
||||
|
||||
float x1 = p1.x;
|
||||
float x2 = p1.x;
|
||||
|
||||
if(dxdyl<dxdyr)
|
||||
{ // swap
|
||||
float x = x1;
|
||||
x1 = x2;
|
||||
x2 = x;
|
||||
|
||||
float d = dxdyl;
|
||||
dxdyl = dxdyr;
|
||||
dxdyr = d;
|
||||
}
|
||||
|
||||
int y2 = max(fastfround(p2.y), 0); // limit by screen bottom
|
||||
if(p1.y>p2.y && y2<COVERAGEBUFFER_SIZE) // if top side of triangle is visible
|
||||
{
|
||||
for( int y = fastfround(p1.y); y >= y2; y-- )
|
||||
{
|
||||
ScanLine(fastfround(x1), fastfround(x2), y, dxdyl, dxdyr);
|
||||
x1 -= dxdyl;
|
||||
x2 -= dxdyr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // draw bottom part
|
||||
Point2d vLeft = (p3-p1);
|
||||
Point2d vRight = (p3-p2);
|
||||
|
||||
float dxdyl = vLeft.x /vLeft.y;
|
||||
float dxdyr = vRight.x/vRight.y;
|
||||
|
||||
float x1 = p3.x;
|
||||
float x2 = p3.x;
|
||||
|
||||
if(dxdyl>dxdyr)
|
||||
{ // swap
|
||||
float x = x1;
|
||||
x1 = x2;
|
||||
x2 = x;
|
||||
|
||||
float d = dxdyl;
|
||||
dxdyl = dxdyr;
|
||||
dxdyr = d;
|
||||
}
|
||||
|
||||
int y2 = min(fastfround(p2.y),COVERAGEBUFFER_SIZE);// limit by screen top
|
||||
if(p2.y>p3.y && y2>0) // if bottom side of triangle is visible ((y2) line was already drawn)
|
||||
{
|
||||
for( int y = fastfround(p3.y); y < y2; y++ ) // ((y2) line was already drawn)
|
||||
{
|
||||
ScanLine(fastfround(x1), fastfround(x2), y, dxdyl, dxdyr);
|
||||
x1 += dxdyl;
|
||||
x2 += dxdyr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_nTrisInBuffer++;
|
||||
}
|
||||
|
||||
void CCoverageBuffer::BeginFrame(const CCamera & camera)
|
||||
{
|
||||
for(int p=0; p<6 ;p++)
|
||||
m_Planes[p] = *camera.GetFrustumPlane(p);
|
||||
|
||||
// make matrices
|
||||
m_matViewPort[0] = 0;
|
||||
m_matViewPort[1] = 0;
|
||||
m_matViewPort[2] = COVERAGEBUFFER_SIZE;
|
||||
m_matViewPort[3] = COVERAGEBUFFER_SIZE;
|
||||
|
||||
float matModel[16];
|
||||
float matProj[16];
|
||||
m_pRenderer->GetModelViewMatrix(matModel);
|
||||
m_pRenderer->GetProjectionMatrix(matProj);
|
||||
MatMul4(m_matCombined,matProj,matModel);
|
||||
|
||||
// reset buffer
|
||||
memset(m_Buffer,0,sizeof(m_Buffer));
|
||||
|
||||
m_nTrisInBuffer=0;
|
||||
}
|
||||
97
Cry3DEngine/cbuffer.h
Normal file
97
Cry3DEngine/cbuffer.h
Normal file
@@ -0,0 +1,97 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cbuffer.h
|
||||
// Version: v1.00
|
||||
// Created: 30/5/2002 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: Occlusion buffer
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef _CBUFFER_H
|
||||
#define _CBUFFER_H
|
||||
|
||||
#define COVERAGEBUFFER_SIZE 128
|
||||
#define COVERAGEBUFFER_OCCLUDERS_MAX_DISTANCE 32
|
||||
#define COVERAGEBUFFER_OCCLUSION_TESTERS_MIN_DISTANCE 32
|
||||
|
||||
class CCoverageBuffer
|
||||
{
|
||||
uchar m_Buffer[COVERAGEBUFFER_SIZE][COVERAGEBUFFER_SIZE];
|
||||
IRenderer * m_pRenderer;
|
||||
int m_matViewPort[4];
|
||||
float m_matCombined[16];
|
||||
Plane m_Planes[6];
|
||||
|
||||
struct Point2d
|
||||
{
|
||||
float x,y;
|
||||
Point2d(){};
|
||||
Point2d(float _x, float _y) { x=_x; y=_y; }
|
||||
Point2d operator - (Point2d & o) { return Point2d (x - o.x,y - o.y); }
|
||||
};
|
||||
|
||||
Point2d ProjectToScreen(const float & x, const float & y, const float & z);
|
||||
void ScanTriangle(Point2d p1,Point2d p2,Point2d p3);
|
||||
void ScanTriangleWithCliping(Point2d p1,Point2d p2,Point2d p3,
|
||||
const Vec3d & v1,const Vec3d & v2,const Vec3d & v3);
|
||||
void ScanLine(int x1, int x2, int y, float & dxdyl, float & dxdyr);
|
||||
bool IsQuadVisible(const Point2d & min2d, const Point2d & max2d);
|
||||
|
||||
#if defined(WIN32) && defined(_CPU_X86)
|
||||
inline int fastfround(float f) // note: only positive numbers works correct
|
||||
{
|
||||
int i;
|
||||
__asm fld [f]
|
||||
__asm fistp [i]
|
||||
return i;
|
||||
}
|
||||
#else
|
||||
inline int fastfround(float f) { int i; i=(int)(f+0.5f); return i; } // note: only positive numbers works correct
|
||||
#endif
|
||||
|
||||
void TransformPoint(float out[4], const float m[16], const float in[4]);
|
||||
void MatMul4( float *product, const float *a, const float *b );
|
||||
static int ClipEdge(const Vec3d & v1, const Vec3d & v2, const Plane & ClipPlane, Vec3d & vRes1, Vec3d & vRes2);
|
||||
|
||||
// tmp containers
|
||||
list2<Vec3d> m_arrVerts3dWS_AddMesh;
|
||||
list2<Point2d> m_arrVerts_AddMesh;
|
||||
|
||||
int m_nTrisInBuffer;
|
||||
|
||||
public:
|
||||
|
||||
CCoverageBuffer(IRenderer * pRenderer)
|
||||
{
|
||||
m_pRenderer = pRenderer;
|
||||
memset(m_Buffer,0,sizeof(m_Buffer));
|
||||
m_nTrisInBuffer=0;
|
||||
}
|
||||
|
||||
// start new frame
|
||||
void BeginFrame(const CCamera & camera);
|
||||
|
||||
// render into buffer
|
||||
void AddBBox(const Vec3d & vMins, const Vec3d & vMaxs, const Vec3d & vDirToCamera);
|
||||
void AddMesh(const Vec3d * arrVerts3d, int nVertCount, const int * pIndices, int nIndCount, Matrix44 * pTranRotMatrix);
|
||||
|
||||
// test visibility
|
||||
bool IsBBoxVisible(const Vec3d & vMins, const Vec3d & vMaxs);
|
||||
bool __IsSphereVisible(const Vec3d & vCenter, float fRadius, float fDistance);
|
||||
bool IsPixelVisible(int nScreenX, int nScreenY);
|
||||
|
||||
// draw content to the screen for debug
|
||||
void DrawDebug(int nStep);
|
||||
|
||||
// can be used by other classes
|
||||
static void ClipPolygon(list2<Vec3d> * pPolygon, const Plane & ClipPlane);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
218
Cry3DEngine/cvars.cpp
Normal file
218
Cry3DEngine/cvars.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cvars.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: console variables used in 3dengine
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "3dEngine.h"
|
||||
#include "irenderer.h"
|
||||
|
||||
// can not be changed by user
|
||||
#define INIT_CVAR_CHEAT(_var,_def_val,_comment)\
|
||||
(_var) = GetConsole()->Register((#_var), &(_var), (_def_val), VF_CHEAT, _comment);
|
||||
|
||||
// can be changed in options menu, will be saved into ini file
|
||||
#define INIT_CVAR_SER__( _var, _def_val,_comment )\
|
||||
( _var ) = GetConsole()->Register( (#_var), &(_var), (_def_val), (e_allow_cvars_serialization ? VF_DUMPTODISK : 0), _comment );
|
||||
|
||||
// can be changed in options menu, will be saved into ini file, require level restart
|
||||
#define INIT_CVAR_SER_R( _var, _def_val,_comment )\
|
||||
( _var ) = GetConsole()->Register( (#_var), &(_var), (_def_val), (e_allow_cvars_serialization ? VF_DUMPTODISK : 0)|VF_REQUIRE_LEVEL_RELOAD, _comment );
|
||||
|
||||
#define INIT_CVAR_SER_R_NET( _var, _def_val,_comment )\
|
||||
( _var ) = GetConsole()->Register( (#_var), &(_var), (_def_val), (e_allow_cvars_serialization ? VF_DUMPTODISK : 0)|VF_REQUIRE_LEVEL_RELOAD|VF_REQUIRE_NET_SYNC, _comment );
|
||||
|
||||
// can be changed by game or user
|
||||
#define INIT_CVAR_PUBL_(_var,_def_val,_comment)\
|
||||
(_var) = GetConsole()->Register((#_var), &(_var), (_def_val), 0, _comment);
|
||||
|
||||
void CVars::Init()
|
||||
{
|
||||
// Ints
|
||||
INIT_CVAR_CHEAT(e_allow_cvars_serialization, 1, "If set to zero - will not save cvars to cfg file");
|
||||
INIT_CVAR_CHEAT(e_detail_objects, 1, "Activates drawing of detail objects");
|
||||
INIT_CVAR_CHEAT(e_fog, 1, "Activates distance based fog");
|
||||
INIT_CVAR_CHEAT(e_motion_blur, 0, "Activates motion blur, values from 1 to 7 will change blur type");
|
||||
INIT_CVAR_SER_R(e_beach, 1, "Activates drawing of shore on the border of the ocean");
|
||||
INIT_CVAR_CHEAT(e_detail_texture, 1, "Activates drawing of detail textures on terrain ground");
|
||||
INIT_CVAR_SER_R(e_detail_texture_quality, 1, "0 - use one single texture per entire level, 1 - use multiple textures");
|
||||
INIT_CVAR_CHEAT(e_particles, 1, "Activates drawing of particles");
|
||||
INIT_CVAR_CHEAT(e_particles_debug, 0, "Debug");
|
||||
INIT_CVAR_SER__(e_particles_max_count, 2048, "Maximum number of particles");
|
||||
INIT_CVAR_SER__(e_decals, 1, "Activates drawing of decals (marks from bullets and explosions)");
|
||||
INIT_CVAR_CHEAT(e_bflyes, 1, "Activates drawing of butterflies around the camera");
|
||||
INIT_CVAR_CHEAT(e_vegetation_bending, 2, "Debug");
|
||||
INIT_CVAR_CHEAT(e_vegetation, 1, "Activates drawing of distributed objects like trees");
|
||||
INIT_CVAR_CHEAT(e_vegetation_sprites, 1, "Activates drawing of sprites instead of distributed objects at far distance");
|
||||
INIT_CVAR_CHEAT(e_entities, 1, "Activates drawing of entities and brushes");
|
||||
INIT_CVAR_CHEAT(e_entities_debug, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_sky_box, 1, "Activates drawing of skybox and moving cloud layers");
|
||||
INIT_CVAR_CHEAT(e_terrain, 1, "Activates drawing of terain ground");
|
||||
INIT_CVAR_CHEAT(e_terrain_debug, 0, "Debug");
|
||||
INIT_CVAR_SER_R(e_shadow_maps, 1, "Activates drawing of shadow maps");
|
||||
INIT_CVAR_SER_R(e_shadow_maps_from_static_objects,1, "Activates drawing of shadow maps from distributed objects");
|
||||
INIT_CVAR_CHEAT(e_water_ocean, 1, "Activates drawing of ocean");
|
||||
INIT_CVAR_CHEAT(e_vegetation_debug, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_shadow_maps_frustums, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_terrain_occlusion_culling, 1, "heightmap occlusion culling with time coherency 0=off, 1=on(distant occluders not processed),\n"
|
||||
"4=on(distant occluders still processed but with less precision) ]");
|
||||
INIT_CVAR_CHEAT(e_terrain_texture_bind, 1, "Debug");
|
||||
INIT_CVAR_CHEAT(e_terrain_log, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_out_space, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_sun, 1, "Activates sun light source");
|
||||
INIT_CVAR_CHEAT(e_terrain_merge_far_sectors, 1, "Render far heightmap sectors as one mesh");
|
||||
INIT_CVAR_CHEAT(e_terrain_texture_mipmaps, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_timedemo_frames, 0, "Will quit appication in X number of frames, r_DisplayInfo must be also enabled");
|
||||
INIT_CVAR_CHEAT(e_timedemo_milliseconds, 0, "Will quit appication in X number of milliseconds");
|
||||
INIT_CVAR_CHEAT(e_terrain_texture_pool, 0, "Debug");
|
||||
|
||||
#ifdef _DEBUG
|
||||
INIT_CVAR_CHEAT(e_cbuffer, 0, "Activates usage of software coverage buffer");
|
||||
#else
|
||||
INIT_CVAR_CHEAT(e_cbuffer, 1, "Activates usage of software coverage buffer");
|
||||
#endif
|
||||
|
||||
INIT_CVAR_SER_R(e_stencil_shadows, 1, "Activates drawing of shadow volumes");
|
||||
INIT_CVAR_CHEAT(e_shadow_maps_debug, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_dynamic_light, 1, "Activates dynamic light sources");
|
||||
INIT_CVAR_CHEAT(e_dynamic_light_exact_vis_test,1, "Use more exact visibility test (based on last draw frame)");
|
||||
INIT_CVAR_CHEAT(e_dynamic_light_debug, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_hw_occlusion_culling_water, 1, "Activates usage of HW occlusion test for ocean");
|
||||
INIT_CVAR_CHEAT(e_hw_occlusion_culling_objects,0, "Activates usage of HW occlusion test for objects");
|
||||
INIT_CVAR_PUBL_(e_hires_screenshoot, 0, "Writes screenshot to disk, X is scale of image resolution relative to current one, big values can cause crash");
|
||||
INIT_CVAR_CHEAT(e_portals, 1, "Activates drawing of visareas content (indoors), values 2,3,4 used for debugging");
|
||||
INIT_CVAR_SER__(e_max_entity_lights, 4, "Set maximum number of lights affecting object");
|
||||
INIT_CVAR_PUBL_(e_max_shadow_map_size, 512, "Set maximum resolution of shadow map, this value is alos limited by screen resolution in OpenGL");
|
||||
INIT_CVAR_CHEAT(e_water_volumes, 1, "Activates drawing of water volumes");
|
||||
INIT_CVAR_CHEAT(e_bboxes, 0, "Activates drawing of bounding boxes");
|
||||
INIT_CVAR_CHEAT(e_register_in_sectors, 1, "Debug, can cause crash");
|
||||
INIT_CVAR_CHEAT(e_stream_cgf, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_stream_for_physics, 1, "Debug");
|
||||
INIT_CVAR_CHEAT(e_stream_for_visuals, 1, "Debug");
|
||||
INIT_CVAR_CHEAT(e_scissor_debug, 0, "Debug");
|
||||
INIT_CVAR_CHEAT(e_projector_exact_test, 1, "Debug");
|
||||
INIT_CVAR_CHEAT(e_ccgf_load, 0, "Load CCGF if found");
|
||||
INIT_CVAR_CHEAT(e_ccgf_make_if_not_found, 0, "Make CCGF if not found");
|
||||
INIT_CVAR_CHEAT(e_check_number_of_physicalized_polygons, 1,
|
||||
"Activates check (during loading) for number of tris in the objects physics representation\n Current maximum is 100 + overall number of tris divided by 2");
|
||||
INIT_CVAR_CHEAT(e_materials, 1, "Activates material support for non animated objects");
|
||||
INIT_CVAR_CHEAT(e_vegetation_sprites_slow_switch, 1, "Orient 3d vegetations and sprites to much each other");
|
||||
INIT_CVAR_CHEAT(e_terrain_single_pass, 1, "Draw all terrain detail layers in single pass");
|
||||
INIT_CVAR_CHEAT(e_light_maps, 1, "Use lightmaps on brushes");
|
||||
INIT_CVAR_CHEAT(e_stream_areas, 0, "Stream content of terrain and indoor sectors");
|
||||
INIT_CVAR_CHEAT(e_stream_preload_textures, 0, "If texture streaming in renderer enabled - dynamicaly preload textures in x neibhour indoor sectors");
|
||||
INIT_CVAR_CHEAT(e_area_merging_distance, 0, "Merge sectror geometry in specified range for rendering speedup");
|
||||
INIT_CVAR_CHEAT(e_area_merging_draw_merged_geometry_only, 0, "Do not draw not merged objects");
|
||||
INIT_CVAR_CHEAT(e_brushes, 1, "Draw brushes");
|
||||
INIT_CVAR_CHEAT(e_brushes_merging_debug, 0, "Print debug info of merged brushes");
|
||||
INIT_CVAR_SER_R(e_brushes_merging, 1, "Merge marked brushes during loading");
|
||||
INIT_CVAR_CHEAT(e_brushes_onlymerged, 0, "Show only merged brushes");
|
||||
INIT_CVAR_CHEAT(e_on_demand_physics, 0, "Turns on on-demand physicalization");
|
||||
INIT_CVAR_SER_R(e_light_maps_quality, 1, "define quality for lightmaps (0-2)");
|
||||
INIT_CVAR_CHEAT(e_sleep, 0, "Sleep X in C3DEngine::Draw");
|
||||
INIT_CVAR_CHEAT(e_objects, 1, "Render or not all objects on terrain");
|
||||
INIT_CVAR_CHEAT(e_terrain_draw_this_sector_only, 0, "1 - render only sector where camera is and objects registered in sector 00, 2 - render only sector where camera is");
|
||||
INIT_CVAR_CHEAT(e_sun_stencil, 0, "Enable stencil shadows from sun light");
|
||||
INIT_CVAR_CHEAT(e_terrain_single_pass_vol_fog,0, "Use single pass volumetric fog on terrain where possible");
|
||||
INIT_CVAR_CHEAT(e_occlusion_volumes, 1, "Enable occlusion volumes(antiportals)");
|
||||
INIT_CVAR_CHEAT(e_terrain_texture_mip_offset, 0, "Allows to reduce terrain texture resolution by selecting more low mips from texture file");
|
||||
INIT_CVAR_SER__(e_overlay_geometry, 1, "Enable rendering of overlay geometry");
|
||||
INIT_CVAR_CHEAT(e_player, 1, "Draw main player");
|
||||
INIT_CVAR_CHEAT(e_vegetation_sprites_texres, 0, "Sprite texture size modifier. 0 - no scale, 1 - scale 2 times down and so on");
|
||||
INIT_CVAR_SER__(e_active_shadow_maps_receving,0, "Allow shadow map receiving from all objects");
|
||||
INIT_CVAR_PUBL_(e_shadow_maps_fade_from_light_bit, 1, "Fade shadow maps on terrain if caster is in dark area");
|
||||
INIT_CVAR_PUBL_(e_capture_frames, 0, "If set to 1 - will save every frame to tga file");
|
||||
INIT_CVAR_PUBL_(e_water_ocean_tesselation, -1, "0 - default tesselation, 2 - high tesselation, -1 - select automatically depends on per pixel projection support");
|
||||
INIT_CVAR_PUBL_(e_shadow_maps_size_ratio, 500,"Controls how shadow map resolution depends from distance to object from camera");
|
||||
INIT_CVAR_SER__(e_shadow_spots, 0, "Draw shadow spot under entities");
|
||||
INIT_CVAR_SER_R(e_use_global_fog_in_fog_volumes,0, "simulate ocean volume fog using global fog");
|
||||
INIT_CVAR_CHEAT(e_precache_level, 1, "Pre-render objects right after level loading");
|
||||
INIT_CVAR_PUBL_(e_shadow_maps_max_casters_per_object, 8, "Maximum number of active shadow casters per object");
|
||||
INIT_CVAR_PUBL_(e_water_ocean_sun_reflection, 0, "Draw sun reflection in the ocean");
|
||||
INIT_CVAR_CHEAT(e_objects_fade_on_distance, 1, "Objects fading out on distance");
|
||||
INIT_CVAR_PUBL_(e_area_merging_max_tris_in_input_brush, 512, "Merge only objects containing no more than x triangles");
|
||||
INIT_CVAR_SER__(e_stencil_shadows_only_from_strongest_light, 0, "Cast no more than one stencil shadow from object");
|
||||
INIT_CVAR_SER_R(e_cgf_load_lods, 1, "Load LOD models for CGFs if found");
|
||||
INIT_CVAR_CHEAT(e_optimized_render_object, 1, "test");
|
||||
INIT_CVAR_CHEAT(e_stencil_shadows_build_on_load, 1, "Build connectivity during level loading");
|
||||
INIT_CVAR_PUBL_(e_vegetation_update_shadow_every_frame, 1, "Allow updating vegetations shadow maps every frame");
|
||||
INIT_CVAR_CHEAT(e_particles_receive_shadows, 0, "Enable shadow maps receiving for particles");
|
||||
INIT_CVAR_CHEAT(e_light_maps_occlusion, 0, "Enable usage of occlusion maps");
|
||||
INIT_CVAR_CHEAT(e_shadow_maps_self_shadowing, 0, "Allow self-shadowing with shadow maps");
|
||||
INIT_CVAR_CHEAT(e_voxel_build, 0, "Regenerate voxel world");
|
||||
INIT_CVAR_CHEAT(e_voxel_debug, 0, "Draw voxel debug info");
|
||||
INIT_CVAR_CHEAT(e_voxel_realtime_light_update,0, "Recalculate voxel terrain vertex colors every frame");
|
||||
INIT_CVAR_CHEAT(e_widescreen, 0, "Activate wide screen mode");
|
||||
INIT_CVAR_PUBL_(e_shadow_maps_receiving, 1, "Allow shadow maps receiving by brushes, vegetation and entities");
|
||||
|
||||
// Floats
|
||||
INIT_CVAR_PUBL_(e_vegetation_sprites_min_distance, 8.0f, "Sets minimal distance when distributed object can be replaced with sprite");
|
||||
INIT_CVAR_PUBL_(e_rain_amount, 0.0f, "Values between 0 and 1 controls density of the rain");
|
||||
INIT_CVAR_SER__(e_vegetation_sprites_distance_ratio, 1.0f, "Allows changing distance on what vegetation switch into sprite");
|
||||
INIT_CVAR_SER__(e_obj_lod_ratio, 10.0f, "LOD for vegetation, brushes and entities");
|
||||
INIT_CVAR_CHEAT(e_obj_view_dist_ratio, 55.0f, "View distance for vegetation, brushes and entities");
|
||||
INIT_CVAR_CHEAT(e_dynamic_ambient_ratio, 1.0f, "Controls how object ambient level dependinds from surrounding lights");
|
||||
INIT_CVAR_PUBL_(e_detail_texture_min_fov,0.55f,"If FOV is less - alternative version of terrain detail texturing will be used");
|
||||
INIT_CVAR_SER_R_NET(e_vegetation_min_size, 0.0f, "Minimal size of static object, smaller objects will be not rendered");
|
||||
INIT_CVAR_CHEAT(e_terrain_occlusion_culling_precision, 0.15f, "Density of rays");
|
||||
INIT_CVAR_PUBL_(e_terrain_lod_ratio, 1.f, "Set heightmap LOD");
|
||||
INIT_CVAR_SER__(e_particles_lod, 1.f, "1 - full LOD, 0.5 - scale frequency and count down twice");
|
||||
INIT_CVAR_CHEAT(e_debug_lights, 0, "Use different colors for objects affected by different number of lights\n 0 - back, 1 - blue, 2 - green, 3 or more - red");
|
||||
INIT_CVAR_SER__(e_shadow_maps_view_dist_ratio, 10, "View dist ratio for shadow maps");
|
||||
INIT_CVAR_SER__(e_decals_life_time_scale, 1.f, "Allows to increase or reduce decals life time for different specs");
|
||||
INIT_CVAR_CHEAT(e_obj_min_view_dist, 0.f, "Min distance on what far objects will be culled out");
|
||||
INIT_CVAR_CHEAT(e_decals_neighbor_max_life_time, 4.f, "If not zero - new decals will force old decals to fade in X seconds");
|
||||
INIT_CVAR_CHEAT(e_explosion_scale, 0.6666f, "Scale size of terrain deformations and explosion decals");
|
||||
|
||||
e_capture_folder = GetConsole()->CreateVariable("e_capture_folder", "CaptureOutput", 0, "Set output folder for video capturing");
|
||||
e_capture_file_format = GetConsole()->CreateVariable("e_capture_file_format", "JPG", 0, "Set output image file format for video capturing. Can be JPG or TGA");
|
||||
|
||||
e_deformable_terrain = GetConsole()->CreateVariable("e_deformable_terrain","1",VF_REQUIRE_NET_SYNC,
|
||||
"Toggles terrain deforming.\n"
|
||||
"Usage: e_deformable_terrain [0/1]\n"
|
||||
"Default is 1 (on). Terrain is deformed by explosions. Set\n"
|
||||
"to 0 to disable terrain deforming.");
|
||||
|
||||
if(e_water_ocean_tesselation<0)
|
||||
{
|
||||
ICVar * pVar = GetConsole()->GetCVar("e_water_ocean_tesselation");
|
||||
if(GetRenderer()->GetFeatures()&RFT_HW_ENVBUMPPROJECTED)
|
||||
pVar->Set(0);
|
||||
else
|
||||
pVar->Set(1);
|
||||
}
|
||||
|
||||
// vars validation
|
||||
if(ICVar * pVar0 = GetConsole()->GetCVar("r_Quality_BumpMapping"))
|
||||
if(pVar0->GetIVal()==0)
|
||||
{
|
||||
if(ICVar * pVar1 = GetConsole()->GetCVar("e_shadow_maps"))
|
||||
pVar1->Set(0);
|
||||
if(ICVar * pVar1 = GetConsole()->GetCVar("e_stencil_shadows"))
|
||||
pVar1->Set(0);
|
||||
}
|
||||
|
||||
int nGPU = GetRenderer()->GetFeatures() & RFT_HW_MASK;
|
||||
if(nGPU == RFT_HW_GF2)
|
||||
{
|
||||
if(ICVar * pVar1 = GetConsole()->GetCVar("e_detail_texture_quality"))
|
||||
pVar1->Set(0);
|
||||
}
|
||||
|
||||
if(!(GetRenderer()->GetFeatures() & (RFT_DEPTHMAPS|RFT_SHADOWMAP_SELFSHADOW)))
|
||||
{
|
||||
if(ICVar * pVar1 = GetConsole()->GetCVar("e_shadow_maps_receiving"))
|
||||
pVar1->Set(0);
|
||||
}
|
||||
}
|
||||
171
Cry3DEngine/cvars.h
Normal file
171
Cry3DEngine/cvars.h
Normal file
@@ -0,0 +1,171 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: cvars.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _3DENGINE_CVARS_H_
|
||||
#define _3DENGINE_CVARS_H_
|
||||
|
||||
// console variables
|
||||
struct CVars : public Cry3DEngineBase
|
||||
{
|
||||
CVars()
|
||||
{ Init(); }
|
||||
|
||||
void Init();
|
||||
|
||||
int
|
||||
e_allow_cvars_serialization,
|
||||
e_shadow_maps,
|
||||
e_shadow_maps_debug,
|
||||
e_shadow_maps_from_static_objects,
|
||||
e_shadow_maps_self_shadowing,
|
||||
e_shadow_maps_receiving,
|
||||
e_detail_objects,
|
||||
e_fog,
|
||||
e_motion_blur,
|
||||
e_beach,
|
||||
e_detail_texture,
|
||||
e_detail_texture_quality,
|
||||
e_particles,
|
||||
e_particles_debug,
|
||||
e_particles_max_count,
|
||||
e_particles_receive_shadows,
|
||||
e_decals,
|
||||
e_bflyes,
|
||||
e_vegetation_bending,
|
||||
e_vegetation,
|
||||
e_vegetation_sprites,
|
||||
e_entities,
|
||||
e_entities_debug,
|
||||
e_sky_box,
|
||||
e_terrain,
|
||||
e_terrain_debug,
|
||||
e_water_ocean,
|
||||
e_vegetation_debug,
|
||||
e_shadow_maps_frustums,
|
||||
e_terrain_occlusion_culling,
|
||||
e_terrain_texture_pool,
|
||||
e_terrain_texture_bind,
|
||||
e_terrain_log,
|
||||
e_out_space,
|
||||
e_video_buffer_stats,
|
||||
e_sun,
|
||||
e_terrain_merge_far_sectors,
|
||||
e_terrain_texture_mipmaps,
|
||||
e_terrain_texture_mip_offset,
|
||||
|
||||
// if set to non-0, then after the specified number of frames rendered,
|
||||
// the game exits printing the average FPS value.
|
||||
// NOTE:
|
||||
// for this to work, the r_DisplayInfo must be "1"
|
||||
e_timedemo_frames,
|
||||
|
||||
// if set to non-0, then after the specified number of milliseconds of rendering,
|
||||
// the game exists unconditionally. This is used for automatic multipass profiling with VTune 6.x
|
||||
e_timedemo_milliseconds,
|
||||
|
||||
e_cbuffer,
|
||||
e_dynamic_light,
|
||||
e_dynamic_light_exact_vis_test,
|
||||
e_stencil_shadows,
|
||||
e_dynamic_light_debug,
|
||||
e_hw_occlusion_culling_water,
|
||||
e_hw_occlusion_culling_objects,
|
||||
e_hires_screenshoot,
|
||||
e_portals,
|
||||
e_max_entity_lights,
|
||||
e_max_shadow_map_size,
|
||||
e_water_volumes,
|
||||
e_bboxes,
|
||||
e_brushes,
|
||||
e_brushes_merging_debug,
|
||||
e_brushes_merging,
|
||||
e_brushes_onlymerged,
|
||||
e_register_in_sectors,
|
||||
e_stream_cgf,
|
||||
e_stream_for_physics,
|
||||
e_stream_for_visuals,
|
||||
e_stream_areas,
|
||||
e_scissor_debug,
|
||||
e_projector_exact_test,
|
||||
e_ccgf_load,
|
||||
e_ccgf_make_if_not_found,
|
||||
e_check_number_of_physicalized_polygons,
|
||||
e_materials,
|
||||
e_vegetation_sprites_slow_switch,
|
||||
e_terrain_single_pass,
|
||||
e_stream_preload_textures,
|
||||
e_area_merging_distance,
|
||||
e_area_merging_draw_merged_geometry_only,
|
||||
e_area_merging_max_tris_in_input_brush,
|
||||
e_on_demand_physics,
|
||||
e_light_maps,
|
||||
e_light_maps_quality,
|
||||
e_light_maps_occlusion,
|
||||
e_sleep,
|
||||
e_objects,
|
||||
e_terrain_draw_this_sector_only,
|
||||
e_sun_stencil,
|
||||
e_terrain_single_pass_vol_fog,
|
||||
e_occlusion_volumes,
|
||||
e_overlay_geometry,
|
||||
e_player,
|
||||
e_vegetation_sprites_texres,
|
||||
e_active_shadow_maps_receving,
|
||||
e_shadow_maps_fade_from_light_bit,
|
||||
e_capture_frames,
|
||||
e_water_ocean_tesselation,
|
||||
e_shadow_maps_size_ratio,
|
||||
e_shadow_spots,
|
||||
e_use_global_fog_in_fog_volumes,
|
||||
e_precache_level,
|
||||
e_shadow_maps_max_casters_per_object,
|
||||
e_water_ocean_sun_reflection,
|
||||
e_objects_fade_on_distance,
|
||||
e_stencil_shadows_only_from_strongest_light,
|
||||
e_cgf_load_lods,
|
||||
e_optimized_render_object,
|
||||
e_stencil_shadows_build_on_load,
|
||||
e_vegetation_update_shadow_every_frame,
|
||||
e_voxel_build,
|
||||
e_voxel_debug,
|
||||
e_voxel_realtime_light_update,
|
||||
e_widescreen;
|
||||
|
||||
float
|
||||
e_vegetation_sprites_min_distance,
|
||||
e_rain_amount,
|
||||
e_vegetation_sprites_distance_ratio,
|
||||
e_obj_lod_ratio,
|
||||
e_obj_view_dist_ratio,
|
||||
e_dynamic_ambient_ratio,
|
||||
e_detail_texture_min_fov,
|
||||
e_terrain_occlusion_culling_precision,
|
||||
e_vegetation_min_size,
|
||||
e_terrain_lod_ratio,
|
||||
e_particles_lod,
|
||||
e_debug_lights,
|
||||
e_shadow_maps_view_dist_ratio,
|
||||
e_decals_life_time_scale,
|
||||
e_decals_neighbor_max_life_time,
|
||||
e_obj_min_view_dist,
|
||||
e_explosion_scale;
|
||||
|
||||
ICVar
|
||||
* e_capture_folder,
|
||||
* e_capture_file_format,
|
||||
* e_deformable_terrain;
|
||||
};
|
||||
|
||||
#endif // _3DENGINE_CVARS_H_
|
||||
103
Cry3DEngine/dds.h
Normal file
103
Cry3DEngine/dds.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// dds.h
|
||||
//
|
||||
// This header defines constants and structures that are useful when parsing
|
||||
// DDS files. DDS files were originally designed to use several structures
|
||||
// and constants that are native to DirectDraw and are defined in ddraw.h,
|
||||
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
|
||||
// (compatible) constants and structures so that one can use DDS files
|
||||
// without needing to include ddraw.h.
|
||||
|
||||
#ifndef _DDS_H_
|
||||
#define _DDS_H_
|
||||
|
||||
struct DDS_PIXELFORMAT
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwFourCC;
|
||||
DWORD dwRGBBitCount;
|
||||
DWORD dwRBitMask;
|
||||
DWORD dwGBitMask;
|
||||
DWORD dwBBitMask;
|
||||
DWORD dwABitMask;
|
||||
};
|
||||
|
||||
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
|
||||
#define DDS_RGB 0x00000040 // DDPF_RGB
|
||||
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT1 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT2 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT3 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
|
||||
|
||||
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
|
||||
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
|
||||
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
|
||||
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
|
||||
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
|
||||
|
||||
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
|
||||
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
|
||||
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
|
||||
|
||||
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
|
||||
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
|
||||
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
|
||||
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
|
||||
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
|
||||
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
|
||||
|
||||
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
|
||||
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
|
||||
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
|
||||
|
||||
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
|
||||
|
||||
#define DDS_RESF1_NORMALMAP 0x01000000
|
||||
#define DDS_RESF1_DSDT 0x02000000
|
||||
|
||||
|
||||
struct DDS_HEADER
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwHeaderFlags;
|
||||
DWORD dwHeight;
|
||||
DWORD dwWidth;
|
||||
DWORD dwPitchOrLinearSize;
|
||||
DWORD dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags
|
||||
DWORD dwMipMapCount;
|
||||
DWORD dwReserved1[11];
|
||||
DDS_PIXELFORMAT ddspf;
|
||||
DWORD dwSurfaceFlags;
|
||||
DWORD dwCubemapFlags;
|
||||
DWORD dwReserved2[3];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
679
Cry3DEngine/detail_grass.cpp
Normal file
679
Cry3DEngine/detail_grass.cpp
Normal file
@@ -0,0 +1,679 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: detail_grass.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: create and draw grass/detail object volume right in front of camera
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "statobj.h"
|
||||
#include "detail_grass.h"
|
||||
|
||||
#include <IXMLDOM.h>
|
||||
|
||||
// class to store vertex buffer for single grass object
|
||||
struct GrassType : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pVertices;
|
||||
uint * uipIndices, nIndCount, nVertCount;
|
||||
int nTexID;
|
||||
char sObjectFileName[256];
|
||||
CStatObj * m_pObject;
|
||||
|
||||
GrassType(char * fname)
|
||||
{ // load object and make buffers
|
||||
memset(this,0,sizeof(*this));
|
||||
strncpy(sObjectFileName,fname,sizeof(sObjectFileName));
|
||||
|
||||
m_pObject = new CStatObj( );
|
||||
if(!m_pObject->Load(fname, NULL, evs_ShareAndSortForCache, false, false))
|
||||
{
|
||||
delete m_pObject;
|
||||
m_pObject=0;
|
||||
return;
|
||||
}
|
||||
|
||||
int tris_count = 0;
|
||||
CLeafBuffer * pLeafBuffer = m_pObject->GetLeafBuffer();
|
||||
|
||||
if(!pLeafBuffer)
|
||||
return; // objects may have no leaf buffer created on dedicated server
|
||||
|
||||
pLeafBuffer->GetIndices(&tris_count);
|
||||
tris_count/=3;
|
||||
|
||||
if(tris_count>12)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"Detail object has more than 12 triangles, skiped: %s (%d tris)",fname,tris_count );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
nVertCount = pLeafBuffer->m_SecVertCount;
|
||||
|
||||
pVertices = new struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F[nVertCount];
|
||||
uipIndices = new uint[tris_count*3];
|
||||
|
||||
Vec3d vCenter = (m_pObject->GetBoxMax()+m_pObject->GetBoxMin())/2;
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pSecVerts = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F*)pLeafBuffer->m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
|
||||
ushort *pInds = pLeafBuffer->GetIndices(NULL);
|
||||
int nStrPos;
|
||||
byte *pPos = pLeafBuffer->GetPosPtr(nStrPos, 0, true);
|
||||
int nStrST;
|
||||
byte *pST = pLeafBuffer->GetUVPtr(nStrST, 0, true);
|
||||
|
||||
for(int i=0; i<tris_count*3; i++)
|
||||
{
|
||||
uint id = pInds[i];
|
||||
Vec3d *vSrcPos = (Vec3d *)&pPos[nStrPos*id];
|
||||
float *fSrcST = (float *)&pST[nStrST*id];
|
||||
|
||||
pVertices[id].xyz.x = vSrcPos->x - vCenter.x;
|
||||
pVertices[id].xyz.y = vSrcPos->y - vCenter.y;
|
||||
pVertices[id].xyz.z = vSrcPos->z;// - pObject->GetBoxMin().z;
|
||||
pVertices[id].st[0] = fSrcST[0];
|
||||
pVertices[id].st[1] = fSrcST[1];
|
||||
|
||||
/* if(pLeafBuffer->m_pLoadedColors)
|
||||
{
|
||||
pVertices[id].r = pSecVerts[id].color[0];
|
||||
pVertices[id].g = pSecVerts[id].color[1];
|
||||
pVertices[id].b = pSecVerts[id].color[2];
|
||||
pVertices[id].a = 255;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
pVertices[id].color.dcolor = -1;
|
||||
}
|
||||
|
||||
uipIndices[nIndCount++] = id;
|
||||
}
|
||||
|
||||
if( m_pObject->GetLeafBuffer()->m_pMats->Count() &&
|
||||
m_pObject->GetLeafBuffer()->m_pMats->Get(0)->shaderItem.m_pShader &&
|
||||
m_pObject->GetLeafBuffer()->m_pMats->Get(0)->shaderItem.m_pShaderResources->m_Textures[EFTT_DIFFUSE] &&
|
||||
m_pObject->GetLeafBuffer()->m_pMats->Get(0)->shaderItem.m_pShaderResources->m_Textures[EFTT_DIFFUSE]->m_TU.m_ITexPic )
|
||||
{
|
||||
nTexID = (m_pObject->GetLeafBuffer()->m_pMats->Get(0)->shaderItem.m_pShaderResources->m_Textures[EFTT_DIFFUSE]->m_TU.m_ITexPic)->GetTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
nTexID = GetRenderer()->LoadTexture("none");
|
||||
}
|
||||
|
||||
// assert(nTexID>=4096);
|
||||
}
|
||||
|
||||
~GrassType()
|
||||
{
|
||||
delete m_pObject;
|
||||
delete [] pVertices;
|
||||
delete [] uipIndices;
|
||||
}
|
||||
|
||||
int GetMemoryUsage()
|
||||
{
|
||||
return sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F) * nVertCount + sizeof(uint) * nIndCount;
|
||||
}
|
||||
};
|
||||
|
||||
// load objects
|
||||
CDetailGrass::CDetailGrass(XDOM::IXMLDOMNodeListPtr pDetTexTagList)
|
||||
{
|
||||
memset(this,0,sizeof(*this));
|
||||
|
||||
// m_pGrassVertices = 0;
|
||||
m_GrassVerticesCount = 0;
|
||||
m_GrassFocusX = m_GrassFocusY = -CTerrain::GetTerrainSize(); // grass focus
|
||||
m_nGrassDensity = 2;
|
||||
|
||||
if( !m_nGrassDensity )
|
||||
return;
|
||||
|
||||
UpdateLoadingScreen("Loading detail objects ...");
|
||||
m_GrassModelsArray.Clear();
|
||||
|
||||
// load detail textures
|
||||
if (pDetTexTagList)
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pDetTexTag;
|
||||
pDetTexTagList->reset();
|
||||
pDetTexTag = pDetTexTagList->nextNode();
|
||||
XDOM::IXMLDOMNodeListPtr pDetTexList;
|
||||
pDetTexList = pDetTexTag->getElementsByTagName("SurfaceType");
|
||||
if (pDetTexList)
|
||||
{
|
||||
pDetTexList->reset();
|
||||
XDOM::IXMLDOMNodePtr pDetTex;
|
||||
int nId = 0;
|
||||
while (pDetTex = pDetTexList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pDetailObjectsList = pDetTex->getElementsByTagName("DetailObjects");
|
||||
pDetailObjectsList->reset();
|
||||
XDOM::IXMLDOMNodePtr pDetailObject;
|
||||
while(pDetailObject = pDetailObjectsList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodeListPtr pObjList = pDetailObject->getElementsByTagName("Object");
|
||||
if(pObjList)
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pObj;
|
||||
pObjList->reset();
|
||||
while(pObj = pObjList->nextNode())
|
||||
{
|
||||
XDOM::IXMLDOMNodePtr pName = pObj->getAttribute("Name");
|
||||
char sObjectsName[256];
|
||||
strcpy(sObjectsName,pName->getText());
|
||||
if(!sObjectsName[0])
|
||||
break;
|
||||
|
||||
// try to find already loaded
|
||||
int l=0;
|
||||
for(l=0; l<m_GrassModelsArray.Count(); l++)
|
||||
{
|
||||
if(strcmp(m_GrassModelsArray[l]->sObjectFileName,sObjectsName)==0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(l>=m_GrassModelsArray.Count())
|
||||
{ // not found
|
||||
GrassType * triData = new GrassType( sObjectsName );
|
||||
|
||||
if(triData && (*triData).nIndCount)
|
||||
m_GrassModelsArray.Add(triData);
|
||||
else
|
||||
{
|
||||
delete triData;
|
||||
break;
|
||||
}
|
||||
|
||||
m_arrlstSurfaceObjects[nId].Add(triData);
|
||||
}
|
||||
else
|
||||
{ // use already loaded
|
||||
m_arrlstSurfaceObjects[nId].Add(m_GrassModelsArray[l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateLoadingScreen(" %d detail objects loaded", m_GrassModelsArray.Count());
|
||||
|
||||
m_GrassTID = 4096;
|
||||
for(int t=0; t<m_GrassModelsArray.Count(); t++)
|
||||
{
|
||||
if(m_GrassModelsArray[t]->nTexID && m_GrassModelsArray[t]->nTexID != 4096)
|
||||
{ // if some valid texture found - ise it for all objects
|
||||
m_GrassTID = m_GrassModelsArray[t]->nTexID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_GrassTID && m_GrassModelsArray.Count())
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
Warning( 0,0,"Texture for detail objects was not loaded");
|
||||
#endif
|
||||
m_GrassTID = 0x1000;
|
||||
}
|
||||
|
||||
if(!m_GrassModelsArray.Count())
|
||||
return;
|
||||
|
||||
m_pShader = GetRenderer()->EF_LoadShader("TerrainDetailObjects", eSH_World, 0);
|
||||
|
||||
// make leaf buffer
|
||||
// m_pGrassVertices = new struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F[DETAIL_GRASS_PIP_BUFFER_SIZE];
|
||||
m_GrassIndices.PreAllocate(DETAIL_GRASS_PIP_BUFFER_SIZE*3,DETAIL_GRASS_PIP_BUFFER_SIZE*3);
|
||||
|
||||
m_pLeafBuffer = GetRenderer()->CreateLeafBufferInitialized(
|
||||
0/*m_pGrassVertices*/, DETAIL_GRASS_PIP_BUFFER_SIZE, VERTEX_FORMAT_P3F_COL4UB_TEX2F,
|
||||
m_GrassIndices.GetElements(), m_GrassIndices.Count(), R_PRIMV_TRIANGLES, "Grass", eBT_Dynamic, 1 , 0, PrepareBufferCallback, this);
|
||||
m_pLeafBuffer->SetRECustomData(m_arrfShaderInfo);
|
||||
|
||||
assert(m_pLeafBuffer);
|
||||
|
||||
m_pLeafBuffer->SetChunk(m_pShader,0,DETAIL_GRASS_PIP_BUFFER_SIZE,0,m_GrassIndices.Count(),0);
|
||||
}
|
||||
|
||||
bool CDetailGrass::PrepareBufferCallback(CLeafBuffer * pLeafBuffer, bool bNeedTangents)
|
||||
{
|
||||
CDetailGrass * pThis = (CDetailGrass *)pLeafBuffer->m_pCustomData;
|
||||
|
||||
// if(pTerrain->m_nRenderStackLevel==0)
|
||||
{
|
||||
// Matrix44 mat;
|
||||
// pThis->GetRenderer()->GetModelViewMatrix(mat.GetData());
|
||||
Vec3d forward = -pThis->GetViewCamera().GetVCMatrixD3D9().GetColumn(2);
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//forward(-mat.cell(2), -mat.cell(6), -mat.cell(10));
|
||||
|
||||
forward.Normalize();
|
||||
|
||||
if(!forward.x && !forward.y)
|
||||
return false;
|
||||
|
||||
Vec3d vCamPos = pThis->GetViewCamera().GetPos();
|
||||
|
||||
int c_X = int(vCamPos.x + forward.x*CAMERA_GRASS_SHIFT);
|
||||
int c_Y = int(vCamPos.y + forward.y*CAMERA_GRASS_SHIFT);
|
||||
|
||||
// GetRenderer()->DrawBall(c_X,c_Y,m_pTerrain->GetZApr(c_X,c_Y),1);
|
||||
|
||||
// check focus
|
||||
float dx = float(c_X-pThis->m_GrassFocusX);
|
||||
float dy = float(c_Y-pThis->m_GrassFocusY);
|
||||
|
||||
float d2 = (dx*dx+dy*dy);
|
||||
|
||||
if(d2>16 && pThis->m_pTerrain)
|
||||
{
|
||||
pThis->m_GrassFocusX = c_X;
|
||||
pThis->m_GrassFocusY = c_Y;
|
||||
|
||||
if(pLeafBuffer->m_pVertexBuffer && pLeafBuffer->m_pVertexBuffer->m_vertexformat == VERTEX_FORMAT_P3F_COL4UB_TEX2F)
|
||||
{
|
||||
pThis->GetRenderer()->UpdateBuffer(pLeafBuffer->m_pVertexBuffer,0,0,0);
|
||||
pThis->CreateSectorGrass(int(CAMERA_GRASS_SHIFT+2),int(1),
|
||||
(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F*)pLeafBuffer->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData);
|
||||
|
||||
// unlock
|
||||
pThis->GetRenderer()->UpdateBuffer(pLeafBuffer->m_pVertexBuffer, NULL, 0, true, 0, 1);
|
||||
|
||||
//pLeafBuffer->UpdateSysIndices(pThis->m_GrassIndices.GetElements(), pThis->m_GrassIndices.Count());
|
||||
pLeafBuffer->UpdateVidIndices(pThis->m_GrassIndices.GetElements(), pThis->m_GrassIndices.Count());
|
||||
|
||||
if(pThis->m_GrassIndices.Count()==0)
|
||||
pLeafBuffer->SetChunk(pThis->m_pShader,0,-1,0,-1,0);
|
||||
else
|
||||
pLeafBuffer->SetChunk(pThis->m_pShader,0,pThis->m_GrassVerticesCount,0,pThis->m_GrassIndices.Count(),0);
|
||||
|
||||
|
||||
pLeafBuffer->SetShader(pThis->m_pShader,pThis->m_GrassTID);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// set alpha glow texgen params
|
||||
const float fDistFadeK = 1.f/(CAMERA_GRASS_SHIFT*4.f);
|
||||
pThis->m_arrfShaderInfo[2] = fDistFadeK;
|
||||
pThis->m_arrfShaderInfo[3] = 0.5f-vCamPos.y*fDistFadeK;
|
||||
pThis->m_arrfShaderInfo[4] = 0.5f-vCamPos.x*fDistFadeK;
|
||||
// assert(pThis->m_pLeafBuffer && pThis->m_pLeafBuffer == pLeafBuffer);
|
||||
if(pThis->m_pLeafBuffer) // lb may be not created yet, this call can come from CreateLeafBufferInitialized()
|
||||
pThis->m_pLeafBuffer->SetRECustomData(pThis->m_arrfShaderInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CDetailGrass::~CDetailGrass()
|
||||
{
|
||||
for(int i=0; i<m_GrassModelsArray.Count(); i++)
|
||||
delete m_GrassModelsArray[i];
|
||||
|
||||
m_GrassModelsArray.Reset();
|
||||
|
||||
if(m_pLeafBuffer)
|
||||
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
|
||||
m_pLeafBuffer=0;
|
||||
|
||||
// delete [] m_pGrassVertices; m_pGrassVertices=0;
|
||||
|
||||
/// GetRenderer()->RemoveTexture(m_GrassTID);
|
||||
}
|
||||
|
||||
// copy object into buffer
|
||||
void CDetailGrass::AddIndexedArray(GrassType * o, float X, float Y, float Z, float fObjBr,
|
||||
float fSizeRatio, float fXSign, float fYSign, int nSwapXY,
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices)
|
||||
{
|
||||
if(fObjBr > 1.f)
|
||||
fObjBr = 1.f;
|
||||
|
||||
fObjBr *= 255.f;
|
||||
|
||||
assert(o->nIndCount%3 == 0);
|
||||
|
||||
for( uint i=0; i<o->nIndCount; i+=3 )
|
||||
{
|
||||
assert(o->uipIndices[i]<o->nVertCount);
|
||||
m_GrassIndices.Add(o->uipIndices[i+0] + m_GrassVerticesCount);
|
||||
|
||||
assert(o->uipIndices[i+1]<o->nVertCount);
|
||||
m_GrassIndices.Add(o->uipIndices[i+1] + m_GrassVerticesCount);
|
||||
|
||||
assert(o->uipIndices[i+2]<o->nVertCount);
|
||||
m_GrassIndices.Add(o->uipIndices[i+2] + m_GrassVerticesCount);
|
||||
}
|
||||
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pVert = &pGrassVertices[m_GrassVerticesCount];
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pSourceVert = &o->pVertices[0];
|
||||
|
||||
unsigned char grass_r = (unsigned char)fObjBr;
|
||||
unsigned char grass_g = (unsigned char)fObjBr;
|
||||
unsigned char grass_b = (unsigned char)fObjBr;
|
||||
|
||||
for(uint v=0; v<o->nVertCount; v++)
|
||||
{
|
||||
switch(nSwapXY)
|
||||
{
|
||||
case 0:
|
||||
pVert->xyz.x = (pSourceVert->xyz.x*fSizeRatio)*fXSign + X;
|
||||
pVert->xyz.y = (pSourceVert->xyz.y*fSizeRatio)*fYSign + Y;
|
||||
pVert->xyz.z = (pSourceVert->xyz.z/fSizeRatio) + Z;
|
||||
break;
|
||||
|
||||
case 1: // swap
|
||||
pVert->xyz.x = (pSourceVert->xyz.y*fSizeRatio)*fXSign + X;
|
||||
pVert->xyz.y = (pSourceVert->xyz.x*fSizeRatio)*fYSign + Y;
|
||||
pVert->xyz.z = (pSourceVert->xyz.z/fSizeRatio) + Z;
|
||||
break;
|
||||
}
|
||||
|
||||
pVert->st[0] = pSourceVert->st[0];
|
||||
pVert->st[1] = pSourceVert->st[1];
|
||||
|
||||
pVert->color.bcolor[0] = grass_r;
|
||||
pVert->color.bcolor[1] = grass_g;
|
||||
pVert->color.bcolor[2] = grass_b;
|
||||
pVert->color.bcolor[3] = 255;
|
||||
|
||||
pVert++;
|
||||
pSourceVert++;
|
||||
}
|
||||
|
||||
m_GrassVerticesCount += o->nVertCount;
|
||||
}
|
||||
|
||||
void CDetailGrass::CreateSectorGrassInUnit(const int x, const int y, const int nStep,
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices)
|
||||
{
|
||||
const float grass_level_min = m_pTerrain->GetWaterLevel() + 0.25f;
|
||||
if(m_pTerrain->GetZSafe(m_GrassFocusX+x,m_GrassFocusY+y)<grass_level_min)
|
||||
return;
|
||||
|
||||
if(m_GrassVerticesCount+4096 > DETAIL_GRASS_PIP_BUFFER_SIZE)
|
||||
{
|
||||
GetLog()->Log("CreateSectorGrass: grass buffer overflow");
|
||||
GetLog()->Log("grass_verts = %d/%d", m_GrassVerticesCount, int(DETAIL_GRASS_PIP_BUFFER_SIZE));
|
||||
return;
|
||||
}
|
||||
|
||||
srand(((m_GrassFocusX+x)*(m_GrassFocusY+y)));
|
||||
srand(rand());
|
||||
srand(rand());
|
||||
|
||||
int nSurfaceID = 0;
|
||||
|
||||
int nUnitSize = CTerrain::GetHeightMapUnitSize();
|
||||
|
||||
// todo skip this if there is has_holes flag not set in sector
|
||||
for(int _x = m_GrassFocusX+x-nUnitSize; _x <= m_GrassFocusX+x+nUnitSize; _x += nUnitSize)
|
||||
for(int _y = m_GrassFocusY+y-nUnitSize; _y <= m_GrassFocusY+y+nUnitSize; _y += nUnitSize)
|
||||
{
|
||||
if(m_pTerrain->IsBurnedOut(_x-1,_y-1))
|
||||
return;
|
||||
|
||||
nSurfaceID = m_pTerrain->GetSurfaceTypeID(_x-1,_y-1);
|
||||
if(nSurfaceID == STYPE_HOLE)
|
||||
return;
|
||||
}
|
||||
|
||||
nSurfaceID = m_pTerrain->GetSurfaceTypeID(m_GrassFocusX+x,m_GrassFocusY+y);
|
||||
if(nSurfaceID == STYPE_HOLE) return;
|
||||
|
||||
assert(nSurfaceID<MAX_SURFACE_TYPES_COUNT);
|
||||
|
||||
if(!m_arrlstSurfaceObjects[nSurfaceID].Count())
|
||||
return;
|
||||
|
||||
assert(nStep == 1);
|
||||
|
||||
CVars * pCVars = GetCVars();
|
||||
|
||||
for(int i=0; i<m_nGrassDensity; i++)
|
||||
{
|
||||
float objX = (float)rnd() - 0.5f+(m_GrassFocusX+x);
|
||||
float objY = (float)rnd() - 0.5f+(m_GrassFocusY+y);
|
||||
|
||||
/// if(m_pTerrain->IsBurnedOut((int)objX,(int)objY))
|
||||
// continue;
|
||||
|
||||
int nObjIdId = rand() % m_arrlstSurfaceObjects[nSurfaceID].Count();
|
||||
GrassType * o = m_arrlstSurfaceObjects[nSurfaceID][nObjIdId];
|
||||
|
||||
if(!o->nIndCount)
|
||||
continue;
|
||||
|
||||
float objZ = m_pTerrain->GetZApr(objX,objY);
|
||||
|
||||
float fBr =
|
||||
//pCVars->e_lighting_bit_test ?
|
||||
//m_pTerrain->IsOnTheLight((int)objX,(int)objY) :
|
||||
0.6f+0.4f*(float)m_pTerrain->IsOnTheLight((int)objX,(int)objY);
|
||||
|
||||
AddIndexedArray(o, objX,objY,objZ, fBr,
|
||||
0.75f+rnd()*0.5f, // size, proportions
|
||||
(rand() > RAND_MAX/2) ? 1.f : -1.f, // x sign
|
||||
(rand() > RAND_MAX/2) ? 1.f : -1.f, // y sign
|
||||
(rand() > RAND_MAX/2), // xy swap
|
||||
pGrassVertices);
|
||||
}
|
||||
}
|
||||
// generating sector grass mesh
|
||||
void CDetailGrass::CreateSectorGrass(const int nRange, const int nStep, struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices)
|
||||
{
|
||||
m_GrassVerticesCount = 0;
|
||||
m_GrassIndices.Clear();
|
||||
|
||||
if(!m_GrassModelsArray.Count())
|
||||
return;
|
||||
|
||||
m_GrassFocusX = m_GrassFocusX/nStep*nStep;
|
||||
m_GrassFocusY = m_GrassFocusY/nStep*nStep;
|
||||
|
||||
if(m_GrassFocusX-nRange<0 || m_GrassFocusY-nRange<0)
|
||||
return;
|
||||
if(m_GrassFocusX+nRange>=CTerrain::GetTerrainSize() || m_GrassFocusY+nRange>=CTerrain::GetTerrainSize())
|
||||
return;
|
||||
|
||||
int nRangeX = nRange;
|
||||
int nRangeY = nRange;
|
||||
|
||||
int nStepX = nStep;
|
||||
int nStepY = nStep;
|
||||
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
if(vCamPos.x > m_GrassFocusX)
|
||||
{
|
||||
if(vCamPos.y > m_GrassFocusY)
|
||||
{
|
||||
for(int x=-nRangeX; x<= nRangeX; x+=nStepX)
|
||||
for(int y=-nRangeY; y<= nRangeY; y+=nStepY)
|
||||
CreateSectorGrassInUnit(x, y , nStep, pGrassVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int x=-nRangeX; x<= nRangeX; x+=nStepX)
|
||||
for(int y= nRangeY; y>=-nRangeY; y-=nStepY)
|
||||
CreateSectorGrassInUnit(x, y , nStep, pGrassVertices);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vCamPos.y > m_GrassFocusY)
|
||||
{
|
||||
for(int x= nRangeX; x>=-nRangeX; x-=nStepX)
|
||||
for(int y=-nRangeY; y<= nRangeY; y+=nStepY)
|
||||
CreateSectorGrassInUnit(x, y , nStep, pGrassVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int x= nRangeX; x>=-nRangeX; x-=nStepX)
|
||||
for(int y= nRangeY; y>=-nRangeY; y-=nStepY)
|
||||
CreateSectorGrassInUnit(x, y , nStep, pGrassVertices);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if(m_GrassVerticesCount>12000)
|
||||
/* {
|
||||
GetLog()->Log("grass_verts = %d/%d", m_GrassVerticesCount, int(DETAIL_GRASS_PIP_BUFFER_SIZE));
|
||||
GetLog()->Log("grass_indic = %d", m_GrassIndices.Count());
|
||||
}*/
|
||||
}
|
||||
|
||||
void CDetailGrass::PreloadResources()
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
ITexPic * pTexPic = GetRenderer()->EF_GetTextureByID(m_GrassTID);
|
||||
if(pTexPic)
|
||||
GetRenderer()->EF_PrecacheResource(pTexPic, 0, 1.f, 0);
|
||||
}
|
||||
|
||||
// check focus and render
|
||||
void CDetailGrass::RenderDetailGrass(CTerrain * pTerrain)
|
||||
{
|
||||
if( !GetCVars()->e_detail_objects || !m_nGrassDensity || !pTerrain || !m_pLeafBuffer )
|
||||
return;
|
||||
|
||||
m_pTerrain = pTerrain;
|
||||
|
||||
if(!m_GrassTID)
|
||||
return;
|
||||
|
||||
if(!(GetRenderer()->GetFeatures()&RFT_DIRECTACCESSTOVIDEOMEMORY))
|
||||
return;
|
||||
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
const int map_border = 12;
|
||||
if(vCamPos.x < map_border || vCamPos.x > CTerrain::GetTerrainSize()-map_border)
|
||||
return;
|
||||
if(vCamPos.y < map_border || vCamPos.y > CTerrain::GetTerrainSize()-map_border)
|
||||
return;
|
||||
|
||||
// if(!m_pGrassVertices)
|
||||
// return;
|
||||
|
||||
float camera_h = vCamPos.z - m_pTerrain->GetZSafe(vCamPos.x,vCamPos.y);
|
||||
|
||||
if(camera_h > 64 || camera_h < -8)
|
||||
return;
|
||||
/*
|
||||
if(pTerrain->m_nRenderStackLevel==0)
|
||||
{
|
||||
Matrix44 mat;
|
||||
GetRenderer()->GetModelViewMatrix(mat.GetData());
|
||||
Vec3d forward = -mat.GetColumn(2);
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//forward(-mat.cell(2), -mat.cell(6), -mat.cell(10));
|
||||
|
||||
forward.Normalize();
|
||||
|
||||
if(!forward.x && !forward.y)
|
||||
return;
|
||||
|
||||
int c_X = int(vCamPos.x + forward.x*CAMERA_GRASS_SHIFT);
|
||||
int c_Y = int(vCamPos.y + forward.y*CAMERA_GRASS_SHIFT);
|
||||
|
||||
// GetRenderer()->DrawBall(c_X,c_Y,m_pTerrain->GetZApr(c_X,c_Y),1);
|
||||
|
||||
// check focus
|
||||
float dx = float(c_X-m_GrassFocusX);
|
||||
float dy = float(c_Y-m_GrassFocusY);
|
||||
|
||||
float d2 = (dx*dx+dy*dy);
|
||||
|
||||
if(d2>16)
|
||||
{
|
||||
m_GrassFocusX = c_X;
|
||||
m_GrassFocusY = c_Y;
|
||||
|
||||
PrepareBufferCallback(m_pLeafBuffer, 0, 0);
|
||||
}
|
||||
|
||||
// set alpha glow texgen params
|
||||
const float fDistFadeK = 1.f/(CAMERA_GRASS_SHIFT*4.f);
|
||||
m_arrfShaderInfo[2] = fDistFadeK;
|
||||
m_arrfShaderInfo[3] = 0.5f-vCamPos.y*fDistFadeK;
|
||||
m_arrfShaderInfo[4] = 0.5f-vCamPos.x*fDistFadeK;
|
||||
m_pLeafBuffer->SetRECustomData(m_arrfShaderInfo);
|
||||
}
|
||||
*/
|
||||
// if(!m_GrassVerticesCount)
|
||||
// return;
|
||||
|
||||
// find fog volume
|
||||
Vec3d vPlus(30,30,30);
|
||||
int nFogId;
|
||||
for(nFogId = 0; nFogId<pTerrain->m_lstFogVolumes.Count(); nFogId++)
|
||||
{
|
||||
if(vCamPos.x > (pTerrain->m_lstFogVolumes[nFogId].vBoxMin-vPlus).x)
|
||||
if(vCamPos.y > (pTerrain->m_lstFogVolumes[nFogId].vBoxMin-vPlus).y)
|
||||
if(vCamPos.z > (pTerrain->m_lstFogVolumes[nFogId].vBoxMin-vPlus).z)
|
||||
if(vCamPos.x < (pTerrain->m_lstFogVolumes[nFogId].vBoxMax+vPlus).x)
|
||||
if(vCamPos.y < (pTerrain->m_lstFogVolumes[nFogId].vBoxMax+vPlus).y)
|
||||
if(vCamPos.z < (pTerrain->m_lstFogVolumes[nFogId].vBoxMax+vPlus).z)
|
||||
break;
|
||||
}
|
||||
|
||||
int nDLMask = Get3DEngine()->GetLightMaskFromPosition(vCamPos, CAMERA_GRASS_SHIFT);
|
||||
|
||||
// render
|
||||
CCObject * pObj = GetRenderer()->EF_GetObject(true);
|
||||
if(GetRenderer()->EF_GetHeatVision())
|
||||
pObj->m_ObjFlags |= FOB_HEATVISION;
|
||||
pObj->m_Matrix.SetIdentity();
|
||||
|
||||
pObj->m_Color.a = 0.99f;
|
||||
|
||||
m_pLeafBuffer->m_vBoxMin = vCamPos;
|
||||
m_pLeafBuffer->m_vBoxMax = vCamPos;
|
||||
|
||||
pObj->m_SortId = -1;
|
||||
|
||||
if(pTerrain->m_nRenderStackLevel==0)
|
||||
m_pLeafBuffer->InvalidateVideoBuffer();
|
||||
|
||||
if(m_pLeafBuffer->m_Indices.m_nItems)
|
||||
m_pLeafBuffer->AddRenderElements( pObj, nDLMask,-1, (nFogId<pTerrain->m_lstFogVolumes.Count()) ? pTerrain->m_lstFogVolumes[nFogId].nRendererVolumeID : 0, eS_TerrainDetailObjects );
|
||||
else
|
||||
{ // nothing to draw now but we must to add render element to be able to generate mesh right before rendering
|
||||
m_pLeafBuffer->AddRenderElements( pObj, nDLMask,-1,
|
||||
(nFogId<pTerrain->m_lstFogVolumes.Count()) ? pTerrain->m_lstFogVolumes[nFogId].nRendererVolumeID : 0 );
|
||||
}
|
||||
}
|
||||
|
||||
int CDetailGrass::GetMemoryUsage()
|
||||
{
|
||||
int nSize=0;
|
||||
nSize += m_GrassIndices.GetMemoryUsage();
|
||||
nSize += m_GrassModelsArray.GetMemoryUsage();
|
||||
for(int i=0; i<m_GrassModelsArray.Count(); i++)
|
||||
nSize += sizeof(*m_GrassModelsArray[i]) + m_GrassModelsArray[i]->GetMemoryUsage();
|
||||
|
||||
return nSize;
|
||||
}
|
||||
|
||||
62
Cry3DEngine/detail_grass.h
Normal file
62
Cry3DEngine/detail_grass.h
Normal file
@@ -0,0 +1,62 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: detail_grass.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _DETAILGRASS_H_
|
||||
#define _DETAILGRASS_H_
|
||||
|
||||
class CVertexBuffer;
|
||||
struct GrassType;
|
||||
class CTerrain;
|
||||
struct CLeafBuffer;
|
||||
|
||||
const int DETAIL_GRASS_PIP_BUFFER_SIZE = 50000;
|
||||
const float CAMERA_GRASS_SHIFT = 9;
|
||||
|
||||
class CDetailGrass : public Cry3DEngineBase
|
||||
{
|
||||
void CreateSectorGrass(const int range, const int step, struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices);
|
||||
void CreateSectorGrassInUnit(const int x, const int y, const int nStep,
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices);
|
||||
void AddIndexedArray(GrassType * o, float X, float Y, float Z, float fbr, float fSizeRatio,
|
||||
float fXSign, float fYSign, int nSwapXY, struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pGrassVertices);
|
||||
|
||||
list2<unsigned short> m_GrassIndices;
|
||||
// struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * m_pGrassVertices;
|
||||
int m_GrassVerticesCount;
|
||||
int m_GrassFocusX, m_GrassFocusY; // grass focus
|
||||
int m_GrassTID;
|
||||
list2<GrassType*> m_GrassModelsArray;
|
||||
int m_nGrassDensity;
|
||||
CTerrain * m_pTerrain;
|
||||
list2<GrassType*> m_arrlstSurfaceObjects[MAX_SURFACE_TYPES_COUNT];
|
||||
|
||||
CLeafBuffer * m_pLeafBuffer;
|
||||
IShader * m_pShader;
|
||||
float m_arrfShaderInfo[16];
|
||||
|
||||
public:
|
||||
CDetailGrass(XDOM::IXMLDOMNodeListPtr pDetTexTagList);
|
||||
~CDetailGrass();
|
||||
void RenderDetailGrass(CTerrain * pTerrain);
|
||||
void UpdateGrass() { m_GrassFocusX=m_GrassFocusY=-CTerrain::GetTerrainSize(); }
|
||||
void PreloadResources();
|
||||
|
||||
static bool PrepareBufferCallback(CLeafBuffer * pLeafBuffer, bool bNeedTangents);
|
||||
// todo: update
|
||||
//void GetMemoryUsage(ICrySizer*pSizer);
|
||||
int GetMemoryUsage();
|
||||
};
|
||||
|
||||
#endif // _DETAILGRASS_H_
|
||||
614
Cry3DEngine/particle.cpp
Normal file
614
Cry3DEngine/particle.cpp
Normal file
@@ -0,0 +1,614 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: particle.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: move, fill vertex buffer
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "partman.h"
|
||||
#include "objman.h"
|
||||
#include "3dengine.h"
|
||||
|
||||
#define OT_RIGID_PARTICLE 10
|
||||
|
||||
void CParticle::FillBuffer(const PartProcessParams & PPP)
|
||||
{
|
||||
float t = (PPP.fCurTime-m_fSpawnTime)/m_fLifeTime;
|
||||
float alpha = (1.f - t);//*2;
|
||||
if(alpha<0)
|
||||
alpha=0;
|
||||
|
||||
Vec3d vColor = m_pParams->vColorStart*(1.f-t) + m_pParams->vColorEnd*t;
|
||||
|
||||
if (m_pParams->eBlendType != ParticleBlendType_AlphaBased)
|
||||
{
|
||||
vColor.x*=alpha;
|
||||
vColor.y*=alpha;
|
||||
vColor.z*=alpha;
|
||||
}
|
||||
|
||||
Vec3d v1 = m_vPos + PPP.vUp *m_fSize;
|
||||
Vec3d v2 = m_vPos + PPP.vRight *m_fSize;
|
||||
Vec3d v3 = m_vPos - PPP.vRight *m_fSize;
|
||||
Vec3d v4 = m_vPos - PPP.vUp *m_fSize;
|
||||
|
||||
UCol col;
|
||||
col.bcolor[0] = FtoI(vColor.x*255.f);
|
||||
col.bcolor[1] = FtoI(vColor.y*255.f);
|
||||
col.bcolor[2] = FtoI(vColor.z*255.f);
|
||||
col.bcolor[3] = FtoI(alpha*255.f);
|
||||
|
||||
PPP.pVertBufChunk[0].xyz = v1;
|
||||
PPP.pVertBufChunk[0].color = col;
|
||||
PPP.pVertBufChunk[0].st[0] = 0; PPP.pVertBufChunk[0].st[1] = 1;
|
||||
|
||||
PPP.pVertBufChunk[1].xyz = v2;
|
||||
PPP.pVertBufChunk[1].color = col;
|
||||
PPP.pVertBufChunk[1].st[0] = 0; PPP.pVertBufChunk[0].st[1] = 0;
|
||||
|
||||
PPP.pVertBufChunk[2].xyz = v3;
|
||||
PPP.pVertBufChunk[2].color = col;
|
||||
PPP.pVertBufChunk[2].st[0] = 1; PPP.pVertBufChunk[0].st[1] = 1;
|
||||
|
||||
PPP.pVertBufChunk[3].xyz = v4;
|
||||
PPP.pVertBufChunk[3].color = col;
|
||||
PPP.pVertBufChunk[3].st[0] = 1; PPP.pVertBufChunk[0].st[1] = 0;
|
||||
}
|
||||
|
||||
bool CParticle::Update(const PartProcessParams & PPP)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Move
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Vec3 prevPos = m_vPos;
|
||||
float fAge = PPP.fCurTime - m_fSpawnTime;
|
||||
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_BIND_EMITTER_TO_CAMERA && m_pEmitter)
|
||||
{
|
||||
float fLen = m_pEmitter->GetParams().vSpaceLoopBoxSize.GetLength();
|
||||
Vec3d vDir = PPP.pCamera->GetVCMatrixD3D9().GetOrtZ();
|
||||
m_pEmitter->m_pos = PPP.pCamera->GetPos()-vDir*fLen*0.75;
|
||||
}
|
||||
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_SPACELOOP && m_pEmitter)
|
||||
{ // process space loop
|
||||
Vec3d vSpaceFocusPos = m_pEmitter->m_pos;
|
||||
float fMaxX = m_pEmitter->GetParams().vSpaceLoopBoxSize.x;
|
||||
float fMaxY = m_pEmitter->GetParams().vSpaceLoopBoxSize.y;
|
||||
float fMaxZ = m_pEmitter->GetParams().vSpaceLoopBoxSize.z;
|
||||
|
||||
// X
|
||||
while((m_vPos.x-vSpaceFocusPos.x)>fMaxX)
|
||||
m_vPos.x-=fMaxX*2;
|
||||
while((vSpaceFocusPos.x-m_vPos.x)>fMaxX)
|
||||
m_vPos.x+=fMaxX*2;
|
||||
|
||||
// Y
|
||||
while((m_vPos.y-vSpaceFocusPos.y)>fMaxY)
|
||||
m_vPos.y-=fMaxY*2;
|
||||
while((vSpaceFocusPos.y-m_vPos.y)>fMaxY)
|
||||
m_vPos.y+=fMaxY*2;
|
||||
|
||||
// Z
|
||||
while((m_vPos.z-vSpaceFocusPos.z)>fMaxZ)
|
||||
m_vPos.z-=fMaxZ*2;
|
||||
while((vSpaceFocusPos.z-m_vPos.z)>fMaxZ)
|
||||
m_vPos.z+=(fMaxZ*2-rnd());
|
||||
}
|
||||
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_NO_INDOOR)
|
||||
{
|
||||
IVisArea * pArea = PPP.p3DEngine->GetVisAreaFromPos(m_vPos);
|
||||
if(pArea)
|
||||
return false;
|
||||
}
|
||||
|
||||
if((m_pParams->nParticleFlags & PART_FLAG_SPACELIMIT) && m_pEmitter)
|
||||
{
|
||||
Vec3d vBoxMin = m_pEmitter->GetParams().vPosition - m_pEmitter->GetParams().vSpaceLoopBoxSize;
|
||||
Vec3d vBoxMax = m_pEmitter->GetParams().vPosition + m_pEmitter->GetParams().vSpaceLoopBoxSize;
|
||||
|
||||
vBoxMin.CheckMin(m_pEmitter->GetParams().vPosition + m_pEmitter->GetParams().vSpaceLoopBoxSize);
|
||||
vBoxMax.CheckMax(m_pEmitter->GetParams().vPosition - m_pEmitter->GetParams().vSpaceLoopBoxSize);
|
||||
|
||||
Vec3d vNextPos = m_vPos + m_vDelta * PPP.fFrameTime;
|
||||
|
||||
if( vNextPos.x < vBoxMin.x ||
|
||||
vNextPos.y < vBoxMin.y ||
|
||||
vNextPos.z < vBoxMin.z ||
|
||||
vNextPos.x > vBoxMax.x ||
|
||||
vNextPos.y > vBoxMax.y ||
|
||||
vNextPos.z > vBoxMax.z )
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_pPhysEnt)
|
||||
{ // use phys engine to control particle
|
||||
pe_status_pos status_pos;
|
||||
m_pPhysEnt->GetStatus(&status_pos);
|
||||
m_vPos = status_pos.pos;
|
||||
|
||||
|
||||
//CHANGED_BY_IVO (NOTE: order of angles is flipped!!!!)
|
||||
//status_pos.q.get_Euler_angles_xyz(PPP.pPartSpray->m_vAngles.z,PPP.pPartSpray->m_vAngles.y,PPP.pPartSpray->m_vAngles.x);
|
||||
//EULER_IVO
|
||||
//Vec3 TempAng; PPP.pPartSpray->m_vAngles = status_pos.q.GetEulerAngles_XYZ(TempAng);
|
||||
m_vAngles = Ang3::GetAnglesXYZ( matrix3x3f(status_pos.q) );
|
||||
m_vAngles *= 180/gf_PI;
|
||||
}
|
||||
else
|
||||
{ // process movement, size and rotation
|
||||
if(!(m_pParams->nParticleFlags & PART_FLAG_LINEPARTICLE))
|
||||
{
|
||||
Vec3 vDelta = m_vDelta;
|
||||
|
||||
if (m_pParams->fSpeedFadeOut != 0)
|
||||
{
|
||||
// Fade out speed.
|
||||
float t = m_fLifeTime - fAge;
|
||||
if (t < m_pParams->fSpeedFadeOut)
|
||||
{
|
||||
float speedScale = (t/m_pParams->fSpeedFadeOut);
|
||||
if (speedScale < 0) speedScale = 0;
|
||||
if (speedScale > 1) speedScale = 1;
|
||||
vDelta = vDelta*speedScale;
|
||||
}
|
||||
}
|
||||
|
||||
m_vPos += vDelta * PPP.fFrameTime;
|
||||
|
||||
if (m_pParams->fTurbulenceSize)
|
||||
{
|
||||
m_vPos += Vec3d( cry_cosf( fAge*m_pParams->fTurbulenceSpeed),
|
||||
cry_sinf( fAge*m_pParams->fTurbulenceSpeed),
|
||||
0)* PPP.fFrameTime * (max(1.f,fAge))*
|
||||
m_pParams->fTurbulenceSize;
|
||||
}
|
||||
|
||||
m_vDelta += m_pParams->vGravity*m_fScale * PPP.fFrameTime;
|
||||
|
||||
if (m_pParams->fSpeedAccel != 0)
|
||||
{
|
||||
if (!m_vDelta.IsZero())
|
||||
{
|
||||
Vec3 heading = GetNormalized(m_vDelta);
|
||||
m_vDelta += heading*m_pParams->fSpeedAccel*m_fScale * PPP.fFrameTime;
|
||||
}
|
||||
}
|
||||
if (m_pParams->fAirResistance != 0)
|
||||
{
|
||||
float fSpeed = GetLength(m_vDelta);
|
||||
if (fSpeed != 0)
|
||||
{
|
||||
Vec3 heading = m_vDelta * (1.0f/fSpeed);
|
||||
float fResistance = (fSpeed*fSpeed) * m_pParams->fAirResistance * PPP.fFrameTime; //D = Cd * A * .5 * r * V^2
|
||||
if (fResistance > fSpeed)
|
||||
fResistance = fSpeed;
|
||||
m_vDelta -= heading*fResistance;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pParams->pStatObj)
|
||||
m_vAngles += m_vRotation*PPP.fFrameTime*(180.0f/gf_PI);
|
||||
else
|
||||
m_vAngles.z += m_vRotation.z*PPP.fFrameTime*(180.0f/gf_PI);
|
||||
}
|
||||
|
||||
if (m_pParams->fSizeSpeed != 0)
|
||||
{
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_SIZE_LINEAR)
|
||||
m_fSize += (m_pParams->fSizeSpeed*m_fScale) * PPP.fFrameTime;
|
||||
else
|
||||
{
|
||||
float inc = (m_pParams->fSizeSpeed*m_fScale) * PPP.fFrameTime;;
|
||||
if (m_fSize > 1)
|
||||
inc = inc / m_fSize;
|
||||
m_fSize += inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_pParams->nParticleFlags & PART_FLAG_BIND_POSITION_TO_EMITTER)
|
||||
{
|
||||
m_vPos = m_pEmitter->m_pos;
|
||||
}
|
||||
|
||||
//bool bScaleFadeInOut = false;
|
||||
float scaleFade = 1.0f;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Process Scale FadeIn/FadeOut of particle.
|
||||
// Override m_fSize member.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_pParams->fSizeFadeIn != 0)
|
||||
{
|
||||
// Fade in scale
|
||||
float t = fAge;
|
||||
if (t <= m_pParams->fSizeFadeIn)
|
||||
{
|
||||
scaleFade = (t/m_pParams->fSizeFadeIn);
|
||||
if (scaleFade < 0) scaleFade = 0;
|
||||
if (scaleFade > 1) scaleFade = 1;
|
||||
//bScaleFadeInOut = true;
|
||||
m_fSize = m_fSizeOriginal * scaleFade;
|
||||
}
|
||||
}
|
||||
if (m_pParams->fSizeFadeOut != 0)
|
||||
{
|
||||
// Fade out scale.
|
||||
float t = m_fLifeTime - fAge;
|
||||
if (t < m_pParams->fSizeFadeOut)
|
||||
{
|
||||
if (t < 0) t = 0;
|
||||
scaleFade *= (t/m_pParams->fSizeFadeOut);
|
||||
if (scaleFade < 0) scaleFade = 0;
|
||||
if (scaleFade > 1) scaleFade = 1;
|
||||
//m_fSize = m_fSizeOriginal * scaleOut;
|
||||
//bScaleFadeInOut = true;
|
||||
m_fSize = m_fSizeOriginal * scaleFade;
|
||||
}
|
||||
}
|
||||
|
||||
// Restrict to minimal size.
|
||||
if (m_fSize < 0.001f)
|
||||
m_fSize = 0.0001f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Simple collision with terrain simulation
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool bContact = false;
|
||||
if(m_pPhysEnt)
|
||||
{ // use real physics
|
||||
pe_status_collisions status;
|
||||
coll_history_item item;
|
||||
status.pHistory = &item;
|
||||
status.age=1.f;
|
||||
status.bClearHistory=1;
|
||||
bContact = m_pPhysEnt->GetStatus(&status)!=0;
|
||||
}
|
||||
else if(m_vDelta.z<0)
|
||||
{
|
||||
const float fFriction = 0.15f;
|
||||
|
||||
/*
|
||||
if (m_pVisArea)
|
||||
{ // if inside the building
|
||||
if(pCVars->e_particles_indoor_collisions)
|
||||
{
|
||||
IndoorRayIntInfo tRayInfo;
|
||||
bool bRes = pObjManager->m_pBuildingManager->RayIntersection(m_vPos-(m_vDelta*fFrameTime), m_vPos, tRayInfo, nBuildingID);
|
||||
if(bRes && m_vDelta.Dot(tRayInfo.vNormal)<0)
|
||||
{ // if collides
|
||||
float fLen = m_vDelta.Length()-fFriction;
|
||||
|
||||
if(fLen>fFriction)
|
||||
{
|
||||
m_vDelta = m_vDelta.Reflect(tRayInfo.vNormal);
|
||||
m_vDelta.SetLen(fLen*PPP.pPartSpray->m_fBouncenes);
|
||||
}
|
||||
else
|
||||
m_vDelta.Clear();
|
||||
|
||||
bContact = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else*/
|
||||
if( PPP.pTerrain && _finite(m_vPos.x) && _finite(m_vPos.y)
|
||||
&& m_vPos.z < PPP.pTerrain->GetZApr(m_vPos.x,m_vPos.y)
|
||||
&& m_vPos.z > PPP.pTerrain->GetZApr(m_vPos.x,m_vPos.y)-0.1f
|
||||
&& !(m_pParams->nParticleFlags & PART_FLAG_SPACELOOP))
|
||||
{ // collide with terrain
|
||||
int x = (int)m_vPos.x;
|
||||
int y = (int)m_vPos.y;
|
||||
if(!PPP.pTerrain->GetHoleSafe(x,y))
|
||||
if(!PPP.pTerrain->GetHoleSafe(x+CTerrain::GetHeightMapUnitSize(),y+CTerrain::GetHeightMapUnitSize()))
|
||||
if(!PPP.pTerrain->GetHoleSafe(x-CTerrain::GetHeightMapUnitSize(),y+CTerrain::GetHeightMapUnitSize()))
|
||||
if(!PPP.pTerrain->GetHoleSafe(x+CTerrain::GetHeightMapUnitSize(),y-CTerrain::GetHeightMapUnitSize()))
|
||||
if(!PPP.pTerrain->GetHoleSafe(x-CTerrain::GetHeightMapUnitSize(),y-CTerrain::GetHeightMapUnitSize()))
|
||||
{
|
||||
float fLen = (m_vDelta - m_pParams->vGravity*m_fScale*PPP.fFrameTime).Length()-fFriction;
|
||||
|
||||
if(fLen>fFriction)
|
||||
{
|
||||
m_vDelta.z = -m_vDelta.z;
|
||||
m_vDelta.SetLen( fLen*m_pParams->fBouncenes);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vDelta(0,0,0);
|
||||
m_vRotation(0,0,0);
|
||||
}
|
||||
|
||||
bContact = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(bContact && !IsEquivalent(m_vDelta,Vec3(0,0,0), 0.001f) )
|
||||
{
|
||||
Vec3d vVec(m_vDelta.x,m_vDelta.y,0);
|
||||
|
||||
if(vVec.Normalize())
|
||||
{
|
||||
vVec = vVec.Cross(Vec3d(0,0,1));
|
||||
quaternionf q;
|
||||
q=quaternionf(0, vVec.x,vVec.y,vVec.z );
|
||||
|
||||
//CHANGED_BY_IVO (NOTE: order of angles is flipped!!!!)
|
||||
//q.get_Euler_angles_xyz( PPP.pPartSpray->m_vRotation.z,PPP.pPartSpray->m_vRotation.y,PPP.pPartSpray->m_vRotation.x );
|
||||
//EULER_IVO
|
||||
//Vec3 TempAng; PPP.pPartSpray->m_vRotation = q.GetEulerAngles_XYZ( TempAng );
|
||||
m_vRotation = Ang3::GetAnglesXYZ( matrix3x3f(q) );
|
||||
m_vRotation *= m_pParams->fBouncenes*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bContact)
|
||||
{ // Run child process on collision
|
||||
if (m_pParams->pChild && m_pParams->pChild->nCount > 0 && m_pParams->fChildSpawnPeriod < 0)
|
||||
{
|
||||
m_pParams->pChild->vPosition = m_vPos;
|
||||
//m_pParams->pChild->pStatObj = 0;
|
||||
m_pParams->pChild->vDirection = Vec3(0,0,1); // Up direction.
|
||||
PPP.pPartManager->Spawn( m_pEmitter,true );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Run child process every X sec
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (m_pParams->pChild && m_pParams->pChild->nCount > 0 &&
|
||||
m_pParams->fChildSpawnPeriod >= 0 &&
|
||||
PPP.fCurTime > m_fChildSpawnLastTime + m_pParams->fChildSpawnPeriod)
|
||||
{
|
||||
if (m_pParams->fChildSpawnTime <= 0 || fAge < m_pParams->fChildSpawnTime)
|
||||
{
|
||||
// Calc current movement direction.
|
||||
if (m_vPos != prevPos)
|
||||
m_pParams->pChild->vDirection = GetNormalized(m_vPos - prevPos);
|
||||
m_pParams->pChild->vPosition = m_vPos;
|
||||
//PPP.pPartSpray->m_ChildParams.pChild=0;
|
||||
//PPP.pPartSpray->m_ChildParams.pStatObj=0;
|
||||
// PPP.pPartSpray->m_pChildPartEmitter->Spawn( m_vPos );
|
||||
|
||||
PPP.pPartManager->Spawn( m_pEmitter,true );
|
||||
m_fChildSpawnLastTime = PPP.fCurTime;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Remember prev positions for trail
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (m_pArrvPosHistory)
|
||||
{
|
||||
//float fTailLength = (m_pParams->fTailLenght/m_nTailSteps) / m_fScale; // Here we must divide by scale because speed is scaled.
|
||||
//m_fTrailCurPos += min(1.f, PPP.fFrameTime/fTailLength);
|
||||
//m_pArrvPosHistory[ ((unsigned int)FtoI(m_fTrailCurPos))%m_nTailSteps ] = m_vPos;
|
||||
|
||||
/*
|
||||
float t = PPP.fCurTime-m_fLastTailPosTime;
|
||||
float dt = 0.3f;
|
||||
float fTailLength = (m_pParams->fTailLenght/PART_HISTORY_ELEMENTS)*m_fScale;
|
||||
if (t > dt)
|
||||
{
|
||||
//m_fTrailCurPos += min(1.f, PPP.fFrameTime/fTailLength);
|
||||
//m_pArrvPosHistory[int(m_fTrailCurPos) & PART_HISTORY_ID_MASK] = m_vPos;
|
||||
for (int i = 0; i < PART_HISTORY_ELEMENTS-1; i++)
|
||||
{
|
||||
m_pArrvPosHistory[i] = m_pArrvPosHistory[i+1];
|
||||
}
|
||||
m_pArrvPosHistory[PART_HISTORY_ELEMENTS-1] = m_vPos;
|
||||
m_fLastTailPosTime = PPP.fCurTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
float a = t / dt; // from 0-1.
|
||||
a *= 0.05f;
|
||||
// Smooth last to prev.
|
||||
for (int i = 0; i < PART_HISTORY_ELEMENTS-1; i++)
|
||||
{
|
||||
Vec3 &last = m_pArrvPosHistory[i];
|
||||
Vec3 &prev = m_pArrvPosHistory[i+1];
|
||||
// //last = last*(1.0f-a) + (prev+Vec3(0,0,0))*a;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Deactivate if too far or too int
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( (PPP.fCurTime/*+PPP.fFrameTime*/) >= (m_fSpawnTime + m_fLifeTime) )
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_UNDERWATER && m_pEmitter->m_fWaterLevel>WATER_LEVEL_UNKNOWN)
|
||||
if(m_vPos.z > m_pEmitter->m_fWaterLevel-m_fSize*0.5)
|
||||
return false;
|
||||
}
|
||||
|
||||
if((m_pParams->nParticleFlags & PART_FLAG_SPACELIMIT) && m_pEmitter)
|
||||
{
|
||||
Vec3d vBoxMin = m_pEmitter->GetParams().vPosition - m_pEmitter->GetParams().vSpaceLoopBoxSize;
|
||||
Vec3d vBoxMax = m_pEmitter->GetParams().vPosition + m_pEmitter->GetParams().vSpaceLoopBoxSize;
|
||||
|
||||
vBoxMin.CheckMin(m_pEmitter->GetParams().vPosition + m_pEmitter->GetParams().vSpaceLoopBoxSize);
|
||||
vBoxMax.CheckMax(m_pEmitter->GetParams().vPosition - m_pEmitter->GetParams().vSpaceLoopBoxSize);
|
||||
|
||||
float fRadius = m_fSize;
|
||||
if(m_pParams->pStatObj)
|
||||
{ // get world space radius of the object
|
||||
float fObjScale = m_fSize;
|
||||
if (m_pParams->fObjectScale)
|
||||
fObjScale *= m_pParams->fObjectScale;
|
||||
fRadius = m_pParams->pStatObj->GetRadius()*fObjScale;
|
||||
}
|
||||
|
||||
Vec3d vHitPos = m_vPos + m_vDelta.GetNormalized()*fRadius;
|
||||
|
||||
// kill particle if position is out of bounds
|
||||
if( vHitPos.x < vBoxMin.x ||
|
||||
vHitPos.y < vBoxMin.y ||
|
||||
vHitPos.z < vBoxMin.z ||
|
||||
vHitPos.x > vBoxMax.x ||
|
||||
vHitPos.y > vBoxMax.y ||
|
||||
vHitPos.z > vBoxMax.z )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CParticle::DeActivateParticle(IPhysicalWorld * pPhysicalWorld)
|
||||
{
|
||||
if(m_pPhysEnt)
|
||||
{
|
||||
pPhysicalWorld->DestroyPhysicalEntity(m_pPhysEnt);
|
||||
m_pPhysEnt=0;
|
||||
}
|
||||
|
||||
if (m_pEmitter)
|
||||
{
|
||||
m_pEmitter->Release();
|
||||
m_pEmitter = 0;
|
||||
}
|
||||
|
||||
if (m_pArrvPosHistory)
|
||||
{
|
||||
delete []m_pArrvPosHistory;
|
||||
m_pArrvPosHistory = 0;
|
||||
}
|
||||
m_pSpawnerEntity = 0;
|
||||
}
|
||||
|
||||
char GetMinAxis(const Vec3d & vVec)
|
||||
{
|
||||
float x = fabs(vVec.x);
|
||||
float y = fabs(vVec.y);
|
||||
float z = fabs(vVec.z);
|
||||
|
||||
if(x<y && x<z)
|
||||
return 'x';
|
||||
|
||||
if(y<x && y<z)
|
||||
return 'y';
|
||||
|
||||
return 'z';
|
||||
}
|
||||
|
||||
void CParticle::Physicalize( ParticleParams &Params,IPhysicalWorld * pPhysicalWorld)
|
||||
{
|
||||
if (Params.nParticleFlags & PART_FLAG_RIGIDBODY)
|
||||
{
|
||||
if (!Params.pStatObj)
|
||||
return;
|
||||
|
||||
float fObjScale = m_fSize;
|
||||
if (m_pParams->fObjectScale)
|
||||
fObjScale *= m_pParams->fObjectScale;
|
||||
|
||||
// Make Physical Rigid Body.
|
||||
pe_params_pos par_pos;
|
||||
par_pos.pos = m_vPos;
|
||||
par_pos.q.SetRotationXYZ( m_vAngles*(gf_PI/180.0f) );
|
||||
m_pPhysEnt = pPhysicalWorld->CreatePhysicalEntity(PE_RIGID,&par_pos,0,OT_RIGID_PARTICLE );
|
||||
|
||||
pe_params_flags pf;
|
||||
pf.flagsOR = pef_never_affect_triggers;
|
||||
m_pPhysEnt->SetParams(&pf);
|
||||
|
||||
pe_geomparams partpos;
|
||||
//partpos.pos.Set(0,0,0);
|
||||
partpos.density = Params.fThickness;
|
||||
partpos.scale = fObjScale;
|
||||
partpos.flags &= ~geom_colltype3; // don't collide with vehicles
|
||||
partpos.flagsCollider = geom_colltype4;
|
||||
m_pPhysEnt->AddGeometry( Params.pStatObj->GetPhysGeom(),&partpos,0 );
|
||||
|
||||
pe_simulation_params symparams;
|
||||
//symparams.damping = 0.3f;
|
||||
//symparams.dampingFreefall = 0.3f;
|
||||
//symparams.gravity = Params.vGravity*m_fScale;
|
||||
symparams.minEnergy = (0.2f)*(0.2f);
|
||||
//symparams.softness = symparams.softnessGroup = 0.003f;
|
||||
//symparams.softnessAngular = symparams.softnessAngularGroup = 0.01f;
|
||||
//symparams.maxTimeStep = 0.05f;
|
||||
m_pPhysEnt->SetParams(&symparams);
|
||||
|
||||
pe_action_set_velocity velparam;
|
||||
velparam.v = m_vDelta;
|
||||
velparam.w = m_vRotation;
|
||||
m_pPhysEnt->Action(&velparam);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make Physical Particle.
|
||||
pe_params_pos par_pos;
|
||||
par_pos.pos = m_vPos;
|
||||
m_pPhysEnt = pPhysicalWorld->CreatePhysicalEntity(PE_PARTICLE,&par_pos);
|
||||
pe_params_particle params;
|
||||
|
||||
// Take particles size from bounding box of piece.
|
||||
|
||||
float fPartSize = 1.0f;
|
||||
if (Params.pStatObj)
|
||||
{
|
||||
Vec3 vSize = Params.pStatObj->GetBoxMax() - Params.pStatObj->GetBoxMin();
|
||||
fPartSize = max(max(vSize.x,vSize.y),vSize.z);
|
||||
}
|
||||
|
||||
params.mass = 0.1f;
|
||||
params.size = m_fSize*fPartSize;
|
||||
if (Params.pStatObj)
|
||||
{
|
||||
params.size = Params.pStatObj->GetRadius()+0.05f;
|
||||
if(m_pParams->fObjectScale)
|
||||
params.size *= Params.fObjectScale;
|
||||
}
|
||||
|
||||
params.thickness = Params.fThickness ? Params.fThickness : params.size*0.5f;
|
||||
params.heading = GetNormalized(m_vDelta);
|
||||
params.velocity = m_vDelta.Length();
|
||||
params.wspin = m_vRotation*0.25f;
|
||||
params.q0.SetRotationXYZ( m_vAngles*(gf_PI/180.0f) );
|
||||
|
||||
if(!Params.vNormal.IsZero())
|
||||
params.normal = Params.vNormal;
|
||||
else if(Params.pStatObj)
|
||||
{
|
||||
Vec3d vSize = Params.pStatObj->GetBoxMax() - Params.pStatObj->GetBoxMin();
|
||||
char cMinAxis = GetMinAxis(vSize);
|
||||
params.normal = Vec3d((cMinAxis=='x')?1.f:0,(cMinAxis=='y')?1.f:0,(cMinAxis=='z')?1.f:0);
|
||||
}
|
||||
|
||||
params.surface_idx = Params.iPhysMat;
|
||||
params.gravity = Params.vGravity*m_fScale;
|
||||
params.flags = particle_no_roll|particle_no_path_alignment;
|
||||
// params.acc_lift=0;
|
||||
// params.k_air_resistance=0;
|
||||
// params.acc_thrust=0;
|
||||
// params.acc_lift=0;
|
||||
// params.wspin = PPP.pPartSpray->m_vRotation;
|
||||
|
||||
// params.q0.set(0,0,0);
|
||||
// params.collider_to_ignore=0;
|
||||
|
||||
m_pPhysEnt->SetParams(¶ms);
|
||||
}
|
||||
}
|
||||
906
Cry3DEngine/partman.cpp
Normal file
906
Cry3DEngine/partman.cpp
Normal file
@@ -0,0 +1,906 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: partman.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: manage particles and sprites
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "partman.h"
|
||||
#include "objman.h"
|
||||
#include "visareas.h"
|
||||
#include "ParticleEffect.h"
|
||||
#include "3dEngine.h"
|
||||
|
||||
#define PARTICLES_FILE_TYPE 2
|
||||
#define PARTICLES_FILE_VERSION 4
|
||||
#define PARTICLES_FILE_SIGNATURE "CRY"
|
||||
|
||||
#define ACTIVE_TIME 1
|
||||
|
||||
#define EFFECTS_FOLDER "CRY"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#pragma pack(push,1)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SExportedParticlesHeader
|
||||
{
|
||||
char signature[3]; // File signature.
|
||||
int filetype; // File type.
|
||||
int version; // File version.
|
||||
};
|
||||
|
||||
struct SExportParticleSound
|
||||
{
|
||||
enum {
|
||||
LOOP = 0x01,
|
||||
EVERY_SPAWN = 0x02,
|
||||
};
|
||||
char soundfile[64];
|
||||
float volume;
|
||||
float minRadius;
|
||||
float maxRadius;
|
||||
char nSoundFlags;
|
||||
};
|
||||
|
||||
enum EParticleExportFlags
|
||||
{
|
||||
PARTICLE_EFFECT_DISABLED = 0x01
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Particle system parameters
|
||||
struct SExportParticleParams
|
||||
{
|
||||
Vec3 vPosition; // spawn position
|
||||
Vec3 vDirection; // initial direction (normalization not important)
|
||||
float fFocus; // if 0 - particles go in all directions, if more than 20 - particles go mostly in vDirection
|
||||
Vec3 vColorStart; // initial color
|
||||
Vec3 vColorEnd; // final color
|
||||
FloatVariant fSpeed; // initial speed ( +- 25% random factor applyed, m/sec )
|
||||
float fSpeedFadeOut; // Time in which before end of life time speed decreases from normal to 0.
|
||||
float fSpeedAccel; // Constant speed acceleration along particle heading.
|
||||
float fAirResistance; // Air resistance.
|
||||
Vec3Variant vRotation; // rotation speed (degree/sec)
|
||||
Vec3Variant vInitAngles; // initial rotation
|
||||
int nCount; // number of particles to spawn
|
||||
FloatVariant fSize; // initial size of particles
|
||||
float fSizeSpeed; // particles will grow with this speed
|
||||
float fSizeFadeIn; // Time in which at the begning of life time size goes from 0 to fSize.
|
||||
float fSizeFadeOut; // Time in which at the end of life time size goes from fSize to 0.
|
||||
float fThickness; // lying thickness - for physicalized particles only
|
||||
FloatVariant fLifeTime; // time of life of particle
|
||||
float fFadeInTime; // particle will fade in slowly during this time
|
||||
int nTexAnimFramesCount; // number of frames in animated texture ( 0 if no animation )
|
||||
ParticleBlendType eBlendType; // see ParticleBlendType
|
||||
float fTailLenght; // delay of tail ( 0 - no tail, 1 meter if speed is 1 meter/sec )
|
||||
float fStretch; // Stretch particles into moving direction.
|
||||
int nParticleFlags; // see particle system flags
|
||||
bool bRealPhysics; // use physics engine to control particles
|
||||
float fChildSpawnPeriod; // if more than 0 - run child process every x seconds, if 0 - run it at collision
|
||||
float fChildSpawnTime; // if more then 0, Spawn child process for max this ammount of time.
|
||||
int nDrawLast; // add this element into second list and draw this list last
|
||||
float fBouncenes; // if 0 - particle will not bounce from the ground, 0.5 is good in most cases
|
||||
float fTurbulenceSize; // radius of turbulence
|
||||
float fTurbulenceSpeed; // speed of rotation
|
||||
float fDirVecScale; //the game need to store this(Alberto)
|
||||
float fPosRandomOffset; // maximum distance of random offset from original position
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// New parameters, used by Particle effects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Spawn Position offset from effect spawn position.
|
||||
Vec3 vPositionOffset;
|
||||
//! Random offset of particle relative to spawn position.
|
||||
Vec3 vRandomPositionOffset;
|
||||
//! Delay actual spawn time by this ammount.
|
||||
FloatVariant fSpawnDelay;
|
||||
//! Life time of emitter.
|
||||
FloatVariant fEmitterLifeTime;
|
||||
//! When using emitter, spawn time between between 2 particle bursts.
|
||||
float fSpawnPeriod;
|
||||
|
||||
//! Global effect scale. (0 ignored)
|
||||
float fScale;
|
||||
//! Object scale, multiplied with fSize to give scale adjustment between object and texture.
|
||||
//! 0 not affect fSize.
|
||||
float fObjectScale;
|
||||
|
||||
Vec3 vNormal; // lying normal - for physicalized particles only
|
||||
int iPhysMat; // material for physicalized particles
|
||||
Vec3 vGravity; // gravity(wind) vector
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Added.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
unsigned short nTailSteps;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Reserve space for new members.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
char reserve[126];
|
||||
};
|
||||
|
||||
struct SExportParticleEffect
|
||||
{
|
||||
char name[64];
|
||||
char texture[2][64];
|
||||
char geometry[2][64];
|
||||
char material[2][64];
|
||||
SExportParticleParams params[2]; // Primary and Child params.
|
||||
SExportParticleSound sound;
|
||||
int parent; // Index of parent particle.
|
||||
int flags; // General flags.
|
||||
};
|
||||
#pragma pack(pop)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPartManager::CPartManager( )
|
||||
{
|
||||
/*
|
||||
// fill list of free particles
|
||||
for(int i=0; i<MAX_PARTICLES_COUNT; i++)
|
||||
{
|
||||
m_arrParts[i].m_nId = i;
|
||||
m_FreeParticles.Add(&m_arrParts[i]);
|
||||
}
|
||||
*/
|
||||
m_currParticlesTime = 0;
|
||||
m_currParticlesFrameTime = 0;
|
||||
m_smoothTimeCount = 0;
|
||||
memset(m_smoothTimes,0,sizeof(m_smoothTimes));
|
||||
|
||||
m_pSpriteMan = new CSpriteManager(this);
|
||||
|
||||
m_nGlowTexID = GetRenderer()->GenerateAlphaGlowTexture(1);
|
||||
|
||||
m_pPartLightShader = GetRenderer()->EF_LoadShader("ParticleLight", eSH_World, EF_SYSTEM);
|
||||
|
||||
// CPartSpray::InitVertBuffers(GetRenderer());
|
||||
}
|
||||
|
||||
CPartManager::~CPartManager()
|
||||
{
|
||||
/* for(int i=0; i<m_lstpPartEmitters.Count(); i++)
|
||||
{
|
||||
m_lstpPartEmitters[i]->Shutdown();
|
||||
delete m_lstpPartEmitters[i];
|
||||
m_lstpPartEmitters.Delete(i);
|
||||
i--;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
while(m_FreeParticles.GetFirst())
|
||||
m_FreeParticles.Remove(m_FreeParticles.GetFirst());
|
||||
*/
|
||||
|
||||
Reset();
|
||||
delete m_pSpriteMan;
|
||||
|
||||
//CPartSpray::DeleteVertBuffers(GetRenderer());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::Spawn( CParticleEmitter *pEmitter,bool bChildProcess )
|
||||
{
|
||||
if(!GetCVars()->e_particles)
|
||||
return;
|
||||
|
||||
if(GetCVars()->e_particles_debug==2)
|
||||
return;
|
||||
|
||||
//GetISystem()->VTuneResume();
|
||||
if(pEmitter->m_pParams && pEmitter->m_pParams->nParticleFlags & PART_FLAG_NO_DRAW_UNDERWATER)
|
||||
{
|
||||
pEmitter->CalculateWaterLevel();
|
||||
if(pEmitter->m_fWaterLevel>pEmitter->m_pos.z)
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
float fMaxViewDist = Get3DEngine()->GetMaxViewDist();
|
||||
|
||||
ParticleParams &Params = *pEmitter->m_pParams;
|
||||
if (!bChildProcess)
|
||||
{
|
||||
Params.vPosition = pEmitter->m_pos;
|
||||
Params.vDirection = pEmitter->m_dir;
|
||||
//Params.pMaterial = pEmitter->m_pMaterial;
|
||||
Params.pEntity = pEmitter->m_pSpawnerEntity;
|
||||
|
||||
// Check distance to camera with MaxViewDistance.
|
||||
if (GetLengthSquared(Params.vPosition-vCamPos) > fMaxViewDist*fMaxViewDist)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pEmitter->m_pChildParams)
|
||||
return;
|
||||
// Check distance to camera with MaxViewDistance.
|
||||
if (GetLengthSquared(pEmitter->m_pChildParams->vPosition-vCamPos) > fMaxViewDist*fMaxViewDist)
|
||||
return;
|
||||
}
|
||||
|
||||
// make sprites
|
||||
pEmitter->OnSpawnParticles(bChildProcess);
|
||||
m_pSpriteMan->Spawn( *pEmitter,bChildProcess );
|
||||
|
||||
//GetISystem()->VTunePause();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::Spawn( const ParticleParams &Params,float fMaxViewDist,CObjManager * pObjManager,bool bNoEmitter )
|
||||
{
|
||||
// if(Params.fLifeTime<0.5 && Params.pStatObj)
|
||||
// return;
|
||||
|
||||
// Params.pStatObj = pObjManager->MakeObject("objects/box.cgf");
|
||||
//Params.vInitAngles = Params.pEntity->GetAngles();
|
||||
/*
|
||||
if((Params.nParticleFlags & PART_FLAG_HORIZONTAL) && fabs(Params.vPosition.z - Get3DEngine()->GetWaterLevel())<1.f)
|
||||
{
|
||||
GetRenderer()->EF_AddSplash(Params.vPosition, EST_Water, Params.fSize+Params.fSizeSpeed);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if(!GetCVars()->e_particles)
|
||||
return;
|
||||
|
||||
if(GetCVars()->e_particles_debug==2)
|
||||
return;
|
||||
|
||||
IParticleEmitter *pEmitter = new CParticleEmitter( this );
|
||||
pEmitter->SetParams( Params );
|
||||
ActivateEmitter( (CParticleEmitter*)pEmitter );
|
||||
}
|
||||
|
||||
void CPartManager::UpdateMan(CObjManager * pObjManager, CTerrain * pTerrain, int nRecursionLevel)
|
||||
{
|
||||
// function not used
|
||||
assert(0);
|
||||
// if(!GetCVars()->e_particles || nRecursionLevel)
|
||||
return;
|
||||
|
||||
// GetRenderer()->ResetToDefault();
|
||||
|
||||
{ // update/render particle emitters
|
||||
/* for(int i=0; i<m_lstpPartEmitters.Count(); i++)
|
||||
if(!m_lstpPartEmitters[i]->Update(pObjManager, pTerrain, nRecursionLevel, &m_FreeParticles))
|
||||
{ // remove if not used
|
||||
m_lstpPartEmitters[i]->Shutdown();
|
||||
delete m_lstpPartEmitters[i];
|
||||
m_lstpPartEmitters.Delete(i);
|
||||
i--;
|
||||
}*/
|
||||
}
|
||||
|
||||
// GetRenderer()->ResetToDefault();
|
||||
|
||||
// Draw sprites
|
||||
// get orientation for billboard particles
|
||||
Matrix44 mat;
|
||||
GetRenderer()->GetModelViewMatrix(mat.GetData());
|
||||
Vec3d
|
||||
vRight = mat.GetColumn(0),
|
||||
vUp = mat.GetColumn(1),
|
||||
vFront = mat.GetColumn(2);
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//vRight(mat.cell(0), mat.cell(4), mat.cell(8));
|
||||
//vUp (mat.cell(1), mat.cell(5), mat.cell(9));
|
||||
//vFront(mat.cell(2), mat.cell(6), mat.cell(10));
|
||||
|
||||
|
||||
/*
|
||||
// set rendering state
|
||||
GetRenderer()->SetDepthFunc(R_LEQUAL);
|
||||
GetRenderer()->EnableBlend(true);
|
||||
GetRenderer()->EnableDepthWrites(false);
|
||||
GetRenderer()->SetEnviMode(R_MODE_MODULATE);
|
||||
GetRenderer()->SetCullMode(R_CULL_DISABLE);
|
||||
|
||||
// set world color
|
||||
Vec3d vColor = GetSystem()->GetI3DEngine()->GetWorldColor();
|
||||
GetRenderer()->SetMaterialColor(vColor.x,vColor.y,vColor.z,1);
|
||||
*/
|
||||
// float fTime = (float)GetCurTimeSec();
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//CCamera * pCamera = &GetViewCamera();
|
||||
//bool bTestVis = (nRecursionLevel==0) && ((GetFrameID()&3)==0);
|
||||
//CVars * pCVars = GetCVars();
|
||||
|
||||
m_pSpriteMan->Render(pObjManager, pTerrain, nRecursionLevel, this, m_pPartLightShader);
|
||||
|
||||
GetRenderer()->ResetToDefault();
|
||||
}
|
||||
|
||||
int CPartManager::Count(int * pCurSpritesCount, int * pCurFreeCount, int * pCurEmitCount)
|
||||
{
|
||||
int nSumm=0;
|
||||
|
||||
// for(int i=0; i<m_lstpPartEmitters.Count(); i++)
|
||||
// nSumm += m_lstpPartEmitters[i]->Count();
|
||||
|
||||
if(pCurSpritesCount)
|
||||
*pCurSpritesCount = m_pSpriteMan->m_nCurSpritesCount;
|
||||
|
||||
/*
|
||||
if(pCurFreeCount)
|
||||
*pCurFreeCount = m_FreeParticles.Count();
|
||||
*/
|
||||
|
||||
if(pCurEmitCount)
|
||||
*pCurEmitCount = 0;//m_lstpPartEmitters.Count();
|
||||
|
||||
return nSumm;
|
||||
}
|
||||
|
||||
void CPartManager::Render(CObjManager * pObjManager, CTerrain * pTerrain)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
int nRecursionLevel = pObjManager->m_nRenderStackLevel;
|
||||
|
||||
float fFrameTime = nRecursionLevel ? 0 : GetTimer()->GetFrameTime();
|
||||
if(fFrameTime>0.2f)
|
||||
fFrameTime=0.2f;
|
||||
if(fFrameTime<0)
|
||||
fFrameTime=0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Smooth frame time if not rendered in recursion.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (nRecursionLevel == 0)
|
||||
{
|
||||
m_smoothTimes[m_smoothTimeCount] = fFrameTime;
|
||||
|
||||
m_smoothTimeCount++;
|
||||
if(m_smoothTimeCount >= PARTICLES_SMOOTH_FRAMES)
|
||||
m_smoothTimeCount = 0;
|
||||
|
||||
// average multiple frames together to smooth changes out a bit
|
||||
float fTotalTime = 0;
|
||||
for (int i = 0 ; i < PARTICLES_SMOOTH_FRAMES; i++ )
|
||||
fTotalTime += m_smoothTimes[i];
|
||||
|
||||
fFrameTime = fTotalTime/PARTICLES_SMOOTH_FRAMES;
|
||||
}
|
||||
|
||||
if (GetCVars()->e_particles_debug==2)
|
||||
fFrameTime = 0;
|
||||
|
||||
if (nRecursionLevel == 0)
|
||||
{
|
||||
m_currParticlesTime += fFrameTime;
|
||||
}
|
||||
m_currParticlesFrameTime = fFrameTime;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update all emitters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (pObjManager->m_nRenderStackLevel == 0)
|
||||
{
|
||||
UpdateEmitters();
|
||||
}
|
||||
|
||||
//GetISystem()->VTuneResume();
|
||||
if(m_pSpriteMan)
|
||||
m_pSpriteMan->Render(pObjManager, pTerrain, nRecursionLevel, this, m_pPartLightShader);
|
||||
//GetISystem()->VTunePause();
|
||||
}
|
||||
/*
|
||||
C_PartEmitter * CPartManager::CreateParticleEmitter(ParticleParams Params, float fSpawnPeriod, float fLifeTime)
|
||||
{
|
||||
if(!Params.nTexId)
|
||||
Params.nTexId = m_nGlowTexID;
|
||||
|
||||
C_PartEmitter * pTmp = 0;//new C_PartEmitter(m_pSystem,this,Params, fSpawnPeriod, fLifeTime);
|
||||
// m_lstpPartEmitters.Add(pTmp);
|
||||
|
||||
return pTmp;
|
||||
} */
|
||||
/*
|
||||
void CPartManager::DeleteParticleEmitter(C_PartEmitter * pPartEmitter)
|
||||
{
|
||||
// delete pPartEmitter;
|
||||
//m_lstpPartEmitters.Delete(pPartEmitter);
|
||||
} */
|
||||
|
||||
void CPartManager::GetMemoryUsage(ICrySizer*pSizer)const
|
||||
{
|
||||
pSizer->Add (*this);
|
||||
|
||||
if(m_pSpriteMan)
|
||||
pSizer->AddObject(m_pSpriteMan, sizeof(*m_pSpriteMan));
|
||||
}
|
||||
|
||||
void CPartManager::Reset()
|
||||
{
|
||||
int i;
|
||||
bool bActive = true;
|
||||
IPhysicalWorld *pPhysWorld = Cry3DEngineBase::GetPhysicalWorld();
|
||||
for (i = 0; i < m_pSpriteMan->m_nCurSpritesCount && i<m_pSpriteMan->m_nMaxSpritesCount; i++)
|
||||
m_pSpriteMan->m_arrSprites[i].DeActivateParticle( pPhysWorld );
|
||||
m_pSpriteMan->m_nCurSpritesCount=0;
|
||||
|
||||
// Clear all emitters.
|
||||
for (ActiveEmitters::iterator it = m_activeEmitters.begin(); it != m_activeEmitters.end(); ++it)
|
||||
{
|
||||
CParticleEmitter *pEmitter = *it;
|
||||
pEmitter->OnActivate( false );
|
||||
}
|
||||
m_activeEmitters.clear();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Unload resources for all effects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
for (i = 0; i < (int)m_effects.size(); i++)
|
||||
{
|
||||
IParticleEffect *pEffect = m_effects[i];
|
||||
((CParticleEffect*)pEffect)->UnloadResources(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CPartManager::OnEntityDeleted(IEntityRender * pEntityRender)
|
||||
{
|
||||
if(m_pSpriteMan)
|
||||
m_pSpriteMan->OnEntityDeleted(pEntityRender);
|
||||
|
||||
{ // delete active emitters of this entity
|
||||
ActiveEmitters::iterator next;
|
||||
for (ActiveEmitters::iterator it = m_activeEmitters.begin(); it != m_activeEmitters.end(); it = next)
|
||||
{
|
||||
next = it;
|
||||
next++;
|
||||
CParticleEmitter *pEmitter = *it;
|
||||
if(pEmitter->m_pSpawnerEntity == pEntityRender)
|
||||
{
|
||||
pEmitter->OnActivate( false );
|
||||
m_activeEmitters.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // delete global emitters of this entity
|
||||
ParticleEmitters::iterator next;
|
||||
for (ParticleEmitters::iterator it = m_allEmitters.begin(); it != m_allEmitters.end(); it = next)
|
||||
{
|
||||
next = it;
|
||||
next++;
|
||||
CParticleEmitter *pEmitter = *it;
|
||||
if(pEmitter->m_pSpawnerEntity == pEntityRender)
|
||||
{
|
||||
pEmitter->OnActivate( false );
|
||||
m_allEmitters.erase( it );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSpriteManager::OnEntityDeleted(IEntityRender * pEntityRender)
|
||||
{
|
||||
for( int i=0; i<m_nCurSpritesCount && i<m_nMaxSpritesCount; i++)
|
||||
{
|
||||
if(m_arrSprites[i].m_pSpawnerEntity == pEntityRender)
|
||||
{ // remove
|
||||
m_arrSprites[i].DeActivateParticle( Cry3DEngineBase::GetPhysicalWorld());
|
||||
m_arrSprites[i].m_pSpawnerEntity=0;
|
||||
|
||||
if(i < m_nCurSpritesCount-1)
|
||||
{
|
||||
m_arrSprites[i] = m_arrSprites[m_nCurSpritesCount-1];
|
||||
memset(&m_arrSprites[m_nCurSpritesCount-1],0,sizeof(m_arrSprites[m_nCurSpritesCount-1]));
|
||||
}
|
||||
m_nCurSpritesCount--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particle Effects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEffect* CPartManager::CreateEffect()
|
||||
{
|
||||
IParticleEffect_AutoPtr pEffect = new CParticleEffect( this );
|
||||
m_effects.push_back( pEffect );
|
||||
return pEffect;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::RenameEffect( IParticleEffect *pEffect,const char *sNewName )
|
||||
{
|
||||
assert( pEffect );
|
||||
const char *sOldName = pEffect->GetName();
|
||||
if (strlen(sOldName) > 0)
|
||||
{
|
||||
// Delete old name.
|
||||
m_effectsMap[sOldName] = 0;
|
||||
}
|
||||
if (strlen(sNewName) > 0)
|
||||
{
|
||||
// Add new name.
|
||||
m_effectsMap[sNewName] = pEffect;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::RemoveEffect( IParticleEffect *pEffect )
|
||||
{
|
||||
assert( pEffect );
|
||||
const char *sOldName = pEffect->GetName();
|
||||
if (strlen(sOldName) > 0)
|
||||
{
|
||||
// Delete old name.
|
||||
m_effectsMap[sOldName] = 0;
|
||||
}
|
||||
stl::find_and_erase( m_effects,pEffect );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEffect* CPartManager::FindEffect( const char *sEffectName )
|
||||
{
|
||||
IParticleEffect *pEffect = stl::find_in_map(m_effectsMap,sEffectName,(IParticleEffect*)NULL);
|
||||
return pEffect;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::UpdateEmitters()
|
||||
{
|
||||
float fTime = GetParticlesTime();
|
||||
CCamera *pCamera = &GetViewCamera();
|
||||
|
||||
ActiveEmitters::iterator next;
|
||||
for (ActiveEmitters::iterator it = m_activeEmitters.begin(); it != m_activeEmitters.end(); it = next)
|
||||
{
|
||||
next = it;
|
||||
next++;
|
||||
|
||||
_smart_ptr<CParticleEmitter> pEmitter = (*it);
|
||||
CParticleEmitter &emitter = *pEmitter;
|
||||
|
||||
/*
|
||||
// Check if emitter is visible.
|
||||
if (pCamera->IsAABBVisibleFast(emitter.m_bbox))
|
||||
emitter.m_bVisible = true;
|
||||
else
|
||||
emitter.m_bVisible = false;
|
||||
// Reset bounding box.
|
||||
emitter.m_bbox.Reset();
|
||||
*/
|
||||
|
||||
float fSpawnPeriod = emitter.m_spawnPeriod/max(0.01f,GetCVars()->e_particles_lod) + (1.f-GetCVars()->e_particles_lod)*0.1f;
|
||||
if (fTime > emitter.m_startTime || emitter.m_startTime == 0)
|
||||
{
|
||||
if (fTime - emitter.m_lastSpawnTime > fSpawnPeriod || fSpawnPeriod == 0)
|
||||
{
|
||||
// Remember last spawn time.
|
||||
emitter.m_lastSpawnTime = fTime;
|
||||
|
||||
if (!pEmitter->m_childEmitters.empty())
|
||||
pEmitter->UpdateChildSpawnTimes(fTime);
|
||||
|
||||
// Spawn particles from this emitter.
|
||||
if (emitter.m_pEffect)
|
||||
{
|
||||
CParticleEffect* pEffect = (CParticleEffect*)((IParticleEffect*)emitter.m_pEffect);
|
||||
if (!pEffect->PrepareSpawn( pEmitter->m_pos ))
|
||||
continue;
|
||||
}
|
||||
Spawn( pEmitter );
|
||||
}
|
||||
}
|
||||
if (!pEmitter->m_childEmitters.empty())
|
||||
{
|
||||
for (int i = 0; i < (int)pEmitter->m_childEmitters.size(); i++)
|
||||
{
|
||||
CParticleEmitter *pChildEmitter = pEmitter->m_childEmitters[i];
|
||||
|
||||
/*
|
||||
// Check if emitter is visible.
|
||||
if (pCamera->IsAABBVisibleFast(pChildEmitter->m_bbox))
|
||||
pChildEmitter->m_bVisible = true;
|
||||
else
|
||||
pChildEmitter->m_bVisible = false;
|
||||
pChildEmitter->m_bbox.Reset();
|
||||
*/
|
||||
|
||||
if (!pChildEmitter->m_bActive || !pChildEmitter->m_bActiveChild)
|
||||
continue;
|
||||
|
||||
if (fTime < pChildEmitter->m_startTime && emitter.m_startTime != 0)
|
||||
continue;
|
||||
|
||||
// Check if needs to Deactivate emitter, on next update, spawn particles on this update anyway.
|
||||
if (fTime > pChildEmitter->m_endTime)
|
||||
pChildEmitter->m_bActiveChild = false;
|
||||
|
||||
float spawnPeriod = pChildEmitter->m_spawnPeriod/max(0.01f,GetCVars()->e_particles_lod) + (1.f-GetCVars()->e_particles_lod)*0.1f;
|
||||
if (pChildEmitter->m_pParams->fEmitterLifeTime <= 0 && pChildEmitter->m_pParams->fSpawnDelay <= 0)
|
||||
{
|
||||
float spawnPeriodMul = pChildEmitter->m_pParams->fSpawnPeriod;
|
||||
if (spawnPeriodMul == 0)
|
||||
spawnPeriodMul = 1;
|
||||
spawnPeriod = fSpawnPeriod * spawnPeriodMul;
|
||||
}
|
||||
|
||||
if (fTime - pChildEmitter->m_lastSpawnTime > spawnPeriod)
|
||||
{
|
||||
// Remember last spawn time.
|
||||
pChildEmitter->m_lastSpawnTime = fTime;
|
||||
pChildEmitter->m_pos = pEmitter->m_pos;
|
||||
pChildEmitter->m_dir = pEmitter->m_dir;
|
||||
pChildEmitter->m_fScale = pEmitter->m_fScale;
|
||||
// Spawn particles from this emitter.
|
||||
if (emitter.m_pEffect)
|
||||
{
|
||||
CParticleEffect* pEffect = (CParticleEffect*)((IParticleEffect*)pChildEmitter->m_pEffect);
|
||||
if (!pEffect->PrepareSpawn( pEmitter->m_pos ))
|
||||
continue;
|
||||
}
|
||||
Spawn( pChildEmitter );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If emitter end time == 0 do not kill this emitter.
|
||||
if (fTime > emitter.m_endTime && emitter.m_bUseEndTime)
|
||||
{
|
||||
pEmitter->OnActivate( false );
|
||||
// Times up, delete this emitter.
|
||||
m_activeEmitters.erase( it );
|
||||
// Also delete it from total emitters.
|
||||
DeleteEmitter( pEmitter );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (emitter.m_bPermament && fTime > emitter.m_lastActiveTime+ACTIVE_TIME)
|
||||
{
|
||||
// This emitter should get deactivated.
|
||||
pEmitter->OnActivate( false );
|
||||
m_activeEmitters.erase( it );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define PATICLEPARAMS_COPY_HELPER( inparam,outparam,name ) outparam.name = inparam.name;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void ExportDataToParticleParams( const SExportParticleParams &inp,ParticleParams &outp )
|
||||
{
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vPosition );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vDirection );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fFocus );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vColorStart );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vColorEnd );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSpeed );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSpeedFadeOut );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSpeedAccel );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fAirResistance );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vRotation );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vInitAngles );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,nCount );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSize );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSizeSpeed );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSizeFadeIn );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSizeFadeOut );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fThickness );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fLifeTime );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fFadeInTime );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,nTexAnimFramesCount );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,eBlendType );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fTailLenght );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,nTailSteps );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fStretch );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,nParticleFlags );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,bRealPhysics );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fChildSpawnPeriod );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fChildSpawnTime );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,nDrawLast );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fBouncenes );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fTurbulenceSize );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fTurbulenceSpeed );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fDirVecScale );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fPosRandomOffset );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vPositionOffset );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vRandomPositionOffset );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSpawnDelay );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fEmitterLifeTime );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fSpawnPeriod );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fScale );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,fObjectScale );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vNormal );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,iPhysMat );
|
||||
PATICLEPARAMS_COPY_HELPER( inp,outp,vGravity );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPartManager::LoadParticles( CCryFile &file )
|
||||
{
|
||||
//UpdateLoadingScreen( "\003Loading Particle Effects..." );
|
||||
|
||||
SExportedParticlesHeader header;
|
||||
file.Read( &header,sizeof(header) );
|
||||
if (strncmp(header.signature,PARTICLES_FILE_SIGNATURE,sizeof(header.signature)) != 0)
|
||||
{
|
||||
// Bad signature.
|
||||
Warning( 0,file.GetFilename(),"Cannot Load Particles,Wrong File Signature %s",file.GetFilename() );
|
||||
return false;
|
||||
}
|
||||
if (header.filetype != PARTICLES_FILE_TYPE)
|
||||
{
|
||||
// Bad signature.
|
||||
Warning( 0,file.GetFilename(),"Cannot Load Particles,Wrong File Type %s",file.GetFilename() );
|
||||
return false;
|
||||
}
|
||||
if (header.version != PARTICLES_FILE_VERSION)
|
||||
{
|
||||
// Bad signature.
|
||||
Warning( 0,file.GetFilename(),"Cannot Load Particles,Wrong File Version %s",file.GetFilename() );
|
||||
return false;
|
||||
}
|
||||
|
||||
int numItems;
|
||||
file.Read( &numItems,sizeof(numItems) );
|
||||
|
||||
std::vector<SExportParticleEffect> exportedEffects;
|
||||
std::vector<IParticleEffect*> libEffects;
|
||||
|
||||
exportedEffects.resize( numItems );
|
||||
libEffects.resize( numItems );
|
||||
|
||||
int fileSize = file.GetLength();
|
||||
if (numItems*sizeof(SExportParticleEffect) != fileSize-sizeof(header)-sizeof(numItems))
|
||||
{
|
||||
Warning( 0,file.GetFilename(),"Cannot Load Particles,Corrupted File %s",file.GetFilename() );
|
||||
return false;
|
||||
}
|
||||
if (numItems > 0)
|
||||
{
|
||||
file.Read( &exportedEffects[0],numItems*sizeof(SExportParticleEffect) );
|
||||
}
|
||||
|
||||
//UpdateLoadingScreen( "Loading Particles %s",file.GetFilename() );
|
||||
int i;
|
||||
// Initialize effects.
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
IParticleEffect_AutoPtr pEffect = CreateEffect();
|
||||
libEffects[i] = pEffect;
|
||||
for (int p = 0; p < IParticleEffect::NUM_PARTICLE_PROCESSES; p++)
|
||||
{
|
||||
ParticleParams ¶ms = pEffect->GetParticleParams(p);
|
||||
ExportDataToParticleParams( exportedEffects[i].params[p],params );
|
||||
// Reset data that must be loaded.
|
||||
params.nTexId = 0;
|
||||
params.pStatObj = 0;
|
||||
params.pMaterial = 0;
|
||||
params.pChild = 0;
|
||||
params.pAnimTex = 0;
|
||||
params.pEntity = 0;
|
||||
params.pShader = 0;
|
||||
|
||||
pEffect->SetTexture( p,exportedEffects[i].texture[p] );
|
||||
pEffect->SetGeometry( p,exportedEffects[i].geometry[p] );
|
||||
pEffect->SetMaterialName( p,exportedEffects[i].material[p] );
|
||||
|
||||
// Load Resources at this point.
|
||||
}
|
||||
if (exportedEffects[i].flags & PARTICLE_EFFECT_DISABLED)
|
||||
{
|
||||
pEffect->SetEnabled(false);
|
||||
}
|
||||
|
||||
IParticleEffect::SoundParams sndParams;
|
||||
sndParams.szSound = exportedEffects[i].sound.soundfile;
|
||||
sndParams.volume = exportedEffects[i].sound.volume;
|
||||
sndParams.minRadius = exportedEffects[i].sound.minRadius;
|
||||
sndParams.maxRadius = exportedEffects[i].sound.maxRadius;
|
||||
sndParams.bLoop = (exportedEffects[i].sound.nSoundFlags & SExportParticleSound::LOOP) != 0;
|
||||
sndParams.bOnEverySpawn = (exportedEffects[i].sound.nSoundFlags & SExportParticleSound::EVERY_SPAWN) != 0;
|
||||
pEffect->SetSoundParams(sndParams);
|
||||
|
||||
pEffect->SetName( exportedEffects[i].name );
|
||||
pEffect->LoadResources();
|
||||
}
|
||||
// Link to parents.
|
||||
for (i = 0; i < (int)exportedEffects.size(); i++)
|
||||
{
|
||||
int parent = exportedEffects[i].parent;
|
||||
if (parent >= 0)
|
||||
{
|
||||
IParticleEffect* pEffect = libEffects[i];
|
||||
IParticleEffect* pParentEffect = libEffects[parent];
|
||||
pParentEffect->AddChild( pEffect );
|
||||
}
|
||||
}
|
||||
|
||||
UpdateLoadingScreen( "\003Loaded %d Particle Effects from %s.",numItems,file.GetFilename() );
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEmitter* CPartManager::CreateEmitter()
|
||||
{
|
||||
CParticleEmitter *pEmitter = new CParticleEmitter( this );
|
||||
pEmitter->m_bPermament = true;
|
||||
m_allEmitters.insert( pEmitter );
|
||||
return pEmitter;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::DeleteEmitter( IParticleEmitter *pEmitter )
|
||||
{
|
||||
assert( pEmitter );
|
||||
|
||||
CParticleEmitter *pEmt = (CParticleEmitter*)pEmitter;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (pEmt->m_bPermament)
|
||||
m_allEmitters.erase( pEmt );
|
||||
// delete emitter from list.
|
||||
if (pEmt->m_bActive)
|
||||
stl::find_and_erase( m_activeEmitters,pEmt );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::ActivateEmitter( CParticleEmitter *pEmitter )
|
||||
{
|
||||
if (pEmitter!=NULL && !pEmitter->m_bActive)
|
||||
{
|
||||
pEmitter->OnActivate( true );
|
||||
m_activeEmitters.push_back( pEmitter );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::LoadSharedParticleLibrary( const char *sEffectsFolder,const char *sLibName )
|
||||
{
|
||||
if (m_loadedLibs.find(sLibName) != m_loadedLibs.end())
|
||||
{
|
||||
// Already loaded.
|
||||
return;
|
||||
}
|
||||
|
||||
char filename[_MAX_PATH];
|
||||
_makepath( filename,NULL,sEffectsFolder,sLibName,"prt" );
|
||||
|
||||
CCryFile file;
|
||||
if (file.Open( filename,"rb" ))
|
||||
{
|
||||
LoadParticles( file );
|
||||
m_loadedLibs.insert( sLibName );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPartManager::LoadParticlesLibs( const char *sEffectsFolder,XmlNodeRef &levelDataRoot )
|
||||
{
|
||||
XmlNodeRef libs = levelDataRoot->findChild( "ParticlesLibrary" );
|
||||
if (!libs)
|
||||
return;
|
||||
|
||||
// Enmerate material libraries.
|
||||
for (int i = 0; i < libs->getChildCount(); i++)
|
||||
{
|
||||
XmlNodeRef libNode = libs->getChild(i);
|
||||
XmlString libraryName = libNode->getAttr( "Name");
|
||||
LoadSharedParticleLibrary( sEffectsFolder,libraryName );
|
||||
}
|
||||
}
|
||||
358
Cry3DEngine/partman.h
Normal file
358
Cry3DEngine/partman.h
Normal file
@@ -0,0 +1,358 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: partman.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PART_MANAGER
|
||||
#define PART_MANAGER
|
||||
|
||||
#define MAX_PARTICLES_IN_VIDEO_BUFFER 16
|
||||
#define MAX_VIDEO_BUFFERS_PER_SPRAY 4
|
||||
|
||||
#define PARTICLES_SMOOTH_FRAMES 20
|
||||
|
||||
#define PART_MAX_HISTORY_ELEMENTS 256
|
||||
|
||||
#define rn() ((((float)rand())/RAND_MAX)-0.5f)
|
||||
|
||||
#include "ParticleEffect.h"
|
||||
#include "ParticleEmitter.h"
|
||||
|
||||
// particle proc params
|
||||
struct PartProcessParams
|
||||
{
|
||||
PartProcessParams() { memset(this, 0, sizeof(PartProcessParams)); }
|
||||
float fCurTime, fFrameTime;
|
||||
Vec3d vRight, vUp, vFront;
|
||||
IRenderer * pIRenderer;
|
||||
CObjManager * pObjManager;
|
||||
CTerrain * pTerrain;
|
||||
IPhysicalWorld * pPhysicalWorld;
|
||||
class C3DEngine *p3DEngine;
|
||||
CCamera * pCamera;
|
||||
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F * pVertBufChunk;
|
||||
struct ISystem * pSystem;
|
||||
class CPartManager * pPartManager;
|
||||
Vec3 vCamPos;
|
||||
Vec3d vSpaceFocusPos;
|
||||
};
|
||||
|
||||
class CPartManager;
|
||||
|
||||
// dynamic particle data
|
||||
class CParticle
|
||||
{
|
||||
public:
|
||||
enum EAdvancedParticleFlags
|
||||
{
|
||||
PARTICLE_COLOR_BASED = 0x10000,
|
||||
PARTICLE_ADDITIVE = 0x20000,
|
||||
PARTICLE_ANIMATED_TEXTURE = 0x40000
|
||||
};
|
||||
|
||||
//int m_nId; // debug
|
||||
//CParticle *m_pNext, *m_pPrev;
|
||||
|
||||
// cur state
|
||||
int m_nParticleFlags;
|
||||
Vec3 m_vPos;
|
||||
Vec3 m_vDelta;
|
||||
float m_fSize;
|
||||
float m_fSizeOriginal;
|
||||
float m_fScale;
|
||||
float m_fSpawnTime;
|
||||
float m_fLifeTime;
|
||||
float m_fChildSpawnLastTime;
|
||||
float m_fTrailCurPos;
|
||||
Vec3 m_vAngles;
|
||||
Vec3 m_vRotation;
|
||||
//int m_nDynLightMask;
|
||||
//int m_nFogVolumeId;
|
||||
unsigned int m_cAmbientColor;
|
||||
//! Override material for this emitter.
|
||||
IMatInfo *m_pMaterial;
|
||||
//! Entity who controls this emitter.
|
||||
IEntityRender *m_pSpawnerEntity;
|
||||
|
||||
//IVisArea * m_pVisArea;
|
||||
IPhysicalEntity * m_pPhysEnt;
|
||||
ParticleParams* m_pParams;
|
||||
|
||||
//! Emitter who spawned this entity.
|
||||
CParticleEmitter* m_pEmitter;
|
||||
|
||||
// For patricles with tail, keeps history of previous positions.
|
||||
Vec3 *m_pArrvPosHistory;
|
||||
unsigned char m_nTailSteps;
|
||||
char m_reserved[3]; // Fill to 32 byte.
|
||||
|
||||
CParticle()
|
||||
{
|
||||
//m_nId=0;
|
||||
m_nParticleFlags = 0;
|
||||
m_vPos(0,0,0);
|
||||
m_vDelta(0,0,0);
|
||||
m_fSize=0;
|
||||
m_fSizeOriginal=0;
|
||||
//m_pNext=m_pPrev=0;
|
||||
m_fSpawnTime=0;
|
||||
m_pPhysEnt=0;
|
||||
m_fScale = 1;
|
||||
m_fChildSpawnLastTime = 0;
|
||||
//m_fTrailCurPos = 0;
|
||||
m_vAngles(0,0,0);
|
||||
m_vRotation(0,0,0);
|
||||
m_cAmbientColor = 0;
|
||||
//m_pVisArea = 0;
|
||||
//m_nDynLightMask = 0;
|
||||
//m_nFogVolumeId = 0;
|
||||
m_pMaterial = 0;
|
||||
m_pSpawnerEntity = 0;
|
||||
m_pArrvPosHistory = 0;
|
||||
m_fTrailCurPos = 0;
|
||||
m_nTailSteps = 8;
|
||||
m_reserved[0] = 0;
|
||||
m_reserved[1] = 0;
|
||||
m_reserved[2] = 0;
|
||||
}
|
||||
|
||||
bool Update(const PartProcessParams & PPP);
|
||||
void FillBuffer(const PartProcessParams & PPP);
|
||||
void DeActivateParticle(IPhysicalWorld * pPhysicalWorld);
|
||||
void Physicalize( ParticleParams &Params,IPhysicalWorld * pPhysicalWorld);
|
||||
unsigned int Vec2Color( const Vec3 &v )
|
||||
{
|
||||
unsigned int r = (FtoI(v.x*255.0f)), g = FtoI(v.y*255.0f), b = FtoI(v.z*255.0f);
|
||||
return r|(g<<8)|(b<<16);
|
||||
}
|
||||
Vec3 Color2Vec( unsigned int c )
|
||||
{
|
||||
return Vec3(
|
||||
((unsigned char)(c))*0.00392156f,
|
||||
((unsigned char)(c>>8))*0.00392156f,
|
||||
((unsigned char)(c>>16))*0.00392156f );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
// linked list of particles
|
||||
class CPartList
|
||||
{
|
||||
CParticle *m_pFirst, *m_pLast;
|
||||
int m_nCount;
|
||||
|
||||
public:
|
||||
|
||||
CPartList() { memset(this,0,sizeof(CPartList)); }
|
||||
~CPartList() { assert(!m_nCount && !m_pFirst); }
|
||||
int Count() { return m_nCount; }
|
||||
CParticle * GetFirst() { return m_pFirst; }
|
||||
CParticle * GetLast() { return m_pLast; }
|
||||
|
||||
void Add(CParticle * pElem)
|
||||
{
|
||||
assert(!pElem->m_pNext && !pElem->m_pPrev);
|
||||
|
||||
if(!m_pFirst)
|
||||
{ // insert first element
|
||||
m_pFirst = m_pLast = pElem;
|
||||
pElem->m_pNext = pElem->m_pPrev = 0;
|
||||
|
||||
assert(!m_nCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!m_pLast->m_pNext && !m_pFirst->m_pPrev);
|
||||
|
||||
pElem->m_pPrev = m_pLast;
|
||||
pElem->m_pNext = 0;
|
||||
m_pLast->m_pNext = pElem;
|
||||
m_pLast = pElem;
|
||||
|
||||
assert(m_nCount);
|
||||
}
|
||||
m_nCount++;
|
||||
}
|
||||
|
||||
void Remove(CParticle * pElem)
|
||||
{
|
||||
if(m_pLast == pElem)
|
||||
m_pLast = pElem->m_pPrev;
|
||||
|
||||
if(m_pFirst == pElem)
|
||||
m_pFirst = pElem->m_pNext;
|
||||
|
||||
if(pElem->m_pNext)
|
||||
{
|
||||
assert(pElem->m_pNext->m_pPrev == pElem);
|
||||
pElem->m_pNext->m_pPrev = pElem->m_pPrev;
|
||||
}
|
||||
|
||||
if(pElem->m_pPrev)
|
||||
{
|
||||
assert(pElem->m_pPrev->m_pNext == pElem);
|
||||
pElem->m_pPrev->m_pNext = pElem->m_pNext;
|
||||
}
|
||||
|
||||
pElem->m_pPrev = pElem->m_pNext = 0;
|
||||
m_nCount--;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
// sprite contain dynamic data and life style
|
||||
class CSprite : public CParticle
|
||||
{
|
||||
public:
|
||||
void Render( const PartProcessParams &PPP, IShader *pShader );
|
||||
int FillTailVertBuffer( SColorVert * pTailVerts,
|
||||
const Vec3d & vCamVec,
|
||||
const UCol & ucColor );
|
||||
};
|
||||
|
||||
// manager contain all sprites(in pool) and emitters
|
||||
class CSpriteManager : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CSpriteManager(class CPartManager *pPartManager);
|
||||
~CSpriteManager();
|
||||
void Spawn( CParticleEmitter &emitter,bool bChildProcess );
|
||||
void Render( CObjManager * pObjManager, CTerrain * pTerrain, int nRecursionLevel, CPartManager * pPartManager, IShader * pPartLightShader);
|
||||
void OnEntityDeleted(IEntityRender * pEntityRender);
|
||||
|
||||
CSprite * m_arrSprites;//[MAX_SPRITES_COUNT];
|
||||
int m_nCurSpritesCount;
|
||||
int m_nMaxSpritesCount;
|
||||
|
||||
private:
|
||||
void SpawnParticle( CParticleEmitter &emitter,bool bChildProcess,float fCurrTime,CParticle *pParticle );
|
||||
|
||||
ISystem* m_pSystem;
|
||||
I3DEngine* m_p3DEngine;
|
||||
CVisAreaManager *m_pVisAreaManager;
|
||||
CObjManager *m_pObjManager;
|
||||
CPartManager *m_pPartManager;
|
||||
};
|
||||
|
||||
// contain part spray and reference counter
|
||||
/*class C_PartEmitter : public Cry3DEngineBase, public IPartEmitter
|
||||
{
|
||||
CPartManager * m_pPartManager;
|
||||
ParticleParams m_PartParams;
|
||||
float m_fSpawnPeriod, m_fLastSpawnTime, m_fLifeEndTime;
|
||||
|
||||
public:
|
||||
CPartSpray * m_pSpray;
|
||||
int m_nUsers;
|
||||
|
||||
C_PartEmitter(CPartManager * pPartManager, const ParticleParams & Params, const float fSpawnPeriod, const float fLifeTime);
|
||||
bool Update(CObjManager * pObjManager, CTerrain * pTerrain, int nRecursionLevel, CPartList * pFreeParticles);
|
||||
virtual void Spawn(const Vec3d & vPos);
|
||||
void Shutdown();
|
||||
int Count() { return m_pSpray->Count(); }
|
||||
};*/
|
||||
|
||||
// top class of particle system
|
||||
class CPartManager : public Cry3DEngineBase
|
||||
{
|
||||
public:
|
||||
CPartManager( );
|
||||
~CPartManager();
|
||||
void Spawn( const ParticleParams &Params,float fMaxViewDist, CObjManager * pObjManager,bool bNoEmitter=false );
|
||||
void Spawn( CParticleEmitter *pEmitter,bool bChildProcess=false );
|
||||
void UpdateMan(CObjManager * pObjManager, CTerrain * pTerrain, int nRecursionLevel);
|
||||
void Render(CObjManager * pObjManager, CTerrain * pTerrain);
|
||||
int Count(int * pCurSpritesCount, int * pCurFreeCount, int * pCurEmitCount);
|
||||
|
||||
// C_PartEmitter * CreateParticleEmitter(ParticleParams Params, float fSpawnPeriod = 1000000, float fLifeTime = 1000000);
|
||||
//void DeleteParticleEmitter(C_PartEmitter * pPartEmitter);
|
||||
void GetMemoryUsage(ICrySizer* pSizer)const;
|
||||
void Reset();
|
||||
void OnEntityDeleted(IEntityRender * pEntityRender);
|
||||
int GetGlowTexID() const { return m_nGlowTexID; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particle effects interface.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEffect* CreateEffect();
|
||||
void RenameEffect( IParticleEffect *pEffect,const char *sNewName );
|
||||
void RemoveEffect( IParticleEffect *pEffect );
|
||||
IParticleEffect* FindEffect( const char *sEffectName );
|
||||
|
||||
//! Load particle effects from file.
|
||||
//! @return true if succesfully loaded.
|
||||
bool LoadParticles( CCryFile &file );
|
||||
void LoadSharedParticleLibrary( const char *sEffectsFolder,const char *sLibName );
|
||||
void LoadParticlesLibs( const char *sEffectsFolder,XmlNodeRef &levelDataRoot );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Emitters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IParticleEmitter* CreateEmitter();
|
||||
void DeleteEmitter( IParticleEmitter *pEmitter );
|
||||
void ActivateEmitter( CParticleEmitter *pEmitter );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particles timing.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float GetParticlesTime() const { return m_currParticlesTime; };
|
||||
float GetParticlesFrameTime() const { return m_currParticlesFrameTime; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void PlaySound( ISound *pSound );
|
||||
|
||||
protected:
|
||||
void UpdateEmitters();
|
||||
void UpdateSounds();
|
||||
|
||||
private:
|
||||
//CPartList m_FreeParticles;
|
||||
//CParticle m_arrParts[MAX_PARTICLES_COUNT];
|
||||
CSpriteManager * m_pSpriteMan;
|
||||
int m_nGlowTexID;
|
||||
// list2<CPartEmitter*> m_lstpPartEmitters;
|
||||
IShader * m_pPartLightShader;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//[Timur] Particle Effects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Array of all registered particle effects.
|
||||
std::vector<IParticleEffect_AutoPtr> m_effects;
|
||||
//! Map of particle effect case insensetive name to interface pointer.
|
||||
typedef std::map<String,IParticleEffect_AutoPtr,stl::less_stricmp<String> > EffectsMap;
|
||||
EffectsMap m_effectsMap;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Loaded particle libs.
|
||||
std::set<String,stl::less_stricmp<String> > m_loadedLibs;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particle effects emitters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef std::set<_smart_ptr<CParticleEmitter> > ParticleEmitters;
|
||||
typedef std::list<_smart_ptr<CParticleEmitter> > ActiveEmitters;
|
||||
ParticleEmitters m_allEmitters;
|
||||
ActiveEmitters m_activeEmitters;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Particle time smoothing.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float m_currParticlesTime;
|
||||
float m_currParticlesFrameTime;
|
||||
int m_smoothTimeCount;
|
||||
float m_smoothTimes[PARTICLES_SMOOTH_FRAMES];
|
||||
};
|
||||
|
||||
#endif // PART_MANAGER
|
||||
|
||||
436
Cry3DEngine/partpolygon.cpp
Normal file
436
Cry3DEngine/partpolygon.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: partpolygon.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: sprite particles, big independent polygons
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "partman.h"
|
||||
|
||||
#include "objman.h"
|
||||
|
||||
|
||||
#include "3dEngine.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSprite::Render( const PartProcessParams &PPP,IShader *pShader )
|
||||
{
|
||||
float fCurTime = PPP.fCurTime;
|
||||
|
||||
uint nDynLightMask = 0;
|
||||
|
||||
if (m_pEmitter->m_pShader)
|
||||
{
|
||||
pShader = m_pEmitter->m_pShader;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pParams->pShader)
|
||||
pShader = m_pParams->pShader;
|
||||
else
|
||||
{
|
||||
if (m_pMaterial)
|
||||
{
|
||||
IShader *pShaderContainer = m_pMaterial->GetShaderItem().m_pShader;
|
||||
if (pShaderContainer)
|
||||
pShader = pShaderContainer->GetTemplate(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pRenderer->DrawLabel(m_vPos,2,"%d",nDynLightMask);
|
||||
|
||||
int dwCCObjFlags = 0;
|
||||
if (m_pParams->nParticleFlags & PART_FLAG_DRAW_NEAR)
|
||||
dwCCObjFlags = FOB_NEAREST;
|
||||
|
||||
// do not draw fire in the water
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_NO_DRAW_UNDERWATER && m_pEmitter->m_fWaterLevel>WATER_LEVEL_UNKNOWN)
|
||||
if(m_vPos.z < m_pEmitter->m_fWaterLevel)
|
||||
return;
|
||||
|
||||
// Render 3d object
|
||||
if(m_pParams->pStatObj)
|
||||
{
|
||||
float fObjScale = m_fSize;
|
||||
if (m_pParams->fObjectScale)
|
||||
fObjScale *= m_pParams->fObjectScale;
|
||||
|
||||
nDynLightMask = PPP.p3DEngine->GetLightMaskFromPosition(m_vPos, fObjScale);
|
||||
PPP.p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_vPos,fObjScale,m_pSpawnerEntity,1);
|
||||
|
||||
//Matrix44 matPart2=GetTranslationMat(m_vPos);
|
||||
|
||||
Matrix44 matPart2=Matrix34::CreateTranslationMat(m_vPos);
|
||||
matPart2=GetTransposed44(matPart2);
|
||||
|
||||
matPart2=Matrix33::CreateScale( Vec3d(fObjScale,fObjScale,fObjScale) )*matPart2;
|
||||
|
||||
if (m_pParams->nParticleFlags & PART_FLAG_SWAP_XY)
|
||||
{
|
||||
matPart2=Matrix33::CreateRotationAA( -m_vAngles.z*gf_DEGTORAD, Vec3d(0,0,1) )*matPart2; //NOTE: angles needs to be negated
|
||||
matPart2=Matrix33::CreateRotationAA( -m_vAngles.x*gf_DEGTORAD, Vec3d(1,0,0) )*matPart2; //NOTE: angles needs to be negated
|
||||
matPart2=Matrix33::CreateRotationAA( -m_vAngles.y*gf_DEGTORAD, Vec3d(0,1,0) )*matPart2; //NOTE: angles needs to be negated
|
||||
}
|
||||
else
|
||||
|
||||
matPart2=Matrix44::CreateRotationZYX(-gf_DEGTORAD*m_vAngles)*matPart2; //NOTE: angles in radians and negated
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
if(!(m_pParams->nParticleFlags & PART_FLAG_NO_OFFSET))
|
||||
{
|
||||
Vec3d vCenter = (m_pParams->pStatObj->GetBoxMax() + m_pParams->pStatObj->GetBoxMin())*0.5f;
|
||||
|
||||
//Matrix44 matOffSet=GetTranslationMat(-vCenter*fObjScale);
|
||||
Matrix44 matOffSet=Matrix34::CreateTranslationMat(-vCenter*fObjScale);
|
||||
matOffSet=GetTransposed44(matOffSet);
|
||||
|
||||
matPart2 = matOffSet * matPart2;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
SRendParams rParms;
|
||||
rParms.pMatrix = &matPart2;
|
||||
rParms.nDLightMask = nDynLightMask;
|
||||
rParms.nStrongestDLightMask = nDynLightMask;
|
||||
rParms.vAmbientColor = Color2Vec(m_cAmbientColor);
|
||||
rParms.dwFObjFlags = FOB_IGNOREMATERIALAMBIENT | dwCCObjFlags;
|
||||
// rParms.nFogVolumeID = m_nFogVolumeId;
|
||||
rParms.pMaterial = m_pMaterial;
|
||||
rParms.dwFObjFlags |= FOB_TRANS_MASK;
|
||||
|
||||
int nSortId = max(-4,min(4,m_pParams->nDrawLast));
|
||||
nSortId = FtoI(PPP.pObjManager->GetSortOffset(m_vPos,PPP.vCamPos,m_pEmitter->m_fWaterLevel)) - nSortId;
|
||||
rParms.fCustomSortOffset = (float)nSortId;
|
||||
|
||||
if(dwCCObjFlags & FOB_NEAREST)
|
||||
rParms.nSortValue = EFSLIST_LAST;
|
||||
|
||||
float fAge = fCurTime-m_fSpawnTime;
|
||||
float fAlpha = (1.f - (fAge - m_pParams->fFadeInTime)/(m_fLifeTime - m_pParams->fFadeInTime));//*2.f;
|
||||
//if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
|
||||
|
||||
// fadde in
|
||||
if (fAge < m_pParams->fFadeInTime && fCurTime)
|
||||
fAlpha *= fAge / m_pParams->fFadeInTime;
|
||||
|
||||
fAlpha*=1.5f;
|
||||
if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
|
||||
|
||||
rParms.fAlpha = fAlpha;
|
||||
m_pParams->pStatObj->Render(rParms,Vec3(zero),0);
|
||||
}
|
||||
|
||||
// render sprite
|
||||
if (m_pParams->nTexId)
|
||||
{
|
||||
if (m_pParams->eBlendType != ParticleBlendType_Additive)
|
||||
{
|
||||
nDynLightMask = PPP.p3DEngine->GetLightMaskFromPosition(m_vPos, 0);
|
||||
PPP.p3DEngine->CheckDistancesToLightSources(nDynLightMask,m_vPos,m_fSize,m_pSpawnerEntity,1);
|
||||
}
|
||||
|
||||
// find vertex offsets from origin
|
||||
Vec3d vFront, vRight, vUp;
|
||||
Vec3d vParticlePos = m_vPos;
|
||||
{
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_HORIZONTAL)
|
||||
{
|
||||
vRight = Vec3d(m_fSize,0,0);
|
||||
vUp = Vec3d(0,m_fSize,0);
|
||||
vFront = Vec3d(0,0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vFront = PPP.vFront;
|
||||
vRight = -PPP.vRight*m_fSize;
|
||||
vUp = -PPP.vUp*m_fSize;
|
||||
}
|
||||
|
||||
if(m_vAngles.z)
|
||||
{
|
||||
Matrix33 mat;
|
||||
mat.SetRotationAA( DEG2RAD(m_vAngles.z), vFront ); //NOTE: angles needs to be negated
|
||||
vRight = mat * vRight;
|
||||
vUp = mat * vUp;
|
||||
}
|
||||
|
||||
// Stretching to speed direction.
|
||||
if (m_pParams->fStretch != 0)
|
||||
{
|
||||
float fSpeed = m_vDelta.GetLength();
|
||||
if (fSpeed < 0.01f)
|
||||
fSpeed = 0.01f;
|
||||
|
||||
vFront = PPP.pCamera->GetPos() - m_vPos;
|
||||
vFront.Normalize();
|
||||
|
||||
Vec3d vVec1 = -vFront.Cross(m_vDelta/fSpeed);
|
||||
Vec3d vVec2 = vVec1.Cross(vFront);
|
||||
vRight = m_fSize * vVec1;
|
||||
vUp = m_fSize * vVec2;
|
||||
vUp = vUp + vUp*fSpeed*m_pParams->fStretch;
|
||||
vParticlePos -= vUp; // Offset partcile.
|
||||
}
|
||||
}
|
||||
|
||||
int nSortId = max(-4,min(4,m_pParams->nDrawLast));
|
||||
nSortId = FtoI(PPP.pObjManager->GetSortOffset(m_vPos,PPP.vCamPos,m_pEmitter->m_fWaterLevel)) - nSortId;
|
||||
/*
|
||||
if((vCamPos.z-pTerrain->Ge tWaterLevel())*(m_vPos.z-pTerrain->GetWaterLev el())>0)
|
||||
nSortId += 10000;
|
||||
else
|
||||
nSortId -= 10000;
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find color, texture and alpha
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int nTexBindId = m_pParams->nTexId;
|
||||
|
||||
float fAlpha = 1.f;
|
||||
|
||||
float t=0; // from 0 to 1
|
||||
|
||||
float fAge = fCurTime-m_fSpawnTime;
|
||||
if ((m_nParticleFlags & PARTICLE_ANIMATED_TEXTURE) && m_pParams->pAnimTex)
|
||||
{ // animated
|
||||
t = fAge/m_fLifeTime;
|
||||
if (t<0) t=0; else if(t>1) t=1;
|
||||
|
||||
float anim_time = t*(m_pParams->nTexAnimFramesCount-1);
|
||||
AnimTexInfo *pAnimTexInfo = m_pParams->pAnimTex;
|
||||
int cur_tid = 0;
|
||||
cur_tid = ((int)anim_time) % pAnimTexInfo->nFramesCount;
|
||||
nTexBindId = pAnimTexInfo->pBindIds[cur_tid];
|
||||
|
||||
//t = float(cur_tid)/(pAnimTexInfo->nFramesCount);
|
||||
}
|
||||
else if(m_pParams->nTexId>=0)
|
||||
{ // one frame
|
||||
nTexBindId = m_pParams->nTexId;
|
||||
|
||||
t = fAge/m_fLifeTime;
|
||||
if (t<0) t=0; else if(t>1) t=1;
|
||||
}
|
||||
|
||||
fAlpha = (1.f - (fAge - m_pParams->fFadeInTime)/(m_fLifeTime - m_pParams->fFadeInTime));//*2.f;
|
||||
//if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
|
||||
|
||||
if(!m_fLifeTime)
|
||||
{
|
||||
fAlpha = 1.f;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
// fadde in
|
||||
if (fAge < m_pParams->fFadeInTime && fCurTime)
|
||||
fAlpha *= fAge / m_pParams->fFadeInTime;
|
||||
|
||||
fAlpha*=1.5f;
|
||||
if(fAlpha<0) fAlpha=0; else if(fAlpha>1) fAlpha=1;
|
||||
|
||||
Vec3d vResColor;
|
||||
vResColor = m_pParams->vColorStart*(1.f-t) + m_pParams->vColorEnd*t;
|
||||
|
||||
// find result color
|
||||
if(nDynLightMask==0 && (!(m_nParticleFlags & CParticle::PARTICLE_ADDITIVE)))
|
||||
{
|
||||
vResColor.Set(0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nParticleFlags & CParticle::PARTICLE_COLOR_BASED)
|
||||
vResColor *= fAlpha*255.f;
|
||||
else
|
||||
vResColor *= 0.5f*255.f;
|
||||
}
|
||||
|
||||
Vec3 vAmbientColor;
|
||||
if (m_nParticleFlags & CParticle::PARTICLE_COLOR_BASED)
|
||||
{
|
||||
vAmbientColor.Set(0,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(PPP.p3DEngine->GetFogEnd()>PPP.p3DEngine->GetFogStart())
|
||||
{
|
||||
float fDist = (L1Distance2D(m_vPos, PPP.vCamPos)-PPP.p3DEngine->GetFogStart())
|
||||
/(PPP.p3DEngine->GetFogEnd()-PPP.p3DEngine->GetFogStart());
|
||||
if(fDist>1.f)
|
||||
fDist=1.f;
|
||||
else if(fDist<0)
|
||||
fDist=0;
|
||||
fAlpha *= (1.f-fDist);
|
||||
}
|
||||
|
||||
vAmbientColor = Color2Vec(m_cAmbientColor);
|
||||
}
|
||||
|
||||
// fade if near the space bounds
|
||||
float fAlphaSpaceLoopRatio = 1.f;
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_SPACELOOP && m_pEmitter)
|
||||
{
|
||||
float fDistFromCenterX = m_pParams->vSpaceLoopBoxSize.x - fabs(m_pEmitter->m_pos.x-m_vPos.x);
|
||||
float fDistFromCenterY = m_pParams->vSpaceLoopBoxSize.y - fabs(m_pEmitter->m_pos.y-m_vPos.y);
|
||||
float fDistFromCenterZ = m_pParams->vSpaceLoopBoxSize.z - fabs(m_pEmitter->m_pos.z-m_vPos.z);
|
||||
float fMinDistToTheBorder = min(min(fDistFromCenterX,fDistFromCenterY),fDistFromCenterZ);
|
||||
fAlphaSpaceLoopRatio = max(0,min(1.f,fMinDistToTheBorder*0.5f));
|
||||
}
|
||||
|
||||
// make particle color
|
||||
UCol ucResCol;
|
||||
ucResCol.bcolor[0] = fastftol_positive(vResColor.x);
|
||||
ucResCol.bcolor[1] = fastftol_positive(vResColor.y);
|
||||
ucResCol.bcolor[2] = fastftol_positive(vResColor.z);
|
||||
ucResCol.bcolor[3] = fastftol_positive(255.f*fAlpha*fAlphaSpaceLoopRatio);
|
||||
|
||||
if(m_pParams->nParticleFlags & PART_FLAG_LINEPARTICLE)
|
||||
{ // line bullet trail
|
||||
Vec3d vCamVec = PPP.pCamera->GetPos()-m_vPos;
|
||||
|
||||
vCamVec.Normalize();
|
||||
|
||||
Vec3d vSideStep = vCamVec.Cross(m_vDelta.normalized());
|
||||
vSideStep.Normalize();
|
||||
|
||||
vSideStep.SetLen(m_fSize);
|
||||
|
||||
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vSideStep, m_vDelta*0.5f,
|
||||
ucResCol,
|
||||
m_pParams->eBlendType,
|
||||
vAmbientColor,
|
||||
vParticlePos+m_vDelta*0.5f, 0,0,0,0, (float)nSortId, dwCCObjFlags, m_pMaterial );
|
||||
}
|
||||
else if (m_pParams->fTailLenght)
|
||||
{ // render with tail
|
||||
SColorVert arrTailVerts[PART_MAX_HISTORY_ELEMENTS*2];
|
||||
byte arrTailIndices[PART_MAX_HISTORY_ELEMENTS*6];
|
||||
int nTailVertsNum=0, nTailIndsNum=0;
|
||||
|
||||
nTailVertsNum = FillTailVertBuffer( arrTailVerts, vFront, ucResCol );
|
||||
if(nTailVertsNum>2)
|
||||
{ // fill tail indices
|
||||
nTailIndsNum = (nTailVertsNum/2-1)*6;
|
||||
int nIdxId = 0;
|
||||
for(int i=0; i<(nTailVertsNum/2-1); i++)
|
||||
{
|
||||
arrTailIndices[nIdxId++] = i*2+0;
|
||||
arrTailIndices[nIdxId++] = i*2+1;
|
||||
arrTailIndices[nIdxId++] = i*2+2;
|
||||
|
||||
arrTailIndices[nIdxId++] = i*2+1;
|
||||
arrTailIndices[nIdxId++] = i*2+2;
|
||||
arrTailIndices[nIdxId++] = i*2+3;
|
||||
|
||||
assert(i*2+3 < m_nTailSteps*2);
|
||||
}
|
||||
assert(nIdxId == nTailIndsNum);
|
||||
}
|
||||
|
||||
// nTailIndsNum=0;
|
||||
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vRight, vUp,
|
||||
ucResCol,
|
||||
m_pParams->eBlendType,
|
||||
vAmbientColor,
|
||||
vParticlePos, arrTailVerts, nTailVertsNum, arrTailIndices, nTailIndsNum, (float)nSortId, dwCCObjFlags, m_pMaterial);
|
||||
|
||||
if (m_pArrvPosHistory)
|
||||
{
|
||||
float fTailLength = (m_pParams->fTailLenght/m_nTailSteps) / m_fScale; // Here we must divide by scale because speed is scaled.
|
||||
m_fTrailCurPos += min(1.f, PPP.fFrameTime/fTailLength);
|
||||
m_pArrvPosHistory[FtoI(m_fTrailCurPos)%m_nTailSteps] = m_vPos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list2<struct ShadowMapLightSourceInstance> * pShadowsList = NULL;
|
||||
if(PPP.pObjManager->GetCVars()->e_particles_receive_shadows &&
|
||||
m_pSpawnerEntity && m_pSpawnerEntity->GetEntityRS() && m_pSpawnerEntity->GetEntityRS()->pShadowMapInfo)
|
||||
pShadowsList = m_pSpawnerEntity->GetEntityRS()->pShadowMapInfo->pShadowMapCasters;
|
||||
|
||||
// no tail
|
||||
PPP.pObjManager->AddPolygonToRenderer( nTexBindId, pShader, nDynLightMask, vRight, vUp,
|
||||
ucResCol,
|
||||
m_pParams->eBlendType,
|
||||
vAmbientColor,
|
||||
vParticlePos, 0,0,0,0, (float)nSortId, dwCCObjFlags, m_pMaterial, NULL, pShadowsList );
|
||||
}
|
||||
}
|
||||
}
|
||||
int CSprite::FillTailVertBuffer( SColorVert * pTailVerts,
|
||||
const Vec3d & vCamVec,
|
||||
const UCol & ucColor )
|
||||
{
|
||||
int nVertCount=0;
|
||||
|
||||
if (m_pArrvPosHistory && m_pParams->fTailLenght && (m_vDelta!=Vec3(0.0f,0.0f,0.0f)) )
|
||||
{
|
||||
int nPos = FtoI(m_fTrailCurPos);
|
||||
|
||||
// if(nPos==1)
|
||||
// return 0;
|
||||
|
||||
// Vec3d vCamVec = PPP.pCamera->GetPos()-m_vPos;
|
||||
// vCamVec.Normalize();
|
||||
|
||||
Vec3d vSideStep,vSideStepPrev,vDelta,vSideStepReal;
|
||||
//Vec3d vSideStepPrev,vSideStepReal;
|
||||
|
||||
//float fMaxItSteps = min( (float)(PART_HISTORY_ELEMENTS-1), m_fTrailCurPos-1);
|
||||
float fInvMaxItHalfSteps = 0.5f/m_nTailSteps;
|
||||
|
||||
float fTC0=0.5f;
|
||||
|
||||
Vec3 vPrev = m_vPos;
|
||||
// fill vert buffer
|
||||
for(int it=0; it < m_nTailSteps && nPos >= 0; it++)
|
||||
{
|
||||
Vec3 vPos = m_pArrvPosHistory[ nPos % m_nTailSteps ];
|
||||
|
||||
vDelta = vPrev-vPos;
|
||||
if (vDelta.IsZero())
|
||||
vDelta = m_vDelta;
|
||||
vSideStep = m_fSize*vCamVec.Cross(GetNormalized(vDelta));
|
||||
|
||||
//if (it > 0)
|
||||
//vSideStepReal = (vSideStep + vSideStepPrev)*0.5f; // Average.
|
||||
//else
|
||||
//vSideStepReal = vSideStep;
|
||||
|
||||
//vSideStepPrev = vSideStep;
|
||||
vPrev = vPos;
|
||||
|
||||
pTailVerts[nVertCount].vert = vPos + vSideStep;
|
||||
pTailVerts[nVertCount].dTC[0] = fTC0;
|
||||
pTailVerts[nVertCount].dTC[1] = 0;
|
||||
pTailVerts[nVertCount].color = ucColor;
|
||||
nVertCount++;
|
||||
|
||||
pTailVerts[nVertCount].vert = vPos - vSideStep;
|
||||
pTailVerts[nVertCount].dTC[0] = fTC0;
|
||||
pTailVerts[nVertCount].dTC[1] = 1;
|
||||
pTailVerts[nVertCount].color = ucColor;
|
||||
nVertCount++;
|
||||
|
||||
nPos--;
|
||||
fTC0+=fInvMaxItHalfSteps;
|
||||
}
|
||||
}
|
||||
|
||||
return nVertCount;
|
||||
}
|
||||
286
Cry3DEngine/rain.cpp
Normal file
286
Cry3DEngine/rain.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: rain.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: draw rain volume
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "rain.h"
|
||||
#include "partman.h"
|
||||
#include "objman.h"
|
||||
|
||||
#define rn() ((((float)rand())/RAND_MAX)-0.5f)
|
||||
|
||||
CRainItem::CRainItem()
|
||||
{
|
||||
ZeroStruct(*this);
|
||||
m_vPos.x = rn()*RAIN_RANGEx2;
|
||||
m_vPos.y = rn()*RAIN_RANGEx2;
|
||||
m_vPos.z = rn()*RAIN_RANGEx2;
|
||||
m_fSize=2.0f;
|
||||
}
|
||||
|
||||
bool CRainItem::IsPointInvalid(const Vec3d & pos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CRainItem::Process(Vec3d &right, Vec3d &up, Vec3d &front, const int & nTexID, const Vec3d & delta,
|
||||
IRenderer * pIRenderer, ITimer * pITimer, const Vec3d & vFocusPos,
|
||||
CPartManager * pPartManager, CTerrain * pTerrain,
|
||||
class CObjManager * pObjManager, const Vec3d & _vCamPos)
|
||||
{
|
||||
{ // space loop
|
||||
float fOldZ = m_vPos.z;
|
||||
|
||||
if((m_vPos.x-vFocusPos.x)>RAIN_RANGE)
|
||||
{
|
||||
while((m_vPos.x-vFocusPos.x)>RAIN_RANGE)
|
||||
m_vPos.x-=RAIN_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.x+=RAIN_RANGEx2;
|
||||
}
|
||||
|
||||
if((vFocusPos.x-m_vPos.x)>RAIN_RANGE)
|
||||
{
|
||||
while((vFocusPos.x-m_vPos.x)>RAIN_RANGE)
|
||||
m_vPos.x+=RAIN_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.x-=RAIN_RANGEx2;
|
||||
}
|
||||
|
||||
if((m_vPos.y-vFocusPos.y)>RAIN_RANGE)
|
||||
{
|
||||
while((m_vPos.y-vFocusPos.y)>RAIN_RANGE)
|
||||
m_vPos.y-=RAIN_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.y+=RAIN_RANGEx2;
|
||||
}
|
||||
|
||||
if((vFocusPos.y-m_vPos.y)>RAIN_RANGE)
|
||||
{
|
||||
while((vFocusPos.y-m_vPos.y)>RAIN_RANGE)
|
||||
m_vPos.y+=RAIN_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.y-=RAIN_RANGEx2;
|
||||
}
|
||||
|
||||
if((m_vPos.z-vFocusPos.z)>RAIN_RANGE)
|
||||
{
|
||||
while((m_vPos.z-vFocusPos.z)>RAIN_RANGE)
|
||||
m_vPos.z-=RAIN_RANGEx2;
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.z+=(RAIN_RANGEx2-rnd());
|
||||
}
|
||||
|
||||
if((vFocusPos.z-m_vPos.z)>RAIN_RANGE)
|
||||
{
|
||||
while((vFocusPos.z-m_vPos.z)>RAIN_RANGE)
|
||||
m_vPos.z+=(RAIN_RANGEx2-rnd());
|
||||
|
||||
if(IsPointInvalid(m_vPos))
|
||||
m_vPos.z-=RAIN_RANGEx2;
|
||||
}
|
||||
|
||||
if(m_vPos.z != fOldZ)
|
||||
{
|
||||
m_vPos.x += rn()*RAIN_RANGE;
|
||||
m_vPos.y += rn()*RAIN_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
// draw
|
||||
pIRenderer->PushMatrix();
|
||||
pIRenderer->TranslateMatrix(m_vPos);
|
||||
pIRenderer->DrawQuad(right*m_fSize, up*m_fSize, Vec3d(0,0,0));
|
||||
pIRenderer->PopMatrix();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Move
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// process movement and size
|
||||
m_vPos += delta*pITimer->GetFrameTime();
|
||||
|
||||
if(0 && fabs((m_vPos.z + m_fSize) - pTerrain->GetZSafe(m_vPos.x,m_vPos.y))<0.1f && delta.z<0)
|
||||
{
|
||||
Vec3d vCollPos = m_vPos;
|
||||
vCollPos.z = pTerrain->GetZApr(m_vPos.x,m_vPos.y)+0.05f;
|
||||
|
||||
float fDist = (float)max(
|
||||
fabs(vCollPos.x - _vCamPos.x),max(fabs(vCollPos.y - _vCamPos.y), fabs(vCollPos.z - _vCamPos.z)));
|
||||
|
||||
fDist/=RAIN_RANGE;
|
||||
float fDistAlpha = 1.f-fDist;
|
||||
fDistAlpha*=2;
|
||||
if(fDistAlpha<0)
|
||||
fDistAlpha=0;
|
||||
if(fDistAlpha>1.f)
|
||||
fDistAlpha=1.f;
|
||||
|
||||
ParticleParams params;
|
||||
/* params.fFocus = 1.f;
|
||||
params.fLifeTime = 0.25f;
|
||||
params.fSize = 0.5f;
|
||||
params.fSizeSpeed = 0;
|
||||
params.fSpeed = 0;
|
||||
params.nCount = 1;
|
||||
params.eBlendType = ParticleBlendType_ColorBased;
|
||||
params.nTexId = pIRenderer->LoadAnimatedTexture("ANIMATED\\raindrop\\rda%02d.tga",7);
|
||||
params.nTexAnimFramesCount = 7;
|
||||
float fAlpha = fDistAlpha*pObjManager->GetCVars()->e_rain_amount;
|
||||
params.vColorStart.Set(fAlpha,fAlpha,fAlpha);
|
||||
params.vColorEnd.Set(fAlpha,fAlpha,fAlpha);
|
||||
params.vDirection.Set(0,0,1);
|
||||
params.vPosition = vCollPos;
|
||||
*/
|
||||
params.fFocus = 1.5f;
|
||||
params.fLifeTime = 0.5f;
|
||||
params.fSize = 0.02f;
|
||||
params.fSizeSpeed = 0;
|
||||
params.fSpeed = 1.f;
|
||||
params.vGravity(0,0,-5.f);
|
||||
params.nCount = 15;
|
||||
params.eBlendType = ParticleBlendType_ColorBased;
|
||||
params.nTexId = pIRenderer->LoadTexture("cloud");
|
||||
float fAlpha = fDistAlpha*pObjManager->GetCVars()->e_rain_amount;
|
||||
params.vColorStart(fAlpha,fAlpha,fAlpha);
|
||||
params.vColorEnd(fAlpha,fAlpha,fAlpha);
|
||||
params.vDirection(0,0,1);
|
||||
params.vPosition = vCollPos;
|
||||
params.fTailLenght = 0.25;
|
||||
|
||||
if(fDistAlpha>0)
|
||||
pPartManager->Spawn(params,RAIN_RANGE,pObjManager);
|
||||
|
||||
m_vPos.x += rn()*RAIN_RANGE;
|
||||
m_vPos.y += rn()*RAIN_RANGE;
|
||||
m_vPos.z -= 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
void CRainManager::Render(CTerrain * pTerrain,
|
||||
const Vec3d & vColor,
|
||||
CObjManager * pObjManager,
|
||||
CPartManager * pPartManager,
|
||||
const Vec3d & vWindDir)
|
||||
{
|
||||
if(!GetCVars()->e_rain_amount)
|
||||
return;
|
||||
|
||||
// get orientation
|
||||
Matrix44 mat;
|
||||
GetRenderer()->GetModelViewMatrix(mat.GetData());
|
||||
Vec3d right,up,front;
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//right(mat.cell(0), mat.cell(4), mat.cell(8));
|
||||
//up (mat.cell(1), mat.cell(5), mat.cell(9));
|
||||
//front(mat.cell(2), mat.cell(6), mat.cell(10));
|
||||
right = mat.GetColumn(0);
|
||||
up = mat.GetColumn(1);
|
||||
front = mat.GetColumn(2);
|
||||
|
||||
|
||||
|
||||
Vec3d vCamPos = GetViewCamera().GetPos();
|
||||
|
||||
//CELL_CHANGED_BY_IVO
|
||||
//front(-mat.cell(2), -mat.cell(6), -mat.cell(10));
|
||||
front = -mat.GetColumn(2);
|
||||
|
||||
front.Normalize();
|
||||
Vec3d vFocusPos = vCamPos + front*RAIN_RANGE;
|
||||
|
||||
if(!m_nRainTexID)
|
||||
m_nRainTexID = GetRenderer()->LoadTexture("textures\\sprites\\rain.tga");
|
||||
|
||||
GetRenderer()->SetTexture(m_nRainTexID);
|
||||
GetRenderer()->SetState(GS_BLSRC_ONE | GS_BLDST_ONE);
|
||||
GetRenderer()->SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture|(eCA_Constant<<3), eCA_Texture|(eCA_Constant<<3));
|
||||
GetRenderer()->SetCullMode(R_CULL_DISABLE);
|
||||
GetRenderer()->SetMaterialColor( 1, 1, 1, GetCVars()->e_rain_amount );
|
||||
|
||||
Vec3d vUp = GetNormalized(-vWindDir);
|
||||
|
||||
// draw
|
||||
for(int i=0; i<RAIN_COUNT; i++)
|
||||
m_arrItems[i].Process(right,vUp,front,m_nRainTexID,vWindDir,
|
||||
GetRenderer(),GetTimer(),vFocusPos,pPartManager,pTerrain,pObjManager,vCamPos);
|
||||
|
||||
m_fDropTime += GetTimer()->GetFrameTime();
|
||||
|
||||
const float fDropPeriod = max(0.002f, (1.f-GetCVars()->e_rain_amount)/50.f);
|
||||
|
||||
while(m_fDropTime>fDropPeriod)
|
||||
{
|
||||
m_fDropTime -= fDropPeriod;
|
||||
|
||||
Vec3d vCollPos( vFocusPos.x + rn()*RAIN_RANGE*2, vFocusPos.y + rn()*RAIN_RANGE*2, 0);
|
||||
vCollPos.z = pTerrain->GetZApr(vCollPos.x,vCollPos.y)+0.05f;
|
||||
|
||||
float fDist = (float)max(
|
||||
fabs(vCollPos.x - vCamPos.x),max(fabs(vCollPos.y - vCamPos.y), fabs(vCollPos.z - vCamPos.z)));
|
||||
|
||||
fDist/=RAIN_RANGE;
|
||||
float fDistAlpha = 1.f-fDist;
|
||||
fDistAlpha*=3;
|
||||
if(fDistAlpha<0)
|
||||
continue;
|
||||
if(fDistAlpha>1.f)
|
||||
fDistAlpha=1.f;
|
||||
|
||||
ParticleParams params;
|
||||
/* params.fFocus = 1.f;
|
||||
params.fLifeTime = 0.25f;
|
||||
params.fSize = 0.5f;
|
||||
params.fSizeSpeed = 0;
|
||||
params.fSpeed = 0;
|
||||
params.nCount = 1;
|
||||
params.eBlendType = ParticleBlendType_ColorBased;
|
||||
params.nTexId = pIRenderer->LoadAnimatedTexture("ANIMATED\\raindrop\\rda%02d.tga",7);
|
||||
params.nTexAnimFramesCount = 7;
|
||||
float fAlpha = fDistAlpha*pObjManager->GetCVars()->e_rain_amount;
|
||||
params.vColorStart.Set(fAlpha,fAlpha,fAlpha);
|
||||
params.vColorEnd.Set(fAlpha,fAlpha,fAlpha);
|
||||
params.vDirection.Set(0,0,1);
|
||||
params.vPosition = vCollPos;
|
||||
*/
|
||||
params.fFocus = 1.5f;
|
||||
params.fLifeTime = 0.5f;
|
||||
params.fSize = 0.02f;
|
||||
params.fSizeSpeed = 0;
|
||||
params.fSpeed = 1.f;
|
||||
params.vGravity(0,0,-5.f);
|
||||
params.nCount = 15;
|
||||
params.eBlendType = ParticleBlendType_ColorBased;
|
||||
params.nTexId = GetRenderer()->LoadTexture("cloud");
|
||||
float fAlpha = fDistAlpha*GetCVars()->e_rain_amount;
|
||||
// params.vColorStart.Set(fAlpha,fAlpha,fAlpha);
|
||||
// params.vColorEnd.Set(fAlpha,fAlpha,fAlpha);
|
||||
params.vColorStart = Get3DEngine()->GetFogColor()*fAlpha;
|
||||
params.vColorEnd = Get3DEngine()->GetFogColor()*fAlpha;
|
||||
|
||||
params.vDirection(0,0,1);
|
||||
params.vPosition = vCollPos;
|
||||
// params.fTailLenght = 1.f;
|
||||
|
||||
if(fAlpha>0.125)
|
||||
pPartManager->Spawn(params,RAIN_RANGE,pObjManager);
|
||||
}
|
||||
}
|
||||
58
Cry3DEngine/rain.h
Normal file
58
Cry3DEngine/rain.h
Normal file
@@ -0,0 +1,58 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: rain.h
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef RAIN_MANAGER
|
||||
#define RAIN_MANAGER
|
||||
|
||||
#define RAIN_COUNT 512
|
||||
const float RAIN_RANGE = 8;
|
||||
const float RAIN_RANGEx2 = RAIN_RANGE*2;
|
||||
|
||||
class CPartManager;
|
||||
|
||||
class CRainItem
|
||||
{
|
||||
public:
|
||||
|
||||
// cur state
|
||||
Vec3d m_vPos;
|
||||
float m_fSize;
|
||||
|
||||
CRainItem();
|
||||
void Process(Vec3d &right, Vec3d &up, Vec3d &front, const int & nTexID, const Vec3d & delta,
|
||||
IRenderer * pIRenderer, ITimer * pITimer, const Vec3d & vFocusPos,
|
||||
CPartManager * pPartManager, CTerrain * pTerrain, class CObjManager * pObjManager, const Vec3d & vCamPos );
|
||||
|
||||
bool IsPointInvalid(const Vec3d & pos);
|
||||
};
|
||||
|
||||
class CRainManager : public Cry3DEngineBase
|
||||
{
|
||||
CRainItem m_arrItems[RAIN_COUNT];
|
||||
int m_nCurItem;
|
||||
int m_nRainTexID;
|
||||
float m_fDropTime;
|
||||
public:
|
||||
|
||||
CRainManager()
|
||||
{
|
||||
m_nCurItem = 0;
|
||||
m_nRainTexID = 0;
|
||||
m_fDropTime = 0;
|
||||
}
|
||||
void Render(class CTerrain * pTerrain, const Vec3d & vColor, class CObjManager * pObjManager, class CPartManager * pPartManager, const Vec3d & vWindDir);
|
||||
};
|
||||
|
||||
#endif // RAIN_MANAGER
|
||||
780
Cry3DEngine/terrain.cpp
Normal file
780
Cry3DEngine/terrain.cpp
Normal file
@@ -0,0 +1,780 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: terrain.cpp
|
||||
// Version: v1.00
|
||||
// Created: 28/5/2001 by Vladimir Kajalin
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description: check vis
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "terrain_sector.h"
|
||||
#include "StatObj.h"
|
||||
#include "objman.h"
|
||||
#include "cbuffer.h"
|
||||
#include "terrain_water.h"
|
||||
#include "detail_grass.h"
|
||||
#include "VisAreas.h"
|
||||
|
||||
void CTerrain::PreCacheArea(const Vec3d & vPos, float fRadius)
|
||||
{
|
||||
// if(!m_pObjManager)
|
||||
return;
|
||||
|
||||
#ifndef _DEBUG
|
||||
#if !defined(_XBOX) && !defined(LINUX)
|
||||
assert(GetConsole()->Exit("Assert should do nothing in release mode")); // just check
|
||||
#endif // _XBOX
|
||||
#endif // DEBUG
|
||||
|
||||
m_nUploadsInFrame = -10000;
|
||||
|
||||
GetLog()->UpdateLoadingScreen("Preloading terrain textures for (%.1f, %.1f, %.1f) ...",
|
||||
vPos.x,vPos.y,vPos.z);
|
||||
|
||||
int nLoaded=0;
|
||||
for( int x=0; x<CTerrain::GetSectorsTableSize(); x++)
|
||||
for( int y=0; y<CTerrain::GetSectorsTableSize(); y++)
|
||||
{
|
||||
m_arrSecInfoTable[x][y]->m_fDistance =
|
||||
GetDist2D(
|
||||
float(m_arrSecInfoTable[x][y]->m_nOriginX+(CTerrain::GetSectorSize()>>1)),
|
||||
float(m_arrSecInfoTable[x][y]->m_nOriginY+(CTerrain::GetSectorSize()>>1)),
|
||||
vPos.x, vPos.y ) - (CTerrain::GetSectorSize()>>1);
|
||||
|
||||
if(m_arrSecInfoTable[x][y]->m_fDistance < fRadius)
|
||||
{
|
||||
m_arrSecInfoTable[x][y]->SetLOD();
|
||||
if(IsSectorNonMergable(m_arrSecInfoTable[x][y]))
|
||||
{
|
||||
m_arrSecInfoTable[x][y]->SetTextures();
|
||||
nLoaded++;
|
||||
}
|
||||
m_arrSecInfoTable[x][y]->m_cLastTimeUsed = fastftol_positive(GetCurTimeSec()) + 20;
|
||||
}
|
||||
}
|
||||
|
||||
GetLog()->LogPlus(" %d sectors loaded", nLoaded);
|
||||
|
||||
m_nUploadsInFrame = 0;
|
||||
}
|
||||
|
||||
int CTerrain::GetSecMML(int x, int y)
|
||||
{
|
||||
assert(x/CTerrain::GetSectorSize()>=0);
|
||||
assert(y/CTerrain::GetSectorSize()>=0);
|
||||
assert(x/CTerrain::GetSectorSize()<CTerrain::GetSectorsTableSize());
|
||||
assert(y/CTerrain::GetSectorSize()<CTerrain::GetSectorsTableSize());
|
||||
|
||||
CSectorInfo * info = m_arrSecInfoTable[x/CTerrain::GetSectorSize()][y/CTerrain::GetSectorSize()];
|
||||
return info->m_cGeometryMML;
|
||||
}
|
||||
|
||||
void CTerrain::AddVisSetcor(CSectorInfo * newsec)
|
||||
{
|
||||
m_lstVisSectors.Add(newsec);
|
||||
}
|
||||
|
||||
void CTerrain::LinkVisSetcors()
|
||||
{
|
||||
for(int i=0; i<m_lstVisSectors.Count(); i++)
|
||||
{
|
||||
CSectorInfo * info = (CSectorInfo*)m_lstVisSectors[i];
|
||||
|
||||
int sx1 = info->m_nOriginX/CTerrain::GetSectorSize();
|
||||
int sy1 = info->m_nOriginY/CTerrain::GetSectorSize();
|
||||
|
||||
if(sx1+1<CTerrain::GetSectorsTableSize())
|
||||
m_arrSecInfoTable[sx1+1][sy1]->CheckGeomCompWithLOD(info->m_cGeometryMML);
|
||||
|
||||
if(sy1+1<CTerrain::GetSectorsTableSize())
|
||||
m_arrSecInfoTable[sx1][sy1+1]->CheckGeomCompWithLOD(info->m_cGeometryMML);
|
||||
|
||||
if(sx1>0)
|
||||
m_arrSecInfoTable[sx1-1][sy1]->CheckGeomCompWithLOD(info->m_cGeometryMML);
|
||||
|
||||
if(sy1>0)
|
||||
m_arrSecInfoTable[sx1][sy1-1]->CheckGeomCompWithLOD(info->m_cGeometryMML);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::RenderTerrain( CObjManager * pObjManager, const int & DrawFlags )
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
m_pObjManager = pObjManager;
|
||||
|
||||
// precache tarrain data if camera was teleported more than 32 meters
|
||||
if(m_nRenderStackLevel==0)
|
||||
{
|
||||
if(GetDistance(m_vPrevCameraPos, GetViewCamera().GetPos()) > 32)
|
||||
PreCacheArea(GetViewCamera().GetPos(), GetViewCamera().GetZMax()*1.5f);
|
||||
m_vPrevCameraPos = GetViewCamera().GetPos();
|
||||
}
|
||||
|
||||
if(m_nRenderStackLevel==0)
|
||||
m_fDistanceToSectorWithWater=-1;
|
||||
m_ucTerrainFrame++;
|
||||
|
||||
m_lstVisSectors.Clear();
|
||||
|
||||
if(!m_nRenderStackLevel)
|
||||
m_lstReflectedTerrainIdxArray.Clear();
|
||||
|
||||
m_pObjManager->m_lstFarObjects[m_nRenderStackLevel].Clear();
|
||||
|
||||
m_vCameraPos = m_pViewCamera->GetPos();
|
||||
RefineSector(0, CTerrain::GetTerrainSize(), 0, CTerrain::GetTerrainSize(), 0);
|
||||
|
||||
LinkVisSetcors();
|
||||
|
||||
if(m_nRenderStackLevel==0)
|
||||
{
|
||||
m_bOceanIsVisibe = m_fDistanceToSectorWithWater > -1 || !m_lstVisSectors.Count();
|
||||
|
||||
m_fDistanceToSectorWithWater-=CTerrain::GetSectorSize()*0.5f;
|
||||
if(m_fDistanceToSectorWithWater<1.0f)
|
||||
m_fDistanceToSectorWithWater=1.0f;
|
||||
|
||||
if(!m_lstVisSectors.Count())
|
||||
m_fDistanceToSectorWithWater=0;
|
||||
|
||||
m_fDistanceToSectorWithWater = max(m_fDistanceToSectorWithWater, (m_pViewCamera->GetPos().z-m_fGlobalWaterLevel)*0.05f);
|
||||
}
|
||||
|
||||
if(m_pDetailObjects)
|
||||
if(DrawFlags & DLD_DETAIL_OBJECTS)
|
||||
m_pDetailObjects->RenderDetailGrass(this);
|
||||
}
|
||||
|
||||
void CSectorInfo :: CheckGeomCompWithLOD(int minMML)
|
||||
{
|
||||
if(m_cLastFrameUsed == m_pTerrain->m_ucTerrainFrame)
|
||||
if(m_cGeometryMML < 100)
|
||||
if(m_cGeometryMML>minMML+1)
|
||||
{
|
||||
m_cGeometryMML = minMML+1;
|
||||
int sx1 = m_nOriginX/CTerrain::GetSectorSize();
|
||||
int sy1 = m_nOriginY/CTerrain::GetSectorSize();
|
||||
|
||||
if(sx1+1<CTerrain::GetSectorsTableSize())
|
||||
m_pTerrain->m_arrSecInfoTable[sx1+1][sy1]->CheckGeomCompWithLOD(m_cGeometryMML);
|
||||
|
||||
if(sy1+1<CTerrain::GetSectorsTableSize())
|
||||
m_pTerrain->m_arrSecInfoTable[sx1][sy1+1]->CheckGeomCompWithLOD(m_cGeometryMML);
|
||||
|
||||
if(sx1>0)
|
||||
m_pTerrain->m_arrSecInfoTable[sx1-1][sy1]->CheckGeomCompWithLOD(m_cGeometryMML);
|
||||
|
||||
if(sy1>0)
|
||||
m_pTerrain->m_arrSecInfoTable[sx1][sy1-1]->CheckGeomCompWithLOD(m_cGeometryMML);
|
||||
}
|
||||
}
|
||||
|
||||
// todo: use real quadtree here
|
||||
void CTerrain::RefineSector(int x1, int x2, int y1, int y2, bool bAllIN)
|
||||
{
|
||||
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
|
||||
|
||||
int xm = (x1+x2)>>1;
|
||||
int ym = (y1+y2)>>1;
|
||||
|
||||
if((x2-x1) > CTerrain::GetSectorSize())
|
||||
{
|
||||
Vec3d bmin((float)x1-TERRAIN_SECTORS_MAX_OVERLAPPING, (float)y1-TERRAIN_SECTORS_MAX_OVERLAPPING,-256.f);
|
||||
Vec3d bmax((float)x2+TERRAIN_SECTORS_MAX_OVERLAPPING, (float)y2+TERRAIN_SECTORS_MAX_OVERLAPPING, 512.f);
|
||||
if( bAllIN || m_pViewCamera->IsAABBVisible_hierarchical(AABB(bmin,bmax),&bAllIN) )
|
||||
{
|
||||
if(m_vCameraPos.x < xm)
|
||||
{
|
||||
if(m_vCameraPos.y < ym)
|
||||
{
|
||||
RefineSector(x1, xm, y1, ym, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, y1, ym, bAllIN );
|
||||
RefineSector(x1, xm, ym, y2, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, ym, y2, bAllIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
RefineSector(x1, xm, ym, y2, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, ym, y2, bAllIN );
|
||||
RefineSector(x1, xm, y1, ym, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, y1, ym, bAllIN );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_vCameraPos.y < ym)
|
||||
{
|
||||
RefineSector(xm, x2, y1, ym, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, ym, y2, bAllIN );
|
||||
RefineSector(x1, xm, y1, ym, bAllIN );
|
||||
|
||||
RefineSector(x1, xm, ym, y2, bAllIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
RefineSector(xm, x2, ym, y2, bAllIN );
|
||||
|
||||
RefineSector(xm, x2, y1, ym, bAllIN );
|
||||
RefineSector(x1, xm, ym, y2, bAllIN );
|
||||
|
||||
RefineSector(x1, xm, y1, ym, bAllIN );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CSectorInfo * info = m_arrSecInfoTable[x1/CTerrain::GetSectorSize()][y1/CTerrain::GetSectorSize()];
|
||||
|
||||
// test higher bbox to include all flying dynamic stuff and reflected in water terrain
|
||||
if(!m_pViewCamera->IsAABBVisible_hierarchical(
|
||||
AABB(
|
||||
Vec3d((float)x1-TERRAIN_SECTORS_MAX_OVERLAPPING,(float)y1-TERRAIN_SECTORS_MAX_OVERLAPPING,0),
|
||||
Vec3d((float)x2+TERRAIN_SECTORS_MAX_OVERLAPPING,(float)y2+TERRAIN_SECTORS_MAX_OVERLAPPING,512.f)),
|
||||
&info->m_bAllStaticsInFrustum))
|
||||
return;
|
||||
|
||||
// debug: render this sector only
|
||||
if(GetCVars()->e_terrain_draw_this_sector_only)
|
||||
if(GetSecInfo(GetViewCamera().GetPos()) != info)
|
||||
return;
|
||||
|
||||
// if(info->m_nOriginX != 1344 || info->m_nOriginY!=1344)
|
||||
// return;
|
||||
|
||||
if(!m_nRenderStackLevel) // for reflections
|
||||
info->MergeSectorIntoLowResTerrain(false);
|
||||
|
||||
// draw dynamic objects
|
||||
info->RenderEntities(m_pObjManager, !info->m_bAllStaticsInFrustum, "", DYNAMIC_ENTITIES);
|
||||
|
||||
// test exact bbox of sector, it includes all static geometry
|
||||
if(!m_pViewCamera->IsAABBVisible_hierarchical( AABB(info->m_vBoxMin,info->m_vBoxMax), &info->m_bAllStaticsInFrustum))
|
||||
return;
|
||||
|
||||
// test ground visibility
|
||||
if(info->m_bAllStaticsInFrustum)
|
||||
info->m_bGroundVisible = true;
|
||||
else
|
||||
{
|
||||
float fOrgX = float(info->m_nOriginX);
|
||||
float fOrgY = float(info->m_nOriginY);
|
||||
info->m_bGroundVisible = m_pViewCamera->IsAABBVisibleFast( AABB(Vec3d(fOrgX,fOrgY,info->m_fMinZ), Vec3d(fOrgX+CTerrain::GetSectorSize(),fOrgY+CTerrain::GetSectorSize(),max(info->m_fMaxZ,m_fGlobalWaterLevel))));
|
||||
}
|
||||
|
||||
// calc distance
|
||||
info->m_fDistance = GetDist2D( (float)xm, (float)ym, m_vCameraPos.x, m_vCameraPos.y ) - (CTerrain::GetSectorSize()>>1)*1.3333f;
|
||||
if(info->m_fDistance > m_pViewCamera->GetZMax())
|
||||
return;
|
||||
if(info->m_fDistance<1)
|
||||
info->m_fDistance=1;
|
||||
/*
|
||||
if( info->m_fDistance>128 && info->m_vBoxMax.z <= m_fGlobalWaterLevel &&
|
||||
m_vCameraPos.z > m_fGlobalWaterLevel+1 && m_bCullUnderwaterTerrain && m_fGlobalWaterLevel)
|
||||
return; */
|
||||
|
||||
// occlusion test (affects only static objects)
|
||||
if(GetCVars()->e_terrain_occlusion_culling)
|
||||
if(m_pObjManager->IsBoxOccluded(info->m_vBoxMin,info->m_vBoxMax,info->m_fDistance, &info->m_OcclusionTestClient))
|
||||
return;
|
||||
|
||||
// test occl by antiportals
|
||||
if(GetVisAreaManager() && GetVisAreaManager()->IsOccludedByOcclVolumes(info->m_vBoxMin,info->m_vBoxMax))
|
||||
return;
|
||||
|
||||
if(m_nRenderStackLevel==0)
|
||||
info->m_cLastFrameUsed = m_ucTerrainFrame;
|
||||
|
||||
if( info->m_bGroundVisible || info->m_fDistance<4 )
|
||||
info->SetLOD();
|
||||
|
||||
// else
|
||||
// info->m_cGeometryMML = MAX_MML_LEVEL;
|
||||
|
||||
// update distance to the ocean
|
||||
if(m_nRenderStackLevel==0)
|
||||
{
|
||||
if(info->m_bGroundVisible)
|
||||
if(info->m_fMinZ<m_fGlobalWaterLevel)
|
||||
if(m_fDistanceToSectorWithWater == -1)
|
||||
m_fDistanceToSectorWithWater = info->m_fDistance;
|
||||
}
|
||||
|
||||
AddVisSetcor(info);
|
||||
|
||||
// render static objects
|
||||
if(info)
|
||||
info->RenderEntities(m_pObjManager, !info->m_bAllStaticsInFrustum, "", STATIC_ENTITIES);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::UnloadOldSectors(float fMaxViewDist)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
static int nStaticLoadedTexturesNum[2]={0,0};
|
||||
|
||||
int cCurTimeSec = fastftol_positive(GetCurTimeSec());
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// x/y cycle
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
for(int t=0; t<16; t++)
|
||||
{
|
||||
m_nOldSectorsY++;
|
||||
if(m_nOldSectorsY>=CTerrain::GetSectorsTableSize())
|
||||
{
|
||||
m_nOldSectorsY=0;
|
||||
m_nOldSectorsX++;
|
||||
if(m_nOldSectorsX>=CTerrain::GetSectorsTableSize())
|
||||
{
|
||||
m_nOldSectorsY=m_nOldSectorsX=0;
|
||||
m_arrLoadedTexturesNum[0] = nStaticLoadedTexturesNum[0];
|
||||
m_arrLoadedTexturesNum[1] = nStaticLoadedTexturesNum[1];
|
||||
nStaticLoadedTexturesNum[0] = nStaticLoadedTexturesNum[1]=0;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
{
|
||||
CSectorInfo * info = m_arrSecInfoTable[m_nOldSectorsX][m_nOldSectorsY];
|
||||
|
||||
if(info->m_bLockTexture)
|
||||
return; // do not unload locked texture
|
||||
|
||||
if(info->m_nTextureID && info->m_nTextureID != info->m_nLowLodTextureID)
|
||||
nStaticLoadedTexturesNum[0]++;
|
||||
|
||||
if(info->m_nLowLodTextureID)
|
||||
nStaticLoadedTexturesNum[1]++;
|
||||
|
||||
float fDistanse = GetDist2D(
|
||||
(float)info->m_nOriginX+(CTerrain::GetSectorSize()>>1),
|
||||
(float)info->m_nOriginY+(CTerrain::GetSectorSize()>>1),
|
||||
m_pViewCamera->GetPos().x, m_pViewCamera->GetPos().y ) - (CTerrain::GetSectorSize()>>1);
|
||||
|
||||
if((fDistanse > (1.5f*fMaxViewDist)) || (info->m_cLastTimeUsed < (cCurTimeSec - 4)))
|
||||
{ // try to release vert buffer if not in use int time
|
||||
info->ReleaseHeightMapVertBuffer();
|
||||
|
||||
// release static shadow vertex buffers
|
||||
// info->ReleaseStaticShadowVertexBuffers();
|
||||
|
||||
// if(GetCVars()->e_terrain_log)
|
||||
// GetLog()->Log("buffer unloaded %d", info->GetSecIndex());
|
||||
}
|
||||
|
||||
if(GetCVars()->e_terrain_debug==3 || !GetCVars()->e_terrain_texture_pool)
|
||||
{
|
||||
if( fDistanse > (1.5f*fMaxViewDist) || (info->m_cLastTimeUsed < (cCurTimeSec - 8)))
|
||||
{
|
||||
info->UnloadHeighFieldTexture(fDistanse, fMaxViewDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CTerrain::RenderEntitiesOutOfTheMap(CObjManager * pObjManager)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
if(!GetCVars()->e_objects || GetCVars()->e_terrain_draw_this_sector_only == 2)
|
||||
return 0;
|
||||
|
||||
// this sector used also for entities outside of the map and for draw near objects
|
||||
m_arrSecInfoTable[0][0]->RenderEntities(pObjManager, true, "", STATIC_ENTITIES);
|
||||
m_arrSecInfoTable[0][0]->RenderEntities(pObjManager, true, "", DYNAMIC_ENTITIES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CTerrain::RenderTerrainWater(bool bRenderShore)
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
if(!GetCVars()->e_water_ocean)
|
||||
return 0;
|
||||
|
||||
m_pWater->Render(m_nRenderStackLevel);
|
||||
|
||||
float fCamZ = GetViewCamera().GetPos().z;
|
||||
if(fCamZ>m_fGlobalWaterLevel)
|
||||
if(bRenderShore && m_pSHShore && !m_nRenderStackLevel && GetCVars()->e_beach)
|
||||
{
|
||||
float fZoomFactor = 0.1f+0.9f*(RAD2DEG(GetViewCamera().GetFov())/90.f);
|
||||
for( int i=0; i<m_lstVisSectors.Count(); i++ )
|
||||
m_lstVisSectors[i]->RenderBeach(m_pSHShore, fZoomFactor, fCamZ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSectorInfo * CTerrain::GetSectorFromPoint(int _x, int _y)
|
||||
{
|
||||
int x = _x/CTerrain::GetSectorSize();
|
||||
int y = _y/CTerrain::GetSectorSize();
|
||||
|
||||
if( x>=0 && y>=0 && x<CTerrain::GetSectorsTableSize() && y<CTerrain::GetSectorsTableSize() )
|
||||
return (m_arrSecInfoTable)[x][y];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CTerrain::ResetDLightMaskInSectors()
|
||||
{
|
||||
CSectorInfo ** p = &m_arrSecInfoTable[0][0];
|
||||
CSectorInfo ** pEnd = &m_arrSecInfoTable[CTerrain::GetSectorsTableSize()-1][CTerrain::GetSectorsTableSize()-1];
|
||||
while(p <= pEnd)
|
||||
{
|
||||
register CSectorInfo *pSector = *p;
|
||||
pSector->m_nDynLightMaskNoSun = 0;
|
||||
pSector->m_nDynLightMask = 0;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::ApplyForceToEnvironment(Vec3d vPos, float fRadius, float fAmountOfForce)
|
||||
{
|
||||
if(fRadius<=0)
|
||||
return;
|
||||
|
||||
if(!_finite(vPos.x) || !_finite(vPos.y) || !_finite(vPos.z))
|
||||
{
|
||||
GetLog()->Log("Error: 3DEngine::ApplyForceToEnvironment: Undefined position passed to the function");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fRadius > 50.f)
|
||||
fRadius = 50.f;
|
||||
|
||||
if(fAmountOfForce>1.f)
|
||||
fAmountOfForce = 1.f;
|
||||
|
||||
if( (GetDistance(vPos,m_pViewCamera->GetPos()) > 50.f+fRadius*2.f ) || // too far
|
||||
vPos.z < (GetZApr(vPos.x, vPos.y)-1.f)) // under ground
|
||||
return;
|
||||
/*
|
||||
int min_x = (int)(((vPos.x-fRadius)/CTerrain::GetSectorSize()))-1;
|
||||
int min_y = (int)(((vPos.y-fRadius)/CTerrain::GetSectorSize()))-1;
|
||||
int max_x = (int)(((vPos.x+fRadius)/CTerrain::GetSectorSize()))+1;
|
||||
int max_y = (int)(((vPos.y+fRadius)/CTerrain::GetSectorSize()))+1;
|
||||
|
||||
if(min_x<0)
|
||||
min_x=0;
|
||||
if(min_y<0)
|
||||
min_y=0;
|
||||
if(max_x>=CTerrain::GetSectorsTableSize())
|
||||
max_x = CTerrain::GetSectorsTableSize()-1;
|
||||
if(max_y>=CTerrain::GetSectorsTableSize())
|
||||
max_y = CTerrain::GetSectorsTableSize()-1;
|
||||
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
{
|
||||
list2<IEntityRender*> * pList = &m_arrSecInfoTable[x][y]->m_lstEntities[STATIC_ENTITIES];
|
||||
for(int s=0; s<pList->Count(); s++)
|
||||
if(pList->GetAt(s)->GetEntityRenderType()==eERType_Vegetation)
|
||||
{
|
||||
CStatObjInst * pEnt = (CStatObjInst *)pList->GetAt(s);
|
||||
float fDist = GetDist2D(pEnt->GetPos(true).x,pEnt->GetPos(true).y, vPos.x,vPos.y);
|
||||
if(fDist<fRadius)
|
||||
{
|
||||
pEnt->m_fCurrentBending = (1.f - fDist/fRadius)*fAmountOfForce*0.25;
|
||||
pEnt->m_fCurrentBending=pEnt->m_fCurrentBending;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// calc area
|
||||
int x1=int(vPos.x-fRadius-CTerrain::GetHeightMapUnitSize());
|
||||
int y1=int(vPos.y-fRadius-CTerrain::GetHeightMapUnitSize());
|
||||
int x2=int(vPos.x+fRadius+CTerrain::GetHeightMapUnitSize());
|
||||
int y2=int(vPos.y+fRadius+CTerrain::GetHeightMapUnitSize());
|
||||
|
||||
int nUnitSize = GetHeightMapUnitSize();
|
||||
|
||||
x1=x1/nUnitSize*nUnitSize;
|
||||
x2=x2/nUnitSize*nUnitSize;
|
||||
y1=y1/nUnitSize*nUnitSize;
|
||||
y2=y2/nUnitSize*nUnitSize;
|
||||
|
||||
// limits
|
||||
if(x1<0) x1=0;
|
||||
if(y1<0) y1=0;
|
||||
if(x2>=CTerrain::GetTerrainSize()) x2=CTerrain::GetTerrainSize()-1;
|
||||
if(y2>=CTerrain::GetTerrainSize()) y2=CTerrain::GetTerrainSize()-1;
|
||||
|
||||
// get near sectors
|
||||
list2<CSectorInfo*> lstNearSecInfos;
|
||||
for(int x=x1; x<=x2; x++)
|
||||
for(int y=y1; y<=y2; y++)
|
||||
{
|
||||
CSectorInfo * pInfo = GetSecInfo(x,y);
|
||||
if(pInfo && lstNearSecInfos.Find(pInfo)<0)
|
||||
lstNearSecInfos.Add(pInfo);
|
||||
}
|
||||
|
||||
{
|
||||
CSectorInfo * pInfo = GetSecInfo(0,0);
|
||||
if(pInfo && lstNearSecInfos.Find(pInfo)<0)
|
||||
lstNearSecInfos.Add(pInfo);
|
||||
}
|
||||
|
||||
// affect objects around
|
||||
for( int s=0; s<lstNearSecInfos.Count(); s++)
|
||||
{
|
||||
CSectorInfo * pSecInfo = lstNearSecInfos[s];
|
||||
for(int i=0; i<pSecInfo->m_lstEntities[STATIC_ENTITIES].Count(); i++)
|
||||
if(pSecInfo->m_lstEntities[STATIC_ENTITIES][i]->GetEntityRenderType() == eERType_Vegetation)
|
||||
{
|
||||
CStatObjInst * pStatObjInst = (CStatObjInst*)pSecInfo->m_lstEntities[STATIC_ENTITIES][i];
|
||||
float fDist = GetDist2D(pStatObjInst->GetPos(true).x,pStatObjInst->GetPos(true).y, vPos.x,vPos.y);
|
||||
if(fDist<fRadius)
|
||||
{
|
||||
float fNewBending = (1.f - fDist/fRadius)*fAmountOfForce;
|
||||
if(fNewBending > pStatObjInst->m_fCurrentBending)
|
||||
pStatObjInst->m_fCurrentBending = fNewBending;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3d CTerrain::GetTerrainSurfaceNormal(Vec3d vPos)
|
||||
{
|
||||
Vec3d v1 = Vec3d(vPos.x-0.5f, vPos.y-0.5f, GetZApr(vPos.x-0.5f,vPos.y-0.5f));
|
||||
Vec3d v2 = Vec3d(vPos.x+0.5f, vPos.y, GetZApr(vPos.x+0.5f,vPos.y ));
|
||||
Vec3d v3 = Vec3d(vPos.x, vPos.y+0.5f, GetZApr(vPos.x, vPos.y+0.5f));
|
||||
return (v2-v1).Cross(v3-v1);
|
||||
}
|
||||
|
||||
bool CTerrain::UnRegisterInAllSectors(IEntityRender * pEntityRS)
|
||||
{
|
||||
assert(pEntityRS);
|
||||
|
||||
bool bRes = 0;
|
||||
|
||||
if(pEntityRS)
|
||||
{
|
||||
int nStatic = (pEntityRS->GetEntityRenderType() != eERType_Unknown);
|
||||
|
||||
for( int x=0; x<CTerrain::GetSectorsTableSize(); x++ )
|
||||
for( int y=0; y<CTerrain::GetSectorsTableSize(); y++ )
|
||||
if(m_arrSecInfoTable[x][y])
|
||||
bRes |= m_arrSecInfoTable[x][y]->m_lstEntities[nStatic].Delete(pEntityRS);
|
||||
|
||||
pEntityRS->m_pSector = 0;
|
||||
}
|
||||
|
||||
return bRes;
|
||||
}
|
||||
|
||||
ushort * CTerrain::GetUnderWaterSmoothHMap(int & nDimensions)
|
||||
{
|
||||
nDimensions = m_arrusUnderWaterSmoothHMap.m_nSize;
|
||||
return m_arrusUnderWaterSmoothHMap.m_pData;
|
||||
}
|
||||
|
||||
void CTerrain::GetMemoryUsage( class ICrySizer*pSizer)
|
||||
{
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "HMap");
|
||||
GetHighMapMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "SecInfoTable");
|
||||
m_arrSecInfoTable.GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "SectorsData");
|
||||
for( int x=0; x<CTerrain::GetSectorsTableSize(); x++)
|
||||
for( int y=0; y<CTerrain::GetSectorsTableSize(); y++)
|
||||
m_arrSecInfoTable[x][y]->GetMemoryUsage(pSizer);
|
||||
}
|
||||
|
||||
int nSize = 0;
|
||||
m_arrusUnderWaterSmoothHMap.GetMemoryUsage(pSizer);
|
||||
nSize += m_lstFogVolumes.GetMemoryUsage();
|
||||
nSize += m_lstLowResTerrainIdxArray.GetMemoryUsage();
|
||||
nSize += m_lstReflectedTerrainIdxArray.GetMemoryUsage();
|
||||
nSize += m_lstSectorVertArray.GetMemoryUsage();
|
||||
nSize += m_lstVisSectors.GetMemoryUsage();
|
||||
// nSize += m_pBugsManager->GetMemoryUsage();
|
||||
if(m_pCoverageBuffer)
|
||||
nSize += sizeof(*m_pCoverageBuffer);
|
||||
|
||||
if(m_pDetailObjects)
|
||||
nSize += sizeof(*m_pDetailObjects) + m_pDetailObjects->GetMemoryUsage();
|
||||
|
||||
if(m_pTexturePool)
|
||||
m_pTexturePool->GetMemoryUsage(pSizer);
|
||||
|
||||
if(m_pWater)
|
||||
nSize += sizeof(*m_pWater) + m_pWater->GetMemoryUsage();
|
||||
|
||||
nSize += m_nSectorTextureDataSizeBytes;
|
||||
|
||||
pSizer->AddObject(this, nSize + sizeof(*this));
|
||||
}
|
||||
|
||||
void CTexturePool::TexInfo::GetSize (ICrySizer*pSizer)const
|
||||
{
|
||||
pSizer->Add (*this);
|
||||
pSectorInfo->GetMemoryUsage (pSizer);
|
||||
}
|
||||
|
||||
void CTexturePool::GetMemoryUsage(class ICrySizer*pSizer)
|
||||
{
|
||||
for (int i = 0; i < sizeof(m_TexturePool)/sizeof(m_TexturePool[0]); ++i)
|
||||
{
|
||||
list2<TexInfo>& arrTexInfo = m_TexturePool[i];
|
||||
for (unsigned j = 0; j < arrTexInfo.size(); ++j)
|
||||
arrTexInfo[j].GetSize (pSizer);
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::UnregisterFogVolumeFromOutdoor(VolumeInfo * pFogVolume)
|
||||
{
|
||||
// reset fog volume pointer in all affected terrain sectors
|
||||
for(int x=0; x<CTerrain::GetSectorsTableSize(); x++)
|
||||
for(int y=0; y<CTerrain::GetSectorsTableSize(); y++)
|
||||
{
|
||||
CSectorInfo * pSecInfo = m_arrSecInfoTable[x][y];
|
||||
if(pSecInfo && pSecInfo->m_pFogVolume == pFogVolume)
|
||||
{
|
||||
pSecInfo->m_pFogVolume = 0;
|
||||
SetSectorFogVolume(pSecInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CTerrain::MoveAllEntitiesIntoList(list2<IEntityRender*> * plstVisAreasEntities,
|
||||
const Vec3d & vBoxMin, const Vec3d & vBoxMax)
|
||||
{
|
||||
// gat 2d bounds
|
||||
int min_x = (int)(((vBoxMin.x - 1.f)/CTerrain::GetSectorSize()));
|
||||
int min_y = (int)(((vBoxMin.y - 1.f)/CTerrain::GetSectorSize()));
|
||||
int max_x = (int)(((vBoxMax.x + 1.f)/CTerrain::GetSectorSize()));
|
||||
int max_y = (int)(((vBoxMax.y + 1.f)/CTerrain::GetSectorSize()));
|
||||
|
||||
if( min_x<0 ) min_x = 0; else if( min_x>=CTerrain::GetSectorsTableSize() ) min_x = CTerrain::GetSectorsTableSize()-1;
|
||||
if( min_y<0 ) min_y = 0; else if( min_y>=CTerrain::GetSectorsTableSize() ) min_y = CTerrain::GetSectorsTableSize()-1;
|
||||
if( max_x<0 ) max_x = 0; else if( max_x>=CTerrain::GetSectorsTableSize() ) max_x = CTerrain::GetSectorsTableSize()-1;
|
||||
if( max_y<0 ) max_y = 0; else if( max_y>=CTerrain::GetSectorsTableSize() ) max_y = CTerrain::GetSectorsTableSize()-1;
|
||||
|
||||
// make list of sectors
|
||||
list2<CSectorInfo*> TerrainSectorsList;
|
||||
for(int x=min_x; x<=max_x; x++)
|
||||
for(int y=min_y; y<=max_y; y++)
|
||||
TerrainSectorsList.Add(m_arrSecInfoTable[x][y]);
|
||||
|
||||
// this sector contains fps weapons and entities from outside of the map
|
||||
TerrainSectorsList.Add(m_arrSecInfoTable[0][0]);
|
||||
|
||||
// add lists of entities where not added
|
||||
for(int i=0; i<TerrainSectorsList.Count(); i++)
|
||||
{
|
||||
// note: lstEntitiesInArea will have duplicates but it's not a problem
|
||||
plstVisAreasEntities->AddList(TerrainSectorsList.GetAt(i)->m_lstEntities[DYNAMIC_ENTITIES]);
|
||||
plstVisAreasEntities->AddList(TerrainSectorsList.GetAt(i)->m_lstEntities[STATIC_ENTITIES]);
|
||||
TerrainSectorsList.GetAt(i)->m_lstEntities[STATIC_ENTITIES].Clear();
|
||||
TerrainSectorsList.GetAt(i)->m_lstEntities[DYNAMIC_ENTITIES].Clear();
|
||||
}
|
||||
|
||||
// remove duplicates
|
||||
for(int i=0; i<plstVisAreasEntities->Count(); i++)
|
||||
{
|
||||
IEntityRender * pEnt = plstVisAreasEntities->GetAt(0);
|
||||
plstVisAreasEntities->Delete(pEnt);
|
||||
plstVisAreasEntities->Add(pEnt);
|
||||
}
|
||||
}
|
||||
|
||||
bool CTerrain::PreloadResources()
|
||||
{
|
||||
FUNCTION_PROFILER( GetSystem(),PROFILE_3DENGINE );
|
||||
|
||||
static int nCurTexPreloadX=0, nCurTexPreloadY=0;
|
||||
|
||||
nCurTexPreloadX++;
|
||||
if(nCurTexPreloadX>=CTerrain::GetSectorsTableSize())
|
||||
{
|
||||
nCurTexPreloadX=0;
|
||||
nCurTexPreloadY++;
|
||||
}
|
||||
|
||||
if(nCurTexPreloadY>=CTerrain::GetSectorsTableSize())
|
||||
{
|
||||
nCurTexPreloadY = 0;
|
||||
|
||||
DrawDetailTextures(32, 64, false);
|
||||
if(m_pDetailObjects)
|
||||
m_pDetailObjects->PreloadResources();
|
||||
}
|
||||
|
||||
assert(nCurTexPreloadX>=0 && nCurTexPreloadX<CTerrain::GetSectorsTableSize());
|
||||
assert(nCurTexPreloadY>=0 && nCurTexPreloadY<CTerrain::GetSectorsTableSize());
|
||||
|
||||
CSectorInfo * pSecInfo = m_arrSecInfoTable[nCurTexPreloadX][nCurTexPreloadY];
|
||||
if(pSecInfo)
|
||||
{
|
||||
pSecInfo->m_fDistance =
|
||||
GetDist2D( float(pSecInfo->m_nOriginX+(CTerrain::GetSectorSize()>>1)),
|
||||
float(pSecInfo->m_nOriginY+(CTerrain::GetSectorSize()>>1)),
|
||||
m_vCameraPos.x, m_vCameraPos.y ) - (CTerrain::GetSectorSize()>>1);
|
||||
|
||||
pSecInfo->SetLOD();
|
||||
if(pSecInfo->m_fDistance<GetViewCamera().GetZMax()*2)
|
||||
{
|
||||
pSecInfo->SetTextures();
|
||||
//CCObject * pTerrainCCObject = GetRenderer()->EF_GetObject(true);
|
||||
//pSecInfo->RenderSector(pTerrainCCObject);
|
||||
pSecInfo->PreloadResources(GetViewCamera().GetPos(), 0);
|
||||
pSecInfo->m_cLastTimeUsed = fastftol_positive( GetCurTimeSec() );
|
||||
}
|
||||
}
|
||||
|
||||
return !nCurTexPreloadX && !nCurTexPreloadY;
|
||||
}
|
||||
|
||||
void CTerrain::GetObjects(list2<struct IEntityRender*> * pLstObjects)
|
||||
{
|
||||
// reset fog volume pointer in all affected terrain sectors
|
||||
for(int x=0; x<CTerrain::GetSectorsTableSize(); x++)
|
||||
for(int y=0; y<CTerrain::GetSectorsTableSize(); y++)
|
||||
{
|
||||
CBasicArea * pSecInfo = m_arrSecInfoTable[x][y];
|
||||
for(int nStatic=0; nStatic<2; nStatic++)
|
||||
{
|
||||
if(pLstObjects)
|
||||
pLstObjects->AddList(pSecInfo->m_lstEntities[nStatic]);
|
||||
pSecInfo->m_lstEntities[nStatic].Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const void * CTerrain::GetShoreGeometry(int & nPosStride, int & nVertCount, int nSectorX, int nSectorY)
|
||||
{
|
||||
CSectorInfo * pSecInfo = GetSecInfo(nSectorX, nSectorY);
|
||||
if(!pSecInfo)
|
||||
return 0;
|
||||
|
||||
return pSecInfo->GetShoreGeometry(nPosStride, nVertCount);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user