#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
+#include "BVHPageNode.hxx"
#include "BVHTransform.hxx"
#include "BVHMotionTransform.hxx"
#include "BVHLineGeometry.hxx"
virtual void apply(BVHGroup& node)
{ expandBy(node.getBoundingSphere()); }
+ virtual void apply(BVHPageNode& node)
+ { expandBy(node.getBoundingSphere()); }
virtual void apply(BVHTransform& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(BVHMotionTransform& node)
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
+#include "BVHPageNode.hxx"
#include "BVHTransform.hxx"
#include "BVHMotionTransform.hxx"
#include "BVHLineGeometry.hxx"
return;
group.traverse(*this);
}
+
+void
+BVHLineSegmentVisitor::apply(BVHPageNode& pageNode)
+{
+ if (!intersects(_lineSegment, pageNode.getBoundingSphere()))
+ return;
+ pageNode.traverse(*this);
+}
void
BVHLineSegmentVisitor::apply(BVHTransform& transform)
{ return _id; }
virtual void apply(BVHGroup& group);
+ virtual void apply(BVHPageNode& node);
virtual void apply(BVHTransform& transform);
virtual void apply(BVHMotionTransform& transform);
virtual void apply(BVHLineGeometry&);
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
+#include "BVHPageNode.hxx"
#include "BVHTransform.hxx"
#include "BVHLineGeometry.hxx"
#include "BVHStaticGeometry.hxx"
return;
leaf.traverse(*this);
}
+ virtual void apply(BVHPageNode& leaf)
+ {
+ if (!intersects(_sphere, leaf.getBoundingSphere()))
+ return;
+ leaf.traverse(*this);
+ }
virtual void apply(BVHTransform& transform)
{
if (!intersects(_sphere, transform.getBoundingSphere()))
class BVHGroup;
class BVHVisitor;
+class BVHPageNode;
// Base for the tree nodes
class BVHNode : public SGReferenced {
protected:
friend class BVHGroup;
+ friend class BVHPageNode;
void addParent(BVHNode* parent);
void removeParent(BVHNode* parent);
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#include "BVHPageNode.hxx"
+
+#include "BVHPager.hxx"
+
+namespace simgear {
+
+BVHPageNode::BVHPageNode() :
+ _useStamp(0),
+ _requested(false)
+{
+}
+
+BVHPageNode::~BVHPageNode()
+{
+}
+
+void
+BVHPageNode::accept(BVHVisitor& visitor)
+{
+ visitor.apply(*this);
+}
+
+}
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#ifndef BVHPageNode_hxx
+#define BVHPageNode_hxx
+
+#include <list>
+
+#include <simgear/structure/SGSharedPtr.hxx>
+
+#include "BVHGroup.hxx"
+#include "BVHVisitor.hxx"
+
+namespace simgear {
+
+class BVHPager;
+class BVHPageRequest;
+
+class BVHPageNode : public BVHGroup {
+public:
+ BVHPageNode();
+ virtual ~BVHPageNode();
+
+ virtual void accept(BVHVisitor& visitor);
+
+ /// Return the usage stamp of the last access
+ unsigned getUseStamp() const
+ { return _useStamp; }
+
+ virtual SGSphered computeBoundingSphere() const = 0;
+
+ virtual BVHPageRequest* newRequest() = 0;
+
+protected:
+ virtual void invalidateBound() = 0;
+
+ bool getRequested() const
+ { return _requested; }
+ void setRequested(bool requested)
+ { _requested = requested; }
+
+private:
+ friend class BVHPager;
+
+ std::list<SGSharedPtr<BVHPageNode> >::iterator _iterator;
+ unsigned _useStamp;
+ bool _requested;
+};
+
+}
+
+#endif
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#include "BVHPageRequest.hxx"
+
+namespace simgear {
+
+BVHPageRequest::~BVHPageRequest()
+{
+}
+
+}
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#ifndef BVHPageRequest_hxx
+#define BVHPageRequest_hxx
+
+#include <simgear/structure/SGReferenced.hxx>
+
+namespace simgear {
+
+class BVHPageNode;
+
+class BVHPageRequest : public SGReferenced {
+public:
+ virtual ~BVHPageRequest();
+
+ /// Happens in the pager thread, do not modify the calling bvh tree
+ virtual void load() = 0;
+ /// Happens in the bvh main thread where the bvh is actually used.
+ /// So inside here it is safe to modify the paged node
+ virtual void insert() = 0;
+ /// The page node this request is for
+ virtual BVHPageNode* getPageNode() = 0;
+};
+
+}
+
+#endif
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#include "BVHPager.hxx"
+
+#include <list>
+
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
+
+#include "BVHPageNode.hxx"
+#include "BVHPageRequest.hxx"
+
+namespace simgear {
+
+struct BVHPager::_PrivateData : protected SGThread {
+ typedef SGSharedPtr<BVHPageRequest> _Request;
+ typedef std::list<_Request> _RequestList;
+ typedef std::list<SGSharedPtr<BVHPageNode> > _PageNodeList;
+
+ struct _LockedQueue {
+ void _push(const _Request& request)
+ {
+ SGGuard<SGMutex> scopeLock(_mutex);
+ _requestList.push_back(request);
+ }
+ _Request _pop()
+ {
+ SGGuard<SGMutex> scopeLock(_mutex);
+ if (_requestList.empty())
+ return _Request();
+ _Request request;
+ request.swap(_requestList.front());
+ _requestList.pop_front();
+ return request;
+ }
+ private:
+ SGMutex _mutex;
+ _RequestList _requestList;
+ };
+
+ struct _WorkQueue {
+ void _stop()
+ {
+ _push(_Request());
+ }
+ void _push(const _Request& request)
+ {
+ SGGuard<SGMutex> scopeLock(_mutex);
+ bool needSignal = _requestList.empty();
+ _requestList.push_back(request);
+ if (needSignal)
+ _waitCondition.signal();
+ }
+ _Request _pop()
+ {
+ SGGuard<SGMutex> scopeLock(_mutex);
+ while (_requestList.empty())
+ _waitCondition.wait(_mutex);
+ _Request request;
+ request.swap(_requestList.front());
+ _requestList.pop_front();
+ return request;
+ }
+ private:
+ SGMutex _mutex;
+ SGWaitCondition _waitCondition;
+ _RequestList _requestList;
+ };
+
+ _PrivateData() :
+ _started(false),
+ _useStamp(0)
+ {
+ }
+ virtual ~_PrivateData()
+ {
+ _stop();
+ }
+
+ virtual void run()
+ {
+ for (;;) {
+ _Request request = _pendingRequests._pop();
+ // This means stop working
+ if (!request.valid())
+ return;
+ request->load();
+ _processedRequests._push(request);
+ }
+ }
+
+ bool _start()
+ {
+ if (_started)
+ return true;
+ if (!start())
+ return false;
+ _started = true;
+ return true;
+ }
+
+ void _stop()
+ {
+ if (!_started)
+ return;
+ // send a stop request ...
+ _pendingRequests._stop();
+ // ... and wait for the thread to finish
+ join();
+ _started = false;
+ }
+
+ void _use(BVHPageNode& pageNode)
+ {
+ if (pageNode._requested) {
+ // move it forward in the lru list
+ _pageNodeList.splice(_pageNodeList.end(), _pageNodeList,
+ pageNode._iterator);
+ } else {
+ _Request request = pageNode.newRequest();
+ if (!request.valid())
+ return;
+
+ pageNode._iterator = _pageNodeList.insert(_pageNodeList.end(),
+ &pageNode);
+ pageNode._requested = true;
+
+ if (_started) {
+ _pendingRequests._push(request);
+ } else {
+ request->load();
+ request->insert();
+ }
+ }
+ pageNode._useStamp = _useStamp;
+ }
+
+ void _update(unsigned expiry)
+ {
+ // Insert all processed requests
+ for (;;) {
+ SGSharedPtr<BVHPageRequest> request;
+ request = _processedRequests._pop();
+ if (!request.valid())
+ break;
+ request->insert();
+ }
+
+ // ... and throw away stuff that is not used for a long time
+ unsigned useStamp = _useStamp - expiry;
+ _PageNodeList::iterator i = _pageNodeList.begin();
+ while (i != _pageNodeList.end()) {
+ // Ok, this means if the highest bit in the below difference
+ // is set which is aequivalent to having a negative difference
+ // but being wraparound save.
+ unsigned diff = (*i)->_useStamp - useStamp;
+ // test the sign bit of the difference
+ if (!(diff & (~((~0u) >> 1))))
+ break;
+ (*i)->clear();
+ (*i)->_requested = false;
+ i = _pageNodeList.erase(i);
+ }
+ }
+
+ bool _started;
+ unsigned _useStamp;
+ _WorkQueue _pendingRequests;
+ _LockedQueue _processedRequests;
+ // Store the rcu list of loaded nodes so that they can expire
+ _PageNodeList _pageNodeList;
+};
+
+BVHPager::BVHPager() :
+ _privateData(new _PrivateData)
+{
+}
+
+BVHPager::~BVHPager()
+{
+ delete _privateData;
+ _privateData = 0;
+}
+
+bool
+BVHPager::start()
+{
+ return _privateData->_start();
+}
+
+void
+BVHPager::stop()
+{
+ _privateData->_stop();
+}
+
+void
+BVHPager::use(BVHPageNode& pageNode)
+{
+ _privateData->_use(pageNode);
+}
+
+void
+BVHPager::update(unsigned expiry)
+{
+ _privateData->_update(expiry);
+}
+
+void
+BVHPager::setUseStamp(unsigned stamp)
+{
+ _privateData->_useStamp = stamp;
+}
+
+unsigned
+BVHPager::getUseStamp() const
+{
+ return _privateData->_useStamp;
+}
+
+}
--- /dev/null
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+
+#ifndef BVHPager_hxx
+#define BVHPager_hxx
+
+#include <simgear/structure/SGSharedPtr.hxx>
+
+namespace simgear {
+
+class BVHPageNode;
+class BVHPageRequest;
+
+class BVHPager {
+public:
+ BVHPager();
+ ~BVHPager();
+
+ /// Starts the pager thread
+ bool start();
+
+ /// Stops the pager thread
+ void stop();
+
+ /// Use this page node, if loaded make it as used, if not loaded schedule
+ void use(BVHPageNode& pageNode);
+
+ /// Call this from the main thread to incorporate the processed page
+ /// requests into the bounding volume tree
+ void update(unsigned expiry);
+
+ /// The usage stamp to mark usage of BVHPageNodes
+ void setUseStamp(unsigned stamp);
+ unsigned getUseStamp() const;
+
+private:
+ BVHPager(const BVHPager&);
+ BVHPager& operator=(const BVHPager&);
+
+ struct _PrivateData;
+ _PrivateData* _privateData;
+};
+
+}
+
+#endif
popNodeList(parentNodeList);
}
+void
+BVHSubTreeCollector::apply(BVHPageNode& group)
+{
+ if (!intersects(_sphere, group.getBoundingSphere()))
+ return;
+
+ // The _nodeList content is somehow the 'return value' of the subtree.
+ // Set it to zero to see if we have something to collect down there.
+ NodeList parentNodeList;
+ pushNodeList(parentNodeList);
+
+ group.traverse(*this);
+
+ popNodeList(parentNodeList);
+}
+
void
BVHSubTreeCollector::apply(BVHTransform& transform)
{
virtual ~BVHSubTreeCollector();
virtual void apply(BVHGroup&);
+ virtual void apply(BVHPageNode&);
virtual void apply(BVHTransform&);
virtual void apply(BVHMotionTransform&);
virtual void apply(BVHLineGeometry&);
-// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
+// Copyright (C) 2008 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
class BVHStaticData;
class BVHGroup;
+class BVHPageNode;
class BVHTransform;
class BVHMotionTransform;
class BVHStaticGeometry;
// High level nodes to handle
virtual void apply(BVHGroup&) = 0;
+ virtual void apply(BVHPageNode&) = 0;
virtual void apply(BVHTransform&) = 0;
virtual void apply(BVHMotionTransform&) = 0;
virtual void apply(BVHLineGeometry&) = 0;
BVHMotionTransform.hxx
BVHNearestPointVisitor.hxx
BVHNode.hxx
+ BVHPageNode.hxx
+ BVHPageRequest.hxx
+ BVHPager.hxx
BVHStaticBinary.hxx
BVHStaticData.hxx
BVHStaticGeometry.hxx
BVHLineSegmentVisitor.cxx
BVHMotionTransform.cxx
BVHNode.cxx
+ BVHPageNode.cxx
+ BVHPageRequest.cxx
+ BVHPager.cxx
BVHStaticBinary.cxx
BVHStaticGeometry.cxx
BVHStaticLeaf.cxx