public static Frame3f GetSOLocalFrame(SceneObject so, CoordSpace eSpace) { if (eSpace == CoordSpace.SceneCoords) { // new code maps object frame up to scene // [TODO] this is not the most efficient approach! can at least get the object // frame directly, and avoid first local-to-obj xform Frame3f objF = Frame3f.Identity; Frame3f result = SceneTransforms.ObjectToScene(so, objF); // [RMS] old code that mapped up to world, and then down to scene // Problem with this code is that it is unstable - if scene-to-world xform changes, // then scene frame will numerically change. Which is a problem. //Frame3f sceneW = UnityUtil.GetGameObjectFrame(so.GetScene().RootGameObject, CoordSpace.WorldCoords); //Frame3f objW = UnityUtil.GetGameObjectFrame(so.RootGameObject, CoordSpace.WorldCoords); //Frame3f result = sceneW.ToFrame(objW); //// world coords have scene scale applied, we don't want that in scene coords //if (so.GetScene().GetSceneScale() != 1.0f) // result = result.Scaled(1.0f / so.GetScene().GetSceneScale()); return(result); } else { return(UnityUtil.GetGameObjectFrame(so.RootGameObject, eSpace)); } }
// same as LocalFrame, but LocalFrame may be tilted up/down, which we want to undo public virtual Frame3f GetLevelViewFrame(CoordSpace eSpace) { // otherwise we can't just set y to 0... Debug.Assert(eSpace == CoordSpace.WorldCoords); Frame3f viewF = UnityUtil.GetGameObjectFrame(ActiveCamera.GameObject(), eSpace); float fAngle = VRUtil.PlaneAngleSigned(Vector3f.AxisZ, viewF.Z, 1); return(new Frame3f(viewF.Origin, Quaternionf.AxisAngleD(Vector3f.AxisY, fAngle))); }
public static Frame3f GetSOLocalFrame(SceneObject so, CoordSpace eSpace) { if (eSpace == CoordSpace.SceneCoords) { Frame3f sceneW = UnityUtil.GetGameObjectFrame(so.GetScene().RootGameObject, CoordSpace.WorldCoords); Frame3f objW = UnityUtil.GetGameObjectFrame(so.RootGameObject, CoordSpace.WorldCoords); Frame3f result = sceneW.ToFrame(objW); // world coords have scene scale applied, we don't want that in scene coords if (so.GetScene().GetSceneScale() != 1.0f) { result = result.Scaled(1.0f / so.GetScene().GetSceneScale()); } return(result); } else { return(UnityUtil.GetGameObjectFrame(so.RootGameObject, eSpace)); } }
public static void SetSOLocalFrame(SceneObject so, CoordSpace eSpace, Frame3f newFrame) { if (eSpace == CoordSpace.SceneCoords) { // scene frames should not be scaled by scene scale, but we want to set as world // coords, so we need to apply it now if (so.GetScene().GetSceneScale() != 1.0f) { newFrame = newFrame.Scaled(so.GetScene().GetSceneScale()); } Frame3f sceneW = UnityUtil.GetGameObjectFrame(so.GetScene().RootGameObject, CoordSpace.WorldCoords); Frame3f objW = sceneW.FromFrame(newFrame); UnityUtil.SetGameObjectFrame(so.RootGameObject, objW, CoordSpace.WorldCoords); } else { UnityUtil.SetGameObjectFrame(so.RootGameObject, newFrame, eSpace); } }
// cockpit frame is oriented such that // +X is right // +Y is up // +Z is into scene // note that for most unity mesh objects are created on the XZ plane, and so you // need to rotate world_y to point to -cockpit_z, ie Quaternion.FromToRotation (Vector3.up, -cockpitF.Z) public virtual Frame3f GetLocalFrame(CoordSpace eSpace) { return(UnityUtil.GetGameObjectFrame(gameobject, eSpace)); }
public virtual Frame3f GetLocalFrame() { return(UnityUtil.GetGameObjectFrame(go, CoordSpace.ObjectCoords)); }
public virtual Frame3f GetWorldFrame() { return(UnityUtil.GetGameObjectFrame(go, CoordSpace.WorldCoords)); }
// extracts MeshFilter object from input GameObject and passes it to a custom constructor // function MakeSOFunc (if null, creates basic MeshSO). Then optionally adds to Scene, // preserving existing 3D position if desired (default true) public static SceneObject ImportExistingUnityMesh(GameObject go, FScene scene, bool bAddToScene = true, bool bKeepWorldPosition = true, bool bRecenterFrame = true, Func <Mesh, SOMaterial, SceneObject> MakeSOFunc = null) { MeshFilter meshF = go.GetComponent <MeshFilter>(); if (meshF == null) { throw new Exception("SceneUtil.ImportExistingUnityMesh: gameObject is not a mesh!!"); } Vector3f scale = go.GetLocalScale(); // [RMS] why don't we bake transform into mesh ??! then we could handle non-uniform scaling... if (SceneTransforms.IsUniformScale(scale) == false) { throw new Exception("UnitySceneUtil.ImportExistingUnityMesh: nonuniform scaling is not supported..."); } Mesh useMesh = meshF.mesh; // makes a copy AxisAlignedBox3f bounds = useMesh.bounds; // bounds.Center is wrt local frame of input go // ie offset from origin in local coordinates // if we want to move frame to center of mesh, we have to re-center it at origin // in local coordinates if (bRecenterFrame) { UnityUtil.TranslateMesh(useMesh, -bounds.Center.x, -bounds.Center.y, -bounds.Center.z); useMesh.RecalculateBounds(); } SceneObject newSO = (MakeSOFunc != null) ? MakeSOFunc(useMesh, scene.DefaultMeshSOMaterial) : new MeshSO().Create(useMesh, scene.DefaultMeshSOMaterial); if (bAddToScene) { scene.AddSceneObject(newSO, false); } if (bKeepWorldPosition) { // compute world rotation/location. If we re-centered the mesh, we need // to offset by the transform we applied above in local coordinates // (hence we have to rotate & scale) if (go.transform.parent != null) { throw new Exception("UnitySceneUtil.ImportExistingUnityMesh: Not handling case where GO has a parent transform"); } Frame3f goFrameW = UnityUtil.GetGameObjectFrame(go, CoordSpace.WorldCoords); Vector3f originW = goFrameW.Origin; if (bRecenterFrame) { originW += goFrameW.Rotation * (scale * bounds.Center); // offset initial frame to be at center of mesh } // convert world frame and offset to scene coordinates Frame3f goFrameS = scene.ToSceneFrame(goFrameW); Vector3f boundsCenterS = scene.ToSceneP(originW); // translate new object to position in scene Frame3f curF = newSO.GetLocalFrame(CoordSpace.SceneCoords); curF.Origin += boundsCenterS; newSO.SetLocalFrame(curF, CoordSpace.SceneCoords); // apply rotation (around current origin) curF = newSO.GetLocalFrame(CoordSpace.SceneCoords); curF.RotateAround(curF.Origin, goFrameS.Rotation); newSO.SetLocalFrame(curF, CoordSpace.SceneCoords); // apply local scale newSO.SetLocalScale(scale); } return(newSO); }
// extracts all MeshFilter objects from input GameObject and appends them, then passes to // function MakeSOFunc (if null, creates basic MeshSO). Then optionally adds to Scene, // preserving existing 3D position if desired (default true) public static SceneObject ImportExistingUnityGO(GameObject go, FScene scene, bool bAddToScene = true, bool bKeepWorldPosition = true, bool bRecenterFrame = true, Func <DMesh3, SOMaterial, SceneObject> MakeSOFunc = null) { List <MeshFilter> filters = new List <MeshFilter>(); List <GameObject> children = new List <GameObject>() { go }; UnityUtil.CollectAllChildren(go, children); foreach (var cgo in children) { if (cgo.GetComponent <MeshFilter>() != null) { filters.Add(cgo.GetComponent <MeshFilter>()); } } if (filters.Count == 0) { throw new Exception("SceneUtil.ImportExistingUnityGO: no meshes!!"); } DMesh3 CombineMesh = new DMesh3(MeshComponents.VertexNormals | MeshComponents.VertexColors); MeshEditor editor = new MeshEditor(CombineMesh); int gid = 0; foreach (MeshFilter mesh in filters) { fMesh uMesh = new fMesh(mesh.sharedMesh); using (var imesh = uMesh.CreateCachedIMesh()) { editor.AppendMesh(imesh, ++gid); } } Vector3f scale = go.GetLocalScale(); AxisAlignedBox3d bounds = CombineMesh.CachedBounds; // bounds.Center is wrt local frame of input go // ie offset from origin in local coordinates // if we want to move frame to center of mesh, we have to re-center it at origin // in local coordinates if (bRecenterFrame) { MeshTransforms.Translate(CombineMesh, -bounds.Center.x, -bounds.Center.y, -bounds.Center.z); } SceneObject newSO = (MakeSOFunc != null) ? MakeSOFunc(CombineMesh, scene.DefaultMeshSOMaterial) : new DMeshSO().Create(CombineMesh, scene.DefaultMeshSOMaterial); newSO.Name = go.name; if (bAddToScene) { scene.AddSceneObject(newSO, false); } if (bKeepWorldPosition) { // compute world rotation/location. If we re-centered the mesh, we need // to offset by the transform we applied above in local coordinates // (hence we have to rotate & scale) if (go.transform.parent != null) { throw new Exception("UnitySceneUtil.ImportExistingUnityGO: Not handling case where GO has a parent transform"); } Frame3f goFrameW = UnityUtil.GetGameObjectFrame(go, CoordSpace.WorldCoords); Vector3f originW = goFrameW.Origin; if (bRecenterFrame) { originW += goFrameW.Rotation * (scale * (Vector3f)bounds.Center); // offset initial frame to be at center of mesh } // convert world frame and offset to scene coordinates Frame3f goFrameS = scene.ToSceneFrame(goFrameW); Vector3f boundsCenterS = scene.ToSceneP(originW); // translate new object to position in scene Frame3f curF = newSO.GetLocalFrame(CoordSpace.SceneCoords); curF.Origin += boundsCenterS; newSO.SetLocalFrame(curF, CoordSpace.SceneCoords); // apply rotation (around current origin) curF = newSO.GetLocalFrame(CoordSpace.SceneCoords); curF.RotateAround(curF.Origin, goFrameS.Rotation); newSO.SetLocalFrame(curF, CoordSpace.SceneCoords); // apply local scale newSO.SetLocalScale(scale); } return(newSO); }
override public bool UpdateCapture(InputEvent e) { if (eState == CaptureState.ClickType && FindHitGO(e.ray) != null) { return(true); } // otherwise we fall into drag state eState = CaptureState.DragType; if (newPrimitive == null) { newPrimitive = CreatePrimitive(); fPrimScale = 1.0f; if (newPrimitive is PivotSO) { fPrimShift = 0.0f; } else { if (newPrimitive is PrimitiveSO) { if (SavedSettings.Restore("DropPrimButton_scale") != null) { fPrimScale = (float)SavedSettings.Restore("DropPrimButton_scale"); newPrimitive.SetLocalScale(fPrimScale * Vector3f.One); } } fPrimShift = newPrimitive.GetLocalBoundingBox().Extents[1] * TargetScene.GetSceneScale(); } // [RMS] this is kind of cheating - we are going to tell this SO // it is part of the scene, but not actually put it in the scene. // This is because sometimes the SO needs to query the scene/camera // (eg for pivot resizing) TargetScene.ReparentSceneObject(newPrimitive, false); newPrimitive.SetScene(TargetScene); lastHitF = UnityUtil.GetGameObjectFrame(TargetScene.RootGameObject, CoordSpace.WorldCoords); newPrimitive.SetLocalFrame(lastHitF.Translated(fPrimShift, 1), CoordSpace.WorldCoords); } // [RMS] only Touch for this?? if (InputState.IsDevice(e.device, InputDevice.OculusTouch) && newPrimitive is PrimitiveSO) { Vector2f vStick = e.input.StickDelta2D((int)e.side); if (vStick[1] != 0) { fPrimScale = fPrimScale * (1.0f + vStick[1] * 0.1f); fPrimScale = MathUtil.Clamp(fPrimScale, 0.01f, 10.0f); newPrimitive.SetLocalScale(fPrimScale * Vector3f.One); fPrimShift = newPrimitive.GetLocalBoundingBox().Extents[1] * TargetScene.GetSceneScale(); } } AnyRayHit hit = null; if (TargetScene.FindSceneRayIntersection(e.ray, out hit)) { update_position(hit); newPrimitive.SetLocalFrame(lastHitF.Translated(fPrimShift, 1), CoordSpace.WorldCoords); } // [RMS] have to do this because prim is not part of scene yet, // and things like pivots need to be resized if (newPrimitive != null) { newPrimitive.PreRender(); } return(true); }
// utility functions public Frame3f GetObjectFrame() { return(UnityUtil.GetGameObjectFrame(RootGameObject, CoordSpace.ObjectCoords)); }