bool TextBase::computeMatrix(osg::Matrix& matrix, osg::State* state) const { if (state && (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen)) { osg::Matrix modelview = state->getModelViewMatrix(); osg::Matrix projection = state->getProjectionMatrix(); matrix.makeTranslate(-_offset); osg::Matrix rotate_matrix; if (_autoRotateToScreen) { osg::Matrix temp_matrix(modelview); temp_matrix.setTrans(0.0f,0.0f,0.0f); rotate_matrix.invert(temp_matrix); } matrix.postMultRotate(_rotation); if (_characterSizeMode!=OBJECT_COORDS) { osg::Matrix M(rotate_matrix); M.postMultTranslate(_position); M.postMult(modelview); osg::Matrix& P = projection; // compute the pixel size vector. // pre adjust P00,P20,P23,P33 by multiplying them by the viewport window matrix. // here we do it in short hand with the knowledge of how the window matrix is formed // note P23,P33 are multiplied by an implicit 1 which would come from the window matrix. // Robert Osfield, June 2002. int width = 1280; int height = 1024; const osg::Viewport* viewport = state->getCurrentViewport(); if (viewport) { width = static_cast<int>(viewport->width()); height = static_cast<int>(viewport->height()); } // scaling for horizontal pixels float P00 = P(0,0)*width*0.5f; float P20_00 = P(2,0)*width*0.5f + P(2,3)*width*0.5f; osg::Vec3 scale_00(M(0,0)*P00 + M(0,2)*P20_00, M(1,0)*P00 + M(1,2)*P20_00, M(2,0)*P00 + M(2,2)*P20_00); // scaling for vertical pixels float P10 = P(1,1)*height*0.5f; float P20_10 = P(2,1)*height*0.5f + P(2,3)*height*0.5f; osg::Vec3 scale_10(M(0,1)*P10 + M(0,2)*P20_10, M(1,1)*P10 + M(1,2)*P20_10, M(2,1)*P10 + M(2,2)*P20_10); float P23 = P(2,3); float P33 = P(3,3); float pixelSizeVector_w = M(3,2)*P23 + M(3,3)*P33; float pixelSizeVert=(_characterHeight*sqrtf(scale_10.length2()))/(pixelSizeVector_w*0.701f); float pixelSizeHori=(_characterHeight/getCharacterAspectRatio()*sqrtf(scale_00.length2()))/(pixelSizeVector_w*0.701f); // avoid nasty math by preventing a divide by zero if (pixelSizeVert == 0.0f) pixelSizeVert= 1.0f; if (pixelSizeHori == 0.0f) pixelSizeHori= 1.0f; if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } if (_characterSizeMode==SCREEN_COORDS) { float scale_font_vert=_characterHeight/pixelSizeVert; float scale_font_hori=_characterHeight/getCharacterAspectRatio()/pixelSizeHori; if (P10<0) scale_font_vert=-scale_font_vert; matrix.postMultScale(osg::Vec3f(scale_font_hori, scale_font_vert, scale_font_hori)); } else if (pixelSizeVert>getFontHeight()) { float scale_font = getFontHeight()/pixelSizeVert; matrix.postMultScale(osg::Vec3f(scale_font, scale_font, scale_font)); } } if (_autoRotateToScreen) { matrix.postMult(rotate_matrix); } matrix.postMultTranslate(_position); } else if (!_rotation.zeroRotation()) { matrix.makeTranslate(-_offset); if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } matrix.postMultRotate(_rotation); matrix.postMultTranslate(_position); // OSG_NOTICE<<"New Need to rotate "<<matrix<<std::endl; } else { matrix.makeTranslate(-_offset); if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } matrix.postMultTranslate(_position); } if (_matrix!=matrix) { _matrix = matrix; const_cast<TextBase*>(this)->dirtyBound(); } return true; }
void makeLocalMatrix(const FbxNode* pNode, osg::Matrix& m) { /*From http://area.autodesk.com/forum/autodesk-fbx/fbx-sdk/the-makeup-of-the-local-matrix-of-an-kfbxnode/ Local Matrix = LclTranslation * RotationOffset * RotationPivot * PreRotation * LclRotation * PostRotation * RotationPivotInverse * ScalingOffset * ScalingPivot * LclScaling * ScalingPivotInverse LocalTranslation : translate (xform -query -translation) RotationOffset: translation compensates for the change in the rotate pivot point (xform -q -rotateTranslation) RotationPivot: current rotate pivot position (xform -q -rotatePivot) PreRotation : joint orientation(pre rotation) LocalRotation: rotate transform (xform -q -rotation & xform -q -rotateOrder) PostRotation : rotate axis (xform -q -rotateAxis) RotationPivotInverse: inverse of RotationPivot ScalingOffset: translation compensates for the change in the scale pivot point (xform -q -scaleTranslation) ScalingPivot: current scale pivot position (xform -q -scalePivot) LocalScaling: scale transform (xform -q -scale) ScalingPivotInverse: inverse of ScalingPivot */ // When this flag is set to false, the RotationOrder, the Pre/Post rotation // values and the rotation limits should be ignored. bool rotationActive = pNode->RotationActive.Get(); EFbxRotationOrder fbxRotOrder = rotationActive ? pNode->RotationOrder.Get() : eEulerXYZ; FbxDouble3 fbxLclPos = pNode->LclTranslation.Get(); FbxDouble3 fbxRotOff = pNode->RotationOffset.Get(); FbxDouble3 fbxRotPiv = pNode->RotationPivot.Get(); FbxDouble3 fbxPreRot = pNode->PreRotation.Get(); FbxDouble3 fbxLclRot = pNode->LclRotation.Get(); FbxDouble3 fbxPostRot = pNode->PostRotation.Get(); FbxDouble3 fbxSclOff = pNode->ScalingOffset.Get(); FbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); FbxDouble3 fbxLclScl = pNode->LclScaling.Get(); m.makeTranslate(osg::Vec3d( fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0], fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1], fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2])); if (rotationActive) { m.preMultRotate( makeQuat(fbxPostRot, fbxRotOrder) * makeQuat(fbxLclRot, fbxRotOrder) * makeQuat(fbxPreRot, fbxRotOrder)); } else { m.preMultRotate(makeQuat(fbxLclRot, fbxRotOrder)); } m.preMultTranslate(osg::Vec3d( fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0], fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1], fbxSclOff[2] + fbxSclPiv[2] - fbxRotPiv[2])); m.preMultScale(osg::Vec3d(fbxLclScl[0], fbxLclScl[1], fbxLclScl[2])); m.preMultTranslate(osg::Vec3d( -fbxSclPiv[0], -fbxSclPiv[1], -fbxSclPiv[2])); }
bool TextBase::computeMatrix(osg::Matrix& matrix, osg::State* state) const { if (state && (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen)) { osg::Matrix modelview = state->getModelViewMatrix(); osg::Matrix projection = state->getProjectionMatrix(); osg::Matrix temp_matrix(modelview); temp_matrix.setTrans(0.0,0.0,0.0); osg::Matrix rotate_matrix; rotate_matrix.invert(temp_matrix); matrix.makeTranslate(-_offset); matrix.postMultRotate(_rotation); if (_characterSizeMode!=OBJECT_COORDS) { typedef osg::Matrix::value_type value_type; value_type width = 1280.0; value_type height = 1024.0; const osg::Viewport* viewport = state->getCurrentViewport(); if (viewport) { width = static_cast<value_type>(viewport->width()); height = static_cast<value_type>(viewport->height()); } osg::Matrix mvpw = rotate_matrix * osg::Matrix::translate(_position) * modelview * projection * osg::Matrix::scale(width/2.0, height/2.0, 1.0); osg::Vec3d origin = osg::Vec3d(0.0, 0.0, 0.0) * mvpw; osg::Vec3d left = osg::Vec3d(1.0, 0.0, 0.0) * mvpw - origin; osg::Vec3d up = osg::Vec3d(0.0, 1.0, 0.0) * mvpw - origin; // compute the pixel size vector. value_type length_x = left.length(); value_type scale_x = length_x>0.0 ? 1.0/length_x : 1.0; value_type length_y = up.length(); value_type scale_y = length_y>0.0 ? 1.0/length_y : 1.0; if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } if (_characterSizeMode==SCREEN_COORDS) { matrix.postMultScale(osg::Vec3(scale_x, scale_y, scale_x)); } else { value_type pixelSizeVert = _characterHeight / scale_y; // avoid nasty math by preventing a divide by zero if (pixelSizeVert == 0.0) pixelSizeVert = 1.0; if (pixelSizeVert>getFontHeight()) { value_type scale_font = getFontHeight()/pixelSizeVert; matrix.postMultScale(osg::Vec3f(scale_font, scale_font, scale_font)); } } } if (_autoRotateToScreen) { matrix.postMult(rotate_matrix); } matrix.postMultTranslate(_position); } else if (!_rotation.zeroRotation()) { matrix.makeTranslate(-_offset); if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } matrix.postMultRotate(_rotation); matrix.postMultTranslate(_position); // OSG_NOTICE<<"New Need to rotate "<<matrix<<std::endl; } else { matrix.makeTranslate(-_offset); if (_glyphNormalized) { osg::Vec3 scaleVec(_characterHeight/getCharacterAspectRatio(), _characterHeight, _characterHeight); matrix.postMultScale(scaleVec); } matrix.postMultTranslate(_position); } if (_matrix!=matrix) { _matrix = matrix; const_cast<TextBase*>(this)->dirtyBound(); } return true; }