예제 #1
0
        private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
        {
            Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
            List<ContactResult> contacts = new List<ContactResult>();

            Vector3 ab = rayEnd - rayStart;

            World.ForEachSOG(delegate(SceneObjectGroup group)
            {
                if (m_host.ParentGroup == group)
                    return;

                if (group.IsAttachment)
                    return;

                if (group.RootPart.PhysActor == null)
                {
                    if (!includePhantom)
                        return;
                }
                else
                {
                    if (group.RootPart.PhysActor.IsPhysical)
                    {
                        if (!includePhysical)
                            return;
                    }
                    else
                    {
                        if (!includeNonPhysical)
                            return;
                    }
                }

                // Find the radius ouside of which we don't even need to hit test
                float minX;
                float maxX;
                float minY;
                float maxY;
                float minZ;
                float maxZ;

                float radius = 0.0f;

                group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);

                if (Math.Abs(minX) > radius)
                    radius = Math.Abs(minX);
                if (Math.Abs(minY) > radius)
                    radius = Math.Abs(minY);
                if (Math.Abs(minZ) > radius)
                    radius = Math.Abs(minZ);
                if (Math.Abs(maxX) > radius)
                    radius = Math.Abs(maxX);
                if (Math.Abs(maxY) > radius)
                    radius = Math.Abs(maxY);
                if (Math.Abs(maxZ) > radius)
                    radius = Math.Abs(maxZ);
                radius = radius*1.413f;
                Vector3 ac = group.AbsolutePosition - rayStart;
//                Vector3 bc = group.AbsolutePosition - rayEnd;

                double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));

                // Too far off ray, don't bother
                if (d > radius)
                    return;

                // Behind ray, drop
                double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
                if (d2 > 0)
                    return;

                ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
                EntityIntersection intersection = group.TestIntersection(ray, true, false);
                // Miss.
                if (!intersection.HitTF)
                    return;

                Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
                Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
                //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
                if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
                    intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
                    intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
                    return;

                ContactResult result = new ContactResult ();
                result.ConsumerID = group.LocalId;
                result.Depth = intersection.distance;
                result.Normal = intersection.normal;
                result.Pos = intersection.ipoint;

                contacts.Add(result);
            });

            return contacts.ToArray();
        }
예제 #2
0
        /// <summary>
        /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
        /// </summary>
        /// <param name="RayStart"></param>
        /// <param name="RayEnd"></param>
        /// <param name="RayTargetID"></param>
        /// <param name="rot"></param>
        /// <param name="bypassRayCast"></param>
        /// <param name="RayEndIsIntersection"></param>
        /// <param name="frontFacesOnly"></param>
        /// <param name="scale"></param>
        /// <param name="FaceCenter"></param>
        /// <returns></returns>
        public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
        {

            Vector3 dir = RayEnd - RayStart;

            float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
            Vector3 wpos = Vector3.Zero;
            // Check for water surface intersection from above
            if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
            {
                float ratio = (wheight - RayStart.Z) / dir.Z;
                wpos.X = RayStart.X + (ratio * dir.X);
                wpos.Y = RayStart.Y + (ratio * dir.Y);
                wpos.Z = wheight;
            }

            Vector3 pos = Vector3.Zero;

            if (RayEndIsIntersection != (byte)1)
            {
                float dist = dir.Length();
                if (dist != 0)
                {
                    Vector3 direction = dir * (1 / dist);

                    dist += 1.0f;

                    if (SupportsRayCastFiltered())
                    {
                        RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
                        rayfilter |= RayFilterFlags.land;
                        rayfilter |= RayFilterFlags.physical;
                        rayfilter |= RayFilterFlags.nonphysical;
                        rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors

                        // get some more contacts ???
                        int physcount = 4;

                        List<ContactResult> physresults =
                            (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
                        if (physresults != null && physresults.Count > 0)
                        {
                            // look for terrain ?
                            if(RayTargetID == UUID.Zero)
                            {
                                foreach (ContactResult r in physresults)
                                {
                                    if (r.ConsumerID == 0)
                                    {
                                        pos = r.Normal * scale;
                                        pos *= 0.5f;
                                        pos = r.Pos + pos;

                                        if (wpos.Z > pos.Z) pos = wpos;
                                        return pos;
                                    }
                                }
                            }
                            else
                            {
                                foreach (ContactResult r in physresults)
                                {
                                    SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
                                    if (part == null)
                                        continue;
                                    if (part.UUID == RayTargetID)
                                    {
                                        pos = r.Normal * scale;
                                        pos *= 0.5f;
                                        pos = r.Pos + pos;

                                        if (wpos.Z > pos.Z) pos = wpos;
                                        return pos;
                                    }
                                }                          
                            }
                            // else the first we got
                            pos = physresults[0].Normal * scale;
                            pos *= 0.5f;
                            pos = physresults[0].Pos + pos;

                            if (wpos.Z > pos.Z)
                                pos = wpos;
                            return pos;
                        }

                    }
                    if (RayTargetID != UUID.Zero)
                    {
                        SceneObjectPart target = GetSceneObjectPart(RayTargetID);

                        Ray NewRay = new Ray(RayStart, direction);

                        if (target != null)
                        {
                            pos = target.AbsolutePosition;

                            // Ray Trace against target here
                            EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);

                            // Un-comment out the following line to Get Raytrace results printed to the console.
                            // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
                            float ScaleOffset = 0.5f;

                            // If we hit something
                            if (ei.HitTF)
                            {
                                Vector3 scaleComponent = ei.AAfaceNormal;
                                if (scaleComponent.X != 0) ScaleOffset = scale.X;
                                if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
                                if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
                                ScaleOffset = Math.Abs(ScaleOffset);
                                Vector3 intersectionpoint = ei.ipoint;
                                Vector3 normal = ei.normal;
                                // Set the position to the intersection point
                                Vector3 offset = (normal * (ScaleOffset / 2f));
                                pos = (intersectionpoint + offset);

                                //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
                                //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
                                // Un-offset the prim (it gets offset later by the consumer method)
                                //pos.Z -= 0.25F;

                                if (wpos.Z > pos.Z) pos = wpos;
                                return pos;
                            }
                        }
                        else
                        {
                            // We don't have a target here, so we're going to raytrace all the objects in the scene.
                            EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);

                            // Un-comment the following line to print the raytrace results to the console.
                            //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());

                            if (ei.HitTF)
                            {
                                pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                            }
                            else
                            {
                                // fall back to our stupid functionality
                                pos = RayEnd;
                            }

                            if (wpos.Z > pos.Z) pos = wpos;
                            return pos;
                        }
                    }
                }
            }

            // fall back to our stupid functionality
            pos = RayEnd;

            //increase height so its above the ground.
            //should be getting the normal of the ground at the rez point and using that?
            pos.Z += scale.Z / 2f;
            //                return pos;
            // check against posible water intercept
            if (wpos.Z > pos.Z) pos = wpos;
            return pos;
        }
예제 #3
0
 public void getLineOfSight()
 {
     string pathID = getPathID();
     PathFromTxToRy path = new PathFromTxToRy(this, transmitter.RootPart.AbsolutePosition, pathID);
     //Direction from transmitter to the reciever 
     Vector3 direction = receiver.RootPart.AbsolutePosition - transmitter.RootPart.AbsolutePosition;
     //Ray vector from transmitter to the receiver
     Ray ray = new Ray(transmitter.RootPart.AbsolutePosition, direction);
     //Get the first object the ray hit
     EntityIntersectionWithPart intersection = findNextHit(ray, transmitter.RootPart);
     path.addNextPoint(receiver.RootPart.AbsolutePosition, receiver.RootPart.Material);
     path.reachesReceiver = true;
     if (!checkPathIsDrawn(path))
     {
         pathHits[0].Add(pathID, path);
     }
 }
        public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
        {
            // We got a request from the inner_scene to raytrace along the Ray hRay
            // We're going to check all of the prim in this group for intersection with the ray
            // If we get a result, we're going to find the closest result to the origin of the ray
            // and send back the intersection information back to the innerscene.

            EntityIntersection result = new EntityIntersection();

            SceneObjectPart[] parts = m_parts.GetArray();

            // Find closest hit here
            float idist = float.MaxValue;

            for (int i = 0; i < parts.Length; i++)
            {
                SceneObjectPart part = parts[i];

                // Temporary commented to stop compiler warning
                //Vector3 partPosition =
                //    new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
                Quaternion parentrotation = GroupRotation;

                // Telling the prim to raytrace.
                //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);

                EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);

                if (inter.HitTF)
                {
                    // We need to find the closest prim to return to the testcaller along the ray
                    if (inter.distance < idist)
                    {
                        result.HitTF = true;
                        result.ipoint = inter.ipoint;
                        result.obj = part;
                        result.normal = inter.normal;
                        result.distance = inter.distance;

                        idist = inter.distance;
                    }
                }
            }
            return result;
        }
예제 #5
0
파일: Scene.cs 프로젝트: CCIR/opensim
        /// <summary>
        /// Duplicates object specified by localID at position raycasted against RayTargetObject using 
        /// RayEnd and RayStart to determine what the angle of the ray is
        /// </summary>
        /// <param name="localID">ID of object to duplicate</param>
        /// <param name="dupeFlags"></param>
        /// <param name="AgentID">Agent doing the duplication</param>
        /// <param name="GroupID">Group of new object</param>
        /// <param name="RayTargetObj">The target of the Ray</param>
        /// <param name="RayEnd">The ending of the ray (farthest away point)</param>
        /// <param name="RayStart">The Beginning of the ray (closest point)</param>
        /// <param name="BypassRaycast">Bool to bypass raycasting</param>
        /// <param name="RayEndIsIntersection">The End specified is the place to add the object</param>
        /// <param name="CopyCenters">Position the object at the center of the face that it's colliding with</param>
        /// <param name="CopyRotates">Rotate the object the same as the localID object</param>
        public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
                                           UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
                                           bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates)
        {
            Vector3 pos;
            const bool frontFacesOnly = true;
            //m_log.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
            SceneObjectPart target = GetSceneObjectPart(localID);
            SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj);

            if (target != null && target2 != null)
            {
                Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
                Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
                Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);

                pos = target2.AbsolutePosition;
                //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());

                // TODO: Raytrace better here

                //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
                Ray NewRay = new Ray(AXOrigin, AXdirection);

                // Ray Trace against target here
                EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);

                // Un-comment out the following line to Get Raytrace results printed to the console.
                //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
                float ScaleOffset = 0.5f;

                // If we hit something
                if (ei.HitTF)
                {
                    Vector3 scale = target.Scale;
                    Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
                    if (scaleComponent.X != 0) ScaleOffset = scale.X;
                    if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
                    if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
                    ScaleOffset = Math.Abs(ScaleOffset);
                    Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                    Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
                    Vector3 offset = normal * (ScaleOffset / 2f);
                    pos = intersectionpoint + offset;

                    // stick in offset format from the original prim
                    pos = pos - target.ParentGroup.AbsolutePosition;
                    SceneObjectGroup copy;
                    if (CopyRotates)
                    {
                        Quaternion worldRot = target2.GetWorldRotation();

                        // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
                        copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
                        //obj.Rotation = worldRot;
                        //obj.UpdateGroupRotationR(worldRot);
                    }
                    else
                    {
                        copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity);
                    }
                    if (copy != null)
                        EventManager.TriggerObjectAddedToScene(copy);
                }
            }
        }
예제 #6
0
        public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
        {
            // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes
            // This breaks down into the ray---> plane equation.
            // TODO: Change to take shape into account
            Vector3[] vertexes = new Vector3[8];

            // float[] distance = new float[6];
            Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
            Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
            Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
            Vector3[] FaceD = new Vector3[6]; // vertex D for Facei

            Vector3[] normals = new Vector3[6]; // Normal for Facei
            Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals

            AAfacenormals[0] = new Vector3(1, 0, 0);
            AAfacenormals[1] = new Vector3(0, 1, 0);
            AAfacenormals[2] = new Vector3(-1, 0, 0);
            AAfacenormals[3] = new Vector3(0, -1, 0);
            AAfacenormals[4] = new Vector3(0, 0, 1);
            AAfacenormals[5] = new Vector3(0, 0, -1);

            Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B
            Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C
            Vector3 cross = new Vector3();

            Vector3 pos = GetWorldPosition();
            Quaternion rot = GetWorldRotation();

            // Variables prefixed with AX are Axiom.Math copies of the LL variety.

            Quaternion AXrot = rot;
            AXrot.Normalize();

            Vector3 AXpos = pos;

            // tScale is the offset to derive the vertex based on the scale.
            // it's different for each vertex because we've got to rotate it
            // to get the world position of the vertex to produce the Oriented Bounding Box

            Vector3 tScale = Vector3.Zero;

            Vector3 AXscale = new Vector3(m_shape.Scale.X * 0.5f, m_shape.Scale.Y * 0.5f, m_shape.Scale.Z * 0.5f);

            //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale));
            //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1));

            // rScale is the rotated offset to find a vertex based on the scale and the world rotation.
            Vector3 rScale = new Vector3();

            // Get Vertexes for Faces Stick them into ABCD for each Face
            // Form: Face<vertex>[face] that corresponds to the below diagram
            #region ABCD Face Vertex Map Comment Diagram
            //                   A _________ B
            //                    |         |
            //                    |  4 top  |
            //                    |_________|
            //                   C           D

            //                   A _________ B
            //                    |  Back   |
            //                    |    3    |
            //                    |_________|
            //                   C           D

            //   A _________ B                     B _________ A
            //    |  Left   |                       |  Right  |
            //    |    0    |                       |    2    |
            //    |_________|                       |_________|
            //   C           D                     D           C

            //                   A _________ B
            //                    |  Front  |
            //                    |    1    |
            //                    |_________|
            //                   C           D

            //                   C _________ D
            //                    |         |
            //                    |  5 bot  |
            //                    |_________|
            //                   A           B
            #endregion

            #region Plane Decomposition of Oriented Bounding Box
            tScale = new Vector3(AXscale.X, -AXscale.Y, AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[0] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
               // vertexes[0].X = pos.X + vertexes[0].X;
            //vertexes[0].Y = pos.Y + vertexes[0].Y;
            //vertexes[0].Z = pos.Z + vertexes[0].Z;

            FaceA[0] = vertexes[0];
            FaceB[3] = vertexes[0];
            FaceA[4] = vertexes[0];

            tScale = AXscale;
            rScale = tScale * AXrot;
            vertexes[1] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

               // vertexes[1].X = pos.X + vertexes[1].X;
               // vertexes[1].Y = pos.Y + vertexes[1].Y;
            //vertexes[1].Z = pos.Z + vertexes[1].Z;

            FaceB[0] = vertexes[1];
            FaceA[1] = vertexes[1];
            FaceC[4] = vertexes[1];

            tScale = new Vector3(AXscale.X, -AXscale.Y, -AXscale.Z);
            rScale = tScale * AXrot;

            vertexes[2] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

            //vertexes[2].X = pos.X + vertexes[2].X;
            //vertexes[2].Y = pos.Y + vertexes[2].Y;
            //vertexes[2].Z = pos.Z + vertexes[2].Z;

            FaceC[0] = vertexes[2];
            FaceD[3] = vertexes[2];
            FaceC[5] = vertexes[2];

            tScale = new Vector3(AXscale.X, AXscale.Y, -AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[3] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

            //vertexes[3].X = pos.X + vertexes[3].X;
               // vertexes[3].Y = pos.Y + vertexes[3].Y;
               // vertexes[3].Z = pos.Z + vertexes[3].Z;

            FaceD[0] = vertexes[3];
            FaceC[1] = vertexes[3];
            FaceA[5] = vertexes[3];

            tScale = new Vector3(-AXscale.X, AXscale.Y, AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[4] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

               // vertexes[4].X = pos.X + vertexes[4].X;
               // vertexes[4].Y = pos.Y + vertexes[4].Y;
               // vertexes[4].Z = pos.Z + vertexes[4].Z;

            FaceB[1] = vertexes[4];
            FaceA[2] = vertexes[4];
            FaceD[4] = vertexes[4];

            tScale = new Vector3(-AXscale.X, AXscale.Y, -AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[5] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

               // vertexes[5].X = pos.X + vertexes[5].X;
               // vertexes[5].Y = pos.Y + vertexes[5].Y;
               // vertexes[5].Z = pos.Z + vertexes[5].Z;

            FaceD[1] = vertexes[5];
            FaceC[2] = vertexes[5];
            FaceB[5] = vertexes[5];

            tScale = new Vector3(-AXscale.X, -AXscale.Y, AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[6] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

               // vertexes[6].X = pos.X + vertexes[6].X;
               // vertexes[6].Y = pos.Y + vertexes[6].Y;
               // vertexes[6].Z = pos.Z + vertexes[6].Z;

            FaceB[2] = vertexes[6];
            FaceA[3] = vertexes[6];
            FaceB[4] = vertexes[6];

            tScale = new Vector3(-AXscale.X, -AXscale.Y, -AXscale.Z);
            rScale = tScale * AXrot;
            vertexes[7] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));

               // vertexes[7].X = pos.X + vertexes[7].X;
               // vertexes[7].Y = pos.Y + vertexes[7].Y;
               // vertexes[7].Z = pos.Z + vertexes[7].Z;

            FaceD[2] = vertexes[7];
            FaceC[3] = vertexes[7];
            FaceD[5] = vertexes[7];
            #endregion

            // Get our plane normals
            for (int i = 0; i < 6; i++)
            {
                //m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]);

                // Our Plane direction
                AmBa = FaceA[i] - FaceB[i];
                AmBb = FaceB[i] - FaceC[i];

                cross = Vector3.Cross(AmBb, AmBa);

                // normalize the cross product to get the normal.
                normals[i] = cross / cross.Length();

                //m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString());
                //distance[i] = (normals[i].X * AmBa.X + normals[i].Y * AmBa.Y + normals[i].Z * AmBa.Z) * -1;
            }

            EntityIntersection result = new EntityIntersection();

            result.distance = 1024;
            float c = 0;
            float a = 0;
            float d = 0;
            Vector3 q = new Vector3();

            #region OBB Version 2 Experiment
            //float fmin = 999999;
            //float fmax = -999999;
            //float s = 0;

            //for (int i=0;i<6;i++)
            //{
                //s = iray.Direction.Dot(normals[i]);
                //d = normals[i].Dot(FaceB[i]);

                //if (s == 0)
                //{
                    //if (iray.Origin.Dot(normals[i]) > d)
                    //{
                        //return result;
                    //}
                   // else
                    //{
                        //continue;
                    //}
                //}
                //a = (d - iray.Origin.Dot(normals[i])) / s;
                //if (iray.Direction.Dot(normals[i]) < 0)
                //{
                    //if (a > fmax)
                    //{
                        //if (a > fmin)
                        //{
                            //return result;
                        //}
                        //fmax = a;
                    //}

                //}
                //else
                //{
                    //if (a < fmin)
                    //{
                        //if (a < 0 || a < fmax)
                        //{
                            //return result;
                        //}
                        //fmin = a;
                    //}
                //}
            //}
            //if (fmax > 0)
            //    a= fmax;
            //else
               //     a=fmin;

            //q = iray.Origin + a * iray.Direction;
            #endregion

            // Loop over faces (6 of them)
            for (int i = 0; i < 6; i++)
            {
                AmBa = FaceA[i] - FaceB[i];
                AmBb = FaceB[i] - FaceC[i];
                d = Vector3.Dot(normals[i], FaceB[i]);

                //if (faceCenters)
                //{
                //    c = normals[i].Dot(normals[i]);
                //}
                //else
                //{
                c = Vector3.Dot(iray.Direction, normals[i]);
                //}
                if (c == 0)
                    continue;

                a = (d - Vector3.Dot(iray.Origin, normals[i])) / c;

                if (a < 0)
                    continue;

                // If the normal is pointing outside the object
                if (Vector3.Dot(iray.Direction, normals[i]) < 0 || !frontFacesOnly)
                {
                    //if (faceCenters)
                    //{   //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f;
                    //    q =  iray.Origin + a * normals[i];
                    //}
                    //else
                    //{
                        q = iray.Origin + iray.Direction * a;
                    //}

                    float distance2 = (float)GetDistanceTo(q, AXpos);
                    // Is this the closest hit to the object's origin?
                    //if (faceCenters)
                    //{
                    //    distance2 = (float)GetDistanceTo(q, iray.Origin);
                    //}

                    if (distance2 < result.distance)
                    {
                        result.distance = distance2;
                        result.HitTF = true;
                        result.ipoint = q;
                        //m_log.Info("[FACE]:" + i.ToString());
                        //m_log.Info("[POINT]: " + q.ToString());
                        //m_log.Info("[DIST]: " + distance2.ToString());
                        if (faceCenters)
                        {
                            result.normal = AAfacenormals[i] * AXrot;

                            Vector3 scaleComponent = AAfacenormals[i];
                            float ScaleOffset = 0.5f;
                            if (scaleComponent.X != 0) ScaleOffset = AXscale.X;
                            if (scaleComponent.Y != 0) ScaleOffset = AXscale.Y;
                            if (scaleComponent.Z != 0) ScaleOffset = AXscale.Z;
                            ScaleOffset = Math.Abs(ScaleOffset);
                            Vector3 offset = result.normal * ScaleOffset;
                            result.ipoint = AXpos + offset;

                            ///pos = (intersectionpoint + offset);
                        }
                        else
                        {
                            result.normal = normals[i];
                        }
                        result.AAfaceNormal = AAfacenormals[i];
                    }
                }
            }
            return result;
        }
예제 #7
0
 protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
 {
     // Primitive Ray Tracing
     float closestDistance = 280f;
     EntityIntersection returnResult = new EntityIntersection();
     List<EntityBase> EntityList = GetEntities();
     foreach (EntityBase ent in EntityList)
     {
         if (ent is SceneObjectGroup)
         {
             SceneObjectGroup reportingG = (SceneObjectGroup)ent;
             EntityIntersection result = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
             if (result.HitTF)
             {
                 if (result.distance < closestDistance)
                 {
                     closestDistance = result.distance;
                     returnResult = result;
                 }
             }
         }
     }
     return returnResult;
 }
예제 #8
0
        /// <summary>
        ///     Duplicates object specified by localID at position raycasted against RayTargetObject using
        ///     RayEnd and RayStart to determine what the angle of the ray is
        /// </summary>
        /// <param name="localID">ID of object to duplicate</param>
        /// <param name="dupeFlags"></param>
        /// <param name="AgentID">Agent doing the duplication</param>
        /// <param name="GroupID">Group of new object</param>
        /// <param name="RayTargetObj">The target of the Ray</param>
        /// <param name="RayEnd">The ending of the ray (farthest away point)</param>
        /// <param name="RayStart">The Beginning of the ray (closest point)</param>
        /// <param name="BypassRaycast">Bool to bypass raycasting</param>
        /// <param name="RayEndIsIntersection">The End specified is the place to add the object</param>
        /// <param name="CopyCenters">Position the object at the center of the face that it's colliding with</param>
        /// <param name="CopyRotates">Rotate the object the same as the localID object</param>
        public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
                                           UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
                                           bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters,
                                           bool CopyRotates)
        {
            const bool frontFacesOnly = true;
            //MainConsole.Instance.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
            ISceneChildEntity target = m_parentScene.GetSceneObjectPart(localID);
            ISceneChildEntity target2 = m_parentScene.GetSceneObjectPart(RayTargetObj);
            IScenePresence Sp = GetScenePresence(AgentID);
            if (target != null && target2 != null)
            {
                Vector3 pos;
                if (EnableFakeRaycasting)
                {
                    RayStart = Sp.CameraPosition;
                    RayEnd = pos = target2.AbsolutePosition;
                }
                Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
                Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
                Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);

                if (target2.ParentEntity != null)
                {
                    pos = target2.AbsolutePosition;
                    // TODO: Raytrace better here

                    //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), false, false);
                    Ray NewRay = new Ray(AXOrigin, AXdirection);

                    // Ray Trace against target here
                    EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
                                                                        CopyCenters);

                    // Un-comment out the following line to Get Raytrace results printed to the console.
                    //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
                    float ScaleOffset = 0.5f;

                    // If we hit something
                    if (ei.HitTF)
                    {
                        Vector3 scale = target.Scale;
                        Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
                        if (scaleComponent.X != 0) ScaleOffset = scale.X;
                        if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
                        if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
                        ScaleOffset = Math.Abs(ScaleOffset);
                        Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                        Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
                        Vector3 offset = normal*(ScaleOffset/2f);
                        pos = intersectionpoint + offset;

                        // stick in offset format from the original prim
                        pos = pos - target.ParentEntity.AbsolutePosition;
                        if (CopyRotates)
                        {
                            Quaternion worldRot = target2.GetWorldRotation();

                            // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
                            DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
                            //obj.Rotation = worldRot;
                            //obj.UpdateGroupRotationR(worldRot);
                        }
                        else
                        {
                            DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID,
                                            Quaternion.Identity);
                        }
                    }

                    return;
                }

                return;
            }
        }
예제 #9
0
파일: Inventory.cs 프로젝트: thoys/simian
        void RezObjectHandler(Packet packet, LLAgent agent)
        {
            RezObjectPacket rez = (RezObjectPacket)packet;

            // Find the target position
            Vector3 position = Vector3.Zero;
            Vector3 linksetScale = Vector3.Zero;
            bool bypassRaycast = (rez.RezData.BypassRaycast == 1);
            //bool rayEndIsIntersection = rez.RezData.RayEndIsIntersection;

            #region Position Calculation

            if (bypassRaycast || m_physics == null)
            {
                position = rez.RezData.RayEnd;
            }
            else
            {
                Vector3 direction = (rez.RezData.RayEnd - rez.RezData.RayStart);
                direction /= direction.Length();
                Ray ray = new Ray(rez.RezData.RayStart, direction);

                ISceneEntity collisionObj;
                float collisionDist;
                if (m_physics.FullSceneCollisionTest(true, ray, null, out collisionObj, out collisionDist))
                {
                    position = ray.GetPoint(collisionDist);
                }
                else
                {
                    m_log.Warn("Full scene collision test for ray " + ray + " failed");
                    position = agent.ScenePosition + Vector3.UnitZ;
                }
            }

            position.Z += linksetScale.Z * 0.5f;

            #endregion Position Calculation

            InventoryBase invObject;
            if (m_inventoryClient.TryGetInventory(agent.ID, rez.InventoryData.ItemID, out invObject) & invObject is InventoryItem)
            {
                InventoryItem item = (InventoryItem)invObject;

                Asset asset;
                if (m_assetClient.TryGetAsset(item.AssetID, item.ContentType, out asset))
                {
                    #region Object Deserialization/Rezzing

                    // Deserialize the asset data into a linkset
                    using (MemoryStream stream = new MemoryStream(asset.Data))
                    {
                        OSDMap linksetMap = OSDParser.DeserializeJson(stream) as OSDMap;
                        if (linksetMap != null)
                        {
                            IList<LLPrimitive> linkset = LLPrimitive.DeserializeLinkset(linksetMap, m_scene, m_primMesher, true);

                            // Rez the parent(s) first
                            for (int i = 0; i < linkset.Count; i++)
                            {
                                LLPrimitive prim = linkset[i];

                                // Make sure the ownerID is set correctly
                                prim.OwnerID = agent.ID;

                                if (prim.Parent == null)
                                {
                                    RezSinglePrim(prim, rez.RezData, position);
                                    m_log.Debug("Deserialized root prim " + prim.ID + " (" + prim.LocalID + ") from inventory");
                                }
                            }

                            // Rez the children
                            for (int i = 0; i < linkset.Count; i++)
                            {
                                if (linkset[i].Parent != null)
                                    RezSinglePrim(linkset[i], rez.RezData, position);
                            }

                            // FIXME: Use these to determine if we need to delete the source inventory or task item
                            //rez.RezData.FromTaskID
                            //rez.RezData.RemoveItem
                        }
                        else
                        {
                            m_log.WarnFormat("Failed to deserialize asset {0} ({1} bytes, Content-Type: {2}) into a linkset",
                                asset.ID, asset.Data.Length, asset.ContentType);
                        }
                    }

                    #endregion Object Deserialization/Rezzing
                }
                else
                {
                    m_log.Warn(agent.Name + "'s RezObject failed to retrieve asset " + item.AssetID);
                }
            }
            else
            {
                m_log.Warn(agent.Name + " called RezObject for unknown item " + rez.InventoryData.ItemID);
            }
        }
예제 #10
0
        void ObjectAddHandler(Packet packet, LLAgent agent)
        {
            if (!agent.IsVerified)
            {
                m_scene.PresenceAlert(this, agent, "You are logged in with an unverified account. Object creation is disabled.");
                return;
            }

            ObjectAddPacket add = (ObjectAddPacket)packet;

            Vector3 position = Vector3.Zero;
            Vector3 scale = add.ObjectData.Scale;
            PCode pcode = (PCode)add.ObjectData.PCode;
            PrimFlags flags = (PrimFlags)add.ObjectData.AddFlags;
            bool bypassRaycast = (add.ObjectData.BypassRaycast == 1);
            //bool rayEndIsIntersection = (add.ObjectData.RayEndIsIntersection == 1);

            #region Position Calculation

            if (bypassRaycast)
            {
                position = add.ObjectData.RayEnd;
            }
            else if (m_physics != null)
            {
                Vector3 direction = (add.ObjectData.RayEnd - add.ObjectData.RayStart);
                direction /= direction.Length();
                Ray ray = new Ray(add.ObjectData.RayStart, direction);

                ISceneEntity collisionObj;
                float collisionDist;
                if (m_physics.FullSceneCollisionTest(true, ray, null, out collisionObj, out collisionDist))
                {
                    position = ray.GetPoint(collisionDist);
                }
                else
                {
                    m_log.Warn("Full scene collision test for ray " + ray + " failed");
                    position = agent.ScenePosition + Vector3.UnitZ;
                }
            }

            position.Z += scale.Z * 0.5f;

            #endregion Position Calculation

            if (!CanAddPrims(agent, position, 1))
                return;

            #region Foliage Handling

            // Set all foliage to phantom
            if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
            {
                flags |= PrimFlags.Phantom;

                if (pcode != PCode.Grass)
                {
                    // Resize based on the foliage type
                    Tree tree = (Tree)add.ObjectData.State;

                    switch (tree)
                    {
                        case Tree.Cypress1:
                        case Tree.Cypress2:
                            scale = new Vector3(4f, 4f, 10f);
                            break;
                        default:
                            scale = new Vector3(4f, 4f, 4f);
                            break;
                    }
                }
            }

            #endregion Foliage Handling

            #region Prim Creation

            // Create an object
            Primitive prim = new Primitive();

            prim.Flags = PrimFlags.CastShadows | PrimFlags.InventoryEmpty;
            prim.Flags |= (PrimFlags)add.ObjectData.AddFlags;

            // TODO: Security check
            prim.GroupID = add.AgentData.GroupID;
            prim.ID = UUID.Random();
            prim.MediaURL = String.Empty;
            prim.OwnerID = agent.ID;
            prim.Position = position;

            prim.PrimData.Material = (Material)add.ObjectData.Material;
            prim.PrimData.PathCurve = (PathCurve)add.ObjectData.PathCurve;
            prim.PrimData.ProfileCurve = (ProfileCurve)add.ObjectData.ProfileCurve;
            prim.PrimData.PathBegin = Primitive.UnpackBeginCut(add.ObjectData.PathBegin);
            prim.PrimData.PathEnd = Primitive.UnpackEndCut(add.ObjectData.PathEnd);
            prim.PrimData.PathScaleX = Primitive.UnpackPathScale(add.ObjectData.PathScaleX);
            prim.PrimData.PathScaleY = Primitive.UnpackPathScale(add.ObjectData.PathScaleY);
            prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearX);
            prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)add.ObjectData.PathShearY);
            prim.PrimData.PathTwist = Primitive.UnpackPathTwist(add.ObjectData.PathTwist);
            prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist(add.ObjectData.PathTwistBegin);
            prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist(add.ObjectData.PathRadiusOffset);
            prim.PrimData.PathTaperX = Primitive.UnpackPathTaper(add.ObjectData.PathTaperX);
            prim.PrimData.PathTaperY = Primitive.UnpackPathTaper(add.ObjectData.PathTaperY);
            prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(add.ObjectData.PathRevolutions);
            prim.PrimData.PathSkew = Primitive.UnpackPathTwist(add.ObjectData.PathSkew);
            prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(add.ObjectData.ProfileBegin);
            prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(add.ObjectData.ProfileEnd);
            prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(add.ObjectData.ProfileHollow);
            prim.PrimData.PCode = pcode;

            prim.Properties = new Primitive.ObjectProperties();
            prim.Properties.CreationDate = DateTime.UtcNow;
            prim.Properties.CreatorID = agent.ID;
            prim.Properties.Description = String.Empty;
            prim.Properties.GroupID = add.AgentData.GroupID;
            prim.Properties.LastOwnerID = agent.ID;
            prim.Properties.Name = "Object";
            prim.Properties.ObjectID = prim.ID;
            prim.Properties.OwnerID = prim.OwnerID;
            prim.Properties.Permissions = m_permissions.GetDefaultPermissions();
            prim.Properties.SalePrice = 10;

            prim.Rotation = add.ObjectData.Rotation;
            prim.Scale = scale;
            prim.TextColor = Color4.Black;

            if (pcode == PCode.Prim)
            {
                prim.Textures = new Primitive.TextureEntry(PLYWOOD_TEXTURE);
            }

            #endregion Prim Creation

            // Add this prim to the scene
            ISceneEntity primObj = new LLPrimitive(prim, m_scene, m_primMesher);
            m_scene.EntityAddOrUpdate(this, primObj, UpdateFlags.FullUpdate, 0);
        }
        /// <summary>
        ///     Gets a new rez location based on the raycast and the size of the object that is being rezzed.
        /// </summary>
        /// <param name="RayStart"></param>
        /// <param name="RayEnd"></param>
        /// <param name="RayTargetID"></param>
        /// <param name="rot"></param>
        /// <param name="bypassRayCast"></param>
        /// <param name="RayEndIsIntersection"></param>
        /// <param name="frontFacesOnly"></param>
        /// <param name="scale"></param>
        /// <param name="FaceCenter"></param>
        /// <returns></returns>
        public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot,
            byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly,
            Vector3 scale, bool FaceCenter)
        {
            Vector3 pos = Vector3.Zero;
            if (RayEndIsIntersection == 1)
            {
                pos = RayEnd;
                return pos;
            }

            if (RayTargetID != UUID.Zero)
            {
                ISceneChildEntity target = m_parentScene.GetSceneObjectPart(RayTargetID);

                Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
                Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
                Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);

                if (target != null)
                {
                    pos = target.AbsolutePosition;
                    //MainConsole.Instance.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());

                    // TODO: Raytrace better here

                    Ray NewRay = new Ray(AXOrigin, AXdirection);

                    // Ray Trace against target here
                    EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
                                                                       FaceCenter);

                    // Un-comment out the following line to Get Raytrace results printed to the console.
                    //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
                    float ScaleOffset = 0.5f;

                    // If we hit something
                    if (ei.HitTF)
                    {
                        Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
                        if (scaleComponent.X != 0) ScaleOffset = scale.X;
                        if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
                        if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
                        ScaleOffset = Math.Abs(ScaleOffset);
                        Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                        Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
                        // Set the position to the intersection point
                        Vector3 offset = (normal*(ScaleOffset/2f));
                        pos = (intersectionpoint + offset);
                    }

                    return pos;
                }
                else
                {
                    // We don't have a target here, so we're going to raytrace all the objects in the scene.

                    EntityIntersection ei = GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);

                    // Un-comment the following line to print the raytrace results to the console.
                    //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());

                    pos = ei.HitTF ? new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z) : RayEnd;

                    return pos;
                }
            }
            // fall back to our stupid functionality
            pos = RayEnd;

            //increase height so its above the ground.
            //should be getting the normal of the ground at the rez point and using that?
            pos.Z += scale.Z/2f;
            return pos;
        }
예제 #12
0
        /// <summary>
        /// A method which find the first object the ray hit. This is done by comparing distances. 
        /// The smallest distance is the distance between the intersection point and the ray start point. 
        /// </summary>
        /// <param name="ray">The ray which will be used to test the intersection against each part in the scene</param>
        /// <param name="source">An object which the ray start from. We need this to make sure that the shortest
        /// distance isn't zero (from itself to itself)</param>
        /// <returns>Intersection point with True if this ray intersect something, or false if nothing at all</returns>
        public EntityIntersectionWithPart findNextHit(Ray ray, SceneObjectPart source)
        {
            float smallestDistance = 1000000f;
            EntityIntersection closestIntersection = new EntityIntersection();
            SceneObjectPart closestPart = new SceneObjectPart();
            foreach (SceneObjectPart part in worldObjects)
            {
                if (!part.Equals(source)) //Cannot intersect itself (i.e. ignore/do nothing when it is itself)
                {
                    //Test if the ray intersect this part. 
                    EntityIntersection intersection;
                    if (part.GetPrimType() == OpenSim.Region.Framework.Scenes.PrimType.SPHERE)
                    {
                        intersection = part.TestIntersection(ray, part.ParentGroup.GroupRotation);
                    }
                    else
                    {
                        intersection = part.TestIntersectionOBB(ray, part.ParentGroup.GroupRotation, true, false);
                    }

                    //If it intersects, then check again with another method checkPointIntersectPrim().
                    if (intersection.HitTF && checkPointIntersectPrim(intersection.ipoint, part, 0.1f))
                    {
                        //If yes, then remember this distance and this intersection as the current 'return' candidate
                        if (intersection.distance < smallestDistance)
                        {
                            smallestDistance = intersection.distance;
                            closestIntersection = intersection;
                            closestPart = part;
                        }//if
                    }//if
                }//if
            }//foreach
            return new EntityIntersectionWithPart(closestIntersection, closestPart);
        }
예제 #13
0
        /// <summary>
        /// A recursive method which trace a ray until its power is less than ray-minimum power thershold
        /// </summary>
        /// <param name="path">New PathFromTxToRy object.</param>
        /// <param name="ray">A starting ray (first ray)</param>
        /// <param name="lastIntersectPart">A world object which this ray last intersect, or start</param>
        /// <returns>PathFromTxToRy with True if it reaches receiver and False if it did not reach the receiver.</returns>
        public PathFromTxToRy traceRay(PathFromTxToRy path, Ray ray, SceneObjectPart lastIntersectPart)
        {
            EntityIntersectionWithPart nextHit = findNextHit(ray, transmitter.RootPart);

            if (nextHit.intersection.HitTF)
            {
                //Check for limit number of reflection allowed.
                if(path.getNoOfReflection() >= MAX_REFLECTIONS)
                {
                    path.reachesReceiver = false;
                    return path;
                }
                //drawRay(ray.Origin, nextHit.intersection.ipoint);
                else if (nextHit.intersectPart.Equals(receiver.RootPart)) //If it reaches the receiver
                {
                    path.reachesReceiver = true;
                    path.addNextPoint(nextHit.intersection.ipoint, receiver.RootPart.Material);
                    return path;
                }//if

                //recursive case, keep tracing this ray.
                else
                {
                    path.addNextPoint(nextHit.intersection.ipoint, nextHit.intersectPart.Material);
                    Vector3 reflectedVector = getReflectedVector(ray.Direction, nextHit.intersection.normal);
                    Ray newRay = new Ray(nextHit.intersection.ipoint, reflectedVector);
                    return traceRay(path, newRay, nextHit.intersectPart);
                }//else if
            }
            else //It didn't hit anything
            {
                path.reachesReceiver = false;
                return path;
            }//else
        }
예제 #14
0
 /// <summary>
 ///     Get a scene object group that contains the prim with the given uuid
 /// </summary>
 /// <param name="hray"></param>
 /// <param name="frontFacesOnly"></param>
 /// <param name="faceCenters"></param>
 /// <returns>null if no scene object group containing that prim is found</returns>
 protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
 {
     // Primitive Ray Tracing
     float closestDistance = 280f;
     EntityIntersection result = new EntityIntersection();
     ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, closestDistance);
     foreach (ISceneEntity ent in EntityList)
     {
         if (ent is SceneObjectGroup)
         {
             SceneObjectGroup reportingG = (SceneObjectGroup) ent;
             EntityIntersection inter = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
             if (inter.HitTF && inter.distance < closestDistance)
             {
                 closestDistance = inter.distance;
                 result = inter;
             }
         }
     }
     return result;
 }
예제 #15
0
 public bool EntityCollisionTest(Ray ray, IPhysical obj, out float distance)
 {
     float unused;
     return RayAABB.CollisionTestSmits(obj.SceneAABB, ray, out distance, out unused);
 }
예제 #16
0
        /// <summary>
        ///     Gets a list of scene object group that intersect with the given ray
        /// </summary>
        public List<EntityIntersection> GetIntersectingPrims(Ray hray, float length, int count,
                                                             bool frontFacesOnly, bool faceCenters, bool getAvatars,
                                                             bool getLand, bool getPrims)
        {
            // Primitive Ray Tracing
            List<EntityIntersection> result = new List<EntityIntersection>(count);
            if (getPrims)
            {
                ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, length);

                result.AddRange(
                    EntityList.OfType<SceneObjectGroup>()
                              .Select(reportingG => reportingG.TestIntersection(hray, frontFacesOnly, faceCenters))
                              .Where(inter => inter.HitTF));
            }
            if (getAvatars)
            {
                List<IScenePresence> presenceList = Entities.GetPresences();
                foreach (IScenePresence ent in presenceList)
                {
                    //Do rough approximation and keep the # of loops down
                    Vector3 newPos = hray.Origin;
                    for (int i = 0; i < 100; i++)
                    {
                        newPos += ((Vector3.One*(length*(i/100)))*hray.Direction);
                        if (ent.AbsolutePosition.ApproxEquals(newPos, ent.PhysicsActor.Size.X*2))
                        {
                            EntityIntersection intersection = new EntityIntersection();
                            intersection.distance = length*(i/100);
                            intersection.face = 0;
                            intersection.HitTF = true;
                            intersection.obj = ent;
                            intersection.ipoint = newPos;
                            intersection.normal = newPos;
                            result.Add(intersection);
                            break;
                        }
                    }
                }
            }
            if (getLand)
            {
                //TODO
            }

            result.Sort((a, b) => a.distance.CompareTo(b.distance));

            if (result.Count > count)
                result.RemoveRange(count, result.Count - count);
            return result;
        }
예제 #17
0
        public bool FullSceneCollisionTest(bool includeTerrain, Ray ray, ISceneEntity castingObj, out ISceneEntity collisionObj, out float dist)
        {
            ISceneEntity minCollider = null;
            float minDist = Single.MaxValue;

            // Test against the AABB of every entity in the scene (can be slow!)
            m_scene.ForEachEntity(
                delegate(ISceneEntity entity)
                {
                    if (entity == castingObj)
                        return;

                    float thisDist;
                    if (entity is IPhysical && EntityCollisionTest(ray, (IPhysical)entity, out thisDist) && thisDist < minDist)
                    {
                        minDist = thisDist;
                        minCollider = entity;
                    }
                }
            );

            collisionObj = minCollider;
            dist = minDist;

            if (includeTerrain)
            {
                // Test against the terrain
                float terrainDist;
                if (RayHeightmap.CollisionTest(ray, m_terrain.GetHeightmap(), 256, 256, 256.0f, out terrainDist) && terrainDist < dist)
                {
                    dist = terrainDist;
                    collisionObj = null;
                    return true;
                }
            }

            return collisionObj != null;
        }
예제 #18
0
파일: Scene.cs 프로젝트: CCIR/opensim
        /// <summary>
        /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
        /// </summary>
        /// <param name="RayStart"></param>
        /// <param name="RayEnd"></param>
        /// <param name="RayTargetID"></param>
        /// <param name="rot"></param>
        /// <param name="bypassRayCast"></param>
        /// <param name="RayEndIsIntersection"></param>
        /// <param name="frontFacesOnly"></param>
        /// <param name="scale"></param>
        /// <param name="FaceCenter"></param>
        /// <returns></returns>
        public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
        {
            Vector3 pos = Vector3.Zero;
            if (RayEndIsIntersection == (byte)1)
            {
                pos = RayEnd;
                return pos;
            }

            if (RayTargetID != UUID.Zero)
            {
                SceneObjectPart target = GetSceneObjectPart(RayTargetID);

                Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
                Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
                Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);

                if (target != null)
                {
                    pos = target.AbsolutePosition;
                    //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());

                    // TODO: Raytrace better here

                    //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
                    Ray NewRay = new Ray(AXOrigin, AXdirection);

                    // Ray Trace against target here
                    EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);

                    // Un-comment out the following line to Get Raytrace results printed to the console.
                   // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
                    float ScaleOffset = 0.5f;

                    // If we hit something
                    if (ei.HitTF)
                    {
                        Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
                        if (scaleComponent.X != 0) ScaleOffset = scale.X;
                        if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
                        if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
                        ScaleOffset = Math.Abs(ScaleOffset);
                        Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                        Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
                        // Set the position to the intersection point
                        Vector3 offset = (normal * (ScaleOffset / 2f));
                        pos = (intersectionpoint + offset);

                        //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
                        //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
                        // Un-offset the prim (it gets offset later by the consumer method)
                        //pos.Z -= 0.25F; 
                       
                    }

                    return pos;
                }
                else
                {
                    // We don't have a target here, so we're going to raytrace all the objects in the scene.

                    EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);

                    // Un-comment the following line to print the raytrace results to the console.
                    //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());

                    if (ei.HitTF)
                    {
                        pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
                    } else
                    {
                        // fall back to our stupid functionality
                        pos = RayEnd;
                    }

                    return pos;
                }
            }
            else
            {
                // fall back to our stupid functionality
                pos = RayEnd;

                //increase height so its above the ground.
                //should be getting the normal of the ground at the rez point and using that?
                pos.Z += scale.Z / 2f;
                return pos;
            }
        }
예제 #19
0
        private void UpdateEntity(ISceneEntity entity)
        {
            if (!(entity is IPhysical)) return;
            if (entity is IScenePresence && ((IScenePresence)entity).IsChildPresence) return;

            float elapsedTime = m_elapsedTime;
            if (elapsedTime <= 0f) return;

            IPhysical physical = (IPhysical)entity;
            if (!physical.DynamicsEnabled) return;

            IPhysicalPresence presence = (physical is IPhysicalPresence) ? (IPhysicalPresence)physical : null;
            Vector3 velocity = physical.Velocity * elapsedTime;
            Vector3 position = physical.RelativePosition;

            Vector3 move = (presence != null) ? presence.InputVelocity : Vector3.Zero;
            bool jumping = (presence != null) ? presence.JumpStart != 0 : false;
            float gravity = 0f;
            float waterHeight = 0.0f;
            if (m_terrain != null)
                waterHeight = m_terrain.WaterHeight;
            float waterChestHeight = waterHeight - (physical.Scale.Z * .33f);
            float speed = elapsedTime;
            float fallElapsed = (float)(Environment.TickCount - physical.FallStart) / 1000f;
            UUID anim = UUID.Zero;
            List<ISceneEntity> colliders = new List<ISceneEntity>();

            if (presence != null && presence.StunMS > 0)
            {
                move = Vector3.Zero;
                presence.StunMS -= (int)((float)1000 * elapsedTime);
            }

            ISceneEntity collider;
            float collisionDist;

            //if (presence != null && presence.InputDirection != Vector3.Zero)
            //{
            //    // Raycast in the direction the avatar wishes to move
            //    Ray avRay = new Ray(physical.ScenePosition, Vector3.Normalize(presence.InputDirection));
            //    if (FullSceneCollisionTest(false, avRay, presence, out collider, out collisionDist))
            //    {
            //        speed = Math.Min(speed, collisionDist - COLLISION_MARGIN);
            //        m_log.Debug("Raycasted to " + collider.Name + " (" + collider.LocalID + ")");
            //    }
            //}
            //HACK: detect both X and Y ray collisions, since we are not calculating a collision normal
            Vector3 normVel = Vector3.Normalize(velocity);
            if ((normVel.X != 0f || move.X != 0f) && FullSceneCollisionTest(false, new Ray(position, normVel.X > 0 || move.X > 0 ? Vector3.UnitX : -Vector3.UnitX), physical, out collider, out collisionDist) && collisionDist <= COLLISION_MARGIN)
            {
                move.X = 0f;
                velocity.X = 0f;

                if (!colliders.Contains(collider))
                    colliders.Add(collider);
            }
            if ((normVel.Y != 0f || move.Y != 0f) && FullSceneCollisionTest(false, new Ray(position, normVel.Y > 0 || move.Y > 0 ? Vector3.UnitY : -Vector3.UnitY), physical, out collider, out collisionDist) && collisionDist <= COLLISION_MARGIN)
            {
                move.Y = 0f;
                velocity.Y = 0f;

                if (!colliders.Contains(collider))
                    colliders.Add(collider);
            }

            #region Terrain Movement

            float oldFloor = 0.0f, newFloor = 0.0f;
            if (m_terrain != null)
                oldFloor = m_terrain.GetTerrainHeightAt(position.X, position.Y);

            position += (move * speed);

            if (m_terrain != null)
                newFloor = m_terrain.GetTerrainHeightAt(position.X, position.Y);

            if (presence != null)
            {
                if (presence.MovementState != MovementState.Flying && newFloor != oldFloor)
                    speed /= (1f + (SQRT_TWO * Math.Abs(newFloor - oldFloor)));
            }

            //HACK: distance from avatar center to the bottom of its feet
            float distanceFromFloor = physical.Scale.Z * .5f;

            // Raycast for gravity
            Ray ray = new Ray(position, -Vector3.UnitZ);
            if (FullSceneCollisionTest(false, ray, physical, out collider, out collisionDist))
            {
                if (position.Z - collisionDist > newFloor)
                {
                    newFloor = position.Z - collisionDist;

                    //FIXME
                    //if (!colliders.Contains(collider))
                        //colliders.Add(collider);
                }
            }

            float lowerLimit = newFloor + distanceFromFloor;

            #endregion Terrain Movement

            if (presence != null && presence.MovementState == MovementState.Flying)
            {
                #region Flying

                physical.FallStart = 0;
                presence.JumpStart = 0;

                //velocity falloff while flying
                velocity.X *= 0.66f;
                velocity.Y *= 0.66f;
                velocity.Z *= 0.33f;

                if (position.Z == lowerLimit)
                    velocity.Z += INITIAL_HOVER_IMPULSE;

                if (move.X != 0f || move.Y != 0f)
                    anim = Animations.FLY;
                else if (move.Z > 0f)
                    anim = Animations.HOVER_UP;
                else if (move.Z < 0f)
                    anim = Animations.HOVER_DOWN;
                else
                    anim = Animations.HOVER;

                #endregion Flying
            }
            else if (position.Z > lowerLimit + FALL_FORGIVENESS || position.Z <= waterChestHeight)
            {
                #region Falling/Floating/Landing

                if (position.Z > waterHeight)
                { //above water

                    //override controls while drifting
                    move = Vector3.Zero;

                    //keep most of our horizontal inertia
                    velocity.X *= 0.975f;
                    velocity.Y *= 0.975f;

                    if (physical.FallStart == 0) //|| (fallElapsed > FALL_DELAY && velocity.Z >= 0f))
                    { //just started falling
                        physical.FallStart = Environment.TickCount;
                    }
                    else
                    {
                        gravity = GRAVITY * fallElapsed * elapsedTime; //normal gravity

                        if (!jumping)
                        { //falling
                            if (fallElapsed > FALL_DELAY)
                            { //falling long enough to trigger the animation
                                anim = Animations.FALLDOWN;
                            }
                        }
                    }
                }
                else if (position.Z >= waterChestHeight)
                { //at the water line

                    velocity *= 0.1f;
                    velocity.Z = 0f;
                    physical.FallStart = 0;

                    if (move.Z < 1f)
                        position.Z = waterChestHeight;

                    if (move.Z > 0f)
                        anim = Animations.HOVER_UP;
                    else if (move.X != 0f || move.Y != 0f)
                        anim = Animations.SWIM_FORWARD;
                    else
                        anim = Animations.HOVER;
                }
                else
                { //underwater

                    velocity *= 0.1f;
                    velocity.Z += 0.75f * elapsedTime; // buoyant

                    if (move.Z < 0f)
                        anim = Animations.SWIM_DOWN;
                    else
                        anim = Animations.SWIM_FORWARD;
                }

                #endregion Falling/Floating/Landing
            }
            else
            {
                #region Ground Movement

                if (presence != null)
                {
                    if (presence.JumpStart == 0 && physical.FallStart > 0)
                    {
                        if (fallElapsed >= FALL_DELAY * 4)
                        {
                            anim = Animations.STANDUP;
                            presence.StunMS = 2000;
                        }
                        else if (fallElapsed >= FALL_DELAY * 3)
                        {
                            anim = Animations.MEDIUM_LAND;
                            presence.StunMS = 1000;
                        }
                        else if (fallElapsed >= FALL_DELAY * 2)
                        {
                            anim = Animations.LAND;
                            presence.StunMS = 500;
                        }
                        if (presence.Animations.SetDefaultAnimation(anim, 1))
                            m_scene.SendPresenceAnimations(this, presence);
                    }
                }

                physical.FallStart = 0;

                //friction
                velocity *= 0.2f;
                velocity.Z = 0f;
                position.Z = lowerLimit;

                if (presence != null)
                {
                    if (move.Z > 0f)
                    { //jumping
                        if (!jumping)
                        { //begin prejump
                            move.Z = 0f; //override Z control
                            anim = Animations.PRE_JUMP;

                            presence.JumpStart = Environment.TickCount;
                        }
                        else if (Environment.TickCount - presence.JumpStart > PREJUMP_DELAY * 1000)
                        { //start actual jump

                            if (presence.JumpStart == -1)
                            {
                                //already jumping! end current jump
                                presence.JumpStart = 0;
                                return;
                            }

                            anim = Animations.JUMP;

                            Vector3 normalVel = Vector3.Normalize(velocity);

                            velocity.X += normalVel.X * JUMP_IMPULSE_HORIZONTAL * elapsedTime;
                            velocity.Y += normalVel.Y * JUMP_IMPULSE_HORIZONTAL * elapsedTime;
                            velocity.Z = JUMP_IMPULSE_VERTICAL * elapsedTime;

                            presence.JumpStart = -1; //flag that we are currently jumping
                        }
                        else move.Z = 0; //override Z control
                    }
                    else
                    { //not jumping
                        presence.JumpStart = 0;

                        if (move.X != 0 || move.Y != 0)
                        {
                            if (move.Z < 0)
                                anim = Animations.CROUCHWALK;
                            else if (presence.MovementState == MovementState.Running)
                                anim = Animations.RUN;
                            else
                                anim = Animations.WALK;
                        }
                        else
                        {
                            if (move.Z < 0)
                                anim = Animations.CROUCH;
                            else
                                anim = Animations.STAND;
                        }
                    }
                }

                #endregion Ground Movement
            }

            if (presence != null)
            {
                if (anim != UUID.Zero && presence.StunMS <= 0 && presence.Animations.SetDefaultAnimation(anim, 1))
                    m_scene.SendPresenceAnimations(this, presence);
            }

            float maxVel = AVATAR_TERMINAL_VELOCITY * elapsedTime;

            #region Update Physical State

            // Calculate how far we moved this frame
            Vector3 moved = position - physical.RelativePosition;
            if (moved.Z < -maxVel)
                moved.Z = -maxVel;
            else if (moved.Z > maxVel)
                moved.Z = maxVel;

            position += velocity;

            moved.Z = moved.Z - gravity;
            velocity += moved;
            if (velocity.Z < -maxVel)
                velocity.Z = -maxVel;
            else if (velocity.Z > maxVel)
                velocity.Z = maxVel;

            if (position.Z < lowerLimit)
                position.Z = lowerLimit;
            if (position.Z < lowerLimit + COLLISION_MARGIN)
                velocity.Z = 0f;

            physical.Velocity = velocity / elapsedTime;
            physical.RelativePosition = position;

            #endregion Update Physical State

            EventHandler<EntityCollisionArgs> callback = OnEntityCollision;
            if (callback != null)
            {
                for (int i = 0, len = colliders.Count; i < len; i++)
                {
                    callback(this, new EntityCollisionArgs { First = physical, Second = colliders[i] });
                    callback(this, new EntityCollisionArgs { First = colliders[i], Second = physical });
                }
            }

            m_scene.EntityAddOrUpdate(this, physical, UpdateFlags.Position | UpdateFlags.Velocity, 0);
        }
예제 #20
0
        public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
        {
            // In this case we're using a sphere with a radius of the largest dimension of the prim
            // TODO: Change to take shape into account

            EntityIntersection result = new EntityIntersection();
            Vector3 vAbsolutePosition = AbsolutePosition;
            Vector3 vScale = Scale;
            Vector3 rOrigin = iray.Origin;
            Vector3 rDirection = iray.Direction;

            //rDirection = rDirection.Normalize();
            // Buidling the first part of the Quadratic equation
            Vector3 r2ndDirection = rDirection*rDirection;
            float itestPart1 = r2ndDirection.X + r2ndDirection.Y + r2ndDirection.Z;

            // Buidling the second part of the Quadratic equation
            Vector3 tmVal2 = rOrigin - vAbsolutePosition;
            Vector3 r2Direction = rDirection*2.0f;
            Vector3 tmVal3 = r2Direction*tmVal2;

            float itestPart2 = tmVal3.X + tmVal3.Y + tmVal3.Z;

            // Buidling the third part of the Quadratic equation
            Vector3 tmVal4 = rOrigin*rOrigin;
            Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition;

            Vector3 tmVal6 = vAbsolutePosition*rOrigin;

            // Set Radius to the largest dimension of the prim
            float radius = 0f;
            if (vScale.X > radius)
                radius = vScale.X;
            if (vScale.Y > radius)
                radius = vScale.Y;
            if (vScale.Z > radius)
                radius = vScale.Z;

            // the second part of this is the default prim size
            // once we factor in the aabb of the prim we're adding we can
            // change this to;
            // radius = (radius / 2) - 0.01f;
            //
            radius = (radius / 2) + (0.5f / 2) - 0.1f;

            //radius = radius;

            float itestPart3 = tmVal4.X + tmVal4.Y + tmVal4.Z + tmVal5.X + tmVal5.Y + tmVal5.Z -
                               (2.0f*(tmVal6.X + tmVal6.Y + tmVal6.Z + (radius*radius)));

            // Yuk Quadradrics..    Solve first
            float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3);
            if (rootsqr < 0.0f)
            {
                // No intersection
                return result;
            }
            float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);

            if (root < 0.0f)
            {
                // perform second quadratic root solution
                root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);

                // is there any intersection?
                if (root < 0.0f)
                {
                    // nope, no intersection
                    return result;
                }
            }

            // We got an intersection.  putting together an EntityIntersection object with the
            // intersection information
            Vector3 ipoint =
                new Vector3(iray.Origin.X + (iray.Direction.X*root), iray.Origin.Y + (iray.Direction.Y*root),
                            iray.Origin.Z + (iray.Direction.Z*root));

            result.HitTF = true;
            result.ipoint = ipoint;

            // Normal is calculated by the difference and then normalizing the result
            Vector3 normalpart = ipoint - vAbsolutePosition;
            result.normal = normalpart / normalpart.Length();

            // It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't.
            // I can write a function to do it..    but I like the fact that this one is Static.

            Vector3 distanceConvert1 = new Vector3(iray.Origin.X, iray.Origin.Y, iray.Origin.Z);
            Vector3 distanceConvert2 = new Vector3(ipoint.X, ipoint.Y, ipoint.Z);
            float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2);

            result.distance = distance;

            return result;
        }
예제 #21
0
        private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom, int max)
        {
            List<ContactResult> contacts = World.PhysicsScene.RaycastWorld(rayStart, Vector3.Normalize(rayEnd - rayStart), Vector3.Distance(rayEnd, rayStart), max);

            for (int i = 0; i < contacts.Count; i++)
            {
                ISceneEntity grp = World.GetGroupByPrim(contacts[i].ConsumerID);
                if(grp == null || (!includePhysical && grp.RootChild.PhysActor.IsPhysical) ||
                    (!includeNonPhysical && !grp.RootChild.PhysActor.IsPhysical))
                    contacts.RemoveAt(i--);
            }

            if (includePhantom)
            {
                Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));

                Vector3 ab = rayEnd - rayStart;

                ISceneEntity[] objlist = World.Entities.GetEntities();
                foreach (ISceneEntity group in objlist)
                {
                    if (m_host.ParentEntity == group)
                        continue;

                    if (group.IsAttachment)
                        continue;

                    if (group.RootChild.PhysActor != null)
                        continue;

                    // Find the radius ouside of which we don't even need to hit test
                    float minX;
                    float maxX;
                    float minY;
                    float maxY;
                    float minZ;
                    float maxZ;

                    float radius = 0.0f;

                    group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);

                    if (Math.Abs(minX) > radius)
                        radius = Math.Abs(minX);
                    if (Math.Abs(minY) > radius)
                        radius = Math.Abs(minY);
                    if (Math.Abs(minZ) > radius)
                        radius = Math.Abs(minZ);
                    if (Math.Abs(maxX) > radius)
                        radius = Math.Abs(maxX);
                    if (Math.Abs(maxY) > radius)
                        radius = Math.Abs(maxY);
                    if (Math.Abs(maxZ) > radius)
                        radius = Math.Abs(maxZ);
                    radius = radius * 1.413f;
                    Vector3 ac = group.AbsolutePosition - rayStart;
                    //                Vector3 bc = group.AbsolutePosition - rayEnd;

                    double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));

                    // Too far off ray, don't bother
                    if (d > radius)
                        continue;

                    // Behind ray, drop
                    double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
                    if (d2 > 0)
                        continue;

                    ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
                    EntityIntersection intersection = group.TestIntersection(ray, true, false);
                    // Miss.
                    if (!intersection.HitTF)
                        continue;

                    Vector3 b1 = new Vector3(minX, minY, minZ);
                    Vector3 b2 = new Vector3(maxX, maxY, maxZ);
                    //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
                    if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
                        intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
                        intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
                        continue;

                    ContactResult result = new ContactResult();
                    result.ConsumerID = group.LocalId;
                    result.Depth = intersection.distance;
                    result.Normal = intersection.normal;
                    result.Pos = intersection.ipoint;

                    contacts.Add(result);
                }
            }

            return contacts.ToArray();
        }
예제 #22
0
        public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
        {
            // We got a request from the inner_scene to raytrace along the Ray hRay
            // We're going to check all of the prim in this group for intersection with the ray
            // If we get a result, we're going to find the closest result to the origin of the ray
            // and send back the intersection information back to the innerscene.

            EntityIntersection result = new EntityIntersection();

            foreach (SceneObjectPart part in m_partsList)
            {
                // Temporary commented to stop compiler warning
                //Vector3 partPosition =
                //    new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
                Quaternion parentrotation = GroupRotation;
                // Telling the prim to raytrace.
                //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
                EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);

                // This may need to be updated to the maximum draw distance possible..
                // We might (and probably will) be checking for prim creation from other sims
                // when the camera crosses the border.
                float idist = Constants.RegionSize;
                if (inter.HitTF)
                {
                    // We need to find the closest prim to return to the testcaller along the ray
                    if (inter.distance < idist)
                    {
                        result.HitTF = true;
                        result.ipoint = inter.ipoint;
                        result.obj = part;
                        result.normal = inter.normal;
                        result.distance = inter.distance;
                    }
                }
            }

            return result;
        }
예제 #23
0
        /// <summary>
        /// From the transmitter, we create a ray in all direction (with angle between ray = ANGLE_BETWEEN_RAY). For each
        /// of those ray, we 'trace/follow' them and find where they are heading. If they reaches the reciever, then 
        /// we store them in a list. 
        /// </summary>
        public void startRayTracerBrutefoce()
        {
            m_log.DebugFormat("[BARE BONES NON SHARED] Started Raytracing!");

            float lat, lon;
            float toPercent = 100.0f/360.0f;

            //For every lon and lat increase by ANGLE_BETWEEN_RAY
            for (lon = 0; lon < 360; lon += ANGLE_BETWEEN_RAY)
            {
                for (lat = 0; lat < 360; lat += ANGLE_BETWEEN_RAY)
                {
                    double lonr = lon * DEG_TO_RAD;
                    double latr = lat * DEG_TO_RAD;
                    
                    //Note: Lat = angle of elevation. Lon = angle around the z-axis
                    //To get a point on a sphere using 2 angle 
                    //Assuming Radius = 1 so we can get rid of multiplying radius. 
                    //http://stackoverflow.com/questions/969798/plotting-a-point-on-the-edge-of-a-sphere

                    float x = (float)(Math.Sin(latr) * Math.Cos(lonr));
                    float y = (float)(Math.Sin(latr) * Math.Sin(lonr));
                    float z = (float)(Math.Cos(latr));

                    Vector3 pointOnSphere = new Vector3(x, y, z);
                    pointOnSphere.Normalize();

                    Vector3 direction = pointOnSphere;
                    Ray ray = new Ray(transmitter.RootPart.AbsolutePosition, direction);

                    //Trace this ray
                    string pathID = getPathID();
                    PathFromTxToRy thisRayPath = new PathFromTxToRy(this, transmitter.RootPart.AbsolutePosition, pathID);
                    thisRayPath = traceRay(thisRayPath, ray, transmitter.RootPart);

                    //If it reaches the receiver, then add it to the hit list. 
                    if (thisRayPath.reachesReceiver && !checkPathIsDrawn(thisRayPath))
                    {
                        pathHits[thisRayPath.getNoOfReflection()].Add(pathID, thisRayPath);
                    }
                }
                //If lon < 359 then calculate the progress 
                if (lon < 359)
                {
                    updateProgressBar(lon * toPercent);
                }
                else //else it is completed so return 100%
                {
                    updateProgressBar(100.0f);
                }
           }//for
        }