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; }
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; } } }
/// <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 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; }
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); }
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 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; } } }