"""Какая камера сдвинута: сверка живой сцены с тем, что записано в файле. В сцене несколько камер разного назначения - шесть стереокамер стенда в /RigRS, корпуса камер в /World/CameraBodies и служебная перспектива вьюпорта. Сдвиг любой из них выглядит одинаково, а чинятся они по-разному, поэтому сначала находится ТА САМАЯ. Живая сцена читается из памяти, эталон - из слоя на диске: несовпадение и есть правка, сделанная мышью во вьюпорте. """ import sys REPO = "/home/dasha/robozon-sorter" if REPO not in sys.path: sys.path.insert(0, REPO) import omni.usd from pxr import Usd, UsdGeom, Gf live = omni.usd.get_context().get_stage() path = live.GetRootLayer().identifier print(f"живая сцена: {path}\n") disk = Usd.Stage.Open(path) cache_l = UsdGeom.XformCache() cache_d = UsdGeom.XformCache() cams = [p for p in live.Traverse() if p.IsA(UsdGeom.Camera)] print(f"камер в сцене: {len(cams)}\n") print(f" {'камера':44s} {'положение сейчас':>34s} расхождение с файлом") print(" " + "-" * 104) moved = [] for c in cams: p = str(c.GetPath()) Ml = cache_l.GetLocalToWorldTransform(c) tl_ = Ml.ExtractTranslation() d = disk.GetPrimAtPath(p) if not d or not d.IsValid(): print(f" {p:44s} ({tl_[0]:+7.3f},{tl_[1]:+7.3f},{tl_[2]:+7.3f}) нет в файле") continue Md = cache_d.GetLocalToWorldTransform(d) td = Md.ExtractTranslation() dt = (tl_ - td).GetLength() # угловое расхождение по направлению взгляда камеры (-Z в её системе) vl = Ml.TransformDir(Gf.Vec3d(0, 0, -1)); vd = Md.TransformDir(Gf.Vec3d(0, 0, -1)) vl = vl / (vl.GetLength() or 1); vd = vd / (vd.GetLength() or 1) import math ang = math.degrees(math.acos(max(-1.0, min(1.0, vl[0]*vd[0] + vl[1]*vd[1] + vl[2]*vd[2])))) flag = "СДВИНУТА" if (dt > 0.001 or ang > 0.1) else "совпадает" print(f" {p:44s} ({tl_[0]:+7.3f},{tl_[1]:+7.3f},{tl_[2]:+7.3f}) " f"{dt*1000:7.1f} мм / {ang:5.2f}° {flag}") if flag == "СДВИНУТА": moved.append((p, td, tl_, dt, ang)) # служебная перспектива вьюпорта - её в файле обычно нет, она хранится в сессии persp = live.GetPrimAtPath("/OmniverseKit_Persp") if persp.IsValid(): M = cache_l.GetLocalToWorldTransform(persp) t = M.ExtractTranslation() print(f"\n перспектива вьюпорта /OmniverseKit_Persp: " f"({t[0]:+.2f}, {t[1]:+.2f}, {t[2]:+.2f})") print() if moved: print(f"СДВИНУТО КАМЕР: {len(moved)}") for p, td, tlv, dt, ang in moved: print(f" {p}") print(f" было в файле: ({td[0]:+7.3f},{td[1]:+7.3f},{td[2]:+7.3f})") print(f" стало сейчас: ({tlv[0]:+7.3f},{tlv[1]:+7.3f},{tlv[2]:+7.3f})") print(f" расхождение {dt*1000:.1f} мм, поворот {ang:.2f}°") else: print("Ни одна камера-прем не сдвинута относительно файла.") print("Значит двигали перспективу вьюпорта - она в файл не пишется и на прогоны не влияет.")