Sirikata
libproxyobject/include/sirikata/proxyobject/ProxyObject.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Sirikata Listener Pattern
00002  *  ProxyObject.hpp
00003  *
00004  *  Copyright (c) 2009, Patrick Reiter Horn
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_PROXY_OBJECT_HPP_
00034 #define _SIRIKATA_PROXY_OBJECT_HPP_
00035 
00036 #include <sirikata/proxyobject/Platform.hpp>
00037 
00038 #include <sirikata/proxyobject/Defs.hpp>
00039 
00040 #include <sirikata/core/util/Extrapolation.hpp>
00041 #include <sirikata/core/util/SpaceObjectReference.hpp>
00042 #include <sirikata/core/util/ListenerProvider.hpp>
00043 #include "PositionListener.hpp"
00044 
00045 #include <sirikata/core/odp/Service.hpp>
00046 
00047 #include "VWObject.hpp"
00048 
00049 #include <sirikata/proxyobject/MeshListener.hpp>
00050 #include "MeshListener.hpp"
00051 
00052 #include <sirikata/core/util/PresenceProperties.hpp>
00053 #include <sirikata/proxyobject/ProxyManager.hpp>
00054 
00055 #include <sirikata/core/util/SerializationCheck.hpp>
00056 #include <boost/functional/hash.hpp>
00057 
00058 namespace Sirikata {
00059 
00060 
00061 //forward declares
00062 class MeshListener;
00063 class ProxyObjectListener;
00064 
00065 
00066 //typedefs
00067 typedef Provider<PositionListener*> PositionProvider;
00068 typedef Provider<ProxyObjectListener*> ProxyObjectProvider;
00069 typedef Provider< MeshListener* > MeshProvider;
00070 
00071 
00072 
00073 
00075 class SIRIKATA_PROXYOBJECT_EXPORT ProxyObjectListener {
00076 public:
00077     virtual ~ProxyObjectListener() {}
00078     // Invoked when the object enters the result set.  Updates will start
00079     // flowing in for this object. Note that this could be called as opposed to
00080     // the actual creation of the ProxyObject, because the ProxyObject still
00081     // exists but had already been invalidated.
00082     virtual void validated(ProxyObjectPtr proxy) = 0;
00083     // Invoked when the object falls out of the result set. No further updates
00084     // will be received.
00085     virtual void invalidated(ProxyObjectPtr proxy, bool permanent) = 0;
00086     // Invoked when the ProxyObject is actually destroyed.
00087     virtual void destroyed(ProxyObjectPtr proxy) = 0;
00088 };
00089 
00090 
00091 
00092 
00103 class SIRIKATA_PROXYOBJECT_EXPORT ProxyObject
00104     : public SelfWeakPtr<ProxyObject>,
00105       public SequencedPresenceProperties,
00106       public ProxyObjectProvider,
00107       public PositionProvider,
00108       public MeshProvider,
00109       SerializationCheck
00110 {
00111 
00112 public:
00113     static ProxyObjectPtr construct(ProxyManagerPtr man, const SpaceObjectReference& id);
00114 
00115     class SIRIKATA_PROXYOBJECT_EXPORT UpdateNeeded {
00116     public:
00117         bool operator()(
00118             const Location&updatedValue,
00119             const Location&predictedValue) const;
00120     };
00121     typedef TimedWeightedExtrapolator<Location,UpdateNeeded> Extrapolator;
00122 
00123 private:
00124     bool mValid;
00125     const SpaceObjectReference mID;
00126     ProxyManagerPtr mParent;
00127 
00128 public:
00136     ProxyObject(ProxyManagerPtr man, const SpaceObjectReference& id);
00137 
00138 
00139     inline const bool isValid() const {
00140       return mValid;
00141     }
00143     virtual void destroy();
00144 
00146     inline const SpaceObjectReference& getObjectReference() const {
00147         return mID;
00148     }
00149     inline const SpaceObjectReference& getOwnerPresenceID() const {
00150         return getOwner()->id();
00151     }
00152 
00154     ProxyManagerPtr getOwner() const { return mParent; }
00155 
00158     bool isPresence() const { return getObjectReference() == getOwnerPresenceID(); }
00159 
00160 
00161 
00162     ~ProxyObject();
00163 
00164     // Resets the state of this proxy as if it had been freshly created
00165     void reset();
00166 
00170     void validate();
00175     void invalidate(bool permanent);
00176 
00178     bool isStatic() const;
00179 
00180     // PresenceProperties Overrides
00181     virtual TimedMotionVector3f location() const;
00182     virtual TimedMotionQuaternion orientation() const;
00183     virtual AggregateBoundingInfo bounds() const;
00184     virtual Transfer::URI mesh() const;
00185     virtual String physics() const;
00186     virtual bool isAggregate() const;
00187     virtual ObjectReference parentAggregate() const;
00188 
00189     // Alternatives that access only the *verified* location information,
00190     // i.e. data sent by the space.
00191     TimedMotionVector3f verifiedLocation() const;
00192     TimedMotionQuaternion verifiedOrientation() const;
00193     AggregateBoundingInfo verifiedBounds() const;
00194     Transfer::URI verifiedMesh() const;
00195     String verifiedPhysics() const;
00196 
00197     void setLocation(const TimedMotionVector3f& reqloc, uint64 seqno);
00198     void setOrientation(const TimedMotionQuaternion& reqorient, uint64 seqno);
00199     void setBounds(const AggregateBoundingInfo& bnds, uint64 seqno);
00200     void setMesh (Transfer::URI const& rhs, uint64 seqno);
00201     void setPhysics(const String& rhs, uint64 seqno);
00202     void setIsAggregate(bool isAggregate, uint64 seqno);
00203 
00204 
00206     Location extrapolateLocation(TemporalValue<Location>::Time current) const {
00207         // Note that we call methods to get these so we use predicted values if possible.
00208         TimedMotionVector3f loc = location();
00209         TimedMotionQuaternion orient = orientation();
00210 
00211         Vector3f angaxis;
00212         float32 angvel;
00213         orient.velocity().toAngleAxis(angvel, angaxis);
00214 
00215         return Location(Vector3d(loc.position(current)), orient.position(current).normal(), loc.velocity(), angaxis, angvel);
00216     }
00217 
00218 
00219     unsigned int hash() const {
00220         // NOTE: Be *very* careful with this. It used to be just owner.hash ^
00221         // object.hash. That can end up with some really horrible
00222         // results. Consider if you end up with a hash_map full of proxies of
00223         // just the objects themselves, i.e. for all entries owner ==
00224         // object. All end up with hash == 0 because the hashes are equal,
00225         // leading to a single bucket holding everything.
00226 
00227         size_t seed = 0;
00228 
00229         boost::hash_combine(seed, getOwnerPresenceID().hash());
00230         boost::hash_combine(seed, getObjectReference().hash());
00231 
00232         return seed;
00233     }
00234 
00235     class Hasher{
00236     public:
00237         size_t operator() (const ProxyObject& p) const {
00238             return p.hash();
00239         }
00240         size_t operator() (ProxyObject* p) const {
00241             return p->hash();
00242         }
00243         size_t operator() (const ProxyObjectPtr& p) const {
00244             return p->hash();
00245         }
00246     };
00247 
00248 };
00249 }
00250 #endif