959 lines
30 KiB
C
959 lines
30 KiB
C
/*=========================================================================
|
|
*
|
|
* RLISave.c - Saving functions for RLI file
|
|
*
|
|
* Version 1.0
|
|
* Revision date
|
|
*
|
|
*=======================================================================*/
|
|
#include <Windows.h>
|
|
|
|
#include "RliSave.h"
|
|
|
|
#include "conventi.h"
|
|
#include "print.h"
|
|
#include "system.h"
|
|
#include "vertex.h"
|
|
|
|
#include "Levels.h"
|
|
#include "ModLib.h"
|
|
#include "Submaps.h"
|
|
#include "VseSave.h"
|
|
|
|
|
|
//--- Global defines --------------------------------------------------------
|
|
|
|
long g_lLightIndex = 0;
|
|
|
|
|
|
//--- Global statics --------------------------------------------------------
|
|
|
|
MLT_Light **gs_hLights = NULL;
|
|
|
|
char *gs_LightTypes[] = {"Spherical", "Ambient", "HotSpot", "Parallel"};
|
|
char *gs_LightPrefix[] = {"_paint", "_alpha", "_list"};
|
|
|
|
|
|
|
|
//--- Mathematic functions --------------------------------------------------------
|
|
|
|
// compute the power2
|
|
float sqr(float x)
|
|
{
|
|
return x*x;
|
|
}
|
|
|
|
|
|
// compute the scalar product between 2 3D vectors
|
|
float ScalarProduct(MTH3D_tdstVector *v1, MTH3D_tdstVector *v2)
|
|
{
|
|
return v1->xX*v2->xX + v1->xY*v2->xY + v1->xZ*v2->xZ;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: Load a LG2 file
|
|
*
|
|
* Parameters:
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vLoadLG2()
|
|
{
|
|
SCR_tdst_Cxt_Values *p_stVal;
|
|
xString szFileName;
|
|
int f;
|
|
|
|
sprintf(szFileName, "%s.lg2", g_sFileIn);
|
|
|
|
MLT_vDeleteAllLights();
|
|
SCR_fn_v_RdL0_RegisterCallback(M_Light, MLT_xLoadLight, SCR_CRC_c_RdL0_ForSection);
|
|
|
|
f = _open(szFileName, O_RDONLY, S_IREAD);
|
|
if(f != -1)
|
|
{
|
|
_close(f);
|
|
p_stVal = SCR_fnp_st_RdL0_AnalyseSection(szFileName, SCR_CDF_uw_Anl_ForceAnalyse);
|
|
}
|
|
|
|
SCR_fn_v_RdL0_DeleteRegisterCallback(M_Light, SCR_CRC_c_RdL0_ForSection, SCR_CDR_c_RdL0_Match);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: Load a LGT file
|
|
*
|
|
* Parameters:
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_LoadLGT()
|
|
{
|
|
SCR_tdst_Cxt_Values *p_stVal;
|
|
xString szFileName;
|
|
int f;
|
|
|
|
sprintf(szFileName, "%s.lgt", g_sFileIn);
|
|
|
|
MLT_vDeleteAllLights();
|
|
SCR_fn_v_RdL0_RegisterCallback(M_Light, MLT_xLoadLight, SCR_CRC_c_RdL0_ForSection);
|
|
|
|
f = _open(szFileName, O_RDONLY, S_IREAD);
|
|
if(f != -1)
|
|
{
|
|
_close(f);
|
|
p_stVal = SCR_fnp_st_RdL0_AnalyseSection(szFileName, SCR_CDF_uw_Anl_ForceAnalyse);
|
|
}
|
|
SCR_fn_v_RdL0_DeleteRegisterCallback(M_Light, SCR_CRC_c_RdL0_ForSection, SCR_CDR_c_RdL0_Match);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: create and save the RLI file
|
|
*
|
|
* Parameters:
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vCreateRLI ()
|
|
{
|
|
MLT_tdxHandleToSuperObject hRoot;
|
|
SCR_tdst_File_Description stFile;
|
|
SCR_tdst_Cxt_Values *p_stVal;
|
|
MLT_tdstMatrix stMatrix;
|
|
MLT_tdstColor **rli;
|
|
xString sRoot, sFileSpo, sDir, sRawBank;
|
|
xString sFile, sAction, sIdent, sSection;
|
|
int i, j, nRLI = 0;
|
|
|
|
g_bExistSpoBank=FALSE;
|
|
|
|
if (!g_bLevel)
|
|
{
|
|
// find SPO file
|
|
if (g_bStandardConfig)
|
|
{
|
|
switch (g_iRaw)
|
|
{
|
|
case 0:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks", g_sRawCommon);
|
|
break;
|
|
case 1:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks", g_sRawSpecific1);
|
|
break;
|
|
case 2:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks", g_sRawSpecific2);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
sprintf(sRawBank, g_szBanks);
|
|
}
|
|
else
|
|
{
|
|
if (g_bStandardConfig)
|
|
{
|
|
switch (g_iRaw)
|
|
{
|
|
case 0:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sRawCommon, g_sFileIn);
|
|
break;
|
|
case 1:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sRawSpecific1, g_sFileIn);
|
|
break;
|
|
case 2:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sRawSpecific2, g_sFileIn);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
sprintf(sRawBank, "%s\\%s", g_szLevels, g_sFileIn);
|
|
}
|
|
|
|
GetCurrentDirectory(256, sDir);
|
|
SetCurrentDirectory(sRawBank);
|
|
sprintf(sFileSpo, "%s.spo", g_sFileIn);
|
|
|
|
if (!g_bLevel)
|
|
{
|
|
SCR_fn_v_RdL0_ComputeSectionName(sRoot, sFileSpo, M_SuperObject, M_Root);
|
|
|
|
// load module hierarchy
|
|
if(SCR_fn_c_RdL0_IsSectionExists(sRoot))
|
|
{
|
|
p_stVal = SCR_fnp_st_RdL0_AnalyseSection(sRoot, SCR_CDF_uw_Anl_Normal);
|
|
hRoot = (MLT_tdxHandleToSuperObject)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0);
|
|
g_bExistSpoBank = TRUE;
|
|
MLT_vOutput( C_ComRes_cNormalLine, "\n\tCreate RLI...");
|
|
}
|
|
else
|
|
g_bExistSpoBank = FALSE;
|
|
}
|
|
else
|
|
hRoot = g_hRoot;
|
|
|
|
if (g_bExistSpoBank || g_bLevel)
|
|
{
|
|
if (!g_bLevel)
|
|
{
|
|
// find SPO file
|
|
switch (g_iData)
|
|
{
|
|
case 0:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks\\%s", g_sGameCommon, g_sFileIn);
|
|
break;
|
|
case 1:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks\\%s", g_sGameSpecific1, g_sFileIn);
|
|
break;
|
|
case 2:
|
|
sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks\\%s", g_sGameSpecific2, g_sFileIn);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (g_iData)
|
|
{
|
|
case 0:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sGameCommon, g_sFileIn);
|
|
break;
|
|
case 1:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sGameSpecific1, g_sFileIn);
|
|
break;
|
|
case 2:
|
|
sprintf(sRawBank, "%s\\World\\Levels\\%s", g_sGameSpecific2, g_sFileIn);
|
|
break;
|
|
}
|
|
}
|
|
SetCurrentDirectory(sRawBank);
|
|
|
|
// init RLI file
|
|
sprintf(stFile.a_szFileName,"%s.rli", g_sFileIn);
|
|
remove(stFile.a_szFileName);
|
|
strcpy(stFile.a_szOpenFileName, stFile.a_szFileName);
|
|
stFile.p_stHandle = (SCR_tdst_File_Handle*)malloc(sizeof(SCR_tdst_File_Handle));
|
|
stFile.p_stHandle->xHandle = (FILE*)_open(stFile.a_szFileName, O_WRONLY | O_CREAT | _O_TEXT, S_IREAD | S_IWRITE);;
|
|
stFile.p_stHandle->p_cBase = stFile.p_stHandle->p_cCurrent = 0;
|
|
stFile.p_stHandle->iCnt = 0;
|
|
stFile.d_stFirstPage = stFile.d_stLastPage = stFile.d_stCurPage = NULL;
|
|
stFile.iCurPosInPage = 0;
|
|
|
|
if(stFile.p_stHandle->xHandle != 0)
|
|
{
|
|
// number of RLI tables
|
|
for (i = 0; i<g_lLightIndex; i++)
|
|
nRLI = max(nRLI, gs_hLights[i]->iRLI);
|
|
nRLI++;
|
|
rli = (MLT_tdstColor **)malloc(nRLI*sizeof(MLT_tdstColor *));
|
|
|
|
// loop in modules hierarchy
|
|
MLT_xSetIdentityMatrix(&stMatrix);
|
|
|
|
|
|
if (g_bLevel)
|
|
{
|
|
sprintf(sFile, "%s.sct", g_sFileIn);
|
|
if(! SCR_fn_c_RdL0_IsSectionExists(sFile))
|
|
return;
|
|
|
|
for(i=0; i<hRoot->lNbChild-(g_iUnivSectors+1); i++)
|
|
{
|
|
// recover the old sector
|
|
SCR_fn_v_RdL0_SplitSectionName(hRoot->d_hChild[i]->stSector.sName, sFile, sSection, sIdent);
|
|
SCR_fn_v_RdL0_ComputeSectionName(sAction, sFile, M_Sector, sIdent);
|
|
|
|
if(SCR_fn_c_RdL0_IsSectionExists(sAction))
|
|
{
|
|
MLT_tdstSector *p_stOldSector;
|
|
|
|
p_stVal = SCR_fnp_st_RdL0_AnalyseSection(sAction, SCR_CDF_uw_Anl_Normal);
|
|
p_stOldSector = (MLT_tdstSector*) SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0);
|
|
|
|
// copy lights
|
|
for (j=0; j<p_stOldSector->lNbStaticLights; j++)
|
|
strcpy(hRoot->d_hChild[i]->stSector.a_sStaticLights[j], p_stOldSector->a_sStaticLights[j]);
|
|
hRoot->d_hChild[i]->stSector.lNbStaticLights = p_stOldSector->lNbStaticLights;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < hRoot->lNbChild; i++)
|
|
{
|
|
for (j = 0; j < hRoot->d_hChild[i]->lNbChild; j++)
|
|
{
|
|
hRoot->d_hChild[i]->d_hChild[j]->stSector = hRoot->d_hChild[i]->stSector;
|
|
MLT_vComputeSector (hRoot->d_hChild[i]->d_hChild[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
MLT_vComputeOneRLI(hRoot, &stMatrix, rli, nRLI, &stFile);
|
|
|
|
free(rli);
|
|
}
|
|
_close((int)stFile.p_stHandle->xHandle);
|
|
free(stFile.p_stHandle);
|
|
// MLT_vDeleteAllLights();
|
|
}
|
|
else
|
|
SetCurrentDirectory(sDir);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Description: Clears the light list
|
|
*
|
|
* Parameters:
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vDeleteAllLights()
|
|
{
|
|
int i;
|
|
if(g_lLightIndex)
|
|
{
|
|
for(i=0; i<g_lLightIndex; i++)
|
|
{
|
|
if(gs_hLights[i]->Matrix) free(gs_hLights[i]->Matrix);
|
|
free(gs_hLights[i]);
|
|
}
|
|
free(gs_hLights);
|
|
gs_hLights = NULL;
|
|
g_lLightIndex = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: Light section callback
|
|
*
|
|
* Parameters: p_stFile : script file pointer
|
|
* szAction : section or entry name
|
|
* szParams : parameters
|
|
* cType : action type
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
SCR_tde_Anl_ReturnValue MLT_xLoadLight(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
|
|
{
|
|
SCR_tdst_Cxt_Values *p_stVal;
|
|
MLT_Light *l;
|
|
char *c;
|
|
|
|
switch (cType)
|
|
{
|
|
case SCR_EA_Anl_BeginSection:
|
|
l = (MLT_Light*)malloc(sizeof(MLT_Light));
|
|
SCR_M_RdL0_SetSectionLong(0,0,(long)l);
|
|
SCR_M_RdL0_SetContextLong(0,0,(long)l);
|
|
gs_hLights = (MLT_Light**)realloc(gs_hLights, (++g_lLightIndex)*sizeof(MLT_Light*));
|
|
gs_hLights[g_lLightIndex - 1] = l;
|
|
l->iGeomType = MLT_iGetLightType(szParams[0]);
|
|
sprintf(l->sName,"%s",SCR_M_RdL0_GetCompleteSectionNameR(0));
|
|
|
|
if ( strstr(l->sName, "FORCE_FULL_LIGHT_"))
|
|
l->bNotCompute = TRUE;
|
|
else
|
|
l->bNotCompute = FALSE;
|
|
|
|
l->Matrix = NULL;
|
|
l->iState = 0;
|
|
l->iRLI = 0;
|
|
l->iType = L_RGB;
|
|
if(strstr(l->sName, gs_LightPrefix[0])) l->iType |= L_PAINT;
|
|
if(strstr(l->sName, gs_LightPrefix[1])) l->iType |= L_ALPHA;
|
|
c = l->sName;
|
|
do c = strstr(c+1, gs_LightPrefix[2]);
|
|
while(c && (!isdigit(c[5]) || !isdigit(c[6])));
|
|
if(c) l->iRLI = atoi(c+5);
|
|
break;
|
|
|
|
case SCR_EA_Anl_Entry:
|
|
SCR_M_RdL0_GetContextLong(0, 0, MLT_Light*, l);
|
|
// set light's state
|
|
if(!lstrcmpi(szAction, M_LGTActionSetState)) l->iState = atoi(szParams[0]);
|
|
if(!lstrcmpi(szAction, M_LGTActionSetColor))
|
|
{
|
|
l->color.xR = (float) atof(szParams[0]);
|
|
l->color.xG = (float) atof(szParams[1]);
|
|
l->color.xB = (float) atof(szParams[2]);
|
|
if(l->iType & L_ALPHA)
|
|
l->color.xA = (float) atof(szParams[0]);
|
|
else
|
|
l->color.xA = (float) atof(szParams[3]);
|
|
}
|
|
// matrix name
|
|
if(!lstrcmpi(szAction, M_LGTActionSetMatrix))
|
|
{
|
|
c = strchr(szParams[0], '^');
|
|
if(c)
|
|
{
|
|
*(c-1) = '*';
|
|
p_stVal = SCR_fnp_st_RdL0_AnalyseSection(c-1, SCR_CDF_uw_Anl_Normal);
|
|
l->Matrix = (MLT_tdstMatrix*)SCR_M_ul_RdL0_ExtractLongValue(p_stVal, 0);
|
|
}
|
|
}
|
|
// Near/Far parameters
|
|
if(!lstrcmpi(szAction, M_LGTActionSetNearFar))
|
|
{
|
|
l->fNearFar[0] = (float)atof(szParams[0]);
|
|
l->fNearFar[1] = (float)atof(szParams[1]);
|
|
}
|
|
// Alpha angles
|
|
if(!lstrcmpi(szAction, M_LGTActionSetAlphas))
|
|
{
|
|
l->fAlphas[0] = (float)atof(szParams[0]);
|
|
l->fAlphas[1] = (float)atof(szParams[1]);
|
|
}
|
|
break;
|
|
|
|
case SCR_EA_Anl_EndSection:
|
|
break;
|
|
}
|
|
return SCR_ERV_Anl_NormalReturn;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: Light matrix section callback
|
|
*
|
|
* Parameters: p_stFile : script file pointer
|
|
* szAction : section or entry name
|
|
* szParams : parameters
|
|
* cType : action type
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
SCR_tde_Anl_ReturnValue MLT_xLoadMatrixRLI(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType)
|
|
{
|
|
long i;
|
|
xString sFile, sAction, sIdent, sIdent2;
|
|
MTH_tdxReal a_xVertex[9];
|
|
MLT_tdstMatrix *p_stMatrix;
|
|
MTH3D_tdstVector stI,stJ,stK;
|
|
|
|
switch (cType)
|
|
{
|
|
case SCR_EA_Anl_BeginSection:
|
|
p_stMatrix=(MLT_tdstMatrix*)malloc(sizeof(MLT_tdstMatrix));
|
|
MLT_xSetIdentityMatrix(p_stMatrix);
|
|
SCR_fn_v_RdL0_SplitSectionName(SCR_M_RdL0_GetCompleteSectionNameR(0), sFile, sAction, sIdent);
|
|
SCR_fn_v_RdL0_ComputeSectionName(p_stMatrix->sName, sFile, sAction, sIdent2);
|
|
|
|
SCR_M_RdL0_SetSectionLong(0,0,(unsigned long)p_stMatrix);
|
|
SCR_M_RdL0_SetContextLong(0,0,(unsigned long)p_stMatrix);
|
|
break;
|
|
|
|
case SCR_EA_Anl_Entry:
|
|
{
|
|
SCR_M_RdL0_GetContextLong(0,0,MLT_tdstMatrix*,p_stMatrix);
|
|
|
|
// load the translation
|
|
if (strcmp(szAction,M_MATActionTranslation)==0)
|
|
{
|
|
|
|
for (i=0;i<3;i++)
|
|
a_xVertex[i]=(MTH_tdxReal)MTH_M_xFloatToReal(atof(szParams[i]));
|
|
|
|
MLT_M_SetVertexXYZ(&stI,a_xVertex[0],a_xVertex[1],a_xVertex[2]);
|
|
MLT_xSetTranslationMatrix(p_stMatrix,&stI);
|
|
}
|
|
|
|
// load the scale
|
|
if (strcmp(szAction,M_MATActionScale)==0)
|
|
{
|
|
for (i=0;i<9;i++)
|
|
a_xVertex[i]=(MTH_tdxReal)MTH_M_xFloatToReal(atof(szParams[i]));
|
|
|
|
MLT_M_SetVertexXYZ(&stI,a_xVertex[0],a_xVertex[1],a_xVertex[2]);
|
|
MLT_M_SetVertexXYZ(&stJ,a_xVertex[3],a_xVertex[4],a_xVertex[5]);
|
|
MLT_M_SetVertexXYZ(&stK,a_xVertex[6],a_xVertex[7],a_xVertex[8]);
|
|
MLT_xSetScaleMatrix(p_stMatrix,&stI,&stJ,&stK);
|
|
}
|
|
|
|
// load the rotation
|
|
if (strcmp(szAction,M_MATActionRotation)==0)
|
|
{
|
|
for (i=0;i<9;i++)
|
|
a_xVertex[i]=(MTH_tdxReal)MTH_M_xFloatToReal(atof(szParams[i]));
|
|
|
|
MLT_M_SetVertexXYZ(&stI,a_xVertex[0],a_xVertex[1],a_xVertex[2]);
|
|
MLT_M_SetVertexXYZ(&stJ,a_xVertex[3],a_xVertex[4],a_xVertex[5]);
|
|
MLT_M_SetVertexXYZ(&stK,a_xVertex[6],a_xVertex[7],a_xVertex[8]);
|
|
MLT_xSetRotationMatrix(p_stMatrix,&stI,&stJ,&stK);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCR_EA_Anl_EndSection:
|
|
break;
|
|
}
|
|
return SCR_ERV_Anl_NormalReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute RLI for Full Light
|
|
*
|
|
* Parameters: obj : geometric object
|
|
* rli : rli list
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeFullRLI(MLT_tdstGeometricObject *obj, MLT_tdstColor *rli)
|
|
{
|
|
int i;
|
|
for(i=0; i<obj->xNbPoints; i++)
|
|
{
|
|
(rli+i)->xR = (float) 255.0;
|
|
(rli+i)->xG = (float) 255.0;
|
|
(rli+i)->xB = (float) 255.0;
|
|
(rli+i)->xA = (float) 255.0;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Description: compute RLI for Spherical Light
|
|
*
|
|
* Parameters: p_stMatrix : current matrix
|
|
* light : current light
|
|
* obj : geometric object
|
|
* rli : rli list
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeSphericalRLI (MLT_tdstMatrix *p_stMatrix, MLT_Light *light, MLT_tdstGeometricObject *obj, MLT_tdstColor *rli)
|
|
{
|
|
MTH3D_tdstVector dist, lightpos, norm, realpoint;
|
|
MTH3D_tdstVector *point = obj->d_stListOfPoints;
|
|
MTH3D_tdstVector *normal = obj->d_stListOfPointsNormals;
|
|
float near2 = sqr(light->fNearFar[0]);
|
|
float far2 = sqr(light->fNearFar[1]);
|
|
float delta, d, coef;
|
|
int i;
|
|
|
|
delta = far2 - near2 > 1e-8 ? 1.f/(far2 - near2) : 1.f;
|
|
MLT_xGetTranslationMatrix(light->Matrix, &lightpos);
|
|
|
|
// for all object's points
|
|
for (i=0; i<obj->xNbPoints; i++)
|
|
{
|
|
MTH3D_M_vCopyVector(&norm, normal+i);
|
|
MTH3D_M_vNormalizeVector(&norm, &norm);
|
|
MLT_xMulMatrixVertex(&realpoint, p_stMatrix, point+i);
|
|
// compute the vector light-point
|
|
MTH3D_M_vSubVector(&dist, &lightpos, &realpoint);
|
|
// compute the square distance
|
|
d = sqr(dist.xX) + sqr(dist.xY) + sqr(dist.xZ);
|
|
// if point may be in the light action zone
|
|
if (d < far2)
|
|
{
|
|
// compute the reflexion coeficient
|
|
coef = -ScalarProduct(&dist, &norm) / (float)(d > 1e-4 ? sqrt(d) : 1e-2);
|
|
// if PaintLight, then no backface
|
|
if (light->iType|L_PAINT && coef<0)
|
|
coef = -coef;
|
|
// update the coeficient
|
|
if (d >= near2)
|
|
coef *= (far2 - d)*delta;
|
|
// adds the light effect to RLI
|
|
if (coef > 0)
|
|
MLT_vAddLightEffect(rli+i, &light->color, coef);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute RLI for Ambiant Light
|
|
*
|
|
* Parameters: p_stMatrix : current matrix
|
|
* light : current light
|
|
* obj : geometric object
|
|
* rli : rli list
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeAmbientRLI (MLT_tdstMatrix *p_stMatrix, MLT_Light *light, MLT_tdstGeometricObject *obj, MLT_tdstColor *rli)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<obj->xNbPoints; i++)
|
|
MLT_vAddLightEffect(rli+i, &light->color, 1.f);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute RLI for HotSpot Light
|
|
*
|
|
* Parameters: p_stMatrix : current matrix
|
|
* light : current light
|
|
* obj : geometric object
|
|
* rli : rli list
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeHotSpotRLI (MLT_tdstMatrix *p_stMatrix, MLT_Light *light, MLT_tdstGeometricObject *obj, MLT_tdstColor *rli)
|
|
{
|
|
MTH3D_tdstVector dist, c0, c1, c2, norm, realpoint;
|
|
MTH3D_tdstVector *point = obj->d_stListOfPoints;
|
|
MTH3D_tdstVector *normal = obj->d_stListOfPointsNormals;
|
|
float near2 = sqr(light->fNearFar[0]);
|
|
float far2 = sqr(light->fNearFar[1]);
|
|
float ltan = (float)tan(light->fAlphas[0]/2);
|
|
float btan = (float)tan(light->fAlphas[1]/2);
|
|
float delta, deltatg, d, coef;
|
|
int i;
|
|
|
|
delta = far2 - near2 > 1e-8 ? 1.f/(far2 - near2) : 1.f;
|
|
deltatg = btan - ltan > 1e-8 ? 1.f/(btan - ltan) : 1.f;
|
|
|
|
// for all object's points
|
|
for (i=0; i<obj->xNbPoints; i++)
|
|
{
|
|
MTH3D_M_vCopyVector(&norm, normal+i);
|
|
MTH3D_M_vNormalizeVector(&norm, &norm)
|
|
MLT_xMulMatrixVertex(&realpoint, p_stMatrix, point+i);
|
|
// get the light-point vector
|
|
MTH3D_M_vSubVector(&c2, &light->Matrix->stTranslation, &realpoint);
|
|
// get the rotation matrix on columns
|
|
MLT_xGetRotationMatrix(light->Matrix, &c0, &c1, &dist);
|
|
dist.xZ = ScalarProduct(&dist, &c2);
|
|
dist.xY = ScalarProduct(&c1, &c2);
|
|
dist.xX = ScalarProduct(&c0, &c2);
|
|
// compute the partial square distance
|
|
d = sqr(dist.xY) + sqr(dist.xZ);
|
|
// if point may be in the light spot
|
|
if (dist.xX < light->fNearFar[1] && dist.xX > 1e-4f && d < far2)
|
|
{
|
|
// get the light-point axis tangent in the light space
|
|
float tangent = (float)(sqrt(d) / dist.xX);
|
|
// if point may be in the light spot
|
|
if(tangent < btan)
|
|
{
|
|
// compute the full square distance
|
|
d += sqr(dist.xZ);
|
|
// compute the reflexion coeficient
|
|
coef = d < near2 ? 1.f : (far2 - d) * delta;
|
|
// update the coeficient
|
|
if(tangent > ltan)
|
|
coef *= (btan - tangent) * deltatg;
|
|
coef *= ScalarProduct(&c0, &norm);
|
|
// if PaintLight then no backface
|
|
if(light->iType|L_PAINT && coef<0)
|
|
coef = -coef;
|
|
// adds the light effect to RLI
|
|
if(coef > 0)
|
|
MLT_vAddLightEffect(rli+i, &light->color, coef);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute RLI for Parallel Light
|
|
*
|
|
* Parameters: p_stMatrix : current matrix
|
|
* light : current light
|
|
* obj : geometric object
|
|
* rli : rli list
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeParallelRLI (MLT_tdstMatrix *p_stMatrix, MLT_Light *light, MLT_tdstGeometricObject *obj, MLT_tdstColor *rli)
|
|
{
|
|
MTH3D_tdstVector c0, c1, c2, norm;
|
|
MTH3D_tdstVector *normal = obj->d_stListOfPointsNormals;
|
|
float coef;
|
|
int i;
|
|
|
|
// get the rotation matrix on columns, so get the light's vector in the world space
|
|
MLT_xGetRotationMatrix(light->Matrix, &c0, &c1, &c2);
|
|
|
|
// for all object's points
|
|
for(i=0; i<obj->xNbPoints; i++)
|
|
{
|
|
MTH3D_M_vCopyVector(&norm, normal+i);
|
|
MTH3D_M_vNormalizeVector(&norm, &norm)
|
|
// compute the reflexion coeficient
|
|
coef = -ScalarProduct(&c2, &norm);
|
|
if(light->iType|L_PAINT && coef<0)
|
|
coef = -coef;
|
|
// adds the light effect to RLI
|
|
if(coef > 0)
|
|
MLT_vAddLightEffect(rli+i, &light->color, coef);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute one RLI
|
|
*
|
|
* Parameters: hSupObj : current super-object
|
|
* p_stMatrix : current matrix
|
|
* rli : pointer on rli lists
|
|
* nRLI : nb of rli lists
|
|
* p_stFile : script pointer of the rli file
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeOneRLI (MLT_tdxHandleToSuperObject hSupObj, MLT_tdstMatrix *p_stMatrix, MLT_tdstColor **rli, int nRLI, SCR_tdst_File_Description *p_stFile)
|
|
{
|
|
MLT_tdstMatrix stMatrix;
|
|
xString sFile, sAction, sIdent, sSection;
|
|
xString sName, sForme, sHabillage;
|
|
long lNoPhy, lNoLod;
|
|
int i, j, k;
|
|
|
|
MLT_xMulMatrixMatrix(&stMatrix, hSupObj->p_stMatrix, p_stMatrix);
|
|
|
|
// look for geometry
|
|
if (strcmp(hSupObj->sGeometric, ""))
|
|
{
|
|
// find geometry
|
|
MLT_tdstGeometricObject *obj = MLT_pFindInLib(hSupObj->sGeometric);
|
|
if(obj == NULL)
|
|
{
|
|
MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't load %s", hSupObj->sGeometric);
|
|
return;
|
|
}
|
|
|
|
if(strlen(obj->sPhysicalSection) || g_bLevel)
|
|
{
|
|
// create the RLI list
|
|
for(j=0; j<nRLI; j++)
|
|
{
|
|
rli[j] = (MLT_tdstColor *)malloc(obj->xNbPoints*sizeof(MLT_tdstColor));
|
|
for(k=0; k<obj->xNbPoints; k++)
|
|
{
|
|
rli[j][k].xR = rli[j][k].xG = rli[j][k].xB = 0; // initialize the RLI list
|
|
rli[j][k].xA = 255; // initialize the RLI list
|
|
}
|
|
}
|
|
if (!g_bLevel)
|
|
{
|
|
// for all lights
|
|
for(j=0; j<g_lLightIndex; j++)
|
|
{
|
|
MLT_Light *light = gs_hLights[j];
|
|
if (light->bNotCompute)
|
|
{
|
|
MLT_vComputeFullRLI(obj, rli[light->iRLI]);
|
|
}
|
|
// if the light is ON
|
|
else if(light->iState && light->Matrix)
|
|
{
|
|
// Compute the RLI lists
|
|
switch(light->iGeomType)
|
|
{
|
|
case SPHERICAL: MLT_vComputeSphericalRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case AMBIENT: MLT_vComputeAmbientRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case HOTSPOT: MLT_vComputeHotSpotRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case PARALLEL: MLT_vComputeParallelRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else //for the level uses just the lights specified in sct file
|
|
{
|
|
for(j=0; j<hSupObj->stSector.lNbStaticLights; j++)
|
|
{
|
|
MLT_Light *light = MLT_hGetLight(hSupObj->stSector.a_sStaticLights[j], gs_hLights);
|
|
if (light == NULL)
|
|
{
|
|
MLT_vOutput( C_ComRes_cErrorLine, "\nError : The light %s doesn't exist", hSupObj->stSector.a_sStaticLights[j]);
|
|
continue;
|
|
}
|
|
|
|
if(light->iState && light->Matrix) // if the light is ON
|
|
{
|
|
// Compute the RLI lists
|
|
switch(light->iGeomType)
|
|
{
|
|
case SPHERICAL: MLT_vComputeSphericalRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case AMBIENT: MLT_vComputeAmbientRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case HOTSPOT: MLT_vComputeHotSpotRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
case PARALLEL: MLT_vComputeParallelRLI(&stMatrix, light, obj, rli[light->iRLI]); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
// Save the RLI data
|
|
if (g_bLevel)
|
|
{
|
|
MLT_vMakePhysicalInLib();
|
|
SCR_fn_v_RdL0_SplitSectionName(obj->sPhysicalSection, sFile, sAction, sIdent);
|
|
for(j=0; j<nRLI; j++)
|
|
{
|
|
SCR_fn_v_RdL0_SplitSectionName(obj->sPhysicalSection, sFile, sAction, sIdent);
|
|
sprintf(sFile, "%s.vse", g_sFileIn);
|
|
MLT_vSplitModuleSectionName(sIdent, sForme, sHabillage, &lNoPhy, &lNoLod, sName);
|
|
MLT_vComputeVisualSetSectionName(sIdent, sForme, sHabillage, sName);
|
|
SCR_fn_v_RdL0_ComputeSectionName(sSection, sFile, M_VS, sIdent);
|
|
obj->lNbLod = MLT_lSaveLodInFile(sSection);
|
|
wsprintf(sSection, "ISI:ISI_%s(NBRLOD, %d)", sIdent, obj->lNbLod);
|
|
SCR_M_SvL0_SaveBeginSection(p_stFile, sSection, SCR_CC_C_Cfg_EOL);
|
|
SCR_M_SvL0_SaveEntry(p_stFile, M_RLIActionAddLOD, SCR_CC_C_Cfg_NoChar);
|
|
SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 2, "%d,%d", 0, obj->xNbPoints);
|
|
for(k=0; k<obj->xNbPoints; k++)
|
|
{
|
|
SCR_M_SvL0_SaveEntry(p_stFile, M_RLIActionAddVertexLOD, SCR_CC_C_Cfg_NoChar);
|
|
SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 5, "%d,%d,%d,%d,%d", k, (int)rli[j][k].xR, (int)rli[j][k].xG, (int)rli[j][k].xB, (int)rli[j][k].xA);
|
|
}
|
|
SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
|
|
free(rli[j]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SCR_fn_v_RdL0_SplitSectionName(obj->sPhysicalSection, sFile, sAction, sIdent);
|
|
sprintf(sSection, "RLI:%s(NBRLI, %d)", sIdent, nRLI);
|
|
SCR_M_SvL0_SaveBeginSection(p_stFile, sSection, SCR_CC_C_Cfg_EOL);
|
|
for(j=0; j<nRLI; j++)
|
|
{
|
|
SCR_fn_v_RdL0_SplitSectionName(obj->sPhysicalSection, sFile, sAction, sIdent);
|
|
sprintf(sFile, "%s.vse", g_sFileIn);
|
|
MLT_vSplitModuleSectionName(sIdent, sForme, sHabillage, &lNoPhy, &lNoLod, sName);
|
|
MLT_vComputeVisualSetSectionName(sIdent, sForme, sHabillage, sName);
|
|
SCR_fn_v_RdL0_ComputeSectionName(sSection, sFile, M_VS, sIdent);
|
|
obj->lNbLod = MLT_lSaveLodInFile(sSection);
|
|
wsprintf(sSection, "IS2:ISI_RLI%02d(NBRLOD, %d)", j, obj->lNbLod);
|
|
SCR_M_SvL0_SaveBeginSection(p_stFile, sSection, SCR_CC_C_Cfg_EOL);
|
|
SCR_M_SvL0_SaveEntry(p_stFile, M_RLIActionAddLOD, SCR_CC_C_Cfg_NoChar);
|
|
SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 2, "%d,%d", 0, obj->xNbPoints);
|
|
for(k=0; k<obj->xNbPoints; k++)
|
|
{
|
|
SCR_M_SvL0_SaveEntry(p_stFile, M_RLIActionAddVertexLOD, SCR_CC_C_Cfg_NoChar);
|
|
SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 5, "%d,%d,%d,%d,%d", k, (int)rli[j][k].xR, (int)rli[j][k].xG, (int)rli[j][k].xB, (int)rli[j][k].xA);
|
|
}
|
|
SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
|
|
free(rli[j]);
|
|
}
|
|
SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// loop on each child
|
|
for (i=0; i<hSupObj->lNbChild; i++)
|
|
MLT_vComputeOneRLI(hSupObj->d_hChild[i], &stMatrix, rli, nRLI, p_stFile);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: Get the light type from it's name
|
|
*
|
|
* Parameters: type : name to parse
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
int MLT_iGetLightType(char *type)
|
|
{
|
|
int i;
|
|
for (i=0; i<sizeof(gs_LightTypes)/sizeof(char*); i++)
|
|
{
|
|
if (!lstrcmpi(type, gs_LightTypes[i]))
|
|
return i;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: adds the light effect to the rli, with the given coefficient
|
|
*
|
|
* Parameters: dst : destination color
|
|
* src : source color
|
|
* coef : coefficient
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vAddLightEffect(MLT_tdstColor *dst, MLT_tdstColor *src, float coef)
|
|
{
|
|
dst->xR += src->xR * coef * 255;
|
|
dst->xG += src->xG * coef * 255;
|
|
dst->xB += src->xB * coef * 255;
|
|
if (!g_bLevel)
|
|
dst->xA -= src->xA * coef * 255;
|
|
else
|
|
dst->xA += src->xA * coef * 255;
|
|
|
|
if (!g_bLevel)
|
|
{
|
|
dst->xR = (dst->xR > 255.0) ? (float) 255.0 : dst->xR;
|
|
dst->xG = (dst->xG > 255.0) ? (float) 255.0 : dst->xG;
|
|
dst->xB = (dst->xB > 255.0) ? (float) 255.0 : dst->xB;
|
|
dst->xA = (dst->xA > 255.0) ? (float) 255.0 : dst->xA;
|
|
dst->xA = (dst->xA < 0.0) ? (float) 0.0 : dst->xA;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: get a light from its name in the array of light
|
|
*
|
|
* Parameters: sStaticLight : name of the light to find
|
|
* g_hLights : array of light to search
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
MLT_Light *MLT_hGetLight (xString sStaticLight, MLT_Light **g_hLights)
|
|
{
|
|
MLT_Light *p_stLight = NULL;
|
|
char * p_sShortName;
|
|
int i;
|
|
|
|
// get short name (without level name)
|
|
p_sShortName = strstr(sStaticLight, "\\");
|
|
if (!p_sShortName)
|
|
p_sShortName = sStaticLight;
|
|
else
|
|
p_sShortName++;
|
|
|
|
for (i=0; i<g_lLightIndex; i++)
|
|
{
|
|
if (!stricmp(g_hLights[i]->sName, p_sShortName))
|
|
return g_hLights[i];
|
|
}
|
|
|
|
return p_stLight;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* Description: compute the sector parameters
|
|
*
|
|
* Parameters: hSupObj : root
|
|
*---------------------------------------------------------------------------
|
|
* Revision date: Author:
|
|
*****************************************************************************/
|
|
void MLT_vComputeSector (MLT_tdxHandleToSuperObject hSupObj)
|
|
{
|
|
int i;
|
|
// loop on each child
|
|
for (i = 0; i < hSupObj->lNbChild; i++)
|
|
hSupObj->d_hChild[i]->stSector = hSupObj->stSector;
|
|
|
|
for (i=0; i<hSupObj->lNbChild; i++)
|
|
MLT_vComputeSector(hSupObj->d_hChild[i]);
|
|
}
|
|
|
|
|
|
|