Sirikata
libcore/include/sirikata/core/util/Location.hpp
Go to the documentation of this file.
00001 /*  Sirikata Utilities -- Math Library
00002  *  Location.hpp
00003  *
00004  *  Copyright (c) 2009, Daniel 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 #ifndef _LOCATION_HPP_
00033 #define _LOCATION_HPP_
00034 
00035 #include "Transform.hpp"
00036 
00037 namespace Sirikata {
00038 
00039 class Location: public Transform {
00040     Vector3<float32> mVelocity;
00041     Vector3<float32> mAxisOfRotation;
00042     float32 mAngularSpeed;
00043 
00044     void changeToWorld(const Location &reference) {
00045         setVelocity(reference.getVelocity() + reference.getOrientation() * getVelocity());
00046         addAngularRotation(reference.getAxisOfRotation(), reference.getAngularSpeed());
00047         setVelocity(getVelocity() +
00048                     reference.getAngularSpeed() * (
00049                         reference.getAxisOfRotation().cross(getPosition().downCast<float32>())));
00050 
00051         Transform temp = Transform::toWorld(reference);
00052         setPosition(temp.getPosition());
00053         setOrientation(temp.getOrientation());
00054     }
00055     void changeToLocal(const Location &reference) {
00056         Transform temp = Transform::toLocal(reference);
00057         setPosition(temp.getPosition());
00058         setOrientation(temp.getOrientation());
00059 
00060         setVelocity(getVelocity() -
00061                     reference.getAngularSpeed() * (
00062                         reference.getAxisOfRotation().cross(getPosition().downCast<float32>())));
00063         addAngularRotation(reference.getAxisOfRotation(), -reference.getAngularSpeed());
00064         Quaternion inverseOtherOrientation (reference.getOrientation().inverse());
00065         setVelocity(inverseOtherOrientation * (getVelocity() - reference.getVelocity()));
00066     }
00067 public:
00068     Location(){}
00069     Location(const Vector3<float64>&position,
00070              const Quaternion&orientation,
00071              const Vector3<float32> &velocity,
00072              const Vector3<float32> angularVelocityAxis,
00073              float32 angularVelocityRadians)
00074      :Transform(position,orientation),mVelocity(velocity),mAxisOfRotation(angularVelocityAxis), mAngularSpeed(angularVelocityRadians)
00075     {
00076     }
00077 
00078     
00079     bool operator ==(const Location&other)const {
00080         bool eq=getPosition()==other.getPosition();
00081         bool veq=other.mVelocity==mVelocity;
00082         bool qeq=getOrientation()==other.getOrientation();
00083         bool aeq=mAxisOfRotation==other.mAxisOfRotation;
00084         bool seq=mAngularSpeed==other.mAngularSpeed;
00085         return eq&&veq&&qeq&&aeq&&seq;
00086     }
00087 
00088     const Vector3<float32>&getVelocity()const {
00089         return mVelocity;
00090     }
00091 
00092     
00093     void setVelocity(const Vector3<float32> velocity) {
00094         mVelocity=velocity;
00095     }
00096     const Transform &getTransform() const {
00097         return *this;
00098     }
00099     const Vector3<float32>&getAxisOfRotation() const {
00100         return mAxisOfRotation;
00101     }
00102     void setAxisOfRotation(const Vector3<float32>&axis) {
00103         mAxisOfRotation=axis;
00104     }
00105     float32 getAngularSpeed() const{
00106         return mAngularSpeed;
00107     }
00108     void setAngularSpeed(float32 radianspersecond) {
00109         mAngularSpeed=radianspersecond;
00110     }
00111     void addAngularRotation(const Vector3<float32> &axis, float32 radianspersecond) {
00112         mAxisOfRotation=mAxisOfRotation*mAngularSpeed+axis*radianspersecond;
00113         mAngularSpeed=mAxisOfRotation.length();
00114         if (mAngularSpeed)
00115             mAxisOfRotation/=mAngularSpeed;
00116     }
00117     Location blend(const Location&newLocation,float32 percentNew) const{
00118         float32 percentOld=(1.0f-percentNew);
00119         Vector3<float32> angAxis=mAxisOfRotation*mAngularSpeed*percentOld;
00120         angAxis+=newLocation.getAxisOfRotation()*newLocation.getAngularSpeed()*percentNew;
00121         float angSpeed=angAxis.length();
00122         if (angSpeed) angAxis/=angSpeed;
00123         return Location (newLocation.getPosition()*percentNew+getPosition()*percentOld,
00124                          (newLocation.getOrientation()*percentNew+getOrientation()*percentOld).normal(),
00125                          newLocation.getVelocity()*percentNew+getVelocity()*percentOld,
00126                          angAxis,
00127                          angSpeed);
00128     }
00129     Location toWorld(const Location &reference) const {
00130         Location copy(*this);
00131         copy.changeToWorld(reference);
00132         return copy;
00133     }
00134     Location toLocal(const Location &reference) const {
00135         Location copy(*this);
00136         copy.changeToLocal(reference);
00137         return copy;
00138     }
00139     template<class TimeDuration> Location extrapolate(const TimeDuration&dt)const {
00140         return Location(getPosition()+Vector3<float64>(getVelocity())*dt.toSeconds(),
00141                         getAngularSpeed()
00142                          ? getOrientation()*Quaternion(getAxisOfRotation(),
00143                                                        (float)(getAngularSpeed()*dt.toSeconds()))
00144                          : getOrientation(),
00145                         getVelocity(),
00146                         getAxisOfRotation(),
00147                         getAngularSpeed());
00148     }
00149 };
00150 inline std::ostream &operator<< (std::ostream &os, const Location &loc) {
00151     os << "[" << loc.getTransform() << "; vel=" <<
00152         loc.getVelocity() << "; angVel = " << loc.getAngularSpeed() <<
00153         " around " << loc.getAxisOfRotation() << "]";
00154     return os;
00155 }
00156 
00157 }
00158 #endif