コード例 #1
0
ファイル: XFileDemo.cpp プロジェクト: kasicass/introdx9
XFileDemo::XFileDemo(HINSTANCE hInstance, std::wstring winCaption)
	: D3DApp(hInstance, winCaption)
{
	InitAllVertexDeclarations();

	mGfxStats = new GfxStats();

	mCameraRadius    = 12.0f;
	mCameraRotationY = 1.2f * D3DX_PI;
	mCameraHeight    = 6.0f;

	mLight.dirW    = D3DXVECTOR3(0.0f, 1.0f, 2.0f);
	D3DXVec3Normalize(&mLight.dirW, &mLight.dirW);
	mLight.ambient = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
	mLight.diffuse = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
	mLight.spec    = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);

	LoadXFile(L"../src/chap14/XFileDemo/Dwarf.x", &mMesh, mMtrl, mTex);
	D3DXMatrixIdentity(&mWorld);

	HR(D3DXCreateTextureFromFile(gd3dDevice, L"../src/chap14/XFileDemo/whitetex.dds", &mWhiteTex));

	mGfxStats->addVertices(mMesh->GetNumVertices());
	mGfxStats->addTriangles(mMesh->GetNumFaces());

	buildFX();
	
	onResetDevice();
}
コード例 #2
0
ファイル: PropsDemo.cpp プロジェクト: chenbk85/3dlearn
void PropsDemo::buildCastle()
{
	// Load the castle mesh.
	D3DXMATRIX T, Ry;
	LoadXFile("castle.x", &mCastle.mesh, mCastle.mtrls, mCastle.textures);

	// Compute castle AABB.
	VertexPNT* v = 0;
	HR(mCastle.mesh->LockVertexBuffer(0, (void**)&v));
	HR(D3DXComputeBoundingBox(&v->pos, mCastle.mesh->GetNumVertices(),
		mCastle.mesh->GetNumBytesPerVertex(), 
		&mCastle.box.minPt, &mCastle.box.maxPt));
	HR(mCastle.mesh->UnlockVertexBuffer());

	// Manually set castle materials.
	for(UINT i = 0; i < mCastle.mtrls.size(); ++i)
	{
		mCastle.mtrls[i].ambient = WHITE*0.5f;
		mCastle.mtrls[i].diffuse = WHITE;
		mCastle.mtrls[i].spec = WHITE*0.8f;
		mCastle.mtrls[i].specPower = 28.0f;
	}

	// Build castle's world matrix.
	D3DXMatrixRotationY(&Ry, D3DX_PI);
	D3DXMatrixTranslation(&T, 8.0f, 35.0f, -80.0f);
	mCastleWorld = Ry*T;
}
コード例 #3
0
ファイル: ProjTexDemo.cpp プロジェクト: chenbk85/3dlearn
ProjTexDemo::ProjTexDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
	if(!checkDeviceCaps())
	{
		MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
		PostQuitMessage(0);
	}

	InitAllVertexDeclarations();

	mGfxStats = new GfxStats();
	mSky = new Sky("grassenvmap1024.dds", 10000.0f);

	LoadXFile("shapes.x", &mSceneMesh, mSceneMtrls, mSceneTextures);
	D3DXMatrixIdentity(&mSceneWorld);

	HR(D3DXCreateTextureFromFile(gd3dDevice, "whitetex.dds", &mWhiteTex));
	HR(D3DXCreateTextureFromFile(gd3dDevice, "skull.dds", &mSkullTex));

	// Build light projective texture matrix.
	D3DXMATRIX lightView;
	D3DXVECTOR3 lightPosW(60.0f, 90.0f, 0.0f);
	D3DXVECTOR3 lightTargetW(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 lightUpW(0.0f, 1.0f, 0.0f);
	D3DXMatrixLookAtLH(&lightView, &lightPosW, &lightTargetW, &lightUpW);

	D3DXMATRIX lightLens;
	float lightFOV = D3DX_PI*0.30f;
	D3DXMatrixPerspectiveFovLH(&lightLens, lightFOV, 1.0f, 1.0f, 200.0f);

	mLightWVP = mSceneWorld*lightView*lightLens;

	// Setup a spotlight corresponding to the projector.
	D3DXVECTOR3 lightDirW = lightTargetW - lightPosW;
	D3DXVec3Normalize(&lightDirW, &lightDirW);
	mLight.posW      = lightPosW;
	mLight.dirW      = lightDirW;
	mLight.ambient   = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
	mLight.diffuse   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	mLight.spec      = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
	mLight.spotPower = 8.0f;

	// Initialize camera.
	gCamera->pos().y = 100.0f;
	gCamera->pos().z = -100.0f;
	gCamera->setSpeed(50.0f);

	mGfxStats->addVertices(mSceneMesh->GetNumVertices());
	mGfxStats->addTriangles(mSceneMesh->GetNumFaces());

	mGfxStats->addVertices(mSky->getNumVertices());
	mGfxStats->addTriangles(mSky->getNumTriangles());

	buildFX();

	onResetDevice();
}
コード例 #4
0
ファイル: RobotArmDemo.cpp プロジェクト: nguyenkim495/KidBuu
RobotArmDemo::RobotArmDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
	if(!checkDeviceCaps())
	{
		MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
		PostQuitMessage(0);
	}

	InitAllVertexDeclarations();

	mGfxStats = new GfxStats();
	
	// Initialize Camera Settings
	mCameraRadius    = 9.0f;
	mCameraRotationY = 1.5f * D3DX_PI;
	mCameraHeight    = 0.0f;

	// Setup a directional light.
	mLight.dirW    = D3DXVECTOR3(0.0f, 1.0f, 2.0f);
	D3DXVec3Normalize(&mLight.dirW, &mLight.dirW);
	mLight.ambient = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
	mLight.diffuse = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);
	mLight.spec    = D3DXCOLOR(0.8f, 0.8f, 0.8f, 1.0f);

	// Load the bone .X file mesh.
	LoadXFile("bone.x", &mBoneMesh, mMtrl, mTex);
	D3DXMatrixIdentity(&mWorld);

	// Create the white dummy texture.
	HR(D3DXCreateTextureFromFile(gd3dDevice, "whitetex.dds", &mWhiteTex));

	// Initialize the bones relative to their parent frame.
	// The root is special--its parent frame is the world space.
	// As such, its position and angle are ignored--its 
	// toWorldXForm should be set explicitly (that is, the world
	// transform of the entire skeleton).
	//
	// *------*------*------*------
	//    0      1      2      3

	for(int i = 1; i < NUM_BONES; ++i) // Ignore root.
	{
		// Describe each bone frame relative to its parent frame.
		mBones[i].pos    = D3DXVECTOR3(2.0f, 0.0f, 0.0f);
		mBones[i].zAngle = 0.0f;
	}
	// Root frame at center of world.
	mBones[0].pos    = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	mBones[0].zAngle = 0.0f;


	// Start off with the last (leaf) bone:
	mBoneSelected = NUM_BONES-1;

	mGfxStats->addVertices(mBoneMesh->GetNumVertices() * NUM_BONES);
	mGfxStats->addTriangles(mBoneMesh->GetNumFaces() * NUM_BONES);

	buildFX();

	onResetDevice();
}
コード例 #5
0
HRESULT RacorX8::RestoreDeviceObjects()
{
	HRESULT hr;

	IDirect3DDevice8* device;
	hr = m_spD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, m_iVP, &m_dpps, &device);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateDevice failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spDevice.reset(device, [](IDirect3DDevice8* device) { device->Release(); });

	//CreateSphere();

	LoadXFile("sphere.x");

	IDirect3DVertexBuffer8* vbNormal;
	hr = m_spDevice->CreateVertexBuffer(m_iNumVertices * 2 * sizeof SimpleVertex, D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_MANAGED, &vbNormal);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateVertexBuffer failed!", L"Error", 0);
		return E_FAIL;
	}
	hr = CreateNormal<ShaderVertex, SimpleVertex>(m_spVB.get(), vbNormal);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateNormal failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spVBNormal.reset(vbNormal, [](IDirect3DVertexBuffer8* vbNormal){vbNormal->Release(); });

	IDirect3DVertexBuffer8* vbTangent;
	hr = m_spDevice->CreateVertexBuffer(m_iNumVertices * 2 * sizeof SimpleVertex, D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_MANAGED, &vbTangent);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateVertexBuffer failed!", L"Error", 0);
		return E_FAIL;
	}
	hr = CreateTangent<ShaderVertex, SimpleVertex>(m_spVB.get(), vbTangent);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateTangent failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spVBTangent.reset(vbTangent, [](IDirect3DVertexBuffer8* vbTangent){vbTangent->Release(); });

	//DWORD dwDecl[MAX_FVF_DECL_SIZE];
	//ZeroMemory(dwDecl, sizeof dwDecl);
	//pSphere->GetDeclaration(dwDecl);
	DWORD decl[] = {
		D3DVSD_STREAM(0),
		D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
		D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3),
		D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2),
		D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT3),
		D3DVSD_END()
	};
	hr = CreateVSFromBinFile(m_spDevice.get(), decl, L"specular.vso", &m_dwVSH);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateVSFromBinFile failed!", L"Error", 0);
		return E_FAIL;
	}

	hr = CreatePSFromBinFile(m_spDevice.get(), L"specular.pso", &m_dwPSH);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreatePSFromBinFile failed!", L"Error", 0);
		return E_FAIL;
	}

	hr = CreatePSFromBinFile(m_spDevice.get(), L"specularBump.pso", &m_dwPSHBump);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreatePSFromBinFile failed!", L"Error", 0);
		return E_FAIL;
	}

	if (m_bPS14Avaliable)
	{
		hr = CreatePSFromBinFile(m_spDevice.get(), L"specularBump14.pso", &m_dwPSHBump14);
		if (FAILED(hr))
		{
			MessageBox(m_hWnd, L"CreatePSFromBinFile failed!", L"Error", 0);
			return E_FAIL;
		}
	}
	DWORD declLine[] = {
		D3DVSD_STREAM(0),
		D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
		D3DVSD_END()
	};
	hr = CreateVSFromBinFile(m_spDevice.get(), declLine, L"line.vso", &m_dwVSHLine);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreateVSFromBinFile failed!", L"Error", 0);
		return E_FAIL;
	}
	hr = CreatePSFromBinFile(m_spDevice.get(), L"line.pso", &m_dwVPHLine);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"CreatePSFromBinFile failed!", L"Error", 0);
		return E_FAIL;
	}

	IDirect3DTexture8* color_map;
	hr = D3DXCreateTextureFromFile(m_spDevice.get(), _T("earth.bmp"), &color_map);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXCreateTextureFromFile failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spColorMap.reset(color_map, [](IDirect3DTexture8* color_map){ color_map->Release(); });

	IDirect3DTexture8* heightMap;
	hr = D3DXCreateTextureFromFile(m_spDevice.get(), _T("earthbump.bmp"), &heightMap);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXCreateTextureFromFile failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spHeightMap.reset(heightMap, [](IDirect3DTexture8* heightMap) { heightMap->Release(); });

	D3DSURFACE_DESC desc;
	m_spHeightMap->GetLevelDesc(0, &desc);

	IDirect3DTexture8* normalMap;
	hr = D3DXCreateTexture(m_spDevice.get(), desc.Width, desc.Height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &normalMap);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXCreateTexture failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spNormalMap.reset(normalMap, [](IDirect3DTexture8* normalMap){ normalMap->Release(); });

	hr = D3DXComputeNormalMap(m_spNormalMap.get(), m_spHeightMap.get(), NULL, 0, D3DX_CHANNEL_RED, 10);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXComputeNormalMap failed!", L"Error", 0);
		return E_FAIL;
	}
	
	IDirect3DTexture8* power;
	hr = D3DXCreateTexture(m_spDevice.get(), 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &power);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXCreateTexture failed!", L"Error", 0);
		return E_FAIL;
	}
	m_spPower.reset(power, [](IDirect3DTexture8* power){ power->Release();  });
	FLOAT fPower = 16.0f;
	hr = D3DXFillTexture(power, LightEval, &fPower);
	if (FAILED(hr))
	{
		MessageBox(m_hWnd, L"D3DXFillTexture failed!", L"Error", 0);
		return E_FAIL;
	}

	m_spDevice->SetViewport(&m_Viewport);

	m_spDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
	m_spDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
	
	m_spDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

	m_spDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	m_spDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

	//m_spDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
	//m_spDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	//m_spDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

	//m_spDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	//m_spDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	//m_spDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	//m_spDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
	//m_spDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
	m_spDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
	m_spDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
	//m_spDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
	//m_spDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
	//m_spDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);

	m_spDevice->SetTextureStageState(2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
	m_spDevice->SetTextureStageState(2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);

	D3DXVECTOR4 vLight(0.0f, 0.0f, 1.0f, 0.0f);
	D3DXVec4Normalize(&vLight, &vLight);
	m_spDevice->SetVertexShaderConstant(12, &vLight, 1);

	D3DXVECTOR4 half(0.5f, 0.5f, 0.5f, 0.5f);
	m_spDevice->SetVertexShaderConstant(33, &half, 1);

	return S_OK;
}
コード例 #6
0
ファイル: WaterDemo.cpp プロジェクト: erickterri/3dlearn
WaterDemo::WaterDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
    : D3DApp(hInstance, winCaption, devType, requestedVP)
{
    if(!checkDeviceCaps())
    {
        MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
        PostQuitMessage(0);
    }

    InitAllVertexDeclarations();

    mLight.dirW = D3DXVECTOR3(0.0f, -2.0f, -1.0f);
    D3DXVec3Normalize(&mLight.dirW, &mLight.dirW);
    mLight.ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
    mLight.diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
    mLight.spec    = D3DXCOLOR(0.7f, 0.7f, 0.7f, 1.0f);

    mGfxStats = new GfxStats();
    mSky = new Sky("grassenvmap1024.dds", 10000.0f);

    D3DXMATRIX waterWorld;
    D3DXMatrixTranslation(&waterWorld, 0.0f, 2.0f, 0.0f);

    Mtrl waterMtrl;
    waterMtrl.ambient   = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f);
    waterMtrl.diffuse   = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f);
    waterMtrl.spec      = 1.0f*WHITE;
    waterMtrl.specPower = 64.0f;

    Water::InitInfo waterInitInfo;
    waterInitInfo.dirLight = mLight;
    waterInitInfo.mtrl     = waterMtrl;
    waterInitInfo.vertRows         = 128;
    waterInitInfo.vertCols         = 128;
    waterInitInfo.dx               = 1.0f;
    waterInitInfo.dz               = 1.0f;
    waterInitInfo.waveMapFilename0 = "wave0.dds";
    waterInitInfo.waveMapFilename1 = "wave1.dds";
    waterInitInfo.waveMapVelocity0 = D3DXVECTOR2(0.05f, 0.08f);
    waterInitInfo.waveMapVelocity1 = D3DXVECTOR2(-0.02f, 0.1f);
    waterInitInfo.texScale = 16.0f;
    waterInitInfo.toWorld = waterWorld;

    mWater = new Water(waterInitInfo);
    mWater->setEnvMap(mSky->getEnvMap());

    ID3DXMesh* tempMesh = 0;
    LoadXFile("BasicColumnScene.x", &tempMesh, mSceneMtrls, mSceneTextures);

    // Get the vertex declaration for the NMapVertex.
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    UINT numElems = 0;
    HR(NMapVertex::Decl->GetDeclaration(elems, &numElems));

    // Clone the mesh to the NMapVertex format.
    ID3DXMesh* clonedTempMesh = 0;
    HR(tempMesh->CloneMesh(D3DXMESH_MANAGED, elems, gd3dDevice, &clonedTempMesh));

    // Now use D3DXComputeTangentFrameEx to build the TNB-basis for each vertex
    // in the mesh.

    HR(D3DXComputeTangentFrameEx(
           clonedTempMesh, // Input mesh
           D3DDECLUSAGE_TEXCOORD, 0, // Vertex element of input tex-coords.
           D3DDECLUSAGE_BINORMAL, 0, // Vertex element to output binormal.
           D3DDECLUSAGE_TANGENT, 0,  // Vertex element to output tangent.
           D3DDECLUSAGE_NORMAL, 0,   // Vertex element to output normal.
           0, // Options
           0, // Adjacency
           0.01f, 0.25f, 0.01f, // Thresholds for handling errors
           &mSceneMesh, // Output mesh
           0));         // Vertex Remapping

    // Done with temps.
    ReleaseCOM(tempMesh);
    ReleaseCOM(clonedTempMesh);

    D3DXMatrixIdentity(&mSceneWorld);
    D3DXMatrixIdentity(&mSceneWorldInv);

    HR(D3DXCreateTextureFromFile(gd3dDevice, "floor_nmap.bmp", &mSceneNormalMaps[0]));
    HR(D3DXCreateTextureFromFile(gd3dDevice, "bricks_nmap.bmp", &mSceneNormalMaps[1]));

    HR(D3DXCreateTextureFromFile(gd3dDevice, "whitetex.dds", &mWhiteTex));

    // Initialize camera.
    gCamera->pos().y = 7.0f;
    gCamera->pos().z = -30.0f;
    gCamera->setSpeed(10.0f);

    mGfxStats->addVertices(mSceneMesh->GetNumVertices());
    mGfxStats->addTriangles(mSceneMesh->GetNumFaces());

    mGfxStats->addVertices(mWater->getNumVertices());
    mGfxStats->addTriangles(mWater->getNumTriangles());

    mGfxStats->addVertices(mSky->getNumVertices());
    mGfxStats->addTriangles(mSky->getNumTriangles());


    buildFX();

    onResetDevice();
}
コード例 #7
0
ファイル: PropsDemo.cpp プロジェクト: chenbk85/3dlearn
void PropsDemo::buildTrees()
{
	// Load 4 unique meshes.  To draw more than 4 trees, we just draw these
	// 4 trees repeatedly, with different world matrices applied.
	LoadXFile("tree0.x", &mTrees[0].mesh, mTrees[0].mtrls, mTrees[0].textures);
	LoadXFile("tree1.x", &mTrees[1].mesh, mTrees[1].mtrls, mTrees[1].textures);
	LoadXFile("tree2.x", &mTrees[2].mesh, mTrees[2].mtrls, mTrees[2].textures);
	LoadXFile("tree3.x", &mTrees[3].mesh, mTrees[3].mtrls, mTrees[3].textures);



	// Build tree bounding boxes.
	for(int i = 0; i < 4; ++i)
	{
		VertexPNT* v = 0;
		HR(mTrees[i].mesh->LockVertexBuffer(0, (void**)&v));
		HR(D3DXComputeBoundingBox(&v->pos, mTrees[i].mesh->GetNumVertices(),
			mTrees[i].mesh->GetNumBytesPerVertex(), 
			&mTrees[i].box.minPt, &mTrees[i].box.maxPt));
		HR(mTrees[i].mesh->UnlockVertexBuffer());
	}


	// Build world matrices for NUM_TREES trees.  To do this, we generate a
	// random position on the terrain surface for each tree.  In reality, 
	// this is not the best way to do it, as we'd like to have more control and
	// manually place trees in the scene by an artist.  Nevertheless, this is 
	// an easy way to get trees in the scene of our demo.  To prevent trees 
	// from being placed on mountain peaks, or in the water, we can specify to 
	// only generate trees in an allowed height range.  By inspecting the heightmap
	// used in this demo, castlehm257.raw, the range [35, 50] seems to be a good
	// one to generate trees in.  Note that this method does not prevent trees from
	// interpenetrating with one another and it does not prevent the trees from
	// interpenetrating with the castle.

	// Scale down a bit do we ignore the borders of the terrain as candidates.
	int w = (int)(mTerrain->getWidth() * 0.8f);
	int d = (int)(mTerrain->getDepth() * 0.8f);
	D3DXMATRIX S, T;
	for(int i = 0; i < NUM_TREES; ++i)
	{
		float x = (float)((rand() % w) - (w*0.5f));
		float z = (float)((rand() % d) - (d*0.5f));

		// Subtract off height to embed trunk in ground.
		float y = mTerrain->getHeight(x, z) - 0.5f; 

		// Trees modeled to a different scale then ours, so scale them down to make sense.
		// Also randomize the height a bit.
		float treeScale = GetRandomFloat(0.15f, 0.25f);

		// Build tree's world matrix.
		D3DXMatrixTranslation(&T, x, y, z);	
		D3DXMatrixScaling(&S, treeScale, treeScale, treeScale);
		mTreeWorlds[i] = S*T;

		// Only generate trees in this height range.  If the height
		// is outside this range, generate a new random position and 
		// try again.
		if(y < 35.0f || y > 50.0f)
			--i; // We are trying again, so decrement back the index.
	}
}