void ccGraphicalTransformationTool::apply() { assert(m_toTransform); //we recompute global GL transformation matrix and display it in console ccGLMatrixd finalTrans = m_rotation; finalTrans += m_rotationCenter + m_translation - m_rotation*m_rotationCenter; //convert matrix back and forth so as to be sure to get a 'true' rotation matrix double alpha_rad; CCVector3d axis3D,t3D; finalTrans.getParameters(alpha_rad,axis3D,t3D); ccGLMatrixd finalTransCorrected; finalTransCorrected.initFromParameters(alpha_rad,axis3D,t3D); #ifdef _DEBUG ccLog::Print("[GraphicalTransformationTool] Final transformation (before correction):"); ccLog::Print(finalTrans.toString(12,' ')); //full precision ccLog::Print(QString("Axis(%1,%2,%3) - Angle(%4) - T(%5,%6,%7)").arg(axis3D.x).arg(axis3D.y).arg(axis3D.z).arg(alpha_rad).arg(t3D.x).arg(t3D.y).arg(t3D.z)); //test: compute rotation "norm" (as it may not be exactly 1 due to numerical (in)accuracy!) { ccGLMatrixd finalRotation = finalTransCorrected; finalRotation.setTranslation(CCVector3(0,0,0)); ccGLMatrixd finalRotationT = finalRotation.transposed(); ccGLMatrixd idTrans = finalRotation * finalRotationT; double norm = idTrans.data()[0] * idTrans.data()[5] * idTrans.data()[10]; ccLog::PrintDebug("[GraphicalTransformationTool] T*T-1:"); ccLog::PrintDebug(idTrans.toString(12,' ')); //full precision ccLog::PrintDebug(QString("Rotation norm = %1").arg(norm)); } #endif //update GL transformation for all entities ccGLMatrix correctedFinalTrans(finalTransCorrected.data()); for (unsigned i=0; i<m_toTransform->getChildrenNumber(); ++i) { ccHObject* toTransform = m_toTransform->getChild(i); toTransform->setGLTransformation(correctedFinalTrans); //DGM: warning, applyGLTransformation may delete associated octree! MainWindow::ccHObjectContext objContext = MainWindow::TheInstance()->removeObjectTemporarilyFromDBTree(toTransform); toTransform->applyGLTransformation_recursive(); toTransform->prepareDisplayForRefresh_recursive(); MainWindow::TheInstance()->putObjectBackIntoDBTree(toTransform,objContext); } stop(true); clear(); //output resulting transformation matrix ccLog::Print("[GraphicalTransformationTool] Applied transformation:"); ccLog::Print(correctedFinalTrans.toString(12,' ')); //full precision #ifdef _DEBUG finalTransCorrected.getParameters(alpha_rad,axis3D,t3D); ccLog::Print(QString("Axis(%1,%2,%3) - Angle(%4) - T(%5,%6,%7)").arg(axis3D.x).arg(axis3D.y).arg(axis3D.z).arg(alpha_rad).arg(t3D.x).arg(t3D.y).arg(t3D.z)); #endif }
void ccGraphicalTransformationTool::apply() { //we recompute global GL transformation matrix and display it in console ccGLMatrixd finalTrans = m_rotation; finalTrans += m_rotationCenter + m_translation - m_rotation*m_rotationCenter; ccGLMatrixd finalTransCorrected = finalTrans; #define NORMALIZE_TRANSFORMATION_MATRIX_WITH_EULER #ifdef NORMALIZE_TRANSFORMATION_MATRIX_WITH_EULER { //convert matrix back and forth so as to be sure to get a 'true' rotation matrix //DGM: we use Euler angles, as the axis/angle method (formerly used) is not robust //enough! Shifts could be percieved by the user. double phi_rad,theta_rad,psi_rad; CCVector3d t3D; finalTrans.getParameters(phi_rad,theta_rad,psi_rad,t3D); finalTransCorrected.initFromParameters(phi_rad,theta_rad,psi_rad,t3D); #ifdef _DEBUG ccLog::Print("[GraphicalTransformationTool] Final transformation (before correction):"); ccLog::Print(finalTrans.toString(12,' ')); //full precision ccLog::Print(QString("Angles(%1,%2,%3) T(%5,%6,%7)").arg(phi_rad).arg(theta_rad).arg(psi_rad).arg(t3D.x).arg(t3D.y).arg(t3D.z)); #endif //_DEBUG } #endif //NORMALIZE_TRANSFORMATION_MATRIX_WITH_EULER #ifdef _DEBUG //test: compute rotation "norm" (as it may not be exactly 1 due to numerical (in)accuracy!) { ccGLMatrixd finalRotation = finalTransCorrected; finalRotation.setTranslation(CCVector3(0,0,0)); ccGLMatrixd finalRotationT = finalRotation.transposed(); ccGLMatrixd idTrans = finalRotation * finalRotationT; double norm = idTrans.data()[0] * idTrans.data()[5] * idTrans.data()[10]; ccLog::PrintDebug("[GraphicalTransformationTool] T*T-1:"); ccLog::PrintDebug(idTrans.toString(12,' ')); //full precision ccLog::PrintDebug(QString("Rotation norm = %1").arg(norm,0,'f',12)); } #endif //_DEBUG //update GL transformation for all entities ccGLMatrix correctedFinalTrans(finalTransCorrected.data()); for (unsigned i=0; i<m_toTransform.getChildrenNumber(); ++i) { ccHObject* toTransform = m_toTransform.getChild(i); toTransform->setGLTransformation(correctedFinalTrans); //DGM: warning, applyGLTransformation may delete the associated octree! MainWindow::ccHObjectContext objContext = MainWindow::TheInstance()->removeObjectTemporarilyFromDBTree(toTransform); toTransform->applyGLTransformation_recursive(); toTransform->prepareDisplayForRefresh_recursive(); MainWindow::TheInstance()->putObjectBackIntoDBTree(toTransform,objContext); //specif case: if the object is a mesh vertices set, we may have to update the mesh normals! if (toTransform->isA(CC_TYPES::POINT_CLOUD) && toTransform->getParent() && toTransform->getParent()->isKindOf(CC_TYPES::MESH)) { ccMesh* mesh = static_cast<ccMesh*>(toTransform->getParent()); if (mesh->hasTriNormals() && !m_toTransform.isAncestorOf(mesh)) { mesh->transformTriNormals(correctedFinalTrans); } } } stop(true); clear(); //output resulting transformation matrix ccLog::Print("[GraphicalTransformationTool] Applied transformation:"); ccLog::Print(correctedFinalTrans.toString(12,' ')); //full precision #ifdef _DEBUG { float phi_rad,theta_rad,psi_rad; Vector3Tpl<float> t3D; correctedFinalTrans.getParameters(phi_rad,theta_rad,psi_rad,t3D); ccLog::Print(QString("Angles(%1,%2,%3) T(%5,%6,%7)").arg(phi_rad).arg(theta_rad).arg(psi_rad).arg(t3D.x).arg(t3D.y).arg(t3D.z)); } #endif }