Sirikata
|
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