public override LightSample Sample(Geometry geometry, Vector3 position) { Vector3 delta = this.position - position; double rr = delta.SqrLength(); double r = Math.Sqrt(rr); Vector3 l = delta / r; double spot; double SdotL = vector ^ l; if (SdotL >= cosTheta) { spot = 1; } else if (SdotL <= cosPhi) { spot = 0; } else { spot = Math.Pow((SdotL - cosPhi) * baseMultiplier, falloff); } if (shadow) { var shadowRay = new Ray3(position, l); var shadowResult = geometry.Intersect(shadowRay); if (shadowResult.Geometry != null && shadowResult.Distance <= r) { return(LightSample.Zero); } } double attenuation = 1 / rr; return(new LightSample(l, intensity * (attenuation * spot))); }
public MovingBlocksRaycastResult?Raycast(Vector3 start, Vector3 end, bool extendToFillCells) { Ray3 ray = new Ray3(start, Vector3.Normalize(end - start)); BoundingBox boundingBox = new BoundingBox(Vector3.Min(start, end), Vector3.Max(start, end)); m_result.Clear(); FindMovingBlocks(boundingBox, extendToFillCells, m_result); float num = float.MaxValue; MovingBlockSet movingBlockSet = null; foreach (MovingBlockSet item in m_result) { BoundingBox box = item.BoundingBox(extendToFillCells); float? num2 = ray.Intersection(box); if (num2.HasValue && num2.Value < num) { num = num2.Value; movingBlockSet = item; } } if (movingBlockSet != null) { MovingBlocksRaycastResult value = default(MovingBlocksRaycastResult); value.Ray = ray; value.Distance = num; value.MovingBlockSet = movingBlockSet; return(value); } return(null); }
private void OnDrawGizmos() { Ray3 ray = CreateRay3(Ray); Plane3 plane = CreatePlane3(Plane); IntersectionTypes intersectionType; bool test = Intersection.TestRay3Plane3(ref ray, ref plane, out intersectionType); Ray3Plane3Intr info; bool find = Intersection.FindRay3Plane3(ref ray, ref plane, out info); FiguresColor(); DrawPlane(ref plane, Plane); DrawRay(ref ray); if (find) { ResultsColor(); DrawPoint(info.Point); } LogInfo(info.IntersectionType + " " + info.RayParameter); if (test != find) { LogError("test != find"); } if (intersectionType != info.IntersectionType) { LogError("intersectionType != info.IntersectionType"); } }
internal static Vector3 Color(Ray3 r, HitableList world, int depth) { HitRecord record = world.Hit(r, 0.01, 10000); if (null != record) { if (depth < 50) { ScatterRecord sr = record.Material.Scatter(r, record); if (null != sr) { return(sr.Attenuation * Color(sr.Scatter, world, depth + 1)); } } // Either got absorbed by material or this ray refracted/reflected 50 times. // Don't want to go more than 50 depth so stop here in that case. return(BlackColor); } Vector3 unitDir = r.Direction.ToUnitVector(); double t = 0.5 * (unitDir.Y + 1.0); return((1.0 - t) * WhiteColor + t * SkyColor); }
public bool Intersects(Ray3 ray) { float near = 0; float far = float.PositiveInfinity; return(IntersectsLine(ref ray.Origin, ref ray.Direction, ref near, ref far)); }
public override bool HitTest(Ray3 ray, out double t) { ray = ray.Transform(InvPosition); double dx = ray.Direction.X; double dy = ray.Direction.Y; double dz = ray.Direction.Z; double x0 = ray.Position.X; double y0 = ray.Position.Y; double z0 = ray.Position.Z; double a = 1.0; //assume ray direction is normalized dx * dx + dy * dy + dz * dz; double b = 2.0 * (x0 * dx + y0 * dy + z0 * dz); double c = x0 * x0 + y0 * y0 + z0 * z0 - rad * rad; bool found = false; t = double.MaxValue; foreach (var tt in RealPolynomial.SolveQuadric(a, b, c)) { if (tt > 1e-4 && tt < t) { t = tt; found = true; } } return(found); }
public void NotEquals_TrueForNotEqual() { var a = new Ray3(new Vector3(1, 2, 3), Vector3.UnitY); var b = new Ray3(new Vector3(1, 2, 3), Vector3.UnitZ); Assert.IsTrue(a != b); }
public void NotEquals_FalseForEqual() { var a = new Ray3(new Vector3(1, 2, 3), Vector3.UnitY); var b = a; Assert.IsFalse(a != b); }
void Update() { Vec3 point; // hit X plane var ray = new Ray3(new Vector3(-.5f, -.5f, -.5f), new Vector3(.75f, .2f, .5f).normalized); Debug.DrawLine(ray.origin.ToVector3(), (ray.origin + (ray.direction * 5)).ToVector3(), Color.green, 0, false); if (ray.IntersectPlaneX(.5f, out point)) { Debug.DrawLine(ray.origin.ToVector3(), point.ToVector3(), Color.red, 0, false); } // hit Y plane ray = new Ray3(new Vector3(-.5f, -.5f, -.5f), new Vector3(.3f, .75f, .5f).normalized); Debug.DrawLine(ray.origin.ToVector3(), (ray.origin + (ray.direction * 5)).ToVector3(), Color.green, 0, false); if (ray.IntersectPlaneY(.5f, out point)) { Debug.DrawLine(ray.origin.ToVector3(), point.ToVector3(), Color.red, 0, false); } // hit Z plane ray = new Ray3(new Vector3(-.5f, -.5f, -.5f), new Vector3(.3f, .2f, 1).normalized); Debug.DrawLine(ray.origin.ToVector3(), (ray.origin + (ray.direction * 5)).ToVector3(), Color.green, 0, false); if (ray.IntersectPlaneZ(.5f, out point)) { Debug.DrawLine(ray.origin.ToVector3(), point.ToVector3(), Color.red, 0, false); } }
public bool Use(Ray3 ray) { if (Use1 != null) { return(Use1(ray)); } int num = Terrain.ExtractContents(ActiveBlockValue); Block block = BlocksManager.Blocks[num]; if (!CanUseTool(ActiveBlockValue)) { ComponentPlayer?.ComponentGui.DisplaySmallMessage(string.Format(LanguageControl.Get(fName, 1), block.PlayerLevelRequired, block.GetDisplayName(m_subsystemTerrain, ActiveBlockValue)), Color.White, blinking: true, playNotificationSound: true); Poke(forceRestart: false); return(false); } SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(num); for (int i = 0; i < blockBehaviors.Length; i++) { if (blockBehaviors[i].OnUse(ray, this)) { Poke(forceRestart: false); return(true); } } return(false); }
private void OnDrawGizmos() { Ray3 ray = CreateRay3(Ray); Triangle3 triangle = CreateTriangle3(V0, V1, V2); IntersectionTypes intersectionType; bool test = Intersection.TestRay3Triangle3(ref ray, ref triangle, out intersectionType); Ray3Triangle3Intr info; bool find = Intersection.FindRay3Triangle3(ref ray, ref triangle, out info); FiguresColor(); DrawRay(ref ray); DrawTriangle(ref triangle); if (find) { ResultsColor(); DrawPoint(info.Point); } LogInfo(info.IntersectionType); if (test != find) { LogError("test != find"); } if (intersectionType != info.IntersectionType) { LogError("intersectionType != info.IntersectionType"); } }
private void OnDrawGizmos() { Ray3 ray = CreateRay3(Ray); Plane3 polygonPlane = CreatePlane3(PolygonPlane); Polygon3 polygon = new Polygon3(PolygonPoints.Length, polygonPlane); for (int i = 0; i < PolygonPoints.Length; ++i) { polygon.SetVertexProjected(i, PolygonPoints[i].position); } polygon.UpdateEdges(); Ray3Polygon3Intr info; bool find = Intersection.FindRay3Polygon3(ref ray, polygon, out info); FiguresColor(); DrawPolygon(polygon); DrawRay(ref ray); if (find) { ResultsColor(); DrawPoint(info.Point); } LogInfo(info.IntersectionType); }
public IntersectResult Intersect(Ray3 ray, double maxDistance) { if (!BoundingBox.Intersect(ray, maxDistance)) { return(IntersectResult.NoHit()); } double minDistance = maxDistance; IntersectResult minResult = IntersectResult.NoHit(); if (nodeTriangles != null) { foreach (var triangle in nodeTriangles) { IntersectResult result = triangle.Intersect(ray, minDistance); if (result.Geometry != null && result.Distance < minDistance) { minDistance = result.Distance; minResult = result; } } } if (children != null) { foreach (var child in children) { IntersectResult result = child.Intersect(ray, minDistance); if (result.Geometry != null && result.Distance < minDistance) { minDistance = result.Distance; minResult = result; } } } return(minResult); }
/// <summary> /// gets position on surface of specified entity /// </summary> /// <param name="position">the position to start looking at</param> /// <param name="entity">the entity to query</param> /// <returns></returns> public static bool GetPositionOnSurface(ref Vector3 position, Entity entity, out Vector3 surfacePosition) { Debug.Assert(entity.HasProperty("collision")); Ray3 ray = new Ray3(position + 1000 * Vector3.UnitY, -Vector3.UnitY); return(Game.Instance.Simulation.CollisionManager.GetIntersectionPoint(ref ray, entity, out surfacePosition)); }
private void OnDrawGizmos() { Ray3 ray = CreateRay3(Ray); AAB3 box = CreateAAB3(Box_Point0, Box_Point1); bool test = Intersection.TestRay3AAB3(ref ray, ref box); Ray3AAB3Intr info; bool find = Intersection.FindRay3AAB3(ref ray, ref box, out info); FiguresColor(); DrawRay(ref ray); DrawAAB(ref box); if (find) { ResultsColor(); if (info.IntersectionType == IntersectionTypes.Point) { DrawPoint(info.Point0); } else if (info.IntersectionType == IntersectionTypes.Segment) { DrawSegment(info.Point0, info.Point1); DrawPoint(info.Point0); DrawPoint(info.Point1); } } LogInfo(info.IntersectionType); if (test != find) { LogError("test != find"); } }
public void RaycastParticle(Particle particle) { particle.YLimit = m_yLimit; particle.GenerateSplash = true; Block block = BlocksManager.Blocks[Terrain.ExtractContents(m_topmostValue)]; if (!block.IsTransparent) { return; } Ray3 ray = new Ray3(new Vector3(particle.Position.X - (float)Point.X, 1f, particle.Position.Z - (float)Point.Y), -Vector3.UnitY); int nearestBoxIndex; BoundingBox nearestBox; float? num = block.Raycast(ray, m_subsystemWeather.SubsystemTerrain, m_topmostValue, useInteractionBoxes: false, out nearestBoxIndex, out nearestBox); if (num.HasValue) { particle.YLimit -= num.Value; return; } particle.YLimit -= 1f; if (BlocksManager.Blocks[Terrain.ExtractContents(m_topmostBelowValue)].IsFaceTransparent(m_subsystemWeather.SubsystemTerrain, 4, m_topmostBelowValue)) { particle.GenerateSplash = false; } }
public void Trace(Camera cam, Painter p) { /* for (int y = 300; y < cam.Height; y++) * { * for (int x = 462; x < cam.Width; x++) * { */ for (int y = 0; y < cam.Height; y++) { for (int x = 0; x < cam.Width; x++) { Ray3 ray = cam.GetRay(x, y); RGB col = GetColor(ray, 0); p.SetPixel(462, 300, Colors.Wheat); if (col != null) { p.SetPixel(x, y, col.ToInt()); } else { p.SetPixel(x, y, Colors.Black); } } } }
public override bool OnUse(Ray3 ray, ComponentMiner componentMiner) { _ = componentMiner.Inventory; if (Terrain.ExtractContents(componentMiner.ActiveBlockValue) == 178) { TerrainRaycastResult?terrainRaycastResult = componentMiner.Raycast <TerrainRaycastResult>(ray, RaycastMode.Digging); if (terrainRaycastResult.HasValue) { Vector3 position = terrainRaycastResult.Value.HitPoint(); DynamicArray <ComponentBody> dynamicArray = new DynamicArray <ComponentBody>(); m_subsystemBodies.FindBodiesInArea(new Vector2(position.X, position.Z) - new Vector2(8f), new Vector2(position.X, position.Z) + new Vector2(8f), dynamicArray); if (dynamicArray.Count((ComponentBody b) => b.Entity.ValuesDictionary.DatabaseObject.Name == "Boat") < 6) { Entity entity = DatabaseManager.CreateEntity(base.Project, "Boat", throwIfNotFound: true); entity.FindComponent <ComponentFrame>(throwOnError: true).Position = position; entity.FindComponent <ComponentFrame>(throwOnError: true).Rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitY, m_random.Float(0f, (float)Math.PI * 2f)); entity.FindComponent <ComponentSpawn>(throwOnError: true).SpawnDuration = 0f; base.Project.AddEntity(entity); componentMiner.RemoveActiveTool(1); m_subsystemAudio.PlaySound("Audio/BlockPlaced", 1f, 0f, position, 3f, autoDelay: true); } else { componentMiner.ComponentPlayer?.ComponentGui.DisplaySmallMessage(LanguageControl.Get(fName, 1), Color.White, blinking: true, playNotificationSound: false); } return(true); } } return(false); }
private bool findDragTarget(Ray3 cameraRay) { var matches = PoseableObjectsManager.findPoseable(cameraRay); foreach (var match in matches.Results) { var bone = match.PoseableIdentifier.PoseHandler.Bone; if (bone != null) { if (bone.Pinned) { repinBone = true; bone.Pinned = false; } else { repinBone = false; } dragControl.TargetBone = bone; hitDistance = match.Distance; Vector3 hitPosition = cameraRay.Direction * hitDistance + cameraRay.Origin; dragControl.LinearMotor.Offset = (hitPosition - bone.Owner.Translation).toBepuVec3(); dragControl.LinearMotor.TargetPosition = hitPosition.toBepuVec3(); ikScene.addExternalControl(dragControl); poseStartPosition = new MusclePosition(true); currentHandler = match.PoseableIdentifier.PoseHandler; currentHandler.posingStarted(activeModes); return(true); } } return(false); }
public void GetHashCode_SameForEqual() { var a = new Ray3(new Vector3(1, 2, 3), Vector3.UnitY); var b = new Ray3(new Vector3(1, 2, 3), Vector3.UnitY); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
public static Pair <bool, float> intersects(Ray3 ray, Vector3 a, Vector3 b, Vector3 c, bool positiveSide, bool negativeSide) { float distance; bool intersect = Math_intersectsRayPoly(ray, a, b, c, positiveSide, negativeSide, out distance); return(new Pair <bool, float>(intersect, distance)); }
private IEnumerable <Pair <Vector3, BuildingWallSegment> > Intersect(Ray3 ray) { return(wallSegments .Select(x => new Pair <Vector3?, BuildingWallSegment>(Intersects(ray, x), x)) .Where(x => x.First.HasValue) .Select(x => new Pair <Vector3, BuildingWallSegment>(x.First.Value, x.Second))); }
public override Color Sample(Ray3 ray, LightSample lightSample, Vector3 normal, Vector3 position, Vector2 textureCoordinates = null) { double NdotL = normal ^ lightSample.Vector; Vector3 H = (lightSample.Vector - ray.Direction).Normalize(); double NdotH = normal ^ H; Color ambientTerm = ambientColor; if (textureCoordinates != null && ambientTexture != null) { ambientTerm = ambientTexture.GetColor(textureCoordinates); } Color diffuseTerm = diffuseColor; if (textureCoordinates != null && diffuseTexture != null) { diffuseTerm = diffuseTexture.GetColor(textureCoordinates); } diffuseTerm = diffuseTerm * (Math.Max(NdotL, 0)); Color specularTerm = specularColor; if (textureCoordinates != null && specularTexture != null) { specularTerm = specularTexture.GetColor(textureCoordinates); } specularTerm = specularColor * (Math.Pow(Math.Max(NdotH, 0), shininess)); Color color = lightSample.Irradiance * (ambientTerm + diffuseTerm + specularTerm); return(color); }
public override bool OnUse(Ray3 ray, ComponentMiner componentMiner) { TerrainRaycastResult?terrainRaycastResult = componentMiner.Raycast <TerrainRaycastResult>(ray, RaycastMode.Interaction); if (terrainRaycastResult.HasValue && terrainRaycastResult.Value.CellFace.Face == 4) { int y = terrainRaycastResult.Value.CellFace.Y; for (int i = terrainRaycastResult.Value.CellFace.X - 1; i <= terrainRaycastResult.Value.CellFace.X + 1; i++) { for (int j = terrainRaycastResult.Value.CellFace.Z - 1; j <= terrainRaycastResult.Value.CellFace.Z + 1; j++) { int cellValue = m_subsystemTerrain.Terrain.GetCellValue(i, y, j); if (Terrain.ExtractContents(cellValue) == 168) { int data = SoilBlock.SetNitrogen(Terrain.ExtractData(cellValue), 3); int value = Terrain.ReplaceData(cellValue, data); m_subsystemTerrain.ChangeCell(i, y, j, value); } } } m_subsystemAudio.PlayRandomSound("Audio/Impacts/Dirt", 0.5f, 0f, new Vector3(terrainRaycastResult.Value.CellFace.X, terrainRaycastResult.Value.CellFace.Y, terrainRaycastResult.Value.CellFace.Z), 3f, autoDelay: true); Vector3 position = new Vector3((float)terrainRaycastResult.Value.CellFace.X + 0.5f, (float)terrainRaycastResult.Value.CellFace.Y + 1.5f, (float)terrainRaycastResult.Value.CellFace.Z + 0.5f); Block block = BlocksManager.Blocks[Terrain.ExtractContents(componentMiner.ActiveBlockValue)]; m_subsystemParticles.AddParticleSystem(block.CreateDebrisParticleSystem(m_subsystemTerrain, position, componentMiner.ActiveBlockValue, 1.25f)); componentMiner.RemoveActiveTool(1); return(true); } return(false); }
public IntersectResult Intersect(Ray3 ray, double maxDistance) { if (!BoundingBox.Intersect(ray, maxDistance)) { return(IntersectResult.NoHit()); } if (normal.SqrLength() == 0) { return(IntersectResult.NoHit()); } Vector3 w0 = ray.Origin - vertices[0]; double x = -normal ^ w0; double y = normal ^ ray.Direction; double distance = x / y; if (y == 0 || distance < 0) { return(IntersectResult.NoHit()); } Vector3 position = ray.GetPoint(distance); double uu = edgeAB ^ edgeAB; double uv = edgeAB ^ edgeAC; double vv = edgeAC ^ edgeAC; Vector3 w = position - vertices[0]; double wu = w ^ (edgeAB); double wv = w ^ (edgeAC); double D = uv * uv - uu * vv; double beta = (uv * wv - vv * wu) / D; if (beta < 0 || beta > 1) { return(IntersectResult.NoHit()); } double gamma = (uv * wu - uu * wv) / D; if (gamma < 0 || beta + gamma > 1) { return(IntersectResult.NoHit()); } double alpha = 1 - beta - gamma; Vector3 newNormal = normal; if (distance > 0 && normals != null) { Vector3 n1Interpolated = normals[0] * alpha; Vector3 n2Interpolated = normals[1] * beta; Vector3 n3Interpolated = normals[2] * gamma; newNormal = n1Interpolated + n2Interpolated + n3Interpolated; } IntersectResult result = new IntersectResult(this, distance, position, newNormal); if (textures != null) { Vector2 t1Interpolated = textures[0] * alpha; Vector2 t2Interpolated = textures[1] * beta; Vector2 t3Interpolated = textures[2] * gamma; result.TextureCoordinates = t1Interpolated + t2Interpolated + t3Interpolated; } return(result); }
private void OnDrawGizmos() { Ray3 ray = CreateRay3(Ray); Sphere3 sphere = CreateSphere3(Sphere); bool test = Intersection.TestRay3Sphere3(ref ray, ref sphere); Ray3Sphere3Intr info; bool find = Intersection.FindRay3Sphere3(ref ray, ref sphere, out info); FiguresColor(); DrawRay(ref ray); DrawSphere(ref sphere); if (find) { ResultsColor(); if (info.IntersectionType == IntersectionTypes.Point) { DrawPoint(info.Point0); } else if (info.IntersectionType == IntersectionTypes.Segment) { DrawSegment(info.Point0, info.Point1); DrawPoint(info.Point0); DrawPoint(info.Point1); } } LogInfo(info.IntersectionType); if (test != find) { LogError("test != find"); } }
public ScatterRecord Scatter(Ray3 rIn, HitRecord record) { Vector3 target = record.Point + record.Normal + sampler.GenerateSample(); return (new ScatterRecord(this.albedo, new Ray3(record.Point, target - record.Point))); }
// Token: 0x06000035 RID: 53 RVA: 0x00002990 File Offset: 0x00000B90 public ICollection <int> RayQuery(Ray3 ray) { List <int> list = new List <int>(); int i = 0; int num = this.quantizedAabbTreeNodes.Length; while (i < num) { bool flag = this.GetAabb(i).CollideRay(ray); bool flag2 = this.IsDataNode(i); if (flag2 && flag) { list.Add(this.GetNodeDataValue(i)); } if (flag || flag2) { i++; } else { i += this.GetBranchNodeWidth(i); } } return(list); }
public override bool OnUse(Ray3 ray, ComponentMiner componentMiner) { BodyRaycastResult?bodyRaycastResult = componentMiner.Raycast <BodyRaycastResult>(ray, RaycastMode.Interaction); if (bodyRaycastResult.HasValue) { ComponentHealth componentHealth = bodyRaycastResult.Value.ComponentBody.Entity.FindComponent <ComponentHealth>(); if (componentHealth == null || componentHealth.Health > 0f) { string entityTemplateName = bodyRaycastResult.Value.ComponentBody.Entity.ValuesDictionary.DatabaseObject.Name + "_Saddled"; Entity entity = DatabaseManager.CreateEntity(base.Project, entityTemplateName, throwIfNotFound: false); if (entity != null) { ComponentBody componentBody = entity.FindComponent <ComponentBody>(throwOnError: true); componentBody.Position = bodyRaycastResult.Value.ComponentBody.Position; componentBody.Rotation = bodyRaycastResult.Value.ComponentBody.Rotation; componentBody.Velocity = bodyRaycastResult.Value.ComponentBody.Velocity; entity.FindComponent <ComponentSpawn>(throwOnError: true).SpawnDuration = 0f; base.Project.RemoveEntity(bodyRaycastResult.Value.ComponentBody.Entity, disposeEntity: true); base.Project.AddEntity(entity); m_subsystemAudio.PlaySound("Audio/BlockPlaced", 1f, m_random.Float(-0.1f, 0.1f), ray.Position, 1f, autoDelay: true); componentMiner.RemoveActiveTool(1); } } return(true); } return(false); }
public ScatterRecord Scatter(Ray3 rIn, HitRecord record) { Vector3 attenuation = new Vector3(1.0, 1.0, 1.0); Vector3 outwardNormal; double ni; double nt; double cosine; // Assumes that refractive index of material outside of this material is air i.e. 1.0 if (rIn.Direction.Dot(record.Normal) > 0) { // Ray is going from inside the material to outside so the normal is facing the wrong // direction for the purpose of our refract function. So flip the normal. outwardNormal = -record.Normal; ni = this.refractiveIndex; nt = 1.0; /* * cosine = rIn.Direction.Dot(record.Normal) / rIn.Direction.Length(); * cosine = Math.Sqrt(1.0 - this.refractiveIndex * this.refractiveIndex * (1.0 - cosine * cosine)); */ cosine = this.refractiveIndex * rIn.Direction.Dot(record.Normal) / rIn.Direction.Length(); } else { outwardNormal = record.Normal; ni = 1.0; nt = this.refractiveIndex; cosine = -(rIn.Direction.Dot(record.Normal)) / rIn.Direction.Length(); } // Check if this should reflect or refract Vector3 refractedDir = Physics.Refract(rIn.Direction, outwardNormal, ni, nt); double reflectProbability; if (refractedDir != null) { reflectProbability = Physics.Schlick(cosine, this.refractiveIndex); } else { reflectProbability = 1.0; } if (rng.NextDouble() < reflectProbability) { // Reflects Vector3 reflectedDir = Physics.Reflect(rIn.Direction, outwardNormal); return(new ScatterRecord(attenuation, new Ray3(record.Point, reflectedDir))); } else { // Ray is refracted return(new ScatterRecord(attenuation, new Ray3(record.Point, refractedDir))); } }
/// <summary> /// Creates a pick ray from a screen position /// </summary> /// <param name="x">Screen X position</param> /// <param name="y">Screen Y position</param> /// <returns>Returns world ray</returns> public Ray3 PickRay( int x, int y ) { Matrix44 matrix = m_InvProjView; float width = Graphics.Renderer.Viewport.Width; float height = Graphics.Renderer.Viewport.Height; Point3 pt = new Point3( ( 2 * x / width ) - 1, ( 2 * ( height - y ) / height ) - 1, 1.0f ); Point3 invPt = matrix.HomogenousMultiply( pt ); Point3 camPos = Frame.Translation; Ray3 result = new Ray3( camPos, ( invPt - camPos ).MakeNormal( ) ); return result; }
/// <summary> /// Tests for an intersection between a ray and a sphere /// </summary> public static Line3Intersection GetRayIntersection( Ray3 ray, Sphere3 sphere ) { Vector3 originToCentre = ray.Origin - sphere.Centre; float a0 = originToCentre.SqrLength - ( sphere.SqrRadius ); float a1 = ray.Direction.Dot( originToCentre ); float discriminant; Point3 intersectionPt; if ( a0 <= 0 ) { // 1 intersection: The origin of the ray is inside the sphere discriminant = ( a1 * a1 ) - a0; float t = -a1 + Functions.Sqrt( discriminant ); intersectionPt = ray.GetPointOnRay( t ); return new Line3Intersection( intersectionPt, ( intersectionPt - sphere.Centre ).MakeNormal( ), t ); } if ( a1 >= 0 ) { // No intersections: Ray origin is outside the sphere, ray direction points away from the sphere return null; } discriminant = ( a1 * a1 ) - a0; if ( discriminant < 0 ) { // No intersections: Ray/sphere equation has no roots return null; } if ( discriminant < 0.0001f ) // TODO: Magic number { // 1 intersection: Discriminant is close to zero - there's only root to the ray/sphere equation float t = -a1; intersectionPt = ray.GetPointOnRay( t ); return new Line3Intersection( intersectionPt, ( intersectionPt - sphere.Centre ).MakeNormal( ), t ); } // 2 intersections: 2 roots to the ray/sphere equation. Choose the closest float root = Functions.Sqrt( discriminant ); float t0 = -a1 - root; float t1 = -a1 + root; float closestT = ( t0 < t1 ) ? t0 : t1; intersectionPt = ray.GetPointOnRay( closestT ); return new Line3Intersection( intersectionPt, ( intersectionPt - sphere.Centre ).MakeNormal( ), closestT ); }
/// <summary> /// Returns information about an intersection between a ray and a plane /// </summary> public static Line3Intersection GetRayIntersection( Ray3 ray, Plane3 plane ) { float startDot = plane.Normal.Dot( ray.Origin ); float diffDot = plane.Normal.Dot( ray.Direction ); if ( !Utils.CloseToZero( diffDot ) ) { float t = ( startDot + plane.Distance ) / -diffDot; if ( t >= 0 ) { Line3Intersection result = new Line3Intersection( ); result.IntersectedObject = plane; result.IntersectionPosition = ray.Origin + ( ray.Direction * t ); result.IntersectionNormal = plane.Normal; result.Distance = t; return result; } } return null; }
/// <summary> /// Gets the first intersection between a ray and the stored intersectable objects /// </summary> /// <param name="ray">Ray</param> /// <param name="options">Ray cast options</param> /// <returns>Intersection result (null if no intersection occurred)</returns> public Line3Intersection GetFirstIntersection( Ray3 ray, RayCastOptions options ) { options = options ?? s_DefaultOptions; Line3Intersection closestIntersection = null; foreach ( IRay3Intersector intersector in m_Intersectors ) { if ( !options.TestObject( intersector ) ) { continue; } Line3Intersection intersection = intersector.GetIntersection( ray ); if ( intersection != null ) { if ( ( closestIntersection == null ) || ( closestIntersection.Distance >= intersection.Distance ) ) { closestIntersection = intersection; } } } return closestIntersection; }
/// <summary> /// Returns true if there is an intersection between the specified ray and this plane /// </summary> public bool TestIntersection( Ray3 ray ) { return Intersections3.TestRayIntersection( ray, this ); }
private bool GetRayPlanetAndAtmosphereIntersection( Point3 origin, Vector3 dir, out Point3 intPt ) { // TODO: AP: Optimise ray intersection code (origin is always outside inner sphere, inside outer sphere) Ray3 ray = new Ray3( origin, dir ); Line3Intersection innerIntersection = Intersections3.GetRayIntersection( ray, m_InnerSphere ); Line3Intersection outerIntersection = Intersections3.GetRayIntersection( ray, m_OuterSphere ); if ( innerIntersection == null ) { if ( outerIntersection == null ) { // This should not happen, but there may be an edge condition intPt = Point3.Origin; return false; } intPt = outerIntersection.IntersectionPosition; return true; } if ( ( outerIntersection == null ) || ( innerIntersection.Distance < outerIntersection.Distance ) ) { intPt = innerIntersection.IntersectionPosition; return true; } intPt = outerIntersection.IntersectionPosition; return true; }
/// <summary> /// Checks if a ray intersects this object, returning information about the intersection if it does /// </summary> /// <param name="ray">Ray to check</param> /// <returns>Intersection information. If no intersection takes place, this method returns null</returns> public Line3Intersection GetIntersection( Ray3 ray ) { Line3Intersection pick = Intersections3.GetRayIntersection( ray, m_Spinner, Vector3.YAxis ); if ( ( pick == null ) || ( pick.IntersectionPosition.DistanceTo( m_Spinner ) > Radius ) ) { return null; } pick.IntersectedObject = this; return pick; }
/// <summary> /// Returns details about the intersection between a specified ray and this plane (returns null if no intersection exists) /// </summary> public Line3Intersection GetIntersection( Ray3 ray ) { return Intersections3.GetRayIntersection( ray, this ); }
/// <summary> /// Intersects a ray with a quad /// </summary> /// <param name="ray">Ray </param> /// <param name="pt0">Quad corner position</param> /// <param name="pt1">Quad corner position</param> /// <param name="pt2">Quad corner position</param> /// <param name="pt3">Quad corner position</param> /// <returns>Returns intersection details, or null if there was no intersection</returns> public static Line3Intersection GetRayQuadIntersection( Ray3 ray, Point3 pt0, Point3 pt1, Point3 pt2, Point3 pt3 ) { // TODO: AP: This is very lazy... Line3Intersection intersection = GetRayTriangleIntersection( ray, pt0, pt1, pt2 ); if ( intersection == null ) { intersection = GetRayTriangleIntersection( ray, pt2, pt3, pt0 ); } return intersection; }
/// <summary> /// Checks if a ray intersects this object /// </summary> /// <param name="ray">Ray to check</param> /// <returns>true if the ray intersects this object</returns> public bool TestIntersection( Ray3 ray ) { Line3Intersection pick = Intersections3.GetRayIntersection( ray, m_Spinner, Vector3.YAxis ); return pick == null ? false : pick.IntersectionPosition.DistanceTo( m_Spinner ) < Radius; }
/// <summary> /// Intersects a ray with a triangle /// </summary> public static Line3Intersection GetRayTriangleIntersection( Ray3 ray, Point3 pt0, Point3 pt1, Point3 pt2 ) { return GetRayTriangleIntersection( ray, pt0, pt1, pt2, float.MaxValue ); }
/// <summary> /// Intersects a ray with a triangle. If the intersection point is beyond a given distance from the ray origin, the intersection is rejected /// </summary> public static Line3Intersection GetRayTriangleIntersection( Ray3 ray, Point3 pt0, Point3 pt1, Point3 pt2, float maxDistance ) { Vector3 uVec = ( pt1 - pt0 ); Vector3 vVec = ( pt2 - pt0 ); Vector3 nVec = Vector3.Cross( uVec, vVec ); float nVecSqrLength = nVec.SqrLength; if ( nVecSqrLength < 0.001f ) { // Degenerate tri - no intersection return null; } Vector3 w0 = ray.Origin - pt0; float a = -nVec.Dot( w0 ); float b = nVec.Dot( ray.Direction ); if ( System.Math.Abs( b ) < 0.001f ) { // Ray is parallel to the tri - reject return null; } float r = a / b; if ( r < 0 ) { // Ray goes away from the tri - reject return null; } // Ray intersects tri plane - calculate position in tri Point3 pt = ray.Origin + ray.Direction * r; float uu = uVec.Dot( uVec ); float uv = uVec.Dot( vVec ); float vv = vVec.Dot( vVec ); Vector3 w = pt - pt0; float wu = w.Dot( uVec ); float wv = w.Dot( vVec ); float d = ( uv * uv - uu * vv ); float s = ( uv * wv - vv * wu ) / d; if ( s < 0 || s > 1 ) { return null; } float t = ( uv * wu - uu * wv ) / d; if ( t < 0 || t > 1 ) { return null; } nVec /= Functions.Sqrt( nVecSqrLength ); return new Line3Intersection( pt, nVec, r ); }
/// <summary> /// Tests for an intersection between a ray and a plane /// </summary> public static bool TestRayIntersection( Ray3 ray, Plane3 plane ) { float startDot = plane.Normal.Dot( ray.Origin ); float diffDot = plane.Normal.Dot( ray.Direction ); if ( !Utils.CloseToZero( diffDot ) ) { float t = ( startDot + plane.Distance ) / -diffDot; return ( t >= 0 ); } return false; }
/// <summary> /// Checks if a ray intersects this object, returning information about the intersection if it does /// </summary> /// <param name="ray">Ray to check</param> /// <returns>Intersection information. If no intersection takes place, this method returns null</returns> public virtual Line3Intersection GetIntersection( Ray3 ray ) { Line3Intersection pick = m_Plane.GetIntersection( ray ); if ( ( pick == null ) || ( pick.IntersectionPosition.DistanceTo( Position ) > Radius ) ) { return null; } pick.IntersectedObject = this; return pick; }
/// <summary> /// Casts a ray /// </summary> /// <param name="ray">Ray to cast</param> /// <param name="options">Options for determining which layers to check, objects to exclude, maximum ray length (!) etc.</param> /// <returns>Returns an array of all intersections</returns> public Line3Intersection[] GetIntersections( Ray3 ray, RayCastOptions options ) { options = options ?? s_DefaultOptions; List< Line3Intersection > intersections = new List< Line3Intersection >( 4 ); foreach ( IRay3Intersector intersector in m_Intersectors ) { if ( !options.TestObject( intersector ) ) { continue; } Line3Intersection intersection = intersector.GetIntersection( ray ); if ( intersection != null ) { intersections.Add( intersection ); } } return intersections.ToArray( ); }
bool Ray3DToPlane(Ray3 ray, Plane plane, ref Vector3 result) { float parallelResult = Vector3.Dot(ray.dir, plane.Normal); if (Math.Abs(parallelResult) > 0) { float d = Vector3.Dot((plane.pos - ray.pos), plane.Normal); d /= parallelResult; result = ray.pos + d * ray.dir; return true; } return false; }
/// <summary> /// Returns information about an intersection between a ray, and a plane defined by a point and a normal /// </summary> public static Line3Intersection GetRayIntersection( Ray3 ray, Point3 pt, Vector3 vec ) { float startDot = vec.Dot( ray.Origin ); float diffDot = vec.Dot( ray.Direction ); if ( !Utils.CloseToZero( diffDot ) ) { float d = -vec.Dot( pt ); float t = ( startDot + d ) / -diffDot; if ( t >= 0 ) { Line3Intersection result = new Line3Intersection( ); result.IntersectedObject = null; result.IntersectionPosition = ray.Origin + ( ray.Direction * t ); result.IntersectionNormal = vec; result.Distance = t; return result; } } return null; }
/// <summary> /// Checks if a ray intersects this object /// </summary> /// <param name="ray">Ray to check</param> /// <returns>true if the ray intersects this object</returns> public virtual bool TestIntersection( Ray3 ray ) { Line3Intersection pick = m_Plane.GetIntersection( ray ); return pick == null ? false : pick.IntersectionPosition.DistanceTo( Position ) > Radius; }
/// <summary> /// Gets the intersection between the base intersector and a ray /// </summary> /// <param name="ray">Ray to test</param> /// <returns>Intersection details, or null if no intersection occurred</returns> public Line3Intersection GetIntersection( Ray3 ray ) { return m_Intersector.GetIntersection( ray ); }
/// <summary> /// Tests if the base intersector intersects the specified ray /// </summary> /// <param name="ray">Ray to test</param> /// <returns>True if ray is intersected</returns> public bool TestIntersection( Ray3 ray ) { return m_Intersector.TestIntersection( ray ); }
/// <summary> /// Makes a 3d ray in world space from a screen space position /// </summary> public override Ray3 PickRay( int x, int y ) { double[] modelMatrix = new double[ 16 ]; double[] projectionMatrix = new double[ 16 ]; int[] viewport = new int[ 4 ]; double outX; double outY; double outZ; Gl.glGetDoublev( Gl.GL_MODELVIEW_MATRIX, modelMatrix ); Gl.glGetDoublev( Gl.GL_PROJECTION_MATRIX, projectionMatrix ); Gl.glGetIntegerv( Gl.GL_VIEWPORT, viewport ); // Correct windows screen space into openGL screen space double inX = x; double inY = ( double )viewport[ 3 ] - y; // TODO:This isn't right - the pick ray origin should be the camera origin Glu.gluUnProject( inX, inY, 0, modelMatrix, projectionMatrix, viewport, out outX, out outY, out outZ ); Ray3 result = new Ray3( ); result.Origin.Set( ( float )outX, ( float )outY, ( float )outZ ); Glu.gluUnProject( inX, inY, 1, modelMatrix, projectionMatrix, viewport, out outX, out outY, out outZ ); result.Direction = new Vector3( ( float )outX, ( float )outY, ( float )outZ ); result.Direction.Normalise( ); return result; }