# 控制 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