首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

三維物理模擬:判斷平拋運動小球與不同傾斜平面的接觸(非碰撞)算法思路

     編輯:程式設計綜合問答

問題定義

三維空間中,小球做平拋運動(受重力、初速度,無空氣阻力)。場景中存在多個平面,包括水平面、任意傾斜面。需**實時判斷小球與平面是否處於「接觸」狀態**(持續接觸、滾動、靜止),而非瞬間「碰撞」(彈射、反彈)。已知:平面法向量、傾斜角、小球位置/速度/加速度。

核心物理判斷邏輯

1. 幾何接觸條件(位置層面)

小球半徑 r,球心位置 P,平面方程 n·(X - P0) = 0(n 歸一化法向量,P0 平面上任意點)。
球心到平面有向距離:d = n·(P - P0)。
**接觸幾何條件**:|d| ≤ r + ε(ε 為數值容差,如 1e-4)。

2. 動力學接觸條件(運動層面)— 區別「碰撞」與「接觸」

  • 碰撞:d ≈ r 且 v·n < 0(相對速度指向平面內部),瞬時發生,需施加脈衝改變速度方向(反彈系數)。
  • 接觸/貼合:|d - r| ≤ ε 且 v·n ≈ 0(法向相對速度趨近零),且**合外力法向分量指向平面內部**(F_total·n < 0),小球被「壓」在平面上,無法分離。此時應施加**約束力**(法向支持力)抵消穿透趨勢,使法向加速度為零,切向受摩擦力/重力分量驅動滾動/滑動。

3. 受力分解與約束力計算(核心算法)

對小球受力分析:

  • 重力:G = m*g(方向 (0, -g, 0) 或自定義)。
  • 法向支持力 N:方向 n,大小未知,由約束條件決定。
  • 摩擦力 f:方向反切向相對速度,大小 μ*|N|(庫侖摩擦)或黏滯摩擦模型。

約束方程(接觸保持):
a·n = 0 (法向加速度為零,不穿透、不分離)
展開:(G + N + f)·n / m = 0 → N·n = - (G·n + f·n)
因 f·n = 0(摩擦力垂直於法向),得 N = - G·n**(標量,方向 n)。
即:**支持力大小恰好抵消重力在法向的分量**。

**切向加速度**:
a_tangent = (G + f)_tangent / m
其中 G_tangent = G - (G·n)n,f = -μ*N*v_tangent/|v_tangent|(滑動摩擦)或靜摩擦判斷。

4. 狀態機建模(實現建議)

為每個球-平面對維護狀態:

enum ContactState { SEPARATED, COLLIDING, CONTACT_SLIDING, CONTACT_ROLLING, CONTACT_RESTING }

每幀更新邏輯:

  1. 計算 d = n·(P - P0)。
  2. 若 d > r + ε → SEPARATED,僅受重力運動。
  3. 若 d ≤ r + ε 且 v·n < -ε → COLLIDING,施加脈衝反彈,轉 SEPARATED 或 CONTACT。
  4. 若 |d - r| ≤ ε 且 |v·n| ≤ ε:
    • 計算 N = -G·n。若 N < 0(重力拉離平面)→ 實際應分離,設 N=0,狀態轉 SEPARATED。
    • 若 N ≥ 0 → CONTACT。計算切向加速度,更新切向速度/位置。根據切向速度大小判斷 SLIDING/ROLLING/RESTING。

進階考量

  • 多平面同時接觸:需解線性互補問題(LCP)計算多個支持力,防止相互矛盾。可用 Projected Gauss-Seidel 迭代求解。
  • 數值穩定性:使用隱式積分(如半隱式 Euler、Verlet)更新速度位置,大時間步長下更穩定。
  • 滾動不滑動條件:v_tangent = ω × r(角速度叉積半徑),需維護角速度狀態,施加扭矩 τ = r × f。
  • 邊緣/頂點接觸:平面有限大小,需額外判斷投影點是否在多邊形內,否則視為邊緣/頂點接觸,法向量不同。

參考資源

  • 《Real-Time Collision Detection》Christer Ericson — 第 4 章接觸判斷、第 7 章約束求解。
  • Bullet Physics / PhysX / Box2D 源碼中 btPersistentManifold、ContactConstraint 實現。
  • Erin Catto "Iterative Dynamics with Temporal Coherence" (GDC 2009) — 约束求解器設計。

總結:**接觸 ≠ 碰撞**。接觸是持續的幾何貼合 + 動力學約束(法向加速度為零 + 支持力平衡法向外力)。核心在於每幀求解支持力 N = -G·n 並施加切向摩擦,維護狀態機處理分離/碰撞/滑動/滾動/靜止轉換。建議直接集成成熟物理引擎(Bullet/PhysX)而非手寫求解器,專注於業務邏輯層的接觸事件回調。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved