voxelTerrain
 All Classes Functions Variables Typedefs Enumerations Pages
base.hpp
1 #ifndef VOXEL_SIMPLE_CONTAINER_BASE_HPP
2 #define VOXEL_SIMPLE_CONTAINER_BASE_HPP
3 
4 #include "blub/core/sharedPointer.hpp"
5 #include "blub/math/axisAlignedBox.hpp"
6 #include "blub/math/axisAlignedBoxInt32.hpp"
7 #include "blub/math/transform.hpp"
8 #include "blub/procedural/voxel/simple/base.hpp"
9 #include "blub/procedural/voxel/simple/container/utils/tile.hpp"
10 
11 
12 namespace blub
13 {
14 namespace procedural
15 {
16 namespace voxel
17 {
18 namespace simple
19 {
20 namespace container
21 {
22 
23 
29 template <class configType>
30 class base : public simple::base<typename configType::t_container::t_tile>
31 {
32 public:
33  typedef configType t_config;
34  typedef typename t_config::t_data t_voxel;
35  typedef typename configType::t_container::t_tile t_tile;
36  typedef simple::base<t_tile> t_base;
37  typedef sharedPointer<t_tile> t_tilePtr;
38  typedef utils::tile<t_tile> t_utilsTile;
39 
40  typedef sharedPointer<edit::base<t_config> const> t_editConstPtr;
41  typedef sharedPointer<edit::base<t_config> > t_editPtr;
42  typedef typename t_base::t_tileId t_tileId;
43 
44  typedef hashMap<t_tileId, t_utilsTile> t_tilesGotChangedMap;
45 
51  : t_base(worker)
52  , m_numInTilesInTask(0)
53  {
54 
55  }
56 
64  void editVoxel(t_editConstPtr change, const transform &trans = blub::transform())
65  {
66  t_base::m_master.post(boost::bind(&base::editMaster, this, change, trans));
67  }
68 
76 // void editVoxel(t_editPtr change, const transform &trans = blub::transform())
77 // {
78 // editVoxel(change.template staticCast<const edit::base<t_config> >(), trans);
79 // }
80 
87  void setTile(const t_tileId& id, const t_utilsTile& toSet)
88  {
89  t_base::m_master.post(boost::bind(&base::setTileMaster, this, id, toSet));
90  }
91 
98  virtual t_utilsTile getTileHolder(const t_tileId& id) const = 0;
104  t_utilsTile getTileHolderByVoxelPosition(const blub::vector3int32& pos) const
105  {
107  }
108 
114  t_voxel getVoxel(const vector3int32& voxelPos) const
115  {
116  t_utilsTile workTile(getTileHolderByVoxelPosition(voxelPos));
117 
118  t_voxel result;
119  if (workTile.state == utils::tileState::full)
120  {
121  result.setMax();
122  return result;
123  }
124  if (workTile.state == utils::tileState::empty)
125  {
126  result.setMin();
127  return result;
128  }
129  return workTile.data->getVoxel(calculateVoxelPosInTile(voxelPos));
130  }
131 
137  static t_tileId calculateVoxelPosToTileId(const vector3int32& voxelPos)
138  {
139  return vector3int32((blub::vector3(voxelPos) / (real)t_config::voxelsPerTile).getFloor());
140  }
141 
147  static vector3int32 calculateVoxelPosInTile(const vector3int32& voxelPos) // TODO floor?!
148  {
149  vector3int32 result(voxelPos % t_config::voxelsPerTile);
150  if (voxelPos.x < 0 && voxelPos.x%t_config::voxelsPerTile != 0)
151  {
152  result.x = t_config::voxelsPerTile + result.x;
153  }
154  if (voxelPos.y < 0 && voxelPos.y%t_config::voxelsPerTile != 0)
155  {
156  result.y = t_config::voxelsPerTile + result.y;
157  }
158  if (voxelPos.z < 0 && voxelPos.z%t_config::voxelsPerTile != 0)
159  {
160  result.z = t_config::voxelsPerTile + result.z;
161  }
162  return result;
163  }
164 
165  const t_tilesGotChangedMap &getTilesThatGotEdited() const
166  {
167  return m_tilesThatGotEdited;
168  }
169 
170 protected:
171  void addToChangeList(const t_tileId &id, t_utilsTile toAdd)
172  {
173  BASSERT(!t_base::m_classLocker.tryLockForWrite());
174  m_tilesThatGotEdited.insert(id, toAdd);
175  }
176  void unlockForEditMaster() override
177  {
179  if (!m_tilesThatGotEdited.empty())
180  {
181  t_base::m_sigEditDone();
182  }
183  }
184  bool tryLockForEditMaster() override
185  {
186  const bool success(t_base::tryLockForEditMaster());
187  if (success)
188  {
189  m_tilesThatGotEdited.clear();
190  }
191  return success;
192  }
193  void lockForEditMaster() override
194  {
196  m_tilesThatGotEdited.clear();
197  }
198 
202  struct editTodo
203  {
204  editTodo(const t_editConstPtr change, const blub::transform& trans_)
205  : edit_(change)
206  , trans(trans_)
207  {
208  ;
209  }
210  editTodo(const editTodo& other)
211  : edit_(other.edit_)
212  , trans(other.trans)
213  {
214  ;
215  }
216  const editTodo& operator = (const editTodo& other)
217  {
218  edit_ = other.edit_;
219  trans = other.trans;
220 
221  return *this;
222  }
223 
224  t_editConstPtr edit_;
225  transform trans;
226  };
227 
228 
234  void editMaster(t_editConstPtr change, const blub::transform& trans)
235  {
236  #ifdef BLUB_LOG_VOXEL
237  blub::BOUT("base::editVoxel");
238  #endif
239 
240  editTodo edit(change, trans);
241 
242  m_editsTodo.push_back(edit);
243 
245  }
246 
251  void doNextEditMaster(const bool &alreadyLocked = false)
252  {
253  #ifdef BLUB_LOG_VOXEL
254  blub::BOUT("base::doNextEditMaster");
255  #endif
256  BASSERT(m_numInTilesInTask >= 0);
257 
258  if (m_editsTodo.empty())
259  {
260  return;
261  }
262  if (m_numInTilesInTask > 0)
263  {
264  return;
265  }
266 
267  if (!alreadyLocked)
268  {
270  }
271 
272  BASSERT(m_numInTilesInTask == 0);
273 
274  editTodo edit(*m_editsTodo.begin());
275  m_editsTodo.erase(m_editsTodo.begin());
276  t_editConstPtr change(edit.edit_);
277 
278  const blub::transform trans(edit.trans);
279  const blub::axisAlignedBox aabb(change->getAxisAlignedBoundingBox(trans));
280  const blub::axisAlignedBoxInt32 aabbScaled(aabb.getMinimum(), aabb.getMaximum());
281  blub::vector3int32 startEdit;
282  blub::vector3int32 endEdit;
283 
284  calculateAffectetedTilesByAabb(aabbScaled, startEdit, endEdit);
285 
286  for (blub::int32 indX = startEdit.x; indX < endEdit.x; ++indX)
287  {
288  for (blub::int32 indY = startEdit.y; indY < endEdit.y; ++indY)
289  {
290  for (blub::int32 indZ = startEdit.z; indZ < endEdit.z; ++indZ)
291  {
292  const blub::vector3int32 id(indX, indY, indZ);
293  const t_utilsTile workTile(getTileHolder(id));
294 
295  ++m_numInTilesInTask;
296  t_base::m_worker.post(boost::bind(&base::editVoxelWorker, this, change, workTile, id, trans));
297  }
298  }
299  }
300  }
301 
310  void editVoxelWorker(t_editConstPtr change, const t_utilsTile &holder, const blub::vector3int32& id, const blub::transform& trans)
311  {
312  #ifdef BLUB_LOG_VOXEL
313  blub::BOUT("base::editVoxelTS id:" + blub::string::number(id));
314  #endif
315  t_tilePtr workTile;
316  if (holder.state == utils::tileState::partitial)
317  {
318  workTile = holder.data;
319  }
320  else
321  {
322  workTile = createTileFull(holder.state == utils::tileState::full);
323  }
324 
325  if (!workTile->getEditing())
326  {
327  workTile->startEdit();
328  }
329  change->calculateVoxel(workTile.data(), id, trans);
330 
331  t_utilsTile result;
332  if (workTile->isEmpty())
333  {
334  result.state = utils::tileState::empty;
335  }
336  else
337  {
338  if (workTile->isFull())
339  {
340  result.state = utils::tileState::full;
341  }
342  else
343  {
344  result.state = utils::tileState::partitial;
345  result.data = workTile;
346  }
347  }
348  t_base::m_master.post(boost::bind(&base::editVoxelDoneMaster, this, result, id));
349  }
350 
356  void editVoxelDoneMaster(t_utilsTile tileHolder_, const blub::vector3int32& id)
357  {
358  setTileMaster(id, tileHolder_);
359 
360  --m_numInTilesInTask;
361  if (m_numInTilesInTask == 0)
362  {
363  if (m_editsTodo.isEmpty())
364  {
365  // unlock all tiles
366  for (const typename t_tilesGotChangedMap::value_type& work : getTilesThatGotEdited())
367  {
368  if (!work.second.data.isNull())
369  {
370  work.second.data->endEdit();
371  }
372  }
374  }
375  else
376  {
377  doNextEditMaster(true);
378  }
379  }
380  }
381 
386  virtual void setTileMaster(const t_tileId& id, const t_utilsTile& toSet) = 0;
387 
393  t_tilePtr getOrCreateTile(const vector3int32& id)
394  {
395  #ifdef BLUB_LOG_VOXEL
396  blub::BOUT("base::getOrCreateTile id:" + blub::string::number(id));
397  #endif
398 
399  t_utilsTile foundTile(getTileHolder(id));
400  if (foundTile.state == utils::tileState::empty)
401  {
402  return createTileFull(false);
403  }
404  if (foundTile.state == utils::tileState::full)
405  {
406  return createTileFull(true);
407  }
408  return foundTile.data;
409  }
410 
416  static t_tilePtr createTileFull(const bool &full)
417  {
418  #ifdef BLUB_LOG_VOXEL
419  blub::BOUT("base::createTile id: full:" + blub::string::number(full));
420  #endif
421  t_tilePtr newOne(t_tile::create()); // FIXME call base class
422 
423  if (full)
424  {
425  newOne->startEdit();
426  newOne->setFull();
427  newOne->endEdit();
428  }
429 
430  return newOne;
431  }
432 
437  virtual void setTileToFullMaster(const t_tileId& id) = 0;
442  virtual void setTileToEmtpyMaster(const t_tileId& id) = 0;
443 
450  static void calculateAffectetedTilesByAabb(const axisAlignedBoxInt32& voxelAabb, t_tileId& startResult, t_tileId& endResult)
451  {
452  startResult = calculateVoxelPosToTileId(voxelAabb.getMinimum());
453  endResult = calculateVoxelPosToTileId(voxelAabb.getMaximum()) + blub::vector3int32(1, 1, 1);
454  }
455 
456 protected:
457  int32 m_numInTilesInTask;
458 
459  typedef list<editTodo> t_editTodoList;
460  t_editTodoList m_editsTodo;
461 
462  // overwrite/reimpl stuff from t_base - because no usage of sharedPointer<>
463  t_tilesGotChangedMap m_tilesThatGotEdited;
464 
465 };
466 
467 
468 }
469 }
470 }
471 }
472 }
473 
474 #endif // VOXEL_SIMPLE_CONTAINER_BASE_HPP
virtual void lockForEditMaster()
lockForEditMaster locks for write, or waits until possible. Call by master dispatcher.
Definition: base.hpp:228
virtual void setTileToEmtpyMaster(const t_tileId &id)=0
setTileToFullMaster sets a tiles voxel to minimum - for memory optimizations. Method gets called by a...
Definition: customVertexInformation.cpp:193
static void calculateAffectetedTilesByAabb(const axisAlignedBoxInt32 &voxelAabb, t_tileId &startResult, t_tileId &endResult)
calculateAffectetedTilesByAabb caluclates a list of affected tiles by an axisAlignedBox. Used to determine which tiles to recalculate for an edit.
Definition: base.hpp:450
static t_tilePtr createTileFull(const bool &full)
createTileFull creates a tile in which all voxel are maximum or minimum.
Definition: base.hpp:416
void setMax()
setMax sets all values to maximum. See class description.
Definition: data.hpp:113
void setMin()
setMin sets all values to minimum. See class description.
Definition: data.hpp:105
void doNextEditMaster(const bool &alreadyLocked=false)
doNextEditMaster finds out which tiles the edit affects and dispaches the change to the worker-thread...
Definition: base.hpp:251
void lockForEditMaster() override
lockForEditMaster locks for write, or waits until possible. Call by master dispatcher.
Definition: base.hpp:193
vector3int32 t_tileId
Definition: base.hpp:44
static vector3int32 calculateVoxelPosInTile(const vector3int32 &voxelPos)
calculateVoxelPosInTile converts an absolute voxel-position to an relative container-confirm position...
Definition: base.hpp:147
The editTodo struct holds the edit information, for the dispatcher. A primitive buffer for the paramt...
Definition: base.hpp:202
Definition: transform.hpp:20
void unlockForEditMaster() override
unlockForEditMaster unlocks write. Call by master dispatcher.
Definition: base.hpp:176
void editMaster(t_editConstPtr change, const blub::transform &trans)
editMaster saves the edit in a qeue and starts to handle it.
Definition: base.hpp:234
virtual bool tryLockForEditMaster()
tryLockForEditMaster tries to lock for write. Call by master dispatcher.
Definition: base.hpp:217
virtual void unlockForEditMaster()
unlockForEditMaster unlocks write. Call by master dispatcher.
Definition: base.hpp:236
void editVoxel(t_editConstPtr change, const transform &trans=blub::transform())
editVoxel edits the container. Its guranteed that the edits are getting in order of calling this meth...
Definition: base.hpp:64
void setTile(const t_tileId &id, const t_utilsTile &toSet)
editVoxel edits the container. Its guranteed that the edits are getting in order of calling this meth...
Definition: base.hpp:87
Definition: axisAlignedBoxInt32.hpp:12
void editVoxelWorker(t_editConstPtr change, const t_utilsTile &holder, const blub::vector3int32 &id, const blub::transform &trans)
editVoxelWorker affects with change holder. Method gets called paralell by various threads...
Definition: base.hpp:310
void editVoxelDoneMaster(t_utilsTile tileHolder_, const blub::vector3int32 &id)
editVoxelDoneMaster gets called after edit got applied on the tile. Call method only by one thread at...
Definition: base.hpp:356
static t_tileId calculateVoxelPosToTileId(const vector3int32 &voxelPos)
calculateVoxelPosToTileId converts an absolute voxel-position to an relative container-id position...
Definition: base.hpp:137
virtual t_utilsTile getTileHolder(const t_tileId &id) const =0
getTileHolder returns a utils::tileHolder setted by setTile() or by editVoxel(). Read-lock class befo...
Definition: dispatcher.hpp:29
virtual void setTileToFullMaster(const t_tileId &id)=0
setTileToFullMaster sets a tiles voxel to maximum - for memory optimizations. Method gets called by a...
t_tilePtr getOrCreateTile(const vector3int32 &id)
getOrCreateTile looks up if tile already exists. If not creates one.
Definition: base.hpp:393
Definition: vector3.hpp:26
Definition: axisAlignedBox.hpp:20
The data class is the default voxel. Contains an 8-bit interpolation value. Replace/derive it and set...
Definition: data.hpp:27
bool tryLockForEditMaster() override
tryLockForEditMaster tries to lock for write. Call by master dispatcher.
Definition: base.hpp:184
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
t_utilsTile getTileHolderByVoxelPosition(const blub::vector3int32 &pos) const
getTileHolderByVoxelPosition returns a utils::tileHolder setted by setTile() or by editVoxel()...
Definition: base.hpp:104
t_voxel getVoxel(const vector3int32 &voxelPos) const
getVoxel returns an voxel. Read-lock the class before call.
Definition: base.hpp:114
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
Definition: customVertexInformation.cpp:177
virtual void setTileMaster(const t_tileId &id, const t_utilsTile &toSet)=0
gets called by setTile. Call only by one thread at a time. Write-lock class before.
base(blub::async::dispatcher &worker)
base constructor.
Definition: base.hpp:50