Show terrain.cpp syntax highlighted
/***************************************************************************
terrain.cpp - Brute force terrain implementation
-------------------
begin : Mon Sep 8 2003
copyright : (C) 2003-2004 by Cody Russell
email : cody `at' jhu.edu
***************************************************************************
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.
The Original Code is the NeoEngine, NeoBrute, terrain.cpp
The Initial Developer of the Original Code is Cody Russell.
Portions created by Cody Russell are Copyright (C) 2003-2004
Cody Russell. All Rights Reserved.
***************************************************************************/
#include "terrain.h"
#include <neoengine/aabb.h>
#include <neoengine/scenenode.h>
#include <neoengine/vertex.h>
using namespace NeoEngine;
using namespace std;
namespace NeoBrute
{
BruteTerrainBlock::BruteTerrainBlock( int iOffsetX, int iOffsetY, int iBlockSizeSize, int iIndex, TerrainMaterialFactory *pkMaterialFactory, BruteTerrain *pkBrutePage ) :
TerrainBlock( iOffsetX, iOffsetY, iBlockSizeSize, iIndex ),
m_pkBrutePage( pkBrutePage ),
m_pkMaterialFactory( pkMaterialFactory )
{
UpdateData();
}
void BruteTerrainBlock::GenerateAABB()
{
neolog << "BruteTerrainBlock::GenerateAABB()" << std::endl;
AABB *pkAABB = new AABB;
pkAABB->Generate( m_pkVertices );
SetBoundingVolume( pkAABB );
}
void BruteTerrainBlock::UpdateData()
{
if( !m_pkVertices )
{
m_pkVertices = Core::Get()->GetRenderDevice()->CreateVertexBuffer( Buffer::STATIC, ( m_iSize + 1 ) * ( m_iSize + 1 ), &NormalDiffuseTexVertex::s_kDecl );
neolog << "Creating VertexBuffer, size " << m_iSize + 1 << " x " << m_iSize + 1 << " == " << ( m_iSize + 1 ) * ( m_iSize + 1 ) << endl;
// if( dynamic_cast< TerrainBlendMaterialFactory* >( m_pkMaterialFactory )->GetLighting() == TerrainBlendMaterialFactory::LIGHT_HARDWARE )
{
float fHScale = m_pkBrutePage->GetHeightmap()->GetHScale();
// Setup the vertex buffer
m_pkVertices->Lock( Buffer::WRITE );
for( int y = 0; y <= m_iSize; y++ )
{
for( int x = 0; x <= m_iSize; x++ )
{
int ix, iy;
ix = m_iOffsetX * m_iSize + x;
iy = m_iOffsetY * m_iSize + y;
if( ix == m_pkBrutePage->GetHeightmap()->GetSize() )
{
ix--;
}
if( iy == m_pkBrutePage->GetHeightmap()->GetSize() )
{
iy--;
}
unsigned int iOffset = y * ( m_iSize + 1 ) + x;
float fHeight = m_pkBrutePage->GetHeightmap()->GetHeight( ix, iy ); // Height is already transformed by VScale
NormalDiffuseTexVertex *pkVertex = (NormalDiffuseTexVertex*) m_pkVertices->GetVertex( iOffset );
pkVertex->m_kPosition.Set( fHScale * ix, fHeight, fHScale * iy );
}
}
m_pkVertices->Unlock();
m_pkMaterialFactory->SetTexCoords( m_pkVertices, m_pkBrutePage );
}
}
if( !m_pkPolygons )
{
m_pkPolygons = Core::Get()->GetRenderDevice()->CreatePolygonBuffer( Buffer::STATIC, m_iSize * m_iSize * 2 );
m_pkPolygons->Lock( Buffer::WRITE );
Polygon *pkPolygon;
unsigned int i = 0;
for( int y = 0; y < m_iSize; y++ )
{
for( int x = 0; x < m_iSize; x++ )
{
pkPolygon = m_pkPolygons->GetPolygon( i );
(*pkPolygon)[0] = x + ( y + 1 ) * ( m_iSize + 1 );
(*pkPolygon)[1] = x + 1 + ( y + 1 ) * ( m_iSize + 1 );
(*pkPolygon)[2] = x + 1 + y * ( m_iSize + 1 );
pkPolygon = m_pkPolygons->GetPolygon( i + 1 );
(*pkPolygon)[0] = x + ( y + 1 ) * ( m_iSize + 1);
(*pkPolygon)[1] = x + 1 + y * ( m_iSize + 1 );
(*pkPolygon)[2] = x + y * ( m_iSize + 1 );
i += 2;
}
}
m_pkPolygons->Unlock();
// if( dynamic_cast< TerrainBlendMaterialFactory* >( m_pkMaterialFactory )->GetLighting() == TerrainBlendMaterialFactory::LIGHT_HARDWARE )
{
m_pkPolygons->CalculateNormals( m_pkVertices, true );
m_pkVertices->Lock( Buffer::WRITE );
m_pkPolygons->Lock( Buffer::READ );
Vector3d *pkNormal = m_pkPolygons->GetNormals();
const VertexElement *pkNormalElement = m_pkVertices->GetVertexFormat()->GetElement( VertexElement::FLOAT3, VertexElement::NORMAL );
unsigned char *pucVertex = (unsigned char*)m_pkVertices->GetVertex() + pkNormalElement->m_uiOffset;
unsigned int uiVertexSize = m_pkVertices->GetVertexSize();
pkPolygon = m_pkPolygons->GetPolygon( 0 );
int iPolyEnd = m_pkPolygons->GetNumElements();
int iEnd = m_pkVertices->GetNumElements();
int j;
for( j = 0; j < iPolyEnd; ++j, ++pkPolygon, ++pkNormal )
{
*((Vector3d*)( pucVertex + uiVertexSize * pkPolygon->v[0] )) += *pkNormal;
*((Vector3d*)( pucVertex + uiVertexSize * pkPolygon->v[1] )) += *pkNormal;
*((Vector3d*)( pucVertex + uiVertexSize * pkPolygon->v[2] )) += *pkNormal;
}
pucVertex = (unsigned char*)m_pkVertices->GetVertex() + pkNormalElement->m_uiOffset;
for( j = 0; j < iEnd; ++j, pucVertex += uiVertexSize )
((Vector3d*)pucVertex)->Normalize();
m_pkPolygons->Unlock();
m_pkVertices->Unlock();
}
}
GenerateAABB();
}
bool BruteTerrain::Render( Frustum *pkFrustum, bool bForce )
{
vector< TerrainBlock* >::iterator ppkBlock = m_vpkBlocks.begin();
vector< TerrainBlock* >::iterator ppkEnd = m_vpkBlocks.end();
// neolog << "BruteTerrain::Render()" << std::endl;
for( ; ppkBlock != ppkEnd; ++ppkBlock )
{
(*ppkBlock)->Render( pkFrustum, bForce );
}
return true;
}
BruteTerrain::BruteTerrain( TerrainHeightmap *pkHeightmap, TerrainMaterialFactory *pkMaterialFactory, int iDepth ) :
TerrainPage( pkHeightmap, pkMaterialFactory, iDepth )
{
m_pkMaterialFactory->GenerateMaterial( this );
int iBlocks = GetNumBlocksOnSide();
for( int iy = 0; iy < iBlocks; iy++ )
{
for( int ix = 0; ix < iBlocks; ix++ )
{
m_vpkBlocks.push_back( new BruteTerrainBlock( ix, iy, m_iBlockSize, iy * iBlocks + ix, pkMaterialFactory, this ) );
}
}
}
bool BruteTerrainBlock::Render( Frustum *pkFrustum, bool bForce )
{
if( !SceneEntity::Render( pkFrustum, bForce ) )
return false;
static RenderPrimitive skPrimitive;
static RenderPrimitive *spkPrimitive = &skPrimitive;
// neolog << "BruteTerrainBlock::Render()" << std::endl;
if( m_pkNode )
{
spkPrimitive->m_kModelMatrix = m_pkNode->GetWorldTransform();
spkPrimitive->m_kInvModelMatrix = m_pkNode->GetInverseWorldTransform();
}
if( !m_pkPolygons->IsStripped() )
{
spkPrimitive->m_ePrimitive = RenderPrimitive::TRIANGLES;
spkPrimitive->m_pkPolygonBuffer = m_pkPolygons;
spkPrimitive->m_uiNumPrimitives = spkPrimitive->m_pkPolygonBuffer->GetNumElements();
}
else
{
spkPrimitive->m_ePrimitive = RenderPrimitive::TRIANGLESTRIP;
spkPrimitive->m_pkPolygonStripBuffer = m_pkPolygons->GetStrip();
spkPrimitive->m_uiNumPrimitives = spkPrimitive->m_pkPolygonStripBuffer->GetNumElements();
}
spkPrimitive->m_pkVertexBuffer = m_pkVertices;
spkPrimitive->m_pkMaterial = m_pkMaterialFactory->m_pkMaterial;
Core::Get()->GetRenderDevice()->Render( *spkPrimitive, 0 );
spkPrimitive->m_pkMaterial = 0;
spkPrimitive->m_pkVertexBuffer = 0;
spkPrimitive->m_pkPolygonStripBuffer = 0;
return true;
}
TerrainPage *BruteTerrainManager::CreateTerrain( TerrainHeightmap *pkHeightmap, TerrainMaterialFactory *pkMaterialFactory )
{
return new BruteTerrain( pkHeightmap, pkMaterialFactory, 2 );
}
}; // namespace NeoBrute
See more files for this project here