Esempio n. 1
0
Matrix4x4f BoneBridgeCAL3D::CalculateBoneSpaceTransform() const
{
   Matrix4x4f boneSpaceTransform = Matrix4x4f::Identity();

   // set up bone space geometry transform
   {
      // transform forward by half the box length
      const Vec3f& dimensions = GetDimensions();
      boneSpaceTransform.SetTranslation(Vec3f(dimensions[Y] / 2.0f, 0.0f, 0.0f));

      // set rotational offset (the inversion of the core bone absolute rotation)
      {
         CalCoreBone* coreBone = mpCalBone->getCoreBone();

         CalQuaternion calRotAbsolute = coreBone->getRotationAbsolute();
         calRotAbsolute.invert();

         Quaternionf kernelRot = ConvertCAL3DtoKernel(calRotAbsolute);

         boneSpaceTransform.SetRotate(kernelRot);
      }
   }

   return boneSpaceTransform;
}
Esempio n. 2
0
void CalCoreBone::initBoundingBox()
{
   CalQuaternion rot;
   rot=m_rotationBoneSpace;   
  
   rot.invert();
   
   CalVector dir = CalVector(1.0f,0.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[0].setNormal(dir);

   dir = CalVector(-1.0f,0.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[1].setNormal(dir);

   dir = CalVector(0.0f,1.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[2].setNormal(dir);

   dir = CalVector(0.0f,-1.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[3].setNormal(dir);

   dir = CalVector(0.0f,0.0f,1.0f);
   dir*=rot;
   m_boundingBox.plane[4].setNormal(dir);

   dir = CalVector(0.0f,0.0f,-1.0f);
   dir*=rot;
   m_boundingBox.plane[5].setNormal(dir);
}
Esempio n. 3
0
void CSkeletonCandidate::GetTranslationAndRotation(int boneCandidateId, float time, CalVector& translation, CalQuaternion& rotation)
{
	// clear the translation and the rotation
	translation.clear();
	rotation.clear();

	// check if the bone candidate id is valid
	if((boneCandidateId < 0) || (boneCandidateId >= (int)m_vectorBoneCandidate.size())) return;

	// get the bone candidate
	CBoneCandidate *pBoneCandidate = m_vectorBoneCandidate[boneCandidateId];

	// get the node of the bone candidate
	CBaseNode *pNode = pBoneCandidate->GetNode();

	// get the parent id
	int parentId = pBoneCandidate->GetParentId();

	// get the node of the parent bone candidate
	CBaseNode *pParentNode = 0;
	if(parentId != -1)
        {
		pParentNode = m_vectorBoneCandidate[parentId]->GetNode();
	}

  // get the translation and rotation of the node
	theExporter.GetInterface()->GetTranslationAndRotation(pNode, pParentNode, time, translation, rotation);
}
Esempio n. 4
0
float
DistanceDegrees( CalQuaternion const & p1, CalQuaternion const & p2 )
{

  // To determine the angular distance between the oris, multiply one by the inverse
  // of the other, which should leave us with an identity ori if they are equal.  If
  // they are not equal, then the angular magnitude of the rotation in degrees is the
  // difference between the oris.
  CalQuaternion odist = p1;
  odist.invert();
  odist *= p2;
  float w = odist.w;
  if( w > 1 ) w = 1;
  if( w < -1 ) w = -1;
  float distrads = 2 * acos( w ); // Non-negative.
  float distdegrees = distrads * 180.0f / 3.141592654f; // Non-negative.
  if( distdegrees > 180.0 ) distdegrees -= 360.0;
  return fabsf( distdegrees );
}
Esempio n. 5
0
bool CalCoreTrack::getState(float time, CalVector& translation, CalQuaternion& rotation) const
{
  std::vector<CalCoreKeyframe*>::const_iterator iteratorCoreKeyframeBefore;
  std::vector<CalCoreKeyframe*>::const_iterator iteratorCoreKeyframeAfter;

  // get the keyframe after the requested time
  iteratorCoreKeyframeAfter = getUpperBound(time);

  // check if the time is after the last keyframe
  if(iteratorCoreKeyframeAfter == m_keyframes.end())
  {
    // return the last keyframe state
    --iteratorCoreKeyframeAfter;
    rotation = (*iteratorCoreKeyframeAfter)->getRotation();
    translation = (*iteratorCoreKeyframeAfter)->getTranslation();

    return true;
  }

  // check if the time is before the first keyframe
  if(iteratorCoreKeyframeAfter == m_keyframes.begin())
  {
    // return the first keyframe state
    rotation = (*iteratorCoreKeyframeAfter)->getRotation();
    translation = (*iteratorCoreKeyframeAfter)->getTranslation();

    return true;
  }

  // get the keyframe before the requested one
  iteratorCoreKeyframeBefore = iteratorCoreKeyframeAfter;
  --iteratorCoreKeyframeBefore;

  // get the two keyframe pointers
  CalCoreKeyframe *pCoreKeyframeBefore;
  pCoreKeyframeBefore = *iteratorCoreKeyframeBefore;
  CalCoreKeyframe *pCoreKeyframeAfter;
  pCoreKeyframeAfter = *iteratorCoreKeyframeAfter;

  // calculate the blending factor between the two keyframe states
  float blendFactor;
  blendFactor = (time - pCoreKeyframeBefore->getTime()) / (pCoreKeyframeAfter->getTime() - pCoreKeyframeBefore->getTime());

  // blend between the two keyframes
  translation = pCoreKeyframeBefore->getTranslation();
  translation.blend(blendFactor, pCoreKeyframeAfter->getTranslation());

  rotation = pCoreKeyframeBefore->getRotation();
  rotation.blend(blendFactor, pCoreKeyframeAfter->getRotation());

  return true;
}
Esempio n. 6
0
bool CalCoreTrack::getState(float time, CalVector& translation, CalQuaternion& rotation)
{
  rde::sorted_vector<float, CalCoreKeyframe *>::iterator iteratorCoreKeyframeBefore;
  rde::sorted_vector<float, CalCoreKeyframe *>::iterator iteratorCoreKeyframeAfter;

  // get the keyframe after the requested time
  iteratorCoreKeyframeAfter = m_mapCoreKeyframe.upper_bound(time);

  // check if the time is after the last keyframe
  if(iteratorCoreKeyframeAfter == m_mapCoreKeyframe.end())
  {
    // return the last keyframe state
    --iteratorCoreKeyframeAfter;
    rotation = (iteratorCoreKeyframeAfter->second)->getRotation();
    translation = (iteratorCoreKeyframeAfter->second)->getTranslation();

    return true;
  }

  // check if the time is before the first keyframe
  if(iteratorCoreKeyframeAfter == m_mapCoreKeyframe.begin())
  {
    // return the first keyframe state
    rotation = (iteratorCoreKeyframeAfter->second)->getRotation();
    translation = (iteratorCoreKeyframeAfter->second)->getTranslation();

    return true;
  }

  // get the keyframe before the requested one
  iteratorCoreKeyframeBefore = iteratorCoreKeyframeAfter;
  --iteratorCoreKeyframeBefore;

  // get the two keyframe pointers
  CalCoreKeyframe *pCoreKeyframeBefore;
  pCoreKeyframeBefore = iteratorCoreKeyframeBefore->second;
  CalCoreKeyframe *pCoreKeyframeAfter;
  pCoreKeyframeAfter = iteratorCoreKeyframeAfter->second;

  // calculate the blending factor between the two keyframe states
  float blendFactor;
  blendFactor = (time - pCoreKeyframeBefore->getTime()) / (pCoreKeyframeAfter->getTime() - pCoreKeyframeBefore->getTime());

  // blend between the two keyframes
  translation = pCoreKeyframeBefore->getTranslation();
  translation.blend(blendFactor, pCoreKeyframeAfter->getTranslation());

  rotation = pCoreKeyframeBefore->getRotation();
  rotation.blend(blendFactor, pCoreKeyframeAfter->getRotation());

  return true;
}
Esempio n. 7
0
bool
CalCoreTrack::keyframeEliminatable( CalCoreKeyframe * prev, 
                                   CalCoreKeyframe * p, 
                                   CalCoreKeyframe * next,
                                   double transTolerance,
                                   double rotTolerance )
{
  CalVector translation;
  CalQuaternion rotation;
  assert( prev && p && next );
  float time = p->getTime();
  float blendFactor;
  blendFactor = ( time - prev->getTime() ) / ( next->getTime() - prev->getTime() );

  // blend between the two keyframes
  translation = prev->getTranslation();
  translation.blend( blendFactor, next->getTranslation() );
  rotation = prev->getRotation();
  rotation.blend( blendFactor, next->getRotation() );
  CalVector const ppos = p->getTranslation();
  CalQuaternion const pori = p->getRotation();
  return Near( translation, rotation, ppos, pori, transTolerance, rotTolerance );
}
Esempio n. 8
0
void CalCoreBone::calculateBoundingBox(CalCoreModel * pCoreModel)
{
   int boneId =  m_pCoreSkeleton->getCoreBoneId(m_strName);
   bool bBoundsComputed=false;
   int planeId;
   
   CalQuaternion rot;
   rot=m_rotationBoneSpace;   
  
   rot.invert();
   
   CalVector dir = CalVector(1.0f,0.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[0].setNormal(dir);

   dir = CalVector(-1.0f,0.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[1].setNormal(dir);

   dir = CalVector(0.0f,1.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[2].setNormal(dir);

   dir = CalVector(0.0f,-1.0f,0.0f);
   dir*=rot;
   m_boundingBox.plane[3].setNormal(dir);

   dir = CalVector(0.0f,0.0f,1.0f);
   dir*=rot;
   m_boundingBox.plane[4].setNormal(dir);

   dir = CalVector(0.0f,0.0f,-1.0f);
   dir*=rot;
   m_boundingBox.plane[5].setNormal(dir);
   
   int meshId;
   for(meshId=0; meshId < pCoreModel->getCoreMeshCount(); ++meshId)
   {
       CalCoreMesh * pCoreMesh = pCoreModel->getCoreMesh(meshId);
	   
       int submeshId;
       for(submeshId=0;submeshId<pCoreMesh->getCoreSubmeshCount();submeshId++)
       {
		   CalCoreSubmesh *pCoreSubmesh = pCoreMesh->getCoreSubmesh(submeshId);
		   
		   if(pCoreSubmesh->getSpringCount()==0)
		   {
			   
			   std::vector<CalCoreSubmesh::Vertex>& vectorVertex =  pCoreSubmesh->getVectorVertex();
			   for(size_t vertexId=0;vertexId <vectorVertex.size(); ++vertexId)
			   {
				   for(size_t influenceId=0;influenceId<vectorVertex[vertexId].vectorInfluence.size();++influenceId)
				   {
					   if(vectorVertex[vertexId].vectorInfluence[influenceId].boneId == boneId && vectorVertex[vertexId].vectorInfluence[influenceId].weight > 0.5f)
					   {						   
						   for(planeId = 0; planeId < 6; ++planeId)
						   {
							   if(m_boundingBox.plane[planeId].eval(vectorVertex[vertexId].position) < 0.0f)
							   {
								   m_boundingBox.plane[planeId].setPosition(vectorVertex[vertexId].position);
								   m_boundingPosition[planeId]=vectorVertex[vertexId].position;
								   bBoundsComputed=true;
							   }
						   }
					   }
				   }
			   }	
		   }
	   }
   }

   // To handle bones with no vertices assigned 
   if(!bBoundsComputed) 
   { 
	   for(planeId = 0; planeId < 6; ++planeId) 
	   { 
		   m_boundingBox.plane[planeId].setPosition(m_translation); 
		   m_boundingPosition[planeId] = m_translation; 
	   } 
   } 
   
   m_boundingBoxPrecomputed = true;
}
Esempio n. 9
0
CalQuaternion CMilkBoneNode::GetRelativeRotation(float time)
{
	// get the initial rotation component
  msVec3 orientation;
  msBone_GetRotation(m_pIBone, orientation);

	// calculate the initial rotation component
  CalQuaternion initialRotation;
  initialRotation = ConvertToQuaternion(orientation);

  // return if the initial state is requested or if there are no keyframes
  if((time < 0.0f) || (msBone_GetRotationKeyCount(m_pIBone) == 0)) return initialRotation;

  // calculate the real frame time
  // REMEMBER: milkshape starts at 1.0!
  float frameTime;
  frameTime = 1.0f + time * (float)theExporter.GetInterface()->GetFps();

  // find the keyframe just before the requested time
  msRotationKey *pKeyBefore;
  pKeyBefore = msBone_GetRotationKeyAt(m_pIBone, msBone_GetRotationKeyCount(m_pIBone) - 1);

  int keyId;
  for(keyId = 0; keyId < msBone_GetRotationKeyCount(m_pIBone); keyId++)
  {
    // get the keyframe
    msRotationKey *pKey;
    pKey = msBone_GetRotationKeyAt(m_pIBone, keyId);

    // stop if we are over the requested time
    if(pKey->fTime > frameTime) break;

    pKeyBefore = pKey;
  }

  // get the keyframe just after the requested time
  msRotationKey *pKeyAfter;
  pKeyAfter = msBone_GetRotationKeyAt(m_pIBone, 0);

  if(keyId < msBone_GetRotationKeyCount(m_pIBone))
  {
    pKeyAfter = msBone_GetRotationKeyAt(m_pIBone, keyId);
  }

  // calculate the "just before" rotation component
  CalQuaternion rotationBefore;
  if(pKeyBefore != 0)
  {
    rotationBefore = ConvertToQuaternion(pKeyBefore->Rotation);

    // return if there is no key after this one
    if(pKeyAfter == 0) return initialRotation * rotationBefore;
  }

	// calculate the "just after" rotation component
  CalQuaternion rotationAfter;
  if(pKeyAfter != 0)
  {
    rotationAfter = ConvertToQuaternion(pKeyAfter->Rotation);

    // return if there is no key before this one
    if(pKeyBefore == 0) return initialRotation * rotationAfter;
  }

  // return if both keys are actually the same
  if(pKeyBefore == pKeyAfter) return initialRotation * rotationAfter;

  // calculate the blending factor
  float factor;
  factor = (frameTime - pKeyBefore->fTime) / (pKeyAfter->fTime - pKeyBefore->fTime);

  // blend the two rotation components
  rotationBefore.blend(factor, rotationAfter);

  return initialRotation * rotationBefore;
}
Esempio n. 10
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();
  }
}