예제 #1
0
/////////////////////////////////////
// Purpose:	set the relative translation
//			of the given bone
// Output:	bone moved
// Return:	none
/////////////////////////////////////
void IgfxObject::BoneSetTrans(s32 boneID, const Vec3D & loc)
{
	if(m_pCalModel)
	{
		Vec3D trans; BoneGetTrans(boneID, &trans);

		CalSkeleton *pSkel = m_pCalModel->getSkeleton();
		CalBone *pBone = pSkel->getBone(boneID);

		if(pBone)
		{
			pBone->setTranslation(CalVector(trans.x+loc.x, trans.y+loc.y, trans.z+loc.z));
			pBone->calculateState();
		}
	}
}
예제 #2
0
/////////////////////////////////////
// Purpose:	set the relative rotation
//			of the given bone
// Output:	bone rotated
// Return:	none
/////////////////////////////////////
void IgfxObject::BoneSetRotate(s32 boneID, const Quaternion & q)
{
	if(m_pCalModel)
	{
		Quaternion quat; BoneGetRotate(boneID, &quat);

		quat *= q;

		CalSkeleton *pSkel = m_pCalModel->getSkeleton();
		CalBone *pBone = pSkel->getBone(boneID);

		if(pBone)
		{
			pBone->setRotation(CalQuaternion(quat.x, quat.y, quat.z, quat.w));
			pBone->calculateState();
		}
	}
}
예제 #3
0
void CalBone::calculateState()
{
  // check if the bone was not touched by any active animation
  if(m_accumulatedWeight == 0.0f)
  {
    // set the bone to the initial skeleton state
    m_translation = m_pCoreBone->getTranslation();
    m_rotation = m_pCoreBone->getRotation();
  }

  // get parent bone id
  int parentId;
  parentId = m_pCoreBone->getParentId();

  if(parentId == -1)
  {
    // no parent, this means absolute state == relative state
    m_translationAbsolute = m_translation;
    m_rotationAbsolute = m_rotation;
  }
  else
  {
    // get the parent bone
    const CalBone *pParent;
    pParent = m_pSkeleton->getBone(parentId);

    // transform relative state with the absolute state of the parent
    m_translationAbsolute = m_translation;
    m_translationAbsolute *= pParent->getRotationAbsolute();
    m_translationAbsolute += pParent->getTranslationAbsolute();

    m_rotationAbsolute = m_rotation;
    m_rotationAbsolute *= pParent->getRotationAbsolute();
  }

  // calculate the bone space transformation
  m_translationBoneSpace = m_pCoreBone->getTranslationBoneSpace();

  // Must go before the *= m_rotationAbsolute.
  bool meshScalingOn;
  if( m_meshScaleAbsolute.x != 1 || m_meshScaleAbsolute.y != 1 || m_meshScaleAbsolute.z != 1 ) {
    meshScalingOn = true;
    CalVector scalevec;

    // The mesh transformation is intended to apply to the vector from the
    // bone node to the vert, relative to the model's global coordinate system.
    // For example, even though the head node's X axis aims up, the model's 
    // global coordinate system has X to stage right, Z up, and Y stage back.
    //
    // The standard vert transformation is:
    // v1 = vmesh - boneAbsPosInJpose
    // v2 = v1 * boneAbsRotInAnimPose
    // v3 = v2 + boneAbsPosInAnimPose
    //
    // Cal3d does the calculation by:
    // u1 = umesh * transformMatrix
    // u2 = u1 + translationBoneSpace
    //
    // where translationBoneSpace = 
    //   "coreBoneTranslationBoneSpace"
    //   * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose
    //
    // and where transformMatrix =
    //   "coreBoneRotBoneSpace"
    //   * boneAbsRotInAnimPose
    //
    // I don't know what "coreBoneRotBoneSpace" and "coreBoneTranslationBoneSpace" actually are,
    // but to add scale to the scandard vert transformation, I simply do:
    // 
    // v3' = vmesh           * scalevec    * boneAbsRotInAnimPose
    //   - boneAbsPosInJpose * scalevec    * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose
    //
    // Essentially, the boneAbsPosInJpose is just an extra vector added to
    // each vertex that we want to subtract out.  We must transform the extra
    // vector in exactly the same way we transform the vmesh.  Therefore if we scale the mesh, we
    // must also scale the boneAbsPosInJpose.
    //
    // Expanding out the u2 equation, we have:
    //
    // u2 = umesh * "coreBoneRotBoneSpace"   * boneAbsRotInAnimPose
    //   + "coreBoneTranslationBoneSpace"    * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose
    //
    // We assume that "coreBoneTranslationBoneSpace" = vectorThatMustBeSubtractedFromUmesh * "coreBoneRotBoneSpace":
    //
    // u2 = umesh * "coreBoneRotBoneSpace"                                 * boneAbsRotInAnimPose
    //   + vectorThatMustBeSubtractedFromUmesh * "coreBoneRotBoneSpace"    * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose
    // 
    // We assume that scale should be applied to umesh, not umesh * "coreBoneRotBoneSpace":
    //
    // u2 = umesh * scaleVec * "coreBoneRotBoneSpace" * boneAbsRotInAnimPose
    //   + "coreBoneTranslationBoneSpace" * "coreBoneRotBoneSpaceInverse" * scaleVec * "coreBoneRotBoneSpace" * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose
    //
    // which yields,
    //
    // transformMatrix' =  scaleVec * "coreBoneRotBoneSpace" * boneAbsRotInAnimPose
    //
    // and,
    //
    // translationBoneSpace' = 
    //   coreBoneTranslationBoneSpace * "coreBoneRotBoneSpaceInverse" * scaleVec * "coreBoneRotBoneSpace"
    //   * boneAbsRotInAnimPose
    //   + boneAbsPosInAnimPose

    CalQuaternion coreBoneRotBoneSpaceInverse = m_pCoreBone->getRotationBoneSpace();
    coreBoneRotBoneSpaceInverse.invert();
    m_translationBoneSpace *= coreBoneRotBoneSpaceInverse;
    m_translationBoneSpace.x *= m_meshScaleAbsolute.x;
    m_translationBoneSpace.y *= m_meshScaleAbsolute.y;
    m_translationBoneSpace.z *= m_meshScaleAbsolute.z;
    m_translationBoneSpace *= m_pCoreBone->getRotationBoneSpace();

  } else {
    meshScalingOn = false;
  }
  m_translationBoneSpace *= m_rotationAbsolute;
  m_translationBoneSpace += m_translationAbsolute;

  m_rotationBoneSpace = m_pCoreBone->getRotationBoneSpace();
  m_rotationBoneSpace *= m_rotationAbsolute;

  m_transformMatrix = m_pCoreBone->getRotationBoneSpace();
  if( meshScalingOn ) {

    // By applying each scale component to the row, instead of the column, we
    // are effectively making the scale apply prior to the rotationBoneSpace.
    m_transformMatrix.dxdx *= m_meshScaleAbsolute.x;
    m_transformMatrix.dydx *= m_meshScaleAbsolute.x;
    m_transformMatrix.dzdx *= m_meshScaleAbsolute.x;  

    m_transformMatrix.dxdy *= m_meshScaleAbsolute.y;
    m_transformMatrix.dydy *= m_meshScaleAbsolute.y;
    m_transformMatrix.dzdy *= m_meshScaleAbsolute.y;  

    m_transformMatrix.dxdz *= m_meshScaleAbsolute.z;
    m_transformMatrix.dydz *= m_meshScaleAbsolute.z;
    m_transformMatrix.dzdz *= m_meshScaleAbsolute.z;  
  }
  m_transformMatrix *= m_rotationAbsolute;

  // calculate all child bones
  std::list<int>::iterator iteratorChildId;
  int i = 0;
  for(iteratorChildId = m_pCoreBone->getListChildId().begin(); iteratorChildId != m_pCoreBone->getListChildId().end(); ++iteratorChildId, i++ )
  {
    CalBone * bo = m_pSkeleton->getBone(*iteratorChildId);
    bo->calculateState();
  }
}