1 #ifndef NETWORK_SYNC_VOXEL_ACCESSOR_MULTIPLETILES_SENDER_HPP
2 #define NETWORK_SYNC_VOXEL_ACCESSOR_MULTIPLETILES_SENDER_HPP
4 #include "blub/async/dispatcher.hpp"
5 #include "blub/core/byteArray.hpp"
6 #include "blub/core/hashList.hpp"
7 #include "blub/core/hashMap.hpp"
8 #include "blub/core/signal.hpp"
9 #include "blub/log/global.hpp"
10 #include "blub/math/axisAlignedBox.hpp"
11 #include "blub/math/octree/search.hpp"
12 #include "blub/procedural/predecl.hpp"
13 #include "blub/procedural/voxel/simple/accessor.hpp"
14 #include "blub/procedural/voxel/tile/accessor.hpp"
15 #include "blub/sync/log/global.hpp"
16 #include "blub/sync/sender.hpp"
17 #include "blub/sync/voxel/accessor/multipleTiles/base.hpp"
19 #include <boost/iostreams/copy.hpp>
20 #include <boost/iostreams/filter/bzip2.hpp>
21 #include <boost/iostreams/filtering_stream.hpp>
22 #include <boost/iostreams/stream.hpp>
23 #include <boost/function/function2.hpp>
24 #include <boost/signals2/connection.hpp>
35 namespace multipleTiles
39 template <
class voxelType,
class identifierType>
43 typedef identifierType t_identifier;
60 typedef boost::function<bool (vector3, axisAlignedBox)> t_octreeSearchCallback;
65 sender(
async::dispatcher &worker,
const real &voxelSize,
const t_octreeSearchCallback& octreeSearch, t_multipleTilesAccessor* tiles)
66 : t_base(worker,
vector3int32(t_tileContainer::voxelLength))
69 , m_searchFunction(octreeSearch)
70 , m_voxelSize(voxelSize)
73 BASSERT(tiles !=
nullptr);
75 m_connTileVoxelEditDone = m_voxels->
signalEditDone()->connect(boost::bind(&sender::tileEditDone,
this));
85 BASSERT(m_voxels !=
nullptr);
89 t_base::m_master.post(boost::bind(&sender::tileEditDoneMaster,
this));
93 void addSyncReceiver(t_receiverIdentifierPtr
receiver,
const vector3& pos)
95 BASSERT(!receiver.isNull());
97 t_base::m_master.post(boost::bind(&sender::addSyncReceiverMaster,
this, receiver, pos));
99 void updateSyncReceiver(t_receiverIdentifierPtr receiver,
const vector3& pos)
101 BASSERT(!receiver.isNull());
103 t_base::m_master.post(boost::bind(&sender::updateSyncReceiverMaster,
this, receiver, pos));
105 void removeSyncReceiver(t_receiverIdentifierPtr receiver)
107 BASSERT(!receiver.isNull());
109 t_base::m_master.post(boost::bind(&sender::removeSyncReceiverMaster,
this, receiver));
114 t_sigSendTileData* signalSendTileData()
116 return &m_sigSendTileData;
120 void tileEditDoneMaster()
124 BASSERT(m_numtilesInWork == 0);
125 m_numtilesInWork = changeList.size();
127 for (
auto change : changeList)
129 t_tileId id(change.first);
130 t_tileAccessorPtr workTile(change.second);
132 if (workTile.isNull())
134 compressTileAfterMaster(
id, workTile,
nullptr);
137 t_tileDataMap::const_iterator it = m_tileData.find(
id);
138 if (it == m_tileData.cend())
140 BASSERT(!workTile->isEmpty());
141 BASSERT(!workTile->isFull());
142 m_worker.post(boost::bind(&sender::compressTileWorker,
this,
id, workTile,
nullptr));
145 m_worker.post(boost::bind(&sender::compressTileWorker,
this,
id, workTile, it->second));
149 void addSyncReceiverMaster(t_receiverIdentifierPtr receiver,
const vector3& pos)
151 t_base::addReceiverMaster(receiver, pos / m_voxelSize);
155 void updateSyncReceiverMaster(t_receiverIdentifierPtr receiver,
const vector3& pos)
157 if (t_base::m_receiverPosMap.find(receiver) == t_base::m_receiverPosMap.cend())
159 BLUB_SYNC_LOG_WARNING() <<
"m_receiverPosMap.find(receiver) == m_receiverPosMap.cend()";
164 t_base::updateReceiverMaster(receiver, pos / m_voxelSize);
168 void removeSyncReceiverMaster(t_receiverIdentifierPtr receiver)
170 t_base::removeReceiverMaster(receiver);
175 void sendSetTileMaster(t_receiverIdentifierPtr receiver,
const t_tileId &
id, t_tileDataPtr
data)
177 std::stringstream result;
181 sendType typeToSend = sendType::setTile;
184 typeToSend = sendType::removeTile;
186 format << typeToSend;
190 format << *data.get();
193 t_tileDataPtr send(
new byteArray(result.str().c_str(), result.str().size()));
195 m_sigSendTileData(receiver, send);
199 std::stringstream result;
203 sendType typeToSend = sendType::unlockForEdit;
206 typeToSend = sendType::lockForEdit;
208 format << typeToSend;
210 t_tileDataPtr send(
new byteArray(result.str().c_str(), result.str().size()));
212 m_sigSendTileData(receiver, send);
216 sendLockUnlockForEditMaster(receiver,
true);
220 sendLockUnlockForEditMaster(receiver,
false);
223 void compressTileWorker(
const t_tileId&
id,
const t_tileAccessorPtr &tile, t_tileDataPtr toSave)
225 BASSERT(!tile.isNull());
227 std::stringstream toCompress;
231 format << *tile.get();
234 std::ostringstream dataContainerCompressed;
236 boost::iostreams::filtering_ostream filterOut;
237 filterOut.push(boost::iostreams::bzip2_compressor());
238 filterOut.push(dataContainerCompressed);
240 boost::iostreams::copy(toCompress, filterOut);
243 const int32 sizeCompressed = dataContainerCompressed.str().size();
247 toSave =
new byteArray(dataContainerCompressed.str().data(), sizeCompressed);
251 toSave->resize(sizeCompressed);
252 memcpy(toSave->data(), dataContainerCompressed.str().data(), sizeCompressed);
255 t_base::m_master.post(boost::bind(&sender::compressTileAfterMaster,
this,
id, tile, toSave));
257 void compressTileAfterMaster(
const t_tileId&
id,
const t_tileAccessorPtr &tile, t_tileDataPtr toSave)
259 t_tileDataMap::const_iterator it = m_tileData.find(
id);
260 const bool found(it != m_tileData.cend());
262 if (found && tile.isNull())
264 m_tileData.erase(it);
265 t_base::removeSyncMaster(
id);
268 if (found && !tile.isNull())
270 typename t_base::t_syncToReceiversMap::const_iterator itTile = t_base::m_syncReceivers.find(
id);
271 BASSERT(itTile != t_base::m_syncReceivers.cend());
273 for (
typename t_base::t_receiverList::const_iterator itRec = receivers.cbegin(); itRec != receivers.cend(); ++itRec)
275 lockReceiver(*itRec);
276 sendSetTileMaster(*itRec,
id, toSave);
280 if (!found && !tile.isNull())
282 m_tileData.insert(
id, toSave);
284 const vector3int32 pos(
id*t_base::m_syncTree.getMinNodeSize() + t_base::m_syncTree.getMinNodeSize()/2);
285 t_base::addSyncMaster(
id,
vector3(pos));
289 BLUB_SYNC_LOG_ERROR() <<
"compressTileAfterMaster: invalid case";
293 BASSERT(m_numtilesInWork >= 0);
294 if (m_numtilesInWork == 0)
303 void lockReceiver(
const typename t_base::t_receiver toLock)
305 if (m_lockedReceiverList.find(toLock) == m_lockedReceiverList.cend())
307 m_lockedReceiverList.insert(toLock);
308 sendLockForEditMaster(toLock);
311 void unlockAllReceiver()
314 for (
auto rec : m_lockedReceiverList)
316 sendUnlockForEditMaster(rec);
318 m_lockedReceiverList.clear();
321 virtual bool isInSyncRangeReceiver(
const typename t_base::t_receiver receiver,
const vector3 &posOfReceiverLeafCenter,
const typename t_base::t_syncTree::t_nodePtr& octreeNode)
324 return m_searchFunction(posOfReceiverLeafCenter,
axisAlignedBox(octreeNode->getBoundingBox()));
326 virtual bool isInSyncRangeSync(
const typename t_base::t_sync sync,
const vector3 &posOfSyncLeafCenter,
const typename t_base::t_receiverTree::t_nodePtr& octreeNode)
329 return m_searchFunction(posOfSyncLeafCenter,
axisAlignedBox(octreeNode->getBoundingBox()));
331 void addSyncReceiver(
const typename t_base::t_receiver receiver,
const typename t_base::t_sync sync)
override
333 lockReceiver(receiver);
335 t_tileDataMap::const_iterator it(m_tileData.find(sync));
336 BASSERT(it != m_tileData.cend());
337 sendSetTileMaster(receiver, sync, it->second);
339 void removeSyncReceiver(
const typename t_base::t_receiver receiver,
const typename t_base::t_sync sync)
override
341 lockReceiver(receiver);
343 sendSetTileMaster(receiver, sync,
nullptr);
350 t_multipleTilesAccessor* m_voxels;
351 t_octreeSearchCallback m_searchFunction;
354 t_tileDataMap m_tileData;
356 int32 m_numtilesInWork;
357 t_lockedReceiverList m_lockedReceiverList;
359 t_sigSendTileData m_sigSendTileData;
361 boost::signals2::scoped_connection m_connTileVoxelEditDone;
373 #endif // NETWORK_SYNC_VOXEL_ACCESSOR_MULTIPLETILES_SENDER_HPP
The base class gets derived by every class in the namespace simple::*. It represends one level of det...
Definition: predecl.hpp:30
Definition: sender.hpp:40
Definition: predecl.hpp:8
The container class contains an array of voxel. The amount of voxel per tile is voxelLength^3. The class counts how many voxel are max and how many are min. if all voxel are min or max the class simple::container::base doesnt save them. Additionally it saves an axisAlignedBox which describes the bounds of the voxel that changed.
Definition: predecl.hpp:19
const t_tilesGotChangedMap & getTilesThatGotEdited() const
getTilesThatGotEdited returns a list of tiles which changed since the last call lockForEdit() / lockF...
Definition: base.hpp:198
Definition: portable_binary_oarchive.hpp:63
Definition: sharedPointer.hpp:12
void unlockRead()
unlockRead unlocks the class after reading.
Definition: base.hpp:192
Definition: receiver.hpp:33
Definition: dispatcher.hpp:29
The accessor class caches all voxel needed by tile::surface for an extremly optimized and fast calcul...
Definition: predecl.hpp:21
Definition: vector3.hpp:26
void lockForRead()
lockForRead locks the class for reading.
Definition: base.hpp:186
Definition: axisAlignedBox.hpp:20
t_sigEditDone * signalEditDone()
signalEditDone gets called after unlockForEdit() got called.
Definition: base.hpp:261
Definition: byteArray.hpp:17
Definition: deadlineTimer.hpp:10
Definition: customVertexInformation.cpp:177