413 lines
16 KiB
C++
413 lines
16 KiB
C++
///////////////////////////////////////////////////////////////////////
|
|
// Name: LeafLighting.cpp
|
|
//
|
|
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
|
|
//
|
|
// Copyright (c) 2001-2004 IDV, Inc.
|
|
// All Rights Reserved.
|
|
//
|
|
// IDV, Inc.
|
|
// 1233 Washington St. Suite 610
|
|
// Columbia, SC 29201
|
|
// Voice: (803) 799-1699
|
|
// Fax: (803) 931-0320
|
|
// Web: http://www.idvinc.com
|
|
//
|
|
// This software is supplied under the terms of a license agreement or
|
|
// nondisclosure agreement with Interactive Data Visualization and may not
|
|
// be copied or disclosed except in accordance with the terms of that
|
|
// agreement.
|
|
|
|
#include "Debug.h"
|
|
#include "LightingEngine.h"
|
|
|
|
|
|
bool CLightingEngine::m_abLightEnabled[c_nMaxLights] = { false };
|
|
float CLightingEngine::m_afLightAttributes[c_nMaxLights][c_nLightParamSize] =
|
|
{
|
|
// 0
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 1
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 2
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 3
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 4
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 5
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 6
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
},
|
|
// 7
|
|
{
|
|
0.0f, 0.0f, 0.0f, // pos
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.0f, 0.0f, 0.0f, // ambient
|
|
1.0f, 1.0f, 1.0f, // specular
|
|
1.0f, // directional flag
|
|
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
|
|
}
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::CLightingEngine definition
|
|
|
|
CLightingEngine::CLightingEngine( ) :
|
|
m_eBranchLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC),
|
|
m_eLeafLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC),
|
|
m_fLeafLightingAdjustmentScalar(0.5f),
|
|
m_eStaticLightingStyle(CSpeedTreeRT::SLS_BASIC),
|
|
m_eFrondLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC)
|
|
{
|
|
float afDefaultBranchMaterial[c_nMaterialParamSize] =
|
|
{
|
|
0.8f, 0.8f, 0.8f, // diffuse
|
|
0.2f, 0.2f, 0.2f, // ambient
|
|
0.0f, 0.0f, 0.0f, // specular
|
|
0.0f, 0.0f, 0.0f, // emissive
|
|
0.0f // shininess
|
|
};
|
|
|
|
float afDefaultLeafMaterial[c_nMaterialParamSize] =
|
|
{
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.5f, 0.5f, 0.5f, // ambient
|
|
0.0f, 0.0f, 0.0f, // specular
|
|
0.0f, 0.0f, 0.0f, // emissive
|
|
0.0f // shininess
|
|
};
|
|
|
|
float afDefaultFrondMaterial[c_nMaterialParamSize] =
|
|
{
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.5f, 0.5f, 0.5f, // ambient
|
|
0.0f, 0.0f, 0.0f, // specular
|
|
0.0f, 0.0f, 0.0f, // emissive
|
|
0.0f // shininess
|
|
};
|
|
|
|
memcpy(m_afBranchMaterial, afDefaultBranchMaterial, c_nMaterialParamSize * sizeof(float));
|
|
memcpy(m_afLeafMaterial, afDefaultLeafMaterial, c_nMaterialParamSize * sizeof(float));
|
|
memcpy(m_afFrondMaterial, afDefaultFrondMaterial, c_nMaterialParamSize * sizeof(float));
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::ComputeStandardStaticLighting definition
|
|
|
|
#define Light m_afLightAttributes[nLight]
|
|
#define Clamp(a, b, c) a < b ? a = b : a > c ? a = c : a = a;
|
|
|
|
void CLightingEngine::ComputeStandardStaticLighting(const float* pNormal, const float* pCoord, float* pColor, EMaterial eMaterial)
|
|
{
|
|
st_assert(pCoord);
|
|
st_assert(pNormal);
|
|
|
|
CVec3 cColor;
|
|
// compute each component of the lighting equation for each light
|
|
for (int nLight = 0; nLight < c_nMaxLights; ++nLight)
|
|
{
|
|
if (m_abLightEnabled[nLight])
|
|
{
|
|
CVec3 cVertex(pCoord[0], pCoord[1], pCoord[2]);
|
|
CVec3 cNormal(pNormal[0], pNormal[1], pNormal[2]);
|
|
CVec3 cLightPos(Light[c_nLightPos + 0], Light[c_nLightPos + 1], Light[c_nLightPos + 2]);
|
|
|
|
// pick the appropriate material
|
|
float* pMaterial;
|
|
switch (eMaterial)
|
|
{
|
|
case MATERIAL_LEAF:
|
|
pMaterial = m_afLeafMaterial;
|
|
break;
|
|
case MATERIAL_FROND:
|
|
pMaterial = m_afFrondMaterial;
|
|
break;
|
|
default: // branch or "other"
|
|
pMaterial = m_afBranchMaterial;
|
|
}
|
|
|
|
// emissive
|
|
CVec3 cEmissive(pMaterial[c_nMaterialEmissive + 0],
|
|
pMaterial[c_nMaterialEmissive + 1],
|
|
pMaterial[c_nMaterialEmissive + 2]);
|
|
// ambient
|
|
CVec3 cAmbient(Light[c_nLightAmbient + 0] * pMaterial[c_nMaterialAmbient + 0],
|
|
Light[c_nLightAmbient + 1] * pMaterial[c_nMaterialAmbient + 1],
|
|
Light[c_nLightAmbient + 2] * pMaterial[c_nMaterialAmbient + 2]);
|
|
|
|
// attenuation
|
|
float fAttenuation = 1.0f;
|
|
if (Light[c_nLightDirectional] != 0.0f)
|
|
{
|
|
float fDistance = cVertex.Distance(cLightPos);
|
|
fAttenuation = 1.0f / (Light[c_nLightAttenuation + 0] +
|
|
Light[c_nLightAttenuation + 1] * fDistance +
|
|
Light[c_nLightAttenuation + 2] * fDistance * fDistance);
|
|
}
|
|
// diffuse
|
|
CVec3 cLightVector(Light[c_nLightDirectional] == 0.0f ? cLightPos : cLightPos - cVertex);
|
|
cLightVector.Normalize( );
|
|
float fDotProduct = cLightVector.Dot(cNormal);
|
|
if (fDotProduct < 0.0f)
|
|
fDotProduct = 0.0f;
|
|
CVec3 cDiffuse(fDotProduct * Light[c_nLightDiffuse + 0] * pMaterial[c_nMaterialDiffuse + 0],
|
|
fDotProduct * Light[c_nLightDiffuse + 1] * pMaterial[c_nMaterialDiffuse + 1],
|
|
fDotProduct * Light[c_nLightDiffuse + 2] * pMaterial[c_nMaterialDiffuse + 2]);
|
|
|
|
// add each light's contribution
|
|
cColor += cEmissive + (cAmbient + cDiffuse) * fAttenuation;
|
|
}
|
|
}
|
|
|
|
pColor[0] = cColor[0];
|
|
pColor[1] = cColor[1];
|
|
pColor[2] = cColor[2];
|
|
pColor[3] = 1.0f;
|
|
|
|
Clamp(pColor[0], 0.0f, 1.0f);
|
|
Clamp(pColor[1], 0.0f, 1.0f);
|
|
Clamp(pColor[2], 0.0f, 1.0f);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::ComputeLeafStaticLighting definition
|
|
|
|
void CLightingEngine::ComputeLeafStaticLighting(const CVec3& cTreeCenter, vector<CBillboardLeaf*>* pLeafLods, int nNumLeafLods)
|
|
{
|
|
if (m_eLeafLightingMethod == CSpeedTreeRT::LIGHT_STATIC &&
|
|
m_eStaticLightingStyle != CSpeedTreeRT::SLS_BASIC)
|
|
{
|
|
// compute all leaf LODs
|
|
for (int nLod = 0; nLod < nNumLeafLods; ++nLod)
|
|
{
|
|
// compute each leaf in each LOD
|
|
for (vector<CBillboardLeaf*>::iterator i = pLeafLods[nLod].begin( ); i != pLeafLods[nLod].end( ); ++i)
|
|
{
|
|
const CVec3& cNormal = (*i)->GetNormal( );
|
|
const CVec3& cVertex = (*i)->GetPosition( );
|
|
CVec3 cDiffuseColor = (*i)->GetColor( );
|
|
|
|
CVec3 cDominantLight; // only one light can be used to simulation the shadow effect
|
|
float fMaxDotProduct = -1.0f;
|
|
CVec3 cColor;
|
|
|
|
// compute each component of the lighting equation for each light
|
|
for (int nLight = 0; nLight < c_nMaxLights; ++nLight)
|
|
{
|
|
if (m_abLightEnabled[nLight])
|
|
{
|
|
CVec3 cLightPos(Light[c_nLightPos + 0], Light[c_nLightPos + 1], Light[c_nLightPos + 2]);
|
|
// angle of incidence
|
|
CVec3 cLightVector(Light[c_nLightDirectional] == 0.0f ? cLightPos : cLightPos - cVertex);
|
|
cLightVector.Normalize( );
|
|
float fDotProduct = cLightVector.Dot(cNormal);
|
|
if (fDotProduct >= fMaxDotProduct) // which light will be used to simulate the shadows?
|
|
{
|
|
fMaxDotProduct = fDotProduct;
|
|
cDominantLight = cLightPos;
|
|
}
|
|
if (fDotProduct < 0.0f)
|
|
fDotProduct = 0.0f;
|
|
fDotProduct = VecInterpolate(m_fLeafLightingAdjustmentScalar, 1.0f, fDotProduct);
|
|
|
|
if (m_eStaticLightingStyle & CSpeedTreeRT::SLS_USE_LIGHT_SOURCES)
|
|
{
|
|
// emissive
|
|
CVec3 cEmissive(m_afLeafMaterial[c_nMaterialEmissive + 0],
|
|
m_afLeafMaterial[c_nMaterialEmissive + 1],
|
|
m_afLeafMaterial[c_nMaterialEmissive + 2]);
|
|
// ambient
|
|
CVec3 cAmbient(Light[c_nLightAmbient + 0] * m_afLeafMaterial[c_nMaterialAmbient + 0],
|
|
Light[c_nLightAmbient + 1] * m_afLeafMaterial[c_nMaterialAmbient + 1],
|
|
Light[c_nLightAmbient + 2] * m_afLeafMaterial[c_nMaterialAmbient + 2]);
|
|
|
|
// attenuation
|
|
float fAttenuation = 1.0f;
|
|
if (Light[c_nLightDirectional] != 0.0f)
|
|
{
|
|
float fDistance = cVertex.Distance(cLightPos);
|
|
float fDenominator = (Light[c_nLightAttenuation + 0] +
|
|
Light[c_nLightAttenuation + 1] * fDistance +
|
|
Light[c_nLightAttenuation + 2] * fDistance * fDistance);
|
|
if (fDenominator != 0.0f)
|
|
fAttenuation = 1.0f / fDenominator;
|
|
}
|
|
// diffuse
|
|
CVec3 cDiffuse(fDotProduct * Light[c_nLightDiffuse + 0] * cDiffuseColor[0],
|
|
fDotProduct * Light[c_nLightDiffuse + 1] * cDiffuseColor[1],
|
|
fDotProduct * Light[c_nLightDiffuse + 2] * cDiffuseColor[2]);
|
|
|
|
cColor += cEmissive + (cAmbient + cDiffuse) * fAttenuation;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clamp color
|
|
Clamp(cColor[0], 0.0f, 1.0f);
|
|
Clamp(cColor[1], 0.0f, 1.0f);
|
|
Clamp(cColor[2], 0.0f, 1.0f);
|
|
|
|
if (m_eStaticLightingStyle & CSpeedTreeRT::SLS_USE_LIGHT_SOURCES)
|
|
(*i)->SetColor(cColor, false);
|
|
if (m_eStaticLightingStyle & CSpeedTreeRT::SLS_SIMULATE_SHADOWS)
|
|
(*i)->AdjustStaticLighting(cTreeCenter, cDominantLight, m_fLeafLightingAdjustmentScalar);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::SetLightAttributes definition
|
|
|
|
void CLightingEngine::SetLightAttributes(unsigned int nLightIndex, const float* pAttributes)
|
|
{
|
|
st_assert(nLightIndex < c_nMaxLights);
|
|
st_assert(pAttributes);
|
|
|
|
memcpy(m_afLightAttributes[nLightIndex], pAttributes, c_nLightParamSize * sizeof(float));
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::Save definition
|
|
|
|
void CLightingEngine::Save(CTreeFileAccess& cFile)
|
|
{
|
|
cFile.SaveToken(File_BeginLightingInfo);
|
|
|
|
cFile.SaveToken(File_BranchLightingMethod);
|
|
cFile.SaveInt(m_eBranchLightingMethod);
|
|
|
|
cFile.SaveToken(File_BranchMaterial);
|
|
int i;
|
|
for (i = 0; i < c_nMaterialParamSize; ++i)
|
|
cFile.SaveFloat(m_afBranchMaterial[i]);
|
|
|
|
cFile.SaveToken(File_LeafLightingMethod);
|
|
cFile.SaveInt(m_eLeafLightingMethod);
|
|
|
|
cFile.SaveToken(File_LeafMaterial);
|
|
for (i = 0; i < c_nMaterialParamSize; ++i)
|
|
cFile.SaveFloat(m_afLeafMaterial[i]);
|
|
|
|
cFile.SaveToken(File_LeafLightingAdjustment);
|
|
cFile.SaveFloat(m_fLeafLightingAdjustmentScalar);
|
|
|
|
cFile.SaveToken(File_StaticLightingStyle);
|
|
cFile.SaveInt(m_eStaticLightingStyle);
|
|
|
|
cFile.SaveToken(File_FrondLightingMethod);
|
|
cFile.SaveInt(m_eFrondLightingMethod);
|
|
|
|
cFile.SaveToken(File_FrondMaterial);
|
|
for (i = 0; i < c_nMaterialParamSize; ++i)
|
|
cFile.SaveFloat(m_afFrondMaterial[i]);
|
|
|
|
cFile.SaveToken(File_EndLightingInfo);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CLightingEngine::Parse definition
|
|
|
|
void CLightingEngine::Parse(CTreeFileAccess& cFile)
|
|
{
|
|
int nToken = cFile.ParseToken( );
|
|
do
|
|
{
|
|
switch (nToken)
|
|
{
|
|
case File_BranchLightingMethod:
|
|
m_eBranchLightingMethod = static_cast<LightMethod>(cFile.ParseInt( ));
|
|
break;
|
|
case File_BranchMaterial:
|
|
{
|
|
for (int i = 0; i < c_nMaterialParamSize; ++i)
|
|
m_afBranchMaterial[i] = cFile.ParseFloat( );
|
|
}
|
|
break;
|
|
case File_LeafLightingMethod:
|
|
m_eLeafLightingMethod = static_cast<LightMethod>(cFile.ParseInt( ));
|
|
break;
|
|
case File_LeafMaterial:
|
|
{
|
|
for (int i = 0; i < c_nMaterialParamSize; ++i)
|
|
m_afLeafMaterial[i] = cFile.ParseFloat( );
|
|
}
|
|
break;
|
|
case File_LeafLightingAdjustment:
|
|
m_fLeafLightingAdjustmentScalar = cFile.ParseFloat( );
|
|
break;
|
|
case File_StaticLightingStyle:
|
|
m_eStaticLightingStyle = static_cast<StaticStyle>(cFile.ParseInt( ));
|
|
break;
|
|
case File_FrondLightingMethod:
|
|
m_eFrondLightingMethod = static_cast<LightMethod>(cFile.ParseInt( ));
|
|
break;
|
|
case File_FrondMaterial:
|
|
{
|
|
for (int i = 0; i < c_nMaterialParamSize; ++i)
|
|
m_afFrondMaterial[i] = cFile.ParseFloat( );
|
|
}
|
|
break;
|
|
default:
|
|
throw(IdvFileError("malformed lighting information"));
|
|
}
|
|
nToken = cFile.ParseToken( );
|
|
} while (nToken != File_EndLightingInfo);
|
|
}
|