/// <summary> /// Link the prims in a given group to this group /// </summary> /// <param name="objectGroup">The group of prims which should be linked to this group</param> public void LinkToGroup(SceneObjectGroup objectGroup) { //m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); //Clear the update schedule so that we don't send wrong updates later about how this group is set up objectGroup.RootPart.ClearUpdateScheduleOnce(); SceneObjectPart linkPart = objectGroup.m_rootPart; Vector3 oldGroupPosition = linkPart.GroupPosition; Quaternion oldRootRotation = linkPart.RotationOffset; Quaternion parentRot = m_rootPart.RotationOffset; linkPart.SetGroupPosition(AbsolutePosition); // just change it without doing anything else Vector3 axPos = oldGroupPosition - AbsolutePosition; axPos *= Quaternion.Inverse(parentRot); linkPart.SetOffsetPosition(axPos); Quaternion newRot = Quaternion.Inverse(parentRot) * oldRootRotation; linkPart.SetRotationOffset(false,newRot,false); //Fix the link number for the root if (m_rootPart.LinkNum == 0) m_rootPart.LinkNum = 1; SceneObjectPart[] objectGroupChildren = new SceneObjectPart[objectGroup.ChildrenList.Count]; objectGroup.ChildrenList.CopyTo(objectGroupChildren, 0); //Destroy the old group m_scene.SceneGraph.DeleteEntity(objectGroup); objectGroup.IsDeleted = true; objectGroup.ClearChildren(); lock (m_partsLock) { int linkNum = 2; //Add the root part to our group! m_scene.SceneGraph.LinkPartToSOG(this, linkPart, linkNum++); linkPart.CreateSelected = true; linkPart.FixOffsetPosition(linkPart.OffsetPosition, true); // nasty let all know about where this is // let physics link it if (linkPart.PhysActor != null && m_rootPart.PhysActor != null) { linkPart.PhysActor.link(m_rootPart.PhysActor); this.Scene.SceneGraph.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor); } //rest of parts foreach (SceneObjectPart part in objectGroupChildren) { if (part.UUID != objectGroup.m_rootPart.UUID) { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); part.FixOffsetPosition(part.OffsetPosition, true); if (part.PhysActor != null && m_rootPart.PhysActor != null) { part.PhysActor.link(m_rootPart.PhysActor); this.Scene.SceneGraph.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); } } } } // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and // unmoved prims! ResetChildPrimPhysicsPositions(); }