From af34bfddd18b5253d9c57dd9191329c159dbd45e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 24 Sep 2015 06:46:07 +0100 Subject: add physics assistance on placement of a new object. This may help on mantis 7727, but may still need more work --- OpenSim/Region/Framework/Scenes/Scene.cs | 162 +++++++++++++-------- .../ubOde/ODERayCastRequestManager.cs | 9 +- 2 files changed, 104 insertions(+), 67 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index cbaf803..fced0cc 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2283,99 +2283,139 @@ namespace OpenSim.Region.Framework.Scenes /// public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) { - + float wheight = (float)RegionInfo.RegionSettings.WaterHeight; Vector3 wpos = Vector3.Zero; // Check for water surface intersection from above - if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) ) + if ((RayStart.Z > wheight) && (RayEnd.Z < wheight)) { float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z); wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X)); wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y)); wpos.Z = wheight; - } - + } + Vector3 pos = Vector3.Zero; if (RayEndIsIntersection == (byte)1) { pos = RayEnd; } - else if (RayTargetID != UUID.Zero) + else { - SceneObjectPart target = GetSceneObjectPart(RayTargetID); + Vector3 rayEnd = RayEnd; + + Vector3 dir = rayEnd - RayStart; + float dist = Vector3.Mag(dir) + 2.0f; - Vector3 direction = Vector3.Normalize(RayEnd - RayStart); - Vector3 AXOrigin = RayStart; - Vector3 AXdirection = direction; + Vector3 direction = dir * (1 / dist); - if (target != null) + if (SupportsRayCastFiltered()) { - 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); + RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull; + rayfilter |= RayFilterFlags.land; + rayfilter |= RayFilterFlags.physical; + rayfilter |= RayFilterFlags.nonphysical; + rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors - // 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; + // get some more contacts ??? + int physcount = 4; - // If we hit something - if (ei.HitTF) + List physresults = + (List)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter); + if (physresults != null && physresults.Count > 0) { - 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 (physresults[0].ConsumerID == 0 || RayTargetID == UUID.Zero) + { + // found something + pos = physresults[0].Normal * scale ; + pos *= 0.5f; + pos = physresults[0].Pos +pos; + return pos; + } + foreach (ContactResult r in physresults) + { + SceneObjectPart part = GetSceneObjectPart(r.ConsumerID); + if (part == null) + continue; + if (part.UUID == RayTargetID) + { + pos = physresults[0].Normal * scale; + pos *= 0.5f; + pos = physresults[0].Pos + pos; + return pos; + } + } } } - else + if (RayTargetID != UUID.Zero) { - // 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); + SceneObjectPart target = GetSceneObjectPart(RayTargetID); - // 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()); + Ray NewRay = new Ray(RayStart, direction); - if (ei.HitTF) + if (target != null) { - pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); - } + 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; + + } + } else { - // fall back to our stupid functionality - pos = RayEnd; + // 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; + } } } - } - 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; + 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; + } } - // check against posible water intercept if (wpos.Z > pos.Z) pos = wpos; return pos; diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs index ef1e57c..b82d593 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs @@ -139,8 +139,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde continue; } } - - + CurrentRayFilter = req.filter; CurrentMaxCount = req.Count; @@ -186,7 +185,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.GeomRaySetLength(ray, req.length); d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); d.GeomRaySetParams(ray, 0, backfacecull); - d.GeomRaySetClosestHit(ray, closestHit); if (req.callbackMethod is RaycastCallback) { @@ -318,9 +316,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde { // current ode land to ray collisions is very bad // so for now limit its range badly - - if (req.length > 30.0f) - d.GeomRaySetLength(ray, 30.0f); + if (req.length > 60.0f) + d.GeomRaySetLength(ray, 60.0f); d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback); } -- cgit v1.1