示例#1
0
        // ------------------------------------------------------------------------------------
        /// <summary>
        /// Solve feet positions.
        /// </summary>
        /// <param name="enabled">Feet resolving is enabled - this is a parameter because of blending over time.</param>
        /// <param name="characterBones">Character bones storage.</param>
        /// <param name="allowMovingWithBody">If feet cannot reach, move the body</param>
        public void SolveFeet(bool enabled, MyCharacterBone[] characterBones, bool allowMovingWithBody)
        {
            m_currentFeetIkInfluence = MathHelper.Clamp(m_currentFeetIkInfluence + (enabled ? 0.1f : -0.1f), 0.0f, 1.0f);
            if (m_currentFeetIkInfluence <= 0 || TerrainHeightProvider == null || characterBones == null || characterBones.Length == 0 || m_feet.Count == 0)
            {
                return;
            }
            RecreateIgnoredBonesTableIfNeeded(characterBones);
            BackupIgnoredBones(characterBones);

            if (allowMovingWithBody)
            {
                MoveTheBodyDown(characterBones);  // move the body down!
            }

            RestoreIgnoredBones(characterBones);

            float refTerrainHeight           = TerrainHeightProvider.GetReferenceTerrainHeight();
            float maximumNegativeOffsetValue = m_characterDirDownOffsetMax;
            bool  foundAnyOffset             = false;

            foreach (var foot in m_feet)
            {
                if (foot.BoneIndex == -1)
                {
                    foreach (var bone in characterBones)
                    {
                        if (bone.Name == foot.BoneName)
                        {
                            foot.BoneIndex = bone.Index;
                            break;
                        }
                    }

                    if (foot.BoneIndex == -1) // alright alright, skip this bone
                    {
                        continue;
                    }
                }
                var footBone   = characterBones[foot.BoneIndex];
                var firstBone  = footBone;
                var secondBone = footBone;
                for (int i = 0; i < foot.ChainLength; i++)
                {
                    secondBone = firstBone;
                    firstBone  = firstBone.Parent;
                }
                firstBone.ComputeAbsoluteTransform(); // will propagate the transform to children

                // obtain terrain height
                Vector3 bonePos = footBone.AbsoluteTransform.Translation;
                float   terrainHeight;
                Vector3 terrainNormal;
                if (TerrainHeightProvider.GetTerrainHeight(bonePos, out terrainHeight, out terrainNormal))
                {
                    terrainNormal = Vector3.Lerp(foot.LastTerrainNormal, terrainNormal, 0.2f);
                }
                else
                {
                    terrainHeight           = foot.LastTerrainHeight;
                    terrainNormal           = Vector3.Lerp(foot.LastTerrainNormal, Vector3.Up, 0.1f);
                    foot.LastTerrainHeight *= 0.9f;
                }
                foot.LastTerrainHeight = terrainHeight;
                foot.LastTerrainNormal = terrainNormal;
                float terrainHeightDelta = terrainHeight - refTerrainHeight;

                // compute IK!
                {
                    float originalBoneY     = bonePos.Y;
                    float unclampedNewBoneY = terrainHeightDelta + (bonePos.Y - m_filteredOffsetValue) / terrainNormal.Y;                       // we expect the normal to be normalized
                    bonePos.Y = Math.Min(secondBone.AbsoluteTransform.Translation.Y, unclampedNewBoneY);                                        // do not allow the feet to be above ankle
                    bonePos.Y = MathHelper.Lerp(originalBoneY, bonePos.Y, m_currentFeetIkInfluence);
                    maximumNegativeOffsetValue = MathHelper.Clamp(terrainHeightDelta, m_characterDirDownOffsetMin, maximumNegativeOffsetValue); // store worst negative offset
                    foundAnyOffset             = true;

                    if (originalBoneY > bonePos.Y)
                    {
                        bonePos.Y = originalBoneY;
                    }

                    SolveIkTwoBones(characterBones, foot, ref bonePos, ref terrainNormal, fromBindPose: false);
                }
            }

            if (!foundAnyOffset)
            {
                maximumNegativeOffsetValue = 0;
            }

            m_characterDirDownOffset = MathHelper.Lerp(maximumNegativeOffsetValue, m_characterDirDownOffset, m_characterDirDownOffsetSmoothness * m_offsetFiltering.Count / m_offsetFilteringSampleCount);
        }
示例#2
0
 public ResourceCeilingProvider(TerrainHeightProvider terrainHeightProvider)
 {
     m_terrainHeightProvider = terrainHeightProvider;
 }