* rewrote mouse rotation to be more intuitive, doing the rotation in

world space instead of local object space.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24148 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Alexandre Deckner
2008-02-27 13:12:38 +00:00
parent 9c800a96c0
commit 552bd60c4b
6 changed files with 862 additions and 34 deletions
+48 -14
View File
@@ -1,3 +1,16 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexandre Deckner
*
*/
/*
* Original Be Sample source modified to use a quaternion for the object's orientation
*/
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
@@ -61,16 +74,13 @@ extern long setEvent(sem_id event);
GLObject::GLObject(ObjectView* ov)
:
rotX(0),
rotY(0),
spinX(2),
spinY(2),
x(0),
y(0),
z(-2.0),
fRotation(0.0f, 0.0f, 0.0f, 1.0f),
spinX(2),
spinY(2),
solidity(0),
lastRotX(0),
lastRotY(0),
color(4),
changed(false),
fObjView(ov)
@@ -131,29 +141,53 @@ GLObject::MenuInvoked(BPoint point)
setEvent(fObjView->drawEvent);
}
int
GLObject::Solidity() const
{
return solidity;
}
bool
GLObject::SpinIt()
{
rotX += spinX;
rotY += spinY;
bool c = changed;
c = c || ((rotX != lastRotX) || (rotY != lastRotY));
lastRotX = rotX;
lastRotY = rotY;
c = c || ((spinX != 0.0f) || (spinY != 0.0f));
if (c)
RotateWorldSpace(spinY, spinX);
return c;
}
void
GLObject::Spin(float rx, float ry)
{
spinX = rx;
spinY = ry;
}
void
GLObject::RotateWorldSpace(float rx, float ry)
{
fRotation = Quaternion(Vector3(0.0f, 1.0f, 0.0f), 0.01f * rx) * fRotation;
fRotation = Quaternion(Vector3(1.0f, 0.0f, 0.0f), 0.01f * ry) * fRotation;
changed = true;
}
void
GLObject::Draw(bool forID, float IDcolor[])
{
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(rotY, 0.0,1.0,0.0);
glRotatef(rotX, 1.0,0.0,0.0);
float mat[4][4];
fRotation.toOpenGLMatrix(mat);
glMultMatrixf((GLfloat*)mat);
if (forID) {
glColor3fv(IDcolor);
}
+24 -4
View File
@@ -1,12 +1,27 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexandre Deckner
*
*/
/*
* Original Be Sample source modified to use a quaternion for the object's orientation
*/
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#ifndef GL_OBJECT_H
#define GL_OBJECT_H
#include "ObjectView.h"
#include "util.h"
#include "Quaternion.h"
struct point {
float x,y,z;
@@ -29,16 +44,21 @@ class GLObject {
GLObject(ObjectView* ov);
virtual ~GLObject();
virtual void Draw(bool forID, float IDcolor[]);
virtual bool SpinIt();
void Spin(float rx, float ry);
void RotateWorldSpace(float rx, float ry);
virtual void MenuInvoked(BPoint point);
virtual void DoDrawing(bool forID) {};
int Solidity() const;
float rotX, rotY, spinX, spinY;
float x, y, z;
int solidity;
Quaternion fRotation;
protected:
float lastRotX, lastRotY;
float spinX, spinY;
int solidity;
int color;
bool changed;
+26 -16
View File
@@ -1,3 +1,16 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexandre Deckner
*
*/
/*
* Original Be Sample source modified to use a quaternion for the object's orientation
*/
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
@@ -409,13 +422,13 @@ ObjectView::MouseDown(BPoint point)
if (buttons == B_PRIMARY_MOUSE_BUTTON || buttons == B_SECONDARY_MOUSE_BUTTON) {
fTrackingInfo.pickedObject = object;
fTrackingInfo.buttons = buttons;
fTrackingInfo.isTracking = true;
fTrackingInfo.isTracking = true;
fTrackingInfo.lastX = point.x;
fTrackingInfo.lastY = point.y;
fTrackingInfo.lastY = point.y;
fTrackingInfo.lastDx = 0.0f;
fTrackingInfo.lastDy = 0.0f;
fTrackingInfo.pickedObject->spinX = 0.0f;
fTrackingInfo.pickedObject->spinY = 0.0f;
fTrackingInfo.lastDy = 0.0f;
fTrackingInfo.pickedObject->Spin(0.0f, 0.0f);
SetMouseEventMask(B_POINTER_EVENTS,
B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
@@ -437,9 +450,8 @@ ObjectView::MouseUp(BPoint point)
&& fTrackingInfo.pickedObject != NULL
&& (fabs(fTrackingInfo.lastDx) > 1.0f
|| fabs(fTrackingInfo.lastDy) > 1.0f) ) {
fTrackingInfo.pickedObject->spinX = 0.5f * fTrackingInfo.lastDy;
fTrackingInfo.pickedObject->spinY = 0.5f * fTrackingInfo.lastDx;
fTrackingInfo.pickedObject->Spin(0.5f * fTrackingInfo.lastDy, 0.5f * fTrackingInfo.lastDx);
setEvent(drawEvent);
}
@@ -468,10 +480,8 @@ ObjectView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON) {
fTrackingInfo.pickedObject->spinX = 0;
fTrackingInfo.pickedObject->spinY = 0;
fTrackingInfo.pickedObject->rotY += dx;
fTrackingInfo.pickedObject->rotX += dy;
fTrackingInfo.pickedObject->Spin(0.0f, 0.0f);
fTrackingInfo.pickedObject->RotateWorldSpace(dx,dy);
fTrackingInfo.lastDx = dx;
fTrackingInfo.lastDy = dy;
@@ -489,12 +499,12 @@ ObjectView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
yinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio);
}
fTrackingInfo.pickedObject->x += xinc;
fTrackingInfo.pickedObject->x += xinc;
if (modifiers() & B_SHIFT_KEY)
fTrackingInfo.pickedObject->z += zinc;
else
fTrackingInfo.pickedObject->y += yinc;
fForceRedraw = true;
setEvent(drawEvent);
}
@@ -721,13 +731,13 @@ ObjectView::DrawFrame(bool noPause)
fObjListLock.Lock();
for (int i = 0; i < fObjects.CountItems(); i++) {
GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i));
if (object->solidity == 0)
if (object->Solidity() == 0)
object->Draw(false, NULL);
}
EnforceState();
for (int i = 0; i < fObjects.CountItems(); i++) {
GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i));
if (object->solidity != 0)
if (object->Solidity() != 0)
object->Draw(false, NULL);
}
fObjListLock.Unlock();
+6
View File
@@ -1,3 +1,9 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
*/
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
+408
View File
@@ -0,0 +1,408 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexandre Deckner
*
*/
/*
*
* This is a refactored and stripped down version of bullet-2.66 src\LinearMath\btQuaternion.h
* The dependancies on base class btQuadWord have been removed for simplification.
* Added gl matrix conversion method.
*
*/
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __QUATERNION_H__
#define __QUATERNION_H__
#include "Vector3.h"
class Quaternion {
protected:
float m_x;
float m_y;
float m_z;
float m_w;
public:
Quaternion() {}
Quaternion(const Quaternion& q)
{
*((Quaternion*)this) = q;
}
Quaternion(const float& x, const float& y, const float& z,const float& w)
{
m_x = x, m_y = y, m_z = z, m_w = w;
}
Quaternion(const Vector3& axis, const float& angle)
{
setRotation(axis, angle);
}
Quaternion(const float& yaw, const float& pitch, const float& roll)
{
setEuler(yaw, pitch, roll);
}
inline const float& x() const { return m_x; }
inline const float& y() const { return m_y; }
inline const float& z() const { return m_z; }
inline const float& w() const { return m_w; }
void setValue(const float& x, const float& y, const float& z)
{
m_x=x;
m_y=y;
m_z=z;
m_w = 0.f;
}
void setValue(const float& x, const float& y, const float& z,const float& w)
{
m_x=x;
m_y=y;
m_z=z;
m_w=w;
}
void setRotation(const Vector3& axis, const float& angle)
{
float d = axis.length();
assert(d != float(0.0));
float s = sin(angle * float(0.5)) / d;
setValue(axis.x() * s, axis.y() * s, axis.z() * s,
cos(angle * float(0.5)));
}
void setEuler(const float& yaw, const float& pitch, const float& roll)
{
float halfYaw = float(yaw) * float(0.5);
float halfPitch = float(pitch) * float(0.5);
float halfRoll = float(roll) * float(0.5);
float cosYaw = cos(halfYaw);
float sinYaw = sin(halfYaw);
float cosPitch = cos(halfPitch);
float sinPitch = sin(halfPitch);
float cosRoll = cos(halfRoll);
float sinRoll = sin(halfRoll);
setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
}
Quaternion& operator+=(const Quaternion& q)
{
m_x += q.x(); m_y += q.y(); m_z += q.z(); m_w += q.m_w;
return *this;
}
Quaternion& operator-=(const Quaternion& q)
{
m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_w -= q.m_w;
return *this;
}
Quaternion& operator*=(const float& s)
{
m_x *= s; m_y *= s; m_z *= s; m_w *= s;
return *this;
}
Quaternion& operator*=(const Quaternion& q)
{
setValue(m_w * q.x() + m_x * q.m_w + m_y * q.z() - m_z * q.y(),
m_w * q.y() + m_y * q.m_w + m_z * q.x() - m_x * q.z(),
m_w * q.z() + m_z * q.m_w + m_x * q.y() - m_y * q.x(),
m_w * q.m_w - m_x * q.x() - m_y * q.y() - m_z * q.z());
return *this;
}
float dot(const Quaternion& q) const
{
return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_w * q.m_w;
}
float length2() const
{
return dot(*this);
}
float length() const
{
return sqrt(length2());
}
Quaternion& normalize()
{
return *this /= length();
}
inline Quaternion
operator*(const float& s) const
{
return Quaternion(x() * s, y() * s, z() * s, m_w * s);
}
Quaternion operator/(const float& s) const
{
assert(s != float(0.0));
return *this * (float(1.0) / s);
}
Quaternion& operator/=(const float& s)
{
assert(s != float(0.0));
return *this *= float(1.0) / s;
}
Quaternion normalized() const
{
return *this / length();
}
float angle(const Quaternion& q) const
{
float s = sqrt(length2() * q.length2());
assert(s != float(0.0));
return acos(dot(q) / s);
}
float getAngle() const
{
float s = float(2.) * acos(m_w);
return s;
}
Quaternion inverse() const
{
return Quaternion(m_x, m_y, m_z, -m_w);
}
inline Quaternion
operator+(const Quaternion& q2) const
{
const Quaternion& q1 = *this;
return Quaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_w + q2.m_w);
}
inline Quaternion
operator-(const Quaternion& q2) const
{
const Quaternion& q1 = *this;
return Quaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_w - q2.m_w);
}
inline Quaternion operator-() const
{
const Quaternion& q2 = *this;
return Quaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_w);
}
inline Quaternion farthest( const Quaternion& qd) const
{
Quaternion diff,sum;
diff = *this - qd;
sum = *this + qd;
if( diff.dot(diff) > sum.dot(sum) )
return qd;
return (-qd);
}
Quaternion slerp(const Quaternion& q, const float& t) const
{
float theta = angle(q);
if (theta != float(0.0))
{
float d = float(1.0) / sin(theta);
float s0 = sin((float(1.0) - t) * theta);
float s1 = sin(t * theta);
return Quaternion((m_x * s0 + q.x() * s1) * d,
(m_y * s0 + q.y() * s1) * d,
(m_z * s0 + q.z() * s1) * d,
(m_w * s0 + q.m_w * s1) * d);
}
else
{
return *this;
}
}
void toOpenGLMatrix(float m[4][4]){
float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
// calculate coefficients
x2 = m_x + m_x; y2 = m_y + m_y;
z2 = m_z + m_z;
xx = m_x * x2; xy = m_x * y2; xz = m_x * z2;
yy = m_y * y2; yz = m_y * z2; zz = m_z * z2;
wx = m_w * x2; wy = m_w * y2; wz = m_w * z2;
m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz;
m[2][0] = xz + wy; m[3][0] = 0.0;
m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz);
m[2][1] = yz - wx; m[3][1] = 0.0;
m[0][2] = xz - wy; m[1][2] = yz + wx;
m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0;
m[0][3] = 0; m[1][3] = 0;
m[2][3] = 0; m[3][3] = 1;
}
};
inline Quaternion
operator-(const Quaternion& q)
{
return Quaternion(-q.x(), -q.y(), -q.z(), -q.w());
}
inline Quaternion
operator*(const Quaternion& q1, const Quaternion& q2) {
return Quaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
}
inline Quaternion
operator*(const Quaternion& q, const Vector3& w)
{
return Quaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
-q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
}
inline Quaternion
operator*(const Vector3& w, const Quaternion& q)
{
return Quaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
-w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
}
inline float
dot(const Quaternion& q1, const Quaternion& q2)
{
return q1.dot(q2);
}
inline float
length(const Quaternion& q)
{
return q.length();
}
inline float
angle(const Quaternion& q1, const Quaternion& q2)
{
return q1.angle(q2);
}
inline Quaternion
inverse(const Quaternion& q)
{
return q.inverse();
}
inline Quaternion
slerp(const Quaternion& q1, const Quaternion& q2, const float& t)
{
return q1.slerp(q2, t);
}
inline Quaternion
shortestArcQuat(const Vector3& v0, const Vector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
{
Vector3 c = v0.cross(v1);
float d = v0.dot(v1);
if (d < -1.0 + FLT_EPSILON)
return Quaternion(0.0f,1.0f,0.0f,0.0f); // just pick any vector
float s = sqrt((1.0f + d) * 2.0f);
float rs = 1.0f / s;
return Quaternion(c.x()*rs, c.y()*rs, c.z()*rs, s * 0.5f);
}
inline Quaternion
shortestArcQuatNormalize2(Vector3& v0,Vector3& v1)
{
v0.normalize();
v1.normalize();
return shortestArcQuat(v0,v1);
}
#endif
+350
View File
@@ -0,0 +1,350 @@
/*
* Copyright 2008 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexandre Deckner
*
*/
/*
*
* This is a refactored and stripped down version of bullet-2.66 src\LinearMath\btVector3.h
* The dependancies on base class btQuadWord have been removed for simplification.
*
*/
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __VECTOR3_H__
#define __VECTOR3_H__
///Vector3 can be used to represent 3D points and vectors.
class Vector3 {
protected:
float m_x;
float m_y;
float m_z;
public:
inline Vector3() {}
inline Vector3(const Vector3& v)
{
*((Vector3*)this) = v;
}
inline Vector3(const float& x, const float& y, const float& z)
{
m_x = x, m_y = y, m_z = z;
}
inline const float& x() const { return m_x; }
inline const float& y() const { return m_y; }
inline const float& z() const { return m_z; }
inline void setValue(const float& x, const float& y, const float& z)
{
m_x=x;
m_y=y;
m_z=z;
}
inline Vector3& operator+=(const Vector3& v)
{
m_x += v.x(); m_y += v.y(); m_z += v.z();
return *this;
}
inline Vector3& operator-=(const Vector3& v)
{
m_x -= v.x(); m_y -= v.y(); m_z -= v.z();
return *this;
}
inline Vector3& operator*=(const float& s)
{
m_x *= s; m_y *= s; m_z *= s;
return *this;
}
inline Vector3& operator/=(const float& s)
{
//btFullAssert(s != float(0.0));
return *this *= float(1.0) / s;
}
inline float dot(const Vector3& v) const
{
return m_x * v.x() + m_y * v.y() + m_z * v.z();
}
inline float length2() const
{
return dot(*this);
}
inline float length() const
{
return sqrt(length2());
}
inline float distance2(const Vector3& v) const;
inline float distance(const Vector3& v) const;
inline Vector3& normalize()
{
return *this /= length();
}
inline Vector3 normalized() const;
inline Vector3 rotate( const Vector3& wAxis, const float angle );
inline float angle(const Vector3& v) const
{
float s = sqrt(length2() * v.length2());
//btFullAssert(s != float(0.0));
return acos(dot(v) / s);
}
inline Vector3 absolute() const
{
return Vector3(
fabs(m_x),
fabs(m_y),
fabs(m_z));
}
inline Vector3 cross(const Vector3& v) const
{
return Vector3(
m_y * v.z() - m_z * v.y(),
m_z * v.x() - m_x * v.z(),
m_x * v.y() - m_y * v.x());
}
inline float triple(const Vector3& v1, const Vector3& v2) const
{
return m_x * (v1.y() * v2.z() - v1.z() * v2.y()) +
m_y * (v1.z() * v2.x() - v1.x() * v2.z()) +
m_z * (v1.x() * v2.y() - v1.y() * v2.x());
}
inline int minAxis() const
{
return m_x < m_y ? (m_x < m_z ? 0 : 2) : (m_y < m_z ? 1 : 2);
}
inline int maxAxis() const
{
return m_x < m_y ? (m_y < m_z ? 2 : 1) : (m_x < m_z ? 2 : 0);
}
inline int furthestAxis() const
{
return absolute().minAxis();
}
inline int closestAxis() const
{
return absolute().maxAxis();
}
inline void setInterpolate3(const Vector3& v0, const Vector3& v1, float rt)
{
float s = float(1.0) - rt;
m_x = s * v0.x() + rt * v1.x();
m_y = s * v0.y() + rt * v1.y();
m_z = s * v0.z() + rt * v1.z();
//don't do the unused w component
// m_co[3] = s * v0[3] + rt * v1[3];
}
inline Vector3 lerp(const Vector3& v, const float& t) const
{
return Vector3(m_x + (v.x() - m_x) * t,
m_y + (v.y() - m_y) * t,
m_z + (v.z() - m_z) * t);
}
inline Vector3& operator*=(const Vector3& v)
{
m_x *= v.x(); m_y *= v.y(); m_z *= v.z();
return *this;
}
};
inline Vector3
operator+(const Vector3& v1, const Vector3& v2)
{
return Vector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z());
}
inline Vector3
operator*(const Vector3& v1, const Vector3& v2)
{
return Vector3(v1.x() * v2.x(), v1.y() * v2.y(), v1.z() * v2.z());
}
inline Vector3
operator-(const Vector3& v1, const Vector3& v2)
{
return Vector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z());
}
inline Vector3
operator-(const Vector3& v)
{
return Vector3(-v.x(), -v.y(), -v.z());
}
inline Vector3
operator*(const Vector3& v, const float& s)
{
return Vector3(v.x() * s, v.y() * s, v.z() * s);
}
inline Vector3
operator*(const float& s, const Vector3& v)
{
return v * s;
}
inline Vector3
operator/(const Vector3& v, const float& s)
{
//btFullAssert(s != float(0.0));
return v * (float(1.0) / s);
}
inline Vector3
operator/(const Vector3& v1, const Vector3& v2)
{
return Vector3(v1.x() / v2.x(),v1.y() / v2.y(),v1.z() / v2.z());
}
inline float
dot(const Vector3& v1, const Vector3& v2)
{
return v1.dot(v2);
}
inline float
distance2(const Vector3& v1, const Vector3& v2)
{
return v1.distance2(v2);
}
inline float
distance(const Vector3& v1, const Vector3& v2)
{
return v1.distance(v2);
}
inline float
angle(const Vector3& v1, const Vector3& v2)
{
return v1.angle(v2);
}
inline Vector3
cross(const Vector3& v1, const Vector3& v2)
{
return v1.cross(v2);
}
inline float
triple(const Vector3& v1, const Vector3& v2, const Vector3& v3)
{
return v1.triple(v2, v3);
}
inline Vector3
lerp(const Vector3& v1, const Vector3& v2, const float& t)
{
return v1.lerp(v2, t);
}
inline bool operator==(const Vector3& p1, const Vector3& p2)
{
return p1.x() == p2.x() && p1.y() == p2.y() && p1.z() == p2.z();
}
inline float Vector3::distance2(const Vector3& v) const
{
return (v - *this).length2();
}
inline float Vector3::distance(const Vector3& v) const
{
return (v - *this).length();
}
inline Vector3 Vector3::normalized() const
{
return *this / length();
}
inline Vector3 Vector3::rotate( const Vector3& wAxis, const float angle )
{
// wAxis must be a unit lenght vector
Vector3 o = wAxis * wAxis.dot( *this );
Vector3 x = *this - o;
Vector3 y;
y = wAxis.cross( *this );
return ( o + x * cos( angle ) + y * sin( angle ) );
}
#endif //__VECTOR3_H__