From fe8d097cc08f168f9b3a640db6dfc8b5423c8fd5 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 25 Jul 2002 22:08:51 +0000 Subject: [PATCH] From Ferdinand Cornelissen - Futher updates to the DOF code. --- src/osgPlugins/flt/flt2osg.cpp | 149 ++++++++++----------------------- 1 file changed, 46 insertions(+), 103 deletions(-) diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 3bc739df4..0b72eaaf9 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -627,125 +627,68 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec) visitAncillary(osgParent, *transform, rec)->addChild( transform ); visitPrimaryNode(*transform, (PrimNodeRecord*)rec); - // note for Judd (and others) shouldn't there be code in here to set up the transform matrix? - // as a transform with an identity matrix is effectively only a - // a Group... I will leave for other more familiar with the - // DofRecord to create the matrix as I don't have any Open Flight - // documentation. RO August 2001. - - // below is DOF code submitted by Sasa Bistrovic SDegreeOfFreedom* p_data = rec->getData(); - //this first transfrom is the transformation fo the local coordinate system in DOF to global; - //that one is "fixed for all times" - //the second transform describes transfromation relative to local coordinate system + // get transformation to O_world + osg::Vec3 O ( p_data->OriginLocalDOF.x(), + p_data->OriginLocalDOF.y(), + p_data->OriginLocalDOF.z()); - //first we need to setup local-to-global transform: + osg::Vec3 xAxis ( p_data->PointOnXaxis.x(), + p_data->PointOnXaxis.y(), + p_data->PointOnXaxis.z()); + xAxis = xAxis - O; + xAxis.normalize(); - //the translation matrix: - osg::Matrix l2g_translation; + osg::Vec3 xyPlane ( p_data->PointInXYplane.x(), + p_data->PointInXYplane.y(), + p_data->PointInXYplane.z()); + xyPlane = xyPlane - O; + xyPlane.normalize(); + + osg::Vec3 normalz = xAxis ^ xyPlane; + normalz.normalize(); - //translation vector - osg::Vec3 origin_translation(p_data->OriginLocalDOF.x(), p_data->OriginLocalDOF.y(), p_data->OriginLocalDOF.z()); - origin_translation *= _unitScale;//of course, has to be scaled to units used + // get X, Y, Z axis of the DOF in terms of global coordinates + osg::Vec3 Rz = normalz; + if (Rz == osg::Vec3(0,0,0)) Rz[2] = 1; + osg::Vec3 Rx = xAxis; + if (Rx == osg::Vec3(0,0,0)) Rx[0] = 1; + osg::Vec3 Ry = Rz ^ Rx; - //so we make translation matrix - l2g_translation.makeTranslate(origin_translation); + // create the putmatrix + osg::Matrix putmat( Rx.x(), Rx.y(), Rx.z(), 0, + Ry.x(), Ry.y(), Ry.z(), 0, + Rz.x(), Rz.y(), Rz.z(), 0, + O.x(), O.y(), O.z(), 1); - //now we need to construct rotation matrix that describes how is local coordinate system - //rotatoed in global: - osg::Matrix l2g_rotation; + // apply DOF transformation + osg::Vec3 trans(_unitScale*p_data->dfX._dfCurrent, + _unitScale*p_data->dfY._dfCurrent, + _unitScale*p_data->dfZ._dfCurrent); - //we make two normalized osg::Vec3s so we can cross-multiply them .... - - //first we have "point on x axis", i.e. what the DOF local looks like in global - osg::Vec3 point_on_x_axis(p_data->PointOnXaxis.x(), p_data->PointOnXaxis.y(), p_data->PointOnXaxis.z()); - point_on_x_axis *= _unitScale; - point_on_x_axis -= origin_translation;//we need to offset it for the origin - - //second, we have "point in xy plane", so x ^ y gives us local z vector - osg::Vec3 point_in_xy_plane(p_data->PointInXYplane.x(), p_data->PointInXYplane.y(), p_data->PointInXYplane.z()); - point_in_xy_plane *= _unitScale; - point_in_xy_plane -= origin_translation;//also offset it - - //just in case, normalize them: - point_on_x_axis.normalize(); - - //now, local x in global is [1 0 0 1] * rotation_matrix, so we can directly write down first row - l2g_rotation.ptr()[0] = point_on_x_axis.x(); //that is mat[0][0] - l2g_rotation.ptr()[1] = point_on_x_axis.y(); //that is mat[0][1] - l2g_rotation.ptr()[2] = point_on_x_axis.z(); //that is mat[0][2] - - - //the cross product of x ^point_in_local_xy_plane gives local z - osg::Vec3 z_transformed = point_on_x_axis ^ point_in_xy_plane; - z_transformed.normalize();//we have to normalize it, and than we can directly writ it down to rotation matrix - //we can write it down to matrix directly: - l2g_rotation.ptr()[8] = z_transformed.x(); //that is mat[2][0] - l2g_rotation.ptr()[9] = z_transformed.y(); //that is mat[2][1] - l2g_rotation.ptr()[10] = z_transformed.z(); //that is mat[2][2] - - //now that we have x and z, we can get y = z ^ x - osg::Vec3 y_transformed = z_transformed ^ point_on_x_axis; - //and just in case, we can normalize it: - // y_transformed.normalize(); - - //this goes to rotation matrix: - l2g_rotation.ptr()[4] = y_transformed.x(); //that is mat[1][0] - l2g_rotation.ptr()[5] = y_transformed.y(); //that is mat[1][0] - l2g_rotation.ptr()[6] = y_transformed.z(); //that is mat[1][0] - - - //now we have actually the second "PUT" transformation, and the first is inverse - osg::Matrix second_put = l2g_rotation * l2g_translation; - - //and we take invers of it since it has to be done at the end, see FLT spec - osg::Matrix the_first = osg::Matrix::inverse(second_put); - - //now the vertices underneath DOF are "in local system" and we do TRS, as in record - - //we setup matrix for this "second transformation" - - osg::Matrix mat; - - //first we write down translation - mat.makeTranslate(_unitScale*p_data->dfX._dfCurrent, - _unitScale*p_data->dfY._dfCurrent, - _unitScale*p_data->dfZ._dfCurrent); - - //now we read roll, pitch and yaw angles and convert them to radians float roll_rad = osg::inDegrees(p_data->dfRoll._dfCurrent); float pitch_rad = osg::inDegrees(p_data->dfPitch._dfCurrent); float yaw_rad = osg::inDegrees(p_data->dfYaw._dfCurrent); - osg::Matrix local_rotation; + float sx = rec->getData()->dfXscale.current(); + float sy = rec->getData()->dfYscale.current(); + float sz = rec->getData()->dfZscale.current(); - //the rotation part: the flt spec says this order: - osg::Matrix mat_pitch = osg::Matrix::rotate(pitch_rad, 1.0, 0.0, 0.0); - osg::Matrix mat_roll = osg::Matrix::rotate(roll_rad, 0.0, 1.0, 0.0); - osg::Matrix mat_yaw = osg::Matrix::rotate(yaw_rad, 0.0, 0.0, 1.0); - - local_rotation.preMult(mat_pitch); - local_rotation.preMult(mat_roll); - local_rotation.preMult(mat_yaw); + // this is the local DOF transformation + osg::Matrix dof_matrix = osg::Matrix::scale(sx, sy, sz)* + osg::Matrix::rotate(yaw_rad, 0.0f,0.0f,1.0f)* + osg::Matrix::rotate(roll_rad, 0.0f,1.0f,0.0f)* + osg::Matrix::rotate(pitch_rad, 1.0f,0.0f,0.0f)* + osg::Matrix::translate(trans); - mat.preMult(local_rotation); + // transforming local into global + dof_matrix.preMult(osg::Matrix::inverse(putmat)); - //and finally, we have to put up a scale as read from record - osg::Matrix scale; - scale.makeScale(p_data->dfXscale._dfCurrent, - p_data->dfYscale._dfCurrent, - p_data->dfZscale._dfCurrent); - - mat.preMult(scale); - - //we have everything ready now: the first transformation is followed by "local transformation" and than "put back" - - the_first.postMult(mat); - the_first.postMult(second_put); - - transform->setMatrix(the_first); + // transforming global into local + dof_matrix.postMult(putmat); + transform->setMatrix(dof_matrix); return transform; }