示例#1
0
        public void quaternion_euler()
        {
            float3     test_angles = TestMatrix.test_angles;
            quaternion q0          = quaternion.Euler(test_angles);
            quaternion q0_xyz      = quaternion.Euler(test_angles, RotationOrder.XYZ);
            quaternion q0_xzy      = quaternion.Euler(test_angles, RotationOrder.XZY);
            quaternion q0_yxz      = quaternion.Euler(test_angles, RotationOrder.YXZ);
            quaternion q0_yzx      = quaternion.Euler(test_angles, RotationOrder.YZX);
            quaternion q0_zxy      = quaternion.Euler(test_angles, RotationOrder.ZXY);
            quaternion q0_zyx      = quaternion.Euler(test_angles, RotationOrder.ZYX);

            quaternion q1     = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z);
            quaternion q1_xyz = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.XYZ);
            quaternion q1_xzy = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.XZY);
            quaternion q1_yxz = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.YXZ);
            quaternion q1_yzx = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.YZX);
            quaternion q1_zxy = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.ZXY);
            quaternion q1_zyx = quaternion.Euler(test_angles.x, test_angles.y, test_angles.z, RotationOrder.ZYX);

            float epsilon = 0.0001f;

            TestUtils.AreEqual(q0, quaternion(-0.3133549f, 0.3435619f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q0_xyz, quaternion(-0.4597331f, 0.06979711f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q0_xzy, quaternion(-0.3133549f, 0.06979711f, 0.3899215f, 0.8630749f), epsilon);
            TestUtils.AreEqual(q0_yxz, quaternion(-0.4597331f, 0.06979711f, 0.1971690f, 0.8630748f), epsilon);
            TestUtils.AreEqual(q0_yzx, quaternion(-0.4597331f, 0.34356190f, 0.1971690f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q0_zxy, quaternion(-0.3133549f, 0.34356190f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q0_zyx, quaternion(-0.3133549f, 0.34356190f, 0.1971690f, 0.8630749f), epsilon);

            TestUtils.AreEqual(q1, quaternion(-0.3133549f, 0.3435619f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q1_xyz, quaternion(-0.4597331f, 0.06979711f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q1_xzy, quaternion(-0.3133549f, 0.06979711f, 0.3899215f, 0.8630749f), epsilon);
            TestUtils.AreEqual(q1_yxz, quaternion(-0.4597331f, 0.06979711f, 0.1971690f, 0.8630748f), epsilon);
            TestUtils.AreEqual(q1_yzx, quaternion(-0.4597331f, 0.34356190f, 0.1971690f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q1_zxy, quaternion(-0.3133549f, 0.34356190f, 0.3899215f, 0.7948176f), epsilon);
            TestUtils.AreEqual(q1_zyx, quaternion(-0.3133549f, 0.34356190f, 0.1971690f, 0.8630749f), epsilon);

            float3x3 m0     = float3x3(q0);
            float3x3 m0_xyz = float3x3(q0_xyz);
            float3x3 m0_xzy = float3x3(q0_xzy);
            float3x3 m0_yxz = float3x3(q0_yxz);
            float3x3 m0_yzx = float3x3(q0_yzx);
            float3x3 m0_zxy = float3x3(q0_zxy);
            float3x3 m0_zyx = float3x3(q0_zyx);

            float3x3 m1     = float3x3(q1);
            float3x3 m1_xyz = float3x3(q1_xyz);
            float3x3 m1_xzy = float3x3(q1_xzy);
            float3x3 m1_yxz = float3x3(q1_yxz);
            float3x3 m1_yzx = float3x3(q1_yzx);
            float3x3 m1_zxy = float3x3(q1_zxy);
            float3x3 m1_zyx = float3x3(q1_zyx);

            TestUtils.AreEqual(m0, TestMatrix.test3x3_zxy, epsilon);
            TestUtils.AreEqual(m0_xyz, TestMatrix.test3x3_xyz, epsilon);
            TestUtils.AreEqual(m0_yzx, TestMatrix.test3x3_yzx, epsilon);
            TestUtils.AreEqual(m0_zxy, TestMatrix.test3x3_zxy, epsilon);
            TestUtils.AreEqual(m0_xzy, TestMatrix.test3x3_xzy, epsilon);
            TestUtils.AreEqual(m0_yxz, TestMatrix.test3x3_yxz, epsilon);
            TestUtils.AreEqual(m0_zyx, TestMatrix.test3x3_zyx, 0.0001f);

            TestUtils.AreEqual(m1, TestMatrix.test3x3_zxy, epsilon);
            TestUtils.AreEqual(m1_xyz, TestMatrix.test3x3_xyz, epsilon);
            TestUtils.AreEqual(m1_yzx, TestMatrix.test3x3_yzx, epsilon);
            TestUtils.AreEqual(m1_zxy, TestMatrix.test3x3_zxy, epsilon);
            TestUtils.AreEqual(m1_xzy, TestMatrix.test3x3_xzy, epsilon);
            TestUtils.AreEqual(m1_yxz, TestMatrix.test3x3_yxz, epsilon);
            TestUtils.AreEqual(m1_zyx, TestMatrix.test3x3_zyx, epsilon);
        }
示例#2
0
            // ボーン
            //[ReadOnly]
            //public NativeArray<quaternion> boneRotList;

            // パーティクルごと
            public void Execute(int index)
            {
                var flag = flagList[index];

                if (flag.IsValid() == false)
                {
                    return;
                }

                // チームデータ
                int teamId   = teamIdList[index];
                var teamData = teamDataList[teamId];

                // ここからは更新がある場合のみ実行(グローバルチームは除く)
                if (teamId != 0 && teamData.IsUpdate() == false)
                {
                    return;
                }

                var        oldpos  = oldPosList[index];
                var        oldrot  = oldRotList[index];
                float3     nextPos = oldpos;
                quaternion nextRot = oldrot;

                if (flag.IsFixed())
                {
                    // キネマティックパーティクル
                    // OldPos/Rot から BasePos/Rot に step で補間して現在姿勢とする
                    float stime   = teamData.startTime + updateDeltaTime * teamData.runCount;
                    float oldtime = teamData.time - teamData.addTime;
                    float step    = math.saturate((stime - oldtime) / teamData.addTime);
                    nextPos = math.lerp(oldPosList[index], basePosList[index], step);
                    nextRot = math.slerp(oldRotList[index], baseRotList[index], step);
                }
                else
                {
                    // 動的パーティクル
                    var depth       = depthList[index];
                    var maxVelocity = teamMaxVelocityList[teamId].Evaluate(depth);
                    var drag        = teamDragList[teamId].Evaluate(depth);
                    var gravity     = teamGravityList[teamId].Evaluate(depth);
                    var mass        = teamMassList[teamId].Evaluate(depth);
                    var velocity    = velocityList[index];

                    // massは主に伸縮を中心に調整されるので、フォース適用時は少し調整する
                    mass = (mass - 1.0f) * teamData.forceMassInfluence + 1.0f;

                    // 最大速度
                    velocity = MathUtility.ClampVector(velocity, 0.0f, maxVelocity);

                    // 空気抵抗(90ups基準)
                    // 重力に影響させたくないので先に計算する(※通常はforce適用後に行うのが一般的)
                    velocity *= math.pow(1.0f - drag, updatePower);

                    // フォース
                    // フォースは空気抵抗を無視して加算する
                    float3 force = 0;

                    // 重力
                    // 重力は質量に関係なく一定
#if false
                    // 方向減衰
                    if (teamData.IsFlag(PhysicsManagerTeamData.Flag_DirectionalDamping) && teamData.directionalDampingBoneIndex >= 0)
                    {
                        float3 dampDir = math.mul(boneRotList[teamData.directionalDampingBoneIndex], teamData.directionalDampingLocalDir);
                        var    dot     = math.dot(dampDir, new float3(0, -1, 0)) * 0.5f + 0.5f; // 1.0(0) - 0.5(90) - 0.0(180)
                        var    damp    = teamDirectionalDampingList[teamId].Evaluate(dot);
                        gravity *= damp;
                    }
#endif

                    // (最後に質量で割るためここでは質量をかける)
                    force.y += gravity * mass;

                    // 外部フォース
                    if (loopIndex == 0)
                    {
                        switch (teamData.forceMode)
                        {
                        case PhysicsManagerTeamData.ForceMode.VelocityAdd:
                            force += teamData.impactForce;
                            break;

                        case PhysicsManagerTeamData.ForceMode.VelocityAddWithoutMass:
                            force += teamData.impactForce * mass;
                            break;

                        case PhysicsManagerTeamData.ForceMode.VelocityChange:
                            force   += teamData.impactForce;
                            velocity = 0;
                            break;

                        case PhysicsManagerTeamData.ForceMode.VelocityChangeWithoutMass:
                            force   += teamData.impactForce * mass;
                            velocity = 0;
                            break;
                        }

                        // 外力
                        force += teamData.externalForce;
                    }

                    // 速度計算(質量で割る)
                    velocity += (force / mass) * updateDeltaTime;

                    // 速度を理想位置に反映させる
                    nextPos = oldpos + velocity * updateDeltaTime;
                }

                // 予定座標更新 ==============================================================
                // 摩擦減衰
                var friction = frictionList[index];
                friction            = friction * Define.Compute.FrictionDampingRate;
                frictionList[index] = friction;

                // 移動前の姿勢
                posList[index] = oldpos;
                rotList[index] = oldrot;

                // 予測位置
                nextPosList[index] = nextPos;
                nextRotList[index] = nextRot;
            }
            public void Execute()
            {
                for (int i = 0; i < activeConstraintCount; ++i)
                {
                    int particleIndex = particleIndices[i];
                    int colliderIndex = colliderIndices[i];

                    // no collider to pin to, so ignore the constraint.
                    if (colliderIndex < 0)
                    {
                        continue;
                    }

                    int rigidbodyIndex = shapes[colliderIndex].rigidbodyIndex;

                    // calculate time adjusted compliances
                    float2 compliances = stiffnesses[i].xy / (deltaTime * deltaTime);

                    float4 particlePosition = positions[particleIndex];

                    // express pin offset in world space:
                    float4     worldPinOffset     = transforms[colliderIndex].TransformPoint(offsets[i]);
                    float4     predictedPinOffset = worldPinOffset;
                    quaternion predictedRotation  = transforms[colliderIndex].rotation;

                    float rigidbodyLinearW  = 0;
                    float rigidbodyAngularW = 0;

                    float4 linearRbDelta  = float4.zero;
                    float4 angularRbDelta = float4.zero;

                    if (rigidbodyIndex >= 0)
                    {
                        var rigidbody = rigidbodies[rigidbodyIndex];
                        linearRbDelta  = rigidbodyLinearDeltas[rigidbodyIndex];
                        angularRbDelta = rigidbodyAngularDeltas[rigidbodyIndex];

                        // predict world-space position of offset point:
                        predictedPinOffset = BurstIntegration.IntegrateLinear(predictedPinOffset, rigidbody.GetVelocityAtPoint(worldPinOffset, linearRbDelta, angularRbDelta), deltaTime);

                        // predict rotation at the end of the step:
                        predictedRotation = BurstIntegration.IntegrateAngular(predictedRotation, rigidbody.angularVelocity + angularRbDelta, deltaTime);

                        // calculate linear and angular rigidbody weights:
                        rigidbodyLinearW  = rigidbody.inverseMass;
                        rigidbodyAngularW = BurstMath.RotationalInvMass(rigidbody.inverseInertiaTensor,
                                                                        worldPinOffset - rigidbody.com,
                                                                        math.normalizesafe(inertialFrame.frame.TransformPoint(particlePosition) - predictedPinOffset));
                    }

                    // Transform pin position to solver space for constraint solving:
                    predictedPinOffset = inertialFrame.frame.InverseTransformPoint(predictedPinOffset);

                    float4 gradient    = particlePosition - predictedPinOffset;
                    float  constraint  = math.length(gradient);
                    float4 gradientDir = gradient / (constraint + BurstMath.epsilon);

                    float4 lambda        = lambdas[i];
                    float  linearDLambda = (-constraint - compliances.x * lambda.w) / (invMasses[particleIndex] + rigidbodyLinearW + rigidbodyAngularW + compliances.x + BurstMath.epsilon);
                    lambda.w += linearDLambda;
                    float4 correction = linearDLambda * gradientDir;

                    deltas[particleIndex] += correction * invMasses[particleIndex];
                    counts[particleIndex]++;

                    if (rigidbodyAngularW > 0 || invRotationalMasses[particleIndex] > 0)
                    {
                        // bend/twist constraint:
                        quaternion omega = math.mul(math.conjugate(orientations[particleIndex]), predictedRotation);   //darboux vector

                        quaternion omega_plus;
                        omega_plus.value = omega.value + restDarboux[i].value;  //delta Omega with - omega_0
                        omega.value     -= restDarboux[i].value;                //delta Omega with + omega_0
                        if (math.lengthsq(omega.value) > math.lengthsq(omega_plus.value))
                        {
                            omega = omega_plus;
                        }

                        float3 dlambda = (omega.value.xyz - compliances.y * lambda.xyz) / new float3(compliances.y + invRotationalMasses[particleIndex] + rigidbodyAngularW + BurstMath.epsilon);
                        lambda.xyz += dlambda;

                        //discrete Darboux vector does not have vanishing scalar part
                        quaternion dlambdaQ = new quaternion(dlambda[0], dlambda[1], dlambda[2], 0);

                        quaternion orientDelta = orientationDeltas[particleIndex];
                        orientDelta.value += math.mul(predictedRotation, dlambdaQ).value *invRotationalMasses[particleIndex];
                        orientationDeltas[particleIndex] = orientDelta;
                        orientationCounts[particleIndex]++;

                        if (rigidbodyIndex >= 0)
                        {
                            rigidbodies[rigidbodyIndex].ApplyDeltaQuaternion(predictedRotation, math.mul(orientations[particleIndex], dlambdaQ).value * -rigidbodyAngularW, ref angularRbDelta, deltaTime);
                        }
                    }

                    if (rigidbodyIndex >= 0)
                    {
                        float4 impulse = correction / deltaTime;

                        rigidbodies[rigidbodyIndex].ApplyImpulse(-inertialFrame.frame.TransformVector(impulse) * 1, worldPinOffset, ref linearRbDelta, ref angularRbDelta);
                        rigidbodyLinearDeltas[rigidbodyIndex]  = linearRbDelta;
                        rigidbodyAngularDeltas[rigidbodyIndex] = angularRbDelta;
                    }

                    lambdas[i] = lambda;
                }
            }
示例#4
0
            // ルートラインごと
            public void Execute(int rootIndex)
            {
                // チーム
                int teamIndex = rootTeamList[rootIndex];

                if (teamIndex == 0)
                {
                    return;
                }
                var team = teamDataList[teamIndex];

                if (team.IsActive() == false || team.clampRotationGroupIndex < 0)
                {
                    return;
                }

                // 更新確認
                if (team.IsUpdate() == false)
                {
                    return;
                }

                // グループデータ
                var gdata = groupList[team.clampRotationGroupIndex];

                if (gdata.active == 0)
                {
                    return;
                }

                // データ
                var rootInfo  = rootInfoList[rootIndex];
                int dataIndex = rootInfo.startIndex + gdata.dataChunk.startIndex;
                int dataCount = rootInfo.dataLength;
                int pstart    = team.particleChunk.startIndex;

                // (1)現在の親からのベクトル長を保持する
                for (int i = 0; i < dataCount; i++)
                {
                    var data   = dataList[dataIndex + i];
                    int pindex = data.parentVertexIndex;
                    if (pindex < 0)
                    {
                        continue;
                    }

                    var index = data.vertexIndex;
                    index  += pstart;
                    pindex += pstart;

                    var npos = nextPosList[index];
                    var ppos = nextPosList[pindex];

                    // 現在ベクトル長
                    float vlen = math.distance(npos, ppos);

                    lengthBuffer[dataIndex + i] = vlen;
                }


                // (2)回転角度制限
                for (int i = 0; i < dataCount; i++)
                {
                    var data   = dataList[dataIndex + i];
                    int pindex = data.parentVertexIndex;
                    if (pindex < 0)
                    {
                        continue;
                    }

                    var index = data.vertexIndex;

                    index  += pstart;
                    pindex += pstart;

                    var flag = flagList[index];
                    if (flag.IsValid() == false)
                    {
                        continue;
                    }

                    var npos = nextPosList[index];
                    var nrot = nextRotList[index];
                    var opos = npos;

                    var ppos = nextPosList[pindex];
                    var prot = nextRotList[pindex];

                    float depth = depthList[index];
                    //float stiffness = gdata.stiffness.Evaluate(depth);


                    // 本来のローカルpos/rotを算出する
                    var        bpos     = basePosList[index];
                    var        brot     = baseRotList[index];
                    var        pbpos    = basePosList[pindex];
                    var        pbrot    = baseRotList[pindex];
                    float3     bv       = math.normalize(bpos - pbpos);
                    var        ipbrot   = math.inverse(pbrot);
                    float3     localPos = math.mul(ipbrot, bv);
                    quaternion localRot = math.mul(ipbrot, brot);


                    // 本来の方向ベクトル
                    //float3 tv = math.mul(prot, data.localPos);
                    float3 tv = math.mul(prot, localPos);

                    // ベクトル長
                    float vlen = math.distance(npos, ppos);   // 最新の距離(※これは伸びる場合があるが、一番安定している)
                    float blen = lengthBuffer[dataIndex + i]; // 計算前の距離
                    vlen = math.clamp(vlen, 0.0f, blen * 1.2f);

                    // 現在ベクトル
                    float3 v = math.normalize(npos - ppos);

                    // ベクトル角度クランプ
                    float maxAngle = gdata.maxAngle.Evaluate(depth);
                    maxAngle = math.radians(maxAngle);

                    float angle = math.acos(math.dot(v, tv));

                    if (flag.IsFixed() == false)
                    {
                        if (angle > maxAngle)
                        {
                            v = MathUtility.ClampAngle(v, tv, maxAngle);
                        }

                        var mv = (ppos + v * vlen) - npos;

                        // 最大速度クランプ
                        mv = MathUtility.ClampVector(mv, 0.0f, maxMoveLength);

                        var fpos = npos + mv;

                        // 摩擦係数から移動率を算出
                        float friction  = frictionList[index];
                        float moveratio = math.saturate(1.0f - friction * Define.Compute.FrictionMoveRatio);

                        // 摩擦係数による移動制限(衝突しているパーティクルは動きづらい)
                        npos = math.lerp(npos, fpos, moveratio);

                        nextPosList[index] = npos;

                        // 速度影響
                        var av = (npos - opos) * (1.0f - gdata.velocityInfluence);
                        posList[index] = posList[index] + av;
                    }

                    // 回転補正
                    //nrot = math.mul(prot, data.localRot);
                    nrot = math.mul(prot, localRot);
                    var q = MathUtility.FromToRotation(tv, v);
                    nrot = math.mul(q, nrot);

                    nextRotList[index] = nrot;
                }
            }
示例#5
0
    float TwistAroundAxis(quaternion q, float3 axis)
    {
        var a = math.dot(math.normalize(q.value.xyz), axis) / q.value.w;

        return(2 * math.atan(a));
    }
示例#6
0
        public static unsafe void SolveCollisionConstraints(PhysicsWorld world, float deltaTime, int maxIterations, float skinWidth, float maxSlope, Collider *collider, ref RigidTransform transform, ref float3 velocity, ref NativeArray <DistanceHit> distanceHits, ref NativeArray <ColliderCastHit> colliderHits, ref NativeArray <SurfaceConstraintInfo> surfaceConstraints)
        {
            float  remainingTime        = deltaTime;
            float3 previousDisplacement = velocity * remainingTime;

            float3 outPosition = transform.pos;
            float3 outVelocity = velocity;

            quaternion orientation = transform.rot;

            const float timeEpsilon = 0.000001f;

            for (int i = 0; i < maxIterations && remainingTime > timeEpsilon; i++)
            {
                MaxHitCollector <DistanceHit> distanceHitCollector = new MaxHitCollector <DistanceHit>(skinWidth, ref distanceHits);

                int constraintCount = 0;

                // Handle distance checks
                {
                    ColliderDistanceInput input = new ColliderDistanceInput
                    {
                        Collider    = collider,
                        MaxDistance = skinWidth,
                        Transform   = new RigidTransform
                        {
                            pos = outPosition,
                            rot = orientation
                        }
                    };
                    world.CalculateDistance(input, ref distanceHitCollector);

                    for (int hitIndex = 0; hitIndex < distanceHitCollector.NumHits; hitIndex++)
                    {
                        DistanceHit hit = distanceHitCollector.AllHits[hitIndex];
                        CreateConstraintFromHit(world, hit.ColliderKey, hit.RigidBodyIndex, hit.Position, float3.zero, hit.SurfaceNormal, hit.Distance, deltaTime, out SurfaceConstraintInfo constraint);
                        CreateSlopeConstraint(math.up(), math.cos(maxSlope), ref constraint, ref surfaceConstraints, ref constraintCount);
                        surfaceConstraints[constraintCount++] = constraint;
                    }
                }

                // Handle Collider
                {
                    float3 displacement = previousDisplacement;
                    MaxHitCollector <ColliderCastHit> colliderHitCollector = new MaxHitCollector <ColliderCastHit>(1.0f, ref colliderHits);

                    ColliderCastInput input = new ColliderCastInput
                    {
                        Collider    = collider,
                        Position    = outPosition,
                        Direction   = velocity,
                        Orientation = orientation
                    };
                    world.CastCollider(input, ref colliderHitCollector);

                    for (int hitIndex = 0; hitIndex < colliderHitCollector.NumHits; hitIndex++)
                    {
                        ColliderCastHit hit = colliderHitCollector.AllHits[hitIndex];

                        bool duplicate = false;
                        for (int distanceHitIndex = 0; distanceHitIndex < distanceHitCollector.NumHits; distanceHitIndex++)
                        {
                            DistanceHit distanceHit = distanceHitCollector.AllHits[distanceHitIndex];
                            if (distanceHit.RigidBodyIndex == hit.RigidBodyIndex && distanceHit.ColliderKey.Equals(hit.ColliderKey))
                            {
                                duplicate = true;
                                break;
                            }
                        }

                        if (!duplicate)
                        {
                            CreateConstraintFromHit(world, hit.ColliderKey, hit.RigidBodyIndex, hit.Position, outVelocity, hit.SurfaceNormal, hit.Fraction * math.length(previousDisplacement), deltaTime, out SurfaceConstraintInfo constraint);
                            CreateSlopeConstraint(math.up(), math.cos(maxSlope), ref constraint, ref surfaceConstraints, ref constraintCount);
                            surfaceConstraints[constraintCount++] = constraint;
                        }
                    }
                }

                float3 previousPosition = outPosition;
                float3 previousVelocity = outVelocity;

                SimplexSolver.Solve(world, remainingTime, math.up(), constraintCount, ref surfaceConstraints, ref outPosition, ref outVelocity, out float integratedTime);

                float3 currentDisplacement = outPosition - previousPosition;

                MaxHitCollector <ColliderCastHit> displacementHitCollector = new MaxHitCollector <ColliderCastHit>(1.0f, ref colliderHits);
                int displacementContactIndex = -1;

                if (math.lengthsq(currentDisplacement) > SimplexSolver.c_SimplexSolverEpsilon)
                {
                    ColliderCastInput input = new ColliderCastInput
                    {
                        Collider    = collider,
                        Position    = previousPosition,
                        Direction   = currentDisplacement,
                        Orientation = orientation
                    };
                    world.CastCollider(input, ref displacementHitCollector);

                    for (int hitIndex = 0; hitIndex < distanceHitCollector.NumHits; hitIndex++)
                    {
                        ColliderCastHit hit = displacementHitCollector.AllHits[hitIndex];

                        bool duplicate = false;
                        for (int constrainIndex = 0; constrainIndex < constraintCount; constrainIndex++)
                        {
                            SurfaceConstraintInfo constraint = surfaceConstraints[constrainIndex];
                            if (constraint.RigidBodyIndex == hit.RigidBodyIndex && constraint.ColliderKey.Equals(hit.ColliderKey))
                            {
                                duplicate = true;
                                break;
                            }

                            if (!duplicate)
                            {
                                displacementContactIndex = hitIndex;
                                break;
                            }
                        }
                    }

                    if (displacementContactIndex >= 0)
                    {
                        ColliderCastHit newContact = displacementHitCollector.AllHits[displacementContactIndex];

                        float fraction = newContact.Fraction / math.length(currentDisplacement);
                        integratedTime *= fraction;

                        float3 displacement = currentDisplacement * fraction;
                        outPosition = previousPosition + displacement;
                    }
                }

                remainingTime -= integratedTime;

                previousDisplacement = outVelocity * remainingTime;
            }

            transform.pos = outPosition;
            velocity      = outVelocity;
        }
示例#7
0
        public static void ItemAttachToOwner(EntityManager entityManager, Entity item,
                                             Entity owner, Entity preOwner, float3 initPos, quaternion initRot)
        {
            if (preOwner != Entity.Null)
            {
                if (entityManager.HasComponent <SlotPredictedState>(preOwner))
                {
                    var preOwnerSlotState = entityManager.GetComponentData <SlotPredictedState>(preOwner);
                    preOwnerSlotState.FilledIn = Entity.Null;
                    entityManager.SetComponentData(preOwner, preOwnerSlotState);
                }
                else if (entityManager.HasComponent <MultiSlotPredictedState>(preOwner))
                {
                    var preOwnerSlotState = entityManager.GetComponentData <MultiSlotPredictedState>(preOwner);
                    preOwnerSlotState.Value.TakeOut();
                    entityManager.SetComponentData(preOwner, preOwnerSlotState);
                }
                else if (entityManager.HasComponent <SinkPredictedState>(preOwner))
                {
                    var preOwnerSlotState = entityManager.GetComponentData <SinkPredictedState>(preOwner);
                    preOwnerSlotState.Value.TakeOut();
                    entityManager.SetComponentData(preOwner, preOwnerSlotState);
                }
                else
                {
                    return;
                }
            }

            if (entityManager.HasComponent <SlotPredictedState>(owner))
            {
                var slotState = entityManager.GetComponentData <SlotPredictedState>(owner);
                slotState.FilledIn = item;
                entityManager.SetComponentData(owner, slotState);
            }
            else if (entityManager.HasComponent <MultiSlotPredictedState>(owner))
            {
                var slotState = entityManager.GetComponentData <MultiSlotPredictedState>(owner);
                slotState.Value.FillIn(item);
                entityManager.SetComponentData(owner, slotState);
            }
            else if (entityManager.HasComponent <SinkPredictedState>(owner))
            {
                var slotState = entityManager.GetComponentData <SinkPredictedState>(owner);
                slotState.Value.FillIn(item);
                entityManager.SetComponentData(owner, slotState);
            }
            else
            {
                return;
            }

            var ownerSlot = entityManager.GetComponentData <SlotSetting>(owner);


            var ownerRotation = entityManager.HasComponent <LocalToWorld>(owner)
                ? entityManager.GetComponentData <LocalToWorld>(owner).Rotation
                : quaternion.identity;

            float3 pos;

            if (entityManager.HasComponent <MultiSlotPredictedState>(owner))
            {
                var slotState = entityManager.GetComponentData <MultiSlotPredictedState>(owner);

                pos = ownerSlot.Pos + ownerSlot.Offset * slotState.Value.Count();//+ offset.Pos;
            }
            else
            {
                pos = ownerSlot.Pos;
            }

            pos = initPos.Equals(float3.zero) ? pos : initPos;
            var rot = initRot.Equals(quaternion.identity) ? ownerSlot.Rot: math.mul(initRot, math.inverse(ownerRotation));

            ItemAttachToOwner1(entityManager, item, owner, preOwner, pos, rot);
        }
 protected Entity CreateDynamicBody(float3 position, quaternion orientation, BlobAssetReference <Collider> collider,
                                    float3 linearVelocity, float3 angularVelocity, float mass)
 {
     return(CreateBody(position, orientation, collider, linearVelocity, angularVelocity, mass, true));
 }
        public static void Contacts(int particleIndex,
                                    float4 position,
                                    quaternion orientation,
                                    float4 radii,
                                    int colliderIndex,
                                    BurstAffineTransform transform,
                                    BurstColliderShape shape,
                                    NativeQueue <BurstContact> .ParallelWriter contacts)
        {
            BurstContact c = new BurstContact()
            {
                entityA = particleIndex,
                entityB = colliderIndex,
            };

            float4 center = shape.center * transform.scale;
            float4 size   = shape.size * transform.scale * 0.5f;

            position = transform.InverseTransformPointUnscaled(position) - center;

            // Get minimum distance for each axis:
            float4 distances = size - math.abs(position);

            // if we are inside the box:
            if (distances.x >= 0 && distances.y >= 0 && distances.z >= 0)
            {
                // find minimum distance in all three axes and the axis index:
                float min  = float.MaxValue;
                int   axis = 0;
                for (int i = 0; i < 3; ++i)
                {
                    if (distances[i] < min)
                    {
                        min  = distances[i];
                        axis = i;
                    }
                }

                c.normal = float4.zero;
                c.point  = position;

                c.distance     = -distances[axis];
                c.normal[axis] = position[axis] > 0 ? 1 : -1;
                c.point[axis]  = size[axis] * c.normal[axis];
            }
            else // we are outside the box:
            {
                // clamp point to be inside the box:
                c.point = math.clamp(position, -size, size);

                // find distance and direction to clamped point:
                float4 diff = position - c.point;
                c.distance = math.length(diff);
                c.normal   = diff / (c.distance + math.FLT_MIN_NORMAL);
            }

            c.point += center;
            c.point  = transform.TransformPointUnscaled(c.point);
            c.normal = transform.TransformDirection(c.normal);

            c.distance -= shape.contactOffset + BurstMath.EllipsoidRadius(c.normal, orientation, radii.xyz);

            contacts.Enqueue(c);
        }
示例#10
0
        public static void AddRotationCurves(AnimationClip clip, string animationPath, NativeArray <float> times, NativeArray <Quaternion> quaternions, InterpolationType interpolationType)
        {
            Profiler.BeginSample("AnimationUtils.AddRotationCurves");
            var rotX = new AnimationCurve();
            var rotY = new AnimationCurve();
            var rotZ = new AnimationCurve();
            var rotW = new AnimationCurve();

            // TODO: Refactor interface to use Unity.Mathematics types and remove this Reinterpret
            var values = quaternions.Reinterpret <quaternion>();

#if DEBUG
            uint duplicates = 0;
#endif

            switch (interpolationType)
            {
            case InterpolationType.STEP: {
                for (var i = 0; i < times.Length; i++)
                {
                    var time  = times[i];
                    var value = values[i];
                    rotX.AddKey(new Keyframe(time, value.value.x, float.PositiveInfinity, 0));
                    rotY.AddKey(new Keyframe(time, value.value.y, float.PositiveInfinity, 0));
                    rotZ.AddKey(new Keyframe(time, value.value.z, float.PositiveInfinity, 0));
                    rotW.AddKey(new Keyframe(time, value.value.w, float.PositiveInfinity, 0));
                }
                break;
            }

            case InterpolationType.CUBICSPLINE: {
                for (var i = 0; i < times.Length; i++)
                {
                    var time       = times[i];
                    var inTangent  = values[i * 3];
                    var value      = values[i * 3 + 1];
                    var outTangent = values[i * 3 + 2];
                    rotX.AddKey(new Keyframe(time, value.value.x, inTangent.value.x, outTangent.value.x, .5f, .5f));
                    rotY.AddKey(new Keyframe(time, value.value.y, inTangent.value.y, outTangent.value.y, .5f, .5f));
                    rotZ.AddKey(new Keyframe(time, value.value.z, inTangent.value.z, outTangent.value.z, .5f, .5f));
                    rotW.AddKey(new Keyframe(time, value.value.w, inTangent.value.w, outTangent.value.w, .5f, .5f));
                }
                break;
            }

            default: {     // LINEAR
                var prevTime  = times[0];
                var prevValue = values[0];
                var inTangent = new quaternion(new float4(0f));

                for (var i = 1; i < times.Length; i++)
                {
                    var time  = times[i];
                    var value = values[i];

                    if (prevTime >= time)
                    {
                        // Time value is not increasing, so we ignore this keyframe
                        // This happened on some Sketchfab files (see #298)
#if DEBUG
                        duplicates++;
#endif
                        continue;
                    }

                    // Ensure shortest path rotation ( see https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#interpolation-slerp )
                    if (math.dot(prevValue, value) < 0)
                    {
                        value.value = -value.value;
                    }

                    var        dT = time - prevTime;
                    var        dV = value.value - prevValue.value;
                    quaternion outTangent;
                    if (dT < k_TimeEpsilon)
                    {
                        outTangent.value.x = (dV.x < 0f) ^ (dT < 0f) ? float.NegativeInfinity : float.PositiveInfinity;
                        outTangent.value.y = (dV.y < 0f) ^ (dT < 0f) ? float.NegativeInfinity : float.PositiveInfinity;
                        outTangent.value.z = (dV.z < 0f) ^ (dT < 0f) ? float.NegativeInfinity : float.PositiveInfinity;
                        outTangent.value.w = (dV.w < 0f) ^ (dT < 0f) ? float.NegativeInfinity : float.PositiveInfinity;
                    }
                    else
                    {
                        outTangent = dV / dT;
                    }

                    rotX.AddKey(new Keyframe(prevTime, prevValue.value.x, inTangent.value.x, outTangent.value.x));
                    rotY.AddKey(new Keyframe(prevTime, prevValue.value.y, inTangent.value.y, outTangent.value.y));
                    rotZ.AddKey(new Keyframe(prevTime, prevValue.value.z, inTangent.value.z, outTangent.value.z));
                    rotW.AddKey(new Keyframe(prevTime, prevValue.value.w, inTangent.value.w, outTangent.value.w));

                    inTangent = outTangent;
                    prevTime  = time;
                    prevValue = value;
                }

                rotX.AddKey(new Keyframe(prevTime, prevValue.value.x, inTangent.value.x, 0));
                rotY.AddKey(new Keyframe(prevTime, prevValue.value.y, inTangent.value.y, 0));
                rotZ.AddKey(new Keyframe(prevTime, prevValue.value.z, inTangent.value.z, 0));
                rotW.AddKey(new Keyframe(prevTime, prevValue.value.w, inTangent.value.w, 0));

                break;
            }
            }

            clip.SetCurve(animationPath, typeof(Transform), "localRotation.x", rotX);
            clip.SetCurve(animationPath, typeof(Transform), "localRotation.y", rotY);
            clip.SetCurve(animationPath, typeof(Transform), "localRotation.z", rotZ);
            clip.SetCurve(animationPath, typeof(Transform), "localRotation.w", rotW);
            Profiler.EndSample();

#if DEBUG
            if (duplicates > 0)
            {
                ReportDuplicateKeyframes();
            }
#endif
        }
 protected Entity CreateStaticBody(float3 position, quaternion orientation, BlobAssetReference <Collider> collider)
 {
     return(CreateBody(position, orientation, collider, float3.zero, float3.zero, 0.0f, false));
 }
示例#12
0
            // パーティクルごと
            public void Execute(int index)
            {
                var flag = flagList[index];

                if (flag.IsValid() == false || flag.IsFixed())
                {
                    return;
                }

                var team = teamDataList[teamIdList[index]];

                if (team.IsActive() == false)
                {
                    return;
                }
                if (team.clampPositionGroupIndex < 0)
                {
                    return;
                }
                // 更新確認
                if (team.IsUpdate() == false)
                {
                    return;
                }

                // グループデータ
                var gdata = clampPositionGroupList[team.clampPositionGroupIndex];

                if (gdata.active == 0)
                {
                    return;
                }

                var nextpos     = nextPosList[index];
                var depth       = depthList[index];
                var limitLength = gdata.limitLength.Evaluate(depth);

                // baseposからの最大移動距離制限
                var basepos = basePosList[index];
                var v       = nextpos - basepos; // nextpos

                // 摩擦係数から移動率を算出
                var   friction  = frictionList[index];
                float moveratio = math.saturate(1.0f - friction * Define.Compute.FrictionMoveRatio);


                if (gdata.IsAxisCheck())
                {
                    // 楕円体判定
                    float3 axisRatio = gdata.axisRatio;
                    // 基準軸のワールド回転
                    quaternion rot = baseRotList[index];
                    // 基準軸のローカルベクトルへ変換
                    quaternion irot = math.inverse(rot);
                    float3     lv   = math.mul(irot, v);

                    // Boxクランプ
                    float3 axisRatio1 = axisRatio * limitLength;
                    lv = math.clamp(lv, -axisRatio1, axisRatio1);

                    // 基準軸のワールドベクトルへ変換
                    // 最終的に(v)が楕円体でクランプされた移動制限ベクトルとなる
                    v = math.mul(rot, lv);
                }

                // nextposの制限
                v = MathUtility.ClampVector(v, 0.0f, limitLength);

                // 最大速度クランプ
                v = (basepos + v) - nextpos;
                if (team.IsFlag(PhysicsManagerTeamData.Flag_IgnoreClampPositionVelocity) == false)
                {
                    v = MathUtility.ClampVector(v, 0.0f, maxMoveLength);
                }

                // 移動位置
                var opos = nextpos;
                var fpos = opos + v;

                // 摩擦係数による移動制限(衝突しているパーティクルは動きづらい)
                nextpos = math.lerp(opos, fpos, moveratio);

                // 書き込み
                nextPosList[index] = nextpos;

                // 速度影響
                var av = (nextpos - opos) * (1.0f - gdata.velocityInfluence);

                posList[index] = posList[index] + av;
            }
        // Update is called once per frame
        protected override void OnUpdate()
        {
            // Make sure the world has finished building before querying it
            CreatePhysicsWorldSystem.FinalJobHandle.Complete();

            PhysicsWorld world = CreatePhysicsWorldSystem.PhysicsWorld;

            float invDt = 1.0f / Time.fixedDeltaTime;

            Entities.ForEach((VehicleMechanics mechanics) =>
            {
                if (mechanics.wheels.Count == 0)
                {
                    return;
                }

                Entity ce = mechanics.chassisEntity;
                if (ce == Entity.Null)
                {
                    return;
                }

                int ceIdx = world.GetRigidBodyIndex(ce);
                if (-1 == ceIdx || ceIdx >= world.NumDynamicBodies)
                {
                    return;
                }

                //float ceMass = world.GetMass(ceIdx);
                float3 cePosition     = EntityManager.GetComponentData <Translation>(ce).Value;
                quaternion ceRotation = EntityManager.GetComponentData <Rotation>(ce).Value;
                float3 ceCenterOfMass = world.GetCenterOfMass(ceIdx);
                float3 ceUp           = math.mul(ceRotation, mechanics.chassisUp);
                float3 ceForward      = math.mul(ceRotation, mechanics.chassisForward);
                float3 ceRight        = math.mul(ceRotation, mechanics.chassisRight);

                var rayResults    = new NativeArray <RaycastHit>(mechanics.wheels.Count, Allocator.TempJob);
                var rayVelocities = new NativeArray <float3>(mechanics.wheels.Count, Allocator.TempJob);

                // Collect the RayCast results
                var rayInputs          = new NativeArray <RaycastInput>(mechanics.wheels.Count, Allocator.TempJob);
                CollisionFilter filter = world.GetCollisionFilter(ceIdx);
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    GameObject weGO = mechanics.wheels[i];

                    float3 wheelCurrentPos = weGO.transform.position;

                    float3 rayStart = weGO.transform.parent.position;
                    float3 rayEnd   = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart;

                    if (mechanics.drawDebugInformation)
                    {
                        Debug.DrawRay(rayStart, rayEnd - rayStart);
                    }

                    rayInputs[i] = new RaycastInput
                    {
                        Start  = rayStart,
                        End    = rayEnd,
                        Filter = filter
                    };
                }
                JobHandle rayJobHandle = ScheduleBatchRayCast(world.CollisionWorld, rayInputs, rayResults);
                rayJobHandle.Complete();
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    RaycastHit rayResult = rayResults[i];

                    rayVelocities[i] = float3.zero;
                    if (rayResult.RigidBodyIndex != -1)
                    {
                        float3 wheelPos = rayResult.Position;
                        wheelPos       -= (cePosition - ceCenterOfMass);

                        float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos);
                        rayVelocities[i]       = velocityAtWheel;
                    }
                }
                rayInputs.Dispose();


                // Calculate a simple slip factor based on chassis tilt.
                float slopeSlipFactor = math.pow(math.abs(math.dot(ceUp, math.up())), 4.0f);

                // Proportional apply velocity changes to each wheel
                float invWheelCount = 1.0f / mechanics.wheels.Count;
                for (int i = 0; i < mechanics.wheels.Count; i++)
                {
                    GameObject weGO = mechanics.wheels[i];

                    float3 rayStart = weGO.transform.parent.position;
                    float3 rayEnd   = (-ceUp * (mechanics.suspensionLength + mechanics.wheelBase)) + rayStart;

                    float3 rayDir = rayEnd - rayStart;

                    RaycastHit rayResult = rayResults[i];
                    //float3 velocityAtWheel = rayVelocities[i];

                    float3 wheelPos = rayResult.Position;
                    wheelPos       -= (cePosition - ceCenterOfMass);

                    float3 velocityAtWheel = world.GetLinearVelocity(ceIdx, wheelPos);

                    float3 weUp      = ceUp;
                    float3 weRight   = ceRight;
                    float3 weForward = ceForward;

                    #region handle wheel steering
                    {
                        bool bIsSteeringWheel = mechanics.steeringWheels.Contains(weGO);
                        if (bIsSteeringWheel)
                        {
                            float steeringAngle = math.radians(mechanics.steeringAngle);
                            //if((mechanics.steeringWheels.IndexOf(weGO)+1) > (0.5f * mechanics.steeringWheels.Count))
                            //    steeringAngle = -steeringAngle;

                            quaternion wRotation = quaternion.AxisAngle(ceUp, steeringAngle);
                            weRight   = math.rotate(wRotation, weRight);
                            weForward = math.rotate(wRotation, weForward);

                            weGO.transform.localRotation = quaternion.AxisAngle(mechanics.chassisUp, steeringAngle);
                        }
                    }
                    #endregion

                    float currentSpeedUp      = math.dot(velocityAtWheel, weUp);
                    float currentSpeedForward = math.dot(velocityAtWheel, weForward);
                    float currentSpeedRight   = math.dot(velocityAtWheel, weRight);

                    #region handle wheel rotation
                    {
                        var rGO = weGO.transform.GetChild(0);
                        if (rGO)
                        {
                            bool isDriven    = (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO));
                            float weRotation = isDriven
                                ? (mechanics.driveDesiredSpeed / mechanics.wheelBase)
                                : (currentSpeedForward / mechanics.wheelBase);

                            weRotation = math.radians(weRotation);
                            rGO.transform.localRotation *= quaternion.AxisAngle(mechanics.chassisRight, weRotation);
                        }
                    }
                    #endregion


                    float3 wheelCurrentPos = weGO.transform.position;
                    bool hit = !math.all(rayResult.SurfaceNormal == float3.zero);
                    if (!hit)
                    {
                        float3 wheelDesiredPos  = (-ceUp * mechanics.suspensionLength) + rayStart;
                        weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength);
                    }
                    else
                    {
                        // remove the wheelbase to get wheel position.
                        float fraction = rayResult.Fraction - (mechanics.wheelBase) / (mechanics.suspensionLength + mechanics.wheelBase);

                        float3 wheelDesiredPos  = math.lerp(rayStart, rayEnd, fraction);
                        weGO.transform.position = math.lerp(wheelCurrentPos, wheelDesiredPos, mechanics.suspensionDamping / mechanics.suspensionStrength);

                        #region Suspension
                        {
                            // Calculate and apply the impulses
                            var posA = rayEnd;
                            var posB = rayResult.Position;
                            var lvA  = currentSpeedUp * weUp;// world.GetLinearVelocity(ceIdx, posA);
                            var lvB  = world.GetLinearVelocity(rayResult.RigidBodyIndex, posB);

                            var impulse     = mechanics.suspensionStrength * (posB - posA) + mechanics.suspensionDamping * (lvB - lvA);
                            impulse         = impulse * invWheelCount;
                            float impulseUp = math.dot(impulse, weUp);

                            // Suspension shouldn't necessarily pull the vehicle down!
                            float downForceLimit = -0.25f;
                            if (downForceLimit < impulseUp)
                            {
                                impulse = impulseUp * weUp;

                                world.ApplyImpulse(ceIdx, impulse, posA);
                                //world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, posB);

                                if (mechanics.drawDebugInformation)
                                {
                                    Debug.DrawRay(wheelDesiredPos, impulse, Color.green);
                                }
                            }
                        }
                        #endregion

                        #region Sideways friction
                        {
                            float deltaSpeedRight = (0.0f - currentSpeedRight);
                            deltaSpeedRight       = math.clamp(deltaSpeedRight, -mechanics.wheelMaxImpulseRight, mechanics.wheelMaxImpulseRight);
                            deltaSpeedRight      *= mechanics.wheelFrictionRight;
                            deltaSpeedRight      *= slopeSlipFactor;

                            float3 impulse      = deltaSpeedRight * weRight;
                            float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos);
                            impulse             = impulse * effectiveMass * invWheelCount;

                            world.ApplyImpulse(ceIdx, impulse, wheelPos);
                            world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos);

                            if (mechanics.drawDebugInformation)
                            {
                                Debug.DrawRay(wheelDesiredPos, impulse, Color.red);
                            }
                        }
                        #endregion

                        #region Drive
                        {
                            if (mechanics.driveEngaged && mechanics.driveWheels.Contains(weGO))
                            {
                                float deltaSpeedForward = (mechanics.driveDesiredSpeed - currentSpeedForward);
                                deltaSpeedForward       = math.clamp(deltaSpeedForward, -mechanics.wheelMaxImpulseForward, mechanics.wheelMaxImpulseForward);
                                deltaSpeedForward      *= mechanics.wheelFrictionForward;
                                deltaSpeedForward      *= slopeSlipFactor;

                                float3 impulse = deltaSpeedForward * weForward;

                                float effectiveMass = world.GetEffectiveMass(ceIdx, impulse, wheelPos);
                                impulse             = impulse * effectiveMass * invWheelCount;

                                world.ApplyImpulse(ceIdx, impulse, wheelPos);
                                world.ApplyImpulse(rayResult.RigidBodyIndex, -impulse, wheelPos);

                                if (mechanics.drawDebugInformation)
                                {
                                    Debug.DrawRay(wheelDesiredPos, impulse, Color.blue);
                                }
                            }
                        }
                        #endregion
                    }
                }

                rayResults.Dispose();
                rayVelocities.Dispose();
            });
        }
示例#14
0
 public static sphere transform(sphere prim, float3 position, quaternion rotation)
 {
     prim.center = mul(rotation, prim.center) + position;
     return(prim);
 }
示例#15
0
        public void TRS_LocalPositionsHierarchy()
        {
            var pi        = 3.14159265359f;
            var rotations = new quaternion[]
            {
                quaternion.EulerYZX(new float3(0.125f * pi, 0.0f, 0.0f)),
                quaternion.EulerYZX(new float3(0.5f * pi, 0.0f, 0.0f)),
                quaternion.EulerYZX(new float3(pi, 0.0f, 0.0f)),
            };
            var translations = new float3[]
            {
                new float3(0.0f, 0.0f, 1.0f),
                new float3(0.0f, 1.0f, 0.0f),
                new float3(1.0f, 0.0f, 0.0f),
                new float3(0.5f, 0.5f, 0.5f),
            };

            //  0: R:[0] T:[0]
            //  1:  - R:[1] T:[1]
            //  2:    - R:[2] T:[0]
            //  3:    - R:[2] T:[1]
            //  4:    - R:[2] T:[2]
            //  5:      - R:[1] T:[0]
            //  6:      - R:[1] T:[1]
            //  7:      - R:[1] T:[2]
            //  8:  - R:[2] T:[2]
            //  9:    - R:[1] T:[0]
            // 10:    - R:[1] T:[1]
            // 11:    - R:[1] T:[2]
            // 12:      - R:[0] T:[0]
            // 13:        - R:[0] T:[1]
            // 14:          - R:[0] T:[2]
            // 15:            - R:[0] T:[2]

            var rotationIndices    = new int[] { 0, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0 };
            var translationIndices = new int[] { 0, 1, 0, 1, 2, 0, 1, 2, 2, 0, 1, 2, 0, 1, 2, 2 };
            var parentIndices      = new int[] { -1, 0, 1, 1, 1, 4, 4, 4, 0, 8, 8, 8, 11, 12, 13, 14 };

            var expectedLocalToParent = new float4x4[16];

            for (int i = 0; i < 16; i++)
            {
                var rotationIndex    = rotationIndices[i];
                var translationIndex = translationIndices[i];
                var localToParent    = new float4x4(rotations[rotationIndex], translations[translationIndex]);
                expectedLocalToParent[i] = localToParent;
            }

            var expectedLocalToWorld = new float4x4[16];

            expectedLocalToWorld[0] = expectedLocalToParent[0];
            for (int i = 1; i < 16; i++)
            {
                var parentIndex = parentIndices[i];
                expectedLocalToWorld[i] = math.mul(expectedLocalToWorld[parentIndex], expectedLocalToParent[i]);
            }

            var bodyArchetype   = m_Manager.CreateArchetype(typeof(Position), typeof(Rotation));
            var attachArchetype = m_Manager.CreateArchetype(typeof(Attach));
            var bodyEntities    = new NativeArray <Entity>(16, Allocator.TempJob);
            var attachEntities  = new NativeArray <Entity>(15, Allocator.TempJob);

            m_Manager.CreateEntity(bodyArchetype, bodyEntities);
            m_Manager.CreateEntity(attachArchetype, attachEntities);

            for (int i = 0; i < 16; i++)
            {
                var rotationIndex    = rotationIndices[i];
                var translationIndex = translationIndices[i];
                var rotation         = new Rotation {
                    Value = rotations[rotationIndex]
                };
                var position = new Position {
                    Value = translations[translationIndex]
                };

                m_Manager.SetComponentData(bodyEntities[i], rotation);
                m_Manager.SetComponentData(bodyEntities[i], position);
            }

            for (int i = 1; i < 16; i++)
            {
                var parentIndex = parentIndices[i];
                m_Manager.SetComponentData(attachEntities[i - 1],
                                           new Attach {
                    Parent = bodyEntities[parentIndex], Child = bodyEntities[i]
                });
            }

            World.GetOrCreateManager <EndFrameTransformSystem>().Update();

            // Check all non-root LocalToParent
            for (int i = 1; i < 16; i++)
            {
                var entity        = bodyEntities[i];
                var localToParent = m_Manager.GetComponentData <LocalToParent>(entity).Value;

                AssertCloseEnough(expectedLocalToParent[i], localToParent);
            }

            // Check all LocalToWorld
            for (int i = 0; i < 16; i++)
            {
                var entity       = bodyEntities[i];
                var localToWorld = m_Manager.GetComponentData <LocalToWorld>(entity).Value;

                AssertCloseEnough(expectedLocalToWorld[i], localToWorld);
            }

            bodyEntities.Dispose();
            attachEntities.Dispose();
        }
 // matrix to transform point from shape's local basis into world space
 static float4x4 GetBasisToWorldMatrix(
     float4x4 localToWorld, float3 center, quaternion orientation, float3 size
     ) =>
 math.mul(localToWorld, float4x4.TRS(center, orientation, size));
示例#17
0
 public box(float3 center, Quaternion rotation, float3 size)
 {
     this.center   = center;
     this.rotation = rotation;
     this.size     = size;
 }
示例#18
0
    public static unsafe void CollideAndIntegrate(
        CharacterControllerStepInput stepInput, float characterMass, bool affectBodies, Collider *collider,
        ref RigidTransform transform, ref float3 linearVelocity, ref NativeStream.Writer deferredImpulseWriter)
    {
        // Copy parameters
        float        deltaTime = stepInput.DeltaTime;
        float3       up        = stepInput.Up;
        PhysicsWorld world     = stepInput.World;

        float remainingTime = deltaTime;

        float3     newPosition = transform.pos;
        quaternion orientation = transform.rot;
        float3     newVelocity = linearVelocity;

        float maxSlopeCos = math.cos(stepInput.MaxSlope);

        const float timeEpsilon = 0.000001f;

        for (int i = 0; i < stepInput.MaxIterations && remainingTime > timeEpsilon; i++)
        {
            NativeList <SurfaceConstraintInfo> constraints = new NativeList <SurfaceConstraintInfo>(k_DefaultConstraintsCapacity, Allocator.Temp);

            // Do a collider cast
            {
                float3 displacement = newVelocity * remainingTime;
                NativeList <ColliderCastHit> castHits = new NativeList <ColliderCastHit>(k_DefaultQueryHitsCapacity, Allocator.Temp);
                CharacterControllerAllHitsCollector <ColliderCastHit> collector = new CharacterControllerAllHitsCollector <ColliderCastHit>(stepInput.RigidBodyIndex, 1.0f, ref castHits, world);
                ColliderCastInput input = new ColliderCastInput()
                {
                    Collider    = collider,
                    Orientation = orientation,
                    Start       = newPosition,
                    End         = newPosition + displacement
                };
                world.CastCollider(input, ref collector);

                // Iterate over hits and create constraints from them
                for (int hitIndex = 0; hitIndex < collector.NumHits; hitIndex++)
                {
                    ColliderCastHit hit = collector.AllHits[hitIndex];
                    CreateConstraint(stepInput.World, stepInput.Up,
                                     hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal, hit.Fraction * math.length(displacement),
                                     stepInput.SkinWidth, maxSlopeCos, ref constraints);
                }
            }

            // Then do a collider distance for penetration recovery,
            // but only fix up penetrating hits
            {
                // Collider distance query
                NativeList <DistanceHit> distanceHits = new NativeList <DistanceHit>(k_DefaultQueryHitsCapacity, Allocator.Temp);
                CharacterControllerAllHitsCollector <DistanceHit> distanceHitsCollector = new CharacterControllerAllHitsCollector <DistanceHit>(
                    stepInput.RigidBodyIndex, stepInput.ContactTolerance, ref distanceHits, world);
                {
                    ColliderDistanceInput input = new ColliderDistanceInput()
                    {
                        MaxDistance = stepInput.ContactTolerance,
                        Transform   = transform,
                        Collider    = collider
                    };
                    world.CalculateDistance(input, ref distanceHitsCollector);
                }

                // Iterate over penetrating hits and fix up distance and normal
                int numConstraints = constraints.Length;
                for (int hitIndex = 0; hitIndex < distanceHitsCollector.NumHits; hitIndex++)
                {
                    DistanceHit hit = distanceHitsCollector.AllHits[hitIndex];
                    if (hit.Distance < stepInput.SkinWidth)
                    {
                        bool found = false;

                        // Iterate backwards to locate the original constraint before the max slope constraint
                        for (int constraintIndex = numConstraints - 1; constraintIndex >= 0; constraintIndex--)
                        {
                            SurfaceConstraintInfo constraint = constraints[constraintIndex];
                            if (constraint.RigidBodyIndex == hit.RigidBodyIndex &&
                                constraint.ColliderKey.Equals(hit.ColliderKey))
                            {
                                // Fix up the constraint (normal, distance)
                                {
                                    // Create new constraint
                                    CreateConstraintFromHit(world, hit.RigidBodyIndex, hit.ColliderKey,
                                                            hit.Position, hit.SurfaceNormal, hit.Distance,
                                                            stepInput.SkinWidth, out SurfaceConstraintInfo newConstraint);

                                    // Resolve its penetration
                                    ResolveConstraintPenetration(ref newConstraint);

                                    // Write back
                                    constraints[constraintIndex] = newConstraint;
                                }

                                found = true;
                                break;
                            }
                        }

                        // Add penetrating hit not caught by collider cast
                        if (!found)
                        {
                            CreateConstraint(stepInput.World, stepInput.Up,
                                             hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal, hit.Distance,
                                             stepInput.SkinWidth, maxSlopeCos, ref constraints);
                        }
                    }
                }
            }

            // Min delta time for solver to break
            float minDeltaTime = 0.0f;
            if (math.lengthsq(newVelocity) > k_SimplexSolverEpsilonSq)
            {
                // Min delta time to travel at least 1cm
                minDeltaTime = 0.01f / math.length(newVelocity);
            }

            // Solve
            float3 prevVelocity = newVelocity;
            float3 prevPosition = newPosition;
            SimplexSolver.Solve(remainingTime, minDeltaTime, up, stepInput.MaxMovementSpeed, constraints, ref newPosition, ref newVelocity, out float integratedTime);

            // Apply impulses to hit bodies
            if (affectBodies)
            {
                CalculateAndStoreDeferredImpulses(stepInput, characterMass, prevVelocity, ref constraints, ref deferredImpulseWriter);
            }

            // Calculate new displacement
            float3 newDisplacement = newPosition - prevPosition;

            // If simplex solver moved the character we need to re-cast to make sure it can move to new position
            if (math.lengthsq(newDisplacement) > k_SimplexSolverEpsilon)
            {
                // Check if we can walk to the position simplex solver has suggested
                var newCollector = new CharacterControllerClosestHitCollector <ColliderCastHit>(constraints, world, stepInput.RigidBodyIndex, 1.0f);

                ColliderCastInput input = new ColliderCastInput()
                {
                    Collider    = collider,
                    Orientation = orientation,
                    Start       = prevPosition,
                    End         = prevPosition + newDisplacement
                };

                world.CastCollider(input, ref newCollector);

                if (newCollector.NumHits > 0)
                {
                    ColliderCastHit hit = newCollector.ClosestHit;

                    // Move character along the newDisplacement direction until it reaches this new contact
                    {
                        Assert.IsTrue(hit.Fraction >= 0.0f && hit.Fraction <= 1.0f);

                        integratedTime *= hit.Fraction;
                        newPosition     = prevPosition + newDisplacement * hit.Fraction;
                    }
                }
            }

            // Reduce remaining time
            remainingTime -= integratedTime;

            // Write back position so that the distance query will update results
            transform.pos = newPosition;
        }

        // Write back final velocity
        linearVelocity = newVelocity;
    }
示例#19
0
        public static void ItemAttachToOwner1(EntityManager entityManager, Entity item,
                                              Entity owner, Entity preOwner, float3 pos, quaternion rot)
        {
            FSLog.Info($"ItemAttachToOwner,owner:{owner},preOnwer:{preOwner}");
            var triggerState = entityManager.GetComponentData <TriggerPredictedState>(item);

            triggerState.TriggeredEntity = Entity.Null;
            triggerState.IsAllowTrigger  = false;
            entityManager.SetComponentData(item, triggerState);

            var ownerPredictedState = entityManager.GetComponentData <OwnerPredictedState>(item);

            ownerPredictedState.Owner    = owner;
            ownerPredictedState.PreOwner = preOwner;
            entityManager.SetComponentData(item, ownerPredictedState);


            var transformPredictedState = entityManager.GetComponentData <TransformPredictedState>(item);

            transformPredictedState.Position = pos;
            transformPredictedState.Rotation = rot;

            entityManager.SetComponentData(item, transformPredictedState);

            var velocityPredictedState = entityManager.GetComponentData <VelocityPredictedState>(item);

            velocityPredictedState.Angular    = float3.zero;
            velocityPredictedState.Linear     = float3.zero;
            velocityPredictedState.MotionType = MotionType.Static;
            entityManager.SetComponentData(item, velocityPredictedState);

            if (entityManager.HasComponent <FlyingPredictedState>(item))
            {
                var flyingPredictedState = entityManager.GetComponentData <FlyingPredictedState>(item);
                flyingPredictedState.IsFlying = false;
                entityManager.SetComponentData(item, flyingPredictedState);
            }
        }
示例#20
0
    public static unsafe void CollideAndIntegrate(PhysicsWorld world, float deltaTime,
                                                  int maxIterations, float3 up, float3 gravity,
                                                  float characterMass, float tau, float damping, float maxSlope, bool affectBodies, Collider *collider,
                                                  ref NativeArray <DistanceHit> distanceHits, ref NativeArray <ColliderCastHit> castHits, ref NativeArray <SurfaceConstraintInfo> constraints,
                                                  ref RigidTransform transform, ref float3 linearVelocity, ref BlockStream.Writer deferredImpulseWriter)
    {
        float  remainingTime    = deltaTime;
        float3 lastDisplacement = linearVelocity * remainingTime;

        float3     newPosition = transform.pos;
        quaternion orientation = transform.rot;
        float3     newVelocity = linearVelocity;

        float maxSlopeCos = math.cos(maxSlope);

        const float timeEpsilon = 0.000001f;

        for (int i = 0; i < maxIterations && remainingTime > timeEpsilon; i++)
        {
            // First do distance query for penetration recovery
            MaxHitsCollector <DistanceHit> distanceHitsCollector = new MaxHitsCollector <DistanceHit>(0.0f, ref distanceHits);
            int numConstraints = 0;
            {
                ColliderDistanceInput input = new ColliderDistanceInput()
                {
                    MaxDistance = 0.0f,
                    Transform   = new RigidTransform
                    {
                        pos = newPosition,
                        rot = orientation,
                    },
                    Collider = collider
                };
                world.CalculateDistance(input, ref distanceHitsCollector);

                // Iterate over hits and create constraints from them
                for (int hitIndex = 0; hitIndex < distanceHitsCollector.NumHits; hitIndex++)
                {
                    DistanceHit hit = distanceHitsCollector.AllHits[hitIndex];
                    CreateConstraintFromHit(world, gravity, deltaTime, hit.RigidBodyIndex, hit.ColliderKey, hit.Position,
                                            hit.SurfaceNormal, hit.Distance, false, out SurfaceConstraintInfo constraint);

                    // Potentially add a max slope constraint
                    AddMaxSlopeConstraint(up, maxSlopeCos, ref constraint, ref constraints, ref numConstraints);

                    // Add original constraint to the list
                    constraints[numConstraints++] = constraint;
                }
            }

            float3 gravityMovement = gravity * remainingTime * remainingTime * 0.5f;

            // Then do a collider cast
            {
                float3 displacement = lastDisplacement + gravityMovement;
                MaxHitsCollector <ColliderCastHit> collector = new MaxHitsCollector <ColliderCastHit>(1.0f, ref castHits);
                ColliderCastInput input = new ColliderCastInput()
                {
                    Collider    = collider,
                    Orientation = orientation,
                    Start       = newPosition,
                    End         = newPosition + displacement,
                };
                world.CastCollider(input, ref collector);

                // Iterate over hits and create constraints from them
                for (int hitIndex = 0; hitIndex < collector.NumHits; hitIndex++)
                {
                    ColliderCastHit hit = collector.AllHits[hitIndex];

                    bool found = false;
                    for (int distanceHitIndex = 0; distanceHitIndex < distanceHitsCollector.NumHits; distanceHitIndex++)
                    {
                        DistanceHit dHit = distanceHitsCollector.AllHits[distanceHitIndex];
                        if (dHit.RigidBodyIndex == hit.RigidBodyIndex &&
                            dHit.ColliderKey.Equals(hit.ColliderKey))
                        {
                            found = true;
                            break;
                        }
                    }

                    // Skip duplicate hits
                    if (!found)
                    {
                        CreateConstraintFromHit(world, gravity, deltaTime, hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal,
                                                hit.Fraction * math.length(lastDisplacement), false, out SurfaceConstraintInfo constraint);

                        // Potentially add a max slope constraint
                        AddMaxSlopeConstraint(up, maxSlopeCos, ref constraint, ref constraints, ref numConstraints);

                        // Add original constraint to the list
                        constraints[numConstraints++] = constraint;
                    }
                }
            }

            // Solve
            float3 prevVelocity = newVelocity;
            float3 prevPosition = newPosition;
            SimplexSolver.Solve(world, remainingTime, up, numConstraints, ref constraints, ref newPosition, ref newVelocity, out float integratedTime);

            // Apply impulses to hit bodies
            if (affectBodies)
            {
                ResolveContacts(world, remainingTime, gravity, tau, damping, characterMass, prevVelocity, numConstraints, ref constraints, ref deferredImpulseWriter);
            }

            float3 newDisplacement = newPosition - prevPosition;

            // Check if we can walk to the position simplex solver has suggested
            MaxHitsCollector <ColliderCastHit> newCollector = new MaxHitsCollector <ColliderCastHit>(1.0f, ref castHits);
            int newContactIndex = -1;

            // If simplex solver moved the character we need to re-cast to make sure it can move to new position
            if (math.lengthsq(newDisplacement) > SimplexSolver.c_SimplexSolverEpsilon)
            {
                float3            displacement = newDisplacement + gravityMovement;
                ColliderCastInput input        = new ColliderCastInput()
                {
                    Collider    = collider,
                    Orientation = orientation,
                    Start       = prevPosition,
                    End         = prevPosition + displacement
                };

                world.CastCollider(input, ref newCollector);

                for (int hitIndex = 0; hitIndex < newCollector.NumHits; hitIndex++)
                {
                    ColliderCastHit hit = newCollector.AllHits[hitIndex];

                    bool found = false;
                    for (int constraintIndex = 0; constraintIndex < numConstraints; constraintIndex++)
                    {
                        SurfaceConstraintInfo constraint = constraints[constraintIndex];
                        if (constraint.RigidBodyIndex == hit.RigidBodyIndex &&
                            constraint.ColliderKey.Equals(hit.ColliderKey))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        newContactIndex = hitIndex;
                        break;
                    }
                }
            }

            // Move character along the newDisplacement direction until it reaches this new contact
            if (newContactIndex >= 0)
            {
                ColliderCastHit newContact = newCollector.AllHits[newContactIndex];

                float fraction = newContact.Fraction / math.length(newDisplacement);
                integratedTime *= fraction;

                float3 displacement = newDisplacement * fraction;
                newPosition = prevPosition + displacement;
            }

            remainingTime -= integratedTime;

            // Remember last displacement for next iteration
            lastDisplacement = newVelocity * remainingTime;
        }

        // Write back position and velocity
        transform.pos  = newPosition;
        linearVelocity = newVelocity;
    }
示例#21
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                data.ProfilerMarker.Begin();
                var output = ctx.Resolve(ref ports.Output);

                output.CopyFrom(ctx.Resolve(in ports.Input));

                var weightValue = ctx.Resolve(ports.Weight);

                if (weightValue > 0f)
                {
                    var stream = AnimationStreamProvider.Create(data.RigDefinition, output);
                    if (stream.IsNull)
                    {
                        data.ProfilerMarker.End();
                        return;
                    }

                    // Use the curve value if defined
                    if (data.IKData.WeightChannelIdx != -1)
                    {
                        weightValue *= stream.GetFloat(data.IKData.WeightChannelIdx);
                    }

                    weightValue = math.clamp(weightValue, 0f, 1f);

                    var targetPositionWeightValue = ctx.Resolve(ports.TargetPositionWeight);
                    var targetRotationWeightValue = ctx.Resolve(ports.TargetRotationWeight);
                    var hintWeightValue           = ctx.Resolve(ports.HintWeight);

                    float3 aPos = stream.GetLocalToRigTranslation(data.IKData.Root);
                    float3 bPos = stream.GetLocalToRigTranslation(data.IKData.Mid);
                    float3 cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);

                    stream.GetLocalToRigTR(data.IKData.Target, out float3 targetPos, out quaternion targetRot);
                    float3     tPos       = math.lerp(cPos, targetPos + data.IKData.TargetOffset.pos, targetPositionWeightValue * weightValue);
                    quaternion tRot       = math.nlerp(stream.GetLocalToRigRotation(data.IKData.Tip), math.mul(targetRot, data.IKData.TargetOffset.rot), targetRotationWeightValue * weightValue);
                    float      hintWeight = hintWeightValue * weightValue;
                    bool       hasHint    = data.IKData.Hint > -1 && hintWeight > 0f;

                    float3 ab = bPos - aPos;
                    float3 bc = cPos - bPos;
                    float3 ac = cPos - aPos;
                    float3 at = tPos - aPos;

                    float oldAbcAngle = TriangleAngle(math.length(ac), data.IKData.LimbLengths);
                    float newAbcAngle = TriangleAngle(math.length(at), data.IKData.LimbLengths);

                    // Bend normal strategy is to take whatever has been provided in the animation
                    // stream to minimize configuration changes, however if this is collinear
                    // try computing a bend normal given the desired target position.
                    // If this also fails, try resolving axis using hint if provided.
                    float3 axis = math.cross(ab, bc);
                    if (math.lengthsq(axis) < k_SqEpsilon)
                    {
                        axis = math.cross(at, bc);
                        if (math.lengthsq(axis) < k_SqEpsilon)
                        {
                            axis = hasHint ? math.cross(stream.GetLocalToRigTranslation(data.IKData.Hint) - aPos, bc) : math.up();
                        }
                    }
                    axis = math.normalize(axis);

                    float      a        = 0.5f * (oldAbcAngle - newAbcAngle);
                    float      sin      = math.sin(a);
                    float      cos      = math.cos(a);
                    quaternion deltaRot = new quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos);
                    stream.SetLocalToRigRotation(data.IKData.Mid, math.mul(deltaRot, stream.GetLocalToRigRotation(data.IKData.Mid)));

                    cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);
                    ac   = cPos - aPos;
                    stream.SetLocalToRigRotation(data.IKData.Root, math.mul(mathex.fromTo(ac, at), stream.GetLocalToRigRotation(data.IKData.Root)));

                    if (hasHint)
                    {
                        float acLengthSq = math.lengthsq(ac);
                        if (acLengthSq > 0f)
                        {
                            bPos = stream.GetLocalToRigTranslation(data.IKData.Mid);
                            cPos = stream.GetLocalToRigTranslation(data.IKData.Tip);
                            ab   = bPos - aPos;
                            ac   = cPos - aPos;

                            float3 acNorm = ac / math.sqrt(acLengthSq);
                            float3 ah     = stream.GetLocalToRigTranslation(data.IKData.Hint) - aPos;
                            float3 abProj = ab - acNorm * math.dot(ab, acNorm);
                            float3 ahProj = ah - acNorm * math.dot(ah, acNorm);

                            float maxReach = data.IKData.LimbLengths.x + data.IKData.LimbLengths.y;
                            if (math.lengthsq(abProj) > (maxReach * maxReach * 0.001f) && math.lengthsq(ahProj) > 0f)
                            {
                                quaternion hintRot = mathex.fromTo(abProj, ahProj);
                                hintRot.value.xyz *= hintWeight;
                                stream.SetLocalToRigRotation(data.IKData.Root, math.mul(hintRot, stream.GetLocalToRigRotation(data.IKData.Root)));
                            }
                        }
                    }

                    stream.SetLocalToRigRotation(data.IKData.Tip, tRot);
                }

                data.ProfilerMarker.End();
            }
示例#22
0
        private void F(PhysicsScene physicsScene, float deltaTime, Transform root, Rigidbody rigidbody, Transform wheel,
                       Vehicle vehicle)
        {
            WheelBaseConfigAuthoring wbc = wheel.GetComponent <WheelBaseConfigAuthoring>();
            WheelBaseInfoAuthoring   wbi = wheel.GetComponent <WheelBaseInfoAuthoring>();

            float drift = 0F;

            wbi.MaxLength = wbc.RestLength + wbc.SpringTravel;
            wbi.MinLength = wbc.RestLength - wbc.SpringTravel;

            RaycastInput input = new RaycastInput
            {
                Start = wheel.position,
                End   = root.transform.up * -1,
            };

            // Debug.DrawRay(input.Start, input.End * wbi.MaxLength, Color.red);
            if (!physicsScene.Raycast(input.Start, input.End, out var hit, wbi.MaxLength, wbc.layerMask))
            {
                return;
            }

            wbi.LastLength     = wbi.SpringLength;
            wbi.SpringLength   = hit.distance;
            wbi.SpringLength   = math.clamp(wbi.SpringLength, wbi.MinLength, wbi.MaxLength);
            wbi.SpringVelocity = (wbi.LastLength - wbi.SpringLength) / deltaTime;

            wbi.SpringForce     = wbc.SpringStiffness * (wbc.RestLength - wbi.SpringLength);
            wbi.DamperForce     = wbc.DamperStiffness * wbi.SpringVelocity;
            wbi.SuspensionForce = (wbi.SpringForce + wbi.DamperForce) * rigidbody.transform.up;

            rigidbody.AddForceAtPosition(wbi.SuspensionForce, wheel.position);

            //=========================================================================================================
            quaternion rootRotation = root.rotation;

            var up      = math.mul(rootRotation, new float3(0, 1, 0));
            var forward = math.mul(rootRotation, new float3(0, 0, 1));

            var v = vehicle.vehicleInput.v;

            rigidbody.AddForceAtPosition(forward * (1000F) * v,
                                         hit.point + (wheel.position - hit.point) / 4f);

            var h = vehicle.vehicleInput.h;

            rigidbody.AddTorque(h * up * vehicle.turn);

            var linearVelocity  = rigidbody.velocity;
            var angularVelocity = rigidbody.angularVelocity;

            float3 localAngleVelocity = root.InverseTransformVector(angularVelocity);

            localAngleVelocity.y *= 0.9f + (drift / 10);
            angularVelocity       = root.TransformVector(localAngleVelocity);

            Vector3 localVelocity = root.InverseTransformVector(linearVelocity);

            localVelocity.x *= 0.9f + (drift / 10);
            linearVelocity   = root.TransformVector(localVelocity);

            rigidbody.velocity        = linearVelocity;
            rigidbody.angularVelocity = angularVelocity;
        }
示例#23
0
 void GetAxisAngle(quaternion q, out float3 axis, out float angle)
 {
     angle = 2 * math.acos(q.value.w);
     axis  = math.normalize(q.value.xyz);
 }
        public quaternion4(quaternion q0, quaternion q1, quaternion q2, quaternion q3)
        {
            var m = mathex.transpose(math.float4x4(q0.value, q1.value, q2.value, q3.value));

            x = m.c0; y = m.c1; z = m.c2; w = m.c3;
        }
 public void SetRotationValue(quaternion q, GhostSerializerState serializerState)
 {
     SetRotationValue(q);
 }
 public static quaternion4 quaternion4(quaternion q1, quaternion q2, quaternion q3, quaternion q4)
 {
     return(new quaternion4(q1, q2, q3, q4));
 }
示例#27
0
            // パーティクルごと
            public void Execute(int index)
            {
                var flag = flagList[index];

                if (flag.IsValid() == false)
                {
                    return;
                }

                // チームデータ
                int teamId   = teamIdList[index];
                var teamData = teamDataList[teamId];

                float3     viewPos = 0;
                quaternion viewRot = quaternion.identity;

                var basePos = basePosList[index];
                var baseRot = baseRotList[index];

                if (flag.IsFixed() == false)
                {
                    // 未来予測
                    // 1フレーム前の表示位置と将来の予測位置を、現在のフレーム位置で線形補間する
                    var   futurePos  = oldPosList[index] + velocityList[index] * updateIntervalTime;
                    var   oldViewPos = oldSlowPosList[index];
                    float oldTime    = teamData.time - teamData.addTime;
                    float futureTime = teamData.time + (updateIntervalTime - teamData.nowTime);
                    float interval   = futureTime - oldTime;
                    float ratio      = teamData.addTime / interval;

                    // todo: 未来予測を切る
                    //futurePos = oldPosList[index];


                    viewPos = math.lerp(oldViewPos, futurePos, ratio);
                    viewRot = oldRotList[index];

                    oldSlowPosList[index] = viewPos;
                }
                else
                {
                    // 固定パーティクルの表示位置は常にベース位置
                    viewPos = basePos;
                    viewRot = baseRot;

                    // 固定パーティクルは今回のbasePosを記録する
                    oldPosList[index] = viewPos;
                    oldRotList[index] = viewRot;
                }

                // ブレンド
                if (teamData.blendRatio < 0.99f)
                {
                    viewPos = math.lerp(basePos, viewPos, teamData.blendRatio);
                    viewRot = math.slerp(baseRot, viewRot, teamData.blendRatio);
                    viewRot = math.normalize(viewRot); // 回転蓄積で精度が落ちていくので正規化しておく
                }

                // 表示位置
                posList[index] = viewPos;
                rotList[index] = viewRot;
            }
 public MTransform(quaternion rotation, float3 translation)
 {
     Rotation    = new float3x3(rotation);
     Translation = translation;
 }
示例#29
0
 /// <summary>
 /// fromからtoへ回転させるクォータニオンを返します
 /// </summary>
 /// <param name="from"></param>
 /// <param name="to"></param>
 /// <param name="t">補間率(0.0-1.0)</param>
 /// <returns></returns>
 public static quaternion FromToRotation(quaternion from, quaternion to, float t = 1.0f)
 {
     return(FromToRotation(math.forward(from), math.forward(to), t));
 }
示例#30
0
        public void TestBoxColliderCreateInvalid()
        {
            float3     center       = new float3(1.0f, 0.0f, 0.0f);
            quaternion orientation  = quaternion.AxisAngle(math.normalize(new float3(4.3f, 1.2f, 0.1f)), 1085.0f);
            float3     size         = new float3(1.0f, 2.0f, 3.0f);
            float      convexRadius = 0.45f;

            // Invalid center, positive infinity
            {
                float3 invalidCenter = new float3(float.PositiveInfinity, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(invalidCenter, orientation, size, convexRadius)
                    );
            }

            // Invalid center, positive infinity
            {
                float3 invalidCenter = new float3(float.NegativeInfinity, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(invalidCenter, orientation, size, convexRadius)
                    );
            }

            // Invalid center, nan
            {
                float3 invalidCenter = new float3(float.NaN, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(invalidCenter, orientation, size, convexRadius)
                    );
            }

            // Negative size
            {
                float3 invalidSize = new float3(-1.0f, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, invalidSize, convexRadius)
                    );
            }

            // Invalid size, positive inf
            {
                float3 invalidSize = new float3(float.PositiveInfinity, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, invalidSize, convexRadius)
                    );
            }

            // Invalid size, negative inf
            {
                float3 invalidSize = new float3(float.NegativeInfinity, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, invalidSize, convexRadius)
                    );
            }

            // Invalid size, nan
            {
                float3 invalidSize = new float3(float.NaN, 1.0f, 1.0f);
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, invalidSize, convexRadius)
                    );
            }

            // Negative convex radius
            {
                float invalidConvexRadius = -0.0001f;
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, size, invalidConvexRadius)
                    );
            }

            // Invalid convex radius, +inf
            {
                float invalidConvexRadius = float.PositiveInfinity;
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, size, invalidConvexRadius)
                    );
            }

            // Invalid convex radius, -inf
            {
                float invalidConvexRadius = float.NegativeInfinity;
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, size, invalidConvexRadius)
                    );
            }

            // Invalid convex radius, nan
            {
                float invalidConvexRadius = float.NaN;
                TestUtils.ThrowsException <System.ArgumentException>(
                    () => BoxCollider.Create(center, orientation, size, invalidConvexRadius)
                    );
            }
        }