/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <remarks> /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race /// condition. But currently there is no /// alternative method that does take a lock to delink a single prim. /// </remarks> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Vector3 worldPos = linkPart.GetWorldPosition(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); SceneObjectPart[] parts = m_parts.GetArray(); // Rejigger the linknum's of the remaining SOP's to fill any gap if (parts.Length == 1 && RootPart != null) { // Single prim left RootPart.LinkNum = 0; } else { for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part.LinkNum > linkPart.LinkNum) part.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; 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) m_scene.PhysicsScene.RemovePrim(linkPartPa); // We need to reset the child part's position // 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; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); */ linkPart.GroupPosition = worldPos; linkPart.OffsetPosition = Vector3.Zero; linkPart.RotationOffset = worldRot; // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; // When we delete a group, we currently have to force persist to the database if the object id has changed // (since delete works by deleting all rows which have a given object id) objectGroup.HasGroupChangedDueToDelink = true; return objectGroup; }
// Old uuid and new sceneobjectgroup public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) { AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, part.GetWorldPosition(), MetaEntity.TRANSLUCENT, new Vector3(0,254,0), part.Scale ); m_NewlyCreatedEntityAura.Add(part.UUID, ent); return ent; }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, bool useTextures) { const float MIN_SIZE = 2f; if ((PCode)prim.Shape.PCode != PCode.Prim) return; if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) return; Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); FacetedMesh renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); if (renderMesh == null) return; warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); if (prim.ParentID != 0) { SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId); if (group != null) m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset))); } warp_Vector primScale = ConvertVector(prim.Scale); string primID = prim.UUID.ToString(); // Create the prim faces // TODO: Implement the useTextures flag behavior for (int i = 0; i < renderMesh.Faces.Count; i++) { Face face = renderMesh.Faces[i]; string meshName = primID + "-Face-" + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3); for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vector norm = ConvertVector(v.Normal); if (prim.Shape.SculptTexture == UUID.Zero) norm = norm.reverse(); warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } for (int j = 0; j < face.Indices.Count; j += 3) { faceObj.addTriangle( face.Indices[j + 0], face.Indices[j + 1], face.Indices[j + 2]); } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = GetFaceColor(teFace); string materialName = GetOrCreateMaterial(renderer, faceColor); faceObj.transform(m); faceObj.setPos(primPos); faceObj.scaleSelf(primScale.x, primScale.y, primScale.z); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <remarks> /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race /// condition. But currently there is no /// alternative method that does take a lock to delink a single prim. /// </remarks> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Vector3 worldPos = linkPart.GetWorldPosition(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); SceneObjectPart[] parts = m_parts.GetArray(); // Rejigger the linknum's of the remaining SOP's to fill any gap if (parts.Length == 1 && RootPart != null) { // Single prim left RootPart.LinkNum = 0; } else { for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part.LinkNum > linkPart.LinkNum) part.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; 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) m_scene.PhysicsScene.RemovePrim(linkPartPa); // We need to reset the child part's position // 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; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); */ linkPart.GroupPosition = worldPos; linkPart.OffsetPosition = Vector3.Zero; linkPart.RotationOffset = worldRot; // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; // We must persist the delinked group to the database immediately, for safety. The problem // is that although in memory the new group has a new SceneGroupID, in the database it // still has the parent group's SceneGroupID (until the next backup). This means that if the // parent group is deleted then the delinked group will also be deleted from the database. // This problem will disappear if the region remains alive long enough for another backup, // since at that time the delinked group's new SceneGroupID will be written to the database. // But if the region crashes before that then the prims will be permanently gone, and this must // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case // because the delinked group doesn't know when the source group is deleted.) m_scene.ForceSceneObjectBackup(objectGroup); return objectGroup; }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, bool useTextures) { const float MIN_SIZE = 2f; if ((PCode)prim.Shape.PCode != PCode.Prim) return; if (prim.Scale.LengthSquared() < MIN_SIZE * MIN_SIZE) return; FacetedMesh renderMesh = null; Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.RotationOffset); if (m_renderMeshes) { if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero) { // Try fetchinng the asset byte[] sculptAsset = m_scene.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); if (sculptAsset != null) { // Is it a mesh? if (omvPrim.Sculpt.Type == SculptType.Mesh) { AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out renderMesh); meshAsset = null; } else // It's sculptie { IJ2KDecoder imgDecoder = m_scene.RequestModuleInterface<IJ2KDecoder>(); if (imgDecoder != null) { Image sculpt = imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); sculpt.Dispose(); } } } } } } // If not a mesh or sculptie, try the regular mesher if (renderMesh == null) { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } if (renderMesh == null) return; warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.RotationOffset); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); if (prim.ParentID != 0) { SceneObjectGroup group = m_scene.SceneGraph.GetGroupByPrim(prim.LocalId); if (group != null) m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootPart.RotationOffset))); } warp_Vector primScale = ConvertVector(prim.Scale); string primID = prim.UUID.ToString(); // Create the prim faces // TODO: Implement the useTextures flag behavior for (int i = 0; i < renderMesh.Faces.Count; i++) { Face face = renderMesh.Faces[i]; string meshName = primID + "-Face-" + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3); for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vector norm = ConvertVector(v.Normal); if (prim.Shape.SculptTexture == UUID.Zero) norm = norm.reverse(); warp_Vertex vert = new warp_Vertex(pos, norm, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } for (int j = 0; j < face.Indices.Count; j += 3) { faceObj.addTriangle( face.Indices[j + 0], face.Indices[j + 1], face.Indices[j + 2]); } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = GetFaceColor(teFace); string materialName = String.Empty; if (m_texturePrims && prim.Scale.LengthSquared() > m_texturePrimSize*m_texturePrimSize) materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); else materialName = GetOrCreateMaterial(renderer, faceColor); faceObj.transform(m); faceObj.setPos(primPos); faceObj.scaleSelf(primScale.x, primScale.y, primScale.z); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }