public static bool Test(SharpDX.Plane plane, Vector3 a, Vector3 b, Vector3 c) { var p1 = plane.Intersects(ref a); var p2 = plane.Intersects(ref b); var p3 = plane.Intersects(ref c); // if all three points are on same side and none of them are on the plane then there is no intersection return(!(p1 == p2 && p2 == p3 && p1 != PlaneIntersectionType.Intersecting)); }
private void ProcessTranslationDrag() { if (m_activeAxis == EGizmoAxis.None) { return; } if (m_activeAxisList.Count <= 0) { return; } Ray pickRay = CreateMouseRay(in m_frameViewInfo); if (m_activeAxisList.Count > 1) { Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]); Plane intersectionPlane = new Plane(m_startLocation, planeNormal); if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection)) { m_controlledTransform.SetWorldPosition(intersection - m_clickOffset); } } else { Vector3 planeTangent = Vector3.Cross(m_activeAxisList[0], m_frameViewInfo.ViewLocation - m_gizmoLocation); Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], planeTangent); Plane intersectionPlane = new Plane(m_startLocation, planeNormal); if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection)) { intersection -= m_originalPosition + m_clickOffset; m_controlledTransform.SetWorldPosition(m_originalPosition + m_activeAxisList[0] * Vector3.Dot(intersection, m_activeAxisList[0])); } } }
public bool Test(SharpDX.Plane other) { return(sbb.Intersects(ref other) == PlaneIntersectionType.Intersecting); }
// tests the aabb with triangle [v0,v1,v2] for intersection public static bool Test(AxisAlignedBoundingBox b, Vector3 v0, Vector3 v1, Vector3 v2) { float p0, p1, p2, r; // Compute box center and extents (if not already given in that format) Vector3 c = (b.Min + b.Max) * 0.5f; float e0 = (b.Max.X - b.Min.X) * 0.5f; float e1 = (b.Max.Y - b.Min.Y) * 0.5f; float e2 = (b.Max.Z - b.Min.Z) * 0.5f; // Translate triangle as conceptually moving AABB to origin v0 = v0 - c; v1 = v1 - c; v2 = v2 - c; // Compute edge vectors for triangle Vector3 f0 = v1 - v0, f1 = v2 - v1, f2 = v0 - v2; // Test axes a00..a22 (category 3) // Test axis a00 p0 = v0.Z * v1.Y - v0.Y * v1.Z; p2 = v2.Z * (v1.Y - v0.Y) - v2.Y * (v1.Z - v0.Z); r = e1 * Math.Abs(f0.Z) + e2 * Math.Abs(f0.Y); if (Math.Max(-Math.Max(p0, p2), Math.Min(p0, p2)) > r) return false; // Axis is a separating axis // axis a01 p0 = -v0.Y * f1.Z + v0.Z * f1.Y; p1 = -v1.Y * f1.Z + v1.Z * f1.Y; p2 = -v2.Y * f1.Z + v2.Z * f1.Y; r = e1 * Math.Abs(f1.Z) + e2 * Math.Abs(f1.Y); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis a02 p0 = -v0.Y * f2.Z + v0.Z * f2.Y; p1 = -v1.Y * f2.Z + v1.Z * f2.Y; p2 = -v2.Y * f2.Z + v2.Z * f2.Y; r = e1 * Math.Abs(f2.Z) + e2 * Math.Abs(f2.Y); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis a10 p0 = v0.X * f0.Z - v0.Z * f0.X; p1 = v1.X * f0.Z - v1.Z * f0.X; p2 = v2.X * f0.Z - v2.Z * f0.X; r = e0 * Math.Abs(f0.Z) + e2 * Math.Abs(f0.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis a11 p0 = v0.X * f1.Z - v0.Z * f1.X; p1 = v1.X * f1.Z - v1.Z * f1.X; p2 = v2.X * f1.Z - v2.Z * f1.X; r = e0 * Math.Abs(f1.Z) + e2 * Math.Abs(f1.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis a12 p0 = v0.X * f2.Z - v0.Z * f2.X; p1 = v1.X * f2.Z - v1.Z * f2.X; p2 = v2.X * f2.Z - v2.Z * f2.X; r = e0 * Math.Abs(f2.Z) + e2 * Math.Abs(f2.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis20 p0 = -v0.X * f0.Y + v0.Y * f0.X; p1 = -v1.X * f0.Y + v1.Y * f0.X; p2 = -v2.X * f0.Y + v2.Y * f0.X; r = e0 * Math.Abs(f0.Y) + e1 * Math.Abs(f0.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis21 p0 = -v0.X * f1.Y + v0.Y * f1.X; p1 = -v1.X * f1.Y + v1.Y * f1.X; p2 = -v2.X * f1.Y + v2.Y * f1.X; r = e0 * Math.Abs(f1.Y) + e1 * Math.Abs(f1.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // axis22 p0 = -v0.X * f2.Y + v0.Y * f2.X; p1 = -v1.X * f2.Y + v1.Y * f2.X; p2 = -v2.X * f2.Y + v2.Y * f2.X; r = e0 * Math.Abs(f2.Y) + e1 * Math.Abs(f2.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) return false; // Test the three axes corresponding to the face normals of AABB b (category 1). // Exit if... // ... [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap if (Math.Max(Math.Max(v0.X, v1.X), v2.X) < -e0 || Math.Min(Math.Min(v0.X, v1.X), v2.X) > e0) return false; // ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap if (Math.Max(Math.Max(v0.Y, v1.Y), v2.Y) < -e1 || Math.Min(Math.Min(v0.Y, v1.Y), v2.Y) > e1) return false; // ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap if (Math.Max(Math.Max(v0.Z, v1.Z), v2.Z) < -e2 || Math.Min(Math.Min(v0.Z, v1.Z), v2.Z) > e2) return false; // Test separating axis corresponding to triangle face normal (category 2) SharpDX.Plane p = new SharpDX.Plane(); p.Normal = Vector3.Cross(f0, f1); p.D = Vector3.Dot(p.Normal, v0); return b.Test(p); }
private static void Step(GraphicsLoop graphicsLoop, Game game, InputSomethingOSDJFH input, Scene scene) { var expectedTicks = (int)(graphicsLoop.Statistics.FrameTime.TotalSeconds * 60); while (game.GameTimeService.Ticks < expectedTicks) { game.Tick(); } var viewProj = ComputeProjViewMatrix(graphicsLoop.Form.ClientSize); viewProj.Transpose(); var ray = Ray.GetPickRay(input.X, input.Y, new ViewportF(0, 0, 1280, 720, 1.0f, 100.0f), viewProj); var terrainOverlayNetwork = game.TerrainService.CompileSnapshot().OverlayNetworkManager.CompileTerrainOverlayNetwork(0); // rmb moves if (input.IsMouseDown(MouseButtons.Right)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.LandPolyNode.PointInLandPolygonNonrecursive(intersectionLocal.XY.LossyToIntVector2())) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); game.MovementSystemService.Pathfind(player, intersectionWorld); } } // lazaars if (input.IsKeyDown(Keys.Q)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.SectorNodeDescription.StaticMetadata.LocalBoundary.Contains(new SDPoint((int)intersectionLocal.X, (int)intersectionLocal.Y))) { continue; } if (!node.LandPolyNode.PointInLandPolygonNonrecursive(player.MovementComponent.LocalPositionIv2)) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); var barriersBvh = node.LandPolyNode.FindContourAndChildHoleBarriersBvh(); var q = new IntLineSegment2(player.MovementComponent.LocalPositionIv2, intersectionLocal.XY.LossyToIntVector2()); debugCanvas.Transform = node.SectorNodeDescription.WorldTransform; debugCanvas.DrawLine(q, StrokeStyle.RedHairLineSolid); foreach (var seg in barriersBvh.Segments) { debugCanvas.DrawLine(seg, StrokeStyle.RedThick5Solid); } var intersectingLeaves = barriersBvh.FindPotentiallyIntersectingLeaves(q); var tFar = 1.0; foreach (var bvhNode in intersectingLeaves) { for (var i = bvhNode.SegmentsStartIndexInclusive; i < bvhNode.SegmentsEndIndexExclusive; i++) { if (GeometryOperations.TryFindNonoverlappingSegmentSegmentIntersectionT(ref q, ref bvhNode.Segments[i], out var t)) { Console.WriteLine(t); tFar = Math.Min(tFar, t); } } } debugCanvas.Transform = Matrix4x4.Identity; debugCanvas.DrawLine(player.MovementComponent.WorldPosition, node.SectorNodeDescription.LocalToWorld(q.PointAt(tFar)), StrokeStyle.LimeThick5Solid); } } // i love rocks var rocksExisting = new List <Entity>(); foreach (var rock in rocks) { var distance = rock.MovementComponent.WorldPosition.To(player.MovementComponent.WorldPosition).Norm2D(); if (distance > player.MovementComponent.ComputedRadius) { rocksExisting.Add(rock); continue; } game.EntityService.RemoveEntity(rock); } rocks = rocksExisting; // W draws walls if (input.IsKeyJustDown(Keys.W)) { foreach (var node in terrainOverlayNetwork.TerrainNodes) { var origin = node.SectorNodeDescription.LocalToWorld(DoubleVector2.Zero); var normal = node.SectorNodeDescription.LocalToWorldNormal(DoubleVector3.UnitZ); var plane = new SDXPlane(ToSharpDX(origin), ToSharpDX(normal)); if (!plane.Intersects(ref ray, out SDXVector3 intersection)) { continue; } var intersectionLocal = node.SectorNodeDescription.WorldToLocal(intersection.ToOpenMoba()); if (!node.SectorNodeDescription.StaticMetadata.LocalBoundary.Contains(new SDPoint((int)intersectionLocal.X, (int)intersectionLocal.Y))) { continue; } // recompute intersectionWorld because floating point error in raycast logic var intersectionWorld = node.SectorNodeDescription.LocalToWorld(intersectionLocal.XY); fred.Add(intersectionWorld.XY.LossyToIntVector2()); // todo: we really need to iterate over LGVs rather than tnodes break; } } if (input.IsKeyJustDown(Keys.E)) { if (fred.Count > 0) { fred.RemoveAt(fred.Count - 1); } } if (input.IsKeyJustDown(Keys.R) && fred.Count >= 2) { var polyTree = PolylineOperations.ExtrudePolygon(fred, 10); var boundsLower = fred.Aggregate(new IntVector2(int.MaxValue, int.MaxValue), (a, b) => new IntVector2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y))); var boundsUpper = fred.Aggregate(new IntVector2(int.MinValue, int.MinValue), (a, b) => new IntVector2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y))); var bounds = new SDRectangle(boundsLower.X, boundsLower.Y, boundsUpper.X - boundsLower.X, boundsUpper.Y - boundsLower.Y); var holeStaticMetadata = new PrismHoleStaticMetadata( bounds, new[] { new Polygon2(polyTree.Childs[0].Contour) }, polyTree.Childs[0].Childs.Map(c => new Polygon2(((IEnumerable <IntVector2>)c.Contour).Reverse().ToList()))); var terrainHole = game.TerrainService.CreateHoleDescription(holeStaticMetadata); game.TerrainService.AddTemporaryHoleDescription(terrainHole); if (!input.IsKeyDown(Keys.ShiftKey)) { var removeEvent = game.CreateRemoveTemporaryHoleEvent(new GameTime(game.GameTimeService.Now.Ticks + 90), terrainHole); game.GameEventQueueService.AddGameEvent(removeEvent); } fred.Clear(); } }
// tests the aabb with triangle [v0,v1,v2] for intersection public static bool Test(AxisAlignedBoundingBox b, Vector3 v0, Vector3 v1, Vector3 v2) { float p0, p1, p2, r; // Compute box center and extents (if not already given in that format) Vector3 c = (b.Min + b.Max) * 0.5f; float e0 = (b.Max.X - b.Min.X) * 0.5f; float e1 = (b.Max.Y - b.Min.Y) * 0.5f; float e2 = (b.Max.Z - b.Min.Z) * 0.5f; // Translate triangle as conceptually moving AABB to origin v0 = v0 - c; v1 = v1 - c; v2 = v2 - c; // Compute edge vectors for triangle Vector3 f0 = v1 - v0, f1 = v2 - v1, f2 = v0 - v2; // Test axes a00..a22 (category 3) // Test axis a00 p0 = v0.Z * v1.Y - v0.Y * v1.Z; p2 = v2.Z * (v1.Y - v0.Y) - v2.Y * (v1.Z - v0.Z); r = e1 * Math.Abs(f0.Z) + e2 * Math.Abs(f0.Y); if (Math.Max(-Math.Max(p0, p2), Math.Min(p0, p2)) > r) { return(false); // Axis is a separating axis } // axis a01 p0 = -v0.Y * f1.Z + v0.Z * f1.Y; p1 = -v1.Y * f1.Z + v1.Z * f1.Y; p2 = -v2.Y * f1.Z + v2.Z * f1.Y; r = e1 * Math.Abs(f1.Z) + e2 * Math.Abs(f1.Y); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis a02 p0 = -v0.Y * f2.Z + v0.Z * f2.Y; p1 = -v1.Y * f2.Z + v1.Z * f2.Y; p2 = -v2.Y * f2.Z + v2.Z * f2.Y; r = e1 * Math.Abs(f2.Z) + e2 * Math.Abs(f2.Y); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis a10 p0 = v0.X * f0.Z - v0.Z * f0.X; p1 = v1.X * f0.Z - v1.Z * f0.X; p2 = v2.X * f0.Z - v2.Z * f0.X; r = e0 * Math.Abs(f0.Z) + e2 * Math.Abs(f0.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis a11 p0 = v0.X * f1.Z - v0.Z * f1.X; p1 = v1.X * f1.Z - v1.Z * f1.X; p2 = v2.X * f1.Z - v2.Z * f1.X; r = e0 * Math.Abs(f1.Z) + e2 * Math.Abs(f1.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis a12 p0 = v0.X * f2.Z - v0.Z * f2.X; p1 = v1.X * f2.Z - v1.Z * f2.X; p2 = v2.X * f2.Z - v2.Z * f2.X; r = e0 * Math.Abs(f2.Z) + e2 * Math.Abs(f2.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis20 p0 = -v0.X * f0.Y + v0.Y * f0.X; p1 = -v1.X * f0.Y + v1.Y * f0.X; p2 = -v2.X * f0.Y + v2.Y * f0.X; r = e0 * Math.Abs(f0.Y) + e1 * Math.Abs(f0.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis21 p0 = -v0.X * f1.Y + v0.Y * f1.X; p1 = -v1.X * f1.Y + v1.Y * f1.X; p2 = -v2.X * f1.Y + v2.Y * f1.X; r = e0 * Math.Abs(f1.Y) + e1 * Math.Abs(f1.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // axis22 p0 = -v0.X * f2.Y + v0.Y * f2.X; p1 = -v1.X * f2.Y + v1.Y * f2.X; p2 = -v2.X * f2.Y + v2.Y * f2.X; r = e0 * Math.Abs(f2.Y) + e1 * Math.Abs(f2.X); if (Math.Max(Math.Max(Math.Max(p0, p1), p2), Math.Min(Math.Min(p0, p1), p2)) > r) { return(false); } // Test the three axes corresponding to the face normals of AABB b (category 1). // Exit if... // ... [-e0, e0] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap if (Math.Max(Math.Max(v0.X, v1.X), v2.X) < -e0 || Math.Min(Math.Min(v0.X, v1.X), v2.X) > e0) { return(false); } // ... [-e1, e1] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap if (Math.Max(Math.Max(v0.Y, v1.Y), v2.Y) < -e1 || Math.Min(Math.Min(v0.Y, v1.Y), v2.Y) > e1) { return(false); } // ... [-e2, e2] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap if (Math.Max(Math.Max(v0.Z, v1.Z), v2.Z) < -e2 || Math.Min(Math.Min(v0.Z, v1.Z), v2.Z) > e2) { return(false); } // Test separating axis corresponding to triangle face normal (category 2) SharpDX.Plane p = new SharpDX.Plane(); p.Normal = Vector3.Cross(f0, f1); p.D = Vector3.Dot(p.Normal, v0); return(b.Test(p)); }
private void ProcessLeftMouse(EButtonEvent buttonEvent) { if (buttonEvent == EButtonEvent.Pressed && m_controlledTransform != null) { if (IsHovered) { Plane axisPlane; if (m_activeAxisList.Count > 1) { Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]); axisPlane = new Plane(m_gizmoLocation, planeNormal); } else { Vector3 planeNormal; if (Mode == EGizmoMode.Rotation) { // Rotation planeNormal = m_activeAxisList[0]; } else { //Translation / Scale Vector3 toCamera = m_frameViewInfo.ViewLocation - m_gizmoLocation; Vector3 planeTangent = Vector3.Cross(m_activeAxisList[0], toCamera); planeNormal = Vector3.Cross(m_activeAxisList[0], planeTangent); } axisPlane = new Plane(m_gizmoLocation, planeNormal); } World.ViewManager.GetViewInfo(out SSceneViewInfo viewInfo); Ray ray = CreateMouseRay(viewInfo); if (ray.Intersects(ref axisPlane, out Vector3 intersectionPoint)) { m_startLocation = intersectionPoint; switch (Mode) { case EGizmoMode.Translation: m_clickOffset = intersectionPoint - m_gizmoLocation; m_originalPosition = m_controlledTransform.WorldPosition; break; case EGizmoMode.Rotation: Vector3 toStart = m_startLocation - m_gizmoLocation; m_rotationDragAxis = Vector3.Cross(toStart, m_activeAxisList[0]); m_rotationDragAxis.Normalize(); m_originalRotation = m_controlledTransform.WorldRotation; break; case EGizmoMode.Scale: m_originalScale = m_controlledTransform.WorldScale; m_scaleAxis = Vector3.Zero; foreach (Vector3 axis in m_activeAxisList) { m_scaleAxis += Vector3.Transform(axis, Quaternion.Invert(m_controlledTransform.WorldRotation)); } m_scaleAxis.Normalize(); m_scaleSizeFactor = m_originalScale.Length(); break; default: throw new ArgumentOutOfRangeException(); } IsClicked = true; } } } else if (m_controlledTransform != null) { if (IsClicked) { switch (Mode) { case EGizmoMode.Translation: Vector3 newPosition = m_controlledTransform.WorldPosition; if (newPosition != m_originalPosition) { OnTranslationChanged?.Invoke(m_controlledTransform, m_originalPosition, newPosition); } break; case EGizmoMode.Rotation: Quaternion newRotation = m_controlledTransform.WorldRotation; if (newRotation != m_originalRotation) { OnRotationChanged?.Invoke(m_controlledTransform, m_originalRotation, newRotation); } break; case EGizmoMode.Scale: Vector3 newScale = m_controlledTransform.WorldScale; if (newScale != m_originalScale) { OnScaleChanged?.Invoke(m_controlledTransform, m_originalScale, newScale); } break; } } IsClicked = false; m_totalAngleDelta = 0.0f; m_totalScaleDelta = 0.0f; } }
public Plane(SharpDX.Plane plane) { this.splane = plane; }
public Plane(Vector3 p1, Vector3 p2, Vector3 p3) { this.Point = p1; this.splane = new SharpDX.Plane(p1, p2, p3); }
public Plane(Vector3 pointOnPlane, Vector3 normal) { this.Point = pointOnPlane; this.splane = new SharpDX.Plane(pointOnPlane, normal); }