// 読み込みボーンごと
            public void Execute(int index, TransformAccess transform)
            {
                float3     pos    = transform.position;
                quaternion rot    = transform.rotation;
                var        oldPos = basePosList[index];
                var        oldRot = baseRotList[index];

                if (oldPos.y < -900000)
                {
                    // リセット
                    basePosList[index] = pos;
                    baseRotList[index] = rot;

                    bonePosList[index] = pos;
                    boneRotList[index] = rot;
                }
                else
                {
                    // 前回からの速度から未来予測の更新量を求める
                    var velocityPos = (pos - oldPos) * ratio;
                    var velocityRot = MathUtility.FromToRotation(oldRot, rot, ratio);

                    basePosList[index] = pos;
                    baseRotList[index] = rot;

                    // 未来予測
                    pos += velocityPos;
                    rot  = math.mul(velocityRot, rot);

                    bonePosList[index] = pos;
                    boneRotList[index] = rot;
                }
            }
            // 読み込みボーンごと
            public void Execute(int index, TransformAccess transform)
            {
                float3     pos    = transform.position;
                quaternion rot    = transform.rotation;
                var        oldPos = basePosList[index];
                var        oldRot = baseRotList[index];

                if (oldPos.y < -900000)
                {
                    // リセット
                    basePosList[index] = pos;
                    baseRotList[index] = rot;

                    bonePosList[index] = pos;
                    boneRotList[index] = rot;
                }
                else
                {
                    // 前回からの速度から未来予測の更新量を求める
                    var velocityPos = (pos - oldPos) * ratio;
                    var velocityRot = MathUtility.FromToRotation(oldRot, rot, ratio);

                    basePosList[index] = pos;
                    baseRotList[index] = rot;

                    // 未来予測
                    pos += velocityPos;
                    rot  = math.mul(velocityRot, rot);

                    bonePosList[index] = pos;
                    boneRotList[index] = rot;
                }

#if !(UNITY_2018 || UNITY_2019_1 || UNITY_2019_2_1 || UNITY_2019_2_2 || UNITY_2019_2_3 || UNITY_2019_2_4 || UNITY_2019_2_5 || UNITY_2019_2_6 || UNITY_2019_2_7 || UNITY_2019_2_8 || UNITY_2019_2_9 || UNITY_2019_2_10 || UNITY_2019_2_11 || UNITY_2019_2_12 || UNITY_2019_2_13)
                // lossyScale取得(現在はUnity2019.2.14以上のみ)
                // マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価)
                float4x4 m    = transform.localToWorldMatrix;
                var      irot = math.inverse(rot);
                var      m2   = math.mul(new float4x4(irot, float3.zero), m);
                var      scl  = new float3(m2.c0.x, m2.c1.y, m2.c2.z);
                boneSclList[index] = scl;
#endif
            }
Beispiel #3
0
            // チームデータごと
            public void Execute(int teamId)
            {
                var tdata = teamData[teamId];

                if (tdata.IsActive() == false || tdata.boneIndex < 0)
                {
                    tdata.updateCount = 0;
                    tdata.runCount    = 0;
                    teamData[teamId]  = tdata;
                    return;
                }

                // ワールド移動影響
                WorldInfluence wdata = teamWorldInfluenceList[teamId];
                var            bpos  = bonePosList[tdata.boneIndex];
                var            brot  = boneRotList[tdata.boneIndex];

                // 移動量算出
                float3     movePos = bpos - wdata.oldPosition;
                quaternion moveRot = MathUtility.FromToRotation(wdata.oldRotation, brot);

                wdata.moveOffset     = movePos;
                wdata.rotationOffset = moveRot;

                // テレポート判定
                if (wdata.resetTeleport == 1)
                {
                    if (math.length(movePos) >= wdata.teleportDistance || math.degrees(MathUtility.Angle(moveRot)) >= wdata.teleportRotation)
                    {
                        tdata.SetFlag(Flag_Reset_WorldInfluence, true);
                        tdata.SetFlag(Flag_Reset_Position, true);
                    }
                }

                bool reset = false;

                if (tdata.IsFlag(Flag_Reset_WorldInfluence) || tdata.IsFlag(Flag_Reset_Position))
                {
                    // リセット
                    wdata.moveOffset     = 0;
                    wdata.rotationOffset = quaternion.identity;
                    wdata.oldPosition    = bpos;
                    wdata.oldRotation    = brot;

                    // チームタイムリセット(強制更新)
                    tdata.nowTime = updateDeltaTime;

                    reset = true;
                }
                wdata.nowPosition = bpos;
                wdata.nowRotation = brot;


                // 時間更新(タイムスケール対応)
                // チームごとに固有の時間で動作する
                tdata.updateCount = 0;
                tdata.runCount    = 0;
                float timeScale = tdata.timeScale * globalTimeScale;
                float addTime   = dtime * timeScale;

                tdata.time   += addTime;
                tdata.addTime = addTime;

                // 時間ステップ
                float nowTime = tdata.nowTime + addTime;

                while (nowTime >= updateDeltaTime)
                {
                    nowTime -= updateDeltaTime;
                    tdata.updateCount++;
                }

                // リセットフラグがONならば最低1回更新とする
                if (reset)
                {
                    tdata.updateCount = Mathf.Max(tdata.updateCount, 1);
                }

                // 最大実行回数
                //tdata.updateCount = math.min(tdata.updateCount, ups / 30);
                tdata.updateCount = math.min(tdata.updateCount, maxUpdateCount);

                tdata.nowTime = nowTime;

                // スタート時間(最初の物理更新が実行される時間)
                tdata.startTime = tdata.time - nowTime - updateDeltaTime * (tdata.updateCount - 1);

                // 補間再生判定
                if (timeScale < 0.99f || unityTimeScale < 0.99f)
                {
                    tdata.SetFlag(Flag_Interpolate, true);
                }
                else
                {
                    tdata.SetFlag(Flag_Interpolate, false);
                }

                // リセットフラグOFF
                tdata.SetFlag(Flag_Reset_WorldInfluence, false);

                // 風
                Wind(ref tdata, bpos);

                // 書き戻し
                teamData[teamId] = tdata;
                teamWorldInfluenceList[teamId] = wdata;
            }
Beispiel #4
0
            // パーティクルごと
            public void Execute(int index)
            {
                // 初期化コピー
                var nextpos = nextPosList[index];

                outNextPosList[index] = nextpos;

                var flag = flagList[index];

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

                // チーム
                var team = teamDataList[teamIdList[index]];

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

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

                int pstart = team.particleChunk.startIndex;
                int vindex = index - pstart;

                // クロスごとの拘束データ
                var gdata = groupList[team.restoreRotationGroupIndex];

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

                // 参照情報
                var refdata = refDataList[gdata.refChunk.startIndex + vindex];

                if (refdata.count > 0)
                {
                    // power
                    float depth     = depthList[index];
                    float dataPower = gdata.restorePower.Evaluate(depth);

                    // 補間力
                    // 90ups基準
                    float power = 1.0f - math.pow(1.0f - dataPower, updatePower);

                    float3 addpos = 0;

                    // 自身の基準位置
                    //float3 bpos = basePosList[index];

                    int dataIndex = gdata.dataChunk.startIndex + refdata.startIndex;
                    for (int i = 0; i < refdata.count; i++, dataIndex++)
                    {
                        var data = dataList[dataIndex];

                        if (data.IsValid() == false)
                        {
                            continue;
                        }

                        // 親
                        int        pindex = pstart + data.targetVertexIndex;
                        quaternion prot   = baseRotList[pindex]; // 常に本来の回転から算出する
                        var        ppos   = nextPosList[pindex]; // 位置は現在の親の位置
                        //float3 pbpos = basePosList[pindex];
                        //var ppos = nextPosList[pindex];

                        // 本来の方向ベクトル
                        //float3 tv = math.mul(prot, data.localPos); // v1.7.0
                        float3 tv = math.mul(prot, data.localPos * team.scaleDirection); // マイナススケール対応(v1.7.6)
                        //float3 tv = bpos - pbpos;

                        // 現在ベクトル
                        float3 v = nextpos - ppos;

                        // 球面線形補間
                        var q = MathUtility.FromToRotation(v, tv, power);
                        v = math.mul(q, v);
                        float3 gpos = ppos + v;

                        // 加算位置
                        addpos += gpos - nextpos;
                    }

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

                    var opos = nextpos;
                    nextpos += addpos / refdata.count;

                    // 書き出し
                    outNextPosList[index] = nextpos;

                    // 速度影響
                    var av = (nextpos - opos) * (1.0f - gdata.velocityInfluence);
                    posList[index] = posList[index] + av;
                }
            }
Beispiel #5
0
            // ルートラインごと
            public void Execute(int rootIndex)
            {
                // チーム
                int teamIndex = rootTeamList[rootIndex];

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

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

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

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

                if (dataCount <= 1)
                {
                    return;
                }

                for (int i = 0; i < dataCount; i++)
                {
                    var data = dataList[dataIndex + i];

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

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

                    // 自身の現在姿勢
                    var pos = posList[pindex];
                    var rot = rotList[pindex];

                    // 子の回転調整
                    if (data.childCount > 0)
                    {
                        // 子への平均ベクトル
                        float3 ctv = 0;
                        float3 cv  = 0;

                        for (int j = 0; j < data.childCount; j++)
                        {
                            var cdata  = dataList[data.childStartDataIndex + dstart + j];
                            int cindex = cdata.vertexIndex + pstart;

                            // 子の現在姿勢
                            var cpos = posList[cindex];

                            // 子の本来のベクトル
                            float3 tv = math.normalize(math.mul(rot, cdata.localPos));
                            ctv += tv;

                            // 子の現在ベクトル
                            float3 v = math.normalize(cpos - pos);
                            cv += v;

                            // 回転
                            var q = MathUtility.FromToRotation(tv, v);

                            // 子の姿勢確定
                            var crot = math.mul(rot, cdata.localRot);
                            crot            = math.mul(q, crot);
                            rotList[cindex] = crot;
                        }

                        // 固定は回転させない判定(v1.5.2)
                        if (team.IsFlag(PhysicsManagerTeamData.Flag_FixedNonRotation) && flag.IsKinematic())
                        {
                            continue;
                        }

                        // 子の移動方向変化に伴う回転調整
                        var cq = MathUtility.FromToRotation(ctv, cv);

                        // 回転補間
                        if (gdata.avarage == 1)
                        {
                            cq = math.slerp(quaternion.identity, cq, 0.5f); // 50%
                        }

                        rot             = math.mul(cq, rot);
                        rotList[pindex] = math.normalize(rot); // 正規化しないとエラーになる場合がある
                    }
                }
            }
Beispiel #6
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, localPos);
                    //float3 tv = math.mul(prot, data.localPos); // v1.7.0
                    float3 tv = math.mul(prot, data.localPos * team.scaleDirection); // マイナススケール対応(v1.7.6)

                    // ベクトル長
                    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);
                            MathUtility.ClampAngle(v, tv, maxAngle, out v);
                        }

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

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

                        // debug
                        //var ln = math.length(mv);
                        //if (ln >= maxMoveLength)
                        //    Debug.Log($"mv={ln}");

                        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;

                        // 現在ベクトル更新(v1.8.0)
                        v = math.normalize(npos - ppos);

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

                    // 回転補正
                    //nrot = math.mul(prot, localRot);
                    //nrot = math.mul(prot, data.localRot); // v1.7.0
                    nrot = math.mul(prot, new quaternion(data.localRot.value * team.quaternionScale)); // マイナススケール対応(v1.7.6)
                    var q = MathUtility.FromToRotation(tv, v);
                    nrot = math.mul(q, nrot);

                    nextRotList[index] = nrot;
                }
            }
Beispiel #7
0
            // チームデータごと
            public void Execute(int teamId)
            {
                var tdata = teamData[teamId];

                // グローバルチーム判定
                bool isGlobal = teamId == 0;

                if (tdata.IsActive() == false || (isGlobal == false && tdata.boneIndex < 0))
                {
                    tdata.updateCount = 0;
                    tdata.runCount    = 0;
                    teamData[teamId]  = tdata;
                    return;
                }

                if (isGlobal)
                {
                    // グローバルチーム
                    // 時間更新(タイムスケール対応)
                    UpdateTime(ref tdata, false);
                }
                else
                {
                    // チームボーン情報
                    var bpos = bonePosList[tdata.boneIndex];
                    var brot = boneRotList[tdata.boneIndex];
                    var bscl = boneSclList[tdata.boneIndex];

                    // チームスケール倍率算出
                    if (tdata.initScale.x > 0.0f)
                    {
                        tdata.scaleRatio = math.length(bscl) / math.length(tdata.initScale);
                    }

                    // マイナススケール対応
                    tdata.scaleDirection = math.sign(bscl);
                    if (bscl.x < 0 || bscl.y < 0 || bscl.z < 0)
                    {
                        tdata.quaternionScale = new float4(-math.sign(bscl), 1);
                    }
                    else
                    {
                        tdata.quaternionScale = 1;
                    }

                    // ワールド移動影響
                    WorldInfluence wdata = teamWorldInfluenceList[teamId];

                    // 移動量算出
                    float3     moveVector = bpos - wdata.oldPosition;
                    quaternion moveRot    = MathUtility.FromToRotation(wdata.oldRotation, brot);

                    // 移動影響(無視する移動量+考慮する移動量)
                    var moveLen = math.length(moveVector);
                    if (moveLen > 1e-06f)
                    {
                        float speed = moveLen / dtime;

                        //const float maxspeed = 10.0f; // todo:最大速度テスト m/s
                        float ratio = math.max(speed - wdata.maxMoveSpeed, 0.0f) / speed;
                        wdata.moveIgnoreOffset = moveVector * ratio;
                        wdata.moveOffset       = moveVector - wdata.moveIgnoreOffset;
                    }
                    else
                    {
                        wdata.moveIgnoreOffset = 0;
                        wdata.moveOffset       = 0;
                    }

                    // 回転影響
                    wdata.rotationOffset = moveRot;

                    // 速度ウエイト更新
                    if (tdata.velocityWeight < 1.0f)
                    {
                        float addw = tdata.velocityRecoverySpeed > 1e-6f ? dtime / tdata.velocityRecoverySpeed : 1.0f;
                        tdata.velocityWeight = math.saturate(tdata.velocityWeight + addw);
                    }

                    // テレポート判定
                    if (wdata.resetTeleport == 1)
                    {
                        // テレポート距離はチームスケールを乗算する
                        if (moveLen >= wdata.teleportDistance * tdata.scaleRatio || math.degrees(MathUtility.Angle(moveRot)) >= wdata.teleportRotation)
                        {
                            tdata.SetFlag(Flag_Reset_WorldInfluence, true);
                            tdata.SetFlag(Flag_Reset_Position, true);
                        }
                    }

                    bool reset = false;
                    if (tdata.IsFlag(Flag_Reset_WorldInfluence) || tdata.IsFlag(Flag_Reset_Position))
                    {
                        // リセット
                        wdata.moveOffset       = 0;
                        wdata.moveIgnoreOffset = 0;
                        wdata.rotationOffset   = quaternion.identity;
                        wdata.oldPosition      = bpos;
                        wdata.oldRotation      = brot;

                        // チームタイムリセット(強制更新)
                        tdata.nowTime = updateDeltaTime;

                        // 速度ウエイト
                        tdata.velocityWeight        = wdata.stabilizationTime > 1e-6f ? 0.0f : 1.0f;
                        tdata.velocityRecoverySpeed = wdata.stabilizationTime;
                        reset = true;
                    }
                    wdata.nowPosition = bpos;
                    wdata.nowRotation = brot;

                    // 書き戻し
                    teamWorldInfluenceList[teamId] = wdata;

                    // 時間更新(タイムスケール対応)
                    UpdateTime(ref tdata, reset);

                    // リセットフラグOFF
                    tdata.SetFlag(Flag_Reset_WorldInfluence, false);

                    // 風
                    Wind(ref tdata, bpos);
                }

                // 書き戻し
                teamData[teamId] = tdata;
            }
            // パーティクルごと
            public void Execute(int index)
            {
                // 初期化コピー
                var nextpos = nextPosList[index];

                outNextPosList[index] = nextpos;

                var flag = flagList[index];

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

                // チーム
                var team = teamDataList[teamIdList[index]];

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

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

                int pstart = team.particleChunk.startIndex;
                int vindex = index - pstart;

                // クロスごとの拘束データ
                var gdata = groupList[team.restoreRotationGroupIndex];

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

                // 参照情報
                var refdata = refDataList[gdata.refChunk.startIndex + vindex];

                if (refdata.count > 0)
                {
                    // power
                    float depth     = depthList[index];
                    float dataPower = gdata.restorePower.Evaluate(depth);

                    // 補間力
                    // 90ups基準
                    float power = 1.0f - math.pow(1.0f - dataPower, updatePower);

                    float3 addpos = 0;

                    // 自身の基準位置
                    float3 bpos = basePosList[index];

                    int dataIndex = gdata.dataChunk.startIndex + refdata.startIndex;
                    for (int i = 0; i < refdata.count; i++, dataIndex++)
                    {
                        var data = dataList[dataIndex];

                        if (data.IsValid() == false)
                        {
                            continue;
                        }

                        // 親
                        int    pindex = pstart + data.targetVertexIndex;
                        float3 pbpos  = basePosList[pindex];
                        var    ppos   = nextPosList[pindex];

                        // 本来の方向ベクトル
                        float3 tv = bpos - pbpos;

                        // 現在ベクトル
                        float3 v = nextpos - ppos;

                        // 球面線形補間
                        var q = MathUtility.FromToRotation(v, tv, power);
                        v = math.mul(q, v);
                        float3 gpos = ppos + v;

                        // 加算位置
                        addpos += gpos - nextpos;
                    }

                    var opos = nextpos;
                    nextpos += addpos / refdata.count;

                    // 書き出し
                    outNextPosList[index] = nextpos;

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