public override bool Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == false) { return(false); } m_node = GetManipulatorNode(TransformationTypes.Pivot); Camera camera = vc.Camera; float s; Util.CalcAxisLengths(camera, HitMatrix.Translation, out s); Matrix4F view = camera.ViewMatrix; Matrix4F vp = view * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt, wvp); m_hitRegion = m_translatorControl.Pick(HitMatrix, view, rayL, HitRayV, s); bool picked = m_hitRegion != HitRegion.None; return(picked); }
void IManipulator.Render(ViewControl vc) { TerrainGob terrain = m_terrainEditor.TerrainEditorControl.SelectedTerrain; TerrainBrush brush = m_terrainEditor.TerrainEditorControl.SelectedBrush; TerrainMap terrainMap = m_terrainEditor.TerrainEditorControl.SelectedTerrainMap; if (brush == null || (!brush.CanApplyTo(terrain) && !brush.CanApplyTo(terrainMap))) { return; } Vec2F drawscale = new Vec2F(1.0f, 1.0f); if (brush.CanApplyTo(terrainMap)) { ImageData mapImg = terrainMap.GetSurface(); ImageData hmImg = terrain.GetSurface(); drawscale.X = (float)hmImg.Width / (float)mapImg.Width; drawscale.Y = (float)hmImg.Height / (float)mapImg.Height; } Point scrPt = vc.PointToClient(Control.MousePosition); if (!vc.ClientRectangle.Contains(scrPt)) { return; } Ray3F rayw = vc.GetWorldRay(scrPt); TerrainGob.RayPickRetVal retval; if (terrain.RayPick(rayw, out retval)) { terrain.DrawBrush(brush, drawscale, retval.hitpos); } }
/// <summary> /// Creates a ray originating at the given normalized window coordinates and pointing into /// the screen, along -Z axis. Normalized window coordinates are in the range [-0.5,0.5] /// with +x pointing to the right and +y pointing up.</summary> /// <param name="x">The x normalized window coordinate</param> /// <param name="y">The y normalized window coordinate</param> /// <returns>The ray</returns> public Ray3F CreateRay(float x, float y) { float height, width; // Setup ray Ray3F ray = new Ray3F(); // World height on origin's z value if (Frustum.IsOrtho) { width = Frustum.Right - Frustum.Left; height = Frustum.Top - Frustum.Bottom; ray.Origin = new Vec3F(x * width, y * height, -NearZ); ray.Direction = new Vec3F(0, 0, -1); } else { height = Frustum.Far * (float)Math.Tan(Frustum.FovY / 2.0f) * 2.0f; width = Frustum.Far * (float)Math.Tan(Frustum.FovX / 2.0f) * 2.0f; ray.Origin = new Vec3F(0, 0, 0); ray.Direction = new Vec3F(x * width, y * height, -Frustum.Far); float l = ray.Direction.Length; ray.Direction = ray.Direction / l; } return(ray); }
public override ManipulatorPickResult Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == ManipulatorPickResult.Miss) { return(ManipulatorPickResult.Miss); } m_node = GetManipulatorNode(TransformationTypes.Pivot); Camera camera = vc.Camera; Matrix4F view = camera.ViewMatrix; Matrix4F vp = view * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt, wvp); m_hitRegion = m_translatorControl.Pick(vc, HitMatrix, view, rayL, HitRayV); bool picked = m_hitRegion != HitRegion.None; if (picked) { return(ManipulatorPickResult.DeferredBeginDrag); } return(ManipulatorPickResult.Miss); }
public static bool RayPick(Matrix4F viewxform, Matrix4F projxfrom, Ray3F rayW, bool skipSelected, out HitRecord hit) { HitRecord *nativeHits = null; int count; //bool skipSelected, fixed(float *ptr1 = &viewxform.M11, ptr2 = &projxfrom.M11) { NativeRayPick( ptr1, ptr2, &rayW, skipSelected, &nativeHits, out count); } if (count > 0) { hit = *nativeHits; } else { hit = new HitRecord(); } return(count > 0); }
public static HitRecord[] RayPick(Matrix4F viewxform, Matrix4F projxfrom, Ray3F rayW, bool skipSelected) { HitRecord *nativeHits = null; int count; fixed(float *ptr1 = &viewxform.M11, ptr2 = &projxfrom.M11) { NativeRayPick( ptr1, ptr2, &rayW, skipSelected, &nativeHits, out count); } var objects = new List <HitRecord>(); for (int k = 0; k < count; k++) { objects.Add(*nativeHits); nativeHits++; } return(objects.ToArray()); }
private void TestToStringWithCulture(CultureInfo culture) { CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = culture; try { string listSeparator = culture.TextInfo.ListSeparator; string decimalSeparator = culture.NumberFormat.NumberDecimalSeparator; var o = new Ray3F(new Vec3F(1.1f, 2.2f, 3.3f), new Vec3F(4.4f, 5.5f, 6.6f)); string s = o.ToString(null, null); TestToStringResults(o, s, listSeparator, decimalSeparator); string s2 = o.ToString(); Assert.AreEqual(s, s2); s = o.ToString("G", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); s = o.ToString("R", culture); TestToStringResults(o, s, listSeparator, decimalSeparator); } finally { Thread.CurrentThread.CurrentCulture = originalCulture; } }
private void ApplyBrush(ViewControl vc, System.Drawing.Point scrPt) { TerrainGob terrain = m_terrainEditor.TerrainEditorControl.SelectedTerrain; TerrainBrush brush = m_terrainEditor.TerrainEditorControl.SelectedBrush; TerrainMap terrainMap = m_terrainEditor.TerrainEditorControl.SelectedTerrainMap; if (brush == null || (!brush.CanApplyTo(terrain) && !brush.CanApplyTo(terrainMap))) { return; } Ray3F rayw = vc.GetWorldRay(scrPt); TerrainGob.RayPickRetVal retval; if (terrain.RayPick(rayw, out retval)) { TerrainOp op = null; if (brush.CanApplyTo(terrain)) { Point pt = terrain.WorldToSurfaceSpace(retval.hitpos); brush.Apply(terrain, pt.X, pt.Y, out op); } else if (brush.CanApplyTo(terrainMap)) { Point pt = terrainMap.WorldToSurfaceSpace(retval.hitpos); brush.Apply(terrainMap, pt.X, pt.Y, out op); } m_tmpOps.Add(op); m_terrainOpList.Add(new WeakReference(op)); m_memUsage += op.SizeInBytes; } }
/// <summary> /// Projects the specified x and y, in normalized window coordinates, onto the grid, /// and snaps it to the nearest grid vertex if necessary. /// Normalized window coordinates are in the range [-0.5,0.5] with +x pointing to the /// right and +y pointing up.</summary> /// <param name="x">Window x in normalized window coords</param> /// <param name="y">Window y in normalized window coords</param> /// <param name="camera">Camera</param> /// <returns>Projection of x and y onto the grid, in world space.</returns> public Vec3F Project(float x, float y, Camera camera) { Ray3F ray = camera.CreateRay(x, y); Matrix4F V = new Matrix4F(camera.ViewMatrix); V.Mul(m_invAxisSystem, V); if (camera.Frustum.IsOrtho) { V = new Matrix4F(m_V); V.Translation = camera.ViewMatrix.Translation; } // origin Vec3F delta = new Vec3F(0, Height, 0); V.Transform(delta, out delta); Vec3F o = delta; // Up vec Vec3F axis = V.YAxis; Vec3F projPt = ray.IntersectPlane(axis, -Vec3F.Dot(o, axis)); // Transform back into world space Matrix4F Inv = new Matrix4F(); Inv.Invert(camera.ViewMatrix); Inv.Transform(projPt, out projPt); if (Snap) { projPt = SnapPoint(projPt); } return projPt; }
public override bool Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == false) { return(false); } Camera camera = vc.Camera; float rad; Util.CalcAxisLengths(camera, HitMatrix.Translation, out rad); float tolerance = rad / 10.0f; // compute ray in object space space. Matrix4F vp = camera.ViewMatrix * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt, wvp); Plane3F xplane = new Plane3F(Vec3F.XAxis, Vec3F.ZeroVector); Plane3F yplane = new Plane3F(Vec3F.YAxis, Vec3F.ZeroVector); Plane3F zplane = new Plane3F(Vec3F.ZAxis, Vec3F.ZeroVector); Vec3F pt; float xdelta = float.MaxValue; float ydelta = float.MaxValue; float zdelta = float.MaxValue; if (rayL.IntersectPlane(xplane, out pt)) { xdelta = Math.Abs(pt.Length - rad); } if (rayL.IntersectPlane(yplane, out pt)) { ydelta = Math.Abs(pt.Length - rad); } if (rayL.IntersectPlane(zplane, out pt)) { zdelta = Math.Abs(pt.Length - rad); } if (xdelta < tolerance && xdelta < ydelta && xdelta < zdelta) { m_hitRegion = HitRegion.XAxis; } else if (ydelta < tolerance && ydelta < zdelta) { m_hitRegion = HitRegion.YAxis; } else if (zdelta < tolerance) { m_hitRegion = HitRegion.ZAxis; } return(m_hitRegion != HitRegion.None); }
protected override void OnDragOver(DragEventArgs drgevent) { base.OnDragOver(drgevent); if (DesignView.Context == null || m_ghosts.Count == 0) { return; } Point clientPoint = PointToClient(new Point(drgevent.X, drgevent.Y)); Ray3F rayw = GetWorldRay(clientPoint); bool shiftPressed = Control.ModifierKeys == Keys.Shift; DomNode hitnode = null; HitRecord?hit = null; if (shiftPressed) { Matrix4F v = Camera.ViewMatrix; Matrix4F p = Camera.ProjectionMatrix; HitRecord[] hits = GameEngine.RayPick(v, p, rayw, false); foreach (HitRecord ht in hits) { hitnode = GameEngine.GetAdapterFromId(ht.instanceId).Cast <DomNode>(); bool skip = false; // ignore ghosts foreach (DomNode node in m_ghosts) { if (hitnode == node || hitnode.IsDescendantOf(node)) { skip = true; break; } } if (skip) { continue; } hit = ht; break; } } ISnapFilter snapFilter = Globals.MEFContainer.GetExportedValue <ISnapFilter>(); bool snap = (shiftPressed && hit.HasValue); foreach (DomNode ghost in m_ghosts) { HitRecord?hr = (snap && (snapFilter == null || snapFilter.CanSnapTo(ghost, hitnode))) ? hit : null; ProjectGhost(ghost, rayw, hr); } GameLoop.Update(); GameLoop.Render(); }
public static Ray3F GetRay(this Point scrPt, Matrix4F mtrx, Size controlSize) { Vec3F min = Unproject(new Vec3F(scrPt.X, scrPt.Y, 0), mtrx, controlSize); Vec3F max = Unproject(new Vec3F(scrPt.X, scrPt.Y, 1), mtrx, controlSize); Vec3F dir = Vec3F.Normalize(max - min); Ray3F ray = new Ray3F(min, dir); return(ray); }
/// <summary> /// compute ray in given space starting from /// screen space x,y. /// The space of the computed ray depends on the value of mtrx: /// world * view * projection // ray in local space (object space). /// view * projection // ray in world space. /// projection // ray in view space. /// </summary> public Ray3F GetRay(Point scrPt, Matrix4F mtrx) { Vec3F min = Unproject(new Vec3F(scrPt.X, scrPt.Y, 0), mtrx); Vec3F max = Unproject(new Vec3F(scrPt.X, scrPt.Y, 1), mtrx); Vec3F dir = Vec3F.Normalize(max - min); Ray3F ray = new Ray3F(min, dir); return(ray); }
public bool Intersect(Ray3F r) { float tmin; float tmax; Vec3F pos; Vec3F norm; bool result = Intersect(r, out tmin, out tmax, out pos, out norm); return(result); }
/// <summary> /// compute ray in world space starting from /// screen space x,y. /// </summary> public Ray3F GetWorldRay(Point scrPt) { Matrix4F vp = Camera.ViewMatrix * Camera.ProjectionMatrix; Vec3F min = Unproject(new Vec3F(scrPt.X, scrPt.Y, 0), vp); Vec3F max = Unproject(new Vec3F(scrPt.X, scrPt.Y, 1), vp); Vec3F dir = Vec3F.Normalize(max - min); Ray3F ray = new Ray3F(min, dir); return(ray); }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0) { return; } // create ray in view space. Ray3F rayV = vc.GetWorldRay(scrPt); using (var intersectionScene = GameEngine.GetEditorSceneManager().GetIntersectionScene()) { Vec3F intersectionPt; if (!CalculateTerrainIntersection(vc, rayV, intersectionScene, out intersectionPt)) { return; } if (m_pendingStartPt) { m_startPt = intersectionPt; m_pendingStartPt = false; } else { bool clampToSurface = Control.ModifierKeys == Keys.Shift; Vec3F translate = new Vec3F(intersectionPt.X - m_startPt.X, intersectionPt.Y - m_startPt.Y, 0.0f); for (int i = 0; i < m_activeOp.NodeList.Count; i++) { ITransformable node = m_activeOp.NodeList[i]; Path <DomNode> path = new Path <DomNode>(Adapters.Cast <DomNode>(node).GetPath()); Matrix4F parentLocalToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2); Matrix4F parentWorldToLocal = new Matrix4F(); parentWorldToLocal.Invert(parentLocalToWorld); Vec3F newWorldPos = m_originalTranslations[i] + translate; float terrainHeight = 0.0f; if (GUILayer.EditorInterfaceUtils.GetTerrainHeight( out terrainHeight, intersectionScene, newWorldPos.X, newWorldPos.Y)) { newWorldPos.Z = terrainHeight + (clampToSurface ? 0.0f : m_originalHeights[i]); Vec3F localTranslation; parentWorldToLocal.TransformVector(newWorldPos, out localTranslation); node.Translation = localTranslation; } } } } }
private void TestToStringResults(Ray3F o, string s, string listSeparator, string decimalSeparator) { string[] results = s.Split(new[] { listSeparator }, StringSplitOptions.RemoveEmptyEntries); Assert.AreEqual(results.Length, 6); foreach (string oneFloatString in results) { Assert.True(oneFloatString.Contains(decimalSeparator)); } Assert.AreEqual(float.Parse(results[0]), o.Origin.X); Assert.AreEqual(float.Parse(results[1]), o.Origin.Y); Assert.AreEqual(float.Parse(results[2]), o.Origin.Z); Assert.AreEqual(float.Parse(results[3]), o.Direction.X); Assert.AreEqual(float.Parse(results[4]), o.Direction.Y); Assert.AreEqual(float.Parse(results[5]), o.Direction.Z); }
private static float CalcAngle(Vec3F origin, Plane3F plane, Ray3F ray0, Ray3F ray1, float snapAngle) { float theta = 0; Vec3F p0; Vec3F p1; if (ray0.IntersectPlane(plane, out p0) && ray1.IntersectPlane(plane, out p1)) { Vec3F v0 = Vec3F.Normalize(p0 - origin); Vec3F v1 = Vec3F.Normalize(p1 - origin); theta = CalcAngle(v0, v1, plane.Normal, snapAngle); } return(theta); }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || !CanManipulate(m_node)) { return; } Matrix4F proj = vc.Camera.ProjectionMatrix; // create ray in view space. Ray3F rayV = vc.GetRay(scrPt, proj); Vec3F translate = m_translatorControl.OnDragging(rayV); Vec3F localTranslation; m_worldToLocal.TransformVector(translate, out localTranslation); m_node.Pivot = m_originalPivot + localTranslation; }
public bool RayPick(Ray3F rayw, out RayPickRetVal retval) { INativeObject nobj = this.As <INativeObject>(); IntPtr retvalPtr = IntPtr.Zero; IntPtr rayptr = new IntPtr(&rayw); nobj.InvokeFunction("RayPick", rayptr, out retvalPtr); if (retvalPtr != IntPtr.Zero) { retval = *(RayPickRetVal *)retvalPtr; } else { retval = new RayPickRetVal(); } return(retval.picked); }
private bool CalculateTerrainIntersection(ViewControl vc, Ray3F ray, GUILayer.IntersectionTestSceneWrapper testScene, out Vec3F result) { var nativeVC = vc as NativeDesignControl; if (nativeVC == null) { result = Vec3F.ZeroVector; return(false); } var pick = XLEBridgeUtils.Picking.RayPick(nativeVC.Adapter, ray, XLEBridgeUtils.Picking.Flags.Terrain); if (pick != null && pick.Length > 0) { result = pick[0].hitPt; return(true); } result = Vec3F.ZeroVector; return(false); }
public override bool Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == false) { return(false); } Camera camera = vc.Camera; Matrix4F view = camera.ViewMatrix; Matrix4F vp = view * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt, wvp); float s = Util.CalcAxisScale(vc.Camera, HitMatrix.Translation, AxisLength, vc.Height); // There's only one hot-spot for this manipulator: // a square at the manipulator origin. Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f); Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f); AABB box = new AABB(min, max); float centerCubeScale = s * CenterCubeSize; Matrix4F centerCubeXform = new Matrix4F(); centerCubeXform.Scale(centerCubeScale); centerCubeXform.Invert(centerCubeXform); Ray3F ray = rayL; ray.Transform(centerCubeXform); if (box.Intersect(ray)) { m_hitRegion = HitRegion.XYSquare; return(true); } m_hitRegion = HitRegion.None; return(false); }
public override bool Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == false) { return(false); } Camera camera = vc.Camera; Matrix4F view = camera.ViewMatrix; Matrix4F vp = view * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; Ray3F rayL = vc.GetRay(scrPt, wvp); m_hitRegion = m_translatorControl.Pick(vc, HitMatrix, view, rayL, HitRayV); bool picked = m_hitRegion != HitRegion.None; return(picked); }
bool IManipulator.Pick(ViewControl vc, System.Drawing.Point scrPt) { TerrainGob terrain = m_terrainEditor.TerrainEditorControl.SelectedTerrain; TerrainBrush brush = m_terrainEditor.TerrainEditorControl.SelectedBrush; if (terrain != null && brush != null) { FlattenBrush fbrush = brush as FlattenBrush; if (fbrush != null) { Ray3F rayw = vc.GetWorldRay(scrPt); TerrainGob.RayPickRetVal retval; if (terrain.RayPick(rayw, out retval)) { Point pt = terrain.WorldToSurfaceSpace(retval.hitpos); ImageData hm = terrain.GetSurface(); fbrush.Height = hm.GetPixelFloat(pt.X, pt.Y); } } return(true); } return(false); }
protected override IList <object> Pick(MouseEventArgs e) { bool multiSelect = DragOverThreshold; List <object> paths = new List <object>(); Picking.HitRecord[] hits; if (multiSelect) {// frustum pick RectangleF rect = MakeRect(FirstMousePoint, CurrentMousePoint); var frustum = XLEBridgeUtils.Utils.MakeFrustumMatrix(Utils.AsCameraDesc(Camera), rect, ClientSize); hits = Picking.FrustumPick( GameEngine.GetEngineDevice(), Adapter.SceneManager, Adapter.TechniqueContext, frustum, Utils.AsCameraDesc(Camera), ClientSize, Picking.Flags.Objects | Picking.Flags.Helpers); } else {// ray pick Ray3F rayW = GetWorldRay(CurrentMousePoint); hits = Picking.RayPick( GameEngine.GetEngineDevice(), Adapter.SceneManager, Adapter.TechniqueContext, rayW, Utils.AsCameraDesc(Camera), ClientSize, Picking.Flags.Terrain | Picking.Flags.Objects | Picking.Flags.Helpers); } if (hits == null) { return(new List <object>()); } // create unique list of hits HashSet <ulong> instanceSet = new HashSet <ulong>(); var uniqueHits = new List <Picking.HitRecord>(); // build 'path' objects for each hit record. foreach (var hit in hits) { bool added = instanceSet.Add(hit.instanceId); if (added) { uniqueHits.Add(hit); } } var firstHit = new Picking.HitRecord(); // build 'path' objects for each hit record. foreach (var hit in uniqueHits) { var nativeIdMapping = Globals.MEFContainer.GetExportedValue <INativeIdMapping>(); var nobj = nativeIdMapping.GetAdapter(hit.documentId, hit.instanceId).As <DomNodeAdapter>(); if (nobj == null) { continue; } DomNode dom = nobj.DomNode; object hitPath = Util.AdaptDomPath(dom); object obj = DesignView.PickFilter.Filter(hitPath, e); if (obj != null) { if (paths.Count == 0) { firstHit = hit; } var newPath = obj as AdaptablePath <object> ?? Util.AdaptDomPath((DomNode)obj); paths.Add(newPath); } } if (multiSelect == false && paths.Count > 0) { var path = paths[0]; ISelectionContext selection = DesignView.Context.As <ISelectionContext>(); ILinear linear = path.As <ILinear>(); if (linear != null && Control.ModifierKeys == System.Windows.Forms.Keys.Shift && selection.SelectionContains(path)) { ITransactionContext trans = DesignView.Context.As <ITransactionContext>(); trans.DoTransaction( delegate { linear.InsertPoint(firstHit.index, firstHit.hitPt.X, firstHit.hitPt.Y, firstHit.hitPt.Z); }, "insert control point".Localize() ); } } return(paths); }
/// <summary> /// Projects the ghost</summary> private void ProjectGhost(DomNode ghost, Ray3F rayw, HitRecord?hit) { ITransformable xformnode = ghost.Cast <ITransformable>(); IBoundable bnode = ghost.As <IBoundable>(); AABB box = bnode.BoundingBox; Vec3F pt; if (hit.HasValue && hit.Value.hasNormal) { Vec3F rad = box.Radius; Vec3F norm = hit.Value.normal; Vec3F absNorm = Vec3F.Abs(norm); Vec3F offset = Vec3F.ZeroVector; if (absNorm.X > absNorm.Y) { if (absNorm.X > absNorm.Z) { offset.X = norm.X > 0 ? rad.X : -rad.X; } else { offset.Z = norm.Z > 0 ? rad.Z : -rad.Z; } } else { if (absNorm.Y > absNorm.Z) { offset.Y = norm.Y > 0 ? rad.Y : -rad.Y; } else { offset.Z = norm.Z > 0 ? rad.Z : -rad.Z; } } Vec3F localCenter = box.Center - xformnode.Translation; pt = hit.Value.hitPt + (offset - localCenter); } else { float offset = 6.0f * box.Radius.Length; pt = rayw.Origin + offset * rayw.Direction; } if (ViewType == ViewTypes.Front) { pt.Z = 0.0f; } else if (ViewType == ViewTypes.Top) { pt.Y = 0.0f; } else if (ViewType == ViewTypes.Left) { pt.X = 0.0f; } xformnode.Translation = pt; }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_cancelDrag || m_hitRegion == HitRegion.None || NodeList.Count == 0) { return; } bool hitAxis = m_hitRegion == HitRegion.XAxis || m_hitRegion == HitRegion.YAxis || m_hitRegion == HitRegion.ZAxis; Matrix4F view = vc.Camera.ViewMatrix; Matrix4F proj = vc.Camera.ProjectionMatrix; Matrix4F vp = view * proj; // create ray in world space. Ray3F rayW = vc.GetRay(scrPt, vp); // create ray in view space. Ray3F rayV = vc.GetRay(scrPt, proj); Vec3F translate = m_translatorControl.OnDragging(rayV); ISnapSettings snapSettings = (ISnapSettings)DesignView; bool snapToGeom = Control.ModifierKeys == m_snapGeometryKey; if (snapToGeom) { Vec3F manipPos = HitMatrix.Translation; Vec3F manipMove; if (hitAxis) { //Make rayw to point toward moving axis and starting // from manipulator’s world position. rayW.Direction = Vec3F.Normalize(translate); rayW.Origin = manipPos; manipMove = Vec3F.ZeroVector; m_cancelDrag = true; //stop further snap-to's } else { manipMove = rayW.ProjectPoint(manipPos) - manipPos; } for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; Vec3F snapOffset = TransformUtils.CalcSnapFromOffset(node, snapSettings.SnapFrom); Path <DomNode> path = new Path <DomNode>(Adapters.Cast <DomNode>(node).GetPath()); Matrix4F parentLocalToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2); Vec3F orgPosW; parentLocalToWorld.Transform(m_originalValues[i], out orgPosW); Matrix4F parentWorldToLocal = new Matrix4F(); parentWorldToLocal.Invert(parentLocalToWorld); rayW.MoveToIncludePoint(orgPosW + snapOffset + manipMove); HitRecord[] hits = GameEngine.RayPick(view, proj, rayW, true); bool cansnap = false; HitRecord target = new HitRecord(); if (hits.Length > 0) { // find hit record. foreach (var hit in hits) { if (m_snapFilter.CanSnapTo(node, GameEngine.GetAdapterFromId(hit.instanceId))) { target = hit; cansnap = true; break; } } } if (cansnap) { Vec3F pos; if (target.hasNearestVert && snapSettings.SnapVertex) { pos = target.nearestVertex; } else { pos = target.hitPt; } pos -= snapOffset; parentWorldToLocal.Transform(ref pos); Vec3F diff = pos - node.Transform.Translation; node.Translation += diff; bool rotateOnSnap = snapSettings.RotateOnSnap && target.hasNormal && (node.TransformationType & TransformationTypes.Rotation) != 0; if (rotateOnSnap) { Vec3F localSurfaceNormal; parentWorldToLocal.TransformNormal(target.normal, out localSurfaceNormal); node.Rotation = TransformUtils.RotateToVector( m_originalRotations[i], localSurfaceNormal, AxisSystemType.YIsUp); } } } } else { IGrid grid = DesignView.Context.Cast <IGame>().Grid; bool snapToGrid = Control.ModifierKeys == m_snapGridKey && grid.Visible && vc.Camera.ViewType == ViewTypes.Perspective; float gridHeight = grid.Height; // translate. for (int i = 0; i < NodeList.Count; i++) { ITransformable node = NodeList[i]; Path <DomNode> path = new Path <DomNode>(Adapters.Cast <DomNode>(node).GetPath()); Matrix4F parentLocalToWorld = TransformUtils.CalcPathTransform(path, path.Count - 2); Matrix4F parentWorldToLocal = new Matrix4F(); parentWorldToLocal.Invert(parentLocalToWorld); Vec3F localTranslation; parentWorldToLocal.TransformVector(translate, out localTranslation); Vec3F trans = m_originalValues[i] + localTranslation; if (snapToGrid) { if (grid.Snap) { trans = grid.SnapPoint(trans); } else { trans.Y = gridHeight; } } node.Translation = trans; } } }
public override ManipulatorPickResult Pick(ViewControl vc, Point scrPt) { m_hitRegion = HitRegion.None; if (base.Pick(vc, scrPt) == ManipulatorPickResult.Miss) { return(ManipulatorPickResult.Miss); } Camera camera = vc.Camera; float s = Util.CalcAxisScale(vc.Camera, HitMatrix.Translation, AxisLength, vc.Height); Matrix4F vp = camera.ViewMatrix * camera.ProjectionMatrix; Matrix4F wvp = HitMatrix * vp; // get ray in object space space. Ray3F rayL = vc.GetRay(scrPt, wvp); m_scale = new Vec3F(1, 1, 1); m_hitScale = s; Vec3F min = new Vec3F(-0.5f, -0.5f, -0.5f); Vec3F max = new Vec3F(0.5f, 0.5f, 0.5f); AABB box = new AABB(min, max); Matrix4F boxScale = new Matrix4F(); Matrix4F boxTrans = new Matrix4F(); Matrix4F BoxMtrx = new Matrix4F(); float handleScale = s * AxisHandle; // +X axis boxScale.Scale(new Vec3F(s, handleScale, handleScale)); boxTrans.Translation = new Vec3F(s / 2, 0, 0); BoxMtrx = boxScale * boxTrans; Ray3F ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.XAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -X boxTrans.Translation = new Vec3F(-s / 2, 0, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegXAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // y axis boxScale.Scale(new Vec3F(handleScale, s, handleScale)); boxTrans.Translation = new Vec3F(0, s / 2, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.YAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -Y boxTrans.Translation = new Vec3F(0, -s / 2, 0); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegYAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // z axis boxScale.Scale(new Vec3F(handleScale, handleScale, s)); boxTrans.Translation = new Vec3F(0, 0, s / 2); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.ZAxis; return(ManipulatorPickResult.DeferredBeginDrag); } // -Z boxTrans.Translation = new Vec3F(0, 0, -s / 2); BoxMtrx = boxScale * boxTrans; ray = rayL; BoxMtrx.Invert(BoxMtrx); ray.Transform(BoxMtrx); if (box.Intersect(ray)) { m_hitRegion = HitRegion.NegZAxis; return(ManipulatorPickResult.DeferredBeginDrag); } return(ManipulatorPickResult.Miss); }
public override void OnDragging(ViewControl vc, Point scrPt) { if (m_hitRegion == HitRegion.None || m_activeOp == null || m_activeOp.NodeList.Count == 0) { return; } Matrix4F view = vc.Camera.ViewMatrix; // compute world * view Matrix4F wv = new Matrix4F(); wv.Mul(HitMatrix, view); // create ray in view space. Ray3F rayV = vc.GetRay(scrPt, vc.Camera.ProjectionMatrix); Vec3F xAxis = wv.XAxis; Vec3F yAxis = wv.YAxis; Vec3F zAxis = wv.ZAxis; Vec3F origin = wv.Translation; m_scale = new Vec3F(1, 1, 1); float scale = 1; float a1, a2; switch (m_hitRegion) { case HitRegion.XAxis: case HitRegion.NegXAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, yAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, zAxis)); Vec3F axis = (a1 > a2 ? yAxis : zAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), xAxis); if (m_hitRegion == HitRegion.NegXAxis) { dragAmount *= -1; } m_scale.X = 1.0f + dragAmount / m_hitScale; scale = m_scale.X; } break; case HitRegion.YAxis: case HitRegion.NegYAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, zAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, xAxis)); Vec3F axis = (a1 > a2 ? zAxis : xAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), yAxis); if (m_hitRegion == HitRegion.NegYAxis) { dragAmount *= -1; } m_scale.Y = 1.0f + dragAmount / m_hitScale; scale = m_scale.Y; } break; case HitRegion.ZAxis: case HitRegion.NegZAxis: { a1 = Math.Abs(Vec3F.Dot(HitRayV.Direction, xAxis)); a2 = Math.Abs(Vec3F.Dot(HitRayV.Direction, yAxis)); Vec3F axis = (a1 > a2 ? xAxis : yAxis); Vec3F p0 = HitRayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); Vec3F p1 = rayV.IntersectPlane(axis, -Vec3F.Dot(axis, origin)); float dragAmount = Vec3F.Dot((p1 - p0), zAxis); if (m_hitRegion == HitRegion.NegZAxis) { dragAmount *= -1; } m_scale.Z = 1.0f + dragAmount / m_hitScale; scale = m_scale.Z; } break; default: throw new ArgumentOutOfRangeException(); } if (m_isUniformScaling) { m_scale = new Vec3F(scale, scale, scale); } // scale for (int i = 0; i < m_activeOp.NodeList.Count; i++) { ITransformable node = m_activeOp.NodeList[i]; node.Scale = Vec3F.Mul(m_originalScales[i], m_scale); Matrix4F mtrx = TransformUtils.CalcTransform( Vec3F.ZeroVector, node.Rotation, node.Scale, m_pivotOffset[i]); node.Translation = m_originalTranslations[i] + mtrx.Translation; } }
protected override IList <object> Pick(MouseEventArgs e) { bool multiSelect = DragOverThreshold; List <object> paths = new List <object>(); HitRecord[] hits; if (multiSelect) {// frustum pick RectangleF rect = MakeRect(FirstMousePoint, CurrentMousePoint); hits = GameEngine.FrustumPick(SurfaceId, Camera.ViewMatrix, Camera.ProjectionMatrix, rect); } else {// ray pick Ray3F rayW = GetWorldRay(CurrentMousePoint); hits = GameEngine.RayPick(Camera.ViewMatrix, Camera.ProjectionMatrix, rayW, false); } // create unique list of hits HashSet <ulong> instanceSet = new HashSet <ulong>(); List <HitRecord> uniqueHits = new List <HitRecord>(); // build 'path' objects for each hit record. foreach (HitRecord hit in hits) { bool added = instanceSet.Add(hit.instanceId); if (added) { uniqueHits.Add(hit); } } HitRecord firstHit = new HitRecord(); // build 'path' objects for each hit record. foreach (HitRecord hit in uniqueHits) { NativeObjectAdapter nobj = GameEngine.GetAdapterFromId(hit.instanceId); DomNode dom = nobj.DomNode; object hitPath = Util.AdaptDomPath(dom); object obj = DesignView.PickFilter.Filter(hitPath, e); if (obj != null) { if (paths.Count == 0) { firstHit = hit; } var newPath = obj as AdaptablePath <object> ?? Util.AdaptDomPath((DomNode)obj); paths.Add(newPath); } } if (multiSelect == false && paths.Count > 0) { var path = paths[0]; ISelectionContext selection = DesignView.Context.As <ISelectionContext>(); ILinear linear = path.As <ILinear>(); if (linear != null && Control.ModifierKeys == System.Windows.Forms.Keys.Shift && selection.SelectionContains(path)) { ITransactionContext trans = DesignView.Context.As <ITransactionContext>(); trans.DoTransaction( delegate { linear.InsertPoint(firstHit.index, firstHit.hitPt.X, firstHit.hitPt.Y, firstHit.hitPt.Z); }, "insert control point".Localize() ); } } return(paths); }