//-------------------------------------------------------------------------------------- // Name: GetBoneTransform() // Desc: Get final transform for a bone //-------------------------------------------------------------------------------------- void CSample::GetBoneTransform( Adreno::Model* pModel, Adreno::Animation* pAnim, INT32 boneIndex, INT32 frameIndex, Adreno::Transform& transform ) { Adreno::Joint* pJoint = m_pModel->Joints + boneIndex; Adreno::AnimationTrack* pTrack = m_pAnim->Tracks + boneIndex; if ( frameIndex >= 0 && frameIndex < pTrack->NumKeyframes ) { transform = *( pTrack->Keyframes + frameIndex ); } else { transform = pJoint->Transform; } if (pJoint->ParentIndex != -1) { Adreno::Transform parentTransform; GetBoneTransform( pModel, pAnim, pJoint->ParentIndex, frameIndex, parentTransform ); FRMMATRIX4X4 parentRotation = FrmMatrixRotate( parentTransform.Rotation ); transform.Position = FrmVector3TransformCoord( transform.Position, parentRotation ); transform.Rotation = FrmQuaternionMultiply( transform.Rotation, parentTransform.Rotation ); transform.Position += parentTransform.Position; } }
FMatrix USkeletalMeshComponent::GetTransformMatrix() const { FTransform RootTransform = GetBoneTransform(0); FVector Translation; FQuat Rotation; // if in editor, it should always use localToWorld // if root motion is ignored, use root transform if( GetWorld()->IsGameWorld() || !SkeletalMesh ) { // add root translation info Translation = RootTransform.GetLocation(); } else { Translation = ComponentToWorld.TransformPosition(SkeletalMesh->RefSkeleton.GetRefBonePose()[0].GetTranslation()); } // if root rotation is ignored, use root transform rotation Rotation = RootTransform.GetRotation(); // now I need to get scale // only LocalToWorld will have scale FVector ScaleVector = ComponentToWorld.GetScale3D(); Rotation.Normalize(); return FScaleMatrix(ScaleVector)*FQuatRotationTranslationMatrix(Rotation, Translation); }
//-------------------------------------------------------------------------------------- // Name: SetupBoneTransform() // Desc: Pre-process all bone transforms and flatten the bones hierarchy //-------------------------------------------------------------------------------------- BOOL CSample::SetupBoneTransform( Adreno::Model* pModel, Adreno::Animation* pAnim ) { // If there is a mismatch, return false if ( pModel->NumJoints != pAnim->NumTracks ) { return FALSE; } // Process each of the bones for ( INT32 boneIndex = 0; boneIndex < pModel->NumJoints; ++boneIndex ) { Adreno::AnimationTrack* pTrack = m_pAnim->Tracks + boneIndex; // If there are frames, process them, in addition to the default transform if ( pTrack->NumKeyframes > 0 ) { Adreno::Transform transform; // For each frame, calculate and save the final transform for the bone for ( INT32 frameIndex = 0; frameIndex < pAnim->NumFrames; ++frameIndex ) { GetBoneTransform( pModel, pAnim, boneIndex, frameIndex, transform ); pTrack->Keyframes[frameIndex] = transform; } // Do the same for the default transform GetBoneTransform( pModel, pAnim, boneIndex, -1, transform ); pModel->Joints[boneIndex].Transform = transform; } else { // Calculate and save the final default transform Adreno::Transform transform; GetBoneTransform( pModel, pAnim, boneIndex, -1, transform ); pModel->Joints[boneIndex].Transform = transform; } // Flatten the bone hierarchy pModel->Joints[boneIndex].ParentIndex = -1; } return TRUE; }
//========================================================= //========================================================= void CAnimating::GetBonePosition ( int iBone, Vector &origin, QAngle &angles ) { CStudioHdr *pStudioHdr = GetModelPtr( ); if (!pStudioHdr) { Assert(!"CBaseAnimating::GetBonePosition: model missing"); return; } if (iBone < 0 || iBone >= pStudioHdr->numbones()) { Assert(!"CBaseAnimating::GetBonePosition: invalid bone index"); return; } matrix3x4_t bonetoworld; GetBoneTransform( iBone, bonetoworld ); MatrixAngles( bonetoworld, angles, origin ); }
void UPhATEdSkeletalMeshComponent::RenderAssetTools(const FSceneView* View, class FPrimitiveDrawInterface* PDI, bool bHitTest) { check(SharedData); UPhysicsAsset* const PhysicsAsset = GetPhysicsAsset(); check(PhysicsAsset); bool bHitTestAndBodyMode = bHitTest && SharedData->EditingMode == FPhATSharedData::PEM_BodyEdit; bool bHitTestAndConstraintMode = bHitTest && SharedData->EditingMode == FPhATSharedData::PEM_ConstraintEdit; FPhATSharedData::EPhATRenderMode CollisionViewMode = SharedData->GetCurrentCollisionViewMode(); #if DEBUG_CLICK_VIEWPORT PDI->DrawLine(SharedData->LastClickOrigin, SharedData->LastClickOrigin + SharedData->LastClickDirection * 5000.0f, FLinearColor(1, 1, 0, 1), SDPG_Foreground); PDI->DrawPoint(SharedData->LastClickOrigin, FLinearColor(1, 0, 0), 5, SDPG_Foreground); #endif // Draw bodies for (int32 i = 0; i <PhysicsAsset->BodySetup.Num(); ++i) { int32 BoneIndex = GetBoneIndex(PhysicsAsset->BodySetup[i]->BoneName); // If we found a bone for it, draw the collision. // The logic is as follows; always render in the ViewMode requested when not in hit mode - but if we are in hit mode and the right editing mode, render as solid if (BoneIndex != INDEX_NONE) { FTransform BoneTM = GetBoneTransform(BoneIndex); float Scale = BoneTM.GetScale3D().GetAbsMax(); FVector VectorScale(Scale); BoneTM.RemoveScaling(); FKAggregateGeom* AggGeom = &PhysicsAsset->BodySetup[i]->AggGeom; for (int32 j = 0; j <AggGeom->SphereElems.Num(); ++j) { if (bHitTest) { PDI->SetHitProxy(new HPhATEdBoneProxy(i, KPT_Sphere, j)); } FTransform ElemTM = GetPrimitiveTransform(BoneTM, i, KPT_Sphere, j, Scale); //solids are drawn if it's the ViewMode and we're not doing a hit, or if it's hitAndBodyMode if( (CollisionViewMode == FPhATSharedData::PRM_Solid && !bHitTest) || bHitTestAndBodyMode) { UMaterialInterface* PrimMaterial = GetPrimitiveMaterial(i, KPT_Sphere, j, bHitTestAndBodyMode); AggGeom->SphereElems[j].DrawElemSolid(PDI, ElemTM, VectorScale, PrimMaterial->GetRenderProxy(0)); } //wires are never used during hit if(!bHitTest) { if (CollisionViewMode == FPhATSharedData::PRM_Solid || CollisionViewMode == FPhATSharedData::PRM_Wireframe) { AggGeom->SphereElems[j].DrawElemWire(PDI, ElemTM, VectorScale, GetPrimitiveColor(i, KPT_Sphere, j)); } } if (bHitTest) { PDI->SetHitProxy(NULL); } } for (int32 j = 0; j <AggGeom->BoxElems.Num(); ++j) { if (bHitTest) { PDI->SetHitProxy(new HPhATEdBoneProxy(i, KPT_Box, j)); } FTransform ElemTM = GetPrimitiveTransform(BoneTM, i, KPT_Box, j, Scale); if ( (CollisionViewMode == FPhATSharedData::PRM_Solid && !bHitTest) || bHitTestAndBodyMode) { UMaterialInterface* PrimMaterial = GetPrimitiveMaterial(i, KPT_Box, j, bHitTestAndBodyMode); AggGeom->BoxElems[j].DrawElemSolid(PDI, ElemTM, VectorScale, PrimMaterial->GetRenderProxy(0)); } if(!bHitTest) { if (CollisionViewMode == FPhATSharedData::PRM_Solid || CollisionViewMode == FPhATSharedData::PRM_Wireframe) { AggGeom->BoxElems[j].DrawElemWire(PDI, ElemTM, VectorScale, GetPrimitiveColor(i, KPT_Box, j)); } } if (bHitTest) { PDI->SetHitProxy(NULL); } } for (int32 j = 0; j <AggGeom->SphylElems.Num(); ++j) { if (bHitTest) { PDI->SetHitProxy(new HPhATEdBoneProxy(i, KPT_Sphyl, j)); } FTransform ElemTM = GetPrimitiveTransform(BoneTM, i, KPT_Sphyl, j, Scale); if ( (CollisionViewMode == FPhATSharedData::PRM_Solid && !bHitTest) || bHitTestAndBodyMode) { UMaterialInterface* PrimMaterial = GetPrimitiveMaterial(i, KPT_Sphyl, j, bHitTestAndBodyMode); AggGeom->SphylElems[j].DrawElemSolid(PDI, ElemTM, VectorScale, PrimMaterial->GetRenderProxy(0)); } if(!bHitTest) { if (CollisionViewMode == FPhATSharedData::PRM_Solid || CollisionViewMode == FPhATSharedData::PRM_Wireframe) { AggGeom->SphylElems[j].DrawElemWire(PDI, ElemTM, VectorScale, GetPrimitiveColor(i, KPT_Sphyl, j)); } } if (bHitTest) { PDI->SetHitProxy(NULL); } } for (int32 j = 0; j <AggGeom->ConvexElems.Num(); ++j) { if (bHitTest) { PDI->SetHitProxy(new HPhATEdBoneProxy(i, KPT_Convex, j)); } FTransform ElemTM = GetPrimitiveTransform(BoneTM, i, KPT_Convex, j, Scale); //convex doesn't have solid draw so render lines if we're in hitTestAndBodyMode if(!bHitTest || bHitTestAndBodyMode) { if (CollisionViewMode == FPhATSharedData::PRM_Solid || CollisionViewMode == FPhATSharedData::PRM_Wireframe) { AggGeom->ConvexElems[j].DrawElemWire(PDI, ElemTM, Scale, GetPrimitiveColor(i, KPT_Convex, j)); } } if (bHitTest) { PDI->SetHitProxy(NULL); } } if (!bHitTest && SharedData->bShowCOM && Bodies.IsValidIndex(i)) { Bodies[i]->DrawCOMPosition(PDI, COMRenderSize, SharedData->COMRenderColor); } } } // Draw Constraints FPhATSharedData::EPhATConstraintViewMode ConstraintViewMode = SharedData->GetCurrentConstraintViewMode(); if (ConstraintViewMode != FPhATSharedData::PCV_None) { for (int32 i = 0; i <PhysicsAsset->ConstraintSetup.Num(); ++i) { int32 BoneIndex1 = GetBoneIndex(PhysicsAsset->ConstraintSetup[i]->DefaultInstance.ConstraintBone1); int32 BoneIndex2 = GetBoneIndex(PhysicsAsset->ConstraintSetup[i]->DefaultInstance.ConstraintBone2); // if bone doesn't exist, do not draw it. It crashes in random points when we try to manipulate. if (BoneIndex1 != INDEX_NONE && BoneIndex2 != INDEX_NONE) { if (bHitTest) { PDI->SetHitProxy(new HPhATEdConstraintProxy(i)); } if(bHitTestAndConstraintMode || !bHitTest) { DrawConstraint(i, View, PDI, SharedData->EditorSimOptions->bShowConstraintsAsPoints); } if (bHitTest) { PDI->SetHitProxy(NULL); } } } } if (!bHitTest && SharedData->EditingMode == FPhATSharedData::PEM_BodyEdit && SharedData->bShowInfluences) { DrawCurrentInfluences(PDI); } // If desired, draw bone hierarchy. if (!bHitTest && SharedData->bShowHierarchy) { DrawHierarchy(PDI, false); } // If desired, draw animation skeleton. if (!bHitTest && SharedData->bShowAnimSkel) { DrawHierarchy(PDI, SharedData->bRunningSimulation); } }