1
/***************************************************************************
2
OgrePagingLandScapeData2D.cpp - description
4
begin : Wen Mar 06 2003
5
copyright : (C) 2003-2006 by Jose A Milan && Tuan Kuranes
6
email : spoke@supercable.es & tuan.kuranes@free.fr
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU Lesser General Public License as *
13
* published by the Free Software Foundation; either version 2 of the *
14
* License, or (at your option) any later version. *
16
***************************************************************************/
18
#include "OgrePagingLandScapePrecompiledHeaders.h"
20
#include "OgreVector3.h"
21
#include "OgreColourValue.h"
23
#include "OgreSphere.h"
25
#include "OgrePagingLandScapeSceneManager.h"
27
#include "OgrePagingLandScapeData2DManager.h"
28
#include "OgrePagingLandScapeData2D.h"
29
#include "OgrePagingLandScapeOptions.h"
34
#include "OgreAxisAlignedBox.h"
35
#include "OgreMovableObject.h"
36
#include "OgreSimpleRenderable.h"
39
#include "OgrePagingLandScapePageManager.h"
40
#include "OgrePagingLandScapeTile.h"
41
#include "OgrePagingLandScapeRenderable.h"
48
PagingLandScapeData2D::PagingLandScapeData2D(PagingLandScapeData2DManager* pageMgr):
53
mIsRectModified (false),
54
mRect (0, 0, 0, 0, 0, 1)
58
//-----------------------------------------------------------------------
59
PagingLandScapeData2D::~PagingLandScapeData2D()
64
//-----------------------------------------------------------------------
65
void PagingLandScapeData2D::init()
70
//-----------------------------------------------------------------------
71
void PagingLandScapeData2D::uninit()
73
PagingLandScapeData2D::unload ();
76
//-----------------------------------------------------------------------
77
bool PagingLandScapeData2D::load(unsigned int x, unsigned int z)
82
mIsRectModified = false;
83
mRect = Image::Box (0, 0, 0, 0, 0, 1);
88
mSize = mParent->getOptions()->PageSize;
90
mShiftX = (mPageX * (mSize - 1)) - mParent->getOptions()->maxUnScaledX;
91
mShiftZ = (mPageZ * (mSize - 1)) - mParent->getOptions()->maxUnScaledZ;
93
const bool isLoadable = _load (x, z);
100
//-----------------------------------------------------------------------
101
void PagingLandScapeData2D::load()
110
//-----------------------------------------------------------------------
111
void PagingLandScapeData2D::unload()
115
if (mIsModified && mParent->getOptions()->saveDeformation)
117
//Use the shared pointer for deletion
118
// delete[] mHeightData;
119
mHeightDataPtr.reset(0);
124
resetDeformationRectangle ();
129
//-----------------------------------------------------------------------
130
void PagingLandScapeData2D::computePowerof2PlusOneSize()
132
mSize = mParent->getOptions()->PageSize;
133
const size_t p2size = mSize - 1;
135
size_t pagex = mXDimension / p2size;
136
if (mXDimension - (pagex * p2size) > 1)
138
mXDimension = pagex * p2size + 1;
140
size_t pagez = mZDimension / p2size;
141
if (mZDimension - (pagez * p2size) > 1)
143
mZDimension = pagez * p2size + 1;
146
//-----------------------------------------------------------------------
147
bool PagingLandScapeData2D::_checkSize(size_t s)
150
const int p = static_cast <unsigned int> (s - 1);
152
return ((p & (p - 1)) == 0);
157
//-----------------------------------------------------------------------
158
void PagingLandScapeData2D::resetDeformationRectangle()
164
mIsRectModified = false;
167
//-----------------------------------------------------------------------
168
const Image::Box& PagingLandScapeData2D::getDeformationRectangle() const
173
//-----------------------------------------------------------------------
174
void PagingLandScapeData2D::adjustDeformationRectangle(unsigned int x, unsigned int z)
185
if (mRect.bottom < z)
190
// first modification :
191
// deformation rectangle is the point
196
mIsRectModified = true;
199
unsigned int tileposx = x;
200
unsigned int tileposz = z;
201
PagingLandScapeTile *t =
202
mParent->getSceneManager()->getPageManager()->getTilePage(tileposx, tileposz,
204
if (t && t->isLoaded ())
206
// tells what tile portion needs to be updated.
207
PagingLandScapeRenderable * const r = t->getRenderable ();
208
r->adjustDeformationRectangle (tileposx, tileposz);
212
//-----------------------------------------------------------------------
213
bool PagingLandScapeData2D::deformHeight(const Vector3& deformationPoint, Real& modificationHeight)
215
// adjust x and z to be local to page
216
const int x = static_cast<int> (deformationPoint.x - mShiftX);
217
const int z = static_cast<int> (deformationPoint.z - mShiftZ);
218
// due to Real imprecision on Reals, we have to use boundaries here
219
// otherwise we'll hit asserts.
220
const int size = static_cast<int> (mSize-1);
221
const unsigned int ux = static_cast<unsigned int> (std::max(std::min (x, size), 0));
222
const unsigned int uz = static_cast<unsigned int> (std::max(std::min (z, size), 0));
223
return deformHeight(ux, uz, modificationHeight);
226
//-----------------------------------------------------------------------
227
bool PagingLandScapeData2D::deformHeight(unsigned int x, unsigned int z, Real& modificationHeight)
229
const unsigned int arraypos = static_cast <unsigned int> (z * mSize + x);
230
assert (mHeightData && arraypos < mMaxArrayPos);
232
const Real maxH = mParent->getMaxHeight();
233
const Real newH = mHeightData[arraypos] - modificationHeight;
235
bool did_modif = false;
238
if (mHeightData[arraypos] != 0.0f)
239
did_modif = setHeight(x, z, arraypos, 0.0f);
240
modificationHeight = 0.0f;
242
else if (newH >= maxH)
244
if (mHeightData[arraypos] != maxH)
245
did_modif = setHeight(x, z, arraypos, maxH);
246
modificationHeight = maxH;
250
did_modif = setHeight(x, z, arraypos, newH);
251
modificationHeight = newH;
256
//-----------------------------------------------------------------------
257
bool PagingLandScapeData2D::setHeight(unsigned int x, unsigned int z, unsigned int Pos, const Real& h)
259
if (mHeightData[Pos] != h)
261
mHeightData[ Pos ] = h;
263
unsigned int tileposx = x;
264
unsigned int tileposz = z;
265
// Make position local to tiles.
266
// and return a Tile.
267
PagingLandScapeTile *t =
268
mParent->getSceneManager()->getPageManager()->getTilePage (tileposx, tileposz,
270
if (t && t->isLoaded ())
272
// tells what tile portion needs to be updated.
273
PagingLandScapeRenderable * const r = t->getRenderable ();
274
r->adjustDeformationRectangle (tileposx, tileposz);
276
const unsigned int tSize = mParent->getOptions()->TileSize - 1;
277
const unsigned int NumTiles = mParent->getOptions()->NumTiles;
279
const PagingLandScapeTileInfo * const info = t->getInfo();
280
const unsigned int tX = info->mTileX;
281
const unsigned int tZ = info->mTileZ;
283
// If we're on a page edge, we must duplicate the change on the
284
// neighbour tile (if it has one...)
285
// could be a direct neighbour or a diagonal one (in a corner.)
286
const bool left = (tileposx == 0 && tX != 0);
287
const bool right = (tileposx == tSize && tX != NumTiles - 1);
288
const bool down = (tileposz == 0 && tZ != 0);
289
const bool up = (tileposz == tSize && tZ != NumTiles - 1);
294
PagingLandScapeRenderable * const rn = r->_getNeighbor(WEST);
299
PagingLandScapeRenderable * const rnUp = rn->_getNeighbor(NORTH);
300
if (rnUp && rnUp->isLoaded ())
302
rnUp->adjustDeformationRectangle (tSize, tSize);
307
PagingLandScapeRenderable * const rnDown = rn->_getNeighbor(SOUTH);
308
if (rnDown && rnDown->isLoaded ())
310
rnDown->adjustDeformationRectangle (tSize, 0);
315
rn->adjustDeformationRectangle (tSize, tileposz);
321
PagingLandScapeRenderable * const rn = r->_getNeighbor(EAST);
326
PagingLandScapeRenderable * const rnUp = rn->_getNeighbor(NORTH);
327
if (rnUp && rnUp->isLoaded ())
329
rnUp->adjustDeformationRectangle (0, tSize);
334
PagingLandScapeRenderable * const rnDown = rn->_getNeighbor(SOUTH);
335
if (rnDown && rnDown->isLoaded ())
337
rnDown->adjustDeformationRectangle (0, 0);
342
rn->adjustDeformationRectangle (0, tileposz);
348
PagingLandScapeRenderable * const rn = r->_getNeighbor(NORTH);
349
if (rn && rn->isLoaded ())
351
rn->adjustDeformationRectangle (tileposx, tSize);
356
PagingLandScapeRenderable * const rn = r->_getNeighbor(SOUTH);
357
if (rn && rn->isLoaded ())
359
rn->adjustDeformationRectangle (tileposx, 0);
364
adjustDeformationRectangle (x, z);
370
//-----------------------------------------------------------------------
371
bool PagingLandScapeData2D::setHeight(unsigned int x, unsigned int z, const Real& h)
373
const unsigned int Pos = static_cast <unsigned int> ((z * mSize)+ x);
374
assert (mHeightData && mMaxArrayPos > Pos);
375
return setHeight(x, z, Pos, h);
377
#endif //_MAPSPLITTER
379
//-----------------------------------------------------------------------
380
Vector3 PagingLandScapeData2D::getNormal(const Real& mX, const Real& mZ) const
382
// First General method : (9 adds and 6 muls + a normalization)
396
// BUT IN CASE OF A HEIGHTMAP :
398
// if you do some math by hand before you code,
399
// you can see that N is immediately given by
400
// Approximation (2 adds and a normalization)
402
// N = Vector3(z[x-1][y] - z[x+1][y], z[x][y-1] - z[x][y+1], 2);
405
// or even using SOBEL operator VERY accurate!
406
// (14 adds and a normalization)
408
// N = Vector3 (z[x-1][y-1] + z[x-1][y] + z[x-1][y] + z[x-1][y+1] - z[x+1][y-1] - z[x+1][y] - z[x+1][y] - z[x+1][y+1],
409
// z[x-1][y-1] + z[x][y-1] + z[x][y-1] + z[x+1][y-1] - z[x-1][y+1] - z[x][y+1] - z[x][y+1] - z[x+1][y+1],
416
const size_t pageSize = mSize - 1;
418
// the divider make sure we do respect proportion (height and width proportional to y)
419
const Real Divider = static_cast <Real> (pageSize) / mParent->getOptions()->scale.y;
421
assert (mHeightData);
423
#define getisIn(a, b) (mHeightData[static_cast<unsigned int> (a) + static_cast<unsigned int> (b) * mSize])
425
if (mX > 0 && mZ > 0 &&
426
mX < pageSize && mZ < pageSize)
429
// Vector3 result (getisIn(x-1,z-1) + getisIn (x-1, z) + getisIn (x-1, z) + getisIn (x-1, z+1) - getisIn (x+1, z-1) - getisIn (x+1, z) - getisIn (x+1, z) - getisIn (x+1, z+1),
431
// getisIn (x-1, z-1) + getisIn (x, z-1) + getisIn (x, z-1) + getisIn (x+1, z-1) - getisIn (x-1, z+1) - getisIn (x, z+1) - getisIn (x, z+1) - getisIn (x+1, z+1));
433
Vector3 result((getisIn (mX - 1 , mZ) - getisIn (mX + 1 , mZ)) * Divider,
435
(getisIn (mX, mZ - 1) - getisIn (mX , mZ + 1)) * Divider);
443
unsigned int x = static_cast <unsigned int> (mX);
444
unsigned int z = static_cast <unsigned int> (mZ);
450
b = getisIn (x + 1, z);
452
else if (x == pageSize)
454
a = getisIn (x - 1 , z);
459
a = getisIn (x - 1 , z);
460
b = getisIn (x + 1, z);
466
d = getisIn (x , z + 1);
468
else if (z == pageSize)
470
c = getisIn (x , z - 1);
475
c = getisIn (x , z - 1);
476
d = getisIn (x , z + 1);
480
Vector3 result((a - b) * Divider,
488
#define getisOut(a, b) (PagingLandScapeData2DManager::getSingleton ().getHeightAtPage (mPageX, mPageZ, static_cast<int> (a), static_cast<int> (b)))
490
// Vector3 result (getisOut(x-1,z-1) + getisOut (x-1, z) + getisOut (x-1, z) + getisOut (x-1, z+1) - getisOut (x+1, z-1) - getisOut (x+1, z) - getisOut (x+1, z) - getisOut (x+1, z+1),
492
// getisOut (x-1, z-1) + getisOut (x, z-1) + getisOut (x, z-1) + getisOut (x+1, z-1) - getisOut (x-1, z+1) - getisOut (x, z+1) - getisOut (x, z+1) - getisOut (x+1, z+1));
494
Vector3 result((getisOut (mX - 1 , mZ) - getisOut (mX + 1 , mZ)) * Divider,
496
(getisOut (mX, mZ - 1) - getisOut (mX , mZ + 1)) * Divider);
502
#endif //_MAPSPLITTER