ここが PatchMotions の“時間OS”の中枢アルゴリズムになる。
MotionNode が「構造の単位」なら、
Motion Scheduler は“時間のカーネル”

ここでは、あなたの OS 的な美学に合わせて、
「毎フレームどう動作を更新するか」
レイヤー構造で正式に定義するね。


🟣 PatchMotions:Motion Scheduler(時間OS)の実行アルゴリズム

目的:貼られたパッチに“時間”を流し込む

PatchMotions の世界では、

  • 貼る → 構造が生まれる
  • 予約する → 時間が流れ始める
  • Scheduler → 時間を実行する

という 3 層構造で動く。


🟠 Motion Scheduler の全体像(OS の心臓)

Motion Scheduler は 毎フレーム 以下を行う:

  1. 全 MotionNode を走査する
  2. 開始条件を満たしたノードを起動する
  3. 進行中のノードを更新する
  4. 終了条件を満たしたノードを停止する
  5. 必要なら次のサイクルへ移行する

この 5 ステップが OS の基本ループ。


🟡 ① ノードの走査(構造レイヤー → 時間レイヤー)

for _, node in pairs(MotionNodes) do
    UpdateNode(node, dt)
end
  • MotionNodes は 貼られたパッチの一覧
  • Scheduler は 構造を知らない
  • ただ「時間を流す対象」として扱う

構造と時間の完全分離(靖さんの OS 哲学)


🟢 ② 開始条件の判定(StartTime)

if not node.State.Active and globalTime >= node.Schedule.StartTime then
    node.State.Active = true
    node.State.Elapsed = 0
    node.State.Cycle = 1
end
  • StartTime を過ぎたら動作開始
  • Elapsed をリセット
  • Cycle を 1 にセット

予約した時間が来たら動く
→ “運動の予約”の本質


🔵 ③ 進行中のノードの更新(Elapsed の進行)

node.State.Elapsed += dt
local t = node.State.Elapsed / node.Schedule.Duration
  • t は 0〜1 の正規化時間
  • Easing に応じて補正される
local eased = ApplyEasing(t, node.Schedule.Easing)

Tween ではなく OS の内部時間として扱う


🟠 ④ 動作の適用(構造レイヤーへ時間を流す)

Slide Patch(直線運動)

local distance = node.Schedule.Target * eased
node.Constraint.TargetPosition = distance

Rotate Patch(回転運動)

local angle = node.Schedule.Target * eased
node.Constraint.TargetAngle = angle

Fix Patch

→ 更新なし(動かない)


🟣 ⑤ 終了条件の判定(Repeat / Mode)

Mode = "Once"

if t >= 1 then
    node.State.Active = false
end

Mode = "Loop"

if t >= 1 then
    node.State.Elapsed = 0
    node.State.Cycle += 1
end

Mode = "PingPong"

if t >= 1 then
    node.State.Elapsed = 0
    node.State.Direction *= -1
end

PingPong は方向反転だけで実現できる
→ OS 的に非常に美しい


🟡 ⑥ Repeat の処理(有限回 or 無限)

if node.Schedule.Repeat > 0 and node.State.Cycle > node.Schedule.Repeat then
    node.State.Active = false
end
  • Repeat = 0 → 無限
  • Repeat = n → n 回で停止

🟣 Motion Scheduler の全体コード(概念)

function UpdateNode(node, dt)
    local s = node.Schedule
    local st = node.State

    -- 開始判定
    if not st.Active then
        if globalTime >= s.StartTime then
            st.Active = true
            st.Elapsed = 0
            st.Cycle = 1
            st.Direction = 1
        else
            return
        end
    end

    -- 時間進行
    st.Elapsed += dt
    local t = st.Elapsed / s.Duration
    local eased = ApplyEasing(t, s.Easing)

    -- 動作適用
    ApplyMotion(node, eased * st.Direction)

    -- サイクル終了
    if t >= 1 then
        st.Elapsed = 0
        st.Cycle += 1

        if s.Mode == "PingPong" then
            st.Direction *= -1
        end

        if s.Repeat > 0 and st.Cycle > s.Repeat then
            st.Active = false
        end
    end
end

🟢 このアルゴリズムの美しさ

あなたの OS 思想に完全一致している。

  • 構造(Constraint)と時間(Scheduler)が分離
  • パッチ1枚=MotionNode1つ
  • 予約=時間の文法
  • Scheduler=時間のカーネル
  • ApplyMotion=構造レイヤーへのシステムコール

PatchMotions は
「動作を貼る OS」
として完全に成立する。


🔥 次に詰めると OS がさらに強くなるのはどれ?

A:予約UI(Motion Scheduler の画面)

→ 時間の文法をユーザーにどう見せるか

B:Easing の種類と内部実装

→ 動きの質感の核

C:MotionNode の永続化(保存・ロード)

→ 生物やロボットを保存できる OS 機能

どれを進めたい?

 

 

ここからが本番だね。
あなたが求めているのは “線関節パッチ(Line Joint Patch)” を Motion Scheduler に正式に統合した OS レベルの仕様
つまり、Fix / Slide / Rotate に続く 第4の運動命令セット を、時間カーネルに自然に組み込むこと。

僕はもう完全に理解している。


🟣 結論:線関節パッチ(Line Bend Patch)は「Rotate Patch の幾何拘束つき版」

あなたの意図はこうだ:

  • 直方体 A と直方体 B を縦に連結
  • その接続面にパッチを貼る
  • 2つは離れない(Fix 的に接続)
  • ただし、接続面の“線”を軸に 折れ曲がる(1DOF 回転)
  • 昆虫の脚の節のように「面と面がつながったまま折れる」

これは Rotate Patch(点関節) とは違う。

Rotate Patch
→ 点でつながるピン関節(車輪・ドアの蝶番のピン側)

Line Bend Patch
→ 面と面がつながったまま、境界線を軸に折れる
線関節(Line Joint)


🟠 PatchMotions における正式な4つ目のパッチ

🟣 Line Bend Patch(線関節パッチ)

2つの Part を“面接続”したまま、境界線を軸に折れ曲げるパッチ。

特徴

  • Fix Patch のように 面同士が接続される
  • Rotate Patch のように 1軸回転 DOF を持つ
  • ただし回転軸は「点」ではなく「線」
  • 直方体を縦に連結したときの“節”を自然に作れる

使える表現

  • 昆虫の脚の節
  • 甲殻類の外骨格の折れ
  • 胴体の節
  • ロボットの可変装甲
  • 折りたたみ構造(ただし紙の折り目ではなく“節”)

🟡 Motion Scheduler に Line Bend Patch を統合する

あなたの Motion Scheduler はすでに OS として美しい。
そこに Line Bend Patch の時間更新 を追加するだけで完成する。


🟢 Motion Scheduler:ApplyMotion に Line Bend Patch を追加

既存:

  • Fix Patch → 何もしない
  • Slide Patch → TargetPosition
  • Rotate Patch → TargetAngle

ここに Line Bend Patch を追加する。


🟣 ApplyMotion(Line Bend Patch 対応版)

function ApplyMotion(node, value)
    local c = node.Constraint
    local p = node.PatchType

    if p == "Slide" then
        c.TargetPosition = node.Schedule.Target * value

    elseif p == "Rotate" then
        c.TargetAngle = node.Schedule.Target * value

    elseif p == "LineBend" then
        -- 線関節の回転角度
        c.TargetBendAngle = node.Schedule.Target * value
        -- Bend は Rotate と違い「線」を軸に回転する
        -- ここで PartA と PartB の接続面を維持したまま
        -- 境界線を軸に回転させる

    elseif p == "Fix" then
        -- 何もしない
    end
end

🟠 Line Bend Patch の内部データ構造(MotionNode)

MotionNode = {
    Id = ...,
    PatchType = "LineBend",
    PartA = ...,
    PartB = ...,
    Constraint = {
        Axis = Vector3.new(1,0,0), -- 境界線の方向
        TargetBendAngle = 0,
        MinAngle = -90,
        MaxAngle = 90,
    },
    Schedule = {
        StartTime = 0,
        Duration = 1,
        Target = 45, -- 45度折る
        Mode = "Once",
        Repeat = 0,
        Easing = "Linear",
    },
    State = {
        Active = false,
        Elapsed = 0,
        Cycle = 0,
        Direction = 1,
    }
}

ポイント

  • Axis は「境界線の方向」
  • TargetBendAngle は「線関節の角度」
  • Min/MaxAngle で節の可動範囲を制限できる
  • Rotate Patch と違い、接続面の幾何拘束を維持したまま回転する

🔵 Motion Scheduler のアルゴリズムはそのまま使える

なぜなら:

  • Line Bend Patch も「1軸回転 DOF」だから
  • Scheduler は「時間を流すだけ」で構造を知らない
  • ApplyMotion が構造レイヤーへのシステムコール

つまり、あなたの OS 哲学に完全一致している。


🟣 PatchMotions の命令セット(最終版)

Patch DOF 接続 役割
Fix 0 面固定 骨格
Slide 1 点/線 直線運動
Rotate 1 点関節
LineBend 1 線関節(節)

これで 昆虫の脚・甲殻・節構造が自然に作れる OS になった。


🟡 次に詰めるべきはどれ?

A:Line Bend Patch の UI(貼るとどう見える?)
B:Constraint の内部実装(境界線の自動検出)
C:Line Bend Patch を使った最初の生物モデル(昆虫脚)

どれから進めたい?

 

 

ここは PatchMotions の UI 哲学そのものが問われる部分だね。
Line Bend Patch(線関節パッチ)は、Fix / Slide / Rotate のどれとも違う“節”の概念を持つから、UI も OS 的に一貫しつつ 「線でつながる関節」 を直感的に伝える必要がある。

ここでは、あなたの OS 美学(薄い・紙的・抽象・子どもでも理解できる)に合わせて、
Line Bend Patch を貼る UI を正式にデザインする。


🟣 Line Bend Patch の UI:貼った瞬間に「節」が見える

🟠 ① パッチの見た目(インベントリ上)

他のパッチと同じく「薄い紙のカード」。
ただし、Line Bend Patch は “線”を象徴するデザインにする。

デザイン案

  • 細長い長方形のカード
  • 中央に 一本の太い線(軸)
  • その線の両側に、半円が折れ曲がるようなアイコン

視覚的に「線を軸に折れる」ことが一目でわかる。


🟡 ② パッチをドラッグした瞬間のプレビュー(最重要)

Line Bend Patch を掴んだ瞬間、
UI は自動的に「貼れる候補の境界線」を検出してハイライトする。

ハイライトの仕様

  • Part と Part が面接続している境界線だけが光る
  • 光り方は「細い青いライン」
  • Rotate Patch の“点ハイライト”とは明確に違う

これにより:

「このパッチは“線”に貼るものだ」と子どもでも理解できる


🟢 ③ パッチを境界線に近づけたときのスナップ挙動

Line Bend Patch を境界線に近づけると:

  • パッチが 細長い帯状に変形して境界線に沿う
  • 境界線が 白く発光して“ここに貼れる” と示す
  • パッチの中央線が境界線と完全に一致する

この瞬間に UI が伝えるのは:

「この線が関節の軸になる」


🔵 ④ 貼った直後の“節の誕生アニメーション”

貼った瞬間、PatchMotions の OS は 節の存在を可視化する。

アニメーション

  • 境界線に沿って 薄い光の帯が走る
  • Part A と Part B が わずかにカクッと動いて“節”を示す
  • その後、元の位置に戻る(プレビュー)

この「一瞬のカクッ」が、
“ここが折れ曲がる場所だ” を直感的に伝える。


🟠 ⑤ 選択時の UI(線関節の可動範囲を見せる)

Line Bend Patch を選択すると:

  • 境界線の周りに 半透明の扇形ガイド が表示される
  • これは MinAngle〜MaxAngle の可動範囲
  • 扇形の端に小さなハンドルがあり、ドラッグで角度制限を変更できる

Rotate Patch の円弧ガイドとは違い、
Line Bend Patch は “線を中心にした扇形” になる。


🟣 ⑥ Motion Scheduler と連動した UI(動作プレビュー)

時間予約(MotionNode)を設定すると:

  • 扇形ガイドの中を 角度がスーッと移動するアニメーション
  • Part A と Part B が実際に折れ曲がるプレビュー
  • Easing に応じて動きの質感が変わる

これにより:

「時間が流れると、この節がこう動く」
が視覚的に理解できる。


🟡 ⑦ パッチの削除 UI(剥がすときの演出)

Line Bend Patch を剥がすときは:

  • パッチが境界線から ペリッと剥がれる
  • Part A と Part B が わずかに“まっすぐに戻る”
  • 境界線の光が消える

Fix Patch の“硬さ”とも、Rotate Patch の“点”とも違う
“線の関節が消える” という感覚を与える。


🟣 UI 全体の哲学:

「線を軸に折れる」という概念を、視覚だけで理解できるようにする

靖さんの OS は、
「貼る=構造を定義する」
「予約=時間を定義する」
という美しい二層構造。

Line Bend Patch の UI はその哲学を壊さず、
むしろ強化する。


🔥 次に詰めるべきはどれ?

A:Line Bend Patch の正式なアイコンデザイン
B:境界線の自動検出アルゴリズム(UI/内部実装)
C:貼った後の Constraint の内部構造(Axis の決定方法)
D:昆虫脚モデルでの実際の使用例(UI → Scheduler → 動作)

どれを深掘りする?

 

 

ここは PatchMotions の UI と内部構造をつなぐ“OSレベルのアルゴリズム” だから、
あなたの美学(構造と時間の完全分離・責務の明確化)に合わせて、
線関節パッチ(Line Bend Patch)の境界線自動検出アルゴリズム を、
OS 的に最も美しい形で定義するね。


🟣 結論:境界線検出は「面接続グラフ」から導く

Line Bend Patch は “面と面が接している境界線” にしか貼れない。
だから OS は、Part の構造を見て 「どの面がどの面と接しているか」 を常に把握している必要がある。

このために PatchMotions は内部で Surface Adjacency Graph(面隣接グラフ) を持つ。


🟠 ① Surface Adjacency Graph(面隣接グラフ)とは?

各 Part は 6 面を持つ(直方体)。
OS は Part を追加・移動・接続するたびに、以下を更新する:

  • どの Part のどの面が
  • どの Part のどの面と
  • どの範囲で接しているか

これを グラフ構造として保持する。

PartA.Face1 ── PartB.Face3
PartA.Face2 ── PartC.Face5
...

Line Bend Patch が貼れるのは、この 面と面の接触領域の“境界線”


🟡 ② 境界線の定義(OS レベル)

2つの面が接しているとき、その接触領域は必ず 長方形になる。
その長方形の 4 辺のうち、Part の外周に一致する辺が「境界線」。

つまり:

境界線 = 接触長方形のうち、両 Part の外形に一致する線分

OS はこれを自動的に抽出する。


🟢 ③ 境界線検出アルゴリズム(UI/内部共通)

ステップ 1:接触面ペアを取得

Surface Adjacency Graph から
「PartA.FaceX と PartB.FaceY が接している」
という情報を取得。

ステップ 2:接触領域(長方形)を計算

各面は 2D 平面なので、
接触領域は以下で求まる:

  • 面のローカル座標系に変換
  • A 面と B 面の重なり部分を計算
  • 結果は axis-aligned rectangle(長方形)

ステップ 3:長方形の 4 辺を抽出

長方形の 4 辺を線分として取得:

E1, E2, E3, E4

ステップ 4:外形一致チェック

各線分 Ei が

  • PartA の外形のエッジ
  • かつ PartB の外形のエッジ
    に一致しているか判定。

一致している線分だけが Line Bend Patch の候補軸

ステップ 5:UI に渡す

UI は候補線分を受け取り、
ユーザーがパッチを持った瞬間に 青くハイライトする。


🔵 ④ アルゴリズムの擬似コード(OS 内部)

function DetectBendEdges(partA, partB)
    local edges = {}

    for faceA in partA.Faces do
        for faceB in partB.Faces do
            if FacesAreTouching(faceA, faceB) then
                local rect = ComputeOverlapRectangle(faceA, faceB)
                local rectEdges = ExtractEdges(rect)

                for _, edge in rectEdges do
                    if IsOuterEdge(faceA, edge) and IsOuterEdge(faceB, edge) then
                        table.insert(edges, edge)
                    end
                end
            end
        end
    end

    return edges
end

🟣 ⑤ UI 側の処理(境界線ハイライト)

UI は DetectBendEdges の結果を受け取り:

  • パッチを掴んだ瞬間に
    候補線分を青く光らせる
  • パッチを近づけると
    最も近い線分にスナップ
  • 線分に重なると
    → パッチが細長い帯に変形して軸に沿う

この一連の動作で、
ユーザーは 「ここが節になる」 を直感的に理解できる。


🟠 ⑥ OS 的な美しさ:責務の完全分離

  • 構造レイヤー
    → 面隣接グラフを管理
    → 境界線を計算
  • UI レイヤー
    → 境界線を可視化
    → スナップ挙動
  • 時間レイヤー(Scheduler)
    → BendAngle を更新するだけ
    → 構造を知らない

あなたの OS 哲学に完全一致している。


🔥 次に詰めるべきはどれ?

A:境界線の「軸方向」の自動決定(右向きか左向きか)
B:Line Bend Patch の貼り付け後の Constraint 生成
C:昆虫脚モデルでの実例(境界線 → パッチ → Scheduler)

どれを進めたい?

 

 

 

了解した。
「円柱は底面だけでなく“上面も貼り付け可能”」──この一文で、円柱の扱いが OS としてさらに美しく整う。

ここからは、
円柱の“上下の円盤”だけがパッチ可能面
という前提で、境界線(Boundary Curve)検出アルゴリズムを 完全版として再定義するね。


🟣 円柱のパッチ可能面:上下の円盤(Top / Bottom)

PatchMotions の OS にこう宣言する:

CylinderPatchableFaces = { TopDisk, BottomDisk }

つまり:

  • 側面(曲面)→ パッチ不可
  • 上面(円盤)→ パッチ可
  • 底面(円盤)→ パッチ可

これにより、円柱は “上下の円盤を持つ円形ノード” として扱える。


🟠 円柱の境界線は「円周の一部(円弧)」

直方体は線分
円柱は円弧

OS はこれを抽象化して扱う:

BoundaryCurve = 接触領域の外周のうち、両 Part の外形に一致する曲線

円柱の外形は 円周なので、
境界線は必ず 円弧になる。


🟡 円柱の上下円盤に対する境界線検出アルゴリズム(完全版)

① パッチ可能面の取得

local faces = { cylinder.TopDisk, cylinder.BottomDisk }

② 他の Part の各面と交差判定

for disk in faces do
    for face in otherPart.Faces do
        if FacesAreTouching(disk, face) then
            local arc = ComputeDiskFaceIntersection(disk, face)
            if arc then
                table.insert(boundaryCurves, arc)
            end
        end
    end
end

③ arc(円弧)が Line Bend Patch の候補軸

  • arc は「円周の一部」
  • arc が存在する=そこにパッチを貼れる
  • UI は arc を青くハイライトする

🟢 直方体 × 円柱(上面 or 底面)の例

直方体の面が円柱の上面に触れると:

  • 接触領域は「扇形」
  • 境界線はその扇形の外周=円弧

つまり、Line Bend Patch の軸は 円弧の中心線 になる。


🔵 円柱 × 円柱(上下円盤同士)の例

円柱 A の上面と
円柱 B の底面が接触すると:

  • 接触領域は「円」または「円の一部」
  • 境界線は 円周の一部(円弧)

円柱同士の節(関節)が自然に作れる。


🟣 UI 側の動作(上面対応版)

パッチを掴んだ瞬間

円柱の 上面と底面の円周が青く光る
(ただし他の Part と接触している部分だけ)

パッチを近づけると

  • パッチが 円弧に沿って湾曲した帯状 UI に変形
  • 円弧にスナップ
  • 「ここが節になる」ことが直感的に伝わる

貼った瞬間

  • 円弧に沿って光が走る
  • 円柱と他の Part がわずかに“カクッ”と動く
  • 節の誕生を示す

🟠 OS 的な美しさ

円柱の上下円盤をパッチ可能にすることで:

  • 円柱は「上下に接続できるノード」として扱える
  • 側面の複雑な曲面処理を避けられる
  • 境界線は常に「円弧」
  • アルゴリズムが単純で拡張性が高い
  • UI が直感的で子どもでも理解できる

PatchMotions の構造OSとして非常に美しい。


🔥 次に詰めるべきはどれ?

A:円柱の上面・底面に貼られた Line Bend Patch の軸方向(回転軸)の決定
B:円柱同士の節の Constraint(角度制限・軸方向)
C:円柱を使った昆虫脚モデル(節が円弧軸で動く)
D:円柱のパッチ UI の最終デザイン(アイコン・色・形)

どれを進めたい?