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

📄 ogrepaginglandscapeindexbuffer.cpp

📁 使用stl技术,(还没看,是听说的)
💻 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 + -