Skip to content

Commit

Permalink
added bus ABM
Browse files Browse the repository at this point in the history
  • Loading branch information
MapTube committed May 10, 2015
1 parent 9e7184b commit e5d4235
Show file tree
Hide file tree
Showing 28 changed files with 981 additions and 83 deletions.
86 changes: 60 additions & 26 deletions GeoGL/GroundBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
//#include "gengine/shaderuniformcollection.h"
//#include "gengine/shaderuniform.h"
#include "cache/DataCache.h"
#include "async/meshworker.h"
#include "async/messagequeueeventargs.h"


using namespace std;

Expand All @@ -35,18 +38,33 @@ using namespace geogl::cache;

const int GroundBox::BoxZoomLevel = 14; // zoom level used for all ground boxes to make it easy to switch

GroundBox::GroundBox() {
GroundBox::GroundBox(gengine::GraphicsContext* workerGC) : _workerGC(workerGC) {
// TODO Auto-generated constructor stub
//_Tau=1.0;
//need min distance before boxes visible
//need min and max depth that there is data for

//set up a request queue for loading meshes asynchronously and a done queue for reporting back when they've been created on the gpu
_requestQueue.MessageReceived.push_back(new geogl::async::MeshWorker(_doneQueue,_workerGC)); //set up the worker that acts on the messages
_requestQueue.StartBackgroundThread();
//set up a done queue handler here to add the loaded mesh objects
//TODO: _Shader isn't actually set at this point!
_doneQueue.MessageReceived.push_back(new GroundBoxMeshWorker(_gndboxes,_Shader)); //this is the worker to put the meshes into the ground boxes array
}

GroundBox::~GroundBox() {
// TODO Auto-generated destructor stub
//TODO: free the meshes in the _gndboxes
}

void GroundBox::SetShader(gengine::Shader* shader) {
//if you change the shader, then you have to get rid of the mesh worker message queue and create another one with the new shader
//of course, anything not yet processed is destroyed, but then all the meshes need to be changed as well...
_Shader=shader;
_doneQueue.MessageReceived.clear();
_doneQueue.MessageReceived.push_back(new GroundBoxMeshWorker(_gndboxes,_Shader));
}

//get rid of this...
//void GroundBox::RenderLOD(gengine::GraphicsContext* GC,const gengine::SceneDataObject& sdo) {
// //you could set a limit on the maximum number of ground tiles to render, statically allocate them and only
Expand Down Expand Up @@ -135,13 +153,15 @@ std::string GetGeoJSONFilename(const int TileZ, const int TileX,const int TileY)
void GroundBox::ShuffleBoxes(const int TileZ, const int TileX, const int TileY) {
//If the centre box already has the correct tile xyz coords, then exit early. Although it is possible that the viewpoint
//could spin, leaving the centre correct and the others changes, we don't bother with direction so it makes no difference.
//std::cout<<"In ShuffleBoxes"<<std::endl;
if ((_gndboxes[4].TileX==TileX)&&(_gndboxes[4].TileY==TileY)&&(_gndboxes[4].TileZ==TileZ)) return;

//std::cout<<"ShuffleBoxes : about to shuffle"<<std::endl;

//OK, it's moved, so we are going to have to do some work
int oldx=_gndboxes[0].TileX, oldy=_gndboxes[0].TileY; //store old min box to check for reuse
BoxContent B[9];
int i=0;
std::set<void*> currentMeshes; //nullptr?
for (int y=TileY-1; y<=TileY+1; y++) {
for (int x=TileX-1; x<=TileX+1; x++) {
B[i].TileX=x;
Expand All @@ -151,31 +171,28 @@ void GroundBox::ShuffleBoxes(const int TileZ, const int TileX, const int TileY)
int x2=x-oldx;
int y2=y-oldy;
if ((x2>=0)&&(x2<=2)&&(y2>=0)&&(y2<=2)) {
B[i].mesh=_gndboxes[y2*3+x2].mesh;
currentMeshes.insert(B[i].mesh);
B[i].IsEmpty=false;
int i2=y2*3+x2;
B[i].mesh=std::move(_gndboxes[i2].mesh);
B[i].IsEmpty=_gndboxes[i2].IsEmpty; B[i].IsLoading=_gndboxes[i2].IsLoading;
}
else B[i].mesh=nullptr;
else { B[i].mesh=nullptr; B[i].IsEmpty=true; }
++i;
}
}
//now assign the local copy to the live copy and free any meshes that aren't being used
for (i=0; i<9; i++) {
if (!_gndboxes[i].IsEmpty) {
if (currentMeshes.find(_gndboxes[i].mesh)==currentMeshes.end()) {
//mesh no longer being used so get rid of it
delete _gndboxes[i].mesh;
}
}
//now assignment
_gndboxes[i].TileX=B[i].TileX;
_gndboxes[i].TileY=B[i].TileY;
_gndboxes[i].TileZ=B[i].TileZ;
_gndboxes[i].mesh=B[i].mesh;
_gndboxes[i].IsEmpty=B[i].IsEmpty;
_gndboxes[i].mesh=std::move(B[i].mesh);
_gndboxes[i].IsEmpty=B[i].IsEmpty; //(_gndboxes[i].mesh==nullptr); //DEBUG TRAP
_gndboxes[i].IsLoading=B[i].IsLoading;
}
//std::cout<<"Exit ShuffleBoxes"<<std::endl;
}


void GroundBox::UpdateData(const gengine::SceneDataObject& sdo) {
//work out closest point to ground and exit early if >min distance
//we know the earth is covered with patches (and the min zoom)
Expand All @@ -193,6 +210,8 @@ void GroundBox::UpdateData(const gengine::SceneDataObject& sdo) {
//need delta to be 2 x radius (side view of earth)
//RenderLOD(GC,sdo,_root,K,(float)Delta);

_doneQueue.ProcessQueue(); //update current ground boxes with any loaded meshes, anything not in view is disposed

//Patch method
//cheat and create an ellipsoid!!
Ellipsoid e;
Expand All @@ -212,9 +231,12 @@ void GroundBox::UpdateData(const gengine::SceneDataObject& sdo) {
int TileX,TileY;
LonLatToTileXY(geodetic3D,TileX,TileY);
ShuffleBoxes(BoxZoomLevel,TileX,TileY); //shuffle current data around centre box as it's unlikely to have moved much
//do a mesh done list check for any newly delivered complete meshes
//now initiate a load and cache check for any ground box meshes set as IsEmpty
//TODO:
//for all mesh worker messages... fill empty boxes and discard any meshes not required
for (int i=0; i<9; i++) {
if (_gndboxes[i].IsEmpty) {
if (!(_gndboxes[i].IsLoading)&&(_gndboxes[i].IsEmpty)) {
std::string TileFilename = GetGeoJSONFilename(_gndboxes[i].TileZ,_gndboxes[i].TileX,_gndboxes[i].TileY); //shouldn't this be a URL?
if (dc->GetRemoteFile(TileFilename)) { //kick off async loading, if the file arrives while still in frame then it gets drawn
std::string LocalFilename = dc->GetLocalCacheFilename(TileFilename); //file is available
Expand All @@ -228,20 +250,24 @@ void GroundBox::UpdateData(const gengine::SceneDataObject& sdo) {
//_gndboxes[i].mesh=geoj;

//load pre-computed obj file - this should also be in a thread
Mesh2* mesh = new Mesh2();
mesh->_VertexFormat=gengine::PositionColourNormal;
mesh->FromOBJ(LocalFilename);
mesh->CreateBuffers();
mesh->AttachShader(_Shader,true);
mesh->SetColour(glm::vec3(1.0f,0.0f,0.0f));
_gndboxes[i].mesh=mesh;
cout<<"Mesh Loaded"<<endl;
//this is the bit that needs to push a mesh worker message
//Mesh2* mesh = new Mesh2();
//mesh->_VertexFormat=gengine::PositionColourNormal;
//mesh->FromOBJ(LocalFilename);
//mesh->CreateBuffers();
//mesh->AttachShader(_Shader,true);
//mesh->SetColour(glm::vec3(1.0f,0.0f,0.0f));
//_gndboxes[i].mesh=mesh;
//cout<<"Mesh Loaded"<<endl;
_requestQueue.Post(new geogl::async::MeshWorkerMsg(LocalFilename,_gndboxes[i].TileX,_gndboxes[i].TileY,_gndboxes[i].TileZ));
//_gndboxes[i].IsEmpty=true; //set flag to false until it's loaded - it's already false (see above)
_gndboxes[i].IsLoading=true; //so we don't try and load it again while it's still in flight

//DEBUG - push a coloured ground square to show the grid
//geoj->AddChild(DebugMesh(BoxZoomLevel,_gndboxes[i].TileX,_gndboxes[i].TileY));
//geoj->AttachShader(_Shader,true);
//END DEBUG
_gndboxes[i].IsEmpty=false; //don't forget to set the flag
//_gndboxes[i].IsEmpty=false; //don't forget to set the flag
}
}
}
Expand All @@ -263,10 +289,18 @@ void GroundBox::Render(gengine::GraphicsContext* GC,const gengine::SceneDataObje
// GC->Render(dobj,sdo);
//}


//Mesh2 Render
//Here, we only have the parent mesh object to render
const DrawObject& dobj = _gndboxes[i].mesh->GetDrawObject();
GC->Render(dobj,sdo);
if (_gndboxes[i].mesh==NULL) {
std::cerr<<"FAULT: NULL BOX "
<<i<<": "<<_gndboxes[i].TileX<<" "<<_gndboxes[i].TileY<<" "<<_gndboxes[i].IsLoading<<std::endl;
//HACK! need to fix this as it shouldn't happen!
}
else {
const DrawObject& dobj = _gndboxes[i].mesh->GetDrawObject();
GC->Render(dobj,sdo);
}
}
}
}
Expand Down
69 changes: 65 additions & 4 deletions GeoGL/GroundBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

#include "object3d.h"
#include "mesh2.h"
#include "async/messagequeue.h"
#include "async/worker.h"
#include "async/meshworker.h"

#include <memory>

//forward references
namespace gengine {
Expand All @@ -14,26 +19,82 @@ namespace gengine {
class Shader;
}



////////////////////////////////////////////////////////////////////////////////////////////////////////

struct BoxContent {
bool IsEmpty;
bool IsLoading;
int TileX,TileY,TileZ;
Object3D* mesh;
BoxContent() { TileX=0; TileY=0; TileZ=0; mesh=nullptr; IsEmpty=true; };
std::unique_ptr<Mesh2> mesh;
BoxContent() { TileX=0; TileY=0; TileZ=0; mesh=nullptr; IsEmpty=true; IsLoading=false; };
};


////////////////////////////////////////////////////////////////////////////////////////////////////////

///<summary>
/// GroundBoxMeshWorker
/// Puts loaded meshes from the done queue into the correct places in the ground box structure (BoxContent)
/// TODO: should really be private and the 9 should NOT be hard coded
///</summary>
class GroundBoxMeshWorker : public geogl::async::Worker {
private:
BoxContent* _boxes; //array of [9];
gengine::Shader* _Shader;
public:
GroundBoxMeshWorker(BoxContent* boxes, gengine::Shader* shader) : _boxes(boxes), _Shader(shader) {}
void Process(geogl::async::MessageQueueEventArgs& args) {
//take the payload of the completed message and apply the new mesh to the relevant box
std::cout<<"GroundBoxMeshWorker: In GroundBoxMeshWorker"<<std::endl;
geogl::async::MeshWorkerMsg* meshmsg = dynamic_cast<geogl::async::MeshWorkerMsg*>(args.umessage.get());
std::cout<<"GroundBoxMeshWorker: "<<meshmsg->src<<" "<<meshmsg->TileZ<<" "<<meshmsg->TileX<<" "<<meshmsg->TileY<<std::endl;
if (!args.Success) return;
for (int i=0; i<9; i++) {
if ((_boxes[i].IsEmpty)
&&(_boxes[i].TileX==meshmsg->TileX)
&&(_boxes[i].TileY==meshmsg->TileY)
&&(_boxes[i].TileZ==meshmsg->TileZ)) {
std::cout<<"GroundBoxMeshWorker: Mesh moved "
<<_boxes[i].TileZ<<" "<<_boxes[i].TileX<<" "<<_boxes[i].TileY<<std::endl;
_boxes[i].mesh=std::move(meshmsg->mesh);
_boxes[i].mesh->AttachShader(_Shader,true);
_boxes[i].mesh->SetColour(glm::vec3(1.0f,0.0f,0.0f));
_boxes[i].IsEmpty=false;
_boxes[i].IsLoading=false;
std::cout<<"GroundBoxMeshWorker: Mesh moved end "
<<_boxes[i].TileZ<<" "<<_boxes[i].TileX<<" "<<_boxes[i].TileY<<std::endl;
//std::cout<<"Mesh: vertices="<<_boxes[i].mesh.get()<<std::endl;
break;
}
}
}
};

////////////////////////////////////////////////////////////////////////////////////////////////////////

class GroundBox : public Object3D {
private:
gengine::GraphicsContext* _workerGC; //graphics context for the mesh loader background thread - make this into a shared_ptr?
gengine::Shader* _Shader; //shader used for rendering
//message queues for loading meshes in the background
geogl::async::MessageQueue _requestQueue;
geogl::async::MessageQueue _doneQueue;
BoxContent _gndboxes[9];
Mesh2* DebugMesh(const int TileZ,const int TileX,const int TileY);
protected:
void ShuffleBoxes(const int TileZ, const int TileX, const int TileY);
void ProcessLoadedMeshes();
void UpdateData(const gengine::SceneDataObject& sdo);
public:
static const int BoxZoomLevel; //zoom level used for all boxes (i.e. switchable between 12 and 13)
gengine::Shader* _Shader; //shader used for rendering
GroundBox();

GroundBox(gengine::GraphicsContext* workerGC);
virtual ~GroundBox();

void SetShader(gengine::Shader* shader);

void LonLatToTileXY(glm::dvec3 RadGeodetic3D,int& TileX,int& TileY);
virtual void Render(gengine::GraphicsContext* GC,const gengine::SceneDataObject& sdo);
virtual bool HasGeometry() { return true; } //yes, this object has geometry associated with it and can be rendered
Expand Down
5 changes: 3 additions & 2 deletions GeoGL/Link.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace ABM {
class Link
{
public:
static Links* _pParentLinks; //parent of all Link classes - Linkss, which needs to keep a list of its children
static Links* _pParentLinks; //parent of all Link classes - Links, which needs to keep a list of its children
std::string _BreedName;
Agent* end1; //agent at start end of link
Agent* end2; //agent at destination end of link
glm::vec3 colour; //colour of this link
Expand Down Expand Up @@ -151,5 +152,5 @@ namespace ABM {

};

}
} //namespace ABM

Loading

0 comments on commit e5d4235

Please sign in to comment.