source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreKdHeightmapTerrainPageSource.cpp @ 1273

Revision 1273, 10.4 KB checked in by szydlowski, 18 years ago (diff)

Added the KdTerrainSceneManager?, a subclass of the KdTreeSceneManager? capable of rendering terrain like the TerrainSceneManager? from Ogre.
All the *Kd*Terrain* classes are identical to their octree counterparts, save prefixing all classes and structures with Kd to avoid namespace clashes.
This was necessary, since the TerrainSceneManager? was hard coded in these classes, and all references had to be replaced with the KdTerrainSceneManager?.
Also added a comprehensive README for the demo application.

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26#include <OgreException.h>
27#include <OgreStringConverter.h>
28#include <OgreResourceManager.h>
29#include <OgreLogManager.h>
30
31#include "OgreKdHeightmapTerrainPageSource.h"
32#include "OgreKdTerrainSceneManager.h"
33#include "OgreKdTerrainPage.h"
34
35namespace Ogre {
36
37    //-------------------------------------------------------------------------
38    KdHeightmapTerrainPageSource::KdHeightmapTerrainPageSource()
39        : mIsRaw(false), mFlipTerrain(false), mPage(0)
40    {
41    }
42    //-------------------------------------------------------------------------
43    KdHeightmapTerrainPageSource::~KdHeightmapTerrainPageSource()
44    {
45        shutdown();
46    }
47    //-------------------------------------------------------------------------
48    void KdHeightmapTerrainPageSource::shutdown(void)
49    {
50        // Image will destroy itself
51        delete mPage;
52        mPage = 0;
53    }
54    //-------------------------------------------------------------------------
55    void KdHeightmapTerrainPageSource::loadHeightmap(void)
56    {
57        size_t imgSize;
58        // Special-case RAW format
59        if (mIsRaw)
60        {
61            // Image size comes from setting (since RAW is not self-describing)
62            imgSize = mRawSize;
63           
64            // Load data
65            mRawData.setNull();
66            DataStreamPtr stream =
67                ResourceGroupManager::getSingleton().openResource(
68                    mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
69            mRawData = MemoryDataStreamPtr(new MemoryDataStream(mSource, stream));
70
71            // Validate size
72            size_t numBytes = imgSize * imgSize * mRawBpp;
73            if (mRawData->size() != numBytes)
74            {
75                shutdown();
76                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
77                    "RAW size (" + StringConverter::toString(mRawData->size()) +
78                    ") does not agree with configuration settings.",
79                    "HeightmapTerrainPageSource::loadHeightmap");
80            }
81        }
82        else
83        {
84            mImage.load(mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
85            // Must be square (dimensions checked later)
86            if ( mImage.getWidth() != mImage.getHeight())
87            {
88                shutdown();
89                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
90                    "Heightmap must be square",
91                    "HeightmapTerrainPageSource::loadHeightmap");
92            }
93            imgSize = mImage.getWidth();
94        }
95        //check to make sure it's the expected size
96        if ( imgSize != mPageSize)
97        {
98            shutdown();
99            String err = "Error: Invalid heightmap size : " +
100                StringConverter::toString( imgSize ) +
101                ". Should be " + StringConverter::toString(mPageSize);
102            OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err,
103                "HeightmapTerrainPageSource::loadHeightmap" );
104        }
105
106    }
107    //-------------------------------------------------------------------------
108    void KdHeightmapTerrainPageSource::initialise(KdTerrainSceneManager* tsm,
109                uint tileSize, uint pageSize, bool asyncLoading,
110        KdTerrainPageSourceOptionList& optionList)
111    {
112        // Shutdown to clear any previous data
113        shutdown();
114
115        KdTerrainPageSource::initialise(tsm, tileSize, pageSize, asyncLoading, optionList);
116
117        // Get source image
118        KdTerrainPageSourceOptionList::iterator ti, tiend;
119        tiend = optionList.end();
120        bool imageFound = false;
121        mIsRaw = false;
122        bool rawSizeFound = false;
123        bool rawBppFound = false;
124        for (ti = optionList.begin(); ti != tiend; ++ti)
125        {
126            String val = ti->first;
127            StringUtil::trim(val);
128            if (StringUtil::startsWith(val, "Heightmap.image", false))
129            {
130                mSource = ti->second;
131                imageFound = true;
132                // is it a raw?
133                if (StringUtil::endsWith(mSource, "raw"))
134                {
135                    mIsRaw = true;
136                }
137            }
138            else if (StringUtil::startsWith(val, "Heightmap.raw.size", false))
139            {
140                mRawSize = atoi(ti->second.c_str());
141                rawSizeFound = true;
142            }
143            else if (StringUtil::startsWith(val, "Heightmap.raw.bpp", false))
144            {
145                mRawBpp = atoi(ti->second.c_str());
146                if (mRawBpp < 1 || mRawBpp > 2)
147                {
148                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
149                        "Invalid value for 'Heightmap.raw.bpp', must be 1 or 2",
150                        "HeightmapTerrainPageSource::initialise");
151                }
152                rawBppFound = true;
153            }
154            else if (StringUtil::startsWith(val, "Heightmap.flip", false))
155            {
156                mFlipTerrain = StringConverter::parseBool(ti->second);
157            }
158            else
159            {
160                LogManager::getSingleton().logMessage("Warning: ignoring unknown Heightmap option '"
161                    + val + "'");
162            }
163        }
164        if (!imageFound)
165        {
166            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
167                "Missing option 'Heightmap.image'",
168                "HeightmapTerrainPageSource::initialise");
169        }
170        if (mIsRaw &&
171            (!rawSizeFound || !rawBppFound))
172        {
173            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
174                "Options 'Heightmap.raw.size' and 'Heightmap.raw.bpp' must "
175                "be specified for RAW heightmap sources",
176                "HeightmapTerrainPageSource::initialise");
177        }
178        // Load it!
179        loadHeightmap();
180    }
181    //-------------------------------------------------------------------------
182    void KdHeightmapTerrainPageSource::requestPage(ushort x, ushort y)
183    {
184        // Only 1 page provided
185        if (x == 0 && y == 0 && !mPage)
186        {
187            // Convert the image data to unscaled floats
188            ulong totalPageSize = mPageSize * mPageSize;
189            Real *heightData = new Real[totalPageSize];
190            const uchar* pOrigSrc, *pSrc;
191            Real* pDest = heightData;
192            Real invScale;
193            bool is16bit = false;
194           
195            if (mIsRaw)
196            {
197                pOrigSrc = mRawData->getPtr();
198                is16bit = (mRawBpp == 2);
199            }
200            else
201            {
202                PixelFormat pf = mImage.getFormat();
203                if (pf != PF_L8 && pf != PF_L16)
204                {
205                    OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
206                        "Error: Image is not a grayscale image.",
207                        "HeightmapTerrainPageSource::requestPage" );
208                }
209
210                pOrigSrc = mImage.getData();
211                is16bit = (pf == PF_L16);
212            }
213            // Determine mapping from fixed to floating
214            ulong rowSize;
215            if ( is16bit )
216            {
217                invScale = 1.0f / 65535.0f;
218                rowSize =  mPageSize * 2;
219            }
220            else
221            {
222                invScale = 1.0f / 255.0f;
223                rowSize =  mPageSize;
224            }
225            // Read the data
226            pSrc = pOrigSrc;
227            for (ulong j = 0; j < mPageSize; ++j)
228            {
229                if (mFlipTerrain)
230                {
231                    // Work backwards
232                    pSrc = pOrigSrc + (rowSize * (mPageSize - j - 1));
233                }
234                for (ulong i = 0; i < mPageSize; ++i)
235                {
236                    if (is16bit)
237                    {
238                        #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
239                            ushort val = *pSrc++ << 8;
240                            val += *pSrc++;
241                        #else
242                            ushort val = *pSrc++;
243                            val += *pSrc++ << 8;
244                        #endif
245                        *pDest++ = Real(val) * invScale;
246                    }
247                    else
248                    {
249                        *pDest++ = Real(*pSrc++) * invScale;
250                    }
251                }
252            }
253
254            // Call listeners
255            firePageConstructed(0, 0, heightData);
256            // Now turn into TerrainPage
257            // Note that we're using a single material for now
258            if (mSceneManager)
259            {
260                mPage = buildPage(heightData,
261                    mSceneManager->getOptions().terrainMaterial);
262                mSceneManager->attachPage(0, 0, mPage);
263            }
264
265            // Free temp store
266            delete [] heightData;
267        }
268    }
269    //-------------------------------------------------------------------------
270    void KdHeightmapTerrainPageSource::expirePage(ushort x, ushort y)
271    {
272        // Single page
273        if (x == 0 && y == 0 && mPage)
274        {
275            delete mPage;
276            mPage = 0;
277        }
278
279    }
280    //-------------------------------------------------------------------------
281
282
283}
Note: See TracBrowser for help on using the repository browser.