Exemple #1
0
void IKCharacter::pullWorldPositions( int root_id, int leaf_id )
{
	CalVector root_pos;
	if ( auto_root_follow )
	{
		// get root pos
		int skel_root_id = skeleton->getCoreSkeleton()->getVectorRootCoreBoneId()[0];
		root_pos = skeleton->getBone(skel_root_id)->getTranslationAbsolute();
	}
	
	// work from the leaves down to the root
	deque<int> queue;
	if ( leaf_id == -1 )
		queue.insert( queue.begin(), leaf_bones.begin(), leaf_bones.end() );
	else
		queue.push_back( leaf_id );
	while ( !queue.empty() )
	{
		int id = queue.front();
		queue.pop_front();
		CalBone* bone = skeleton->getBone(id);
		world_positions[id] = bone->getTranslationAbsolute() - root_pos;
		int parent_id = bone->getCoreBone()->getParentId();
		if ( parent_id != -1 && id != root_id )
			queue.push_back( parent_id );
	}
	
}
Exemple #2
0
/// calculate a rotation to bring the current direction vector between parent and bone
/// to the given new direction vector (non-normalized)
ofxQuaternion IKCharacter::getRotationForParentBone( int bone_id, CalVector new_parent_to_bone_direction )
{
	CalCoreSkeleton* core_skel = skeleton->getCoreSkeleton();
	CalBone* bone = skeleton->getBone( bone_id );
	int parent_id = core_skel->getCoreBone( bone_id )->getParentId();
	CalBone* parent_bone = skeleton->getBone( parent_id );
	int parent_parent_id = parent_bone->getCoreBone()->getParentId();
	// don't rotate the base state
	if ( parent_parent_id == -1 )
		return ofxQuaternion();


	// new_parent_to_bone_direction is currently in world-space
	// we need to bring it into the space of the parent bone
	CalQuaternion bone_space_rot = bone->getRotationBoneSpace();
	bone_space_rot.invert();
	new_parent_to_bone_direction *= bone_space_rot;

	CalVector old_dir = bone->getTranslation();
	CalVector new_dir = new_parent_to_bone_direction;
	old_dir.normalize();
	new_dir.normalize();
	
	
	// rotate from one to the other
	ofxQuaternion rot;
	ofxVec3f od( old_dir.x, old_dir.y, old_dir.z );
	ofxVec3f nd( new_dir.x, new_dir.y, new_dir.z );

	rot.makeRotate( od, nd );
	
	// return
	return rot.inverse();
}
Exemple #3
0
int CalSkeleton::getBoneLinesStatic(float *pLines)
{
  int nrLines;
  nrLines = 0;

  rde::vector<CalBone *>::iterator iteratorBone;
  for(iteratorBone = m_vectorBone.begin(); iteratorBone != m_vectorBone.end(); ++iteratorBone)
  {
    int parentId;
    parentId = (*iteratorBone)->getCoreBone()->getParentId();

    if(parentId != -1)
    {
      CalBone *pParent;
      pParent = m_vectorBone[parentId];

      const CalVector& translation = (*iteratorBone)->getCoreBone()->getTranslationAbsolute();
      const CalVector& translationParent = pParent->getCoreBone()->getTranslationAbsolute();

      *pLines++ = translationParent[0];
      *pLines++ = translationParent[1];
      *pLines++ = translationParent[2];

      *pLines++ = translation[0];
      *pLines++ = translation[1];
      *pLines++ = translation[2];

      nrLines++;
    }
  }

  return nrLines;
}
Exemple #4
0
void
CalMixer::applyBoneAdjustments()
{
  CalSkeleton * pSkeleton = m_pModel->getSkeleton();
  std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone();
  unsigned int i;
  for( i = 0; i < m_numBoneAdjustments; i++ ) {
    CalMixerBoneAdjustmentAndBoneId * ba = & m_boneAdjustmentAndBoneIdArray[ i ];
    CalBone * bo = vectorBone[ ba->boneId_ ];
    CalCoreBone * cbo = bo->getCoreBone();
    if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagMeshScale ) {
      bo->setMeshScaleAbsolute( ba->boneAdjustment_.meshScaleAbsolute_ );
    }
    if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagPosRot ) {
      const CalVector & localPos = cbo->getTranslation();
      CalVector adjustedLocalPos = localPos;
      CalQuaternion adjustedLocalOri = ba->boneAdjustment_.localOri_;
      static float const scale = 1.0f;
      float rampValue = ba->boneAdjustment_.rampValue_;
      static bool const replace = true;
      static float const unrampedWeight = 1.0f;
      bo->blendState( unrampedWeight, 
        adjustedLocalPos,
        adjustedLocalOri, 
        scale, replace, rampValue );
    }
  }
}
Exemple #5
0
const std::list<int>& BoneBridgeCAL3D::GetListChildBoneID() const
{
   CalBone*     calBone  = (CalBone*)GetCalBone();
   CalCoreBone* coreBone = calBone->getCoreBone();

   std::list<int>& listChildID = coreBone->getListChildId();

   return listChildID;
}
Exemple #6
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
    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();
  m_translationBoneSpace *= m_rotationAbsolute;
  m_translationBoneSpace += m_translationAbsolute;

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

  // Generate the vertex transform.  If I ever add support for bone-scaling
  // to Cal3D, this step will become significantly more complex.
  m_transformMatrix = m_rotationBoneSpace;

  // calculate all child bones
  std::list<int>::iterator iteratorChildId;
  for(iteratorChildId = m_pCoreBone->getListChildId().begin(); iteratorChildId != m_pCoreBone->getListChildId().end(); ++iteratorChildId)
  {
    m_pSkeleton->getBone(*iteratorChildId)->calculateState();
  }
}
Exemple #7
0
/////////////////////////////////////
// Purpose:	get the translation
//			to bring a point into the 
//			bone instance space
//			of given boneID
// Output:	pLoc set
// Return:	none
/////////////////////////////////////
void IgfxObject::BoneGetTransBoneSpace(s32 boneID, Vec3D *pLoc)
{
	if(m_pCalModel)
	{
		CalSkeleton *pSkel = m_pCalModel->getSkeleton();
		CalBone *pBone = pSkel->getBone(boneID);
		CalVector cVec = pBone->getTranslationBoneSpace();

		pLoc->x = cVec.x;
		pLoc->y = cVec.y;
		pLoc->z = cVec.z;
	}
}
Exemple #8
0
/////////////////////////////////////
// Purpose:	get the given bone's
//			bone space transformation
// Output:	pMtx filled
// Return:	none
/////////////////////////////////////
void IgfxObject::BoneGetTransformMtx(s32 boneID, Matrix *pMtx)
{
	if(m_pCalModel)
	{
		CalSkeleton *pSkel = m_pCalModel->getSkeleton();
		CalBone *pBone = pSkel->getBone(boneID);
		CalMatrix cMtx = pBone->getTransformMatrix();

		pMtx->_11 = cMtx.dxdx; pMtx->_21 = cMtx.dydx; pMtx->_31 = cMtx.dzdx; pMtx->_41 = 0;
		pMtx->_12 = cMtx.dxdy; pMtx->_22 = cMtx.dydy; pMtx->_32 = cMtx.dzdy; pMtx->_42 = 0;
		pMtx->_13 = cMtx.dxdz; pMtx->_23 = cMtx.dydz; pMtx->_33 = cMtx.dzdz; pMtx->_43 = 0;
		pMtx->_14 = 0;         pMtx->_24 = 0;		  pMtx->_34 = 0;         pMtx->_44 = 1;
	}
}
Exemple #9
0
/////////////////////////////////////
// Purpose:	get the rotation
//			to bring a point into the 
//			bone instance space
// Output:	pQ set
// Return:	none
/////////////////////////////////////
void IgfxObject::BoneGetRotateBoneSpace(s32 boneID, Quaternion *pQ)
{
	if(m_pCalModel)
	{
		CalSkeleton *pSkel = m_pCalModel->getSkeleton();
		CalBone *pBone = pSkel->getBone(boneID);
		CalQuaternion cQuat = pBone->getRotationBoneSpace();

		pQ->x = cQuat.x;
		pQ->y = cQuat.y;
		pQ->z = cQuat.z;
		pQ->w = cQuat.w;
	}
}
Exemple #10
0
bool CalSkeleton::create(CalCoreSkeleton *pCoreSkeleton)
{
  if(pCoreSkeleton == 0)
  {
    CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
    return false;
  }

  m_pCoreSkeleton = pCoreSkeleton;

  // clone the skeleton structure of the core skeleton
  rde::vector<CalCoreBone *>& vectorCoreBone = pCoreSkeleton->getVectorCoreBone();

  // get the number of bones
  int boneCount;
  boneCount = vectorCoreBone.size();

  // reserve space in the bone vector
  m_vectorBone.reserve(boneCount);

  // clone every core bone
  int boneId;
  for(boneId = 0; boneId < boneCount; boneId++)
  {
    CalBone *pBone;
    pBone = new CalBone();
    if(pBone == 0)
    {
      CalError::setLastError(CalError::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__);
      return false;
    }

    // create a bone for every core bone
    if(!pBone->create(vectorCoreBone[boneId]))
    {
      delete pBone;
      return false;
    }

    // set skeleton in the bone instance
    pBone->setSkeleton(this);

    // insert bone into bone vector
    m_vectorBone.push_back(pBone);
  }

  return true;
}
Exemple #11
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();
		}
	}
}
Exemple #12
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();
		}
	}
}
core::matrix4 CCal3DSceneNode::getBoneMatrix( s32 boneId ) const
{
    if ( calModel == 0 ) return core::matrix4();
    
    CalSkeleton* skeleton = calModel->getSkeleton();
    CalBone* bone = skeleton->getBone(boneId);
    
    CalQuaternion rot = bone->getRotationAbsolute();
    CalVector pos = bone->getTranslationAbsolute();
    
    // Note: Swap Y and Z to convert to Irrlicht coordinates
    core::quaternion quat = core::quaternion( rot.x, rot.y, rot.z, rot.w );
    core::vector3df v = core::vector3df( pos.x, pos.y, pos.z );
    
    core::matrix4 mat = quat.getMatrix();
    mat.setTranslation(v);
    
    return mat;
}
Exemple #14
0
void IKCharacter::pullWorldPositions( int root_id, int leaf_id )
{
    deque<int> queue;
    if ( leaf_id == -1 )
        queue.insert( queue.begin(), leaf_bones.begin(), leaf_bones.end() );
    else
        queue.push_back( leaf_id );

    // work backwards up the tree
    while ( !queue.empty() )
    {
        int id = queue.front();
        queue.pop_front();
        CalBone* bone = skeleton->getBone(id);
        world_positions[id] = bone->getTranslationAbsolute();
        int parent_id = bone->getCoreBone()->getParentId();
        if ( parent_id != -1 && id != root_id )
            queue.push_back( parent_id );
    }

}
Exemple #15
0
int CalPhysique::calculateVerticesNormalsAndTexCoords(CalSubmesh *pSubmesh, float *pVertexBuffer, int NumTexCoords) const
{
  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();

  // get vertex vector of the core submesh
  std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pSubmesh->getCoreSubmesh()->getVectorVertex();

  // get the texture coordinate vector vector
  std::vector<std::vector<CalCoreSubmesh::TextureCoordinate> >& vectorvectorTextureCoordinate = pSubmesh->getCoreSubmesh()->getVectorVectorTextureCoordinate();

  int TextureCoordinateCount=(int)vectorvectorTextureCoordinate.size();

  // check if the map id is valid
  if(((NumTexCoords < 0) || (NumTexCoords > TextureCoordinateCount)))
  {
	 if(TextureCoordinateCount!=0)
	 {
		 CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
		 return -1;
	 }
  }

  // get physical property vector of the core submesh
  std::vector<CalCoreSubmesh::PhysicalProperty>& vectorPhysicalProperty = pSubmesh->getCoreSubmesh()->getVectorPhysicalProperty();

  // get the number of vertices
  int vertexCount;
  vertexCount = pSubmesh->getVertexCount();

  // get the sub morph target vector from the core sub mesh
  std::vector<CalCoreSubMorphTarget*>& vectorSubMorphTarget =
  pSubmesh->getCoreSubmesh()->getVectorCoreSubMorphTarget();



  // get the number of morph targets
  int morphTargetCount = pSubmesh->getMorphTargetWeightCount();

  // Check for spring case
  bool	hasSpringsAndInternalData =
	(pSubmesh->getCoreSubmesh()->getSpringCount() > 0) &&
	pSubmesh->hasInternalData();

  // calculate all submesh vertices
  int vertexId;
  for(vertexId = 0; vertexId < vertexCount; ++vertexId)
  {
    // get the vertex
    CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

    // blend the morph targets
    CalVector position=vertex.position;
    CalVector normal=vertex.normal;

    {

      int morphTargetId;
      for(morphTargetId=0; morphTargetId < morphTargetCount;++morphTargetId)
      {
         CalCoreSubMorphTarget::BlendVertex const * blendVertex =
            vectorSubMorphTarget[morphTargetId]->getBlendVertex(vertexId);
         float currentWeight = pSubmesh->getMorphTargetWeight(morphTargetId);
         if( currentWeight != 0 ) {
            if( blendVertex ) {
               position.x += currentWeight*blendVertex->position.x;
               position.y += currentWeight*blendVertex->position.y;
               position.z += currentWeight*blendVertex->position.z;
               normal.x += currentWeight*blendVertex->normal.x;
               normal.y += currentWeight*blendVertex->normal.y;
               normal.z += currentWeight*blendVertex->normal.z;
            }
         }
      }
    }

    // initialize vertex
    float x, y, z;
    x = 0.0f;
    y = 0.0f;
    z = 0.0f;

	// initialize normal
    float nx, ny, nz;
    nx = 0.0f;
    ny = 0.0f;
    nz = 0.0f;

    // blend together all vertex influences
    int influenceId;
	int influenceCount=(int)vertex.vectorInfluence.size();
	if(influenceCount == 0)
	{
      x = position.x;
      y = position.y;
      z = position.z;
      nx = normal.x;
      ny = normal.y;
      nz = normal.z;
    }
	else
	{
		for(influenceId = 0; influenceId < influenceCount; ++influenceId)
		{
			// get the influence
			CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

			// get the bone of the influence vertex
			CalBone *pBone;
			pBone = vectorBone[influence.boneId];

			// transform vertex with current state of the bone
			CalVector v(position);
			v *= pBone->getTransformMatrix();
			v += pBone->getTranslationBoneSpace();

			x += influence.weight * v.x;
			y += influence.weight * v.y;
			z += influence.weight * v.z;

			// transform normal with current state of the bone
			CalVector n(normal);
			n *= pBone->getTransformMatrix();

			nx += influence.weight * n.x;
			ny += influence.weight * n.y;
			nz += influence.weight * n.z;
		}
	}

    // save vertex position
    if(hasSpringsAndInternalData)
    {
      // get the pgysical property of the vertex
      CalCoreSubmesh::PhysicalProperty& physicalProperty = vectorPhysicalProperty[vertexId];

      // assign new vertex position if there is no vertex weight
      if(physicalProperty.weight == 0.0f)
      {
        pVertexBuffer[0] = x * m_axisFactorX;
        pVertexBuffer[1] = y * m_axisFactorY;
        pVertexBuffer[2] = z * m_axisFactorZ;
      }
    }
    else
    {
      pVertexBuffer[0] = x * m_axisFactorX;
      pVertexBuffer[1] = y * m_axisFactorY;
      pVertexBuffer[2] = z * m_axisFactorZ;
    }

	 // re-normalize normal if necessary
    if (m_Normalize)
    {
	  nx/= m_axisFactorX;
	  ny/= m_axisFactorY;
	  nz/= m_axisFactorZ;

      float scale;
      scale = (float) (1.0f / sqrt(nx * nx + ny * ny + nz * nz));

      pVertexBuffer[3] = nx * scale;
      pVertexBuffer[4] = ny * scale;
      pVertexBuffer[5] = nz * scale;
    }
    else
    {
      pVertexBuffer[3] = nx;
      pVertexBuffer[4] = ny;
      pVertexBuffer[5] = nz;
    }

	pVertexBuffer += 6;

	if(TextureCoordinateCount==0)
	{
		pVertexBuffer+=NumTexCoords*2;
	}
	else
	{
		for(int mapId=0; mapId < NumTexCoords; ++mapId)
		{
			pVertexBuffer[0] = vectorvectorTextureCoordinate[mapId][vertexId].u;
			pVertexBuffer[1] = vectorvectorTextureCoordinate[mapId][vertexId].v;
			pVertexBuffer += 2;
		}
	}
  }

  return vertexCount;
}
Exemple #16
0
int CalPhysique::calculateVertices(CalSubmesh *pSubmesh, float *pVertexBuffer, int stride) const
{
  if(stride <= 0)
  {
	  stride = 3*sizeof(float);
  }

  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();

  // get vertex vector of the core submesh
  std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pSubmesh->getCoreSubmesh()->getVectorVertex();

  // get physical property vector of the core submesh
  std::vector<CalCoreSubmesh::PhysicalProperty>& vectorPhysicalProperty = pSubmesh->getCoreSubmesh()->getVectorPhysicalProperty();

  // get the number of vertices
  int vertexCount;
  vertexCount = pSubmesh->getVertexCount();

  // get the sub morph target vector from the core sub mesh
  std::vector<CalCoreSubMorphTarget*>& vectorSubMorphTarget =
  pSubmesh->getCoreSubmesh()->getVectorCoreSubMorphTarget();


  // Get the number of morph targets and cache the weights in an array
  // that can be indexed quickly inside the vertex inner loop.
  int morphTargetCount = pSubmesh->getMorphTargetWeightCount();
  static int const morphTargetCountMax = 100; // Arbitrary.
  if( morphTargetCount > morphTargetCountMax ) {
     morphTargetCount = morphTargetCountMax;
  }
  static float morphTargetScaleArray[ morphTargetCountMax ];
  for(int i = 0; i < morphTargetCount; i++ )
  {
     morphTargetScaleArray[ i ] = pSubmesh->getMorphTargetWeight( i );
  }

  // Check for spring case
  bool	hasSpringsAndInternalData =
	(pSubmesh->getCoreSubmesh()->getSpringCount() > 0) &&
	pSubmesh->hasInternalData();



  // calculate all submesh vertices
  int vertexId;
  for(vertexId = 0; vertexId < vertexCount; ++vertexId)
  {
    // get the vertex
    CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

    // blend the morph targets
    CalVector position=vertex.position;

    {

      int morphTargetId;
      for(morphTargetId=0; morphTargetId < morphTargetCount;++morphTargetId)
      {
         CalCoreSubMorphTarget::BlendVertex const * blendVertex =
            vectorSubMorphTarget[morphTargetId]->getBlendVertex(vertexId);
         float morphScale = morphTargetScaleArray[ morphTargetId ];
         if( blendVertex )
         {
            position.x += morphScale * blendVertex->position.x;
            position.y += morphScale * blendVertex->position.y;
            position.z += morphScale * blendVertex->position.z;
         }

      }
    }

    // initialize vertex
    float x, y, z;
    x = 0.0f;
    y = 0.0f;
    z = 0.0f;

    // blend together all vertex influences
    size_t influenceCount=vertex.vectorInfluence.size();
    if(influenceCount == 0)
	{
      x = position.x;
      y = position.y;
      z = position.z;
    }
	else
	{
		for(size_t influenceId = 0; influenceId < influenceCount; ++influenceId)
		{
			// get the influence
			CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

			// get the bone of the influence vertex
			CalBone *pBone;
			pBone = vectorBone[influence.boneId];

			// transform vertex with current state of the bone
			CalVector v(position);
			v *= pBone->getTransformMatrix();
			v += pBone->getTranslationBoneSpace();

			x += influence.weight * v.x;
			y += influence.weight * v.y;
			z += influence.weight * v.z;
		}
	}

    // save vertex position
    if(hasSpringsAndInternalData)
    {
      // get the physical property of the vertex
      CalCoreSubmesh::PhysicalProperty& physicalProperty = vectorPhysicalProperty[vertexId];

      // assign new vertex position if there is no vertex weight
      if(physicalProperty.weight == 0.0f)
      {
        pVertexBuffer[0] = x * m_axisFactorX;
        pVertexBuffer[1] = y * m_axisFactorY;
        pVertexBuffer[2] = z * m_axisFactorZ;
      }
    }
    else
    {
      pVertexBuffer[0] = x * m_axisFactorX;
      pVertexBuffer[1] = y * m_axisFactorY;
      pVertexBuffer[2] = z * m_axisFactorZ;
    }

    // next vertex position in buffer
    pVertexBuffer = (float *)(((char *)pVertexBuffer) + stride) ;
  }

  return vertexCount;
}
Exemple #17
0
int CalPhysique::calculateVerticesAndNormals(CalSubmesh *pSubmesh, float *pVertexBuffer, int stride) const
{
  if(stride <= 0)
  {
	  stride = 6*sizeof(float);
  }

  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();
 // CalBone ** vectorBonePtr = &vectorBone[0];

  // get vertex vector of the core submesh
  CalCoreSubmesh::Vertex* vectorVertex = &pSubmesh->getCoreSubmesh()->getVectorVertex()[0];

  // get physical property vector of the core submesh
  std::vector<CalCoreSubmesh::PhysicalProperty>& vectorPhysicalProperty = pSubmesh->getCoreSubmesh()->getVectorPhysicalProperty();

  // get the number of vertices
  int vertexCount = pSubmesh->getVertexCount();

  // get the sub morph target vector from the core sub mesh
  std::vector<CalCoreSubMorphTarget*>& vectorSubMorphTarget =
	pSubmesh->getCoreSubmesh()->getVectorCoreSubMorphTarget();



  // get the number of morph targets
  int morphTargetCount = pSubmesh->getMorphTargetWeightCount();
  EnlargeMiawCacheAsNecessary( morphTargetCount );
  unsigned int numMiaws;
  pSubmesh->getMorphIdAndWeightArray( MiawCache, & numMiaws, ( unsigned int ) morphTargetCount );



  // Check for spring case
  bool	hasSpringsAndInternalData =
	(pSubmesh->getCoreSubmesh()->getSpringCount() > 0) &&
	pSubmesh->hasInternalData();

  // calculate all submesh vertices
  int vertexId;
  //CalCoreSubMorphTarget::BlendVertex	blendVertex;
  for(vertexId = 0; vertexId < vertexCount; ++vertexId)
  {
    // get the vertex
    CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

    // Off unless normalizing set to on and either there are morph targets or multiple influences.
    bool mustNormalize = false;

    // blend the morph targets
    CalVector position=vertex.position;
    CalVector normal=vertex.normal;

    {

       mustNormalize = true; // Morph targets can skew normals.
       unsigned int i;

       for( i = 0; i < numMiaws; i++ ) {
          MorphIdAndWeight * miaw = & MiawCache[ i ];
          int morphTargetId = miaw->morphId_;
          CalCoreSubMorphTarget::BlendVertex const * blendVertex =
             vectorSubMorphTarget[morphTargetId]->getBlendVertex(vertexId);
          float currentWeight = miaw->weight_;
          if( blendVertex ) {
             position.x += currentWeight*blendVertex->position.x;
             position.y += currentWeight*blendVertex->position.y;
             position.z += currentWeight*blendVertex->position.z;
             normal.x += currentWeight*blendVertex->normal.x;
             normal.y += currentWeight*blendVertex->normal.y;
             normal.z += currentWeight*blendVertex->normal.z;
          }
       }

    }

    // initialize vertex
    float x, y, z;
    x = 0.0f;
    y = 0.0f;
    z = 0.0f;

	// initialize normal
    float nx, ny, nz;
    nx = 0.0f;
    ny = 0.0f;
    nz = 0.0f;

    // blend together all vertex influences
    int influenceId;
	int influenceCount=(int)vertex.vectorInfluence.size();
    if(influenceCount > 1)
	{
      mustNormalize = true; // If multiple influences, normalize the normals!
    }

    for(influenceId = 0; influenceId < influenceCount; ++influenceId)
    {
       // get the influence
       CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

       // get the bone of the influence vertex
       CalBone *pBone;
       pBone = vectorBone[influence.boneId];

       // transform vertex with current state of the bone
       CalVector v(position);
       v *= pBone->getTransformMatrix();
       v += pBone->getTranslationBoneSpace();

       x += influence.weight * v.x;
       y += influence.weight * v.y;
       z += influence.weight * v.z;

       // transform normal with current state of the bone
       CalVector n(normal);
       n *= pBone->getTransformMatrix();

       nx += influence.weight * n.x;
       ny += influence.weight * n.y;
       nz += influence.weight * n.z;
    }
    // save vertex position
    if(hasSpringsAndInternalData)
    {
       mustNormalize = true;

      // get the physical property of the vertex
      CalCoreSubmesh::PhysicalProperty& physicalProperty = vectorPhysicalProperty[vertexId];

      // assign new vertex position if there is no vertex weight
      if(physicalProperty.weight == 0.0f)
      {
        pVertexBuffer[0] = x * m_axisFactorX;
        pVertexBuffer[1] = y * m_axisFactorY;
        pVertexBuffer[2] = z * m_axisFactorZ;
      }
    }
    else
    {
      pVertexBuffer[0] = x * m_axisFactorX;
      pVertexBuffer[1] = y * m_axisFactorY;
      pVertexBuffer[2] = z * m_axisFactorZ;
    }

    // re-normalize normal if necessary
    if (m_Normalize && mustNormalize)
    {
	  nx/= m_axisFactorX;
	  ny/= m_axisFactorY;
	  nz/= m_axisFactorZ;

      float scale;
      scale = (float)( 1.0f / sqrt(nx * nx + ny * ny + nz * nz));

      pVertexBuffer[3] = nx * scale;
      pVertexBuffer[4] = ny * scale;
      pVertexBuffer[5] = nz * scale;
    }
    else
    {
      pVertexBuffer[3] = nx;
      pVertexBuffer[4] = ny;
      pVertexBuffer[5] = nz;
    }


	// next vertex position in buffer
    pVertexBuffer = (float *)(((char *)pVertexBuffer) + stride) ;
  }

  return vertexCount;
}
Exemple #18
0
int CalPhysique::calculateNormals(CalSubmesh *pSubmesh, float *pNormalBuffer, int stride) const
{
  if(stride <= 0)
  {
	  stride = 3*sizeof(float);
  }

  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();

  // get vertex vector of the submesh
  std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pSubmesh->getCoreSubmesh()->getVectorVertex();

  // get the number of vertices
  int vertexCount;
  vertexCount = pSubmesh->getVertexCount();

  // get the sub morph target vector from the core sub mesh
  std::vector<CalCoreSubMorphTarget*>& vectorSubMorphTarget =
  pSubmesh->getCoreSubmesh()->getVectorCoreSubMorphTarget();



  // get the number of morph targets
  int morphTargetCount = pSubmesh->getMorphTargetWeightCount();

  // calculate normal for all submesh vertices
  int vertexId;
  for(vertexId = 0; vertexId < vertexCount; ++vertexId)
  {
    // get the vertex
    CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

    // blend the morph targets
    CalVector normal=vertex.normal;

    {
      int morphTargetId;
      for(morphTargetId=0; morphTargetId < morphTargetCount;++morphTargetId)
      {
         CalCoreSubMorphTarget::BlendVertex const * blendVertex =
            vectorSubMorphTarget[morphTargetId]->getBlendVertex(vertexId);
         float currentWeight = pSubmesh->getMorphTargetWeight(morphTargetId);
         if( blendVertex ) {
            normal.x += currentWeight*blendVertex->normal.x;
            normal.y += currentWeight*blendVertex->normal.y;
            normal.z += currentWeight*blendVertex->normal.z;
         }
      }
    }

    // initialize normal
    float nx, ny, nz;
    nx = 0.0f;
    ny = 0.0f;
    nz = 0.0f;

    // blend together all vertex influences
    int influenceId;
	int influenceCount=(int)vertex.vectorInfluence.size();
    if(influenceCount == 0)
	{
      nx = normal.x;
      ny = normal.y;
      nz = normal.z;
    }
	else
	{
		for(influenceId = 0; influenceId < influenceCount; ++influenceId)
		{
			// get the influence
			CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

			// get the bone of the influence vertex
			CalBone *pBone;
			pBone = vectorBone[influence.boneId];

			// transform normal with current state of the bone
			CalVector v(normal);
			v *= pBone->getTransformMatrix();

			nx += influence.weight * v.x;
			ny += influence.weight * v.y;
			nz += influence.weight * v.z;
		}
	}

    // re-normalize normal if necessary
    if (m_Normalize)
    {
	  nx/= m_axisFactorX;
	  ny/= m_axisFactorY;
	  nz/= m_axisFactorZ;

      float scale;
      scale = (float)( 1.0f / sqrt(nx * nx + ny * ny + nz * nz));

      pNormalBuffer[0] = nx * scale;
      pNormalBuffer[1] = ny * scale;
      pNormalBuffer[2] = nz * scale;
    }
    else
    {
      pNormalBuffer[0] = nx;
      pNormalBuffer[1] = ny;
      pNormalBuffer[2] = nz;
    }

    // next vertex position in buffer
    pNormalBuffer = (float *)(((char *)pNormalBuffer) + stride) ;
  }

  return vertexCount;
}
Exemple #19
0
int CalPhysique::calculateTangentSpaces(CalSubmesh *pSubmesh, int mapId, float *pTangentSpaceBuffer, int stride) const
{
  if((mapId < 0) || (mapId >= (int)pSubmesh->getCoreSubmesh()->getVectorVectorTangentSpace().size())) return false;
  if(stride <= 0)
  {
	  stride = 4*sizeof(float);
  }

  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();

  // get vertex vector of the submesh
  std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pSubmesh->getCoreSubmesh()->getVectorVertex();

  // get tangent space vector of the submesh
  std::vector<CalCoreSubmesh::TangentSpace>& vectorTangentSpace = pSubmesh->getCoreSubmesh()->getVectorVectorTangentSpace()[mapId];

  // get the number of vertices
  int vertexCount;
  vertexCount = pSubmesh->getVertexCount();

  // calculate normal for all submesh vertices
  int vertexId;
  for(vertexId = 0; vertexId < vertexCount; vertexId++)
  {
    CalCoreSubmesh::TangentSpace& tangentSpace = vectorTangentSpace[vertexId];

    // get the vertex
    CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

    // initialize tangent
    float tx, ty, tz;
    tx = 0.0f;
    ty = 0.0f;
    tz = 0.0f;

    // blend together all vertex influences
    int influenceId;
    int influenceCount=(int)vertex.vectorInfluence.size();

    for(influenceId = 0; influenceId < influenceCount; influenceId++)
    {
      // get the influence
      CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

      // get the bone of the influence vertex
      CalBone *pBone;
      pBone = vectorBone[influence.boneId];

      // transform normal with current state of the bone
      CalVector v(tangentSpace.tangent);
      v *= pBone->getTransformMatrix();

      tx += influence.weight * v.x;
      ty += influence.weight * v.y;
      tz += influence.weight * v.z;
    }

    // re-normalize tangent if necessary
    if (m_Normalize)
    {
      float scale;
	  tx/= m_axisFactorX;
	  ty/= m_axisFactorY;
	  tz/= m_axisFactorZ;

      scale = (float)( 1.0f / sqrt(tx * tx + ty * ty + tz * tz));

      pTangentSpaceBuffer[0] = tx * scale;
      pTangentSpaceBuffer[1] = ty * scale;
      pTangentSpaceBuffer[2] = tz * scale;
    }
    else
    {
      pTangentSpaceBuffer[0] = tx;
      pTangentSpaceBuffer[1] = ty;
      pTangentSpaceBuffer[2] = tz;
    }

    pTangentSpaceBuffer[3] = tangentSpace.crossFactor;
    // next vertex position in buffer
    pTangentSpaceBuffer = (float *)(((char *)pTangentSpaceBuffer) + stride) ;
  }

  return vertexCount;
}
Exemple #20
0
CalVector CalPhysique::calculateVertex(CalSubmesh *pSubmesh, int vertexId)
{
  // get bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = m_pModel->getSkeleton()->getVectorBone();

  // get vertex of the core submesh
  std::vector<CalCoreSubmesh::Vertex>& vectorVertex = pSubmesh->getCoreSubmesh()->getVectorVertex();

  // get physical property vector of the core submesh
  //std::vector<CalCoreSubmesh::PhysicalProperty>& vectorPhysicalProperty = pSubmesh->getCoreSubmesh()->getVectorPhysicalProperty();

  // get the sub morph target vector from the core sub mesh
  std::vector<CalCoreSubMorphTarget*>& vectorSubMorphTarget =
  pSubmesh->getCoreSubmesh()->getVectorCoreSubMorphTarget();



  // get the number of morph targets
  int morphTargetCount = pSubmesh->getMorphTargetWeightCount();

  // get the vertex
  CalCoreSubmesh::Vertex& vertex = vectorVertex[vertexId];

  // blend the morph targets
  CalVector position=vertex.position;


  {

    int morphTargetId;
    for(morphTargetId=0; morphTargetId < morphTargetCount;++morphTargetId)
    {
      CalCoreSubMorphTarget::BlendVertex	blendVertex;
	  vectorSubMorphTarget[morphTargetId]->getBlendVertex(vertexId, blendVertex);
      float currentWeight = pSubmesh->getMorphTargetWeight(morphTargetId);
      position.x += currentWeight*blendVertex.position.x;
      position.y += currentWeight*blendVertex.position.y;
      position.z += currentWeight*blendVertex.position.z;
    }
  }

  // initialize vertex
  float x, y, z;
  x = 0.0f;
  y = 0.0f;
  z = 0.0f;

  // blend together all vertex influences
  int influenceId;
  int influenceCount=(int)vertex.vectorInfluence.size();
  if(influenceCount == 0)
  {
    x = position.x;
    y = position.y;
    z = position.z;
  }
  else
  {
	  for(influenceId = 0; influenceId < influenceCount; ++influenceId)
	  {
		  // get the influence
		  CalCoreSubmesh::Influence& influence = vertex.vectorInfluence[influenceId];

		  // get the bone of the influence vertex
		  CalBone *pBone;
		  pBone = vectorBone[influence.boneId];

		  // transform vertex with current state of the bone
		  CalVector v(position);
		  v *= pBone->getTransformMatrix();
		  v += pBone->getTranslationBoneSpace();

		  x += influence.weight * v.x;
		  y += influence.weight * v.y;
		  z += influence.weight * v.z;
	  }
  }
  /*
  // save vertex position
  if(pSubmesh->getCoreSubmesh()->getSpringCount() > 0 && pSubmesh->hasInternalData())
  {
    // get the pgysical property of the vertex
    CalCoreSubmesh::PhysicalProperty& physicalProperty = vectorPhysicalProperty[vertexId];

    // assign new vertex position if there is no vertex weight
    if(physicalProperty.weight == 0.0f)
    {
      pVertexBuffer[0] = x;
      pVertexBuffer[1] = y;
      pVertexBuffer[2] = z;
    }
  }
  else
  {
    pVertexBuffer[0] = x;
    pVertexBuffer[1] = y;
    pVertexBuffer[2] = z;
  }
  */
  // return the vertex
  //return CalVector(x, y, z);
  return CalVector(x*m_axisFactorX,y*m_axisFactorY,z*m_axisFactorZ);
}
Exemple #21
0
void IKCharacter::solve( int iterations, int root_id, int leaf_id )
{
	while ( iterations>0 )
	{
		// start at leaf nodes
		deque<int> queue;
		
		// push leaf bones to target positions
		for ( int i=0; i<leaf_bones.size(); i++ )
		{
			// if we have a leaf id to use, skip all other leaves
			if ( leaf_id != -1 && leaf_id != leaf_bones[i] )
				continue;
			
			// if we have a target for this one
			if ( leaf_targets.find(leaf_bones[i]) != leaf_targets.end() )
			{
				// set it
				world_positions[leaf_bones[i]] = leaf_targets[leaf_bones[i]].second;
			}
			int parent_id = skeleton->getCoreSkeleton()->getCoreBone( leaf_bones[i] )->getParentId();
			if ( parent_id != -1 )
				queue.push_back( parent_id );
		}
		
		// queue to handle branching
		deque< int > branch_queue;
		while ( !queue.empty() || !branch_queue.empty() )
		{
			// if main queue is empty then we are ready to deal with branches
			if ( queue.empty() )
			{
				queue.push_back( branch_queue.front() );
				branch_queue.pop_front();
				continue;
			}
			
			int next_id = queue.front();
			queue.pop_front();
			// bail out if we should
			if ( root_id != -1 && next_id == root_id )
				continue;
			
			CalBone* bone = skeleton->getBone( next_id );
			list<int>& children = bone->getCoreBone()->getListChildId();
			// is this a branch?
			if ( children.size()>1 )
			{
				// still other children to process -- push to branch queue
				if ( !queue.empty() )
				{
					branch_queue.push_back( next_id );
					continue;
				}
				
				// otherwise, process branch here
				// if we're here, then all the children of this branch have been processed already
				int parent_id = bone->getCoreBone()->getParentId();
				if ( parent_id != -1 )
				{
					//printf("averaging %lu positions for %s wc %f: ", children.size(), bone->getCoreBone()->getName().c_str(), getWeightCentre( next_id ) );
					// fetch all child positions
					vector<CalVector> results;
					results.insert( results.begin(), children.size(), world_positions[next_id] );
					int count=0;
					for ( list<int>::iterator it = children.begin(); it != children.end(); ++it,++count ) 
					{
						
						// child_pos
						CalVector& b_c = world_positions[*it];
						// current pos
						CalVector& b_p = results[count];

						// now, the bone is the wrong length. correct its length to fulfil size constraint.
						CalVector delta = b_c - b_p;
						float length = delta.length();
						length = max( 0.00001f, length );
						// pointing from parent to child
						CalVector direction = delta/length;
						
						CalCoreBone* child_bone = skeleton->getCoreSkeleton()->getCoreBone( *it );
						CalVector rest_delta = bone->getCoreBone()->getTranslationAbsolute() - child_bone->getTranslationAbsolute();
						float desired_length = rest_delta.length();
						float delta_length = desired_length - length;
						
						// balance according to weight_centre
						float weight_centre = getWeightCentre(next_id);
						
						// move
						b_c += weight_centre * delta_length * direction;
						b_p -= (1.0f-weight_centre) * delta_length * direction;
						
						//printf("%s %f (%f %f %f), ", child_bone->getName().c_str(), delta_length, b_p.x, b_p.y, b_p.z );
						
					}
					//printf("\n");
					
					// now average
					CalVector average;
					for ( int i=0; i<results.size(); i++ )
					{
						average += results[i];
					}
					average /= results.size();

					// store
					world_positions[next_id] = average;
					
					// add parent
					queue.push_back( parent_id );
				}				
				
			}
			else
			{
				// children.size() is exactly 1
				assert( children.size()==1 );
				int child_id = children.front();
				
				// child_pos
				CalVector& b_c = world_positions[child_id];
				// current pos
				CalVector& b_p = world_positions[next_id];
				
				// now, the bone is the wrong length. correct its length to fulfil size constraint.
				float desired_length = getBoneLength(next_id);
				CalVector delta = b_c - b_p;
				float length = delta.length();
				length = max( 0.00001f, length );
				length = min( desired_length*1.5f, length );
				// pointing from parent to child
				CalVector direction = delta/length;
				
				float delta_length = desired_length - length;
				
				// balance according to weight_centre
				float weight_centre = getWeightCentre(next_id);
				
				// move
				b_c += weight_centre * delta_length * direction;
				b_p -= (1.0f-weight_centre) * delta_length * direction;
				
				
				// add parent
				int parent_id = bone->getCoreBone()->getParentId();
				if ( parent_id != -1 )
					queue.push_back( parent_id );
			}
		}	
		
		iterations--;
	}
	
	
}
Exemple #22
0
void CalMixer::updateSkeleton()
{
  // get the skeleton we need to update
  CalSkeleton *pSkeleton;
  pSkeleton = m_pModel->getSkeleton();
  if(pSkeleton == 0) return;

  // clear the skeleton state
  pSkeleton->clearState();

  // get the bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone();

  // loop through all animation actions
  std::list<CalAnimationAction *>::iterator iteratorAnimationAction;
  for(iteratorAnimationAction = m_listAnimationAction.begin(); iteratorAnimationAction != m_listAnimationAction.end(); ++iteratorAnimationAction)
  {
    // get the core animation instance
    CalCoreAnimation *pCoreAnimation;
    pCoreAnimation = (*iteratorAnimationAction)->getCoreAnimation();

    // Ask the animation for the pose at the given time
    std::vector<CalTransform> pose;
    pose.resize(pCoreAnimation->getTrackCount());
    pCoreAnimation->getPose((*iteratorAnimationAction)->getTime(), pose);

    // Blend the pose into the current bone states
    for (unsigned bone_id = 0; bone_id < pSkeleton->getCoreSkeleton()->getVectorCoreBone().size(); ++bone_id)
    {
      int track_number = pCoreAnimation->getTrackAssignment(bone_id);

      // Skip this bone if the bone does not have a track assigned in the animation
      if (track_number == -1)
      {
        continue;
      }

      // Blend the animation pose with the skeleton
      CalBone* pBone = vectorBone[bone_id];
      pBone->blendState((*iteratorAnimationAction)->getWeight(), pose[track_number].getTranslation(), pose[track_number].getRotation());
    }
  }

  // lock the skeleton state
  pSkeleton->lockState();

  // loop through all animation cycles
  std::list<CalAnimationCycle *>::iterator iteratorAnimationCycle;
  for(iteratorAnimationCycle = m_listAnimationCycle.begin(); iteratorAnimationCycle != m_listAnimationCycle.end(); ++iteratorAnimationCycle)
  {
    // get the core animation instance
    CalCoreAnimation *pCoreAnimation;
    pCoreAnimation = (*iteratorAnimationCycle)->getCoreAnimation();

    // calculate adjusted time
    float animationTime;
    if((*iteratorAnimationCycle)->getState() == CalAnimation::STATE_SYNC)
    {
      if(m_animationDuration == 0.0f)
      {
        animationTime = 0.0f;
      }
      else
      {
        animationTime = m_animationTime * pCoreAnimation->getDuration() / m_animationDuration;
      }
    }
    else
    {
      animationTime = (*iteratorAnimationCycle)->getTime();
    }

    // Ask the animation for the pose at the given time
    std::vector<CalTransform> pose;
    pose.resize(pCoreAnimation->getTrackCount());
    pCoreAnimation->getPose(animationTime, pose);

    // Blend the pose into the current bone states
    for (unsigned index = 0; index < pose.size(); ++index)
    {
      int track_number = pCoreAnimation->getTrackAssignment(index);

      // Skip this bone if the bone does not have a track assigned in the animation
      if (track_number == -1)
      {
        continue;
      }

      CalBone* pBone = vectorBone[index];
      pBone->blendState((*iteratorAnimationCycle)->getWeight(), pose[track_number].getTranslation(), pose[track_number].getRotation());
    }
  }

  // lock the skeleton state
  pSkeleton->lockState();

  // let the skeleton calculate its final state
  pSkeleton->calculateState();
}
Exemple #23
0
void CalMixer::updateSkeleton()
{

  // get the skeleton we need to update
  CalSkeleton *pSkeleton;
  pSkeleton = m_pModel->getSkeleton();
  if(pSkeleton == 0) return;

  // clear the skeleton state
  pSkeleton->clearState();

  // get the bone vector of the skeleton
  std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone();

  // The bone adjustments are "replace" so they have to go first, giving them
  // highest priority and full influence.  Subsequent animations affecting the same bones, 
  // including subsequent replace animations, will have their incluence attenuated appropriately.
  applyBoneAdjustments();

  // loop through all animation actions
  std::list<CalAnimationAction *>::iterator itaa;
  for( itaa = m_listAnimationAction.begin(); itaa != m_listAnimationAction.end(); itaa++ ) {

    // get the core animation instance
    CalAnimationAction * aa = * itaa;
    
    // Manual animations can be on or off.  If they are off, they do not apply
    // to the bone.
    if( aa->on() ) {

      CalCoreAnimation * pCoreAnimation = aa->getCoreAnimation();
      
      // get the list of core tracks of above core animation
      std::list<CalCoreTrack *>& listCoreTrack = pCoreAnimation->getListCoreTrack();
      
      // loop through all core tracks of the core animation
      std::list<CalCoreTrack *>::iterator itct;
      for( itct = listCoreTrack.begin(); itct != listCoreTrack.end(); itct++ ) {
        
        // get the appropriate bone of the track
        CalCoreTrack * ct = * itct;
        if( ct->getCoreBoneId() >= int(vectorBone.size()) ) {
          continue;
        }
        CalBone * pBone = vectorBone[ ct->getCoreBoneId() ];
        
        // get the current translation and rotation
        CalVector translation;
        CalQuaternion rotation;
        ct->getState( aa->getTime(), translation, rotation);
        
        // Replace and CrossFade both blend with the replace function.
        bool replace = aa->getCompositionFunction() != CalAnimation::CompositionFunctionAverage;
        float scale = aa->getScale();
        pBone->blendState( aa->getWeight(), translation, rotation, scale, replace, aa->getRampValue() );
      }
    }
  }

  // === What does lockState() mean?  Why do we need it at all?  It seems only to allow us
  // to blend all the animation actions together into a temporary sum, and then
  // blend all the animation cycles together into a different sum, and then blend
  // the two sums together according to their relative weight sums.  I believe this is mathematically
  // equivalent of blending all the animation actions and cycles together into a single sum,
  // according to their relative weights.
  pSkeleton->lockState();

  // let the skeleton calculate its final state
  pSkeleton->calculateState();
}
Exemple #24
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();
  }
}
void CCal3DSceneNode::render()
{
    if ( bInitialized )
    {
      irr::video::IVideoDriver* driver = SceneManager->getVideoDriver(); 


      driver->setTransform( irr::video::ETS_WORLD, AbsoluteTransformation ); 


      irr::video::S3DVertex tmp; 
      irr::scene::SMeshBuffer mb; 

      unsigned char meshColor[4]; // r g b a 


      // get the renderer of the model 
      CalRenderer* pCalRenderer; 
      pCalRenderer = m_calModel->getRenderer(); 
      pCalRenderer->setNormalization( true ); 

      if ( this->DebugDataVisible )
      {
        irr::video::SMaterial mat; 
        mat.Wireframe = false; 
        mat.Lighting = false; 
        driver->setMaterial( mat ); 
        driver->draw3DBox( Box ); 

        CalSkeleton* pCalSkeleton = m_calModel->getSkeleton(); 
        pCalSkeleton->calculateBoundingBoxes(); 
        std::vector<CalBone*>& vectorCoreBone = pCalSkeleton->getVectorBone(); 
        irr::core::aabbox3df b; 
        CalVector p[8]; 
        Vector3 v[8]; 


        for ( size_t boneId = 0; boneId < vectorCoreBone.size(); ++boneId )
        {
          CalBone* bone = vectorCoreBone[boneId]; 
          CalBoundingBox& calBoundingBox = bone->getBoundingBox(); 
          calBoundingBox.computePoints( p ); 

          for ( int i = 0; i < 8; ++i )
          {
            v[i].set( p[i].x, p[i].y, p[i].z );
          } 

          driver->setMaterial( mat ); 
          // draw the box 
          driver->draw3DLine( v[0], v[1], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[0], v[2], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[1], v[3], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[2], v[3], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[4], v[5], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[4], v[6], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[5], v[7], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[6], v[7], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[0], v[4], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[1], v[5], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[2], v[6], irr::video::SColor( 255, 0, 0, 255 ) ); 
          driver->draw3DLine( v[3], v[7], irr::video::SColor( 255, 0, 0, 255 ) ); 
          //printf("F: %f\n", v[0].X);
        }
      } 


      // begin the rendering loop 
      if ( pCalRenderer->beginRendering() )
      {
        // get the number of meshes 
        int meshCount; 
        meshCount = pCalRenderer->getMeshCount(); 

        // render all meshes of the model 
        int meshId; 
        for ( meshId = 0; meshId < meshCount; meshId++ )
        {
          // get the number of submeshes 
          int submeshCount; 
          submeshCount = pCalRenderer->getSubmeshCount( meshId ); 

          // render all submeshes of the mesh 
          int submeshId; 
          for ( submeshId = 0; submeshId < submeshCount; submeshId++ )
          {
            // select mesh and submesh for further data access 
            if ( pCalRenderer->selectMeshSubmesh( meshId, submeshId ) )
            {
              // set the material ambient color 
              pCalRenderer->getAmbientColor( &meshColor[0] ); 
              material.AmbientColor.set( meshColor[3], meshColor[0], meshColor[1], meshColor[2] ); 

              // set the material diffuse color 
              pCalRenderer->getDiffuseColor( &meshColor[0] ); 
              material.DiffuseColor.set( meshColor[3], meshColor[0], meshColor[1], meshColor[2] ); 

              // set the material specular color 
              pCalRenderer->getSpecularColor( &meshColor[0] ); 
              material.SpecularColor.set( meshColor[3], meshColor[0], meshColor[1], meshColor[2] ); 

              // set the material shininess factor 
              material.Shininess = pCalRenderer->getShininess(); 

              // get the transformed vertices of the submesh 
              static float meshVertices[3000][3]; 
              int vertexCount = 0; 
              // TODO:
              //if (KERNEL.GetTicks() % 3 == 0) //- make lod dependent?
              vertexCount = pCalRenderer->getVertices( &meshVertices[0][0] ); 

              // get the transformed normals of the submesh 
              static float meshNormals[3000][3]; 
              int normalsCount = 0;
              //    if (KERNEL.GetTicks() % 3 == 0)
              normalsCount = pCalRenderer->getNormals( &meshNormals[0][0] ); 

              // get the texture coordinates of the submesh 
              static float meshTextureCoordinates[3000][2]; 
              int textureCoordinateCount = 0; 
              textureCoordinateCount = pCalRenderer->getTextureCoordinates( 0, &meshTextureCoordinates[0][0] ); 

              // get the faces of the submesh 
              static CalIndex meshFaces[5000][3]; 
              int faceCount = 0;
              //if (KERNEL.GetTicks() % 12 == 0)
              faceCount = pCalRenderer->getFaces( &meshFaces[0][0] ); 

              if ( ( pCalRenderer->getMapCount() > 0 ) && ( textureCoordinateCount > 0 ) )
              {
                irr::video::ITexture* t = static_cast<irr::video::ITexture*>( pCalRenderer->getMapUserData( 0 ) ); 
                material.Texture1 = t;
              } 

              static S3DVertex vs[5000];
              for ( int i = 0; i < vertexCount; i++ )
              {
                vs[i].Pos.set( meshVertices[i][0], meshVertices[i][1], meshVertices[i][2] ); 
                vs[i].Normal.set( meshNormals[i][0], meshNormals[i][1], meshNormals[i][2] ); 
                vs[i].TCoords.set( meshTextureCoordinates[i][0], meshTextureCoordinates[i][1] ); 
                vs[i].Color = irr::video::SColor( 255, 255, 255, 255 );
              } 

              static u16 is[5000];
              for ( int i = 0; i < faceCount; i += 1 )
              {
                is[i * 3 + 0] = meshFaces[i][0]; 
                is[i * 3 + 1] = meshFaces[i][1]; 
                is[i * 3 + 2] = meshFaces[i][2];
              } 

              //mb.Vertices.clear(); 
              //mb.Vertices.reallocate(vertexCount);
              //for(int i=0;i<vertexCount;i++) 
              //{ 
              //    tmp.Pos.set(meshVertices[i][0],meshVertices[i][1],meshVertices[i][2]); 
              //    tmp.Normal.set(meshNormals[i][0],meshNormals[i][1],meshNormals[i][2]); 
              //    tmp.TCoords.set(meshTextureCoordinates[i][0],meshTextureCoordinates[i][1]); 
              //    tmp.Color=irr::video::SColor(255,255,255,255); 
              //    mb.Vertices.push_back(tmp); 
              //} 

              //mb.Indices.clear(); 
              //mb.Indices.reallocate(faceCount);
              //for(int i=0; i<faceCount; ++i)
              //{ 
              //    mb.Indices.push_back(meshFaces[i][0]); 
              //    mb.Indices.push_back(meshFaces[i][1]); 
              //    mb.Indices.push_back(meshFaces[i][2]); 
              //} 

              // draw 

              driver->setMaterial( material ); 
              //driver->drawIndexedTriangleList(mb.Vertices.const_pointer(),mb.Vertices.size(),mb.Indices.const_pointer(),faceCount); 
              driver->drawIndexedTriangleList( vs, vertexCount, is, faceCount ); 
              //driver->drawMeshBuffer(&mb); 

              //CONSOLE.addx("#Verts %d #Norm %d #Tex %d #Faces %d #Map %d", 
              //       vertexCount,normalsCount,textureCoordinateCount,faceCount, pCalRenderer->getMapCount()); 
            }
          }
        } 

        // end the rendering 
        pCalRenderer->endRendering();
      }
    }
} 
Exemple #26
0
void IKCharacter::draw( int bone_id, float scale, bool additional_drawing )
{
	CalBone* bone = skeleton->getBone( bone_id );
	int parent_id = bone->getCoreBone()->getParentId();
	if ( parent_id != -1 )
	{
		// current
		CalBone* parent = skeleton->getBone( parent_id );
		glBegin( GL_LINES );
		CalVector v = parent->getTranslationAbsolute();
		v*=scale;
		CalVector c = v;
		glVertex3f( v.x, v.y, v.z );
		v = bone->getTranslationAbsolute();
		v*=scale;
		c += v;
		c /= 2.0f;
		glVertex3f( v.x, v.y, v.z );
		glEnd();

		// world
		glPushAttrib( GL_CURRENT_BIT );
		glColor3f( 0.1f, 0.8f, 0.1f );
		glBegin( GL_LINES );
		v = world_positions[parent_id];
		v*=scale;
		glVertex3f( v.x, v.y, v.z );
		v = world_positions[bone_id];
		v*=scale;
		glVertex3f( v.x, v.y, v.z );
		glEnd();
		glPopAttrib();


		if ( additional_drawing )
		{
			glPushAttrib( GL_CURRENT_BIT );
			glBegin( GL_LINES );
			// core
			glColor3f( (parent_id==debug_bone)?1.0f:0.3f, 0.3f, 0.5f );
			v = parent->getCoreBone()->getTranslationAbsolute();
			v*=scale;
			glVertex3f( v.x, v.y, v.z );
			v = bone->getCoreBone()->getTranslationAbsolute();
			v*=scale;
			glVertex3f( v.x, v.y, v.z );
			glEnd();
			

			// draw rotation
			glPushMatrix();
			CalVector root = bone->getCoreBone()->getTranslationAbsolute();
			glTranslatef( root.x, root.y, root.z );
			CalVector rot;
			
			rot.set( 0, 0.1f*scale, 0 );
			rot *= bone->getCoreBone()->getRotationAbsolute();
			ofEnableAlphaBlending();
			glColor4f( 0.2f, 0.2f, 0.8f, 0.2f );
			glBegin( GL_TRIANGLES );
			//glVertex3f( 0,0,0 );
			glVertex3f( rot.x, rot.y, rot.z );
			rot *= debug_cached_rotations[bone_id];
			glVertex3f( rot.x, rot.y, rot.z );
			glEnd();
			
			glColor4f( 0.2f, 0.2f, 0.8f, 0.8f );
			rot.set( 0, 0.1f*scale, 0 );
			rot *= bone->getCoreBone()->getRotationAbsolute();
			glBegin( GL_LINES );
			glVertex3f( 0,0,0 );
			glVertex3f( rot.x, rot.y, rot.z );
			rot *= debug_cached_rotations[bone_id];
			glVertex3f( 0,0,0 );
			glVertex3f( rot.x, rot.y, rot.z );
			glEnd();
			
			ofDisableAlphaBlending();
			
			glPopMatrix();
			
			CalVector u( 0, 0.1f*scale, 0);
			u *= bone->getRotationAbsolute();
			CalVector r( 0.1f*scale, 0, 0 );
			r *= bone->getRotationAbsolute();
			CalVector f( 0, 0, 0.1f*scale );
			f *= bone->getRotationAbsolute();
			
			
			// right blue
			glPushMatrix();
			root = bone->getTranslationAbsolute();
			glTranslatef( root.x, root.y, root.z );
			glBegin( GL_LINES );
			glColor3f( 0, 0, 1 );
			glVertex3f( 0,0,0 );
			glVertex3f( r.x, r.y, r.z );
			// up red
			glColor3f( 1, 0, 0 );
			glVertex3f( 0,0,0 );
			glVertex3f( u.x, u.y, u.z );
			// forward green
			glColor3f( 0, 1, 0 );
			glVertex3f( 0,0,0 );
			glVertex3f( f.x, f.y, f.z );
			glEnd();
			glPopMatrix();

			// right blue
			glPushMatrix();
			root = world_positions[bone_id];
			glTranslatef( root.x, root.y, root.z );
			glBegin( GL_LINES );
			glColor3f( 0, 0, 1 );
			glVertex3f( 0,0,0 );
			glVertex3f( r.x, r.y, r.z );
			// up red
			glColor3f( 1, 0, 0 );
			glVertex3f( 0,0,0 );
			glVertex3f( u.x, u.y, u.z );
			// forward green
			glColor3f( 0, 1, 0 );
			glVertex3f( 0,0,0 );
			glVertex3f( f.x, f.y, f.z );
			glEnd();
			glPopMatrix();
			
			glPopAttrib();
		}
		
	}
	
	
	list<int> children = bone->getCoreBone()->getListChildId();
	for ( list<int>::iterator it = children.begin(); 
		 it != children.end();
		 ++it )
	{
		draw( *it, scale, additional_drawing );
	}
	
	
}