private void btnReset_Click(object sender, EventArgs e) { _sphere = new Sphere(GetMiddlePoint(), new DoubleVector(0, 1, 0, -1, 0, 0), 200); _prevRadians = 0; _currentRadians = 0; trackBar1.Value = 0; }
/// <summary> /// This will return a transform for a model or camera so that the model/camera will be placed and oriented just like /// the physical sphere. Just set my return to model.Transform /// </summary> /// <param name="modelSphere">The tranform will be applied to the model that is described by this modelSphere</param> /// <param name="physicalSphere">This is where the model should be transformed to (the physical location)</param> public static Transform3D GetTransfromForSlaving(Sphere modelSphere, Sphere physicalSphere) { Transform3DGroup retVal = new Transform3DGroup(); // Rotate MyQuaternion rotation = modelSphere.DirectionFacing.GetAngleAroundAxis(physicalSphere.DirectionFacing); retVal.Children.Add(new RotateTransform3D(new QuaternionRotation3D(new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W)))); //// Translate //MyVector offset = physicalSphere.Position - modelSphere.Position; //retVal.Children.Add(new TranslateTransform3D(offset.X, offset.Y, offset.Z)); // Exit Function return retVal; }
/// <summary> /// The only reason you would pass in your own guid is when loading a previously saved scene (the token /// works good for processing in ram, but when stuff needs to go to file, use the guid) /// </summary> public RadarBlip(Sphere sphere, CollisionStyle collisionStyle, RadarBlipQual blipQual, long token, Guid objectID) { _sphere = sphere; _collisionStyle = collisionStyle; _token = token; _qual = blipQual; _qualInt = _qual.GetHashCode(); _objectID = objectID; }
/// <summary> /// This is the basic constructor. These are the only things that need to be passed in. /// </summary> public RadarBlip(Sphere sphere, CollisionStyle collisionStyle, RadarBlipQual blipQual, long token) : this(sphere, collisionStyle, blipQual, token, Guid.NewGuid()) { }
public static MyVector IsIntersecting_SphereTriangle(Sphere sphere, Triangle triangle) { // Find the point on the triangle closest to the sphere's center MyVector retVal = triangle.GetClosestPointOnTriangle(sphere.Position); // Sphere and triangle intersect if the (squared) distance from sphere // center to point is less than the (squared) sphere radius MyVector v = retVal - sphere.Position; if (MyVector.Dot(v, v) <= sphere.Radius * sphere.Radius) { return retVal; } else { return null; } }
/// <summary> /// This static method just returns the point of intersection (or null). /// </summary> public static MyVector IsIntersecting_SphereSphere(Sphere sphere1, Sphere sphere2) { MyVector lineBetween = sphere2.Position - sphere1.Position; double distanceSquared = lineBetween.GetMagnitudeSquared(); double sumRadii = sphere1.Radius + sphere2.Radius; // See if they missed each other if (distanceSquared > sumRadii * sumRadii) { return null; } // Figure out the percent of penetration double distance = Math.Sqrt(distanceSquared); double percentPenetrating = (sumRadii - distance) / sumRadii; // Turn lineBetween into a vector the length of ball1's radius lineBetween.BecomeUnitVector(); lineBetween.Multiply(sphere1.Radius); lineBetween.Multiply(1 - percentPenetrating); // shorten the line by the amount penetrating // Exit Function return sphere1.Position + lineBetween; }
/// <summary> /// This overload simply returns a boolean (less expensive) /// </summary> public static bool IsIntersecting_SphereSphere_Bool(Sphere sphere1, Sphere sphere2) { MyVector lineBetween = sphere2.Position - sphere1.Position; double sumRadii = sphere1.Radius + sphere2.Radius; return lineBetween.GetMagnitudeSquared() <= sumRadii * sumRadii; }
/// <summary> /// This overload compares the sphere and polygon (no up front sphere/sphere check) /// </summary> public static MyVector[] IsIntersecting_SpherePolygon(Sphere sphere, MyVector polygonCenterPoint, IMyPolygon polygon) { List<MyVector> retVal = new List<MyVector>(); // See if I need to recurse on the polygon's children if (polygon.HasChildren) { #region Test Child Polys MyVector[] curCollisions; // Call myself for each of the child polys foreach (IMyPolygon childPoly in polygon.ChildPolygons) { curCollisions = IsIntersecting_SpherePolygon(sphere, polygonCenterPoint, childPoly); if (curCollisions != null) { retVal.AddRange(curCollisions); } } if (retVal.Count > 0) { return retVal.ToArray(); } else { return null; } #endregion } #region Test Edges // Compare the sphere with the edges MyVector curCollision; foreach (Triangle triangle in polygon.Triangles) { curCollision = CollisionHandler.IsIntersecting_SphereTriangle(sphere, polygonCenterPoint + triangle); if (curCollision != null) { retVal.Add(curCollision); } } if (retVal.Count > 0) { return retVal.ToArray(); } #endregion //TODO: collide the sphere with the interior of the poly // Exit Function return null; }
/// <summary> /// This overload will do a sphere/sphere check first, and if those intersect, then it will do the more /// expensive sphere/poly check /// </summary> /// <param name="polygonSphere">A sphere that totally surrounds the polygon</param> public static MyVector[] IsIntersecting_SpherePolygon(Sphere sphere, MyVector polygonCenterPoint, IMyPolygon polygon, Sphere polygonSphere) { // Do a sphere/sphere check first if (!CollisionHandler.IsIntersecting_SphereSphere_Bool(sphere, polygonSphere)) { return null; } // The spheres intersect. Now do the sphere/poly check return IsIntersecting_SpherePolygon(sphere, polygonCenterPoint, polygon); }
/* // It looks like his definition of a polygon is simply a list of vectors. It doesn't appear to be made of triangles, // but arbitrary sided faces. // // Actually, the more I think about it, I think is definition of a poly is strictly 2D. This should be replaced with // triangle //typedef std::vector<Vector3> poly_t; // This function should probably be moved to triangle (assuming it's not the same as GetClosestPointOnTriangle()) private bool PointInPoly(MyVector p, poly_t v, Vector n) { for (int i = 0; i < v.size(); i++) { if (Vector.Dot(p - v[i], Vector.Cross(n, v[(i + 1) % v.size()] - v[i]), false) < 0d) { return false; } } return true; } private Vector ClosestPointOnPlane(Vector p, Vector n, float d) { return p - (n * (Vector.Dot(p, n, false) - d)); } private Vector ClosestPointOnSegment(Vector p, Vector p1, Vector p2) { Vector dir = p2 - p1; Vector diff = p - p1; double t = Vector.Dot(diff, dir, false) / Vector.Dot(dir, dir, false); if (t <= 0.0f) { return p1; } else if (t >= 1.0f) { return p2; } return p1 + t * dir; } Vector3 ClosestPointOnPoly(const Vector3& p, const poly_t& v) { // Poly plane Vector3 n = Vector3::Normalize(Vector3::Cross(v[1] - v[0], v[2] - v[0])); float d = v[0].Dot(n); // Closest point on plane to p Vector3 closest = ClosestPointOnPlane(p, n, d); // If p is in the poly, we've found our closest point if (PointInPoly(closest, v, n)) return closest; // Else find the closest point to a poly edge bool found = false; float minDist; for (int i = 0; i < v.size(); ++i) { Vector3 temp = ClosestPointOnSegment(p, v[i], v[(i + 1) % v.size()]); float dist = Vector3::LengthSquared(p - temp); if (!found || dist < minDist) { found = true; minDist = dist; closest = temp; } } return closest; } bool IntersectSpherePoly(const Vector3& c, float r, const poly_t& poly, Vector3& n, float& d) { Vector3 p = ClosestPointOnPoly(c, poly); n = c - p; float dist = n.LengthSquared(); if (dist > r * r) return false; dist = Math::Sqrt(dist); n /= dist; d = r - dist; return true; } */ #endregion public static MyVector[] TestCollision(out MyVector trueCollision, Sphere sphere, MyVector polygonCenterPoint, IMyPolygon polygon, Sphere polygonSphere) { MyVector[] retVal = IsIntersecting_SpherePolygon(sphere, polygonCenterPoint, polygon, polygonSphere); if (retVal == null) { trueCollision = null; return null; } // Find the closest point double minDist = double.MaxValue; int minDistIndex = -1; for (int returnCntr = 0; returnCntr < retVal.Length; returnCntr++) { double curDist = Utility3D.GetDistance3D(sphere.Position, retVal[returnCntr]); if (curDist < minDist) { minDist = curDist; minDistIndex = returnCntr; } } trueCollision = retVal[minDistIndex]; return retVal; }