On 1/19/2011 5:29 PM, Jean-Sébastien Guay wrote:
Hi Rob,
Of course, we don't need to
make osg::Matrix::transpose() part of the public API, if we don't want
to.
I personally think there's nothing *wrong* with having a transpose()
method, it's just that if the existing M*V would have fit your use
case then it would have avoided duplicating functionality and having 2
ways of doing things, which would potentially confuse new users.
Though you may argue that *not* having a transpose() method and
relying on the M*V might confuse them more, given that it's more
obscure and hard to understand at a glance and we need a wiki page to
explain its use.
So I would be open to adding transpose(), and while you're at it,
perhaps the doxygen comment for transpose() can mention that when
transforming normals and planes you can use M*V to avoid extra
operations involved in an explicit transpose, and the doxygen comment
for the M*V operator can also mention the particular cases where this
is useful and not to confuse it with the regular V*M operator...
Attached is a patch (against trunk) that contains my original changes:
- Add a transpose() function to Matrixf and Matrixd
- Add two new osg "global" glsl uniforms: osg_NormalViewMatrix and
osg_NormalViewMatrixInverse
as well as some doxygen comments that discuss the merits of using
transpose() vs. postMult() etc. The meat of the comments are on the
preMult() and postMult() functions with see also's on the relevant
operator*() functions.
Rob
Index: include/osg/Matrixd
===================================================================
--- include/osg/Matrixd (revision 12107)
+++ include/osg/Matrixd (working copy)
@@ -249,6 +249,15 @@
value_type angle2, const Vec3d& axis2,
value_type angle3, const Vec3d& axis3);
inline static Matrixd rotate( const Quat& quat);
+ /**
+ * Returns the transpose of 'matrix'. Although this function is
occasionally
+ * useful, it is often more efficient to use the Matrix classes
postMult (M*v)
+ * function to eliminate the need to transpose the matrix in the
first place.
+ * This is especially important to keep in mind when multiplying by
vectors and planes.
+ * For example, instead of using "v * M(T)", it would be more
efficient to simply use
+ * "M * v".
+ */
+ inline static Matrixd transpose( const Matrixd& matrix );
inline static Matrixd inverse( const Matrixd& matrix);
inline static Matrixd orthoNormal(const Matrixd& matrix);
/** Create an orthographic projection matrix.
@@ -299,10 +308,21 @@
inline Vec3f operator* ( const Vec3f& v ) const;
inline Vec3d operator* ( const Vec3d& v ) const;
inline Vec4f preMult( const Vec4f& v ) const;
+ /** Transforms v by this matrix ( v * M ). This is the most commonly
used
+ * matrix multiply operation.
+ */
inline Vec4d preMult( const Vec4d& v ) const;
inline Vec4f postMult( const Vec4f& v ) const;
+ /** Transforms v by the transpose of this matrix. Conceptually, this
can
+ * be thought of as either ( M * v ) or ( v * M(Transpose) ) and it
is
+ * computationally more efficient than actually computing the
transpose
+ * of the matrix.
+ */
inline Vec4d postMult( const Vec4d& v ) const;
inline Vec4f operator* ( const Vec4f& v ) const;
+ /** A synonym for postMult()
+ * \sa postMult( const Vec4d& )
+ */
inline Vec4d operator* ( const Vec4d& v ) const;
#ifdef USE_DEPRECATED_API
@@ -511,6 +531,17 @@
return m;
}
+inline Matrixd Matrixd::transpose( const Matrixd& matrix )
+{
+ Matrixd m;
+ for( int c = 0 ; c < 4 ; c++ ) {
+ for( int r = 0 ; r < 4 ; r++ ) {
+ m(c,r) = matrix(r,c);
+ }
+ }
+ return m;
+}
+
inline Matrixd Matrixd::inverse( const Matrixd& matrix)
{
Matrixd m;
@@ -783,6 +814,9 @@
return m.preMult(v);
}
+/** A synonym for preMult()
+ * \sa Matrixd::preMult( const Vec4d& )
+ */
inline Vec4d operator* (const Vec4d& v, const Matrixd& m )
{
return m.preMult(v);
Index: include/osg/Matrixf
===================================================================
--- include/osg/Matrixf (revision 12107)
+++ include/osg/Matrixf (working copy)
@@ -249,6 +249,15 @@
value_type angle2, const Vec3d& axis2,
value_type angle3, const Vec3d& axis3);
inline static Matrixf rotate( const Quat& quat);
+ /**
+ * Returns the transpose of 'matrix'. Although this function is
occasionally
+ * useful, it is often more efficient to use the Matrix classes
postMult (M*v)
+ * function to eliminate the need to transpose the matrix in the
first place.
+ * This is especially important to keep in mind when multiplying by
vectors and planes.
+ * For example, instead of using "v * M(T)", it would be more
efficient to simply use
+ * "M * v".
+ */
+ inline static Matrixf transpose( const Matrixf& matrix );
inline static Matrixf inverse( const Matrixf& matrix);
inline static Matrixf orthoNormal(const Matrixf& matrix);
@@ -299,10 +308,21 @@
inline Vec3d postMult( const Vec3d& v ) const;
inline Vec3f operator* ( const Vec3f& v ) const;
inline Vec3d operator* ( const Vec3d& v ) const;
+ /** Transforms v by this matrix ( v * M ). This is the most commonly
used
+ * matrix multiply operation.
+ */
inline Vec4f preMult( const Vec4f& v ) const;
inline Vec4d preMult( const Vec4d& v ) const;
+ /** Transforms v by the transpose of this matrix. Conceptually, this
can
+ * be thought of as either ( M * v ) or ( v * M(Transpose) ) and it
is
+ * computationally more efficient than actually computing the
transpose
+ * of the matrix.
+ */
inline Vec4f postMult( const Vec4f& v ) const;
inline Vec4d postMult( const Vec4d& v ) const;
+ /** A synonym for postMult()
+ * \sa postMult( const Vec4f& )
+ */
inline Vec4f operator* ( const Vec4f& v ) const;
inline Vec4d operator* ( const Vec4d& v ) const;
@@ -623,6 +643,17 @@
return m;
}
+inline Matrixf Matrixf::transpose( const Matrixf& matrix )
+{
+ Matrixf m;
+ for( int c = 0 ; c < 4 ; c++ ) {
+ for( int r = 0 ; r < 4 ; r++ ) {
+ m(c,r) = matrix(r,c);
+ }
+ }
+ return m;
+}
+
inline Matrixf Matrixf::inverse( const Matrixf& matrix)
{
Matrixf m;
@@ -881,6 +912,9 @@
{
return m.preMult(v);
}
+/** A synonym for preMult()
+ * \sa Matrixf::preMult( const Vec4f& )
+ */
inline Vec4f operator* (const Vec4f& v, const Matrixf& m )
{
return m.preMult(v);
Index: src/osgUtil/SceneView.cpp
===================================================================
--- src/osgUtil/SceneView.cpp (revision 12107)
+++ src/osgUtil/SceneView.cpp (working copy)
@@ -38,6 +38,15 @@
#define GL_BACK_RIGHT 0x0403
#endif
+static osg::Matrix3 toNormalMatrix( const osg::Matrix& mat )
+{
+ osg::Matrix normVMat = osg::Matrix::orthoNormal( osg::Matrix::transpose(
osg::Matrix::inverse( mat ) ) );
+ osg::Matrix3 normalViewMatrix3x3( normVMat(0,0), normVMat(0,1),
normVMat(0,2),
+ normVMat(1,0), normVMat(1,1),
normVMat(1,2),
+ normVMat(2,0), normVMat(2,1),
normVMat(2,2) );
+ return normalViewMatrix3x3;
+}
+
static const GLubyte patternVertEven[] = {
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
@@ -417,12 +426,18 @@
{
osg::Uniform* uniform =
_localStateSet->getOrCreateUniform("osg_ViewMatrix",osg::Uniform::FLOAT_MAT4);
uniform->set(getViewMatrix());
+ osg::Uniform* uniformNorm =
_localStateSet->getOrCreateUniform("osg_NormalViewMatrix",osg::Uniform::FLOAT_MAT3);
+ uniformNorm->set(toNormalMatrix(getViewMatrix()));
}
if (_activeUniforms & VIEW_MATRIX_INVERSE_UNIFORM)
{
osg::Uniform* uniform =
_localStateSet->getOrCreateUniform("osg_ViewMatrixInverse",osg::Uniform::FLOAT_MAT4);
- uniform->set(osg::Matrix::inverse(getViewMatrix()));
+ osg::Matrix inverseViewMatrix = osg::Matrix::inverse(getViewMatrix());
+ uniform->set(inverseViewMatrix);
+ osg::Uniform* uniformNorm =
_localStateSet->getOrCreateUniform("osg_NormalViewMatrixInverse",osg::Uniform::FLOAT_MAT3);
+ osg::Matrix3 m = toNormalMatrix(inverseViewMatrix);
+ uniformNorm->set(m);
}
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org