---
# System prepended metadata

title: 控制 ridig body 來實作簡易版開關門
tags: [Omniverse]

---

# 控制 ridig body 來實作簡易版開關門
###### tags: `Omniverse`

## 功能
1. 鍵盤控制 Controller 在場景內移動
2. 碰撞偵測 : trigger
> 持續增添新功能中。 [name=megan ( Omniverse 菜雞仔 )]

## 實作步驟
1. 開啟環境 : `Omniverse > Create > LAUNCH`
2. 新增場景
    * 創建物理場景 : `Create > Physics > Physics Scene`
        * 創建地面 : `Create > Physics > Ground Plane`
4. 新增可控制角色
    * 創建角色 : `Create > Shape > Capsule`
    * 套用 Rigid Body : `Property > Add > Physics > Rigid Body with Colliders Preset`
5. 新增門與牆壁
    * 創建門 : 
        * `Asset Store(beta) > Search:door`
        * download 順眼的門 : Simple_Wood_Door (輸入 sketchfab 密碼)
    * 創建牆壁*3 : `Create > Shape > Cube`
### 碰撞偵測
1. 在需要有物理阻擋的物件(牆壁*3、門)上賦予碰撞功能 : `Property > Add > Physics > Collider`
2. 開關門事件
*  新建碰撞觸發器 : 
    *  `Create > Cube`
    *  rename `door_trigger`
    *  放在門口處(若是被 Capsule 碰到則觸發開門，沒有碰到時表示關門狀態)
        ![](https://i.imgur.com/uU3BNWR.png =400x250)
    * 隱藏(但仍可以偵測碰撞) : `property > Visual > Purpose : guide`
    * 新增Trigger : 
        `property > Add > Physics > collider`
        `property > Add > Trigger`
* 建立 Trigger 腳本
```python=
import sys
from pxr import Usd, UsdGeom, Gf, Vt, UsdUtils

def main():
    print("fafa")
    if not hasattr(sys, 'argv'):
        sys.argv  = ['']
    if len(sys.argv) ==6:
        stageId = int(sys.argv[1])
        triggerPath = sys.argv[2]
        otherPath = sys.argv[3]
        eventName = sys.argv[4]
        scriptFileName = sys.argv[5]
        print("Executed script: " + scriptFileName)
        print("Event name: " + eventName)
        cache = UsdUtils.StageCache.Get()
        stage = cache.Find(Usd.StageCache.Id.FromLongInt(stageId))
        if stage:
            otherPrim = stage.GetPrimAtPath("/World/Simple_Wood_Door")
            cube_prim = UsdGeom.Mesh.Get(stage, otherPrim.GetPath())
            if eventName == "LeaveEvent": #colse door
                xform = UsdGeom.Xformable(cube_prim)
                xform.ClearXformOpOrder()
                transform = xform.AddTransformOp()
                mat = Gf.Matrix4d()
                mat.SetTranslateOnly(Gf.Vec3d(0,0,0))
                mat.SetRotateOnly(Gf.Rotation(Gf.Vec3d(0, 1, 0), 0))
                transform.Set(mat)
            else: # open door
                xform = UsdGeom.Xformable(cube_prim)
                xform.ClearXformOpOrder()
                transform = xform.AddTransformOp()
                mat = Gf.Matrix4d()
                mat.SetTranslateOnly(Gf.Vec3d(0,0,0))
                mat.SetRotateOnly(Gf.Rotation(Gf.Vec3d(0, 1, 0), 120))
                transform.Set(mat)
    pass


main()    
``` 

* 將腳本路徑宣告在`door_trigger > property > Physic > Trigger > On Enter Script & On Leave Script`
![](https://i.imgur.com/Jv8NKF8.png =300x400)

### Keyboard 事件
1. W A S D 控制 Capsule 前後左右移動
2. 於 Script Editor 內執行腳本
3. code : 
```python=
import carb.imgui
import carb.windowing
import carb.input
import omni.appwindow
import omni
from pxr import UsdGeom, Gf
import omni.usd

#get capsule original position
stage = omni.usd.get_context().get_stage()
door_prim = stage.GetPrimAtPath("/World/Capsule")
local_transform = omni.usd.get_local_transform_SRT(door_prim)
translate = local_transform[3]
_x = translate[0]
_y = translate[1]
_z = translate[2]

appwindow = omni.appwindow.get_default_app_window()
keyboard = appwindow.get_keyboard()

def on_input(e):

	xform = UsdGeom.Xformable(door_prim)
	xform.ClearXformOpOrder()
	transform = xform.AddTransformOp()
	mat = Gf.Matrix4d()
	
	global _x
	global _y
	global _z
	
	if e.input == carb.input.KeyboardInput.W:
		#forward  z--
		_z = _z -10
		mat.SetTranslateOnly(Gf.Vec3d(_x,_y,_z))
		transform.Set(mat)
	
	if e.input == carb.input.KeyboardInput.A:
		#left x--
		_x = _x -10
		mat.SetTranslateOnly(Gf.Vec3d(_x,_y,_z))
		transform.Set(mat)
		
	if e.input == carb.input.KeyboardInput.S:
		#back z++
		_z = _z +10
		mat.SetTranslateOnly(Gf.Vec3d(_x,_y,_z))
		transform.Set(mat)
		
	if e.input == carb.input.KeyboardInput.D:
	#right x++
		_x = _x +10
		mat.SetTranslateOnly(Gf.Vec3d(_x,_y,_z))
		transform.Set(mat)
	
	return True

input = carb.input.acquire_input_interface()
keyboard_sub_id = input.subscribe_to_keyboard_events(keyboard, on_input)
```
4. 參考來源
    * [取得當前位置](https://forums.developer.nvidia.com/t/get-position-of-a-prim-object/224198)

## 影片 demo
網址 : https://www.youtube.com/watch?v=esIZ5J_E22k