diff options
author | nlin | 2009-04-10 06:39:52 +0000 |
---|---|---|
committer | nlin | 2009-04-10 06:39:52 +0000 |
commit | 8e6c20b27fdb95b9008614eb36678508407a4d19 (patch) | |
tree | 562e0363e5e551c8d3fee03736d319f9e8963c64 /OpenSim/Region/Framework | |
parent | * Updated BulletDotNET dll with the ContactFlags definition. (diff) | |
download | opensim-SC-8e6c20b27fdb95b9008614eb36678508407a4d19.zip opensim-SC-8e6c20b27fdb95b9008614eb36678508407a4d19.tar.gz opensim-SC-8e6c20b27fdb95b9008614eb36678508407a4d19.tar.bz2 opensim-SC-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')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/EventManager.cs | 32 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 41 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 100 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 |
5 files changed, 180 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 8621f70..7496af0 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -132,6 +132,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
132 | 132 | ||
133 | public event SceneGroupGrabed OnSceneGroupGrab; | 133 | public event SceneGroupGrabed OnSceneGroupGrab; |
134 | 134 | ||
135 | public delegate bool SceneGroupSpinStarted(UUID groupID); | ||
136 | |||
137 | public event SceneGroupSpinStarted OnSceneGroupSpinStart; | ||
138 | |||
139 | public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); | ||
140 | |||
141 | public event SceneGroupSpun OnSceneGroupSpin; | ||
142 | |||
135 | public delegate void LandObjectAdded(ILandObject newParcel); | 143 | public delegate void LandObjectAdded(ILandObject newParcel); |
136 | 144 | ||
137 | public event LandObjectAdded OnLandObjectAdded; | 145 | public event LandObjectAdded OnLandObjectAdded; |
@@ -381,6 +389,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
381 | private StopScript handlerStopScript = null; //OnStopScript; | 389 | private StopScript handlerStopScript = null; //OnStopScript; |
382 | private SceneGroupMoved handlerSceneGroupMove = null; //OnSceneGroupMove; | 390 | private SceneGroupMoved handlerSceneGroupMove = null; //OnSceneGroupMove; |
383 | private SceneGroupGrabed handlerSceneGroupGrab = null; //OnSceneGroupGrab; | 391 | private SceneGroupGrabed handlerSceneGroupGrab = null; //OnSceneGroupGrab; |
392 | private SceneGroupSpinStarted handlerSceneGroupSpinStarted = null; //OnSceneGroupSpinStart; | ||
393 | private SceneGroupSpun handlerSceneGroupSpin = null; //OnSceneGroupSpin; | ||
384 | private LandObjectAdded handlerLandObjectAdded = null; //OnLandObjectAdded; | 394 | private LandObjectAdded handlerLandObjectAdded = null; //OnLandObjectAdded; |
385 | private LandObjectRemoved handlerLandObjectRemoved = null; //OnLandObjectRemoved; | 395 | private LandObjectRemoved handlerLandObjectRemoved = null; //OnLandObjectRemoved; |
386 | private AvatarEnteringNewParcel handlerAvatarEnteringNewParcel = null; //OnAvatarEnteringNewParcel; | 396 | private AvatarEnteringNewParcel handlerAvatarEnteringNewParcel = null; //OnAvatarEnteringNewParcel; |
@@ -636,6 +646,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
636 | return true; | 646 | return true; |
637 | } | 647 | } |
638 | 648 | ||
649 | public bool TriggerGroupSpinStart(UUID groupID) | ||
650 | { | ||
651 | handlerSceneGroupSpinStarted = OnSceneGroupSpinStart; | ||
652 | |||
653 | if (handlerSceneGroupSpinStarted != null) | ||
654 | { | ||
655 | return handlerSceneGroupSpinStarted(groupID); | ||
656 | } | ||
657 | return true; | ||
658 | } | ||
659 | |||
660 | public bool TriggerGroupSpin(UUID groupID, Quaternion rotation) | ||
661 | { | ||
662 | handlerSceneGroupSpin = OnSceneGroupSpin; | ||
663 | |||
664 | if (handlerSceneGroupSpin != null) | ||
665 | { | ||
666 | return handlerSceneGroupSpin(groupID, rotation); | ||
667 | } | ||
668 | return true; | ||
669 | } | ||
670 | |||
639 | public void TriggerGroupGrab(UUID groupID, Vector3 offset, UUID userID) | 671 | public void TriggerGroupGrab(UUID groupID, Vector3 offset, UUID userID) |
640 | { | 672 | { |
641 | handlerSceneGroupGrab = OnSceneGroupGrab; | 673 | handlerSceneGroupGrab = OnSceneGroupGrab; |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0fe27a5..54c420d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -1933,6 +1933,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1933 | client.OnObjectSelect += SelectPrim; | 1933 | client.OnObjectSelect += SelectPrim; |
1934 | client.OnObjectDeselect += DeselectPrim; | 1934 | client.OnObjectDeselect += DeselectPrim; |
1935 | client.OnGrabUpdate += m_sceneGraph.MoveObject; | 1935 | client.OnGrabUpdate += m_sceneGraph.MoveObject; |
1936 | client.OnSpinStart += m_sceneGraph.SpinStart; | ||
1937 | client.OnSpinUpdate += m_sceneGraph.SpinObject; | ||
1936 | client.OnDeRezObject += DeRezObject; | 1938 | client.OnDeRezObject += DeRezObject; |
1937 | client.OnRezObject += RezObject; | 1939 | client.OnRezObject += RezObject; |
1938 | client.OnRezSingleAttachmentFromInv += RezSingleAttachment; | 1940 | client.OnRezSingleAttachmentFromInv += RezSingleAttachment; |
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index c2f9fd2..e6328dc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -1342,6 +1342,47 @@ namespace OpenSim.Region.Framework.Scenes | |||
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | /// <summary> | 1344 | /// <summary> |
1345 | /// Start spinning the given object | ||
1346 | /// </summary> | ||
1347 | /// <param name="objectID"></param> | ||
1348 | /// <param name="rotation"></param> | ||
1349 | /// <param name="remoteClient"></param> | ||
1350 | protected internal void SpinStart(UUID objectID, IClientAPI remoteClient) | ||
1351 | { | ||
1352 | SceneObjectGroup group = GetGroupByPrim(objectID); | ||
1353 | if (group != null) | ||
1354 | { | ||
1355 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) | ||
1356 | { | ||
1357 | group.SpinStart(remoteClient); | ||
1358 | } | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | /// <summary> | ||
1363 | /// Spin the given object | ||
1364 | /// </summary> | ||
1365 | /// <param name="objectID"></param> | ||
1366 | /// <param name="rotation"></param> | ||
1367 | /// <param name="remoteClient"></param> | ||
1368 | protected internal void SpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient) | ||
1369 | { | ||
1370 | SceneObjectGroup group = GetGroupByPrim(objectID); | ||
1371 | if (group != null) | ||
1372 | { | ||
1373 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) | ||
1374 | { | ||
1375 | group.SpinMovement(rotation, remoteClient); | ||
1376 | } | ||
1377 | // This is outside the above permissions condition | ||
1378 | // so that if the object is locked the client moving the object | ||
1379 | // get's it's position on the simulator even if it was the same as before | ||
1380 | // This keeps the moving user's client in sync with the rest of the world. | ||
1381 | group.SendGroupTerseUpdate(); | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | /// <summary> | ||
1345 | /// | 1386 | /// |
1346 | /// </summary> | 1387 | /// </summary> |
1347 | /// <param name="primLocalID"></param> | 1388 | /// <param name="primLocalID"></param> |
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> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2a5a563..1a5dd6d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -176,6 +176,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
176 | public bool VolumeDetectActive = false; // XmlIgnore set to avoid problems with persistance until I come to care for this | 176 | public bool VolumeDetectActive = false; // XmlIgnore set to avoid problems with persistance until I come to care for this |
177 | // Certainly this must be a persistant setting finally | 177 | // Certainly this must be a persistant setting finally |
178 | 178 | ||
179 | [XmlIgnore] | ||
180 | public bool IsWaitingForFirstSpinUpdatePacket = false; | ||
181 | [XmlIgnore] | ||
182 | public Quaternion SpinOldOrientation = new Quaternion(); | ||
183 | |||
179 | /// <summary> | 184 | /// <summary> |
180 | /// This part's inventory | 185 | /// This part's inventory |
181 | /// </summary> | 186 | /// </summary> |