⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skydome.cpp

📁 天空绘制
💻 CPP
字号:
//-----------------------------------------------------------------------------
//
// @doc
//
// @module	SkyDome.cpp - Sky dome |
//
// This module contains the support for the sky dome.
//
// Copyright (c) 1999 - Descartes Systems Sciences, Inc.
//
// @end
//
// $History: DcComEngGenConfigurePage.h $
//
//-----------------------------------------------------------------------------

#include "stdafx.h"
#include "SkyDome.h"
#include "../_CoreLib/Matrix.h"
#include "../_CoreLib/Utility.h"
#include "Frustum.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//
// Force all render code into own seg
//

#pragma code_seg ("renderer_segment")

//-----------------------------------------------------------------------------
//
// @mfunc <c CSkyDome> constructor.
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

CSkyDome::CSkyDome () 
{

	//
	// Invoke the helper routine
	//

	Initialize ();
}

//-----------------------------------------------------------------------------
//
// @mfunc <c CSkyDome> destructor.
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

CSkyDome::~CSkyDome () 
{

	//
	// Invoke the helper routine
	//

	Destroy ();
}

//-----------------------------------------------------------------------------
//
// @mfunc Initialize the sky dome
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::Initialize () 
{

	//
	// Initialize the variables
	//

	m_nVertex = 0;
	m_pVertex = NULL;
	m_nResolution = 0;

	//
	// Initialize the sky light information
	//

	m_vBaseDayAmbient    = CVector3 (1, 1, 1);
	m_vBaseNightAmbient  = CVector3 (0, 0, 0);
	m_vBaseDayColor      = CVector3 (0, 0, 1);
	m_vBaseNightColor    = CVector3 (0, 0, 0);
}

//-----------------------------------------------------------------------------
//
// @mfunc Destroy the sky dome
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::Destroy () 
{

	//
	// Remove all bodies and clouds
	//

	m_sBodyList .RemoveAllChildren ();
	m_sCloudsList .RemoveAllChildren ();

	//
	// Deallocate the vertex array
	//

	if (m_pVertex)
		delete [] m_pVertex;

	//
	// Initialize
	//

	Initialize ();
}

//-----------------------------------------------------------------------------
//
// @mfunc Create a new sky dome
//
// @parm int | nResolution | Defines the number of subdivisions in a 90
//		degree slice of the sky dome.  This applies to the horizontal and
//		vertical aspects of the dome.
//
// @parm float | fVertSweep | Vertical sweep.  Must be greater than zero 
//		and less or equal to 90.  This defines the amount of the hemisphere
//		that will be included in the dome.
//
// @parm float | fRadius | Radius of the sky dome at the base
//
// @parm float | fHeightScale | Height scale of the sky dome.  Used to either
//		increase or decrease the height of the dome after generation.
//
// @parm const CVector3 & | vOrigin | Origin of the center of the sky dome.
//		Usually, the sky dome is place slightly below the landscape.
//
// @parm const CVector3 & | vDayAmbient | Base ambient color for the sun light.
//
// @parm const CVector3 & | vNightAmbient | Base ambient color for the night light.
//
// @parm const CVector3 & | vDayColor | Base color for the day sky
//
// @parm const CVector3 & | vNightColor | Base color for the night sky
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::Create (int nResolution, float fVertSweep, float fRadius, 
		float fHeightScale, const CVector3 &vOrigin, const CVector3 &vDayAmbient,
		const CVector3 &vNightAmbient, const CVector3 &vDayColor,
		const CVector3 &vNightColor)
{
	//
	// Validate the arguments
	//

	_ASSERT (nResolution > 0 && fRadius > 0);
	_ASSERT (fVertSweep > 0 && fVertSweep <= 90);

	//
	// Destroy the old dome
	//

	Destroy ();

	//
	// Save the generation arguments
	//

	m_nResolution = nResolution;
	m_fVertSweep = fVertSweep;
	m_fRadius = fRadius;
	m_fHeightScale = fHeightScale;
	m_vOrigin = vOrigin;
	m_vBaseDayAmbient = vDayAmbient;
	m_vBaseNightAmbient = vNightAmbient;
	m_vBaseDayColor = vDayColor;
	m_vBaseNightColor = vNightColor;


	//
	// Compute the number of vertices
	//

	m_nVertex = 1 + 4 * nResolution * nResolution;

	//
	// Allocate the buffer to contain vertices
	//

	m_pVertex = new _Vertex [m_nVertex];


	//
	// Adjust the radius based on the vertical sweep
	//

	float fRadAngle = (90 - fVertSweep) / 180 * PI;
	fRadius /= cos (fRadAngle);

	//
	// Compute the z adjustment
	//

	float fZAdj = fRadius * sin (fRadAngle);

	//
	// Start the vertex list with the very top of the dome
	//

	m_pVertex [0] .vVertex = CVector3 (0, 0, 
		(fRadius - fZAdj) * fHeightScale) + vOrigin;

	//
	// From the resolution, compute the angular sweep of one section
	// of the dome
	//

	float fHorzSweep = 90.0 / nResolution;

	//
	// Adjust the vertical resolution
	//

	fVertSweep /= nResolution;
	
	//
	// Starting from the top, populate with nResolution number of rings
	//

	int nVertex = 1;
	for (int i = 0; i < nResolution; i++)
	{

		//
		// Compute the vertex that will be rotated around to make a ring
		//

		CVector3 vPoint (0, 0, fRadius);
		CMatrix m;
		m .MakeHPR (0, fVertSweep * (i + 1), 0);
		m .PreMultiply (vPoint, vPoint);
		_ASSERT (vPoint .m_z >= fZAdj - ON_EPSILON);
		vPoint .m_z = (vPoint .m_z - fZAdj) * fHeightScale;

		//
		// Loop through the ring creating the points
		//

		for (int j = 0; j < nResolution * 4; j++)
		{

			//
			// Map the point
			//

			m .SetHPR (fHorzSweep * j, 0, 0);
			m .PreMultiply (vPoint, m_pVertex [nVertex] .vVertex);
			m_pVertex [nVertex] .vVertex += vOrigin;
			nVertex++;
		}
	}

	//
	// All done
	//

	return;
}

//-----------------------------------------------------------------------------
//
// @mfunc Map the vertices
//
// @parm const CMatrix & | sModelToEye | Matrix used to map the sky dome
//		vertices to the eye space.  The translation part of the matrix is
//		not used.
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::MapVertices (const CMatrix &sModelToEye)
{


	//
	// Loop through the vertices
	//

	for (int i = 0; i < m_nVertex; i++)
	{

		//
		// Map
		//

		sModelToEye .PreNormalMultiply (
//		sModelToEye .PreMultiply (
			m_pVertex [i] .vVertex,
			m_pVertex [i] .vMapVertex);
//		m_pVertex [i] .vMapVertex .m_y += sModelToEye .m_m [3] [1];
	}
}

//-----------------------------------------------------------------------------
//
// @mfunc Compute the position of the sky objects
//
// @parm float | fTimeInDays | The current time in days
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::ComputePositions (float fTimeInDays)
{

	CSkyBody *pSun = NULL;

	//
	// Loop through the sky bodies computing positions
	//

	CDoubleLink *pStart = &m_sBodyList;
	for (CDoubleLink *pLink = pStart ->GetNext (); 
	pLink != pStart; pLink = pLink ->GetNext ())
	{

		//
		// Get a pointer to the body
		//

		CSkyBody *pBody = CSkyBody::FromLink (pLink);

		//
		// Compute the position.  If the time is -1, just compute
		// a constant position in the sky
		//

		if (fTimeInDays == -1)
		{
			CVector3 vNormal (1, -1, 1);
			vNormal .Normalize ();
			pBody ->SetPosition (vNormal * pBody ->GetA ());
		}
		else
		{
			pBody ->ComputePosition (fTimeInDays);
		}

		//
		// If this is a sun, save the pointer
		//

		if (pBody ->GetType () == CSkyBody::Type_Sun)
			pSun = pBody;
	}

	//
	// If a sun was found, then compute the sun light
	//

	float fDayFactor;
	if (pSun)
	{
		//
		// Get the normal
		//

		CVector3 vNormal (pSun ->GetNormal ());
		m_vCurrentSunNormal = vNormal;

		//
		// Compute the angle of the sun
		//

		float fSunAngle = asin (vNormal .m_z) * 180.0f / PI;
		bool fSunrise = vNormal .m_x >= 0.0;

		//
		// Compute the day factor
		//

		if (fTimeInDays != -1) 
		{
			if (fSunAngle > 20.0) 
			{
				fDayFactor = 1.0;
				m_vCurrentSkyColor = m_vBaseDayColor;
			} 
			else if (fSunAngle >= -10.0)
			{
				fDayFactor = (fSunAngle + 10.0f) / 30.0f;
			} 
			else 
			{
				fDayFactor = 0.0;
				m_vCurrentSkyColor = m_vBaseNightColor;
			}
		}
		else
		{
			fDayFactor = 1.0;
			m_vCurrentSkyColor = m_vBaseDayColor;
		}

		//
		// Compute the sky color
		//

		CVector3 vDeltaSky (m_vBaseDayColor - m_vBaseNightColor);
		m_vCurrentSkyColor = m_vBaseNightColor + vDeltaSky * fDayFactor;

		//
		// Compute the ambient
		//

		CVector3 vDeltaAmbient (m_vBaseDayAmbient - m_vBaseNightAmbient);
		m_vCurrentAmbient = m_vBaseNightAmbient + vDeltaAmbient * fDayFactor;
	}

	//
	// If not, just used the default values
	//

	else
	{
		m_vCurrentSunNormal = CVector3 (1,0,1);
		fDayFactor = 1.0;
		m_vCurrentAmbient = m_vBaseDayAmbient;
		m_vCurrentSkyColor = m_vBaseDayColor;
	}

	//
	// Force the w value for the colors to 1
	//

	m_vCurrentAmbient .m_w = 1.0;
	m_vCurrentSkyColor .m_w = 1.0;

	//
	// Compute the positions of the clouds
	//

	pStart = &m_sCloudsList;
	for (pLink = pStart ->GetNext (); 
	pLink != pStart; pLink = pLink ->GetNext ())
	{

		//
		// Get a pointer to the clouds
		//

		CSkyClouds *pClouds = CSkyClouds::FromLink (pLink);

		//
		// Compute the position.
		//

		pClouds ->ComputePosition (fTimeInDays, fDayFactor);
	}

	//
	// Compute the colors of the bodies
	//

	pStart = &m_sBodyList;
	for (pLink = pStart ->GetNext (); 
	pLink != pStart; pLink = pLink ->GetNext ())
	{

		//
		// Get a pointer to the body
		//

		CSkyBody *pBody = CSkyBody::FromLink (pLink);

		//
		// Compute the color.
		//

		pBody ->ComputeColor (fDayFactor);
	}

}

//-----------------------------------------------------------------------------
//
// @mfunc Prepare a sky dome
//
//		Prepare a sky dome.
//
// @rdesc None.
//
//-----------------------------------------------------------------------------

void CSkyDome::Prep ()
{

	//
	// Loop through the bodies in the sky dome
	//

	CDoubleLink *pStart = &m_sBodyList;
	for (CDoubleLink *pLink = pStart ->GetNext (); 
	pLink != pStart; pLink = pLink ->GetNext ())
	{
		CSkyBody *pBody = CSkyBody::FromLink (pLink);
		pBody ->Prep ();
	}

	//
	// Loop through the clounds in the sky dome
	//

	pStart = &m_sCloudsList;
	for (pLink = pStart ->GetNext (); 
	pLink != pStart; pLink = pLink ->GetNext ())
	{
		CSkyClouds *pClouds = CSkyClouds::FromLink (pLink);
		pClouds ->Prep ();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -