示例#1
0
        private void SetupParticles()
        {
            if (rootBoneTransform == null)
            {
                return;
            }

            particleCount = 0;
            HeadInfo      = new HeadInfo
            {
                ObjectPrevPosition = rootBoneTransform.position,
                ObjectScale        = math.abs(rootBoneTransform.lossyScale.x),
                Gravity            = gravity,
                Weight             = weight,
                Force         = force,
                ParticleCount = 0,
            };

            particleCount   = 0;
            boneTotalLength = 0;
            AppendParticles(rootBoneTransform, -1, 0, in HeadInfo);
            UpdateParameters();

            HeadInfo.ParticleCount = particleCount;
        }
示例#2
0
        /// <summary>
        /// 当目标骨骼需要移除的时候使用,目前还不完善,先不要使用
        /// </summary>
        /// <param name="target">要移除的目标骨骼</param>
        public void RemoveBone(DynamicBone target)
        {
            int index = boneList.IndexOf(target);

            if (index == -1)
            {
                return;
            }

            //TODO:移除骨骼的逻辑
            boneList.RemoveAt(index);
            int curHeadIndex = target.HeadInfo.Index;

            //移除Bone的相关Collider的关系
            boneColliderMatchMap.Remove(curHeadIndex);

            //是否是队列中末尾对象
            bool isEndTarget = curHeadIndex == headInfoList.Length - 1;

            if (isEndTarget)
            {
                headInfoList.RemoveAtSwapBack(curHeadIndex);
                headTransformAccessArray.RemoveAtSwapBack(curHeadIndex);
                for (int i = MaxParticleLimit - 1; i >= 0; i--)
                {
                    int dataOffset = curHeadIndex * MaxParticleLimit + i;
                    particleInfoList.RemoveAtSwapBack(dataOffset);
                    particleTransformAccessArray.RemoveAtSwapBack(dataOffset);
                }
            }
            else
            {
                //将最末列的HeadInfo 索引设置为当前将要移除的HeadInfo 索引
                DynamicBone lastTarget   = boneList[boneList.Count - 1];
                HeadInfo    lastHeadInfo = lastTarget.ResetHeadIndexAndDataOffset(curHeadIndex);
                headInfoList.RemoveAtSwapBack(curHeadIndex);
                headInfoList[curHeadIndex] = lastHeadInfo;
                headTransformAccessArray.RemoveAtSwapBack(curHeadIndex);
                for (int i = MaxParticleLimit - 1; i >= 0; i--)
                {
                    int dataOffset = curHeadIndex * MaxParticleLimit + i;
                    particleInfoList.RemoveAtSwapBack(dataOffset);
                    particleTransformAccessArray.RemoveAtSwapBack(dataOffset);
                }
            }
            target.ClearJobData();
        }
示例#3
0
            public void Execute(int index, TransformAccess transform)
            {
                HeadInfo curHeadInfo = HeadArray[index];

                curHeadInfo.RootParentBoneWorldPosition = transform.position;
                curHeadInfo.RootParentBoneWorldRotation = transform.rotation;

                curHeadInfo.ObjectMove = transform.position - (Vector3)curHeadInfo.ObjectPrevPosition;

                curHeadInfo.ObjectPrevPosition = transform.position;
                float3 force    = curHeadInfo.Gravity;
                float3 forceDir = math.normalizesafe(force);
                float3 pf       = forceDir * math.max(math.dot(force, forceDir),
                                                      0); // project current gravity to rest gravity

                force -= pf;                              // remove projected gravity
                force  = (force + curHeadInfo.Force) * curHeadInfo.ObjectScale;
                curHeadInfo.FinalForce = force;

                HeadArray[index] = curHeadInfo;
            }
示例#4
0
            public void Execute(int index)
            {
                int      headIndex   = index / MaxParticleLimit;
                HeadInfo curHeadInfo = HeadArray[headIndex];

                int offset = index % MaxParticleLimit;

                //每个Head及其Particle只需要计算一次就够了!
                if (offset == 0)
                {
                    float3     parentPosition = curHeadInfo.RootParentBoneWorldPosition;
                    quaternion parentRotation = curHeadInfo.RootParentBoneWorldRotation;

                    for (int j = 0; j < curHeadInfo.ParticleCount; j++)
                    {
                        int          pIdx = curHeadInfo.DataOffsetInGlobalArray + j;
                        ParticleInfo p    = ParticleArray[pIdx];



                        float3     localPosition = p.LocalPosition * p.ParentScale;
                        quaternion localRotation = p.LocalRotation;
                        float3     worldPosition =
                            Util.LocalToWorldPosition(parentPosition, parentRotation, localPosition);
                        quaternion worldRotation =
                            Util.LocalToWorldRotation(parentRotation, localRotation);



                        parentPosition = p.WorldPosition = worldPosition;
                        parentRotation = p.WorldRotation = worldRotation;

                        ParticleArray[pIdx] = p;
                    }
                }

                //如果遍历到空的部分就直接跳过就好了
                if (offset >= curHeadInfo.ParticleCount)
                {
                    return;
                }

                int          particleId = curHeadInfo.DataOffsetInGlobalArray + offset;
                ParticleInfo particle   = ParticleArray[particleId];


                if (particle.ParentIndex >= 0)
                {
                    float3 v     = particle.TempWorldPosition - particle.TempPrevWorldPosition;
                    float3 rMove = curHeadInfo.ObjectMove * particle.Inert;
                    particle.TempPrevWorldPosition = particle.TempWorldPosition + rMove;

                    float damping = particle.Damping;
                    if (particle.IsCollide)
                    {
                        damping += particle.Friction;
                        if (damping > 1)
                        {
                            damping = 1;
                        }
                        particle.IsCollide = false;
                    }

                    particle.TempWorldPosition += v * (1 - damping) + curHeadInfo.FinalForce + rMove;
                }
                else
                {
                    particle.TempPrevWorldPosition = particle.TempWorldPosition;
                    particle.TempWorldPosition     = particle.WorldPosition;
                }

                ParticleArray[particleId] = particle;
            }
示例#5
0
            public void Execute(int index)
            {
                //避免IndexOutOfRangeException:Index {0} is out of restricted IJobParallelFor range [{1}...{2] in ReadWriteBuffer.
                if (index % MaxParticleLimit == 0)
                {
                    return;
                }

                int      headIndex   = index / MaxParticleLimit;
                HeadInfo curHeadInfo = HeadArray[headIndex];

                //遍历到那些空的Particle就不用再计算了
                int offset = index % MaxParticleLimit;

                if (offset >= curHeadInfo.ParticleCount)
                {
                    return;
                }

                int          particleId   = curHeadInfo.DataOffsetInGlobalArray + offset;
                ParticleInfo particleInfo = ParticleArray[particleId];

                int          parentParticleIndex = curHeadInfo.DataOffsetInGlobalArray + particleInfo.ParentIndex;
                ParticleInfo parentParticleInfo  = ParticleArray[parentParticleIndex];

                float3 pos       = particleInfo.WorldPosition;
                float3 parentPos = parentParticleInfo.WorldPosition;


                //TODO:尾节点的长度计算方法需要用math修改
                Matrix4x4 m = float4x4.TRS(parentParticleInfo.TempWorldPosition, parentParticleInfo.WorldRotation,
                                           particleInfo.ParentScale);

                float restLen = !particleInfo.IsEndBone
                    ? math.distance(parentPos, pos)
                    : m.MultiplyVector(particleInfo.EndOffset).magnitude;


                float stiffness = math.lerp(1.0f, particleInfo.Stiffness, curHeadInfo.Weight);

                if (stiffness > 0 || particleInfo.Elasticity > 0)
                {
                    float4x4 em0 = float4x4.TRS(parentParticleInfo.TempWorldPosition, parentParticleInfo.WorldRotation,
                                                particleInfo.ParentScale);
                    float3 restPos = math.mul(em0, new float4(particleInfo.LocalPosition.xyz, 1)).xyz;

                    float3 d = restPos - particleInfo.TempWorldPosition;
                    particleInfo.TempWorldPosition += d * particleInfo.Elasticity;

                    if (stiffness > 0)
                    {
                        d = restPos - particleInfo.TempWorldPosition;
                        float len    = math.length(d);
                        float maxLen = restLen * (1 - stiffness) * 2;
                        if (len > maxLen)
                        {
                            particleInfo.TempWorldPosition += d * ((len - maxLen) / len);
                        }
                    }
                }

                // //与指定的非全局碰撞器进行计算,会过滤掉挂载的全局碰撞器防止重复计算
                // NativeMultiHashMap<int, int>.Enumerator enumerator = BoneColliderMatchMap.GetValuesForKey(headIndex);
                // while (enumerator.MoveNext())
                // {
                //     if (ColliderArray[enumerator.Current].IsGlobal) continue;
                //     particleInfo.IsCollide =
                //         DynamicBoneCollider.HandleCollision(ColliderArray[enumerator.Current],
                //             ref particleInfo.TempWorldPosition,
                //             in particleInfo.Radius);
                // }
                //
                // //与所有的全局碰撞器进行计算
                // for (int i = 0; i < ColliderArray.Length; i++)
                // {
                //     if (!ColliderArray[i].IsGlobal) continue;
                //     particleInfo.IsCollide =
                //         DynamicBoneCollider.HandleCollision(ColliderArray[i],
                //             ref particleInfo.TempWorldPosition,
                //             in particleInfo.Radius);
                // }


                // particleInfo.WorldPosition = particleInfo.TempWorldPosition;

                float3 dd   = parentParticleInfo.TempWorldPosition - particleInfo.TempWorldPosition;
                float  leng = math.length(dd);

                if (leng > 0)
                {
                    particleInfo.TempWorldPosition += dd * ((leng - restLen) / leng);
                }


                ParticleArray[particleId] = particleInfo;
            }