Exemple #1
0
 private void GetAgentMatches(RayData ray, RayTestHitFlags flags, List <RayResult> results)
 {
     foreach (IAgent agent in m_Scene.RootAgents)
     {
         BoundingBox bbox;
         agent.GetBoundingBox(out bbox);
         bbox.CenterOffset = agent.GlobalPosition;
         bbox.Size        *= agent.GlobalRotation;
         bbox.Size         = bbox.Size.ComponentMax(-bbox.Size);
         double dist = IntersectBox(ray, ref bbox);
         if (dist < 0)
         {
             continue;
         }
         results.Add(new RayResult
         {
             IsTerrain     = false,
             ObjectId      = agent.ID,
             PartId        = agent.ID,
             HitPointWorld = ray.Origin + ray.Direction * dist
         });
     }
 }
Exemple #2
0
        public RayResult[] RayTest(Vector3 rayFromWorld, Vector3 rayToWorld, RayTestHitFlags flags, uint maxHits)
        {
            var     results = new List <RayResult>();
            RayData ray     = new RayData(rayFromWorld, rayToWorld);

            if ((flags & RayTestHitFlags.Avatar) != 0)
            {
                GetAgentMatches(ray, flags, results);
            }

            if ((flags & (RayTestHitFlags.NonPhantom | RayTestHitFlags.Phantom | RayTestHitFlags.NonPhantom | RayTestHitFlags.Phantom | RayTestHitFlags.Character)) != 0)
            {
                GetObjectMatches(ray, flags, results);
            }

            results.Sort((r1, r2) => (r1.HitPointWorld - rayFromWorld).LengthSquared.CompareTo((r2.HitPointWorld - rayFromWorld).LengthSquared));

            if (results.Count > maxHits)
            {
                results.RemoveRange((int)maxHits, results.Count - (int)maxHits);
            }

            return(results.ToArray());
        }
Exemple #3
0
        private void GetObjectMatches(RayData ray, RayTestHitFlags flags, List <RayResult> results)
        {
            foreach (ObjectGroup grp in m_Scene.ObjectGroups)
            {
                if (grp.IsAttached)
                {
                    /* ignore attachments */
                    continue;
                }

                /* flag checks are cheap so do those first */
                if (((flags & RayTestHitFlags.NonPhantom) != 0 && !grp.IsPhantom) ||
                    ((flags & RayTestHitFlags.Phantom) != 0 && grp.IsPhantom) ||
                    ((flags & RayTestHitFlags.NonPhysical) != 0 && !grp.IsPhysics) ||
                    ((flags & RayTestHitFlags.Physical) != 0 && grp.IsPhysics))
                {
                    /* found a flag match */
                }
                else
                {
                    continue;
                }

                BoundingBox bbox;
                grp.GetBoundingBox(out bbox);
                bbox.CenterOffset = grp.GlobalPosition;
                bbox.Size        *= grp.GlobalRotation;
                bbox.Size         = bbox.Size.ComponentMax(-bbox.Size);
                double distance = IntersectBox(ray, ref bbox);
                if (distance < 0)
                {
                    /* only process if linkset bounding box is hit */
                    continue;
                }

                foreach (ObjectPart part in grp.ValuesByKey1)
                {
                    part.GetBoundingBox(out bbox);
                    distance = IntersectBox(ray, ref bbox);
                    if (distance < 0)
                    {
                        /* skip if not hit */
                        continue;
                    }

                    var res = new RayResult
                    {
                        ObjectId = grp.ID,
                        PartId   = part.ID
                    };

                    /* calculate actual HitPoint and HitNormal */
                    ObjectPart.PrimitiveShape shape = part.Shape;

                    MeshLOD lod = null;
                    if (shape.Type == PrimitiveShapeType.Sculpt && shape.SculptType == PrimitiveSculptType.Mesh)
                    {
                        var m = new LLMesh(m_Scene.AssetService[shape.SculptMap]);
                        foreach (LLMesh.LodLevel level in LodOrder)
                        {
                            if (m.HasLOD(level))
                            {
                                lod = m.GetLOD(level);
                                break;
                            }
                        }
                    }
                    else
                    {
                        lod = shape.ToMesh(m_Scene.AssetService);
                    }

                    if (lod != null)
                    {
                        lod.Optimize();
                        Vector3 normal;
                        foreach (Triangle tri in lod.Triangles)
                        {
                            double dist = IntersectTri(ray,
                                                       lod.Vertices[tri.Vertex1],
                                                       lod.Vertices[tri.Vertex2],
                                                       lod.Vertices[tri.Vertex3],
                                                       out normal);

                            if (dist >= 0)
                            {
                                res.HitNormalWorld = normal;
                                res.HitPointWorld  = ray.Origin + ray.Direction * dist;
                                results.Add(res);
                                break;
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        private void GetTerrainMatches(RayData ray, RayTestHitFlags flags, List <RayResult> results)
        {
            var pos           = new List <ulong>();
            var regionExtents = new Vector3(m_Scene.SizeX, m_Scene.SizeY, 0);

            double d;

            for (d = 0; d < ray.RayLength; d += 0.5)
            {
                BoundingBox bbox = new BoundingBox();
                bbox.CenterOffset   = ray.Origin + (ray.Direction * d);
                bbox.CenterOffset.X = Math.Floor(bbox.CenterOffset.X) + 0.5;
                bbox.CenterOffset.Y = Math.Floor(bbox.CenterOffset.Y) + 0.5;
                ulong tPos = (((ulong)bbox.CenterOffset.Y) << 32) + (ulong)bbox.CenterOffset.X;

                if (pos.Contains(tPos))
                {
                    /* skip if already tested */
                    continue;
                }
                pos.Add(tPos);

                if (bbox.CenterOffset.X < 0 || bbox.CenterOffset.X > regionExtents.X + 1 ||
                    bbox.CenterOffset.Y < 0 || bbox.CenterOffset.Y > regionExtents.Y + 1)
                {
                    /* skip */
                    continue;
                }

                var t0 = new Vector3(bbox.CenterOffset.X - 0.5, bbox.CenterOffset.Y - 0.5, 0);
                var t1 = new Vector3(bbox.CenterOffset.X + 0.5, bbox.CenterOffset.Y - 0.5, 0);
                var t2 = new Vector3(bbox.CenterOffset.X - 0.5, bbox.CenterOffset.Y + 0.5, 0);
                var t3 = new Vector3(bbox.CenterOffset.X + 0.5, bbox.CenterOffset.Y + 0.5, 0);
                t0.Z = m_Scene.Terrain[t0];
                t1.Z = m_Scene.Terrain[t1];
                t2.Z = m_Scene.Terrain[t2];
                t3.Z = m_Scene.Terrain[t3];

                Vector3 tmin = t0.ComponentMin(t1).ComponentMin(t2).ComponentMin(t3);
                Vector3 tmax = t0.ComponentMax(t1).ComponentMax(t2).ComponentMax(t3);
                bbox.CenterOffset.Z = (tmin.Z + tmax.Z) / 2;
                bbox.Size           = tmax - tmin;

                double dist = IntersectBox(ray, ref bbox);
                if (dist < 0)
                {
                    /* not hitting terrain at all */
                    continue;
                }

                Vector3 normal;
                dist = IntersectTri(ray, t0, t1, t2, out normal);
                if (dist < 0)
                {
                    dist = IntersectTri(ray, t0, t3, t2, out normal);
                }

                if (dist < 0)
                {
                    continue;
                }

                results.Add(new RayResult
                {
                    HitNormalWorld = normal,
                    HitPointWorld  = ray.Origin + ray.Direction * dist,
                    IsTerrain      = true,
                    ObjectId       = UUID.Zero,
                    PartId         = UUID.Zero
                });
            }
        }
Exemple #5
0
 public RayResult[] RayTest(Vector3 rayFromWorld, Vector3 rayToWorld, RayTestHitFlags flags) =>
 RayTest(rayFromWorld, rayToWorld, flags, uint.MaxValue);