diff options
author | UbitUmarov | 2015-09-24 06:46:07 +0100 |
---|---|---|
committer | UbitUmarov | 2015-09-24 06:46:07 +0100 |
commit | af34bfddd18b5253d9c57dd9191329c159dbd45e (patch) | |
tree | 37996a525802f84a581dfb587ec3d99323a20724 /OpenSim/Region/Framework/Scenes | |
parent | bug fix, let ubODE see more than one mesh on cast ray (diff) | |
download | opensim-SC-af34bfddd18b5253d9c57dd9191329c159dbd45e.zip opensim-SC-af34bfddd18b5253d9c57dd9191329c159dbd45e.tar.gz opensim-SC-af34bfddd18b5253d9c57dd9191329c159dbd45e.tar.bz2 opensim-SC-af34bfddd18b5253d9c57dd9191329c159dbd45e.tar.xz |
add physics assistance on placement of a new object. This may help on mantis 7727, but may still need more work
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rwxr-xr-x | OpenSim/Region/Framework/Scenes/Scene.cs | 162 |
1 files changed, 101 insertions, 61 deletions
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 | |||
2283 | /// <returns></returns> | 2283 | /// <returns></returns> |
2284 | public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) | 2284 | public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) |
2285 | { | 2285 | { |
2286 | 2286 | ||
2287 | float wheight = (float)RegionInfo.RegionSettings.WaterHeight; | 2287 | float wheight = (float)RegionInfo.RegionSettings.WaterHeight; |
2288 | Vector3 wpos = Vector3.Zero; | 2288 | Vector3 wpos = Vector3.Zero; |
2289 | // Check for water surface intersection from above | 2289 | // Check for water surface intersection from above |
2290 | if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) ) | 2290 | if ((RayStart.Z > wheight) && (RayEnd.Z < wheight)) |
2291 | { | 2291 | { |
2292 | float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z); | 2292 | float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z); |
2293 | wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X)); | 2293 | wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X)); |
2294 | wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y)); | 2294 | wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y)); |
2295 | wpos.Z = wheight; | 2295 | wpos.Z = wheight; |
2296 | } | 2296 | } |
2297 | 2297 | ||
2298 | Vector3 pos = Vector3.Zero; | 2298 | Vector3 pos = Vector3.Zero; |
2299 | if (RayEndIsIntersection == (byte)1) | 2299 | if (RayEndIsIntersection == (byte)1) |
2300 | { | 2300 | { |
2301 | pos = RayEnd; | 2301 | pos = RayEnd; |
2302 | } | 2302 | } |
2303 | else if (RayTargetID != UUID.Zero) | 2303 | else |
2304 | { | 2304 | { |
2305 | SceneObjectPart target = GetSceneObjectPart(RayTargetID); | 2305 | Vector3 rayEnd = RayEnd; |
2306 | |||
2307 | Vector3 dir = rayEnd - RayStart; | ||
2308 | float dist = Vector3.Mag(dir) + 2.0f; | ||
2306 | 2309 | ||
2307 | Vector3 direction = Vector3.Normalize(RayEnd - RayStart); | 2310 | Vector3 direction = dir * (1 / dist); |
2308 | Vector3 AXOrigin = RayStart; | ||
2309 | Vector3 AXdirection = direction; | ||
2310 | 2311 | ||
2311 | if (target != null) | 2312 | if (SupportsRayCastFiltered()) |
2312 | { | 2313 | { |
2313 | pos = target.AbsolutePosition; | 2314 | RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull; |
2314 | //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()); | 2315 | rayfilter |= RayFilterFlags.land; |
2315 | 2316 | rayfilter |= RayFilterFlags.physical; | |
2316 | // TODO: Raytrace better here | 2317 | rayfilter |= RayFilterFlags.nonphysical; |
2317 | 2318 | rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors | |
2318 | //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); | ||
2319 | Ray NewRay = new Ray(AXOrigin, AXdirection); | ||
2320 | |||
2321 | // Ray Trace against target here | ||
2322 | EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); | ||
2323 | 2319 | ||
2324 | // Un-comment out the following line to Get Raytrace results printed to the console. | 2320 | // get some more contacts ??? |
2325 | // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); | 2321 | int physcount = 4; |
2326 | float ScaleOffset = 0.5f; | ||
2327 | 2322 | ||
2328 | // If we hit something | 2323 | List<ContactResult> physresults = |
2329 | if (ei.HitTF) | 2324 | (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter); |
2325 | if (physresults != null && physresults.Count > 0) | ||
2330 | { | 2326 | { |
2331 | Vector3 scaleComponent = ei.AAfaceNormal; | 2327 | if (physresults[0].ConsumerID == 0 || RayTargetID == UUID.Zero) |
2332 | if (scaleComponent.X != 0) ScaleOffset = scale.X; | 2328 | { |
2333 | if (scaleComponent.Y != 0) ScaleOffset = scale.Y; | 2329 | // found something |
2334 | if (scaleComponent.Z != 0) ScaleOffset = scale.Z; | 2330 | pos = physresults[0].Normal * scale ; |
2335 | ScaleOffset = Math.Abs(ScaleOffset); | 2331 | pos *= 0.5f; |
2336 | Vector3 intersectionpoint = ei.ipoint; | 2332 | pos = physresults[0].Pos +pos; |
2337 | Vector3 normal = ei.normal; | 2333 | return pos; |
2338 | // Set the position to the intersection point | 2334 | } |
2339 | Vector3 offset = (normal * (ScaleOffset / 2f)); | 2335 | foreach (ContactResult r in physresults) |
2340 | pos = (intersectionpoint + offset); | 2336 | { |
2341 | 2337 | SceneObjectPart part = GetSceneObjectPart(r.ConsumerID); | |
2342 | //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 | 2338 | if (part == null) |
2343 | //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method | 2339 | continue; |
2344 | // Un-offset the prim (it gets offset later by the consumer method) | 2340 | if (part.UUID == RayTargetID) |
2345 | //pos.Z -= 0.25F; | 2341 | { |
2346 | 2342 | pos = physresults[0].Normal * scale; | |
2343 | pos *= 0.5f; | ||
2344 | pos = physresults[0].Pos + pos; | ||
2345 | return pos; | ||
2346 | } | ||
2347 | } | ||
2347 | } | 2348 | } |
2348 | } | 2349 | } |
2349 | else | 2350 | if (RayTargetID != UUID.Zero) |
2350 | { | 2351 | { |
2351 | // We don't have a target here, so we're going to raytrace all the objects in the scene. | 2352 | SceneObjectPart target = GetSceneObjectPart(RayTargetID); |
2352 | EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); | ||
2353 | 2353 | ||
2354 | // Un-comment the following line to print the raytrace results to the console. | 2354 | Ray NewRay = new Ray(RayStart, direction); |
2355 | //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); | ||
2356 | 2355 | ||
2357 | if (ei.HitTF) | 2356 | if (target != null) |
2358 | { | 2357 | { |
2359 | pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); | 2358 | pos = target.AbsolutePosition; |
2360 | } | 2359 | |
2360 | // Ray Trace against target here | ||
2361 | EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); | ||
2362 | |||
2363 | // Un-comment out the following line to Get Raytrace results printed to the console. | ||
2364 | // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); | ||
2365 | float ScaleOffset = 0.5f; | ||
2366 | |||
2367 | // If we hit something | ||
2368 | if (ei.HitTF) | ||
2369 | { | ||
2370 | Vector3 scaleComponent = ei.AAfaceNormal; | ||
2371 | if (scaleComponent.X != 0) ScaleOffset = scale.X; | ||
2372 | if (scaleComponent.Y != 0) ScaleOffset = scale.Y; | ||
2373 | if (scaleComponent.Z != 0) ScaleOffset = scale.Z; | ||
2374 | ScaleOffset = Math.Abs(ScaleOffset); | ||
2375 | Vector3 intersectionpoint = ei.ipoint; | ||
2376 | Vector3 normal = ei.normal; | ||
2377 | // Set the position to the intersection point | ||
2378 | Vector3 offset = (normal * (ScaleOffset / 2f)); | ||
2379 | pos = (intersectionpoint + offset); | ||
2380 | |||
2381 | //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 | ||
2382 | //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method | ||
2383 | // Un-offset the prim (it gets offset later by the consumer method) | ||
2384 | //pos.Z -= 0.25F; | ||
2385 | |||
2386 | } | ||
2387 | } | ||
2361 | else | 2388 | else |
2362 | { | 2389 | { |
2363 | // fall back to our stupid functionality | 2390 | // We don't have a target here, so we're going to raytrace all the objects in the scene. |
2364 | pos = RayEnd; | 2391 | EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false); |
2392 | |||
2393 | // Un-comment the following line to print the raytrace results to the console. | ||
2394 | //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); | ||
2395 | |||
2396 | if (ei.HitTF) | ||
2397 | { | ||
2398 | pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); | ||
2399 | } | ||
2400 | else | ||
2401 | { | ||
2402 | // fall back to our stupid functionality | ||
2403 | pos = RayEnd; | ||
2404 | } | ||
2365 | } | 2405 | } |
2366 | } | 2406 | } |
2367 | } | ||
2368 | else | ||
2369 | { | ||
2370 | // fall back to our stupid functionality | ||
2371 | pos = RayEnd; | ||
2372 | 2407 | ||
2373 | //increase height so its above the ground. | 2408 | else |
2374 | //should be getting the normal of the ground at the rez point and using that? | 2409 | { |
2375 | pos.Z += scale.Z / 2f; | 2410 | // fall back to our stupid functionality |
2376 | // return pos; | 2411 | pos = RayEnd; |
2412 | |||
2413 | //increase height so its above the ground. | ||
2414 | //should be getting the normal of the ground at the rez point and using that? | ||
2415 | pos.Z += scale.Z / 2f; | ||
2416 | // return pos; | ||
2417 | } | ||
2377 | } | 2418 | } |
2378 | |||
2379 | // check against posible water intercept | 2419 | // check against posible water intercept |
2380 | if (wpos.Z > pos.Z) pos = wpos; | 2420 | if (wpos.Z > pos.Z) pos = wpos; |
2381 | return pos; | 2421 | return pos; |