// http://www.geometrictools.com/Documentation/DistancePointLine.pdf public static float DistanceToLine_3(SSRay ray, Vector3 point) { float t0 = Vector3.Dot(ray.dir, (point - ray.pos)) / Vector3.Dot(ray.dir, ray.dir); float distance = (point - (ray.pos + (t0 * ray.dir))).Length; return(distance); }
public override bool Intersect(ref SSRay worldSpaceRay) { // transform the ray into object space SSRay localRay = worldSpaceRay.Transformed(this.worldMat.Inverted()); float distanceToSphereOrigin = OpenTKHelper.DistanceToLine(localRay,Vector3.Zero); bool result = distanceToSphereOrigin <= this.radius; #if false Console.WriteLine("_____________________________"); Console.WriteLine("sphere intersect test {0} vs radius {1}",distanceToSphereOrigin,radius); Console.WriteLine("worldray {0}",worldSpaceRay); Console.WriteLine("localray {0}",localRay); Console.WriteLine("objectPos {0}",this.Pos); if (result) { Console.WriteLine(" ----> hit <-----"); Console.WriteLine("----------------------------"); } else { Console.WriteLine(" miss"); Console.WriteLine("----------------------------"); } #endif return result; }
public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { SSRay localRay = worldSpaceRay.Transformed (this.worldMat.Inverted ()); SSAbstractMesh mesh = this._mesh; bool hit = false; float localNearestContact = float.MaxValue; if (mesh == null) { return true; // no mesh to test } else { // precise meshIntersect bool global_hit = mesh.traverseTriangles ((state, V1, V2, V3) => { float contact; if (OpenTKHelper.TriangleRayIntersectionTest (V1, V2, V3, localRay.pos, localRay.dir, out contact)) { hit = true; localNearestContact = Math.Min (localNearestContact, contact); Console.WriteLine ("Triangle Hit @ {0} : Object {1}", contact, Name); } return false; // don't short circuit }); if (hit) { float worldSpaceContactDistance = -localNearestContact * this.Scale.LengthFast; Console.WriteLine ("Nearest Triangle Hit @ {0} vs Sphere {1} : Object {2}", worldSpaceContactDistance, distanceAlongRay, Name); distanceAlongRay = worldSpaceContactDistance; } return global_hit || hit; } }
public SSObject Intersect(ref SSRay worldSpaceRay) { SSObject nearestIntersection = null; float nearestDistance = float.MinValue; // distances get "smaller" as they move in camera direction for some reason (why?) foreach (var obj in m_objects) { float distanceAlongRay; if (obj.Intersect(ref worldSpaceRay, out distanceAlongRay)) { // intersection must be in front of the camera ( < 0.0 ) if (distanceAlongRay < 0.0) { Console.WriteLine("intersect: [{0}] @distance: {1}", obj.Name, distanceAlongRay); // then we want the nearest one (numerically biggest if (distanceAlongRay > nearestDistance) { nearestDistance = distanceAlongRay; nearestIntersection = obj; } } } } return(nearestIntersection); }
public SSObjectRay(SSRay ray) : base() { this.ray = ray; this.Pos = ray.pos; // the ray is in world-space, so we adjust our object pos, and then save the ray (so we have the world-space ray.dir) // NOTE: technically the ray.pos is still the world-space pos... }
public SSObjectRay(SSRay ray) : base() { this.ray = ray; this.Pos = ray.pos; this.renderState.alphaBlendingOn = false; this.renderState.lighted = false; // the ray is in world-space, so we adjust our object pos, and then save the ray (so we have the world-space ray.dir) // NOTE: technically the ray.pos is still the world-space pos... }
/// <summary> /// Distance from a ray to a point at the closest spot. The ray is assumed to be infinite length. /// </summary> /// <param name="ray"></param> /// <param name="point"></param> /// <returns></returns> public static float DistanceToLine(SSRay ray, Vector3 point) { // http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line Vector3 a = ray.pos; Vector3 n = ray.dir; Vector3 p = point; return ((a-p) - Vector3.Dot((a-p),n) * n).Length; }
/// <summary> /// Distance from a ray to a point at the closest spot. The ray is assumed to be infinite length. /// </summary> /// <param name="ray"></param> /// <param name="point"></param> /// <returns></returns> public static float DistanceToLine(SSRay ray, Vector3 point, out float distanceAlongRay) { // http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line Vector3 a = ray.pos; Vector3 n = ray.dir; Vector3 p = point; var t = Vector3.Dot((a-p),n); distanceAlongRay = -t; return ((a-p) - t * n).Length; }
/// <summary> /// Distance from a ray to a point at the closest spot. The ray is assumed to be infinite length. /// </summary> /// <param name="ray"></param> /// <param name="point"></param> /// <returns></returns> public static float DistanceToLine(SSRay ray, Vector3 point, out float distanceAlongRay) { // http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line Vector3 a = ray.pos; Vector3 n = ray.dir; Vector3 p = point; distanceAlongRay = Vector3.Dot((a - p), n); return(((a - p) - distanceAlongRay * n).Length); }
// MouseToWorldRay // // This takes the view matricies, and a window-local mouse coordinate, and returns a ray in world space. public static SSRay MouseToWorldRay( Matrix4 projection, Matrix4 view, System.Drawing.Size viewport, Vector2 mouse) { // these mouse.Z values are NOT scientific. // Near plane needs to be < -1.5f or we have trouble selecting objects right in front of the camera. (why?) Vector3 pos1 = UnProject(ref projection, view, viewport, new Vector3(mouse.X, mouse.Y, -1.5f)); // near Vector3 pos2 = UnProject(ref projection, view, viewport, new Vector3(mouse.X, mouse.Y, 1.0f)); // far return(SSRay.FromTwoPoints(pos1, pos2)); }
public virtual bool Intersect(ref SSRay worldSpaceRay, out float distanceAlongRay) { distanceAlongRay = 0.0f; if (localBoundingSphereRadius > 0f) { var objBoundingSphere = worldBoundingSphere; if (objBoundingSphere.IntersectsRay(ref worldSpaceRay, out distanceAlongRay)) { return(PreciseIntersect(ref worldSpaceRay, ref distanceAlongRay)); } } distanceAlongRay = 0f; return(false); }
public override bool preciseIntersect(ref SSRay localRay, out float localRayContact) { localRayContact = float.PositiveInfinity; foreach (var subset in geometrySubsets) { float contact; if (subset.triangleMesh.preciseIntersect(ref localRay, out contact) && contact < localRayContact) { localRayContact = contact; } } return(localRayContact < float.PositiveInfinity); }
public virtual bool Intersect(ref SSRay worldSpaceRay, out float distanceAlongRay) { distanceAlongRay = 0.0f; if (boundingSphere != null) { if (boundingSphere.Intersect(ref worldSpaceRay, out distanceAlongRay)) { if (collisionShell != null) { return(collisionShell.Intersect(ref worldSpaceRay, out distanceAlongRay)); } else { return(PreciseIntersect(ref worldSpaceRay, ref distanceAlongRay)); } } } return(false); }
// Ray to AABB (AxisAlignedBoundingBox) // http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms public static bool intersectRayAABox2(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { Vector3d T_1 = new Vector3d(); Vector3d T_2 = new Vector3d(); // vectors to hold the T-values for every direction double t_near = double.MinValue; // maximums defined in float.h double t_far = double.MaxValue; for (int i = 0; i < 3; i++) //we test slabs in every direction { if (ray.dir[i] == 0) // ray parallel to planes in this direction { if ((ray.pos[i] < box.Min[i]) || (ray.pos[i] > box.Max[i])) { return(false); // parallel AND outside box : no intersection possible } } else // ray not parallel to planes in this direction { T_1[i] = (box.Min[i] - ray.pos[i]) / ray.dir[i]; T_2[i] = (box.Max[i] - ray.pos[i]) / ray.dir[i]; if (T_1[i] > T_2[i]) // we want T_1 to hold values for intersection with near plane { var swp = T_2; // swap T_1 = swp; T_2 = T_1; } if (T_1[i] > t_near) { t_near = T_1[i]; } if (T_2[i] < t_far) { t_far = T_2[i]; } if ((t_near > t_far) || (t_far < 0)) { return(false); } } } tnear = (float)t_near; tfar = (float)t_far; // put return values in place return(true); // if we made it here, there was an intersection - YAY }
public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongWorldRay) { SSRay localRay = worldSpaceRay.Transformed (this.worldMat.Inverted ()); if (this.Mesh != null) { float localNearestContact; bool ret = this.Mesh.preciseIntersect(ref localRay, out localNearestContact); if (ret) { Vector3 localContactPt = localRay.pos + localNearestContact * localRay.dir; Vector3 worldContactPt = Vector3.Transform(localContactPt, this.worldMat); distanceAlongWorldRay = (worldContactPt - worldSpaceRay.pos).Length; //Console.WriteLine ("Nearest Triangle Hit @ {0} vs Sphere {1} : Object {2}", worldSpaceContactDistance, distanceAlongRay, Name); } else { distanceAlongWorldRay = float.PositiveInfinity; } return ret; } else { distanceAlongWorldRay = float.PositiveInfinity; return false; } }
} // fn public static bool intersectRayAABox1(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { // r.dir is unit direction vector of ray Vector3 dirfrac = new Vector3(); float t; dirfrac.X = 1.0f / ray.dir.X; dirfrac.Y = 1.0f / ray.dir.Y; dirfrac.Z = 1.0f / ray.dir.Z; // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner // r.org is origin of ray float t1 = (box.Min.X - ray.pos.X) * dirfrac.X; float t2 = (box.Max.X - ray.pos.X) * dirfrac.X; float t3 = (box.Min.Y - ray.pos.Y) * dirfrac.Y; float t4 = (box.Max.Y - ray.pos.Y) * dirfrac.Y; float t5 = (box.Min.Z - ray.pos.Z) * dirfrac.Z; float t6 = (box.Max.Z - ray.pos.Z) * dirfrac.Z; float tmin = Math.Max(Math.Max(Math.Min(t1, t2), Math.Min(t3, t4)), Math.Min(t5, t6)); float tmax = Math.Min(Math.Min(Math.Max(t1, t2), Math.Max(t3, t4)), Math.Max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { t = tmax; return(false); } // if tmin > tmax, ray doesn't intersect AABB if (tmin > tmax) { t = tmax; return(false); } t = tmin; return(true); }
/// <summary> /// Whether the plane and a ray intersect and where /// http://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection /// </summary> public bool intersects(ref SSRay ray, out Vector3 intersectPt) { Vector3 n = this.normal; var rayDirDotPlaneN = Vector3.Dot(ray.dir, n); if (Math.Abs(rayDirDotPlaneN) < epsilon) { // rayDirDotPlaneN == 0; ray and the plane are parallel intersectPt = new Vector3 (float.NaN); return false; } else { // plug parametric equation of a line into the plane normal equation // solve (rayPos + rayDir * t - planeP0) dot planeN == 0 // rayDir dot planeN + (rayPos - planeP0) dot planeN == 0 Vector3 p0 = this.pickASurfacePoint(); float t = Vector3.Dot(p0 - ray.pos, n) / rayDirDotPlaneN; if (t < -epsilon) { // this means that the line-plane intersection is behind the ray origin (in the wrong // direction). in the context of a ray this means no intersection intersectPt = new Vector3 (float.NaN); return false; } intersectPt = ray.pos + ray.dir * t; return true; } }
public static float DistanceToLine_2(SSRay ray, Vector3 point) { return Vector3.Cross(ray.dir, point - ray.pos).Length; }
public virtual bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { return(true); }
public override bool preciseIntersect(ref SSRay localRay, out float localRayContact) { localRayContact = float.PositiveInfinity; foreach (var subset in geometrySubsets) { float contact; if (subset.triangleMesh.preciseIntersect(ref localRay, out contact) && contact < localRayContact) { localRayContact = contact; } } return localRayContact < float.PositiveInfinity; }
public virtual bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { return true; }
// Ray to AABB (AxisAlignedBoundingBox) // http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms public static bool intersectRayAABox2(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { Vector3d T_1 = new Vector3d(); Vector3d T_2 = new Vector3d(); // vectors to hold the T-values for every direction double t_near = double.MinValue; // maximums defined in float.h double t_far = double.MaxValue; for (int i = 0; i < 3; i++){ //we test slabs in every direction if (ray.dir[i] == 0){ // ray parallel to planes in this direction if ((ray.pos[i] < box.Min[i]) || (ray.pos[i] > box.Max[i])) { return false; // parallel AND outside box : no intersection possible } } else { // ray not parallel to planes in this direction T_1[i] = (box.Min[i] - ray.pos[i]) / ray.dir[i]; T_2[i] = (box.Max[i] - ray.pos[i]) / ray.dir[i]; if(T_1[i] > T_2[i]){ // we want T_1 to hold values for intersection with near plane var swp = T_2; // swap T_1 = swp; T_2 = T_1; } if (T_1[i] > t_near){ t_near = T_1[i]; } if (T_2[i] < t_far){ t_far = T_2[i]; } if( (t_near > t_far) || (t_far < 0) ){ return false; } } } tnear = (float)t_near; tfar = (float)t_far; // put return values in place return true; // if we made it here, there was an intersection - YAY }
public static bool intersectRayAABox1(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { // r.dir is unit direction vector of ray Vector3 dirfrac = new Vector3(); float t; dirfrac.X = 1.0f / ray.dir.X; dirfrac.Y = 1.0f / ray.dir.Y; dirfrac.Z = 1.0f / ray.dir.Z; // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner // r.org is origin of ray float t1 = (box.Min.X - ray.pos.X)*dirfrac.X; float t2 = (box.Max.X - ray.pos.X)*dirfrac.X; float t3 = (box.Min.Y - ray.pos.Y)*dirfrac.Y; float t4 = (box.Max.Y - ray.pos.Y)*dirfrac.Y; float t5 = (box.Min.Z - ray.pos.Z)*dirfrac.Z; float t6 = (box.Max.Z - ray.pos.Z)*dirfrac.Z; float tmin = Math.Max(Math.Max(Math.Min(t1, t2), Math.Min(t3, t4)), Math.Min(t5, t6)); float tmax = Math.Min(Math.Min(Math.Max(t1, t2), Math.Max(t3, t4)), Math.Max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { t = tmax; return false; } // if tmin > tmax, ray doesn't intersect AABB if (tmin > tmax) { t = tmax; return false; } t = tmin; return true; }
public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { SSRay localRay = worldSpaceRay.Transformed(this.worldMat.Inverted()); SSAbstractMesh abstrMesh = this.mesh as SSAbstractMesh; float nearestLocalRayContact = float.PositiveInfinity; if (useBVHForIntersections) { if (_bvh == null) { _bvh = new SSInstanceBVH(this.instanceData); for (int i = 0; i < instanceData.activeBlockLength; ++i) { if (instanceData.isValid(i)) { _bvh.addObject(i); } } } List <ssBVHNode <int> > nodesHit = _bvh.traverseRay(localRay); foreach (var node in nodesHit) { if (!node.IsLeaf) { continue; } foreach (int i in node.gobjects) { if (!instanceData.isValid(i)) { continue; } float localContact; if (_perInstanceIntersectionTest(abstrMesh, i, ref localRay, out localContact)) { if (localContact < nearestLocalRayContact) { nearestLocalRayContact = localContact; } } } } } else { // no BVH is used for (int i = 0; i < instanceData.activeBlockLength; ++i) { if (!instanceData.isValid(i)) { continue; } float localContact; if (_perInstanceIntersectionTest(abstrMesh, i, ref localRay, out localContact)) { if (localContact < nearestLocalRayContact) { nearestLocalRayContact = localContact; } } } } if (nearestLocalRayContact < float.PositiveInfinity) { Vector3 localContactPt = localRay.pos + nearestLocalRayContact * localRay.dir; Vector3 worldContactPt = Vector3.Transform(localContactPt, this.worldMat); distanceAlongRay = (worldContactPt - worldSpaceRay.pos).Length; return(true); } else { distanceAlongRay = float.PositiveInfinity; return(false); } }
public SSObject Intersect(ref SSRay worldSpaceRay) { SSObject nearestIntersection = null; float nearestDistance = float.MinValue; // distances get "smaller" as they move in camera direction for some reason (why?) foreach (var obj in objects) { float distanceAlongRay; if (obj.Selectable && obj.Intersect(ref worldSpaceRay, out distanceAlongRay)) { // intersection must be in front of the camera ( < 0.0 ) if (distanceAlongRay < 0.0) { Console.WriteLine("intersect: [{0}] @distance: {1}", obj.Name, distanceAlongRay); // then we want the nearest one (numerically biggest if (distanceAlongRay > nearestDistance) { nearestDistance = distanceAlongRay; nearestIntersection = obj; } } } } return nearestIntersection; }
public virtual bool preciseIntersect(ref SSRay localRay, out float localRayContact) { localRayContact = 0f; return(true); }
// http://www.geometrictools.com/Documentation/DistancePointLine.pdf public static float DistanceToLine_3(SSRay ray, Vector3 point) { float t0 = Vector3.Dot(ray.dir, ( point - ray.pos) ) / Vector3.Dot(ray.dir,ray.dir); float distance = (point - (ray.pos + (t0 * ray.dir))).Length; return distance; }
public virtual bool Intersect(ref SSRay worldSpaceRay, out float distanceAlongRay) { distanceAlongRay = 0.0f; if (localBoundingSphereRadius > 0f) { var objBoundingSphere = worldBoundingSphere; if (objBoundingSphere.IntersectsRay(ref worldSpaceRay, out distanceAlongRay)) { return PreciseIntersect(ref worldSpaceRay, ref distanceAlongRay); } } distanceAlongRay = 0f; return false; }
//--------------------- public override bool preciseIntersect(ref SSRay localRay, out float nearestLocalRayContact) { nearestLocalRayContact = float.PositiveInfinity; if (useBVHForIntersections) { if (_bvh == null && _vbo != null && _ibo != null) { // rebuilding BVH // TODO try updating instead of rebuilding? _bvh = new SSIndexedMeshTrianglesBVH(_vbo, _ibo); for (UInt16 triIdx = 0; triIdx < _ibo.numIndices / 3; ++triIdx) { _bvh.addObject(triIdx); } } if (_bvh != null) { List <ssBVHNode <UInt16> > nodesHit = _bvh.traverseRay(localRay); foreach (var node in nodesHit) { if (!node.IsLeaf) { continue; } foreach (UInt16 triIdx in node.gobjects) { Vector3 v0, v1, v2; _readTriangleVertices(triIdx, out v0, out v1, out v2); float contact; if (OpenTKHelper.TriangleRayIntersectionTest( ref v0, ref v1, ref v2, ref localRay.pos, ref localRay.dir, out contact)) { if (contact < nearestLocalRayContact) { nearestLocalRayContact = contact; } } } } } } else { _bvh = null; // slow, tedious intersection test int numTri = lastAssignedIndices.Length / 3; for (UInt16 triIdx = 0; triIdx < numTri; ++triIdx) { Vector3 v0, v1, v2; _readTriangleVertices(triIdx, out v0, out v1, out v2); float contact; if (OpenTKHelper.TriangleRayIntersectionTest( ref v0, ref v1, ref v2, ref localRay.pos, ref localRay.dir, out contact)) { if (contact < nearestLocalRayContact) { nearestLocalRayContact = contact; } } } } return(nearestLocalRayContact < float.PositiveInfinity); }
public SSObject Intersect(ref SSRay worldSpaceRay, out float nearestDistance) { SSObject nearestIntersection = null; nearestDistance = float.PositiveInfinity; // distances get "smaller" as they move in camera direction for some reason (why?) foreach (var obj in objects) { float distanceAlongRay; DateTime start = DateTime.Now; if (obj.selectable && obj.Intersect(ref worldSpaceRay, out distanceAlongRay)) { // intersection must be in front of the camera ( < 0.0 ) if (distanceAlongRay > 0.0) { Console.WriteLine("intersect: [{0}] @distance: {1} in {2}ms", obj.Name, distanceAlongRay, (DateTime.Now - start).TotalMilliseconds); // then we want the nearest one (numerically biggest if (distanceAlongRay < nearestDistance) { nearestDistance = distanceAlongRay; nearestIntersection = obj; } } } } return nearestIntersection; }
public static float DistanceToLine_2(SSRay ray, Vector3 point) { return(Vector3.Cross(ray.dir, point - ray.pos).Length); }
public override bool PreciseIntersect(ref SSRay worldSpaceRay, ref float distanceAlongRay) { // for now, particle systems don't intersect with anything // TODO: figure out how to do this. return(false); }