public void SceneRotateAround(FScene scene, Quaternionf rotation, Vector3f position) { Frame3f curF = scene.RootGameObject.GetWorldFrame(); curF.RotateAround(position, rotation); scene.RootGameObject.SetPosition(curF.Origin); scene.RootGameObject.SetRotation(curF.Rotation); }
// 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); }
public static void SwapUpDirection(FScene scene, List <PrintMeshSO> objects) { AxisAlignedBox3f sceneBounds = AxisAlignedBox3f.Empty; Vector3f sharedOrigin = Vector3f.Zero; foreach (var meshSO in objects) { sharedOrigin += meshSO.GetLocalFrame(CoordSpace.SceneCoords).Origin; sceneBounds.Contain(meshSO.GetBoundingBox(CoordSpace.SceneCoords).ToAABB()); } sharedOrigin /= objects.Count; foreach (var so in objects) { Frame3f curF = so.GetLocalFrame(CoordSpace.SceneCoords); UpDirection from = so.UpDirection; UpDirection to = (from == UpDirection.YUp) ? UpDirection.ZUp : UpDirection.YUp; Quaternionf rotate = Quaternionf.AxisAngleD(Vector3f.AxisX, (to == UpDirection.YUp) ? -90 : 90); Frame3f newF = curF; newF.RotateAround(sharedOrigin, rotate); TransformSOChange upChange = new TransformSOChange(so, newF, CoordSpace.SceneCoords) { OnApplyF = (x) => { so.UpDirection = to; }, OnRevertF = (x) => { so.UpDirection = from; } }; scene.History.PushChange(upChange, false); } AxisAlignedBox3f newSceneBounds = AxisAlignedBox3f.Empty; foreach (var meshSO in objects) { newSceneBounds.Contain(meshSO.GetBoundingBox(CoordSpace.SceneCoords).ToAABB()); } Vector3f startBase = sceneBounds.Center; startBase.y = 0; Vector3f newBase = newSceneBounds.Center; newBase.y = newSceneBounds.Min.y; Vector3f df = startBase - newBase; foreach (var so in objects) { Frame3f curF = so.GetLocalFrame(CoordSpace.SceneCoords); Frame3f newF = curF.Translated(df); TransformSOChange centerChange = new TransformSOChange(so, newF, CoordSpace.SceneCoords); scene.History.PushChange(centerChange, false); } // reposition pivots at base of List <Frame3f> setF = new List <Frame3f>(); foreach (var so in objects) { Frame3f objF = so.GetLocalFrame(CoordSpace.ObjectCoords); Vector3f center = so.GetBoundingBox(CoordSpace.SceneCoords).Center; center.y = 0; Frame3f sceneF = new Frame3f(center); setF.Add(sceneF); } for (int k = 0; k < objects.Count; ++k) { RepositionPivotChangeOp change = new RepositionPivotChangeOp(setF[k], objects[k], CoordSpace.SceneCoords); scene.History.PushChange(change, false); } }