void QModelNode::activate() { float minX, minY, minZ, maxX, maxY, maxZ; h3dGetNodeAABB(m_hordeID, &minX, &minY, &minZ, &maxX, &maxY, &maxZ); unsigned int cameraID = HordeSceneEditor::instance()->glContext()->activeCam(); float leftPlane = h3dGetNodeParamF(cameraID, H3DCamera::LeftPlaneF, 0 ); float rightPlane = h3dGetNodeParamF(cameraID, H3DCamera::RightPlaneF, 0); float bottomPlane = h3dGetNodeParamF(cameraID, H3DCamera::BottomPlaneF, 0); float topPlane = h3dGetNodeParamF(cameraID, H3DCamera::TopPlaneF, 0); float nearPlane = h3dGetNodeParamF(cameraID, H3DCamera::NearPlaneF, 0); const float* camera = 0; H3DNode parentNode = h3dGetNodeParent(cameraID); h3dGetNodeTransMats(parentNode, 0, &camera); if ( !camera ) return; /** * (maxX - minX) = width of the bounding box * rightPlane / (rightPlane - leftPlane) = right fraction of the viewing frustum */ float offsetX = (maxX - minX) * rightPlane / (rightPlane - leftPlane); float offsetY = (maxY - minY) * topPlane / (topPlane - bottomPlane); QMatrix4f newCamTrans = QMatrix4f::TransMat(maxX - offsetX, maxY - offsetY, maxZ); newCamTrans.translate(0, 0, qMax(nearPlane * offsetX / rightPlane, nearPlane * offsetY / topPlane)); h3dSetNodeTransMat(cameraID, (QMatrix4f(camera).inverted() * newCamTrans).x); }
void QSceneNode::setPosition(const QVec3f& position) { if (signalsBlocked()) { const float* mat = 0; h3dGetNodeTransMats(m_hordeID, &mat, 0); // Normally this should never be occure, but in case of an invalid camera this may happen if (mat == 0) return; const_cast<float*>(mat)[12] = roundIt( position.X, 5 ); const_cast<float*>(mat)[13] = roundIt( position.Y, 5 ); const_cast<float*>(mat)[14] = roundIt( position.Z, 5 ); h3dSetNodeTransMat(m_hordeID, mat); m_xmlNode.setAttribute("tx", QString::number( position.X, 'f', 5 ) ); m_xmlNode.setAttribute("ty", QString::number( position.Y, 'f', 5 )); m_xmlNode.setAttribute("tz", QString::number( position.Z, 'f', 5 )); } else if (position != QSceneNode::position()) { static const QString undoText = tr("Set Position"); if (m_model->undoStack()->undoText() == undoText) m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Position", QVariant::fromValue(position), -1)); else m_model->undoStack()->push(new QXmlNodePropertyCommand(undoText, this, "Position", QVariant::fromValue(position), TransformationID)); } }
static void updateModelCB(Model model, float* mat) { H3DNodeModel nm; nm.m = model; # ifdef DEBUG_UPDATES LOG("Updating node %d: [%.3f %.3f %.3f %.3f] [%.3f %.3f %.3f %.3f] [%.3f %.3f %.3f %.3f] [%.3f %.3f %.3f %.3f]", nm.n, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], mat[6], mat[7], mat[8], mat[9], mat[10], mat[11], mat[12], mat[13], mat[14], mat[15] ); # endif // DEBUG_UPDATES h3dSetNodeTransMat(nm.n, mat); } // end updateModelCB
void SceneGraphComponent::sendTransformation() { if (m_hordeID > 0) { // printf("Inside send Transformation with hID: %d\n", m_hordeID); const float* parentMat = 0; // since the event transformation is absolute we have to create a relative transformation matrix for Horde3D h3dGetNodeTransMats(h3dGetNodeParent(m_hordeID), 0, &parentMat); if (parentMat) h3dSetNodeTransMat(m_hordeID, (Matrix4f(parentMat).inverted() * Matrix4f(m_transformation)).x); else printf("no parent MAT\n"); // ensure reset of Horde3D transformation flag since we have updated it from the GameEngine and such don't need to be informed // when calling SceneGraphComponent::update() (note that the node transformed flag will be set again if someone else will update // the transformation from outside, so this way of avoiding unnecessary updates should be safe) h3dCheckNodeTransFlag( m_hordeID, true ); //printf("SceneGraphComponent::setTransformation\n\t %.3f, %.3f, %.3f\n", transformation[12], transformation[13], transformation[14]); m_visibilityFlag = 0; } }
void QSceneNode::setRelTrans( const QMatrix4f& relTrans) { // Does not update the XML representation h3dSetNodeTransMat(m_hordeID, relTrans.x); }
bool Gaze::computeHeadRotation( Horde3D::Vec3f *out_axis, float *out_angleRad) { //Saving the current eye transformation Horde3D::Vec3f p,r,s; m_leye->update(); Horde3D::Matrix4f eyeTransf( m_leye->getRelTransf()->x ); eyeTransf.decompose( p, r, s ); //Computing the head pitch // Allow (-10 , +10) values for head_picth // where -10 means a higher angle for the "pointing joint" therefor a "less arrogant" gaze // and +10 means a lower angle for the "point joint" therefor a "more arrogant" gaze if(m_headpitch > 10) m_headpitch = 10; else if(m_headpitch < -10) m_headpitch = -10; m_headpitch = (m_headpitch > 0) ? m_headpitch + (int)((m_headpitch/2)*(m_headpitch/2)) : m_headpitch - (int)((m_headpitch/2)*(m_headpitch/2)); //We simplify the geometric problem by saying that the head's rotational adjustment is the same as the eye's //if we position it at the center of the distance between the two eyes //This, depending on the skeleton, may be inaccurate //First, we must temporary position the eye in the center of the face, //clear its rotations and calculate the endPos //This computation is skeleton specific. Remove comments from desired aproach (TODO: better implementation) //You MUST also set the DfltEyeRot parameters to correspond to the "looking straight ahead" rotation of the eyes //** 1. Eyetype: x-axis goes left (or right), y-axis goes up (or down), z-axis comes out of the eye // Known skeletons: // - Ritchie (some versions, Bip01-Skeleton used at Human Centered Multimedia, Augsburg University) //h3dSetNodeTransform( m_leye->getHordeID(), // 0, p.y, p.z, // (float)(Config::getParamF(IK_Param::DfltEyeRotX_F) + m_headpitch), Config::getParamF(IK_Param::DfltEyeRotY_F), Config::getParamF(IK_Param::DfltEyeRotZ_F), // 1, 1, 1); //** 2. Eyetype: x-axis goes up (or down), y-axis goes left (or right), z-axis comes out of the eye // Known skeletons: // - Biergarten Agents (Bip01-Skeleton used at Human Centered Multimedia, Augsburg University) // - Ritchie (some versions, Bip01-Skeleton used at Human Centered Multimedia, Augsburg University) h3dSetNodeTransform( m_leye->getHordeID(), p.x, 0, p.z, Config::getParamF(IK_Param::DfltEyeRotX_F), (float)(Config::getParamF(IK_Param::DfltEyeRotY_F) + m_headpitch), Config::getParamF(IK_Param::DfltEyeRotZ_F), 1, 1, 1); //** 3. Eyetype: x-axis comes out of the eye, y-axis goes up (or down), z-axis goes left (or right) // Known skeletons: // - Hamster (CAT-Skeleton used at Human Centered Multimedia, Augsburg University) //h3dSetNodeTransform( m_leye->getHordeID(), // p.x, p.y, 0, // Config::getParamF(IK_Param::DfltEyeRotX_F), Config::getParamF(IK_Param::DfltEyeRotY_F), (float)(Config::getParamF(IK_Param::DfltEyeRotZ_F) + m_headpitch), // 1, 1, 1); m_aux_leye->update(); Horde3D::Vec3f endPos = m_aux_leye->getAbsTranslation(); //Second, we have to align the eye's coordinate system with the head's coordinate system //We eliminate all rotations from the eye's coordinate system h3dSetNodeTransform( m_leye->getHordeID(), p.x, 0, p.z, 0, 0, 0, 1, 1, 1); m_leye->update(); //We create the 2 vectors and normalize them Horde3D::Vec3f targetVec = m_leye->getAbsTransf()->inverted() * m_target; Horde3D::Vec3f currentVec = m_leye->getAbsTransf()->inverted() * endPos; targetVec = targetVec.normalized(); currentVec = currentVec.normalized(); //Finally, we reset the transformations h3dSetNodeTransMat( m_leye->getHordeID(), eyeTransf.x ); //get angle between vectors float angleCos = targetVec.dot(currentVec); if(angleCos < 1.0f - Config::getParamF(IK_Param::CCDRotJitterTolerance_F) ) { *out_angleRad = -acosf(angleCos); //get vector perpendicular to the plain described by two vectors *out_axis = targetVec.cross( currentVec ); *out_axis = out_axis->normalized(); return true; } return false; }