Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/PlugIns/OctreeSceneManager/src/OgreHeightmapTerrainPageSource.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 10.2 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30#include "OgreHeightmapTerrainPageSource.h"
31#include "OgreTerrainPage.h"
32#include "OgreException.h"
33#include "OgreStringConverter.h"
34#include "OgreTerrainSceneManager.h"
35#include "OgreResourceManager.h"
36#include "OgreLogManager.h"
37
38namespace Ogre {
39
40    //-------------------------------------------------------------------------
41    HeightmapTerrainPageSource::HeightmapTerrainPageSource()
42        : mIsRaw(false), mFlipTerrain(false), mPage(0)
43    {
44    }
45    //-------------------------------------------------------------------------
46    HeightmapTerrainPageSource::~HeightmapTerrainPageSource()
47    {
48        shutdown();
49    }
50    //-------------------------------------------------------------------------
51    void HeightmapTerrainPageSource::shutdown(void)
52    {
53        // Image will destroy itself
54        delete mPage;
55        mPage = 0;
56    }
57    //-------------------------------------------------------------------------
58    void HeightmapTerrainPageSource::loadHeightmap(void)
59    {
60        size_t imgSize;
61        // Special-case RAW format
62        if (mIsRaw)
63        {
64            // Image size comes from setting (since RAW is not self-describing)
65            imgSize = mRawSize;
66           
67            // Load data
68            mRawData.setNull();
69            DataStreamPtr stream = 
70                ResourceGroupManager::getSingleton().openResource(
71                    mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
72            mRawData = MemoryDataStreamPtr(new MemoryDataStream(mSource, stream));
73
74            // Validate size
75            size_t numBytes = imgSize * imgSize * mRawBpp;
76            if (mRawData->size() != numBytes)
77            {
78                shutdown();
79                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
80                    "RAW size (" + StringConverter::toString(mRawData->size()) + 
81                    ") does not agree with configuration settings.", 
82                    "HeightmapTerrainPageSource::loadHeightmap");
83            }
84        }
85        else
86        {
87            mImage.load(mSource, ResourceGroupManager::getSingleton().getWorldResourceGroupName());
88            // Must be square (dimensions checked later)
89            if ( mImage.getWidth() != mImage.getHeight())
90            {
91                shutdown();
92                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
93                    "Heightmap must be square",
94                    "HeightmapTerrainPageSource::loadHeightmap");
95            }
96            imgSize = mImage.getWidth();
97        }
98        //check to make sure it's the expected size
99        if ( imgSize != mPageSize)
100        {
101            shutdown();
102            String err = "Error: Invalid heightmap size : " +
103                StringConverter::toString( imgSize ) +
104                ". Should be " + StringConverter::toString(mPageSize);
105            OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, err, 
106                "HeightmapTerrainPageSource::loadHeightmap" );
107        }
108
109    }
110    //-------------------------------------------------------------------------
111    void HeightmapTerrainPageSource::initialise(TerrainSceneManager* tsm, 
112        ushort tileSize, ushort pageSize, bool asyncLoading, 
113        TerrainPageSourceOptionList& optionList)
114    {
115        // Shutdown to clear any previous data
116        shutdown();
117
118        TerrainPageSource::initialise(tsm, tileSize, pageSize, asyncLoading, optionList);
119
120        // Get source image
121        TerrainPageSourceOptionList::iterator ti, tiend;
122        tiend = optionList.end();
123        bool imageFound = false;
124        mIsRaw = false;
125        bool rawSizeFound = false;
126        bool rawBppFound = false;
127        for (ti = optionList.begin(); ti != tiend; ++ti)
128        {
129            String val = ti->first;
130            StringUtil::trim(val);
131            if (StringUtil::startsWith(val, "Heightmap.image", false))
132            {
133                mSource = ti->second;
134                imageFound = true;
135                // is it a raw?
136                if (StringUtil::endsWith(mSource, "raw"))
137                {
138                    mIsRaw = true;
139                }
140            }
141            else if (StringUtil::startsWith(val, "Heightmap.raw.size", false))
142            {
143                mRawSize = atoi(ti->second.c_str());
144                rawSizeFound = true;
145            }
146            else if (StringUtil::startsWith(val, "Heightmap.raw.bpp", false))
147            {
148                mRawBpp = atoi(ti->second.c_str());
149                if (mRawBpp < 1 || mRawBpp > 2)
150                {
151                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
152                        "Invalid value for 'Heightmap.raw.bpp', must be 1 or 2",
153                        "HeightmapTerrainPageSource::initialise");
154                }
155                rawBppFound = true;
156            }
157            else if (StringUtil::startsWith(val, "Heightmap.flip", false))
158            {
159                mFlipTerrain = StringConverter::parseBool(ti->second);
160            }
161            else
162            {
163                LogManager::getSingleton().logMessage("Warning: ignoring unknown Heightmap option '"
164                    + val + "'");
165            }
166        }
167        if (!imageFound)
168        {
169            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
170                "Missing option 'Heightmap.image'", 
171                "HeightmapTerrainPageSource::initialise");
172        }
173        if (mIsRaw && 
174            (!rawSizeFound || !rawBppFound))
175        {
176            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
177                "Options 'Heightmap.raw.size' and 'Heightmap.raw.bpp' must "
178                "be specified for RAW heightmap sources", 
179                "HeightmapTerrainPageSource::initialise");
180        }
181        // Load it!
182        loadHeightmap();
183    }
184    //-------------------------------------------------------------------------
185    void HeightmapTerrainPageSource::requestPage(ushort x, ushort y)
186    {
187        // Only 1 page provided
188        if (x == 0 && y == 0 && !mPage)
189        {
190            // Convert the image data to unscaled floats
191            ulong totalPageSize = mPageSize * mPageSize; 
192            Real *heightData = new Real[totalPageSize];
193            const uchar* pOrigSrc, *pSrc;
194            Real* pDest = heightData;
195            Real invScale;
196            bool is16bit = false;
197           
198            if (mIsRaw)
199            {
200                pOrigSrc = mRawData->getPtr();
201                is16bit = (mRawBpp == 2);
202            }
203            else
204            {
205                PixelFormat pf = mImage.getFormat();
206                if (pf != PF_L8 && pf != PF_L16)
207                {
208                    OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, 
209                        "Error: Image is not a grayscale image.",
210                        "HeightmapTerrainPageSource::requestPage" );
211                }
212
213                pOrigSrc = mImage.getData();
214                is16bit = (pf == PF_L16);
215            }
216            // Determine mapping from fixed to floating
217            ulong rowSize;
218            if ( is16bit )
219            {
220                invScale = 1.0f / 65535.0f; 
221                rowSize =  mPageSize * 2;
222            }
223            else 
224            {
225                invScale = 1.0f / 255.0f; 
226                rowSize =  mPageSize;
227            }
228            // Read the data
229            pSrc = pOrigSrc;
230            for (ulong j = 0; j < mPageSize; ++j)
231            {
232                if (mFlipTerrain)
233                {
234                    // Work backwards
235                    pSrc = pOrigSrc + (rowSize * (mPageSize - j - 1));
236                }
237                for (ulong i = 0; i < mPageSize; ++i)
238                {
239                    if (is16bit)
240                    {
241                        #if OGRE_ENDIAN == OGRE_ENDIAN_BIG
242                            ushort val = *pSrc++ << 8;
243                            val += *pSrc++;
244                        #else
245                            ushort val = *pSrc++;
246                            val += *pSrc++ << 8;
247                        #endif
248                        *pDest++ = Real(val) * invScale;
249                    }
250                    else
251                    {
252                        *pDest++ = Real(*pSrc++) * invScale;
253                    }
254                }
255            }
256
257            // Call listeners
258            firePageConstructed(0, 0, heightData);
259            // Now turn into TerrainPage
260            // Note that we're using a single material for now
261            if (mSceneManager)
262            {
263                mPage = buildPage(heightData, 
264                    mSceneManager->getOptions().terrainMaterial);
265                mSceneManager->attachPage(0, 0, mPage);
266            }
267
268            // Free temp store
269            delete [] heightData;
270        }
271    }
272    //-------------------------------------------------------------------------
273    void HeightmapTerrainPageSource::expirePage(ushort x, ushort y)
274    {
275        // Single page
276        if (x == 0 && y == 0 && mPage)
277        {
278            delete mPage;
279            mPage = 0;
280        }
281
282    }
283    //-------------------------------------------------------------------------
284
285
286}
Note: See TracBrowser for help on using the repository browser.