Many explanitory comments added to the link and delink code in
SOG and SOP. Should have no functionality changes.0.7.4.1
parent
916e3bf886
commit
743437262e
|
@ -451,6 +451,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restuff the new GroupPosition into each SOP of the linkset.
|
||||||
|
// This has the affect of resetting and tainting the physics actors.
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
parts[i].GroupPosition = val;
|
parts[i].GroupPosition = val;
|
||||||
|
@ -1133,6 +1135,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void ResetChildPrimPhysicsPositions()
|
public void ResetChildPrimPhysicsPositions()
|
||||||
{
|
{
|
||||||
|
// Setting this SOG's absolute position also loops through and sets the positions
|
||||||
|
// of the SOP's in this SOG's linkset. This has the side affect of making sure
|
||||||
|
// the physics world matches the simulated world.
|
||||||
AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
|
AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
|
||||||
|
|
||||||
// teravus: AbsolutePosition is NOT a normal property!
|
// teravus: AbsolutePosition is NOT a normal property!
|
||||||
|
@ -1987,6 +1992,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
LinkToGroup(objectGroup, false);
|
LinkToGroup(objectGroup, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Link an existing group to this group.
|
||||||
|
// The group being linked need not be a linkset -- it can have just one prim.
|
||||||
public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
|
public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
|
@ -1997,35 +2004,51 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (objectGroup == this)
|
if (objectGroup == this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// 'linkPart' == the root of the group being linked into this group
|
||||||
SceneObjectPart linkPart = objectGroup.m_rootPart;
|
SceneObjectPart linkPart = objectGroup.m_rootPart;
|
||||||
|
|
||||||
// physics flags from group to be applied to linked parts
|
// physics flags from group to be applied to linked parts
|
||||||
bool grpusephys = UsesPhysics;
|
bool grpusephys = UsesPhysics;
|
||||||
bool grptemporary = IsTemporary;
|
bool grptemporary = IsTemporary;
|
||||||
|
|
||||||
|
// Remember where the group being linked thought it was
|
||||||
Vector3 oldGroupPosition = linkPart.GroupPosition;
|
Vector3 oldGroupPosition = linkPart.GroupPosition;
|
||||||
Quaternion oldRootRotation = linkPart.RotationOffset;
|
Quaternion oldRootRotation = linkPart.RotationOffset;
|
||||||
|
|
||||||
linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
|
// A linked SOP remembers its location and rotation relative to the root of a group.
|
||||||
linkPart.ParentID = m_rootPart.LocalId;
|
// Convert the root of the group being linked to be relative to the
|
||||||
linkPart.GroupPosition = AbsolutePosition;
|
// root of the group being linked to.
|
||||||
Vector3 axPos = linkPart.OffsetPosition;
|
// Note: Some of the assignments have complex side effects.
|
||||||
|
|
||||||
|
// First move the new group's root SOP's position to be relative to ours
|
||||||
|
// (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
|
||||||
|
// this code can be reordered to have a more logical flow.)
|
||||||
|
linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
|
||||||
|
// Assign the new parent to the root of the old group
|
||||||
|
linkPart.ParentID = m_rootPart.LocalId;
|
||||||
|
// Now that it's a child, it's group position is our root position
|
||||||
|
linkPart.GroupPosition = AbsolutePosition;
|
||||||
|
|
||||||
|
Vector3 axPos = linkPart.OffsetPosition;
|
||||||
|
// Rotate the linking root SOP's position to be relative to the new root prim
|
||||||
Quaternion parentRot = m_rootPart.RotationOffset;
|
Quaternion parentRot = m_rootPart.RotationOffset;
|
||||||
axPos *= Quaternion.Inverse(parentRot);
|
axPos *= Quaternion.Inverse(parentRot);
|
||||||
|
|
||||||
linkPart.OffsetPosition = axPos;
|
linkPart.OffsetPosition = axPos;
|
||||||
|
|
||||||
|
// Make the linking root SOP's rotation relative to the new root prim
|
||||||
Quaternion oldRot = linkPart.RotationOffset;
|
Quaternion oldRot = linkPart.RotationOffset;
|
||||||
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
||||||
linkPart.RotationOffset = newRot;
|
linkPart.RotationOffset = newRot;
|
||||||
|
|
||||||
linkPart.ParentID = m_rootPart.LocalId;
|
// If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
|
||||||
|
// Now that we know this SOG has at least two SOPs in it, the new root
|
||||||
|
// SOP becomes the first in the linkset.
|
||||||
if (m_rootPart.LinkNum == 0)
|
if (m_rootPart.LinkNum == 0)
|
||||||
m_rootPart.LinkNum = 1;
|
m_rootPart.LinkNum = 1;
|
||||||
|
|
||||||
lock (m_parts.SyncRoot)
|
lock (m_parts.SyncRoot)
|
||||||
{
|
{
|
||||||
|
// Calculate the new link number for the old root SOP
|
||||||
int linkNum;
|
int linkNum;
|
||||||
if (insert)
|
if (insert)
|
||||||
{
|
{
|
||||||
|
@ -2041,6 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
linkNum = PrimCount + 1;
|
linkNum = PrimCount + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the old root SOP as a part in our group's list
|
||||||
m_parts.Add(linkPart.UUID, linkPart);
|
m_parts.Add(linkPart.UUID, linkPart);
|
||||||
|
|
||||||
linkPart.SetParent(this);
|
linkPart.SetParent(this);
|
||||||
|
@ -2048,6 +2072,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
|
// let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
|
||||||
linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive);
|
linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive);
|
||||||
|
|
||||||
|
// If the added SOP is physical, also tell the physics engine about the link relationship.
|
||||||
if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
|
if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
|
||||||
{
|
{
|
||||||
linkPart.PhysActor.link(m_rootPart.PhysActor);
|
linkPart.PhysActor.link(m_rootPart.PhysActor);
|
||||||
|
@ -2056,20 +2082,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
linkPart.LinkNum = linkNum++;
|
linkPart.LinkNum = linkNum++;
|
||||||
|
|
||||||
|
// Get a list of the SOP's in the old group in order of their linknum's.
|
||||||
SceneObjectPart[] ogParts = objectGroup.Parts;
|
SceneObjectPart[] ogParts = objectGroup.Parts;
|
||||||
Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
|
Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
|
||||||
{
|
{
|
||||||
return a.LinkNum - b.LinkNum;
|
return a.LinkNum - b.LinkNum;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add each of the SOP's from the old linkset to our linkset
|
||||||
for (int i = 0; i < ogParts.Length; i++)
|
for (int i = 0; i < ogParts.Length; i++)
|
||||||
{
|
{
|
||||||
SceneObjectPart part = ogParts[i];
|
SceneObjectPart part = ogParts[i];
|
||||||
if (part.UUID != objectGroup.m_rootPart.UUID)
|
if (part.UUID != objectGroup.m_rootPart.UUID)
|
||||||
{
|
{
|
||||||
LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
|
LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
|
||||||
// let physics know
|
|
||||||
|
// Update the physics flags for the newly added SOP
|
||||||
|
// (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
|
||||||
part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive);
|
part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive);
|
||||||
|
|
||||||
|
// If the added SOP is physical, also tell the physics engine about the link relationship.
|
||||||
if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
|
if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
|
||||||
{
|
{
|
||||||
part.PhysActor.link(m_rootPart.PhysActor);
|
part.PhysActor.link(m_rootPart.PhysActor);
|
||||||
|
@ -2080,6 +2112,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that we've aquired all of the old SOG's parts, remove the old SOG from the scene.
|
||||||
m_scene.UnlinkSceneObject(objectGroup, true);
|
m_scene.UnlinkSceneObject(objectGroup, true);
|
||||||
objectGroup.IsDeleted = true;
|
objectGroup.IsDeleted = true;
|
||||||
|
|
||||||
|
@ -2152,7 +2185,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
|
/// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race
|
||||||
/// condition. But currently there is no
|
/// condition. But currently there is no
|
||||||
/// alternative method that does take a lonk to delink a single prim.
|
/// alternative method that does take a lock to delink a single prim.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="partID"></param>
|
/// <param name="partID"></param>
|
||||||
/// <param name="sendEvents"></param>
|
/// <param name="sendEvents"></param>
|
||||||
|
@ -2165,6 +2198,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
linkPart.ClearUndoState();
|
linkPart.ClearUndoState();
|
||||||
|
|
||||||
|
Vector3 worldPos = linkPart.GetWorldPosition();
|
||||||
Quaternion worldRot = linkPart.GetWorldRotation();
|
Quaternion worldRot = linkPart.GetWorldRotation();
|
||||||
|
|
||||||
// Remove the part from this object
|
// Remove the part from this object
|
||||||
|
@ -2174,6 +2208,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
|
||||||
|
// Rejigger the linknum's of the remaining SOP's to fill any gap
|
||||||
if (parts.Length == 1 && RootPart != null)
|
if (parts.Length == 1 && RootPart != null)
|
||||||
{
|
{
|
||||||
// Single prim left
|
// Single prim left
|
||||||
|
@ -2195,22 +2230,31 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
PhysicsActor linkPartPa = linkPart.PhysActor;
|
PhysicsActor linkPartPa = linkPart.PhysActor;
|
||||||
|
|
||||||
|
// Remove the SOP from the physical scene.
|
||||||
|
// If the new SOG is physical, it is re-created later.
|
||||||
|
// (There is a problem here in that we have not yet told the physics
|
||||||
|
// engine about the delink. Someday, linksets should be made first
|
||||||
|
// class objects in the physics engine interface).
|
||||||
if (linkPartPa != null)
|
if (linkPartPa != null)
|
||||||
m_scene.PhysicsScene.RemovePrim(linkPartPa);
|
m_scene.PhysicsScene.RemovePrim(linkPartPa);
|
||||||
|
|
||||||
// We need to reset the child part's position
|
// We need to reset the child part's position
|
||||||
// ready for life as a separate object after being a part of another object
|
// ready for life as a separate object after being a part of another object
|
||||||
|
|
||||||
|
/* This commented out code seems to recompute what GetWorldPosition already does.
|
||||||
|
* Replace with a call to GetWorldPosition (before unlinking)
|
||||||
Quaternion parentRot = m_rootPart.RotationOffset;
|
Quaternion parentRot = m_rootPart.RotationOffset;
|
||||||
|
|
||||||
Vector3 axPos = linkPart.OffsetPosition;
|
Vector3 axPos = linkPart.OffsetPosition;
|
||||||
|
|
||||||
axPos *= parentRot;
|
axPos *= parentRot;
|
||||||
linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
|
linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z);
|
||||||
linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
|
linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
|
||||||
linkPart.OffsetPosition = new Vector3(0, 0, 0);
|
linkPart.OffsetPosition = new Vector3(0, 0, 0);
|
||||||
|
*/
|
||||||
|
linkPart.GroupPosition = worldPos;
|
||||||
|
linkPart.OffsetPosition = Vector3.Zero;
|
||||||
linkPart.RotationOffset = worldRot;
|
linkPart.RotationOffset = worldRot;
|
||||||
|
|
||||||
|
// Create a new SOG to go around this unlinked and unattached SOP
|
||||||
SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
|
SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
|
||||||
|
|
||||||
m_scene.AddNewSceneObject(objectGroup, true);
|
m_scene.AddNewSceneObject(objectGroup, true);
|
||||||
|
@ -2239,42 +2283,56 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_isBackedUp = false;
|
m_isBackedUp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This links an SOP from a previous linkset into my linkset.
|
||||||
|
// The trick is that the SOP's position and rotation are relative to the old root SOP's
|
||||||
|
// so we are passed in the position and rotation of the old linkset so this can
|
||||||
|
// unjigger this SOP's position and rotation from the previous linkset and
|
||||||
|
// then make them relative to my linkset root.
|
||||||
private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
|
private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
|
||||||
{
|
{
|
||||||
Quaternion parentRot = oldGroupRotation;
|
Quaternion parentRot = oldGroupRotation;
|
||||||
Quaternion oldRot = part.RotationOffset;
|
Quaternion oldRot = part.RotationOffset;
|
||||||
Quaternion worldRot = parentRot * oldRot;
|
|
||||||
|
|
||||||
parentRot = oldGroupRotation;
|
|
||||||
|
|
||||||
|
// Move our position to not be relative to the old parent
|
||||||
Vector3 axPos = part.OffsetPosition;
|
Vector3 axPos = part.OffsetPosition;
|
||||||
|
|
||||||
axPos *= parentRot;
|
axPos *= parentRot;
|
||||||
part.OffsetPosition = axPos;
|
part.OffsetPosition = axPos;
|
||||||
part.GroupPosition = oldGroupPosition + part.OffsetPosition;
|
part.GroupPosition = oldGroupPosition + part.OffsetPosition;
|
||||||
part.OffsetPosition = Vector3.Zero;
|
part.OffsetPosition = Vector3.Zero;
|
||||||
|
|
||||||
|
// Compution our rotation to be not relative to the old parent
|
||||||
|
Quaternion worldRot = parentRot * oldRot;
|
||||||
part.RotationOffset = worldRot;
|
part.RotationOffset = worldRot;
|
||||||
|
|
||||||
|
// Add this SOP to our linkset
|
||||||
part.SetParent(this);
|
part.SetParent(this);
|
||||||
part.ParentID = m_rootPart.LocalId;
|
part.ParentID = m_rootPart.LocalId;
|
||||||
|
|
||||||
m_parts.Add(part.UUID, part);
|
m_parts.Add(part.UUID, part);
|
||||||
|
|
||||||
part.LinkNum = linkNum;
|
part.LinkNum = linkNum;
|
||||||
|
|
||||||
|
// Compute the new position of this SOP relative to the group position
|
||||||
part.OffsetPosition = part.GroupPosition - AbsolutePosition;
|
part.OffsetPosition = part.GroupPosition - AbsolutePosition;
|
||||||
|
|
||||||
Quaternion rootRotation = m_rootPart.RotationOffset;
|
// (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
|
||||||
|
// It would have the affect of setting the physics engine position multiple
|
||||||
|
// times. In theory, that is not necessary but I don't have a good linkset
|
||||||
|
// test to know that cleaning up this code wouldn't break things.)
|
||||||
|
|
||||||
|
// Rotate the relative position by the rotation of the group
|
||||||
|
Quaternion rootRotation = m_rootPart.RotationOffset;
|
||||||
Vector3 pos = part.OffsetPosition;
|
Vector3 pos = part.OffsetPosition;
|
||||||
pos *= Quaternion.Inverse(rootRotation);
|
pos *= Quaternion.Inverse(rootRotation);
|
||||||
part.OffsetPosition = pos;
|
part.OffsetPosition = pos;
|
||||||
|
|
||||||
|
// Compute the SOP's rotation relative to the rotation of the group.
|
||||||
parentRot = m_rootPart.RotationOffset;
|
parentRot = m_rootPart.RotationOffset;
|
||||||
oldRot = part.RotationOffset;
|
oldRot = part.RotationOffset;
|
||||||
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
|
||||||
part.RotationOffset = newRot;
|
part.RotationOffset = newRot;
|
||||||
|
|
||||||
|
// Since this SOP's state has changed, push those changes into the physics engine
|
||||||
|
// and the simulator.
|
||||||
part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect);
|
part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -693,9 +693,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// If this is a linkset, we don't want the physics engine mucking up our group position here.
|
// If this is a linkset, we don't want the physics engine mucking up our group position here.
|
||||||
PhysicsActor actor = PhysActor;
|
PhysicsActor actor = PhysActor;
|
||||||
|
// If physical and the root prim of a linkset, the position of the group is what physics thinks.
|
||||||
if (actor != null && ParentID == 0)
|
if (actor != null && ParentID == 0)
|
||||||
m_groupPosition = actor.Position;
|
m_groupPosition = actor.Position;
|
||||||
|
|
||||||
|
// If I'm an attachment, my position is reported as the position of who I'm attached to
|
||||||
if (ParentGroup.IsAttachment)
|
if (ParentGroup.IsAttachment)
|
||||||
{
|
{
|
||||||
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
|
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
|
||||||
|
@ -721,7 +723,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// To move the child prim in respect to the group position and rotation we have to calculate
|
// The physics engine always sees all objects (root or linked) in world coordinates.
|
||||||
actor.Position = GetWorldPosition();
|
actor.Position = GetWorldPosition();
|
||||||
actor.Orientation = GetWorldRotation();
|
actor.Orientation = GetWorldRotation();
|
||||||
}
|
}
|
||||||
|
@ -795,6 +797,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// We don't want the physics engine mucking up the rotations in a linkset
|
// We don't want the physics engine mucking up the rotations in a linkset
|
||||||
PhysicsActor actor = PhysActor;
|
PhysicsActor actor = PhysActor;
|
||||||
|
// If this is a root of a linkset, the real rotation is what the physics engine thinks.
|
||||||
|
// If not a root prim, the offset rotation is computed by SOG and is relative to the root.
|
||||||
if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
|
if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
|
||||||
{
|
{
|
||||||
if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
|
if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
|
||||||
|
@ -1980,14 +1984,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <returns>A Linked Child Prim objects position in world</returns>
|
/// <returns>A Linked Child Prim objects position in world</returns>
|
||||||
public Vector3 GetWorldPosition()
|
public Vector3 GetWorldPosition()
|
||||||
{
|
{
|
||||||
Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
|
Vector3 ret;
|
||||||
Vector3 axPos = OffsetPosition;
|
if (_parentID == 0)
|
||||||
axPos *= parentRot;
|
// if a root SOP, my position is what it is
|
||||||
Vector3 translationOffsetPosition = axPos;
|
ret = GroupPosition;
|
||||||
if(_parentID == 0)
|
|
||||||
return GroupPosition;
|
|
||||||
else
|
else
|
||||||
return ParentGroup.AbsolutePosition + translationOffsetPosition;
|
{
|
||||||
|
// If a child SOP, my position is relative to the root SOP so take
|
||||||
|
// my info and add the root's position and rotation to
|
||||||
|
// get my world position.
|
||||||
|
Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
|
||||||
|
Vector3 translationOffsetPosition = OffsetPosition * parentRot;
|
||||||
|
ret = ParentGroup.AbsolutePosition + translationOffsetPosition;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2004,6 +2014,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// A child SOP's rotation is relative to the root SOP's rotation.
|
||||||
|
// Combine them to get my absolute rotation.
|
||||||
Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
|
Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
|
||||||
Quaternion oldRot = RotationOffset;
|
Quaternion oldRot = RotationOffset;
|
||||||
newRot = parentRot * oldRot;
|
newRot = parentRot * oldRot;
|
||||||
|
|
Loading…
Reference in New Issue