///////////////////////////////////////// public MeshRayTestOptimized(Vector3F[] vertices, int[] indices) { this.vertices = vertices; this.indices = indices; if (vertices.Length != 0 && indices.Length != 0) { var bounds = Bounds.Cleared; foreach (var vertex in vertices) { bounds.Add(vertex); } var initSettings = new OctreeContainer.InitSettings(); initSettings.InitialOctreeBounds = bounds; initSettings.OctreeBoundsRebuildExpand = Vector3.Zero; initSettings.MinNodeSize = bounds.GetSize() / 50; octreeContainer = new OctreeContainer(initSettings); for (int nTriangle = 0; nTriangle < indices.Length / 3; nTriangle++) { var vertex0 = vertices[indices[nTriangle * 3 + 0]]; var vertex1 = vertices[indices[nTriangle * 3 + 1]]; var vertex2 = vertices[indices[nTriangle * 3 + 2]]; var triangleBounds = new Bounds(vertex0); triangleBounds.Add(vertex1); triangleBounds.Add(vertex2); octreeContainer.AddObject(triangleBounds, 1); } } }
protected override void OnSpaceBoundsUpdate(ref SpaceBounds newBounds) { base.OnSpaceBoundsUpdate(ref newBounds); //!!!!bounding sphere switch (Shape.Value) { case ShapeEnum.Box: newBounds = new SpaceBounds(GetBox().ToBounds()); break; case ShapeEnum.Sphere: newBounds = new SpaceBounds(GetSphere()); break; case ShapeEnum.Ray: { var ray = GetRay(); Bounds b = new Bounds(ray.Origin); b.Add(ray.GetEndPoint()); newBounds = new SpaceBounds(b); } break; } }
public Bounds ToBounds() { Bounds result = new Bounds(Point1); result.Add(Point2); result.Expand(Radius); return(result); }
////!!!! ///// <summary>Computes the convex hull of a polygon, in clockwise order in a Y-up ///// coordinate system (counterclockwise in a Y-down coordinate system).</summary> ///// <remarks>Uses the Monotone Chain algorithm, a.k.a. Andrew's Algorithm.</remarks> //public static List<Vector2> ComputeConvexHull( IEnumerable<Vector2> points ) //{ // var list = new List<Vector2>( points ); // return ComputeConvexHull( list, true ); //} //public static List<Vector2> ComputeConvexHull( List<Vector2> points, bool sortInPlace )//= false ) //{ // if( !sortInPlace ) // points = new List<Vector2>( points ); // points.Sort( ( a, b ) => a.X == b.X ? a.Y.CompareTo( b.Y ) : ( a.X > b.X ? 1 : -1 ) ); // // Importantly, DList provides O(1) insertion at beginning and end // List<Vector2> hull = new List<Vector2>(); // int L = 0, U = 0; // size of lower and upper hulls // // Builds a hull such that the output polygon starts at the leftmost point. // for( int i = points.Count - 1; i >= 0; i-- ) // { // Vector2 p = points[ i ], p1; // // build lower hull (at end of output list) // while( L >= 2 && ( p1 = hull.Last ).Sub( hull[ hull.Count - 2 ] ).Cross( p.Sub( p1 ) ) >= 0 ) // { // hull.RemoveAt( hull.Count - 1 ); // L--; // } // hull.PushLast( p ); // L++; // // build upper hull (at beginning of output list) // while( U >= 2 && ( p1 = hull.First ).Sub( hull[ 1 ] ).Cross( p.Sub( p1 ) ) <= 0 ) // { // hull.RemoveAt( 0 ); // U--; // } // if( U != 0 ) // share the point added above, except in the first iteration // hull.PushFirst( p ); // U++; // } // hull.RemoveAt( hull.Count - 1 ); // return hull; //} void GetDirectionalLightShadowsCascadeHullPlanes(ViewportRenderingContext context, LightItem lightItem, int cascadeIndex, out Plane[] planes, out Bounds bounds) { var cornerPoints = GetDirectionalLightShadowsCameraCornerPoints(context, cascadeIndex); var inputVertices = new List <Vector3>(cornerPoints.Length * 2); inputVertices.AddRange(cornerPoints); foreach (var point in cornerPoints) { inputVertices.Add(point - lightItem.data.Rotation.ToQuaternion().GetForward() * ShadowDirectionalLightExtrusionDistance); } var projectMatrix = lightItem.data.Rotation.ToQuaternion().GetInverse(); var unprojectMatrix = lightItem.data.Rotation.ToQuaternion(); var projected2D = new Vector2[cornerPoints.Length]; for (int n = 0; n < projected2D.Length; n++) { var p = projectMatrix * cornerPoints[n]; projected2D[n] = new Vector2(p.Y, p.Z); } var convex = MathAlgorithms.GetConvexByPoints(projected2D); var planesList = new List <Plane>(convex.Count); for (int n = 0; n < convex.Count; n++) { var p1 = convex[n]; var p2 = convex[(n + 1) % convex.Count]; var u1 = unprojectMatrix * new Vector3(0, p1.X, p1.Y); var u2 = unprojectMatrix * new Vector3(0, p2.X, p2.Y); var u3 = unprojectMatrix * new Vector3(1, p2.X, p2.Y); planesList.Add(Plane.FromPoints(u1, u3, u2)); } planes = planesList.ToArray(); ////!!!!глючит //ConvexHullAlgorithm.Create( inputVertices.ToArray(), out planes ); bounds = Bounds.Cleared; foreach (var p in inputVertices) { bounds.Add(p); } }
public bool Contains(Vector3 point) { if (Point1 != Point2) { double radiusSquared = Radius * Radius; if ((Point1 - point).LengthSquared() <= radiusSquared) { return(true); } if ((Point2 - point).LengthSquared() <= radiusSquared) { return(true); } Vector3 projectPoint; MathAlgorithms.ProjectPointToLine(ref Point1, ref Point2, ref point, out projectPoint); Bounds pointsBounds = new Bounds(Point1); pointsBounds.Add(Point2); if (pointsBounds.Contains(projectPoint)) { if ((projectPoint - point).LengthSquared() <= radiusSquared) { return(true); } } return(false); } else { return(new Sphere(Point1, Radius).Contains(point)); } }
protected override void OnSpaceBoundsUpdate(ref SpaceBounds newBounds) { base.OnSpaceBoundsUpdate(ref newBounds); if (rigidBody != null) { var tr = Transform.Value; var trNoScale = new Transform(tr.Position, tr.Rotation); Bounds bounds = Bounds.Cleared; foreach (var p in rigidBodyLocalPoints) { bounds.Add(trNoScale * new Vector3(p, 0)); } if (!bounds.IsCleared()) { bounds.Expand(new Vector3(0, 0, 0.001)); var b = new SpaceBounds(bounds); newBounds = SpaceBounds.Merge(newBounds, b); } } }
public void ToBounds(out Bounds result) { result = new Bounds(Point1); result.Add(Point2); result.Expand(Radius); }
public Bounds GetVisualBounds() { var transform = Transform.Value; var pos = transform.Position; var rot = transform.Rotation; var bounds = new Bounds(pos); double aspectRatio = AspectRatio; if (aspectRatio == 0) { aspectRatio = 1; } double halfWidth; double halfHeight; if (Projection.Value == ProjectionType.Perspective) { double tan = Math.Tan(FieldOfView.Value.InRadians() / 2); halfWidth = tan * FarClipPlane.Value * aspectRatio; halfHeight = tan * FarClipPlane.Value; } else { halfWidth = Height * .5 * aspectRatio; halfHeight = Height * .5; } var frustum = new Frustum(true, Projection.Value, pos, rot, NearClipPlane.Value, FarClipPlane.Value, halfWidth, halfHeight); var frustumPoints = frustum.Points; switch (Projection.Value) { case ProjectionType.Perspective: { var points = new Vector3[8]; { for (int n = 4; n < 8; n++) { double distance = GetVisualLength(); var dir = (frustumPoints[n] - pos).GetNormalize() * distance; var p = pos + dir * distance; points[n] = p; } } for (int n = 4; n < 8; n++) { bounds.Add(points[n]); } } break; case ProjectionType.Orthographic: { //!!!! } break; } return(bounds); }
protected internal override IList <Fixture> CreateShape(Body body, Transform shapeTransform, List <Vector2> rigidBodyLocalPoints) { var epsilon = 0.0001f; //clear data processedVertices = null; processedIndices = null; processedTrianglesToSourceIndex = null; //get source geometry if (!GetSourceData(out var sourceVertices, out var sourceIndices)) { return(null); } //check valid data if (CheckValidData) { if (!MathAlgorithms.CheckValidVertexIndexBuffer(sourceVertices.Length, sourceIndices, false)) { Log.Info("Component_CollisionShape2D_Mesh: CreateShape: Invalid source data."); return(null); } } //process geometry if (MergeEqualVerticesRemoveInvalidTriangles) { MathAlgorithms.MergeEqualVerticesRemoveInvalidTriangles(sourceVertices, sourceIndices, epsilon, epsilon, out processedVertices, out processedIndices, out processedTrianglesToSourceIndex); } else { processedVertices = sourceVertices; processedIndices = sourceIndices; } if (ShapeType.Value == ShapeTypeEnum.Auto && ParentRigidBody.MotionType.Value == Component_RigidBody2D.MotionTypeEnum.Dynamic && MathAlgorithms.IsMeshConvex(processedVertices, processedIndices, epsilon) || ShapeType.Value == ShapeTypeEnum.Convex) { //convex var points = new List <Vector2>(processedVertices.Length); Bounds bounds = Bounds.Cleared; foreach (var p in processedVertices) { var p2 = shapeTransform * new Vector3(p.ToVector2(), 0); points.Add(p2.ToVector2()); bounds.Add(p2); //points.Add( ( shapeTransform * new Vector3( p.ToVector2(), 0 ) ).ToVector2() ); } var fixtures = new List <Fixture>(); { var currentList = new Vertices(points.Count); for (int vertex = 0; vertex < points.Count; vertex++) { currentList.Add(Physics2DUtility.Convert(points[vertex])); if (currentList.Count == Settings.MaxPolygonVertices) { fixtures.Add(body.CreatePolygon(currentList, 0)); currentList = new Vertices(); currentList.Add(Physics2DUtility.Convert(points[0])); currentList.Add(Physics2DUtility.Convert(points[vertex])); } } if (currentList.Count >= 3) { fixtures.Add(body.CreatePolygon(currentList, 0)); } } //rigidBodyLocalPoints { var r = bounds.ToRectangle(); rigidBodyLocalPoints.Add(r.LeftTop); rigidBodyLocalPoints.Add(r.RightTop); rigidBodyLocalPoints.Add(r.RightBottom); rigidBodyLocalPoints.Add(r.LeftBottom); } if (fixtures.Count != 0) { return(fixtures.ToArray()); } //var points = new List<Vector2>(); //foreach( var p in processedVertices ) // points.Add( ( shapeTransform * new Vector3( p.ToVector2(), 0 ) ).ToVector2() ); //var vertices = new Vertices( points.Count ); //foreach( var p in points ) // vertices.Add( Physics2DUtility.Convert( p ) ); //if( vertices.Count > 1 ) // return new Fixture[] { body.CreatePolygon( vertices, 0 ) }; } else { //chain shapes var fixtures = new List <Fixture>(); Rectangle bounds = Rectangle.Cleared; //!!!! ESet <(Vector2, Vector2)> wasAdded = new ESet <(Vector2, Vector2)>(); void Add(Vector2 p1, Vector2 p2) { if (p1 != p2 && !wasAdded.Contains((p1, p2)) && !wasAdded.Contains((p2, p1))) { wasAdded.Add((p1, p2)); fixtures.Add(body.CreateEdge(Physics2DUtility.Convert(p1), Physics2DUtility.Convert(p2))); bounds.Add(p1); bounds.Add(p2); } } for (int nTriangle = 0; nTriangle < processedIndices.Length / 3; nTriangle++) { var v0 = shapeTransform * processedVertices[processedIndices[nTriangle * 3 + 0]]; var v1 = shapeTransform * processedVertices[processedIndices[nTriangle * 3 + 1]]; var v2 = shapeTransform * processedVertices[processedIndices[nTriangle * 3 + 2]]; Add(v0.ToVector2(), v1.ToVector2()); Add(v1.ToVector2(), v2.ToVector2()); Add(v2.ToVector2(), v0.ToVector2()); } //rectangle //for( int nTriangle = 0; nTriangle < processedIndices.Length / 3; nTriangle++ ) //{ // //!!!!slowly shapeTransform * // var v0 = shapeTransform * processedVertices[ processedIndices[ nTriangle * 3 + 0 ] ]; // var v1 = shapeTransform * processedVertices[ processedIndices[ nTriangle * 3 + 1 ] ]; // var v2 = shapeTransform * processedVertices[ processedIndices[ nTriangle * 3 + 2 ] ]; // bounds.Add( v0 ); // bounds.Add( v1 ); // bounds.Add( v2 ); //} //var vertices = new Vertices(); //var r = bounds.ToRectangle(); //vertices.Add( Physics2DUtility.Convert( r.LeftTop ) ); //vertices.Add( Physics2DUtility.Convert( r.RightTop ) ); //vertices.Add( Physics2DUtility.Convert( r.RightBottom ) ); //vertices.Add( Physics2DUtility.Convert( r.LeftBottom ) ); //local points for space bounds calculation rigidBodyLocalPoints.Add(bounds.LeftTop); rigidBodyLocalPoints.Add(bounds.RightTop); rigidBodyLocalPoints.Add(bounds.RightBottom); rigidBodyLocalPoints.Add(bounds.LeftBottom); return(fixtures.ToArray()); //return new Fixture[] { body.CreateLoopShape( vertices ) }; } return(null); }
public bool Intersects(ref Bounds bounds) { if (Bounds != null && Planes != null) { //Planes + Bounds if (Bounds.Value.Intersects(ref bounds) || BoundsPlanesIntersects(bounds, Planes)) { return(true); } } else if (Planes != null) { //Planes if (BoundsPlanesIntersects(bounds, Planes)) { return(true); } } else if (Frustum != null) { //Frustum Bounds frustumBounds = new Bounds(Frustum.Points[0]); for (int n = 1; n < 8; n++) { frustumBounds.Add(Frustum.Points[n]); } if (frustumBounds.Intersects(ref bounds) || BoundsPlanesIntersects(bounds, Frustum.Planes)) { return(true); } } else if (Bounds != null) { //Bounds if (Bounds.Value.Intersects(ref bounds)) { return(true); } } else if (Box != null) { //Box if (Box.Value.Intersects(ref bounds)) { return(true); } } else if (Sphere != null) { //Sphere if (Sphere.Value.Intersects(ref bounds)) { return(true); } } else if (Ray != null) { //Ray if (bounds.Intersects(Ray.Value)) { return(true); } } return(false); }