Re: [osg-users] Quat * Vec3 proposals - request for comments/help

2009-05-02 Thread Paul Fotheringham

--- On Tue, 21/4/09, J.P. Delport jpdelp...@csir.co.za wrote:

 From: J.P. Delport jpdelp...@csir.co.za
 Subject: [osg-users] Quat * Vec3 proposals - request for comments/help
 To: osg users osg-users@lists.openscenegraph.org
 Date: Tuesday, 21 April, 2009, 1:36 PM
 Hi all,
 
 it's been known for a while [1] that there are
 inconsistencies with the way OSG handles Quat * Vec3. In
 short: Quat * Vec3 is written in code as a post-multiply,
 but the result of the operation is as if a pre-multiply was
 performed. The attached test app also shows the problem
 (more on it later).
 
 [1]
 http://thread.gmane.org/gmane.comp.graphics.openscenegraph.user/21003
 and
 http://thread.gmane.org/gmane.comp.graphics.openscenegraph.user/33099
 
 What doesn't work?
 There are many examples that can be constructed of where a
 mathematical expression usings quats and vectors would not
 provide the expected results. See also [1]. The easiest one
 I could come up with is this:
 
 ((q1 * q2) * v) != (q1 * (q2 * v))
 
 Why are there not more complaints?

Well I curse this all the time, but not for the same reason. For me it's q1 * 
q2 that's annoying as I see it as the opposite of what I expect from the 
mathematics of applying a quaternion to a vector but then therein lies the 
problem.

Using operator* for matrix multiplications is fine as that mirrors precisely 
what you are doing with the matrices mathematically. Using operator* for 
quaternion multiplication is a loose analogy since you are actually doing 
q*v*q' mathematically when applying q to v. If you have two rotations, q1 
followed by q2 then you would get q2*q1*v*q1'*q2' mathematically and so I 
expect the interpretation of operator* to allow me to write q2*q1*v in code.

Of course that's just my interpretation and what I'm effectively saying within 
that interpretation is that it's quat * quat that is wrong but there's no way 
in the world you can swap that now! :)

Alternatively you could drop osg::Vec3::operator*( osg::Quat ) altogether and 
have osg::Vec3::apply( osg::Quat ) or osg::Vec3::rotate( osg::Quat ). I've used 
math libraries that do it this way (and where vec::operator*( quat ) is just 
that i.e. the mathematical multiplication rather than the full blown rotation.

I guess it depends on whether you value the brevity of operator* over the 
underlying mathematics. If operator* is still going to be used for applying a 
quaternion to a vector then I support the idea of making the multiplication 
orders consistent between quat/quat and vec/quat as per your proposal.

Making it consistent with OSG's row-major matrix multiplication is probably 
easier for coders who are not concerned with the details of the maths (and as I 
noted above it's not a workable solution to swap it now anyway).

Whatever happens I second the comment of Tanguy Fautre who asked for it to be 
documented clearly somewhere. :)

Anyway I hope you don't mind me chipping in. It certainly is interesting that 
there hasn't been more discussion. Maybe people just do what works and leave 
it. ;)

Paul Fotheringham.



  
___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] Quat * Vec3 proposals - request for comments/help

2009-05-02 Thread Paul Fotheringham

 Alternatively you could drop osg::Vec3::operator*(
 osg::Quat ) altogether and have osg::Vec3::apply( osg::Quat
 ) or osg::Vec3::rotate( osg::Quat ).

Woops. Of course I meant that it was osg::Quat::operator*( osg ::Vec3 ) that 
could be dropped. Sorry.

Paul Fotheringham.



  
___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


[osg-users] Quat * Vec3 proposals - request for comments/help

2009-04-21 Thread J.P. Delport

Hi all,

it's been known for a while [1] that there are inconsistencies with the 
way OSG handles Quat * Vec3. In short: Quat * Vec3 is written in code as 
a post-multiply, but the result of the operation is as if a pre-multiply 
was performed. The attached test app also shows the problem (more on it 
later).


[1]
http://thread.gmane.org/gmane.comp.graphics.openscenegraph.user/21003
and
http://thread.gmane.org/gmane.comp.graphics.openscenegraph.user/33099

What doesn't work?
There are many examples that can be constructed of where a mathematical 
expression usings quats and vectors would not provide the expected 
results. See also [1]. The easiest one I could come up with is this:


((q1 * q2) * v) != (q1 * (q2 * v))

Why are there not more complaints?
I suppose most people do all the quat multiplications before they 
multiply with the vector. Since OSG does not have a pre-multiply for 
quat, the only option is then to post-multiply the resulting quat with 
the vector.


What can be done?
As a first step I think we can add the pre-multiply to OSG. The attached 
header does this. (To fix the post-multiply can be done later.)


What will break?
I think and hope nothing, since there was no pre-multiply that people 
could have used. (Fixing the post-multiply would break current code.)


Why now?
The itch finally got annoying enough.

What about the post-multiply?
I think we should in some way let developers know that the post-multiply 
they currently use will change in future and that they should switch 
their multiply to the pre-version (which will behave the same as current 
code). I think a compiler warning or error would help more than only 
documentation. Something like a deprecated warning. I need help with 
this though, I do not know how to generate a warning in a cross-platform 
manner. Later we can then fix the post-multiply quat code.


Test app details:
The test app considers two rotations and a vector. It shows that for 
Matrix and Vec3 interactions everything is consistent, e.g.


((m1 * m2) * v) == (m1 * (m2 * v))
and
(v * (m1 * m2)) == ((v * m1) * m2)

It then shows that Quat post-multiply does not behave as Matrix 
post-multiply does and actually behaves more like Matrix pre-multiply 
does. It also shows the inconsistency of various expressions.


We also know (from the osgunittest example) that
m1(q1) * m2(q2) == q1 * q2
so the internal quat * quat is consistent with the matrix multiply 
order. It is only the quat * vec that is not.


Finally it shows that with the added pre-multiply (enable by making the 
#if 0 a 1), the quat pre-mult behaves the same as the matrix pre-mult.


Comments welcome.

regards
jp



--
This message is subject to the CSIR's copyright terms and conditions, e-mail legal notice, and implemented Open Document Format (ODF) standard. 
The full disclaimer details can be found at http://www.csir.co.za/disclaimer.html.


This message has been scanned for viruses and dangerous content by MailScanner, 
and is believed to be clean.  MailScanner thanks Transtec Computers for their support.


/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSG_QUAT
#define OSG_QUAT 1

#include osg/Export
#include osg/Vec3f
#include osg/Vec4f
#include osg/Vec3d
#include osg/Vec4d

namespace osg {

class Matrixf;
class Matrixd;

/** A quaternion class. It can be used to represent an orientation in 3D 
space.*/
class OSG_EXPORT Quat
{

public:

typedef double value_type;

value_type  _v[4];// a four-vector

inline Quat() { _v[0]=0.0; _v[1]=0.0; _v[2]=0.0; _v[3]=1.0; }

inline Quat( value_type x, value_type y, value_type z, value_type w )
{
_v[0]=x;
_v[1]=y;
_v[2]=z;
_v[3]=w;
}

inline Quat( const Vec4f v )
{
_v[0]=v.x();
_v[1]=v.y();
_v[2]=v.z();
_v[3]=v.w();
}

inline Quat( const Vec4d v )
{
_v[0]=v.x();
_v[1]=v.y();
_v[2]=v.z();
_v[3]=v.w();
}

inline Quat( value_type angle, const Vec3f axis)
{
makeRotate(angle,axis);
}
inline Quat( value_type angle, const Vec3d axis)
{
makeRotate(angle,axis);
}

inline Quat( value_type angle1, const Vec3f axis1, 
 value_type angle2,