Skip to content

Commit

Permalink
Merge branch 'PquadTree'
Browse files Browse the repository at this point in the history
  • Loading branch information
latami committed Dec 6, 2016
2 parents 3cae9a8 + 673a490 commit d9115aa
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 29 deletions.
30 changes: 29 additions & 1 deletion HeightMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. */

#include <assert.h>
#include "HeightMap.h"
#include "Common.h"

Expand All @@ -40,7 +41,8 @@ HeightMap::HeightMap(unsigned int size,

RParam = param;
seaHeight = Height_sea;
textureResolution = 256;
textureResolution = 128;
this->entity = NULL;

height = allocate2DArray<float>(size, size);
memset(height[0], 0, sizeof(float)*size*size);
Expand Down Expand Up @@ -323,6 +325,7 @@ void HeightMap::unload(Ogre::SceneNode *node, Ogre::SceneManager *scene)
{
node->detachObject(this->entity->getName());
scene->destroyEntity(this->entity->getName());
this->entity = NULL;
}

void HeightMap::bufferMesh(const std::string &meshName, float scalingFactor)
Expand Down Expand Up @@ -527,3 +530,28 @@ void HeightMap::getChildren(HeightMap *&upperLeft, HeightMap *&upperRight,
lowerLeft = this->child[2];
lowerRight = this->child[3];
}

HeightMap *HeightMap::getChild(unsigned char child)
{
assert(child < 4);
return this->child[child];
}

Ogre::Vector3 HeightMap::getCenterPosition()
{
Ogre::Vector2 tileCenter;
Ogre::Vector3 pos;

tileCenter = (this->UpperLeft + this->LowerRight)/2.0f;
pos = Ogre::Vector3(tileCenter.x, 1.0f, tileCenter.y).normalisedCopy();

return this->orientation*pos*RParam->getRadius();
}

bool HeightMap::isLoaded()
{
if (this->entity != NULL)
return true;
else
return false;
}
5 changes: 5 additions & 0 deletions HeightMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class HeightMap: public Grid
void getChildren(HeightMap *&upperLeft, HeightMap *&upperRight,
HeightMap *&lowerLeft, HeightMap *&lowerRight);

HeightMap *getChild(unsigned char child);

Ogre::Vector3 getCenterPosition();

bool isLoaded();
private:
float **height;
float minHeight;
Expand Down
2 changes: 2 additions & 0 deletions Linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ set(HDRS
../initOgre.h
../Grid.h
../HeightMap.h
../PquadTree.h
../CollisionManager.h
../Common.h
../ResourceParameter.h
Expand All @@ -108,6 +109,7 @@ set(SRCS
../main.cpp
../Grid.cpp
../HeightMap.cpp
../PquadTree.cpp
../CollisionManager.cpp
../Common.cpp
../ResourceParameter.cpp
Expand Down
52 changes: 31 additions & 21 deletions PSphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ PSphere::PSphere(Ogre::uint32 iters, Ogre::uint32 gridSize, ResourceParameter re

exportImage = NULL;
observer = Ogre::Vector3(0.0f, 0.0f, 0.0f);
this->scene = NULL;
this->node = NULL;

create(iters, gridSize, resourceParameter);
}
Expand Down Expand Up @@ -116,22 +118,22 @@ void PSphere::create(Ogre::uint32 iters, Ogre::uint32 gridSize, ResourceParamete
calculateSeaLevel(minimumHeight, maximumHeight, waterFraction);

// No rotation
faceYP = new HeightMap(iters, noRot, upperL, lowerR, &RParameter, seaHeight);
faceYP = new PquadTree("YP", iters, noRot, seaHeight, &RParameter);
gridYP = new Grid(gridSize, noRot, upperL_g, lowerR_g);
// 90 degrees through z-axis
faceXM = new HeightMap(iters, rotZ_90, upperL, lowerR, &RParameter, seaHeight);
faceXM = new PquadTree("XM", iters, rotZ_90, seaHeight, &RParameter);
gridXM = new Grid(gridSize, rotZ_90, upperL_g, lowerR_g);
// 180 degrees through z-axis
faceYM = new HeightMap(iters, rotZ_180, upperL, lowerR, &RParameter, seaHeight);
faceYM = new PquadTree("YM", iters, rotZ_180, seaHeight, &RParameter);
gridYM = new Grid(gridSize, rotZ_180, upperL_g, lowerR_g);
// 270 degrees through z-axis
faceXP = new HeightMap(iters, rotZ_270, upperL, lowerR, &RParameter, seaHeight);
faceXP = new PquadTree("XP", iters, rotZ_270, seaHeight, &RParameter);
gridXP = new Grid(gridSize, rotZ_270, upperL_g, lowerR_g);
// 90 degrees through x-axis
faceZP = new HeightMap(iters, rotX_90, upperL, lowerR, &RParameter, seaHeight);
faceZP = new PquadTree("ZP", iters, rotX_90, seaHeight, &RParameter);
gridZP = new Grid(gridSize, rotX_90, upperL_g, lowerR_g);
// 270 degrees through x-axis
faceZM = new HeightMap(iters, rotX_270, upperL, lowerR, &RParameter, seaHeight);
faceZM = new PquadTree("ZM", iters, rotX_270, seaHeight, &RParameter);
gridZM = new Grid(gridSize, rotX_270, upperL_g, lowerR_g);

gridYP->setNeighbours(gridXM, gridXP, gridZP, gridZM);
Expand Down Expand Up @@ -302,7 +304,21 @@ void PSphere::setGridLandInfo(Grid *grid)

void PSphere::setObserverPosition(Ogre::Vector3 position)
{
observer = position;
/* Avoid updating before scene is set */
if ( (this->scene != NULL) && (this->node != NULL) )
{
/* Convert to model coordinates */
this->observer = this->node->convertWorldToLocalPosition(position);

faceYP->update(this->observer);
faceXM->update(this->observer);
faceYM->update(this->observer);
faceXP->update(this->observer);
faceZP->update(this->observer);
faceZM->update(this->observer);
}
else
this->observer = position;
}

Ogre::Real PSphere::getObserverDistanceToSurface()
Expand Down Expand Up @@ -368,24 +384,18 @@ PSphere* PSphere::getAstroChild(const std::string &objectName)
void PSphere::load(Ogre::SceneNode *parent, Ogre::SceneManager *scene, const std::string &planetName)
{
this->node = parent->createChildSceneNode(planetName);

faceYP->load(this->node, scene, planetName+"_YP", radius);
faceXM->load(this->node, scene, planetName+"_XM", radius);
faceYM->load(this->node, scene, planetName+"_YM", radius);
faceXP->load(this->node, scene, planetName+"_XP", radius);
faceZP->load(this->node, scene, planetName+"_ZP", radius);
faceZM->load(this->node, scene, planetName+"_ZM", radius);
this->scene = scene;

faceYP->setScene(scene, node);
faceXM->setScene(scene, node);
faceYM->setScene(scene, node);
faceXP->setScene(scene, node);
faceZP->setScene(scene, node);
faceZM->setScene(scene, node);
}

void PSphere::unload(Ogre::SceneManager *scene)
{
faceYP->unload(this->node, scene);
faceXM->unload(this->node, scene);
faceYM->unload(this->node, scene);
faceXP->unload(this->node, scene);
faceZP->unload(this->node, scene);
faceZM->unload(this->node, scene);

scene->destroySceneNode(this->node);
}

Expand Down
15 changes: 9 additions & 6 deletions PSphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "HeightMap.h"
#include "ResourceParameter.h"
#include "CollisionManager.h"
#include "PquadTree.h"

using namespace std;


Expand Down Expand Up @@ -132,14 +134,15 @@ class PSphere
Ogre::Real radius;
Ogre::Real seaHeight;
Ogre::SceneNode *node;
Ogre::SceneManager *scene;
unsigned char *exportImage;
Ogre::Vector3 observer;
HeightMap *faceYP;
HeightMap *faceXM;
HeightMap *faceYM;
HeightMap *faceXP;
HeightMap *faceZP;
HeightMap *faceZM;
PquadTree *faceYP;
PquadTree *faceXM;
PquadTree *faceYM;
PquadTree *faceXP;
PquadTree *faceZP;
PquadTree *faceZM;
Grid *gridYP;
Grid *gridXM;
Grid *gridYM;
Expand Down
181 changes: 181 additions & 0 deletions PquadTree.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/* The MIT License (MIT)
*
* Copyright (c) 2016 Taneli Mikkonen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. */

#include <sstream>
#include "PquadTree.h"

PquadTree::PquadTree(const std::string name, Ogre::uint16 levelSize,
Ogre::Matrix3 orientation, Ogre::Real seaHeight,
std::ResourceParameter *parameters)
{
Ogre::Vector2 upperLeft, lowerRight;

this->name = name;
this->params = parameters;
this->runningNumber = 0;

upperLeft = Ogre::Vector2(-1.0f, 1.0f);
lowerRight = Ogre::Vector2(1.0f, -1.0f);

this->root = new HeightMap(levelSize, orientation, upperLeft, lowerRight,
parameters, seaHeight);

std::vector <HeightMap *> childQueue;
HeightMap *child[4];
Ogre::uint8 level = 0;

/* Create full static quadtree up to level 4 for leaf-nodes. Breadth-first. */
childQueue.push_back(this->root);
while(level < 4)
{
int i = childQueue.size() - static_cast<int>(Ogre::Math::Pow(4, level));
int iters = childQueue.size();
for(; i < iters; i++)
{
childQueue[i]->createChildren();
childQueue[i]->getChildren(child[0], child[1], child[2], child[3]);
childQueue.push_back(child[0]);
childQueue.push_back(child[1]);
childQueue.push_back(child[2]);
childQueue.push_back(child[3]);

}
level++;
}
}

PquadTree::~PquadTree()
{
std::vector <HeightMap *> childQueue;
HeightMap *child[4];

/* Get all nodes in the tree. Breadth-first. */
childQueue.push_back(this->root);
unsigned int i=0, previousSize;
while (1) {
previousSize = childQueue.size();
/* i should be correct from previous iteration */
for(; i < previousSize; i++)
{
childQueue[i]->getChildren(child[0], child[1], child[2], child[3]);
/* Correct quadtree has either all 4 children or none at all. */
if (child[0] != NULL)
{
childQueue.push_back(child[0]);
childQueue.push_back(child[1]);
childQueue.push_back(child[2]);
childQueue.push_back(child[3]);
}
}
if (previousSize == childQueue.size())
break;
}

std::cout << "PquadTree \"" << this->name << "\": deleting "
<< childQueue.size() << " nodes." << std::endl;

while (childQueue.size() > 0)
{
delete childQueue[childQueue.size()-1];
childQueue.pop_back();
}
}

void PquadTree::recursiveTest(HeightMap *node, Ogre::Vector3 viewer,
float distanceTest, Ogre::uint16 level)
{
Ogre::Vector3 distTocenter;
float distance;
std::stringstream levelSS, runningSS;
std::string hName, ss_str;

/* Make individual name for every tile. qtree-name + _l<level> + _<running> */
/* FIXME: Tiny, but non-zero change, that 2 different entitys have same name. */
levelSS << level;
hName = this->name + "_l";
ss_str = levelSS.str();
runningSS << this->runningNumber;
ss_str = ss_str + "_" + runningSS.str();
hName = hName + ss_str;

this->runningNumber++;

distTocenter = node->getCenterPosition() - viewer;
distance = distTocenter.length();

/* If distance is bigger than test, render tile. */
if (distance > distanceTest )
{
if (node->isLoaded() == false)
{
node->load(this->scNode, this->scene, hName, params->getRadius());

/* FIXME: Assumes checking one level up is enough, but might not be
* in every case, e.g. camera backing off quicly. */
if (node->getChild(0) != NULL)
{
for(int i=0; i < 4; i++)
{
/* Unload child-tiles, if previously loaded. */
if (node->getChild(i)->isLoaded() == true)
node->getChild(i)->unload(scNode, scene);
}
}
}
}
/* Sub-divide. */
else if (node->getChild(0) != NULL)
{
if (node->isLoaded() == true)
node->unload(scNode, scene);

distanceTest /= 2.0f;

level++;
for(int i=0; i < 4; i++)
{
recursiveTest(node->getChild(i), viewer, distanceTest, level);

}
}
/* Leaf reached. */
else
{
if (node->isLoaded() == false)
node->load(this->scNode, this->scene, hName, params->getRadius());
}
return;
}

void PquadTree::update(Ogre::Vector3 viewer)
{
Ogre::Real subdivideDistance = 40.5f;

/* Test for a subdivision in the quadtree. Depth-first. */
recursiveTest(this->root, viewer, subdivideDistance, 0);
}

void PquadTree::setScene(Ogre::SceneManager *scene, Ogre::SceneNode *node)
{
this->scene = scene;
this->scNode = node;
}
Loading

0 comments on commit d9115aa

Please sign in to comment.