686 lines
18 KiB
C++
686 lines
18 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Renders a cone for spotlight entities. Only renders when the parent
|
|
// entity is selected.
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "stdafx.h"
|
|
#include "Box3D.h"
|
|
#include "fgdlib/HelperInfo.h"
|
|
#include "MapDefs.h" // dvs: For COORD_NOTINIT
|
|
#include "MapEntity.h"
|
|
#include "MapLightCone.h"
|
|
#include "Render3D.h"
|
|
#include "Material.h"
|
|
#include "materialsystem/imaterialsystem.h"
|
|
#include "TextureSystem.h"
|
|
#include "hammer.h"
|
|
#include "Options.h"
|
|
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
#define NUM_LIGHTCONE_ZONES 5
|
|
|
|
|
|
IMPLEMENT_MAPCLASS(CMapLightCone)
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Factory function. Used for creating a CMapLightCone helper from a
|
|
// set of string parameters from the FGD file.
|
|
// Input : *pInfo - Pointer to helper info class which gives us information
|
|
// about how to create the helper.
|
|
// Output : Returns a pointer to the helper, NULL if an error occurs.
|
|
//-----------------------------------------------------------------------------
|
|
CMapClass *CMapLightCone::Create(CHelperInfo *pHelperInfo, CMapEntity *pParent)
|
|
{
|
|
CMapLightCone *new1=new CMapLightCone;
|
|
if( new1 != NULL )
|
|
{
|
|
//
|
|
// The first parameter should be the inner fov key name. If it isn't
|
|
// there we assume "_inner_cone".
|
|
//
|
|
const char *pszKeyName = pHelperInfo->GetParameter(0);
|
|
if (pszKeyName != NULL)
|
|
{
|
|
strcpy(new1->m_szInnerConeKeyName, pszKeyName);
|
|
}
|
|
else
|
|
{
|
|
strcpy(new1->m_szInnerConeKeyName, "_inner_cone");
|
|
}
|
|
|
|
//
|
|
// The second parameter should be the outer fov key name. If it isn't
|
|
// there we assume "_cone".
|
|
//
|
|
pszKeyName = pHelperInfo->GetParameter(1);
|
|
if (pszKeyName != NULL)
|
|
{
|
|
strcpy(new1->m_szOuterConeKeyName, pszKeyName);
|
|
}
|
|
else
|
|
{
|
|
strcpy(new1->m_szOuterConeKeyName, "_cone");
|
|
}
|
|
|
|
//
|
|
// The third parameter should be the color of the light. If it isn't
|
|
// there we assume "_light".
|
|
//
|
|
pszKeyName = pHelperInfo->GetParameter(2);
|
|
if (pszKeyName != NULL)
|
|
{
|
|
strcpy(new1->m_szColorKeyName, pszKeyName);
|
|
}
|
|
else
|
|
{
|
|
strcpy(new1->m_szColorKeyName, "_light");
|
|
}
|
|
|
|
pszKeyName = pHelperInfo->GetParameter(3);
|
|
if (pszKeyName != NULL)
|
|
{
|
|
new1->m_flPitchScale = Q_atof( pszKeyName );
|
|
}
|
|
else
|
|
{
|
|
new1->m_flPitchScale = 1.0f;
|
|
}
|
|
}
|
|
return new1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
CMapLightCone::CMapLightCone(void)
|
|
{
|
|
m_fQuadraticAttn = 1;
|
|
m_fLinearAttn = 0;
|
|
m_fConstantAttn = 0;
|
|
m_bPitchSet = false;
|
|
m_fPitch = 0;
|
|
m_fFocus = 1;
|
|
m_flPitchScale = 1;
|
|
|
|
m_fBrightness = 100;
|
|
m_fInnerConeAngle = 0;
|
|
m_fOuterConeAngle = 45;
|
|
|
|
m_fFiftyPercentDistance = -1; // disabled - use attenuation
|
|
m_Angles.Init();
|
|
SignalUpdate( EVTYPE_LIGHTING_CHANGED );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Destructor. Deletes faces allocated by BuildCone.
|
|
//-----------------------------------------------------------------------------
|
|
CMapLightCone::~CMapLightCone(void)
|
|
{
|
|
for (int i = 0; i < m_Faces.Count(); i++)
|
|
{
|
|
CMapFace *pFace = m_Faces.Element(i);
|
|
delete pFace;
|
|
}
|
|
SignalUpdate( EVTYPE_LIGHTING_CHANGED );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Builds the light cone faces in local space. Does NOT call CalcBounds,
|
|
// because that CalcBounds updates the parent, which causes problems
|
|
// in the undo system.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::BuildCone(void)
|
|
{
|
|
//
|
|
// Delete the current face list.
|
|
//
|
|
for (int i = 0; i < m_Faces.Count(); i++)
|
|
{
|
|
CMapFace *pFace = m_Faces.Element(i);
|
|
delete pFace;
|
|
}
|
|
m_Faces.RemoveAll();
|
|
|
|
//
|
|
// Make sure at least one of the lighting coefficients is nonzero.
|
|
//
|
|
if ((m_fQuadraticAttn == 0) && (m_fLinearAttn == 0) && (m_fConstantAttn == 0))
|
|
{
|
|
m_fConstantAttn = 1;
|
|
}
|
|
|
|
//
|
|
// Solve for the lighting scale factor by which the brightness will be multiplied.
|
|
//
|
|
float fScaleFactor = m_fQuadraticAttn * 10000 + m_fLinearAttn * 100 + m_fConstantAttn;
|
|
if (fScaleFactor == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Calculate the distances from the light origin to the various zones.
|
|
//
|
|
float fOffsetDist = 0;
|
|
// Constant attenuation factor doesn't actually offset the cone yet. If it does, uncomment this:
|
|
//SolveQuadratic(fOffsetDist, 0, m_fQuadraticAttn, m_fLinearAttn, -m_fConstantAttn);
|
|
|
|
float fZoneDist[NUM_LIGHTCONE_ZONES];
|
|
memset( fZoneDist, 0, sizeof( fZoneDist ) );
|
|
fZoneDist[0] = 0;
|
|
SolveQuadratic(fZoneDist[1], 0.25 * fScaleFactor, m_fQuadraticAttn, m_fLinearAttn, m_fConstantAttn);
|
|
SolveQuadratic(fZoneDist[2], fScaleFactor, m_fQuadraticAttn, m_fLinearAttn, m_fConstantAttn);
|
|
SolveQuadratic(fZoneDist[3], 4 * fScaleFactor, m_fQuadraticAttn, m_fLinearAttn, m_fConstantAttn);
|
|
SolveQuadratic(fZoneDist[4], Options.view3d.fLightConeLength * fScaleFactor, m_fQuadraticAttn, m_fLinearAttn, m_fConstantAttn);
|
|
|
|
//
|
|
// there's no cone if it's greater then 90 degrees
|
|
//
|
|
if (m_fOuterConeAngle < 90)
|
|
{
|
|
|
|
//
|
|
// Calculate the cone radius at each zone.
|
|
//
|
|
float fZoneRadius[NUM_LIGHTCONE_ZONES];
|
|
for (int i = 0; i < NUM_LIGHTCONE_ZONES; i++)
|
|
{
|
|
fZoneRadius[i] = (fOffsetDist + fZoneDist[i]) * tan(DEG2RAD(m_fOuterConeAngle));
|
|
}
|
|
|
|
//
|
|
// Build the new face list using the new parameters.
|
|
//
|
|
float fStepSize = 360.0 / 15.0;
|
|
for (int nZone = 0; nZone < NUM_LIGHTCONE_ZONES - 1; nZone++)
|
|
{
|
|
float fSin0 = 0;
|
|
float fCos0 = 1;
|
|
|
|
float fTopDist = fZoneDist[nZone];
|
|
float fBottomDist = fZoneDist[nZone + 1];
|
|
|
|
float fTopRadius = fZoneRadius[nZone];
|
|
float fBottomRadius = fZoneRadius[nZone + 1];
|
|
|
|
for (int fAngle = fStepSize; fAngle <= 361; fAngle += fStepSize)
|
|
{
|
|
float fSin1 = sin(DEG2RAD(fAngle));
|
|
float fCos1 = cos(DEG2RAD(fAngle));
|
|
|
|
Vector Points[4];
|
|
|
|
Points[0][2] = fBottomRadius * fCos1;
|
|
Points[0][1] = fBottomRadius * fSin1;
|
|
Points[0][0] = fBottomDist;
|
|
|
|
Points[1][2] = fBottomRadius * fCos0;
|
|
Points[1][1] = fBottomRadius * fSin0;
|
|
Points[1][0] = fBottomDist;
|
|
|
|
Points[2][2] = fTopRadius * fCos0;
|
|
Points[2][1] = fTopRadius * fSin0;
|
|
Points[2][0] = fTopDist;
|
|
|
|
int nPoints = 3;
|
|
if (fTopRadius != 0)
|
|
{
|
|
Points[3][2] = fTopRadius * fCos1;
|
|
Points[3][1] = fTopRadius * fSin1;
|
|
Points[3][0] = fTopDist;
|
|
nPoints = 4;
|
|
}
|
|
|
|
CMapFace *pFace = new CMapFace;
|
|
pFace->SetRenderColor(r * (1 - nZone / (float)NUM_LIGHTCONE_ZONES), g * (1 - nZone / (float)NUM_LIGHTCONE_ZONES), b * (1 - nZone / (float)NUM_LIGHTCONE_ZONES));
|
|
pFace->SetRenderAlpha(180);
|
|
pFace->CreateFace(Points, nPoints);
|
|
pFace->RenderUnlit(true);
|
|
m_Faces.AddToTail(pFace);
|
|
|
|
fSin0 = fSin1;
|
|
fCos0 = fCos1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Lobe's aren't defined for > 90
|
|
//
|
|
if (m_fOuterConeAngle > 90)
|
|
return;
|
|
|
|
//
|
|
// Build the a face list that shows light-angle falloff
|
|
//
|
|
float fStepSize = 360.0 / 15.0;
|
|
float fPitchStepSize = 90.0 / 15.0;
|
|
float fFocusRadius0 = 0;
|
|
float fFocusDist0 = fZoneDist[1];
|
|
float fInnerDot = cos(DEG2RAD(m_fInnerConeAngle));
|
|
float fOuterDot = cos(DEG2RAD(m_fOuterConeAngle));
|
|
|
|
for (float fPitch = fPitchStepSize; fPitch < m_fOuterConeAngle + fPitchStepSize; fPitch += fPitchStepSize)
|
|
{
|
|
float fSin0 = 0;
|
|
float fCos0 = 1;
|
|
|
|
// clamp to edge of cone
|
|
if (fPitch > m_fOuterConeAngle)
|
|
fPitch = m_fOuterConeAngle;
|
|
|
|
float fIllumination = 0;
|
|
if (fPitch <= m_fInnerConeAngle)
|
|
{
|
|
fIllumination = 1.0;
|
|
}
|
|
else
|
|
{
|
|
float fPitchDot = cos(DEG2RAD(fPitch));
|
|
|
|
fIllumination = (fPitchDot - fOuterDot) / (fInnerDot - fOuterDot);
|
|
|
|
if ((m_fFocus != 1) && (m_fFocus != 0))
|
|
{
|
|
fIllumination = pow( fIllumination, m_fFocus );
|
|
}
|
|
}
|
|
|
|
// cosine falloff ^ exponent
|
|
|
|
// draw as lobe
|
|
float fFocusDist1 = cos(DEG2RAD(fPitch)) * fIllumination * fZoneDist[1];
|
|
float fFocusRadius1 = sin(DEG2RAD(fPitch)) * fIllumination * fZoneDist[1];
|
|
|
|
// draw as disk
|
|
// float fFocusDist1 = fZoneDist[1];
|
|
// float fFocusRadius1 = sin(DEG2RAD(fPitch)) * fZoneRadius[1] / sin(DEG_RAD * m_fConeAngle);
|
|
|
|
for (int fAngle = fStepSize; fAngle <= 361; fAngle += fStepSize)
|
|
{
|
|
float fSin1 = sin(DEG2RAD(fAngle));
|
|
float fCos1 = cos(DEG2RAD(fAngle));
|
|
|
|
Vector Points[4];
|
|
|
|
Points[0][2] = fFocusRadius1 * fCos0;
|
|
Points[0][1] = fFocusRadius1 * fSin0;
|
|
Points[0][0] = fFocusDist1;
|
|
|
|
Points[1][2] = fFocusRadius1 * fCos1;
|
|
|
|
Points[1][1] = fFocusRadius1 * fSin1;
|
|
Points[1][0] = fFocusDist1;
|
|
|
|
Points[2][2] = fFocusRadius0 * fCos1;
|
|
Points[2][1] = fFocusRadius0 * fSin1;
|
|
Points[2][0] = fFocusDist0;
|
|
|
|
int nPoints = 3;
|
|
if (fFocusRadius0 != 0)
|
|
{
|
|
Points[3][2] = fFocusRadius0 * fCos0;
|
|
Points[3][1] = fFocusRadius0 * fSin0;
|
|
Points[3][0] = fFocusDist0;
|
|
nPoints = 4;
|
|
}
|
|
|
|
CMapFace *pFace = new CMapFace;
|
|
pFace->SetRenderColor(r * fIllumination, g * fIllumination, b * fIllumination);
|
|
pFace->SetRenderAlpha(180);
|
|
pFace->CreateFace(Points, nPoints);
|
|
pFace->RenderUnlit(true);
|
|
m_Faces.AddToTail(pFace);
|
|
|
|
fSin0 = fSin1;
|
|
fCos0 = fCos1;
|
|
}
|
|
fFocusRadius0 = fFocusRadius1;
|
|
fFocusDist0 = fFocusDist1;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : bFullUpdate -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::CalcBounds(BOOL bFullUpdate)
|
|
{
|
|
CMapClass::CalcBounds(bFullUpdate);
|
|
|
|
//
|
|
// HACK: Update our origin to stick to our parent.
|
|
//
|
|
if (m_pParent != NULL)
|
|
{
|
|
GetParent()->GetOrigin(m_Origin);
|
|
}
|
|
|
|
//
|
|
// Pretend to be very small for the 2D view. Won't be necessary when 2D
|
|
// rendering is done in the map classes.
|
|
//
|
|
m_Render2DBox.ResetBounds();
|
|
m_Render2DBox.UpdateBounds(m_Origin);
|
|
|
|
SetCullBoxFromFaceList( &m_Faces );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : Angles -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::GetAngles(QAngle &Angles)
|
|
{
|
|
Angles = m_Angles;
|
|
|
|
if (m_bPitchSet)
|
|
{
|
|
Angles[PITCH] = m_fPitch;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : CMapClass
|
|
//-----------------------------------------------------------------------------
|
|
CMapClass *CMapLightCone::Copy(bool bUpdateDependencies)
|
|
{
|
|
CMapLightCone *pCopy = new CMapLightCone;
|
|
|
|
if (pCopy != NULL)
|
|
{
|
|
pCopy->CopyFrom(this, bUpdateDependencies);
|
|
}
|
|
|
|
return(pCopy);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : pObject -
|
|
// Output : CMapClass
|
|
//-----------------------------------------------------------------------------
|
|
CMapClass *CMapLightCone::CopyFrom(CMapClass *pObject, bool bUpdateDependencies)
|
|
{
|
|
Assert(pObject->IsMapClass(MAPCLASS_TYPE(CMapLightCone)));
|
|
CMapLightCone *pFrom = (CMapLightCone *)pObject;
|
|
|
|
CMapClass::CopyFrom(pObject, bUpdateDependencies);
|
|
|
|
m_fBrightness = pFrom->m_fBrightness;
|
|
|
|
m_fQuadraticAttn = pFrom->m_fQuadraticAttn;
|
|
m_fLinearAttn = pFrom->m_fLinearAttn;
|
|
m_fConstantAttn = pFrom->m_fConstantAttn;
|
|
m_flPitchScale = pFrom->m_flPitchScale;
|
|
|
|
m_fInnerConeAngle = pFrom->m_fInnerConeAngle;
|
|
m_fOuterConeAngle = pFrom->m_fOuterConeAngle;
|
|
|
|
m_Angles = pFrom->m_Angles;
|
|
|
|
m_bPitchSet = pFrom->m_bPitchSet;
|
|
m_fPitch = pFrom->m_fPitch;
|
|
|
|
m_fFocus = pFrom->m_fFocus;
|
|
|
|
m_fFiftyPercentDistance = pFrom->m_fFiftyPercentDistance;
|
|
m_fZeroPercentDistance = pFrom->m_fZeroPercentDistance;
|
|
m_LightColor = pFrom->m_LightColor;
|
|
|
|
Q_strncpy( m_szColorKeyName, pFrom->m_szColorKeyName, sizeof( m_szColorKeyName ) );
|
|
Q_strncpy( m_szInnerConeKeyName, pFrom->m_szInnerConeKeyName, sizeof( m_szInnerConeKeyName ) );
|
|
Q_strncpy( m_szOuterConeKeyName, pFrom->m_szOuterConeKeyName, sizeof( m_szOuterConeKeyName ) );
|
|
|
|
BuildCone();
|
|
|
|
SignalUpdate( EVTYPE_LIGHTING_CHANGED );
|
|
return(this);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Notifies that this object's parent entity has had a key value change.
|
|
// Input : szKey - The key that changed.
|
|
// szValue - The new value of the key.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::OnParentKeyChanged(const char *szKey, const char *szValue)
|
|
{
|
|
bool bRebuild = true;
|
|
|
|
if (!stricmp(szKey, "angles"))
|
|
{
|
|
sscanf(szValue, "%f %f %f", &m_Angles[PITCH], &m_Angles[YAW], &m_Angles[ROLL]);
|
|
}
|
|
else if (!stricmp(szKey, m_szColorKeyName))
|
|
{
|
|
int nRed;
|
|
int nGreen;
|
|
int nBlue;
|
|
int nBrightness;
|
|
sscanf(szValue, "%d %d %d %d", &nRed, &nGreen, &nBlue, &nBrightness);
|
|
|
|
r = m_LightColor.x = nRed;
|
|
g = m_LightColor.y = nGreen;
|
|
b = m_LightColor.z = nBlue;
|
|
m_fBrightness = nBrightness;
|
|
}
|
|
else if (!stricmp(szKey, "pitch"))
|
|
{
|
|
// Pitch
|
|
m_bPitchSet = true;
|
|
m_fPitch = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_constant_attn"))
|
|
{
|
|
// Constant attenuation
|
|
m_fConstantAttn = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_linear_attn"))
|
|
{
|
|
// Linear attenuation
|
|
m_fLinearAttn = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_quadratic_attn"))
|
|
{
|
|
// Quadratic attenuation
|
|
m_fQuadraticAttn = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_exponent"))
|
|
{
|
|
// Focus
|
|
m_fFocus = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_fifty_percent_distance"))
|
|
{
|
|
// Focus
|
|
m_fFiftyPercentDistance = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, "_zero_percent_distance"))
|
|
{
|
|
// Focus
|
|
m_fZeroPercentDistance = atof(szValue);
|
|
}
|
|
else if (!stricmp(szKey, m_szInnerConeKeyName) || !stricmp(szKey, m_szOuterConeKeyName))
|
|
{
|
|
// check both of these together since they might be the same key.
|
|
if( !stricmp(szKey, m_szInnerConeKeyName ))
|
|
{
|
|
// Inner Cone angle
|
|
m_fInnerConeAngle = atof(szValue);
|
|
}
|
|
if( !stricmp(szKey, m_szOuterConeKeyName ))
|
|
{
|
|
// Outer Cone angle
|
|
m_fOuterConeAngle = atof(szValue);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRebuild = false;
|
|
}
|
|
|
|
if (bRebuild)
|
|
{
|
|
SignalUpdate( EVTYPE_LIGHTING_CHANGED );
|
|
BuildCone();
|
|
PostUpdate(Notify_Changed);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Called after the entire map has been loaded. This allows the object
|
|
// to perform any linking with other map objects or to do other operations
|
|
// that require all world objects to be present.
|
|
// Input : pWorld - The world that we are in.
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::PostloadWorld(CMapWorld *pWorld)
|
|
{
|
|
CMapClass::PostloadWorld(pWorld);
|
|
|
|
BuildCone();
|
|
SignalUpdate( EVTYPE_LIGHTING_CHANGED );
|
|
CalcBounds();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : pRender -
|
|
//-----------------------------------------------------------------------------
|
|
void CMapLightCone::Render3D(CRender3D *pRender)
|
|
{
|
|
if (m_pParent->IsSelected())
|
|
{
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
|
|
pRenderContext->MatrixMode(MATERIAL_MODEL);
|
|
pRenderContext->PushMatrix();
|
|
|
|
pRenderContext->Translate(m_Origin[0], m_Origin[1], m_Origin[2]);
|
|
|
|
QAngle Angles;
|
|
GetAngles(Angles);
|
|
|
|
pRenderContext->Rotate(Angles[YAW], 0, 0, 1);
|
|
pRenderContext->Rotate(m_flPitchScale * Angles[PITCH], 0, -1, 0);
|
|
pRenderContext->Rotate(Angles[ROLL], 1, 0, 0);
|
|
|
|
if (
|
|
(pRender->GetCurrentRenderMode() != RENDER_MODE_LIGHT_PREVIEW2) &&
|
|
(pRender->GetCurrentRenderMode() != RENDER_MODE_LIGHT_PREVIEW_RAYTRACED) &&
|
|
(GetSelectionState() != SELECT_MODIFY )
|
|
)
|
|
{
|
|
// Render the cone faces flatshaded.
|
|
pRender->PushRenderMode( RENDER_MODE_TRANSLUCENT_FLAT );
|
|
|
|
for (int i = 0; i < m_Faces.Count(); i++)
|
|
{
|
|
CMapFace *pFace = m_Faces.Element(i);
|
|
pFace->Render3D(pRender);
|
|
}
|
|
|
|
pRender->PopRenderMode();
|
|
}
|
|
|
|
//
|
|
// Render the cone faces in yellow wireframe (on top)
|
|
//
|
|
pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
|
|
|
|
for (int i = 0; i < m_Faces.Count(); i++)
|
|
{
|
|
CMapFace *pFace = m_Faces.Element(i);
|
|
pFace->Render3D(pRender);
|
|
}
|
|
|
|
//
|
|
// Restore the default rendering mode.
|
|
//
|
|
pRender->PopRenderMode();
|
|
|
|
pRenderContext->PopMatrix();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : File -
|
|
// bRMF -
|
|
// Output : int
|
|
//-----------------------------------------------------------------------------
|
|
int CMapLightCone::SerializeRMF(std::fstream &File, BOOL bRMF)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : File -
|
|
// bRMF -
|
|
// Output : int
|
|
//-----------------------------------------------------------------------------
|
|
int CMapLightCone::SerializeMAP(std::fstream &File, BOOL bRMF)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Solves a quadratic equation with the given coefficients.
|
|
// Input : x - Receives solution.
|
|
// y - Root to solve for.
|
|
// A, B, C - Quadratic, linear, and constant coefficients.
|
|
// Output : Returns true if a real solution was found, false if not.
|
|
//-----------------------------------------------------------------------------
|
|
bool CMapLightCone::SolveQuadratic(float &x, float y, float A, float B, float C)
|
|
{
|
|
C -= y;
|
|
|
|
if (A == 0)
|
|
{
|
|
if (B != 0)
|
|
{
|
|
x = -C / B;
|
|
return(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float fDeterminant = B * B - 4 * A * C;
|
|
if (fDeterminant > 0)
|
|
{
|
|
x = (-B + sqrt(fDeterminant)) / (2 * A);
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Never select anything because of this helper.
|
|
//-----------------------------------------------------------------------------
|
|
CMapClass *CMapLightCone::PrepareSelection(SelectMode_t eSelectMode)
|
|
{
|
|
return NULL;
|
|
}
|