aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
authornlin2009-04-10 06:39:52 +0000
committernlin2009-04-10 06:39:52 +0000
commit8e6c20b27fdb95b9008614eb36678508407a4d19 (patch)
tree562e0363e5e551c8d3fee03736d319f9e8963c64 /OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
parent* Updated BulletDotNET dll with the ContactFlags definition. (diff)
downloadopensim-SC_OLD-8e6c20b27fdb95b9008614eb36678508407a4d19.zip
opensim-SC_OLD-8e6c20b27fdb95b9008614eb36678508407a4d19.tar.gz
opensim-SC_OLD-8e6c20b27fdb95b9008614eb36678508407a4d19.tar.bz2
opensim-SC_OLD-8e6c20b27fdb95b9008614eb36678508407a4d19.tar.xz
Handle ObjectSpin* packets to spin physical prims on Ctrl+Shift+Drag
Addresses Mantis #3381 The current implementation works as expected if the object has no rotation or only rotation around the Z axis; you can spin the object left or right (around the world Z axis). It works a little unexpectedly if the object has a non-Z-axis rotation; in this case the body is spun about its local Z axis, not the world Z-axis. (But SL also behaves oddly with a spin on an arbitrarily rotated object.)
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs100
1 files changed, 100 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 1834215..4fdc71e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2299,6 +2299,106 @@ namespace OpenSim.Region.Framework.Scenes
2299 } 2299 }
2300 2300
2301 /// <summary> 2301 /// <summary>
2302 /// If object is physical, prepare for spinning torques (set flag to save old orientation)
2303 /// </summary>
2304 /// <param name="rotation">Rotation. We do the math here to turn it into a torque</param>
2305 /// <param name="remoteClient"></param>
2306 public void SpinStart(IClientAPI remoteClient)
2307 {
2308 if (m_scene.EventManager.TriggerGroupSpinStart(UUID))
2309 {
2310 if (m_rootPart.PhysActor != null)
2311 {
2312 if (m_rootPart.PhysActor.IsPhysical)
2313 {
2314 m_rootPart.IsWaitingForFirstSpinUpdatePacket = true;
2315 }
2316 }
2317 }
2318 }
2319
2320 /// <summary>
2321 /// If object is physical, apply torque to spin it around
2322 /// </summary>
2323 /// <param name="rotation">Rotation. We do the math here to turn it into a torque</param>
2324 /// <param name="remoteClient"></param>
2325 public void SpinMovement(Quaternion newOrientation, IClientAPI remoteClient)
2326 {
2327 // The incoming newOrientation, sent by the client, "seems" to be the
2328 // desired target orientation. This needs further verification; in particular,
2329 // one would expect that the initial incoming newOrientation should be
2330 // fairly close to the original prim's physical orientation,
2331 // m_rootPart.PhysActor.Orientation. This however does not seem to be the
2332 // case (might just be an issue with different quaternions representing the
2333 // same rotation, or it might be a coordinate system issue).
2334 //
2335 // Since it's not clear what the relationship is between the PhysActor.Orientation
2336 // and the incoming orientations sent by the client, we take an alternative approach
2337 // of calculating the delta rotation between the orientations being sent by the
2338 // client. (Since a spin is invoked by ctrl+shift+drag in the client, we expect
2339 // a steady stream of several new orientations coming in from the client.)
2340 // This ensures that the delta rotations are being calculated from self-consistent
2341 // pairs of old/new rotations. Given the delta rotation, we apply a torque around
2342 // the delta rotation axis, scaled by the object mass times an arbitrary scaling
2343 // factor (to ensure the resulting torque is not "too strong" or "too weak").
2344 //
2345 // Ideally we need to calculate (probably iteratively) the exact torque or series
2346 // of torques needed to arrive exactly at the destination orientation. However, since
2347 // it is not yet clear how to map the destination orientation (provided by the viewer)
2348 // into PhysActor orientations (needed by the physics engine), we omit this step.
2349 // This means that the resulting torque will at least be in the correct direction,
2350 // but it will result in over-shoot or under-shoot of the target orientation.
2351 // For the end user, this means that ctrl+shift+drag can be used for relative,
2352 // but not absolute, adjustments of orientation for physical prims.
2353
2354 if (m_scene.EventManager.TriggerGroupSpin(UUID, newOrientation))
2355 {
2356 if (m_rootPart.PhysActor != null)
2357 {
2358 if (m_rootPart.PhysActor.IsPhysical)
2359 {
2360 if(m_rootPart.IsWaitingForFirstSpinUpdatePacket)
2361 {
2362 // first time initialization of "old" orientation for calculation of delta rotations
2363 m_rootPart.SpinOldOrientation = newOrientation;
2364 m_rootPart.IsWaitingForFirstSpinUpdatePacket = false;
2365 }
2366 else
2367 {
2368 // save and update old orientation
2369 Quaternion old = m_rootPart.SpinOldOrientation;
2370 m_rootPart.SpinOldOrientation = newOrientation;
2371 //m_log.Error("[SCENE OBJECT GROUP]: Old orientation is " + old);
2372 //m_log.Error("[SCENE OBJECT GROUP]: Incoming new orientation is " + newOrientation);
2373
2374 // compute difference between previous old rotation and new incoming rotation
2375 Quaternion minimalRotationFromQ1ToQ2 = Quaternion.Inverse(old) * newOrientation;
2376
2377 float rotationAngle;
2378 Vector3 rotationAxis;
2379 minimalRotationFromQ1ToQ2.GetAxisAngle(out rotationAxis, out rotationAngle);
2380 rotationAxis.Normalize();
2381
2382 //m_log.Error("SCENE OBJECT GROUP]: rotation axis is " + rotationAxis);
2383 PhysicsVector spinforce = new PhysicsVector(rotationAxis.X, rotationAxis.Y, rotationAxis.Z);
2384 spinforce = (spinforce/8) * m_rootPart.PhysActor.Mass; // 8 is an arbitrary torque scaling factor
2385 m_rootPart.PhysActor.AddAngularForce(spinforce,true);
2386 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2387 }
2388 }
2389 else
2390 {
2391 //NonPhysicalSpinMovement(pos);
2392 }
2393 }
2394 else
2395 {
2396 //NonPhysicalSpinMovement(pos);
2397 }
2398 }
2399 }
2400
2401 /// <summary>
2302 /// Return metadata about a prim (name, description, sale price, etc.) 2402 /// Return metadata about a prim (name, description, sale price, etc.)
2303 /// </summary> 2403 /// </summary>
2304 /// <param name="client"></param> 2404 /// <param name="client"></param>