Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #pragma once
00024
00025 #include "cinder/Vector.h"
00026
00027 namespace cinder {
00028
00029 class Arcball {
00030 public:
00031 Arcball()
00032 {
00033 setNoConstraintAxis();
00034 mCurrentQuat = mInitialQuat = Quatf::identity();
00035 }
00036 Arcball( const Vec2i &aScreenSize )
00037 : mWindowSize( aScreenSize )
00038 {
00039 setCenter( Vec2f( mWindowSize.x / 2.0f, mWindowSize.y / 2.0f ) );
00040 mRadius = std::min( (float)mWindowSize.x / 2, (float)mWindowSize.y / 2 );
00041 setNoConstraintAxis();
00042 mCurrentQuat = mInitialQuat = Quatf::identity();
00043 }
00044
00045 void mouseDown( const Vec2i &mousePos )
00046 {
00047 mInitialMousePos = mousePos;
00048 mInitialQuat = mCurrentQuat;
00049 }
00050
00051 void mouseDrag( const Vec2i &mousePos )
00052 {
00053 Vec3f from = mouseOnSphere( mInitialMousePos );
00054 Vec3f to = mouseOnSphere( mousePos );
00055 if( mUseConstraint ) {
00056 from = constrainToAxis( from, mConstraintAxis );
00057 to = constrainToAxis( to, mConstraintAxis );
00058 }
00059
00060 Vec3f axis = from.cross( to );
00061 mCurrentQuat = mInitialQuat * Quatf( from.dot( to ), axis.x, axis.y, axis.z );
00062 mCurrentQuat.normalize();
00063 }
00064
00065 void resetQuat() { mCurrentQuat = mInitialQuat = Quatf::identity(); }
00066 Quatf getQuat() { return mCurrentQuat; }
00067 void setQuat( const Quatf &quat ) { mCurrentQuat = quat; }
00068
00069 void setWindowSize( const Vec2i &aWindowSize ) { mWindowSize = aWindowSize; }
00070 void setCenter( const Vec2f &aCenter ) { mCenter = aCenter; }
00071 Vec2f getCenter() const { return mCenter; }
00072 void setRadius( float aRadius ) { mRadius = aRadius; }
00073 float getRadius() const { return mRadius; }
00074 void setConstraintAxis( const Vec3f &aConstraintAxis ) { mConstraintAxis = aConstraintAxis; mUseConstraint = true; }
00075 void setNoConstraintAxis() { mUseConstraint = false; }
00076 bool isUsingConstraint() const { return mUseConstraint; }
00077 Vec3f getConstraintAxis() const { return mConstraintAxis; }
00078
00079 Vec3f mouseOnSphere( const Vec2i &point ) {
00080 Vec3f result;
00081
00082 result.x = ( point.x - mCenter.x ) / ( mRadius * 2 );
00083 result.y = ( point.y - mCenter.y ) / ( mRadius * 2 );
00084 result.z = 0.0f;
00085
00086 float mag = result.lengthSquared();
00087 if( mag > 1.0f ) {
00088 result.normalize();
00089 }
00090 else {
00091 result.z = math<float>::sqrt( 1.0f - mag );
00092 result.normalize();
00093 }
00094
00095 return result;
00096 }
00097
00098 private:
00099
00100 Vec3f constrainToAxis( const Vec3f &loose, const Vec3f &axis )
00101 {
00102 float norm;
00103 Vec3f onPlane = loose - axis * axis.dot( loose );
00104 norm = onPlane.lengthSquared();
00105 if( norm > 0.0f ) {
00106 if( onPlane.z < 0.0f )
00107 onPlane = -onPlane;
00108 return ( onPlane * ( 1.0f / math<float>::sqrt( norm ) ) );
00109 }
00110
00111 if( axis.dot( Vec3f::zAxis() ) < 0.0001f ) {
00112 onPlane = Vec3f::xAxis();
00113 }
00114 else {
00115 onPlane = Vec3f( -axis.y, axis.x, 0.0f ).normalized();
00116 }
00117
00118 return onPlane;
00119 }
00120
00121 Vec2i mWindowSize;
00122 Vec2i mInitialMousePos;
00123 Vec2f mCenter;
00124 Quatf mCurrentQuat, mInitialQuat;
00125 float mRadius;
00126 Vec3f mConstraintAxis;
00127 bool mUseConstraint;
00128 };
00129
00130 }