FacetedMesh MeshPrim(Primitive prim) { FacetedMesh mesh = null; if (prim.Sculpt == null || prim.Sculpt.SculptTexture == UUID.Zero) { mesh = Mesher.GenerateFacetedMesh(prim, DetailLevel.Highest); } else if (prim.Sculpt.Type != SculptType.Mesh) { Image img = null; if (LoadTexture(prim.Sculpt.SculptTexture, ref img, true)) { mesh = Mesher.GenerateFacetedSculptMesh(prim, (Bitmap)img, DetailLevel.Highest); } } else { var gotMesh = new System.Threading.AutoResetEvent(false); Client.Assets.RequestMesh(prim.Sculpt.SculptTexture, (success, meshAsset) => { if (!success || !FacetedMesh.TryDecodeFromAsset(prim, meshAsset, DetailLevel.Highest, out mesh)) { Logger.Log("Failed to fetch or decode the mesh asset", Helpers.LogLevel.Warning, Client); } gotMesh.Set(); }); gotMesh.WaitOne(20 * 1000, false); } return(mesh); }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim) { if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } Vector3 ppos = prim.GetWorldPosition(); if (ppos.Z < m_renderMinHeight || ppos.Z > m_renderMaxHeight) { return; } warp_Vector primPos = ConvertVector(ppos); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); float screenFactor = renderer.Scene.EstimateBoxProjectedArea(primPos, ConvertVector(prim.Scale), m); if (screenFactor < 0) { return; } const float log2inv = -1.442695f; int p2 = (int)((float)Math.Log(screenFactor) * log2inv * 0.25 - 1); if (p2 < 0) { p2 = 0; } else if (p2 > 3) { p2 = 3; } DetailLevel lod = (DetailLevel)(3 - p2); 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 AssetBase sculptAsset = m_scene.AssetService.Get(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.Data); FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, lod, out renderMesh); meshAsset = null; } else // It's sculptie { if (m_imgDecoder != null) { Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset.Data); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, lod); sculpt.Dispose(); } } } } else { m_log.WarnFormat("[Warp3D] failed to get mesh or sculpt asset {0} of prim {1} at {2}", omvPrim.Sculpt.SculptTexture.ToString(), prim.Name, prim.GetWorldPosition().ToString()); } } } // If not a mesh or sculptie, try the regular mesher if (renderMesh == null) { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, lod); } if (renderMesh == null) { return; } 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 + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(); Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); Color4 faceColor = teFace.RGBA; if (faceColor.A == 0) { continue; } string materialName = string.Empty; if (m_texturePrims) { // if(lod > DetailLevel.Low) { // materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, lod == DetailLevel.Low); materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID, false, prim); if (String.IsNullOrEmpty(materialName)) { continue; } int c = renderer.Scene.material(materialName).getColor(); if ((c & warp_Color.MASKALPHA) == 0) { continue; } } } else { materialName = GetOrCreateMaterial(renderer, faceColor); } if (renderer.Scene.material(materialName).getTexture() == null) { // uv map details dont not matter for color; for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vertex vert = new warp_Vertex(pos, v.TexCoord.X, v.TexCoord.Y); faceObj.addVertex(vert); } } else { float tu; float tv; float offsetu = teFace.OffsetU + 0.5f; float offsetv = teFace.OffsetV + 0.5f; float scaleu = teFace.RepeatU; float scalev = teFace.RepeatV; float rotation = teFace.Rotation; float rc = 0; float rs = 0; if (rotation != 0) { rc = (float)Math.Cos(rotation); rs = (float)Math.Sin(rotation); } for (int j = 0; j < face.Vertices.Count; j++) { warp_Vertex vert; Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); if (teFace.TexMapType == MappingType.Planar) { UVPlanarMap(v, prim.Scale, out tu, out tv); } else { tu = v.TexCoord.X - 0.5f; tv = 0.5f - v.TexCoord.Y; } if (rotation != 0) { float tur = tu * rc - tv * rs; float tvr = tu * rs + tv * rc; tur *= scaleu; tur += offsetu; tvr *= scalev; tvr += offsetv; vert = new warp_Vertex(pos, tur, tvr); } else { tu *= scaleu; tu += offsetu; tv *= scalev; tv += offsetv; vert = new warp_Vertex(pos, tu, tv); } 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]); } faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); faceObj.transform(m); faceObj.setPos(primPos); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }
private void CreatePrim(WarpRenderer renderer, SceneObjectPart prim, bool useTextures) { const float MIN_SIZE_SQUARE = 4f; if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } float primScaleLenSquared = prim.Scale.LengthSquared(); if (primScaleLenSquared < MIN_SIZE_SQUARE) { 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; } 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 + i.ToString(); // Avoid adding duplicate meshes to the scene if (renderer.Scene.objectData.ContainsKey(meshName)) { continue; } warp_Object faceObj = new warp_Object(); for (int j = 0; j < face.Vertices.Count; j++) { Vertex v = face.Vertices[j]; warp_Vector pos = ConvertVector(v.Position); warp_Vertex vert = new warp_Vertex(pos, 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 && primScaleLenSquared > m_texturePrimSize * m_texturePrimSize) { materialName = GetOrCreateMaterial(renderer, faceColor, teFace.TextureID); } else { materialName = GetOrCreateMaterial(renderer, faceColor); } warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.GetWorldRotation()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); faceObj.transform(m); faceObj.setPos(primPos); faceObj.scaleSelf(prim.Scale.X, prim.Scale.Z, prim.Scale.Y); renderer.Scene.addObject(meshName, faceObj); renderer.SetObjectMaterial(meshName, materialName); } }
/// <summary> /// Creates a faceted mesh from a primitive. /// </summary> /// <param name="Client">the client to use for meshing</param> /// <param name="primitive">the primitive to convert</param> /// <param name="mesher">the mesher to use</param> /// <param name="facetedMesh">a reference to an output facted mesh object</param> /// <param name="millisecondsTimeout">the services timeout</param> /// <returns>true if the mesh could be created successfully</returns> public static bool MakeFacetedMesh(GridClient Client, Primitive primitive, MeshmerizerR mesher, ref FacetedMesh facetedMesh, uint millisecondsTimeout) { if (primitive.Sculpt == null || primitive.Sculpt.SculptTexture.Equals(UUID.Zero)) { facetedMesh = mesher.GenerateFacetedMesh(primitive, DetailLevel.Highest); return(true); } if (!primitive.Sculpt.Type.Equals(SculptType.Mesh)) { byte[] assetData = null; switch (!Client.Assets.Cache.HasAsset(primitive.Sculpt.SculptTexture)) { case true: Locks.ClientInstanceAssetsLock.EnterReadLock(); var ImageDownloadedEvent = new ManualResetEventSlim(false); Client.Assets.RequestImage(primitive.Sculpt.SculptTexture, (state, args) => { if (!state.Equals(TextureRequestState.Finished)) { return; } assetData = args.AssetData; ImageDownloadedEvent.Set(); }); if (!ImageDownloadedEvent.Wait((int)millisecondsTimeout)) { Locks.ClientInstanceAssetsLock.ExitReadLock(); return(false); } Locks.ClientInstanceAssetsLock.ExitReadLock(); break; default: assetData = Client.Assets.Cache.GetCachedAssetBytes(primitive.Sculpt.SculptTexture); break; } Image image; ManagedImage managedImage; switch (!OpenJPEG.DecodeToImage(assetData, out managedImage)) { case true: return(false); default: if ((managedImage.Channels & ManagedImage.ImageChannels.Alpha) != 0) { managedImage.ConvertChannels(managedImage.Channels & ~ManagedImage.ImageChannels.Alpha); } image = LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA())); break; } facetedMesh = mesher.GenerateFacetedSculptMesh(primitive, (Bitmap)image, DetailLevel.Highest); return(true); } FacetedMesh localFacetedMesh = null; var MeshDownloadedEvent = new ManualResetEventSlim(false); Locks.ClientInstanceAssetsLock.EnterReadLock(); Client.Assets.RequestMesh(primitive.Sculpt.SculptTexture, (success, meshAsset) => { FacetedMesh.TryDecodeFromAsset(primitive, meshAsset, DetailLevel.Highest, out localFacetedMesh); MeshDownloadedEvent.Set(); }); if (!MeshDownloadedEvent.Wait((int)millisecondsTimeout)) { Locks.ClientInstanceAssetsLock.ExitReadLock(); return(false); } Locks.ClientInstanceAssetsLock.ExitReadLock(); switch (localFacetedMesh != null) { case true: facetedMesh = localFacetedMesh; return(true); default: return(false); } }
private void UpdatePrimBlocking(Primitive prim) { FacetedMesh mesh = null; FacetedMesh existingMesh = null; lock (Prims) { if (Prims.ContainsKey(prim.LocalID)) { existingMesh = Prims[prim.LocalID]; } } if (prim.Textures == null) { return; } try { if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero) { if (prim.Sculpt.Type != SculptType.Mesh) { // Regular sculptie Image img = null; if (!LoadTexture(prim.Sculpt.SculptTexture, ref img, true)) { return; } mesh = renderer.GenerateFacetedSculptMesh(prim, (Bitmap)img, DetailLevel.Highest); } else { // Mesh AutoResetEvent gotMesh = new AutoResetEvent(false); bool meshSuccess = false; Client.Assets.RequestMesh(prim.Sculpt.SculptTexture, (success, meshAsset) => { if (!success || !FacetedMesh.TryDecodeFromAsset(prim, meshAsset, DetailLevel.Highest, out mesh)) { Logger.Log("Failed to fetch or decode the mesh asset", Helpers.LogLevel.Warning, Client); } else { meshSuccess = true; } gotMesh.Set(); }); if (!gotMesh.WaitOne(20 * 1000, false)) { return; } if (!meshSuccess) { return; } } } else { mesh = renderer.GenerateFacetedMesh(prim, DetailLevel.Highest); } } catch { return; } // Create a FaceData struct for each face that stores the 3D data // in a OpenGL friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; FaceData data = new FaceData { Vertices = new float[face.Vertices.Count * 3], Normals = new float[face.Vertices.Count * 3] }; // Vertices for this face for (int k = 0; k < face.Vertices.Count; k++) { data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X; data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y; data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z; data.Normals[k * 3 + 0] = face.Vertices[k].Normal.X; data.Normals[k * 3 + 1] = face.Vertices[k].Normal.Y; data.Normals[k * 3 + 2] = face.Vertices[k].Normal.Z; } // Indices for this face data.Indices = face.Indices.ToArray(); // Texture transform for this face Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j); renderer.TransformTexCoords(face.Vertices, face.Center, teFace, prim.Scale); // Texcoords for this face data.TexCoords = new float[face.Vertices.Count * 2]; for (int k = 0; k < face.Vertices.Count; k++) { data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X; data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y; } // Set the UserData for this face to our FaceData struct face.UserData = data; mesh.Faces[j] = face; if (existingMesh != null && j < existingMesh.Faces.Count && existingMesh.Faces[j].TextureFace.TextureID == teFace.TextureID && ((FaceData)existingMesh.Faces[j].UserData).TextureInfo.TexturePointer != 0 ) { FaceData existingData = (FaceData)existingMesh.Faces[j].UserData; data.TextureInfo.TexturePointer = existingData.TextureInfo.TexturePointer; } else { var textureItem = new TextureLoadItem() { Data = data, Prim = prim, TeFace = teFace }; PendingTextures.Enqueue(textureItem); } } lock (Prims) { Prims[prim.LocalID] = mesh; } SafeInvalidate(); }
void CreatePrim(WarpRenderer renderer, ISceneChildEntity prim, bool texturePrims) { try { if ((PCode)prim.Shape.PCode != PCode.Prim) { return; } if (prim.Scale.LengthSquared() < MIN_PRIM_SIZE * MIN_PRIM_SIZE) { return; } Primitive omvPrim = prim.Shape.ToOmvPrimitive(prim.OffsetPosition, prim.GetRotationOffset()); FacetedMesh renderMesh = null; // Are we dealing with a sculptie or mesh? if (omvPrim.Sculpt != null && omvPrim.Sculpt.SculptTexture != UUID.Zero) { // Try fetching 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 { Image sculpt = m_imgDecoder.DecodeToImage(sculptAsset); if (sculpt != null) { renderMesh = m_primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); sculpt.Dispose(); } } sculptAsset = null; } else { // missing sculpt data... replace with something renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } } else // Prim { renderMesh = m_primMesher.GenerateFacetedMesh(omvPrim, DetailLevel.Medium); } if (renderMesh == null) { return; } warp_Vector primPos = ConvertVector(prim.GetWorldPosition()); warp_Quaternion primRot = ConvertQuaternion(prim.GetRotationOffset()); warp_Matrix m = warp_Matrix.quaternionMatrix(primRot); if (prim.ParentID != 0) { ISceneEntity group = m_scene.GetGroupByPrim(prim.LocalId); if (group != null) { m.transform(warp_Matrix.quaternionMatrix(ConvertQuaternion(group.RootChild.GetRotationOffset()))); } } warp_Vector primScale = ConvertVector(prim.Scale); string primID = prim.UUID.ToString(); // Create the prim faces for (int i = 0; i < renderMesh.Faces.Count; i++) { Face renderFace = renderMesh.Faces [i]; string meshName = primID + "-Face-" + i; warp_Object faceObj = new warp_Object(renderFace.Vertices.Count, renderFace.Indices.Count / 3); foreach (Vertex v in renderFace.Vertices) { 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 < renderFace.Indices.Count;) { faceObj.addTriangle( renderFace.Indices [j++], renderFace.Indices [j++], renderFace.Indices [j++]); } Primitive.TextureEntryFace teFace = prim.Shape.Textures.GetFace((uint)i); string materialName; Color4 faceColor = GetFaceColor(teFace); if (texturePrims && (prim.Scale.LengthSquared() > 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); faceObj = null; } renderMesh.Faces.Clear(); renderMesh = null; } catch (Exception ex) { MainConsole.Instance.Warn("[WarpTile generator]: Exception creating prim, " + ex); } }
public PrimDisplayData ExtractPrimMesh(SceneObjectPart part, GroupLoader.LoaderParams parms, HashSet <UUID> fullPermTextures) { Primitive prim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); //always generate at scale 1.0 and export the true scale for each part prim.Scale = new Vector3(1, 1, 1); FacetedMesh mesh; try { if (prim.Sculpt != null && prim.Sculpt.SculptTexture != UUID.Zero) { if (prim.Sculpt.Type != SculptType.Mesh) { // Regular sculptie Image img = null; if (!LoadTexture(prim.Sculpt.SculptTexture, ref img, true)) { return(null); } mesh = _renderer.GenerateFacetedSculptMesh(prim, (Bitmap)img, DetailLevel.Highest); img.Dispose(); } else { // Mesh var meshAsset = _stratus.RequestAssetSync(prim.Sculpt.SculptTexture); if (!FacetedMesh.TryDecodeFromAsset(prim, new OpenMetaverse.Assets.AssetMesh(prim.Sculpt.SculptTexture, meshAsset.Data), DetailLevel.Highest, out mesh)) { return(null); } } } else { mesh = _renderer.GenerateFacetedMesh(prim, DetailLevel.Highest); } } catch { return(null); } // Create a FaceData struct for each face that stores the 3D data // in a OpenGL friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; PrimFace.FaceData data = new PrimFace.FaceData(); // Vertices for this face data.Vertices = new float[face.Vertices.Count * 3]; data.Normals = new float[face.Vertices.Count * 3]; for (int k = 0; k < face.Vertices.Count; k++) { data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X; data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y; data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z; data.Normals[k * 3 + 0] = face.Vertices[k].Normal.X; data.Normals[k * 3 + 1] = face.Vertices[k].Normal.Y; data.Normals[k * 3 + 2] = face.Vertices[k].Normal.Z; } // Indices for this face data.Indices = face.Indices.ToArray(); // Texture transform for this face Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j); //not sure where this bug is coming from, but in order for sculpt textures //to line up, we need to flip V here if (prim.Sculpt != null && prim.Sculpt.Type != SculptType.None && prim.Sculpt.Type != SculptType.Mesh) { teFace.RepeatV *= -1.0f; } _renderer.TransformTexCoords(face.Vertices, face.Center, teFace, prim.Scale); // Texcoords for this face data.TexCoords = new float[face.Vertices.Count * 2]; for (int k = 0; k < face.Vertices.Count; k++) { data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X; data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y; } if (((parms.Checks & LoaderChecks.TexturesMustBeFullPerm) != 0)) { if (teFace.TextureID != UUID.Zero && !fullPermTextures.Contains(teFace.TextureID)) { teFace.TextureID = UUID.Zero; } } //store the actual texture data.TextureInfo = new PrimFace.TextureInfo { TextureID = teFace.TextureID }; // Set the UserData for this face to our FaceData struct face.UserData = data; mesh.Faces[j] = face; } var pos = part.IsRootPart() ? part.RawGroupPosition : part.OffsetPosition; return(new PrimDisplayData { Mesh = mesh, IsRootPrim = part.IsRootPart(), OffsetPosition = pos, OffsetRotation = part.RotationOffset, Scale = part.Scale, ShapeHash = _objectHasher.GetMeshShapeHash(part.Shape), MaterialHash = _objectHasher.GetMeshMaterialHash(prim), LinkNum = part.LinkNum }); }