📄 ogrepaginglandscapeindexbuffer.cpp
字号:
/***************************************************************************
OgrePagingLandScapeIndexBuffer.cpp - description
-------------------
begin : Fri Feb 28 2003
copyright : (C) 2003 by Jose A Milan
email : spoke2@supercable.es
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "OgreHardwareBufferManager.h"
#include "OgreHardwareIndexBuffer.h"
#include "OgreVertexIndexData.h"
#include "OgreVector3.h"
#include "OgreColourValue.h"
#include "OgreSimpleRenderable.h"
#include "OgrePagingLandScapeRenderable.h"
#include "OgrePagingLandScapeOptions.h"
#include "OgrePagingLandScapeIndexBuffer.h"
namespace Ogre
{
//-----------------------------------------------------------------------
template<> PagingLandScapeIndexBuffer* Singleton<PagingLandScapeIndexBuffer>::ms_Singleton = 0;
PagingLandScapeIndexBuffer* PagingLandScapeIndexBuffer::getSingletonPtr(void)
{
return ms_Singleton;
}
//-----------------------------------------------------------------------
PagingLandScapeIndexBuffer& PagingLandScapeIndexBuffer::getSingleton(void)
{
assert( ms_Singleton ); return ( *ms_Singleton );
}
//-----------------------------------------------------------------------
PagingLandScapeIndexBuffer::PagingLandScapeIndexBuffer( )
{
mTileSize = PagingLandScapeOptions::getSingleton().TileSize + 1;
mNumIndexes = PagingLandScapeOptions::getSingleton().maxRenderLevel + 1;
//mLevelIndex.reserve (mNumIndexes);
for ( uint i = 0; i < mNumIndexes; i++ )
{
mLevelIndex.push_back( new IndexMap() );
}
}
//-----------------------------------------------------------------------
PagingLandScapeIndexBuffer::~PagingLandScapeIndexBuffer()
{
for ( uint i = 0; i < mNumIndexes; i++ )
{
delete mLevelIndex[i];
}
mLevelIndex.clear();
for( uint i = 0; i < mCache.size(); i++ )
{
delete mCache[i];
}
mCache.clear();
}
//-----------------------------------------------------------------------
IndexData *PagingLandScapeIndexBuffer::getIndexData( const uint stitchFlags, const uint RenderLevel,
PagingLandScapeRenderable **Neighbors )
{
// Check preexisting
assert (mLevelIndex[ RenderLevel ]);
IndexMap::iterator ii = mLevelIndex[ RenderLevel ]->find( stitchFlags );
if ( ii == mLevelIndex[ RenderLevel ]->end())
{
// Create
IndexData* indexData = generateTriListIndexes(stitchFlags, RenderLevel,
Neighbors);
mLevelIndex[ RenderLevel ]->insert(
IndexMap::value_type(stitchFlags, indexData));
return indexData;
}
else
{
return ii->second;
}
}
//-----------------------------------------------------------------------
IndexData* PagingLandScapeIndexBuffer::generateTriListIndexes(const uint stitchFlags, const uint RenderLevel,
PagingLandScapeRenderable **Neighbors)
{
uint step = 1 << RenderLevel;
uint north = stitchFlags & STITCH_NORTH ? step : 0;
uint south = stitchFlags & STITCH_SOUTH ? step : 0;
uint east = stitchFlags & STITCH_EAST ? step : 0;
uint west = stitchFlags & STITCH_WEST ? step : 0;
uint new_length = ( mTileSize * mTileSize * 6 ) / step;
IndexData* indexData = new IndexData;
indexData->indexBuffer =
HardwareBufferManager::getSingleton().createIndexBuffer(
HardwareIndexBuffer::IT_16BIT,
new_length, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
mCache.push_back( indexData );
/** Returns the index into the height array for the given coordinates. */
ushort* pIdx = static_cast<ushort*>(indexData->indexBuffer->lock(0,
indexData->indexBuffer->getSizeInBytes(),
HardwareBuffer::HBL_DISCARD));
uint numIndexes = 0;
uint step_offset = step * mTileSize;
uint height_count = north * mTileSize;
for (uint j = north; j < mTileSize - 1 - south; j += step )
{
for (uint i = west; i < mTileSize - 1 - east; i += step )
{
//triangles
*pIdx++ = ushort (i + height_count); numIndexes++;
*pIdx++ = ushort (i + height_count + step_offset); numIndexes++;
*pIdx++ = ushort (i + step + height_count); numIndexes++;
*pIdx++ = ushort (i + height_count + step_offset); numIndexes++;
*pIdx++ = ushort (i + step + height_count + step_offset); numIndexes++;
*pIdx++ = ushort (i + step + height_count); numIndexes++;
}
height_count += step_offset;
}
// North stitching
if ( north )
{
numIndexes += stitchEdge(NORTH, RenderLevel, Neighbors[NORTH]->mRenderLevel,
west > 0 , east > 0 , &pIdx);
}
// East stitching
if ( east )
{
numIndexes += stitchEdge(EAST, RenderLevel, Neighbors[EAST]->mRenderLevel,
north > 0, south > 0, &pIdx);
}
// South stitching
if ( south )
{
numIndexes += stitchEdge(SOUTH, RenderLevel, Neighbors[SOUTH]->mRenderLevel,
east > 0 , west > 0, &pIdx);
}
// West stitching
if ( west )
{
numIndexes += stitchEdge(WEST, RenderLevel, Neighbors[WEST]->mRenderLevel,
south > 0 , north > 0, &pIdx);
}
indexData->indexBuffer->unlock();
indexData->indexCount = numIndexes;
indexData->indexStart = 0;
return indexData;
}
//-----------------------------------------------------------------------
uint PagingLandScapeIndexBuffer::stitchEdge(Neighbor neighbor, const uint hiLOD, const uint loLOD,
bool omitFirstTri, bool omitLastTri, ushort** ppIdx)
{
assert(loLOD > hiLOD);
/*
Now do the stitching; we can stitch from any level to any level.
The stitch pattern is like this for each pair of vertices in the lower LOD
(excuse the poor ascii art):
lower LOD
*-----------*
|\ \ 3 / /|
|1\2 \ / 4/5|
*--*--*--*--*
higher LOD
The algorithm is, for each pair of lower LOD vertices:
1. Iterate over the higher LOD vertices, generating tris connected to the
first lower LOD vertex, up to and including 1/2 the span of the lower LOD
over the higher LOD (tris 1-2). Skip the first tri if it is on the edge
of the tile and that edge is to be stitched itself.
2. Generate a single tri for the middle using the 2 lower LOD vertices and
the middle vertex of the higher LOD (tri 3).
3. Iterate over the higher LOD vertices from 1/2 the span of the lower LOD
to the end, generating tris connected to the second lower LOD vertex
(tris 4-5). Skip the last tri if it is on the edge of a tile and that
edge is to be stitched itself.
The same algorithm works for all edges of the patch; stitching is done
clockwise so that the origin and steps used change, but the general
approach does not.
*/
// Get pointer to be updated
ushort* pIdx = *ppIdx;
// Work out the steps ie how to increment indexes
// Step from one vertex to another in the high detail version
int step = 1 << hiLOD;
// Step from one vertex to another in the low detail version
int superstep = 1 << loLOD;
// Step half way between low detail steps
int halfsuperstep = superstep >> 1;
// Work out the starting points and sign of increments
// We always work the strip clockwise
int startx, starty, endx, rowstep;
bool horizontal;
switch(neighbor)
{
case NORTH:
startx = starty = 0;
endx = mTileSize - 1;
rowstep = step;
horizontal = true;
break;
case SOUTH:
// invert x AND y direction, helps to keep same winding
startx = starty = mTileSize - 1;
endx = 0;
rowstep = -step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
horizontal = true;
break;
case EAST:
startx = 0;
endx = mTileSize - 1;
starty = mTileSize - 1;
rowstep = -step;
horizontal = false;
break;
case WEST:
startx = mTileSize - 1;
endx = 0;
starty = 0;
rowstep = step;
step = -step;
superstep = -superstep;
halfsuperstep = -halfsuperstep;
horizontal = false;
break;
default:
break;
};
uint numIndexes = 0;
for ( int j = startx; j != endx; j += superstep )
{
int k;
for (k = 0; k != halfsuperstep; k += step)
{
int jk = j + k;
//skip the first bit of the corner?
if ( j != startx || k != 0 || !omitFirstTri )
{
if (horizontal)
{
*pIdx++ = _index( j , starty ); numIndexes++;
*pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index( starty, j ); numIndexes++;
*pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index( starty + rowstep, jk + step); numIndexes++;
}
}
}
// Middle tri
if (horizontal)
{
*pIdx++ = _index( j, starty ); numIndexes++;
*pIdx++ = _index( j + halfsuperstep, starty + rowstep); numIndexes++;
*pIdx++ = _index( j + superstep, starty ); numIndexes++;
}
else
{
*pIdx++ = _index( starty, j ); numIndexes++;
*pIdx++ = _index( starty + rowstep, j + halfsuperstep ); numIndexes++;
*pIdx++ = _index( starty, j + superstep ); numIndexes++;
}
for (k = halfsuperstep; k != superstep; k += step)
{
int jk = j + k;
if ( j != endx - superstep || k != superstep - step || !omitLastTri )
{
if (horizontal)
{
*pIdx++ = _index( j + superstep, starty ); numIndexes++;
*pIdx++ = _index( jk, starty + rowstep ); numIndexes++;
*pIdx++ = _index( jk + step, starty + rowstep ); numIndexes++;
}
else
{
*pIdx++ = _index( starty, j + superstep ); numIndexes++;
*pIdx++ = _index( starty + rowstep, jk ); numIndexes++;
*pIdx++ = _index( starty + rowstep, jk + step ); numIndexes++;
}
}
}
}
*ppIdx = pIdx;
return numIndexes;
}
} //namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -