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);
}
Exemple #6
0
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;
}