add physics assistance on placement of a new object. This may help on mantis 7727, but may still need more work

avinationmerge
UbitUmarov 2015-09-24 06:46:07 +01:00
parent 5ca610d56a
commit af34bfddd1
2 changed files with 119 additions and 82 deletions

View File

@ -2287,7 +2287,7 @@ namespace OpenSim.Region.Framework.Scenes
float wheight = (float)RegionInfo.RegionSettings.WaterHeight; float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
Vector3 wpos = Vector3.Zero; Vector3 wpos = Vector3.Zero;
// Check for water surface intersection from above // 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); float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X)); wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
@ -2300,82 +2300,122 @@ namespace OpenSim.Region.Framework.Scenes
{ {
pos = RayEnd; pos = RayEnd;
} }
else if (RayTargetID != UUID.Zero) else
{ {
SceneObjectPart target = GetSceneObjectPart(RayTargetID); Vector3 rayEnd = RayEnd;
Vector3 direction = Vector3.Normalize(RayEnd - RayStart); Vector3 dir = rayEnd - RayStart;
Vector3 AXOrigin = RayStart; float dist = Vector3.Mag(dir) + 2.0f;
Vector3 AXdirection = direction;
if (target != null) Vector3 direction = dir * (1 / dist);
if (SupportsRayCastFiltered())
{ {
pos = target.AbsolutePosition; RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
//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()); rayfilter |= RayFilterFlags.land;
rayfilter |= RayFilterFlags.physical;
rayfilter |= RayFilterFlags.nonphysical;
rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
// TODO: Raytrace better here // get some more contacts ???
int physcount = 4;
//EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); List<ContactResult> physresults =
Ray NewRay = new Ray(AXOrigin, AXdirection); (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
if (physresults != null && physresults.Count > 0)
// 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 (physresults[0].ConsumerID == 0 || RayTargetID == UUID.Zero)
if (scaleComponent.X != 0) ScaleOffset = scale.X; {
if (scaleComponent.Y != 0) ScaleOffset = scale.Y; // found something
if (scaleComponent.Z != 0) ScaleOffset = scale.Z; pos = physresults[0].Normal * scale ;
ScaleOffset = Math.Abs(ScaleOffset); pos *= 0.5f;
Vector3 intersectionpoint = ei.ipoint; pos = physresults[0].Pos +pos;
Vector3 normal = ei.normal; return pos;
// Set the position to the intersection point }
Vector3 offset = (normal * (ScaleOffset / 2f)); foreach (ContactResult r in physresults)
pos = (intersectionpoint + offset); {
SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
//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 if (part == null)
//And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method continue;
// Un-offset the prim (it gets offset later by the consumer method) if (part.UUID == RayTargetID)
//pos.Z -= 0.25F; {
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. SceneObjectPart target = GetSceneObjectPart(RayTargetID);
EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
// Un-comment the following line to print the raytrace results to the console. Ray NewRay = new Ray(RayStart, direction);
//m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
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 else
{ {
// fall back to our stupid functionality // We don't have a target here, so we're going to raytrace all the objects in the scene.
pos = RayEnd; 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. else
//should be getting the normal of the ground at the rez point and using that? {
pos.Z += scale.Z / 2f; // fall back to our stupid functionality
// return pos; 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 // check against posible water intercept
if (wpos.Z > pos.Z) pos = wpos; if (wpos.Z > pos.Z) pos = wpos;
return pos; return pos;

View File

@ -140,7 +140,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
} }
} }
CurrentRayFilter = req.filter; CurrentRayFilter = req.filter;
CurrentMaxCount = req.Count; CurrentMaxCount = req.Count;
@ -186,7 +185,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
d.GeomRaySetLength(ray, req.length); 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.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.GeomRaySetParams(ray, 0, backfacecull);
d.GeomRaySetClosestHit(ray, closestHit);
if (req.callbackMethod is RaycastCallback) if (req.callbackMethod is RaycastCallback)
{ {
@ -318,9 +316,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
{ {
// current ode land to ray collisions is very bad // current ode land to ray collisions is very bad
// so for now limit its range badly // so for now limit its range badly
if (req.length > 60.0f)
if (req.length > 30.0f) d.GeomRaySetLength(ray, 60.0f);
d.GeomRaySetLength(ray, 30.0f);
d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback); d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
} }