Ejemplo n.º 1
0
 public void Update(float time)
 {
     try
     {
         if (_actor != null)
         {
             desc.Origin = _actor.WorldPose.Translation + origin;
             for (int i = iter; i < iter + 108; i++)
             {
                 //Origin offset Transform
                 desc.Direction = _actor.WorldPose.Matrix * rayVec[i];
                 result = _world.RayCastClosest(desc);
                 if (result == null)
                     _player.saveLIDAR(30, i);
                 else
                     _player.saveLIDAR((result.Distance > 30 ? 30 : result.Distance), i);
             }
             iter += 108;
             if (iter > 972)
             {
                 _player.publishLIDAR();
                 _player.setIMU(_drone.CurrentPitch, _drone.CurrentYaw, _drone.CurrentRoll);
                 _player.setGPS(_drone.GPS);
                 iter = 0;
             }
         }
     }
     catch (SystemException e)
     {
         Console.WriteLine("Exception: " + e.ToString());
         return;
     }
 }
Ejemplo n.º 2
0
        public BaseBxdf GetBsdf(ref RayData pathRay, ref RayHit hit, ref MediumInfo med, bool fromLight, float u0)
        {
            var currentTriangleIndex = (int) hit.Index;
            bool isLight = scene.IsLight(currentTriangleIndex);

            var mesh = scene.GetMeshByTriangleIndex(currentTriangleIndex);
            if (mesh == null)
            //|| mesh.MeshName.Equals("COL254_01", StringComparison.InvariantCultureIgnoreCase))
            {
                //ii.Color = new RgbSpectrum(1f);
                //Debugger.Break();
                throw new ApplicationException("Invalid triangle index " + currentTriangleIndex + " Mesh not found");
            }
            UV TexCoords;
            Normal normal = new Normal(), shadeN = new Normal();

            mesh.InterpolateTriUV(currentTriangleIndex, hit.U, hit.V, out TexCoords);
            //normal = -scene.Triangles[currentTriangleIndex].ComputeNormal(scene.Vertices).Normalize();

            mesh.InterpolateTriangleNormal((int)hit.Index, hit.U, hit.V, ref normal);
            //normal = -normal;
            shadeN = (Normal.Dot(ref pathRay.Dir, ref normal) > 0f) ? -normal : normal;


            var bsdf =  mesh.Material.GetBsdf(ref pathRay, ref hit, ref normal, ref shadeN, ref TexCoords, ref med, fromLight,u0);
            bsdf.SetLight(isLight);
            return bsdf;
        }
Ejemplo n.º 3
0
        public PathVertexData CreateVertex(ref RayRecord ray, ref RayHit rayHit)
        {
            var wo = -ray.Direction;

            if (rayHit.Miss())
            {
                return new PathVertexData()
                    {
                        Flags = (byte)PathVertexType.Environment,
                        Emission = context.Scene.SampleEnvironment(ref wo)
                    };
            }
            var vertex = new PathVertexData { HitPoint = ray.Point(rayHit.Distance) };

            var mesh = context.Scene.GetMeshByTriangleIndex((int)rayHit.Index);

            if (mesh.MeshProfile is SurfaceProfile)
            {
                vertex.Flags = (byte)PathVertexType.Surface;
                vertex.SurfaceHit = new UV(rayHit.U, rayHit.V);
                var meshMat = mesh.MaterialID;
                var MMaterial = context.Scene.MatLib.GetSurfMat(meshMat);
                var matInfo = context.Scene.MaterialProvider.Get(meshMat);
                mesh.InterpolateTriangleNormal((int)rayHit.Index, rayHit.U, rayHit.V, ref vertex.GeoNormal);
                var rayDir = ray.Direction;
                vertex.ShadingNormal = (Normal.Dot(ref rayDir, ref vertex.GeoNormal) > 0f) ? -vertex.GeoNormal : vertex.GeoNormal;
                UV texCoord;
                mesh.InterpolateTriUV((int)rayHit.Index, rayHit.U, rayHit.V, out texCoord);
                vertex.Brdf = MMaterial;
                vertex.MaterialInfo = matInfo;
                var diffuseTex = context.Scene.Query(meshMat, TextureType.Diffuse);
                if (diffuseTex != null)
                {
                    texSampler.SampleTexture(texCoord.U, texCoord.V, diffuseTex, out vertex.Color);
                    //ii.Color = diffuseTex.Sample(ii.TexCoords.U, ii.TexCoords.V);
                    //ii.Color = diffuseTex.Sample(hit.U, hit.V);
                }
                else
                {
                    vertex.Color = RgbSpectrum.Max(ref matInfo.Ks, ref matInfo.Kd);
                }
            }
            else if (mesh.MeshProfile is LightsourceProfile)
            {
                vertex.Flags = (byte)PathVertexType.Light;
                var light = context.Scene.GetLightByIndex((int)rayHit.Index);
                vertex.LightId = context.Scene.Lights.ToList().IndexOf(light);
                vertex.Emission = (RgbSpectrum)(light.Le(ref wo));
            }
            else if (mesh.MeshProfile is VolumeProfile)
            {
                vertex.Flags = (byte)PathVertexType.Volume;
            }

            return vertex;
        }
Ejemplo n.º 4
0
        public static RayHit QueryRayFirst(Vector2f Start, Vector2f End)
        {
            RayHit Ret = new RayHit();

            Engine.Space.RayCast((Fix, Point, Norm, Frac) => {
                Ret = new RayHit(Fix, Point.ToVec(), Norm.ToVec(), Frac);
                return 0;
            }, Start.ToVec(), End.ToVec());

            return Ret;
        }
Ejemplo n.º 5
0
        protected BaseBxdf(ref RayHit rh, ref RayData ray, ref Normal ng, ref Normal ns, ref UV texCoord,
                MaterialInfo mi, SurfaceTextureInfo texData, bool fromLight)
        {
#if VERBOSE
            if (ng.Length > 1f || ns.Length > 1f)
            {
                Console.WriteLine("Normals in bsdf arent normalized");
            }
#endif
            this.Init(ref rh, ref ray, ref ng, ref ns, ref texCoord, mi, texData, fromLight);
        }
        public override void Process(ref RayHit rh, ref Vector wo, out bool finishPath, out float pdf)
        {
            var lt = PathSampler.scene.GetLightByIndex((int)rh.Index);
            pdf = 0;
            if (lt != null)
            {
                var le = lt.Emittance(ref wo, out pdf);//* hitInfo.Color 
                //Radiance += Throughput * le;
                if (!le.IsBlack())
                    PathSampler.mutate = true;

                PathSampler.Radiance.MAdd(ref PathSampler.Throughput, ref le);
            }
            finishPath = true;
        }
Ejemplo n.º 7
0
        public RayIntersection EvalIntersection(RayDifferential ray, ref RayHit rh, RayIntersection isect)
        {
            var ii = isect ?? (isect = new RayIntersection());
            var currentTriangleIndex = (int) rh.Index;

            var obj = GetObjectByTriangleIndex(currentTriangleIndex);
            ii.Hitpoint = ray.Point(rh.Distance);
            ii.BaryCentricPoint = new UV(rh.U, rh.V);
            

            obj.Entity.InterpolateTriangleNormal(currentTriangleIndex, rh.U, rh.V, ref ii.ShadingNormal);
            obj.Entity.InterpolateTriUV(currentTriangleIndex, rh.U, rh.V, out ii.TextureCoords);

            ii.GeoNormal = scene.sceneData.Triangles[currentTriangleIndex].ComputeNormal(scene.sceneData.GeoData.Vertices);
            ii.ComputeDifferential(ray);

            return ii;
        }
Ejemplo n.º 8
0
 internal void Init(ref RayHit rh, ref RayData ray, ref Normal ng, ref Normal ns, ref UV texCoord,
     MaterialInfo mi, SurfaceTextureInfo texData, bool fromLight)
 {
     if (rh.Miss())
     {
         throw new ArgumentException("RayHit missed geometry!");
     }
     //if (HitPoint == null)
     //{
         HitPoint = new HitPointInfo
         {
             Color = RgbSpectrum.Max(ref mi.Kd, ref mi.Ks),
             HitPoint = ray.Point(rh.Distance),
             TexCoord = texCoord,
             FromDirection = -ray.Dir,
             GeoNormal = ng,
             ShadingNormal = ns,
             FromLight = fromLight
         };
     //}
     //else
     //{
     //    HitPoint.HitPoint = ray.Point(rh.Distance);
     //    HitPoint.TexCoord = texCoord;
     //    HitPoint.FromDirection = -ray.Dir;
     //    HitPoint.GeoNormal = ng;
     //    HitPoint.ShadingNormal = ns;
     //    HitPoint.FromLight = fromLight;
     //};
     this.MaterialInfo = mi;
     this.TexData = texData;
     if (Frame == null)
         this.Frame = new ONB(ref HitPoint.GeoNormal);
     else
         Frame.SetFromZ(ref HitPoint.GeoNormal);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Sweeps a convex shape against the entry.
 /// </summary>
 /// <param name="castShape">Swept shape.</param>
 /// <param name="startingTransform">Beginning location and orientation of the cast shape.</param>
 /// <param name="sweep">Sweep motion to apply to the cast shape.</param>
 /// <param name="hit">Hit data of the cast on the entry, if any.</param>
 /// <returns>Whether or not the cast hit the entry.</returns>
 public abstract bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit);
Ejemplo n.º 10
0
 private bool IsLocalRayOriginInMeshHelper(ref Ray ray, out RayHit hit)
 {
     var overlapList = Resources.GetIntList();
     if (triangleMesh.Tree.GetOverlaps(ray, overlapList))
     {
         var hits = Resources.GetRayHitList();
         hit = new RayHit();
         hit.T = float.MaxValue;
         for (int i = 0; i < overlapList.Count; i++)
         {
             Vector3 vA, vB, vC;
             triangleMesh.Data.GetTriangle(overlapList[i], out vA, out vB, out vC);
             RayHit tempHit;
             if (Toolbox.FindRayTriangleIntersection(ref ray, float.MaxValue, TriangleSidedness.DoubleSided, ref vA, ref vB, ref vC, out tempHit) &&
                 IsHitUnique(hits, ref tempHit) && //Adds if unique.
                 tempHit.T < hit.T)
             {
                 hit = tempHit;
             }
         }
         int hitCount = hits.count;
         Resources.GiveBack(hits);
         Resources.GiveBack(overlapList);
         //An odd number of hits implies that the object started inside.
         return hitCount % 2 != 0;
     }
     Resources.GiveBack(overlapList);
     hit = new RayHit() { T = float.MaxValue };
     return false;
 }
Ejemplo n.º 11
0
 public override bool ConvexCast(ConvexShape castShape, ref MathExtensions.RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
 {
     hit = new RayHit();
     BoundingBox boundingBox;
     Toolbox.GetExpandedBoundingBox(ref castShape, ref startingTransform, ref sweep, out boundingBox);
     var tri = Resources.GetTriangle();
     var hitElements = Resources.GetIntList();
     if (triangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
     {
         hit.T = float.MaxValue;
         for (int i = 0; i < hitElements.Count; i++)
         {
             triangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
             Vector3 center;
             Vector3.Add(ref tri.vA, ref tri.vB, out center);
             Vector3.Add(ref center, ref tri.vC, out center);
             Vector3.Multiply(ref center, 1f / 3f, out center);
             Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
             Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
             Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
             tri.maximumRadius = tri.vA.LengthSquared();
             float radius = tri.vB.LengthSquared();
             if (tri.maximumRadius < radius)
                 tri.maximumRadius = radius;
             radius = tri.vC.LengthSquared();
             if (tri.maximumRadius < radius)
                 tri.maximumRadius = radius;
             tri.maximumRadius = (float)Math.Sqrt(tri.maximumRadius);
             tri.collisionMargin = 0;
             var triangleTransform = new RigidTransform { Orientation = Quaternion.Identity, Position = center };
             RayHit tempHit;
             if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
             {
                 hit = tempHit;
             }
         }
         tri.maximumRadius = 0;
         Resources.GiveBack(tri);
         Resources.GiveBack(hitElements);
         return hit.T != float.MaxValue;
     }
     Resources.GiveBack(tri);
     Resources.GiveBack(hitElements);
     return false;
 }
Ejemplo n.º 12
0
        ///<summary>
        /// Tests a ray against the terrain shape.
        ///</summary>
        ///<param name="ray">Ray to test against the shape.</param>
        ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        ///<param name="transform">Transform to apply to the terrain shape during the test.</param>
        ///<param name="sidedness">Sidedness of the triangles to use when raycasting.</param>
        ///<param name="hit">Hit data of the ray cast, if any.</param>
        ///<returns>Whether or not the ray hit the transformed terrain shape.</returns>
        public bool RayCast(ref Ray ray, float maximumLength, ref AffineTransform transform, TriangleSidedness sidedness, out RayHit hit)
        {
            hit = new RayHit();
            //Put the ray into local space.
            Ray localRay;
            AffineTransform inverse;
            AffineTransform.Invert(ref transform, out inverse);
            Matrix3X3.Transform(ref ray.Direction, ref inverse.LinearTransform, out localRay.Direction);
            AffineTransform.Transform(ref ray.Position, ref inverse, out localRay.Position);

            //Use rasterizey traversal.
            //The origin is at 0,0,0 and the map goes +X, +Y, +Z.
            //if it's before the origin and facing away, or outside the max and facing out, early out.
            float maxX = heights.GetLength(0) - 1;
            float maxZ = heights.GetLength(1) - 1;

            Vector3 progressingOrigin = localRay.Position;
            float distance = 0;
            //Check the outside cases first.
            if (progressingOrigin.X < 0)
            {
                if (localRay.Direction.X > 0)
                {
                    //Off the left side.
                    float timeToMinX = -progressingOrigin.X / localRay.Direction.X;
                    distance += timeToMinX;
                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToMinX, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }
                else
                    return false; //Outside and pointing away from the terrain.
            }
            else if (progressingOrigin.X > maxX)
            {
                if (localRay.Direction.X < 0)
                {
                    //Off the left side.
                    float timeToMinX = -(progressingOrigin.X - maxX) / localRay.Direction.X;
                    distance += timeToMinX;
                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToMinX, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }
                else
                    return false; //Outside and pointing away from the terrain.
            }

            if (progressingOrigin.Z < 0)
            {
                if (localRay.Direction.Z > 0)
                {
                    float timeToMinZ = -progressingOrigin.Z / localRay.Direction.Z;
                    distance += timeToMinZ;
                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToMinZ, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }
                else
                    return false;
            }
            else if (progressingOrigin.Z > maxZ)
            {
                if (localRay.Direction.Z < 0)
                {
                    float timeToMinZ = -(progressingOrigin.Z - maxZ) / localRay.Direction.Z;
                    distance += timeToMinZ;
                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToMinZ, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }
                else
                    return false;
            }

            if (distance > maximumLength)
                return false;



            //By now, we should be entering the main body of the terrain.

            int xCell = (int)progressingOrigin.X;
            int zCell = (int)progressingOrigin.Z;
            //If it's hitting the border and going in, then correct the index
            //so that it will initially target a valid quad.
            //Without this, a quad beyond the border would be tried and failed.
            if (xCell == heights.GetLength(0) - 1 && localRay.Direction.X < 0)
                xCell = heights.GetLength(0) - 2;
            if (zCell == heights.GetLength(1) - 1 && localRay.Direction.Z < 0)
                zCell = heights.GetLength(1) - 2;

            while (true)
            {
                //Check for a miss.
                if (xCell < 0 ||
                    zCell < 0 ||
                    xCell >= heights.GetLength(0) - 1 ||
                    zCell >= heights.GetLength(1) - 1)
                    return false;

                //Test the triangles of this cell.
                Vector3 v1, v2, v3, v4;
                // v3 v4
                // v1 v2
                GetLocalPosition(xCell, zCell, out v1);
                GetLocalPosition(xCell + 1, zCell, out v2);
                GetLocalPosition(xCell, zCell + 1, out v3);
                GetLocalPosition(xCell + 1, zCell + 1, out v4);
                RayHit hit1, hit2;
                bool didHit1;
                bool didHit2;

                //Don't bother doing ray intersection tests if the ray can't intersect it.

                float highest = v1.Y;
                float lowest = v1.Y;
                if (v2.Y > highest)
                    highest = v2.Y;
                else if (v2.Y < lowest)
                    lowest = v2.Y;
                if (v3.Y > highest)
                    highest = v3.Y;
                else if (v3.Y < lowest)
                    lowest = v3.Y;
                if (v4.Y > highest)
                    highest = v4.Y;
                else if (v4.Y < lowest)
                    lowest = v4.Y;


                if (!(progressingOrigin.Y > highest && localRay.Direction.Y > 0 ||
                    progressingOrigin.Y < lowest && localRay.Direction.Y < 0))
                {


                    if (quadTriangleOrganization == QuadTriangleOrganization.BottomLeftUpperRight)
                    {
                        //Always perform the raycast as if Y+ in local space is the way the triangles are facing.
                        didHit1 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v2, ref v3, out hit1);
                        didHit2 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v2, ref v4, ref v3, out hit2);
                    }
                    else //if (quadTriangleOrganization == CollisionShapes.QuadTriangleOrganization.BottomRightUpperLeft)
                    {
                        didHit1 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v2, ref v4, out hit1);
                        didHit2 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v4, ref v3, out hit2);
                    }
                    if (didHit1 && didHit2)
                    {
                        if (hit1.T < hit2.T)
                        {
                            Vector3.Multiply(ref ray.Direction, hit1.T, out hit.Location);
                            Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                            Matrix3X3.TransformTranspose(ref hit1.Normal, ref inverse.LinearTransform, out hit.Normal);
                            hit.T = hit1.T;
                            return true;
                        }
                        Vector3.Multiply(ref ray.Direction, hit2.T, out hit.Location);
                        Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                        Matrix3X3.TransformTranspose(ref hit2.Normal, ref inverse.LinearTransform, out hit.Normal);
                        hit.T = hit2.T;
                    }
                    else if (didHit1)
                    {
                        Vector3.Multiply(ref ray.Direction, hit1.T, out hit.Location);
                        Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                        Matrix3X3.TransformTranspose(ref hit1.Normal, ref inverse.LinearTransform, out hit.Normal);
                        hit.T = hit1.T;
                        return true;
                    }
                    else if (didHit2)
                    {
                        Vector3.Multiply(ref ray.Direction, hit2.T, out hit.Location);
                        Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
                        Matrix3X3.TransformTranspose(ref hit2.Normal, ref inverse.LinearTransform, out hit.Normal);
                        hit.T = hit2.T;
                        return true;
                    }
                }

                //Move to the next cell.

                float timeToX;
                if (localRay.Direction.X < 0)
                    timeToX = -(progressingOrigin.X - xCell) / localRay.Direction.X;
                else if (ray.Direction.X > 0)
                    timeToX = (xCell + 1 - progressingOrigin.X) / localRay.Direction.X;
                else
                    timeToX = float.MaxValue;

                float timeToZ;
                if (localRay.Direction.Z < 0)
                    timeToZ = -(progressingOrigin.Z - zCell) / localRay.Direction.Z;
                else if (localRay.Direction.Z > 0)
                    timeToZ = (zCell + 1 - progressingOrigin.Z) / localRay.Direction.Z;
                else
                    timeToZ = float.MaxValue;

                //Move to the next cell.
                if (timeToX < timeToZ)
                {
                    if (localRay.Direction.X < 0)
                        xCell--;
                    else
                        xCell++;

                    distance += timeToX;
                    if (distance > maximumLength)
                        return false;

                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToX, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }
                else
                {
                    if (localRay.Direction.Z < 0)
                        zCell--;
                    else
                        zCell++;

                    distance += timeToZ;
                    if (distance > maximumLength)
                        return false;

                    Vector3 increment;
                    Vector3.Multiply(ref localRay.Direction, timeToZ, out increment);
                    Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin);
                }

            }


        }
Ejemplo n.º 13
0
 /// <summary>
 /// Casts a convex shape against the collidable.
 /// </summary>
 /// <param name="castShape">Shape to cast.</param>
 /// <param name="startingTransform">Initial transform of the shape.</param>
 /// <param name="sweep">Sweep to apply to the shape.</param>
 /// <param name="hit">Hit data, if any.</param>
 /// <returns>Whether or not the cast hit anything.</returns>
 public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
 {
     hit = new RayHit();
     BoundingBox boundingBox;
     Toolbox.GetExpandedBoundingBox(ref castShape, ref startingTransform, ref sweep, out boundingBox);
     var hitElements = Resources.GetCompoundChildList();
     if (hierarchy.Tree.GetOverlaps(boundingBox, hitElements))
     {
         hit.T = float.MaxValue;
         for (int i = 0; i < hitElements.count; i++)
         {
             var candidate = hitElements.Elements[i].CollisionInformation;
             RayHit tempHit;
             if (candidate.ConvexCast(castShape, ref startingTransform, ref sweep, out tempHit) && tempHit.T < hit.T)
             {
                 hit = tempHit;
             }
         }
         Resources.GiveBack(hitElements);
         return hit.T != float.MaxValue;
     }
     Resources.GiveBack(hitElements);
     return false;
 }
Ejemplo n.º 14
0
        protected override bool ShadowRayTest(ref RayHit shadowRayHit, ref RayData shadowRay, out RgbSpectrum attenuation, out bool continueTrace)
        {
            var hit = shadowRayHit.Index == 0xffffffffu || scene.IsLight((int)shadowRayHit.Index);
            attenuation = new RgbSpectrum(1f);
            continueTrace = false;

            if (hit) return true;
            var mesh = scene.GetMeshByTriangleIndex((int)shadowRayHit.Index);
            var mat =
                //SurfaceMaterials.CreateMaterial(scene.MaterialProvider.Get(mesh.MaterialName));
                scene.MatLib.GetSurfMat(mesh != null ? mesh.MaterialName : "default");
            shadowRayEvent = mat.Type.TypeToEvent();
            if (mat.TransparentShadows)
            {
                continueTrace = true;
                return true;
            }

            //if (shadowRayEvent.Has(BsdfEvent.Transmit))
            //{
            //    var att = MathLab.Exp(-0.1f*shadowRayHit.Distance);
            //    attenuation *= att + att* hitInfo.TextureData.Transmittance;
            //    continueTrace = true;
            //    return true;
            //}

            //if (mat.AlphaTexture != null)
            //{
            //    continueTrace = true;
            //    this.SurfaceSampler.GetIntersection(ref shadowRay, ref shadowRayHit, ref hitInfo, IntersectionOptions.ResolveTextures);
            //    attenuation = (RgbSpectrum) hitInfo.TextureData.Alpha;
            //    hit = true;
            //    //mat.MaterialData.Kt.Filter() < Sample.GetLazyValue();
            //}

            return hit;
        }
Ejemplo n.º 15
0
        private bool ShadowRayTest(ref RayHit shadowRayHit, out RgbSpectrum attenuation)
        {
            var hit = shadowRayHit.Index == 0xffffffffu || scene.IsLight((int)shadowRayHit.Index);
            attenuation = new RgbSpectrum(1f);
            if (hit) return true;
            var mesh = scene.GetMeshByTriangleIndex((int)shadowRayHit.Index);
            var mat =
                //SurfaceMaterials.CreateMaterial(scene.MaterialProvider.Get(mesh.MaterialName));
                scene.MatLib.GetSurfMat(mesh != null ? mesh.MaterialName : "default");

            if (mat.AlphaTexture != null)
            {
                attenuation = (RgbSpectrum) (mat.AlphaTexture as ConstTextureInfo).Color;
                hit = true;
                //mat.MaterialData.Kt.Filter() < Sample.GetLazyValue();
            }

            return hit;
        }
Ejemplo n.º 16
0
        ///<summary>
        /// Tests a ray against the triangle mesh.
        ///</summary>
        ///<param name="ray">Ray to test against the mesh.</param>
        /// <param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        /// <param name="sidedness">Sidedness to apply to the mesh for the ray cast.</param>
        ///<param name="rayHit">Hit data for the ray, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
        {
            var  rayHits  = CommonResources.GetRayHitList();
            bool toReturn = RayCast(ray, maximumLength, sidedness, rayHits);

            if (toReturn)
            {
                rayHit = rayHits[0];
                for (int i = 1; i < rayHits.Count; i++)
                {
                    RayHit hit = rayHits[i];
                    if (hit.T < rayHit.T)
                    {
                        rayHit = hit;
                    }
                }
            }
            else
            {
                rayHit = new RayHit();
            }
            CommonResources.GiveBack(rayHits);
            return(toReturn);
        }
Ejemplo n.º 17
0
 ///<summary>
 /// Tests a ray against the triangle mesh.
 ///</summary>
 ///<param name="ray">Ray to test against the mesh.</param>
 /// <param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
 ///<param name="rayHit">Hit data for the ray, if any.</param>
 ///<returns>Whether or not the ray hit the mesh.</returns>
 public bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
 {
     return(RayCast(ray, maximumLength, TriangleSidedness.DoubleSided, out rayHit));
 }
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
        /// in the entry, this filter will be passed into inner ray casts.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayHit hit)
        {
            RayCastResult result;
            bool          toReturn = Shape.ConvexCast(castShape, ref startingTransform, ref sweep, filter, out result);

            hit = result.HitData;
            return(toReturn);
        }
        /// <summary>
        /// Tests a ray against the entry.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
        /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
        /// in the entry, this filter will be passed into inner ray casts.</param>
        /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
        /// <returns>Whether or not the ray hit the entry.</returns>
        public override bool RayCast(Ray ray, float maximumLength, Func <BroadPhaseEntry, bool> filter, out RayHit rayHit)
        {
            RayCastResult result;
            bool          toReturn = Shape.RayCast(ray, maximumLength, filter, out result);

            rayHit = result.HitData;
            return(toReturn);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Tests a ray against the entry.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
        /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
        /// <returns>Whether or not the ray hit the entry.</returns>
        public override bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
        {
            //Put the ray into local space.
            Ray       localRay;
            Matrix3x3 orientation;

            Matrix3x3.CreateFromQuaternion(ref worldTransform.Orientation, out orientation);
            Matrix3x3.TransformTranspose(ref ray.Direction, ref orientation, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref worldTransform.Position, out localRay.Position);
            Matrix3x3.TransformTranspose(ref localRay.Position, ref orientation, out localRay.Position);


            if (Shape.solidity == MobileMeshSolidity.Solid)
            {
                //Find all hits.  Use the count to determine the ray started inside or outside.
                //If it starts inside and we're in 'solid' mode, then return the ray start.
                //The raycast must be of infinite length at first.  This allows it to determine
                //if it is inside or outside.
                if (Shape.IsLocalRayOriginInMesh(ref localRay, out rayHit))
                {
                    //It was inside!
                    rayHit = new RayHit()
                    {
                        Location = ray.Position, Normal = Vector3.Zero, T = 0
                    };
                    return(true);
                }
                else
                {
                    if (rayHit.T < maximumLength)
                    {
                        //Transform the hit into world space.
                        Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                        Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                        Matrix3x3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                    }
                    else
                    {
                        //The hit was too far away, or there was no hit (in which case T would be float.MaxValue).
                        return(false);
                    }
                    return(true);
                }
            }
            else
            {
                //Just do a normal raycast since the object isn't solid.
                TriangleSidedness sidedness;
                switch (Shape.solidity)
                {
                case MobileMeshSolidity.Clockwise:
                    sidedness = TriangleSidedness.Clockwise;
                    break;

                case MobileMeshSolidity.Counterclockwise:
                    sidedness = TriangleSidedness.Counterclockwise;
                    break;

                default:
                    sidedness = TriangleSidedness.DoubleSided;
                    break;
                }
                if (Shape.TriangleMesh.RayCast(localRay, maximumLength, sidedness, out rayHit))
                {
                    //Transform the hit into world space.
                    Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                    Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                    Matrix3x3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                    return(true);
                }
            }
            rayHit = new RayHit();
            return(false);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            if (Shape.solidity == MobileMeshSolidity.Solid)
            {
                //If the convex cast is inside the mesh and the mesh is solid, it should return t = 0.
                var ray = new Ray()
                {
                    Position = startingTransform.Position, Direction = Toolbox.UpVector
                };
                if (Shape.IsLocalRayOriginInMesh(ref ray, out hit))
                {
                    hit = new RayHit()
                    {
                        Location = startingTransform.Position, Normal = new Vector3(), T = 0
                    };
                    return(true);
                }
            }
            hit = new RayHit();
            BoundingBox boundingBox;
            var         transform = new AffineTransform {
                Translation = worldTransform.Position
            };

            Matrix3x3.CreateFromQuaternion(ref worldTransform.Orientation, out transform.LinearTransform);
            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref transform, ref sweep, out boundingBox);
            var tri         = PhysicsResources.GetTriangle();
            var hitElements = CommonResources.GetIntList();

            if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    AffineTransform.Transform(ref tri.vA, ref transform, out tri.vA);
                    AffineTransform.Transform(ref tri.vB, ref transform, out tri.vB);
                    AffineTransform.Transform(ref tri.vC, ref transform, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.MaximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    tri.MaximumRadius   = (float)Math.Sqrt(tri.MaximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform {
                        Orientation = Quaternion.Identity, Position = center
                    };
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.MaximumRadius = 0;
                PhysicsResources.GiveBack(tri);
                CommonResources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            PhysicsResources.GiveBack(tri);
            CommonResources.GiveBack(hitElements);
            return(false);
        }
Ejemplo n.º 22
0
        ///<summary>
        /// Tests a ray against the surface of the mesh.  This does not take into account solidity.
        ///</summary>
        ///<param name="ray">Ray to test.</param>
        ///<param name="maximumLength">Maximum length of the ray to test; in units of the ray's direction's length.</param>
        ///<param name="sidedness">Sidedness to use during the ray cast.  This does not have to be the same as the mesh's sidedness.</param>
        ///<param name="rayHit">The hit location of the ray on the mesh, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
        {
            //Put the ray into local space.
            Ray       localRay;
            Matrix3x3 orientation;

            Matrix3x3.CreateFromQuaternion(ref worldTransform.Orientation, out orientation);
            Matrix3x3.TransformTranspose(ref ray.Direction, ref orientation, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref worldTransform.Position, out localRay.Position);
            Matrix3x3.TransformTranspose(ref localRay.Position, ref orientation, out localRay.Position);

            if (Shape.TriangleMesh.RayCast(localRay, maximumLength, sidedness, out rayHit))
            {
                //Transform the hit into world space.
                Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                Matrix3x3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                return(true);
            }
            rayHit = new RayHit();
            return(false);
        }
Ejemplo n.º 23
0
 public virtual void Process(ref RayHit rh, ref Vector wo, out bool finishPath, out float pdf)
 {
     finishPath = true;
     pdf = 0f;            
 }
Ejemplo n.º 24
0
        /// <summary>
        /// Gets the intersection between the triangle and the ray.
        /// </summary>
        /// <param name="ray">Ray to test against the triangle.</param>
        /// <param name="transform">Transform to apply to the triangle shape for the test.</param>
        /// <param name="maximumLength">Maximum distance to travel in units of the direction vector's length.</param>
        /// <param name="hit">Hit data of the ray cast, if any.</param>
        /// <returns>Whether or not the ray hit the target.</returns>
        public override bool RayTest(ref Ray ray, ref RigidTransform transform, float maximumLength, out RayHit hit)
        {
            Matrix3X3 orientation;
            Matrix3X3.CreateFromQuaternion(ref transform.Orientation, out orientation);
            Ray localRay;
            Quaternion conjugate;
            Quaternion.Conjugate(ref transform.Orientation, out conjugate);
            Vector3.Transform(ref ray.Direction, ref conjugate, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref transform.Position, out localRay.Position);
            Vector3.Transform(ref localRay.Position, ref conjugate, out localRay.Position);

            bool toReturn = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref vA, ref vB, ref vC, out hit);
            //Move the hit back into world space.
            Vector3.Multiply(ref ray.Direction, hit.T, out hit.Location);
            Vector3.Add(ref ray.Position, ref hit.Location, out hit.Location);
            Vector3.Transform(ref hit.Normal, ref transform.Orientation, out hit.Normal);
            return toReturn;
        }
Ejemplo n.º 25
0
 ///<summary>
 /// Tests a ray against the triangle mesh.
 ///</summary>
 ///<param name="ray">Ray to test against the mesh.</param>
 /// <param name="sidedness">Sidedness to apply to the mesh for the ray cast.</param>
 ///<param name="rayHit">Hit data for the ray, if any.</param>
 ///<returns>Whether or not the ray hit the mesh.</returns>
 public bool RayCast(Ray ray, TriangleSidedness sidedness, out RayHit rayHit)
 {
     return(RayCast(ray, float.MaxValue, sidedness, out rayHit));
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            if (Shape.solidity == MobileMeshSolidity.Solid)
            {
                //If the convex cast is inside the mesh and the mesh is solid, it should return t = 0.
                var ray = new Ray() { Position = startingTransform.Position, Direction = Toolbox.UpVector };
                if (Shape.IsLocalRayOriginInMesh(ref ray, out hit))
                {

                    hit = new RayHit() { Location = startingTransform.Position, Normal = new Vector3(), T = 0 };
                    return true;
                }
            }
            hit = new RayHit();
            BoundingBox boundingBox;
            AffineTransform transform = new AffineTransform();
            transform.Translation = worldTransform.Position;
            Matrix3X3.CreateFromQuaternion(ref worldTransform.Orientation, out transform.LinearTransform);
            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref transform, ref sweep, out boundingBox);
            var tri = Resources.GetTriangle();
            var hitElements = Resources.GetIntList();
            if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    AffineTransform.Transform(ref tri.vA, ref transform, out tri.vA);
                    AffineTransform.Transform(ref tri.vB, ref transform, out tri.vB);
                    AffineTransform.Transform(ref tri.vC, ref transform, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.maximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.maximumRadius < radius)
                        tri.maximumRadius = radius;
                    radius = tri.vC.LengthSquared();
                    if (tri.maximumRadius < radius)
                        tri.maximumRadius = radius;
                    tri.maximumRadius = (float)Math.Sqrt(tri.maximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform();
                    triangleTransform.Orientation = Quaternion.Identity;
                    triangleTransform.Position = center;
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.maximumRadius = 0;
                Resources.GiveBack(tri);
                Resources.GiveBack(hitElements);
                return hit.T != float.MaxValue;
            }
            Resources.GiveBack(tri);
            Resources.GiveBack(hitElements);
            return false;
        }
    public static RayHit Trace(Ray cameraRay, SpatialGrid spatialGrid, List <int> geometryIndexList,
                               List <RTTriangle_t> geometryList, int exclude)
    {
        RayHit bestHit = RayHit.CreateRayHit();

        float t0 = float.NegativeInfinity;
        float t1 = float.PositiveInfinity;

        if (RayBoxIntersectionCompute.RayBoxIntersection(cameraRay, spatialGrid.min, spatialGrid.max, ref t0, ref t1))
        {
            Vector3 entry = cameraRay.GetPoint(t1);

            GridStep step = DetermineGridStep(cameraRay);

            Ray entryToBoundaryRay          = CreateRay(entry, cameraRay.direction);
            SpatialGridIndex entryGridIndex = SpatialGridCompute.GetGridIndexAtPoint(spatialGrid, entry);

            RayHit deltaX = new RayHit();
            RayHit deltaY = new RayHit();
            RayHit deltaZ = new RayHit();
            SpatialGridCompute.GetDeltaToBoundary(
                entryGridIndex,
                spatialGrid,
                entryToBoundaryRay,
                step,
                ref deltaX,
                ref deltaY,
                ref deltaZ);

            RayHit distToNextX = new RayHit();
            RayHit distToNextY = new RayHit();
            RayHit distToNextZ = new RayHit();
            SpatialGridCompute.DistanceBetweenBoundary(
                cameraRay,
                step,
                entryGridIndex,
                spatialGrid,
                deltaX.hitPoint,
                deltaY.hitPoint,
                deltaZ.hitPoint,
                ref distToNextX,
                ref distToNextY,
                ref distToNextZ
                );

            float tx = deltaX.distance;
            float ty = deltaY.distance;
            float tz = deltaZ.distance;

            SpatialGridIndex current = entryGridIndex;

            #region Debug
            CubeController currentGridController = CubeGlobalData.Instance.GetGridAtIndex(current);
            JoeRayCaster.voxelsHitList.Clear();
            JoeRayCaster.voxelsHitList.Add(currentGridController);
            #endregion    //Debug

            bool hasHit  = false;
            bool outside = false;

            do
            {
                bestHit = LocalGridTrace(
                    cameraRay,
                    current,
                    geometryIndexList,
                    geometryList,
                    spatialGrid,
                    -1);

                if (tx < ty)
                {
                    if (tx < tz)
                    {
                        // Move On X
                        current.x = current.x + step.x;
                        tx       += distToNextX.distance;
                    }
                    else
                    {
                        // Move On Z
                        current.z = current.z + step.z;
                        tz       += distToNextZ.distance;
                    }
                }
                else
                {
                    if (ty < tz)
                    {
                        // Move On Y
                        current.y = current.y + step.y;
                        ty       += distToNextY.distance;
                    }
                    else
                    {
                        // Move On Z
                        current.z = current.z + step.z;
                        tz       += distToNextZ.distance;
                    }
                }

                #region Debug
                currentGridController = CubeGlobalData.Instance.GetGridAtIndex(current);
                if (currentGridController != null)
                {
                    JoeRayCaster.voxelsHitList.Add(currentGridController);
                }
                #endregion

                hasHit  = (bestHit.distance < float.PositiveInfinity);
                outside = SpatialGridCompute.IsGridIndexOutsideGrid(spatialGrid, current);
            }while(!hasHit && !outside);
        }
        else
        {
            JoeRayCaster.voxelsHitList.Clear();
        }

        return(bestHit);
    }
Ejemplo n.º 28
0
        //TODO: Substantial redundancy here.  If a change is ever needed, compress them down.

        /// <summary>
        /// Tests a ray against the collidable.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
        /// <param name="rayHit">Hit location of the ray on the collidable, if any.</param>
        /// <returns>Whether or not the ray hit the collidable.</returns>
        public override bool RayCast(Ray ray, float maximumLength, Func<BroadPhaseEntry, bool> filter, out RayHit rayHit)
        {
            rayHit = new RayHit();
            if (filter(this))
            {
                var hitElements = Resources.GetCompoundChildList();
                if (hierarchy.Tree.GetOverlaps(ray, maximumLength, hitElements))
                {
                    rayHit.T = float.MaxValue;
                    for (int i = 0; i < hitElements.count; i++)
                    {
                        RayHit tempHit;
                        if (hitElements.Elements[i].CollisionInformation.RayCast(ray, maximumLength, filter, out tempHit) && tempHit.T < rayHit.T)
                        {
                            rayHit = tempHit;
                        }
                    }
                    Resources.GiveBack(hitElements);
                    return rayHit.T != float.MaxValue;
                }
                Resources.GiveBack(hitElements);
            }
            return false;
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Gets the intersection between the triangle and the ray.
        /// </summary>
        /// <param name="ray">Ray to test against the triangle.</param>
        /// <param name="transform">Transform to apply to the triangle shape for the test.</param>
        /// <param name="maximumLength">Maximum distance to travel in units of the direction vector's length.</param>
        /// <param name="hit">Hit data of the ray cast, if any.</param>
        /// <returns>Whether or not the ray hit the target.</returns>
        public override bool RayTest(ref Ray ray, ref RigidTransform transform, Fix64 maximumLength, out RayHit hit)
        {
            Matrix3x3 orientation;

            Matrix3x3.CreateFromQuaternion(ref transform.Orientation, out orientation);
            Ray        localRay;
            Quaternion conjugate;

            Quaternion.Conjugate(ref transform.Orientation, out conjugate);
            Quaternion.Transform(ref ray.Direction, ref conjugate, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref transform.Position, out localRay.Position);
            Quaternion.Transform(ref localRay.Position, ref conjugate, out localRay.Position);

            bool toReturn = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref vA, ref vB, ref vC, out hit);

            //Move the hit back into world space.
            Vector3.Multiply(ref ray.Direction, hit.T, out hit.Location);
            Vector3.Add(ref ray.Position, ref hit.Location, out hit.Location);
            Quaternion.Transform(ref hit.Normal, ref transform.Orientation, out hit.Normal);
            return(toReturn);
        }
Ejemplo n.º 30
0
 ///<summary>
 /// Tests a ray against the mesh.
 ///</summary>
 ///<param name="ray">Ray to test.</param>
 ///<param name="maximumLength">Maximum length to test in units of the ray direction's length.</param>
 ///<param name="sidedness">Sidedness to use when raycasting.  Doesn't have to be the same as the mesh's own sidedness.</param>
 ///<param name="rayHit">Data about the ray's intersection with the mesh, if any.</param>
 ///<returns>Whether or not the ray hit the mesh.</returns>
 public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
 {
     return(mesh.RayCast(ray, maximumLength, sidedness, out rayHit));
 }
Ejemplo n.º 31
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public override bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
 {
     return(Shape.RayCast(ref ray, maximumLength, ref worldTransform, out rayHit));
 }
Ejemplo n.º 32
0
 public override bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
 {
     return triangleMesh.RayCast(ray, maximumLength, TriangleSidedness.DoubleSided, out rayHit);
 }
Ejemplo n.º 33
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            hit = new RayHit();
            BoundingBox localSpaceBoundingBox;

            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref worldTransform, ref sweep, out localSpaceBoundingBox);
            var tri         = PhysicsThreadResources.GetTriangle();
            var hitElements = new QuickList <int>(BufferPools <int> .Thread);

            if (Shape.GetOverlaps(localSpaceBoundingBox, ref hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.GetTriangle(hitElements.Elements[i], ref worldTransform, out tri.vA, out tri.vB, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.MaximumRadius = tri.vA.LengthSquared;
                    float radius = tri.vB.LengthSquared;
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared;
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    tri.MaximumRadius   = (float)Math.Sqrt(tri.MaximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform {
                        Orientation = Quaternion.Identity, Position = center
                    };
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.MaximumRadius = 0;
                PhysicsThreadResources.GiveBack(tri);
                hitElements.Dispose();
                return(hit.T != float.MaxValue);
            }
            PhysicsThreadResources.GiveBack(tri);
            hitElements.Dispose();
            return(false);
        }
Ejemplo n.º 34
0
        /// <summary>
        /// Tests to see if a ray's origin is contained within the mesh.
        /// If it is, the hit location is found.
        /// If it isn't, the hit location is still valid if a hit occurred.
        /// If the origin isn't inside and there was no hit, the hit has a T value of float.MaxValue.
        /// </summary>
        /// <param name="ray">Ray in the local space of the shape to test.</param>
        /// <param name="hit">The first hit against the mesh, if any.</param>
        /// <returns>Whether or not the ray origin was in the mesh.</returns>
        public bool IsLocalRayOriginInMesh(ref Ray ray, out RayHit hit)
        {
            if (IsLocalRayOriginInMeshHelper(ref ray, out hit))
            {
                if (numberOfContainmentChecks > 1 && hit.T > DepthDoubleCheckLimit)
                {
                    //It's an extremely deep penetration... Suspicious.
                    //Send the ray in the other direction to corroborate the result.
                    //A false positive can sometimes occur
                    Ray alternateRay;
                    Vector3.Negate(ref ray.Direction, out alternateRay.Direction);
                    alternateRay.Position = ray.Position;
                    RayHit alternateHit;
                    if (!IsLocalRayOriginInMeshHelper(ref alternateRay, out alternateHit))
                    {
                        //The double check didn't hit anything.  It's very unlikely that the object is actually inside the shape.
                        return false;
                    }
                    else if (numberOfContainmentChecks > 2)
                    {
                        //It found a hit in the other direction.  Triple checking is enabled though, so let's try a third direction!
                        //This one will be perpendicular to the current ray direction.
                        Vector3.Cross(ref ray.Direction, ref Toolbox.UpVector, out alternateRay.Direction);
                        float lengthSquared = alternateRay.Direction.LengthSquared();
                        if (lengthSquared < Toolbox.Epsilon)
                        {
                            //The ray direction was already pointing nearly up.  Pick a different direction.
                            Vector3.Cross(ref ray.Direction, ref Toolbox.RightVector, out alternateRay.Direction);
                            lengthSquared = alternateRay.Direction.LengthSquared();
                        }
                        Vector3.Divide(ref alternateRay.Direction, (float)Math.Sqrt(lengthSquared), out alternateRay.Direction);
                        alternateRay.Position = ray.Position;
                        if (!IsLocalRayOriginInMeshHelper(ref alternateRay, out alternateHit))
                        {
                            //No hit was found on the third test!  The fact that we had two false positives is extremely improbable,
                            //but it's better to assume that it is not intersecting.
                            return false;
                        }
                    }

                }
                return true;
            }
            return false;
        }
Ejemplo n.º 35
0
 public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayHit hit)
 {
     return(MPRToolbox.Sweep(castShape, Shape, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref worldTransform, out hit));
 }
Ejemplo n.º 36
0
 internal bool IsHitUnique(RawList<RayHit> hits, ref RayHit hit)
 {
     for (int i = 0; i < hits.count; i++)
     {
         if (Math.Abs(hits.Elements[i].T - hit.T) < MeshHitUniquenessThreshold)
             return false;
     }
     hits.Add(hit);
     return true;
 }
Ejemplo n.º 37
0
 /// <summary>
 /// Gets the intersection between the sphere and the ray.
 /// </summary>
 /// <param name="ray">Ray to test against the sphere.</param>
 /// <param name="transform">Transform applied to the convex for the test.</param>
 /// <param name="maximumLength">Maximum distance to travel in units of the ray direction's length.</param>
 /// <param name="hit">Ray hit data, if any.</param>
 /// <returns>Whether or not the ray hit the target.</returns>
 public override bool RayTest(ref Ray ray, ref RigidTransform transform, float maximumLength, out RayHit hit)
 {
     return(Toolbox.RayCastSphere(ref ray, ref transform.Position, collisionMargin, maximumLength, out hit));
 }
Ejemplo n.º 38
0
 public override bool ConvexCast(ConvexShape castShape, ref MathExtensions.RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
 {
     return MPRToolbox.Sweep(castShape, Shape, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref worldTransform, out hit);
 }
Ejemplo n.º 39
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public override bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
 {
     return(RayCast(ray, maximumLength, sidedness, out rayHit));
 }
Ejemplo n.º 40
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
 /// in the entry, this filter will be passed into inner ray casts.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public virtual bool RayCast(Ray ray, float maximumLength, Func <BroadPhaseEntry, bool> filter, out RayHit rayHit)
 {
     if (filter(this))
     {
         return(RayCast(ray, maximumLength, out rayHit));
     }
     rayHit = new RayHit();
     return(false);
 }
Ejemplo n.º 41
0
        ///<summary>
        /// Tests a ray against the instance.
        ///</summary>
        ///<param name="ray">Ray to test.</param>
        ///<param name="maximumLength">Maximum length of the ray to test; in units of the ray's direction's length.</param>
        ///<param name="sidedness">Sidedness to use during the ray cast.  This does not have to be the same as the mesh's sidedness.</param>
        ///<param name="rayHit">The hit location of the ray on the mesh, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
        {
            //Put the ray into local space.
            Ray             localRay;
            AffineTransform inverse;

            AffineTransform.Invert(ref worldTransform, out inverse);
            Matrix3X3.Transform(ref ray.Direction, ref inverse.LinearTransform, out localRay.Direction);
            AffineTransform.Transform(ref ray.Position, ref inverse, out localRay.Position);

            if (Shape.TriangleMesh.RayCast(localRay, maximumLength, sidedness, out rayHit))
            {
                //Transform the hit into world space.
                Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                Matrix3X3.TransformTranspose(ref rayHit.Normal, ref inverse.LinearTransform, out rayHit.Normal);
                return(true);
            }
            rayHit = new RayHit();
            return(false);
        }
Ejemplo n.º 42
0
        /// <summary>
        /// Helper to add ray hit in a Tri (triangle).
        /// </summary>
        private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
        {
            // Check for hit in triangle
            Vector3 posHitProj;
            Vector3 normalProj;
            if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
            {
                // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
                if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
                    return;

                // Transform hit and normal to region coordinate system
                Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
                Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);

                // Remove duplicate hits at triangle intersections
                float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
                for (int i = rayHits.Count - 1; i >= 0; i--)
                {
                    if (rayHits[i].PartId != rayTrans.PartId)
                        break;
                    if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
                        return;
                }

                // Build result data set
                RayHit rayHit = new RayHit();
                rayHit.PartId = rayTrans.PartId;
                rayHit.GroupId = rayTrans.GroupId;
                rayHit.Link = rayTrans.Link;
                rayHit.Position = posHit;
                rayHit.Normal = normal;
                rayHit.Distance = distance;
                rayHits.Add(rayHit);
            }
        }
Ejemplo n.º 43
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            hit = new RayHit();
            BoundingBox boundingBox;

            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref worldTransform, ref sweep, out boundingBox);
            var tri         = Resources.GetTriangle();
            var hitElements = Resources.GetIntList();

            if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    AffineTransform.Transform(ref tri.vA, ref worldTransform, out tri.vA);
                    AffineTransform.Transform(ref tri.vB, ref worldTransform, out tri.vB);
                    AffineTransform.Transform(ref tri.vC, ref worldTransform, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.maximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.maximumRadius < radius)
                    {
                        tri.maximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared();
                    if (tri.maximumRadius < radius)
                    {
                        tri.maximumRadius = radius;
                    }
                    tri.maximumRadius   = (float)Math.Sqrt(tri.maximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform();
                    triangleTransform.Orientation = Quaternion.Identity;
                    triangleTransform.Position    = center;
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.maximumRadius = 0;
                Resources.GiveBack(tri);
                Resources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            Resources.GiveBack(tri);
            Resources.GiveBack(hitElements);
            return(false);
        }
Ejemplo n.º 44
0
        ///<summary>
        /// Tests a ray against the surface of the mesh.  This does not take into account solidity.
        ///</summary>
        ///<param name="ray">Ray to test.</param>
        ///<param name="maximumLength">Maximum length of the ray to test; in units of the ray's direction's length.</param>
        ///<param name="sidedness">Sidedness to use during the ray cast.  This does not have to be the same as the mesh's sidedness.</param>
        ///<param name="rayHit">The hit location of the ray on the mesh, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
        {
            //Put the ray into local space.
            Ray localRay;
            Matrix3X3 orientation;
            Matrix3X3.CreateFromQuaternion(ref worldTransform.Orientation, out orientation);
            Matrix3X3.TransformTranspose(ref ray.Direction, ref orientation, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref worldTransform.Position, out localRay.Position);
            Matrix3X3.TransformTranspose(ref localRay.Position, ref orientation, out localRay.Position);

            if (Shape.TriangleMesh.RayCast(localRay, maximumLength, sidedness, out rayHit))
            {
                //Transform the hit into world space.
                Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                Matrix3X3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                return true;
            }
            rayHit = new RayHit();
            return false;
        }
Ejemplo n.º 45
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public abstract bool RayCast(Ray ray, float maximumLength, out RayHit rayHit);
Ejemplo n.º 46
0
        /// <summary>
        /// Tests a ray against the entry.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
        /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
        /// <returns>Whether or not the ray hit the entry.</returns>
        public override bool RayCast(Ray ray, float maximumLength, out RayHit rayHit)
        {
            //Put the ray into local space.
            Ray localRay;
            Matrix3X3 orientation;
            Matrix3X3.CreateFromQuaternion(ref worldTransform.Orientation, out orientation);
            Matrix3X3.TransformTranspose(ref ray.Direction, ref orientation, out localRay.Direction);
            Vector3.Subtract(ref ray.Position, ref worldTransform.Position, out localRay.Position);
            Matrix3X3.TransformTranspose(ref localRay.Position, ref orientation, out localRay.Position);


            if (Shape.solidity == MobileMeshSolidity.Solid)
            {
                //Find all hits.  Use the count to determine the ray started inside or outside.
                //If it starts inside and we're in 'solid' mode, then return the ray start.
                //The raycast must be of infinite length at first.  This allows it to determine
                //if it is inside or outside.
                if (Shape.IsLocalRayOriginInMesh(ref localRay, out rayHit))
                {
                    //It was inside!
                    rayHit = new RayHit() { Location = ray.Position, Normal = Vector3.Zero, T = 0 };
                    return true;

                }
                else
                {
                    if (rayHit.T < maximumLength)
                    {
                        //Transform the hit into world space.
                        Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                        Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                        Matrix3X3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                    }
                    else
                    {
                        //The hit was too far away, or there was no hit (in which case T would be float.MaxValue).
                        return false;
                    }
                    return true;
                }
            }
            else
            {
                //Just do a normal raycast since the object isn't solid.
                TriangleSidedness sidedness;
                switch (Shape.solidity)
                {
                    case MobileMeshSolidity.Clockwise:
                        sidedness = TriangleSidedness.Clockwise;
                        break;
                    case MobileMeshSolidity.Counterclockwise:
                        sidedness = TriangleSidedness.Counterclockwise;
                        break;
                    case MobileMeshSolidity.DoubleSided:
                    default:
                        sidedness = TriangleSidedness.DoubleSided;
                        break;
                }
                if (Shape.TriangleMesh.RayCast(localRay, maximumLength, sidedness, out rayHit))
                {
                    //Transform the hit into world space.
                    Vector3.Multiply(ref ray.Direction, rayHit.T, out rayHit.Location);
                    Vector3.Add(ref rayHit.Location, ref ray.Position, out rayHit.Location);
                    Matrix3X3.Transform(ref rayHit.Normal, ref orientation, out rayHit.Normal);
                    return true;
                }
            }
            rayHit = new RayHit();
            return false;
        }
Ejemplo n.º 47
0
 public override void registerHit(RayHit hit)
 {
     m_hits.Add(hit);
     m_lightTexture.SetPixel(hit.pixel.x, hit.pixel.y, hit.ray.color);
 }
Ejemplo n.º 48
0
        protected override bool ShadowRayTest(ref RayHit shadowRayHit, ref RayData shadowRay, out RgbSpectrum attenuation, out bool continueTrace)
        {
            var hit = shadowRayHit.Index == 0xffffffffu || scene.IsLight((int)shadowRayHit.Index);
            attenuation = new RgbSpectrum(1f);
            continueTrace = false;

            if (hit) return true;
            var mesh = scene.GetMeshByTriangleIndex((int)shadowRayHit.Index);
            var mat =
                //SurfaceMaterials.CreateMaterial(scene.MaterialProvider.Get(mesh.MaterialName));
                scene.MatLib.GetSurfMat(mesh != null ? mesh.MaterialName : "default");

            if (mat.TransparentShadows)
            {
                continueTrace = true;
                return true;
            }

            if (mat.AlphaTexture != null)
            {
                continueTrace = true;
                this.SurfaceSampler.GetIntersection(ref shadowRay, ref shadowRayHit, ref hitInfo, IntersectionOptions.ResolveTextures);
                attenuation = (RgbSpectrum) hitInfo.TextureData.Alpha;
                hit = true;
                //mat.MaterialData.Kt.Filter() < Sample.GetLazyValue();
            }

            return hit;
        }
Ejemplo n.º 49
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public abstract bool RayCast(Ray ray, float maximumLength, out RayHit rayHit);
Ejemplo n.º 50
0
 /// <summary>
 /// Tests a ray against the collidable.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="rayHit">Hit data, if any.</param>
 /// <param name="hitChild">Child collidable hit by the ray, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public bool RayCast(Ray ray, float maximumLength, out RayHit rayHit, out CompoundChild hitChild)
 {
     rayHit = new RayHit();
     hitChild = null;
     var hitElements = Resources.GetCompoundChildList();
     if (hierarchy.Tree.GetOverlaps(ray, maximumLength, hitElements))
     {
         rayHit.T = float.MaxValue;
         for (int i = 0; i < hitElements.count; i++)
         {
             EntityCollidable candidate = hitElements.Elements[i].CollisionInformation;
             RayHit tempHit;
             if (candidate.RayCast(ray, maximumLength, out tempHit) && tempHit.T < rayHit.T)
             {
                 rayHit = tempHit;
                 hitChild = hitElements.Elements[i];
             }
         }
         Resources.GiveBack(hitElements);
         return rayHit.T != float.MaxValue;
     }
     Resources.GiveBack(hitElements);
     return false;
 }
Ejemplo n.º 51
0
 /// <summary>
 /// Sweeps a convex shape against the entry.
 /// </summary>
 /// <param name="castShape">Swept shape.</param>
 /// <param name="startingTransform">Beginning location and orientation of the cast shape.</param>
 /// <param name="sweep">Sweep motion to apply to the cast shape.</param>
 /// <param name="filter">Test to apply to the entry. If it returns true, the entry is processed, otherwise the entry is ignored. If a collidable hierarchy is present
 /// in the entry, this filter will be passed into inner ray casts.</param>
 /// <param name="hit">Hit data of the cast on the entry, if any.</param>
 /// <returns>Whether or not the cast hit the entry.</returns>
 public virtual bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, Func <BroadPhaseEntry, bool> filter, out RayHit hit)
 {
     if (filter(this))
     {
         return(ConvexCast(castShape, ref startingTransform, ref sweep, out hit));
     }
     hit = new RayHit();
     return(false);
 }
Ejemplo n.º 52
0
 /// <summary>
 /// Sweeps a convex shape against the entry.
 /// </summary>
 /// <param name="castShape">Swept shape.</param>
 /// <param name="startingTransform">Beginning location and orientation of the cast shape.</param>
 /// <param name="sweep">Sweep motion to apply to the cast shape.</param>
 /// <param name="hit">Hit data of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public abstract bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit);
Ejemplo n.º 53
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayHit hit)
        {
            hit = new RayHit();
            BoundingBox boundingBox;

            castShape.GetSweptBoundingBox(ref startingTransform, ref sweep, out boundingBox);
            var tri         = PhysicsThreadResources.GetTriangle();
            var hitElements = CommonResources.GetIntList();

            if (Mesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    mesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    System.Numerics.Vector3 center;
                    Vector3Ex.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3Ex.Add(ref center, ref tri.vC, out center);
                    Vector3Ex.Multiply(ref center, 1f / 3f, out center);
                    Vector3Ex.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3Ex.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3Ex.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.MaximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    tri.MaximumRadius   = (float)Math.Sqrt(tri.MaximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform {
                        Orientation = System.Numerics.Quaternion.Identity, Position = center
                    };
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.MaximumRadius = 0;
                PhysicsThreadResources.GiveBack(tri);
                CommonResources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            PhysicsThreadResources.GiveBack(tri);
            CommonResources.GiveBack(hitElements);
            return(false);
        }
Ejemplo n.º 54
0
 /// <summary>
 /// Tests a ray against the entry.
 /// </summary>
 /// <param name="ray">Ray to test.</param>
 /// <param name="maximumLength">Maximum length, in units of the ray's direction's length, to test.</param>
 /// <param name="filter">Test to apply to try on the entry.  If a collidable hierarchy is present
 /// in the entry, this filter will be passed into inner ray casts.</param>
 /// <param name="rayHit">Hit location of the ray on the entry, if any.</param>
 /// <returns>Whether or not the ray hit the entry.</returns>
 public virtual bool RayCast(Ray ray, float maximumLength, Func<BroadPhaseEntry, bool> filter, out RayHit rayHit)
 {
     if (filter(this))
         return RayCast(ray, maximumLength, out rayHit);
     else
     {
         rayHit = new RayHit();
         return false;
     }
 }
Ejemplo n.º 55
0
        /// <summary>
        /// Gets the intersection between the box and the ray.
        /// </summary>
        /// <param name="ray">Ray to test against the box.</param>
        /// <param name="transform">Transform of the shape.</param>
        /// <param name="maximumLength">Maximum distance to travel in units of the direction vector's length.</param>
        /// <param name="hit">Hit data for the raycast, if any.</param>
        /// <returns>Whether or not the ray hit the target.</returns>
        public override bool RayTest(ref Ray ray, ref RigidTransform transform, float maximumLength, out RayHit hit)
        {
            hit = new RayHit();

            Quaternion conjugate;

            Quaternion.Conjugate(ref transform.Orientation, out conjugate);
            Vector3 localOrigin;

            Vector3.Subtract(ref ray.Position, ref transform.Position, out localOrigin);
            Vector3.Transform(ref localOrigin, ref conjugate, out localOrigin);
            Vector3 localDirection;

            Vector3.Transform(ref ray.Direction, ref conjugate, out localDirection);
            Vector3 normal = Toolbox.ZeroVector;
            float   temp, tmin = 0, tmax = maximumLength;

            if (Math.Abs(localDirection.X) < Toolbox.Epsilon && (localOrigin.X < -halfWidth || localOrigin.X > halfWidth))
            {
                return(false);
            }
            float inverseDirection = 1 / localDirection.X;
            float t1         = (-halfWidth - localOrigin.X) * inverseDirection;
            float t2         = (halfWidth - localOrigin.X) * inverseDirection;
            var   tempNormal = new Vector3(-1, 0, 0);

            if (t1 > t2)
            {
                temp        = t1;
                t1          = t2;
                t2          = temp;
                tempNormal *= -1;
            }
            temp = tmin;
            tmin = Math.Max(tmin, t1);
            if (temp != tmin)
            {
                normal = tempNormal;
            }
            tmax = Math.Min(tmax, t2);
            if (tmin > tmax)
            {
                return(false);
            }
            if (Math.Abs(localDirection.Y) < Toolbox.Epsilon && (localOrigin.Y < -halfHeight || localOrigin.Y > halfHeight))
            {
                return(false);
            }
            inverseDirection = 1 / localDirection.Y;
            t1         = (-halfHeight - localOrigin.Y) * inverseDirection;
            t2         = (halfHeight - localOrigin.Y) * inverseDirection;
            tempNormal = new Vector3(0, -1, 0);
            if (t1 > t2)
            {
                temp        = t1;
                t1          = t2;
                t2          = temp;
                tempNormal *= -1;
            }
            temp = tmin;
            tmin = Math.Max(tmin, t1);
            if (temp != tmin)
            {
                normal = tempNormal;
            }
            tmax = Math.Min(tmax, t2);
            if (tmin > tmax)
            {
                return(false);
            }
            if (Math.Abs(localDirection.Z) < Toolbox.Epsilon && (localOrigin.Z < -halfLength || localOrigin.Z > halfLength))
            {
                return(false);
            }
            inverseDirection = 1 / localDirection.Z;
            t1         = (-halfLength - localOrigin.Z) * inverseDirection;
            t2         = (halfLength - localOrigin.Z) * inverseDirection;
            tempNormal = new Vector3(0, 0, -1);
            if (t1 > t2)
            {
                temp        = t1;
                t1          = t2;
                t2          = temp;
                tempNormal *= -1;
            }
            temp = tmin;
            tmin = Math.Max(tmin, t1);
            if (temp != tmin)
            {
                normal = tempNormal;
            }
            tmax = Math.Min(tmax, t2);
            if (tmin > tmax)
            {
                return(false);
            }
            hit.T = tmin;
            Vector3.Multiply(ref ray.Direction, tmin, out hit.Location);
            Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location);
            Vector3.Transform(ref normal, ref transform.Orientation, out normal);
            hit.Normal = normal;
            return(true);
        }