voxelTerrain
 All Classes Functions Variables Typedefs Enumerations Pages
surface.hpp
1 #ifndef PROCEDURAL_VOXEL_SIMPLE_SURFACE_HPP
2 #define PROCEDURAL_VOXEL_SIMPLE_SURFACE_HPP
3 
4 
5 #include "blub/core/globals.hpp"
6 #include "blub/core/hashList.hpp"
7 #include "blub/core/hashMap.hpp"
8 #include "blub/core/signal.hpp"
9 #include "blub/math/vector3int.hpp"
10 #include "blub/procedural/log/global.hpp"
11 #include "blub/procedural/voxel/simple/accessor.hpp"
12 
13 #include <boost/signals2/connection.hpp>
14 
15 
16 namespace blub
17 {
18 namespace procedural
19 {
20 namespace voxel
21 {
22 namespace simple
23 {
24 
25 
29 template <class configType>
30 class surface : public base<typename configType::t_surface::t_tile>
31 {
32 public:
33  typedef configType t_config;
34  typedef typename t_config::t_surface::t_tile t_tile;
35  typedef sharedPointer<t_tile> t_tilePtr;
36  typedef base<t_tile> t_base;
37 
38  typedef typename t_base::t_tileId t_tileId;
39 
40  typedef hashMap<t_tileId, t_tilePtr> t_tilesMap;
41  typedef hashList<vector3int32> t_tileIdList;
42 
43  typedef typename t_config::t_accessor::t_tile t_tileAccessor;
44  typedef sharedPointer<t_tileAccessor> t_tileAccessorPtr;
45  typedef base<t_tileAccessor> t_voxelAccessor;
46 
47 
55  t_voxelAccessor& voxels,
56  const int32& lod)
57  : t_base(worker)
58  , m_voxels(voxels)
59  , m_lod(lod)
60  , m_numTilesInWork(0)
61  {
62  voxels.signalEditDone()->connect(boost::bind(&surface::editDone, this));
63 
64  t_base::setCreateTileCallback(boost::bind(&t_tile::create));
65  }
70  {
71  ;
72  }
73 
78  int32 getTileCount() const
79  {
80  return m_tiles.size();
81  }
86  real getVoxelSize() const
87  {
88  return math::pow(2., m_lod);
89  }
90 
96  t_tilePtr getTile(const blub::vector3int32& id) const
97  {
98  typename t_tilesMap::const_iterator it(m_tiles.find(id));
99  if (it == m_tiles.cend())
100  {
101  return nullptr;
102  }
103  return it->second;
104  }
105 
112  t_tilePtr getOrCreateTile(const blub::vector3int32& id) const
113  {
114  t_tilePtr workTile(getTile(id));
115  if (workTile.isNull())
116  {
117  return t_base::createTile();
118  }
119  return workTile;
120  }
121 
122 protected:
126  void editDone()
127  {
128  m_voxels.lockForRead();
129 
130  t_base::m_master.post(boost::bind(&surface::editDoneMaster, this));
131  }
132 
139  {
140  const typename t_voxelAccessor::t_tilesGotChangedMap& change(m_voxels.getTilesThatGotEdited());
141 #ifdef BLUB_LOG_VOXEL
142  BLUB_PROCEDURAL_LOG_OUT() << "surface editDoneMaster change.size():" << change.size();
143 #endif
144  if (change.empty())
145  {
146  BLUB_PROCEDURAL_LOG_WARNING() << "change.empty()";
147  return;
148  }
149 
151 
152  BASSERT(m_numTilesInWork == 0);
153  m_numTilesInWork = change.size();
154 
155  for (auto work : change)
156  {
157  if (work.second.isNull())
158  {
159  afterCalculateSurfaceMaster(work.first, nullptr);
160  continue;
161  }
162 
163  BASSERT(!work.second->isEmpty());
164  BASSERT(!work.second->isFull());
165 
166  t_tilePtr workTile(getTile(work.first));
167 
168  t_base::m_worker.post(boost::bind(&surface::calculateSurfaceTS, this, work.first, work.second, workTile));
169  }
170  }
171 
180  void calculateSurfaceTS(const t_tileId id, t_tileAccessorPtr work, t_tilePtr workTile)
181  {
182  if (workTile.isNull())
183  {
184  workTile = t_base::createTile();
185  }
186  workTile->calculateSurface(work,
187  getVoxelSize(),
188  true,
189  m_lod);
190 
191  if (workTile->getIndices().empty())
192  {
193 #ifdef BLUB_LOG_VOXEL
194  BLUB_PROCEDURAL_LOG_WARNING() << "workTile->getIndices().empty() id:" << id << " m_lod:" << m_lod << " work->getNumVoxelLargerZero():" << work->getNumVoxelLargerZero();
195 #endif
196  t_base::m_master.post(boost::bind(&surface::afterCalculateSurfaceMaster, this, id, nullptr));
197  return;
198  }
199 
200  t_base::m_master.post(boost::bind(&surface::afterCalculateSurfaceMaster, this, id, workTile));
201  }
202 
209  void afterCalculateSurfaceMaster(const t_tileId& id, t_tilePtr workTile)
210  {
211 #ifdef BLUB_LOG_VOXEL
212  BLUB_LOG_OUT() << "afterCalculateSurfaceMaster id:" << id;
213 #endif
214 
215  typename t_tilesMap::const_iterator it(m_tiles.find(id));
216 
217  int32 numIndices(0);
218  if (!workTile.isNull())
219  {
220  numIndices = workTile->getIndices().size();
221  }
222 
223  // no indices
224  if (numIndices == 0)
225  {
226  if (it != m_tiles.cend())
227  {
228  t_base::addToChangeList(id, nullptr);
229  m_tiles.erase(it);
230  }
231  }
232  else
233  {
234  BASSERT(!workTile.isNull());
235  if (it == m_tiles.cend())
236  {
237  m_tiles.insert(id, workTile);
238  }
239  t_base::addToChangeList(id, workTile);
240  }
241 
242  --m_numTilesInWork;
243  BASSERT(m_numTilesInWork >= 0);
244  if (m_numTilesInWork == 0)
245  {
246  m_voxels.unlockRead();
248  }
249  }
250 
251 
252 private:
253  t_tilesMap m_tiles;
254 
255  t_voxelAccessor &m_voxels;
256  int32 m_lod;
257  int32 m_numTilesInWork;
258 
259  boost::signals2::scoped_connection m_connTilesGotChanged;
260 
261 };
262 
263 
264 }
265 }
266 }
267 }
268 
269 
270 #endif // PROCEDURAL_VOXEL_SIMPLE_SURFACE_HPP
void calculateSurfaceTS(const t_tileId id, t_tileAccessorPtr work, t_tilePtr workTile)
calculateSurfaceTS gets called by editDoneMaster(), by any worker-thread. Calls afterCalculateSurface...
Definition: surface.hpp:180
virtual void lockForEditMaster()
lockForEditMaster locks for write, or waits until possible. Call by master dispatcher.
Definition: base.hpp:228
Definition: customVertexInformation.cpp:193
vector3int32 t_tileId
Definition: base.hpp:44
void editDoneMaster()
editDoneMaster same like editDone() but on master-thread. Write locks class, dispatches surface gener...
Definition: surface.hpp:138
virtual t_tilePtr createTile() const
createTile creates a new Tile. Uses callback set by setCreateTileCallback()
Definition: base.hpp:249
virtual void unlockForEditMaster()
unlockForEditMaster unlocks write. Call by master dispatcher.
Definition: base.hpp:236
const t_tilesGotChangedMap & getTilesThatGotEdited() const
getTilesThatGotEdited returns a list of tiles which changed since the last call lockForEdit() / lockF...
Definition: base.hpp:198
void addToChangeList(const t_tileId &id, t_tilePtr toAdd)
addToChangeList adds a tile to the change-list.
Definition: base.hpp:210
t_tilePtr getOrCreateTile(const blub::vector3int32 &id) const
getOrCreateTile returns same like getTile() except that when not found instances a new tile...
Definition: surface.hpp:112
void unlockRead()
unlockRead unlocks the class after reading.
Definition: base.hpp:192
int32 getTileCount() const
getTileCount returns the tile count calculated by this class. Read-lock class before calling...
Definition: surface.hpp:78
surface(blub::async::dispatcher &worker, t_voxelAccessor &voxels, const int32 &lod)
surface constructor.
Definition: surface.hpp:54
Definition: dispatcher.hpp:29
void afterCalculateSurfaceMaster(const t_tileId &id, t_tilePtr workTile)
afterCalculateSurfaceMaster gets called by calculateSurfaceTS() on master-thread. ...
Definition: surface.hpp:209
real getVoxelSize() const
getVoxelSize returns the voxel-size.
Definition: surface.hpp:86
void lockForRead()
lockForRead locks the class for reading.
Definition: base.hpp:186
t_sigEditDone * signalEditDone()
signalEditDone gets called after unlockForEdit() got called.
Definition: base.hpp:261
blub::async::dispatcher & m_worker
m_worker use it to dispatch heavy work. Don't write to class member with it. Do not use any locks...
Definition: base.hpp:148
Definition: deadlineTimer.hpp:10
blub::async::strand m_master
m_master The master synchronises jobs for the worker-thread and writes to class member. The master calls all methods which end with *Master.
Definition: base.hpp:143
The accessor class contains a custom amount of level of details of type simple::accessor.
Definition: predecl.hpp:60
t_tilePtr getTile(const blub::vector3int32 &id) const
getTile returns a surface-tile. Lock-read class before.
Definition: surface.hpp:96
void editDone()
editDone gets called when data in accessor changed.
Definition: surface.hpp:126
void setCreateTileCallback(const t_createTileCallback &callback)
setCreateTileCallback sets a callback for creating tiles. Use this method if you want to create custo...
Definition: base.hpp:204
~surface()
~surface destructor.
Definition: surface.hpp:69