void Objects_OnObjectUpdate(object sender, PrimEventArgs e) { //leave tree out temporarily. Radegast doesn't implement tree rendering yet. if (e.Prim.PrimData.PCode != PCode.Prim) { Debug.Log("Receive " + e.Prim.PrimData.PCode.ToString()); return; } FacetedMesh mesh = null; //FIXME : need to update prims? if (objects.ContainsKey(e.Prim.LocalID)) { Debug.Log("receive prim with LocalID " + e.Prim.LocalID.ToString() + " again!"); return; } if (e.Prim.Sculpt != null) { //leave sculpt prim out temporarily } else { mesh = R.GenerateFacetedMesh(e.Prim, DetailLevel.Highest); lock (newPrims) { newPrims[e.Prim.LocalID] = mesh; } foreach (Face face in mesh.Faces) { DownloadTexture(face.TextureFace.TextureID); } } }
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 cboPrim_SelectedIndexChanged(object sender, EventArgs e) { CurrentPrim = (FacetedMesh)cboPrim.Items[cboPrim.SelectedIndex]; PopulateFaceCombobox(); glControl.Invalidate(); }
private void RenderText() { lock (Prims) { int primNr = 0; foreach (FacetedMesh mesh in Prims.Values) { primNr++; Primitive prim = mesh.Prim; if (string.IsNullOrEmpty(prim.Text)) { continue; } string text = System.Text.RegularExpressions.Regex.Replace(prim.Text, "(\r?\n)+", "\n"); OpenTK.Vector3 screenPos = OpenTK.Vector3.Zero; OpenTK.Vector3 primPos = OpenTK.Vector3.Zero; // Is it child prim FacetedMesh parent = null; if (Prims.TryGetValue(prim.ParentID, out parent)) { var newPrimPos = prim.Position * Matrix4.CreateFromQuaternion(parent.Prim.Rotation); primPos = new OpenTK.Vector3(newPrimPos.X, newPrimPos.Y, newPrimPos.Z); } primPos.Z += prim.Scale.Z * 0.8f; if (!Math3D.GluProject(primPos, ModelMatrix, ProjectionMatrix, Viewport, out screenPos)) { continue; } screenPos.Y = glControl.Height - screenPos.Y; textRendering.Begin(); Color color = Color.FromArgb((int)(prim.TextColor.A * 255), (int)(prim.TextColor.R * 255), (int)(prim.TextColor.G * 255), (int)(prim.TextColor.B * 255)); TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.Top; using (Font f = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular)) { var size = TextRendering.Measure(text, f, flags); screenPos.X -= size.Width / 2; screenPos.Y -= size.Height; // Shadow if (color != Color.Black) { textRendering.Print(text, f, Color.Black, new Rectangle((int)screenPos.X + 1, (int)screenPos.Y + 1, size.Width, size.Height), flags); } textRendering.Print(text, f, color, new Rectangle((int)screenPos.X, (int)screenPos.Y, size.Width, size.Height), flags); } textRendering.End(); } } }
List <int> GetFacesWithMaterial(FacetedMesh obj, MaterialInfo mat) { var ret = new List <int>(); for (int face_num = 0; face_num < obj.Faces.Count; face_num++) { if (mat == GetMaterial(obj.Faces[(int)face_num].TextureFace)) { ret.Add(face_num); } } return(ret); }
private bool TryPick(int x, int y, out FacetedMesh picked, out int faceID) { // Save old attributes GL.PushAttrib(AttribMask.AllAttribBits); // Disable some attributes to make the objects flat / solid color when they are drawn GL.Disable(EnableCap.Fog); GL.Disable(EnableCap.Texture2D); GL.Disable(EnableCap.Dither); GL.Disable(EnableCap.Lighting); GL.Disable(EnableCap.LineStipple); GL.Disable(EnableCap.PolygonStipple); GL.Disable(EnableCap.CullFace); GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.AlphaTest); Render(true); byte[] color = new byte[4]; GL.ReadPixels(x, glControl.Height - y, 1, 1, PixelFormat.Rgba, PixelType.UnsignedByte, color); GL.PopAttrib(); int primID = Utils.BytesToUInt16(color, 0); faceID = color[2]; picked = null; lock (Prims) { foreach (var mesh in Prims.Values) { foreach (var face in mesh.Faces) { if (((FaceData)face.UserData).PickingID == primID) { picked = mesh; break; } } if (picked != null) { break; } } } return(picked != null); }
/// <summary> /// Returns a hash value calculated from face parameters that would affect /// the appearance of the mesh faces but not their shape /// </summary> /// <param name="faces"></param> /// <returns></returns> public ulong GetMeshMaterialHash(FacetedMesh mesh, Primitive prim) { ulong hash = 5381; var numFaces = mesh.Faces.Count; for (int i = 0; i < numFaces; i++) { Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)i); hash = GetMaterialFaceHash(hash, teFace); } return(hash); }
void Objects_OnObjectUpdate(object sender, PrimEventArgs e) { //leave other regions out temporarily if (e.Simulator.Handle != Client.Network.CurrentSim.Handle) { return; } //leave tree out temporarily. Radegast doesn't implement tree rendering yet. if (e.Prim.PrimData.PCode != PCode.Prim) { //Debug.Log("Receive " + e.Prim.PrimData.PCode.ToString()); return; } //FIXME : need to update prims? if (objects.ContainsKey(e.Prim.LocalID)) { //Debug.Log ("receive prim with LocalID " + e.Prim.LocalID.ToString() + " again!"); return; } if (e.Prim.Sculpt != null) { //leave sculpt prim out temporarily } else { FacetedMesh mesh = Utility.R.GenerateFacetedMesh(e.Prim, DetailLevel.Highest); lock (newPrims) { newPrims[e.Prim.LocalID] = mesh; } if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) { foreach (Face face in mesh.Faces) { m_textures.DownloadTexture(face.TextureFace.TextureID); } } } }
List <MaterialInfo> GetMaterials(FacetedMesh obj) { var ret = new List <MaterialInfo>(); for (int face_num = 0; face_num < obj.Faces.Count; face_num++) { var te = obj.Faces[(int)face_num].TextureFace; if (SkipTransparentFaces && te.RGBA.A < 0.01f) { continue; } var mat = GetMaterial(te); if (!ret.Contains(mat)) { ret.Add(mat); } } return(ret); }
private void XmlObjectLoadedHandler(OpenMetaverse.Assets.AssetPrim linkset, long bytesRead, long totalBytes) { Prims = new List <FacetedMesh>(linkset.Children.Count + 1); Primitive parent = linkset.Parent.ToPrimitive(); { FacetedMesh mesh = null; if (parent.Sculpt == null || parent.Sculpt.SculptTexture.IsZero()) { mesh = Render.Plugin.GenerateFacetedMesh(parent, DetailLevel.Highest); } if (mesh != null) { LoadMesh(mesh, null); } } for (int i = 0; i < linkset.Children.Count; i++) { Primitive child = linkset.Children[i].ToPrimitive(); FacetedMesh mesh = null; if (parent.Sculpt == null || child.Sculpt.SculptTexture.IsZero()) { mesh = Render.Plugin.GenerateFacetedMesh(child, DetailLevel.Highest); } if (mesh != null) { LoadMesh(mesh, null); } } PopulatePrimCombobox(); glControl.Invalidate(); }
private void LoadDebugPrim() { Prims = new List <FacetedMesh>(); Primitive prim = new Primitive(); prim.Textures = new Primitive.TextureEntry(UUID.Zero); prim.Scale = Vector3.One; prim.PrimData = ObjectManager.BuildBasicShape(PrimType.Cylinder); prim.PrimData.ProfileHollow = 0.95f; SimpleMesh simpleMesh = Render.Plugin.GenerateSimpleMesh(prim, DetailLevel.High); FacetedMesh facetedMesh = new FacetedMesh(); facetedMesh.Faces = new List <Face> { new Face { Vertices = simpleMesh.Vertices, Indices = simpleMesh.Indices } }; facetedMesh.Path = simpleMesh.Path; facetedMesh.Profile = simpleMesh.Profile; facetedMesh.Prim = prim; LoadMesh(facetedMesh, "."); PopulatePrimCombobox(); glControl.Invalidate(); }
private void LoadSculpt(string filename) { // Try to parse this as an image file Image sculptTexture = Image.FromFile(filename); Primitive prim = new Primitive(); prim.PrimData = ObjectManager.BuildBasicShape(PrimType.Sculpt); prim.Sculpt = new Primitive.SculptData { SculptTexture = UUID.Random(), Type = SculptType.Sphere }; prim.Textures = new Primitive.TextureEntry(UUID.Zero); prim.Scale = Vector3.One * 3f; FacetedMesh mesh = Render.Plugin.GenerateFacetedSculptMesh(prim, (Bitmap)sculptTexture, DetailLevel.Highest); if (mesh != null) { Prims = new List <FacetedMesh>(1); LoadMesh(mesh, null); } glControl.Invalidate(); }
public RenderingMesh GetRenderingMesh(LLPrimitive prim, DetailLevel lod) { RenderingMesh mesh; ulong physicsKey = prim.GetPhysicsKey(); // Try a cache lookup first if (m_meshCache != null && m_meshCache.TryGetRenderingMesh(physicsKey, lod, out mesh)) { return(mesh); } // Can't go any further without a prim renderer if (m_renderer == null) { return(null); } // Convert our DetailLevel to the OpenMetaverse.Rendering DetailLevel OpenMetaverse.Rendering.DetailLevel detailLevel; switch (lod) { case DetailLevel.Low: detailLevel = OpenMetaverse.Rendering.DetailLevel.Low; break; case DetailLevel.Medium: detailLevel = OpenMetaverse.Rendering.DetailLevel.Medium; break; case DetailLevel.High: detailLevel = OpenMetaverse.Rendering.DetailLevel.High; break; case DetailLevel.Highest: default: detailLevel = OpenMetaverse.Rendering.DetailLevel.Highest; break; } FacetedMesh facetedMesh = null; if (prim.Prim.Sculpt != null && prim.Prim.Sculpt.SculptTexture != UUID.Zero) { // Sculpty meshing Bitmap sculptTexture = GetSculptMap(prim.Prim.Sculpt.SculptTexture); if (sculptTexture != null) { facetedMesh = m_renderer.GenerateFacetedSculptMesh(prim.Prim, sculptTexture, detailLevel); } } else { // Basic prim meshing facetedMesh = m_renderer.GenerateFacetedMesh(prim.Prim, detailLevel); } if (facetedMesh != null) { #region FacetedMesh to RenderingMesh Conversion mesh = new RenderingMesh(); mesh.Faces = new RenderingMesh.Face[facetedMesh.Faces.Count]; for (int i = 0; i < facetedMesh.Faces.Count; i++) { Face face = facetedMesh.Faces[i]; Vertex[] vertices = new Vertex[face.Vertices.Count]; for (int j = 0; j < face.Vertices.Count; j++) { OpenMetaverse.Rendering.Vertex omvrVertex = face.Vertices[j]; vertices[j] = new Vertex { Position = omvrVertex.Position, Normal = omvrVertex.Normal, TexCoord = omvrVertex.TexCoord }; } ushort[] indices = face.Indices.ToArray(); mesh.Faces[i] = new RenderingMesh.Face { Vertices = vertices, Indices = indices }; } #endregion FacetedMesh to RenderingMesh Conversion // Store the result in the mesh cache, if we have one if (m_meshCache != null) { m_meshCache.StoreRenderingMesh(physicsKey, lod, mesh); } return(mesh); } else { return(null); } }
/// <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(); }
private void RenderObjects(RenderPass pass) { lock (Prims) { int primNr = 0; foreach (FacetedMesh mesh in Prims.Values) { primNr++; Primitive prim = mesh.Prim; // Individual prim matrix GL.PushMatrix(); if (prim.ParentID == RootPrimLocalID) { FacetedMesh parent = null; if (Prims.TryGetValue(prim.ParentID, out parent)) { // Apply prim translation and rotation relative to the root prim GL.MultMatrix(Math3D.CreateRotationMatrix(parent.Prim.Rotation)); //GL.MultMatrixf(Math3D.CreateTranslationMatrix(parent.Prim.Position)); } // Prim roation relative to root GL.MultMatrix(Math3D.CreateTranslationMatrix(prim.Position)); } // Prim roation GL.MultMatrix(Math3D.CreateRotationMatrix(prim.Rotation)); // Prim scaling GL.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z); // Draw the prim faces for (int j = 0; j < mesh.Faces.Count; j++) { Primitive.TextureEntryFace teFace = mesh.Prim.Textures.FaceTextures[j]; Face face = mesh.Faces[j]; FaceData data = (FaceData)face.UserData; if (teFace == null) { teFace = mesh.Prim.Textures.DefaultTexture; } if (pass == RenderPass.Picking) { data.PickingID = primNr; var primNrBytes = Utils.Int16ToBytes((short)primNr); var faceColor = new byte[] { primNrBytes[0], primNrBytes[1], (byte)j, 255 }; GL.Color4(faceColor); } else { bool belongToAlphaPass = (teFace.RGBA.A < 0.99) || data.TextureInfo.HasAlpha; if (belongToAlphaPass && pass != RenderPass.Alpha) { continue; } if (!belongToAlphaPass && pass == RenderPass.Alpha) { continue; } // Don't render transparent faces if (teFace.RGBA.A <= 0.01f) { continue; } switch (teFace.Shiny) { case Shininess.High: GL.Material(MaterialFace.Front, MaterialParameter.Shininess, 94f); break; case Shininess.Medium: GL.Material(MaterialFace.Front, MaterialParameter.Shininess, 64f); break; case Shininess.Low: GL.Material(MaterialFace.Front, MaterialParameter.Shininess, 24f); break; case Shininess.None: default: GL.Material(MaterialFace.Front, MaterialParameter.Shininess, 0f); break; } var faceColor = new float[] { teFace.RGBA.R, teFace.RGBA.G, teFace.RGBA.B, teFace.RGBA.A }; GL.Color4(faceColor); GL.Material(MaterialFace.Front, MaterialParameter.AmbientAndDiffuse, faceColor); GL.Material(MaterialFace.Front, MaterialParameter.Specular, faceColor); if (data.TextureInfo.TexturePointer != 0) { GL.Enable(EnableCap.Texture2D); } else { GL.Disable(EnableCap.Texture2D); } // Bind the texture GL.BindTexture(TextureTarget.Texture2D, data.TextureInfo.TexturePointer); } GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, data.TexCoords); GL.VertexPointer(3, VertexPointerType.Float, 0, data.Vertices); GL.NormalPointer(NormalPointerType.Float, 0, data.Normals); GL.DrawElements(PrimitiveType.Triangles, data.Indices.Length, DrawElementsType.UnsignedShort, data.Indices); } // Pop the prim matrix GL.PopMatrix(); } } }
/// <summary> /// Calculate a hash that takes both the prim shape and materials into account /// </summary> public ulong GetPrimHash(ulong hash, PrimitiveBaseShape shape, DetailLevel lod, FacetedMesh mesh, Primitive prim) { hash = Murmur2.Hash(GetMeshShapeHash(shape, lod), hash); return(Murmur2.Hash(GetMeshMaterialHash(mesh, prim), hash)); }
private void openPrimXMLToolStripMenuItem1_Click(object sender, EventArgs e) { Prims = null; OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Prim Package (*.zip)|*.zip"; if (dialog.ShowDialog() == DialogResult.OK) { string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); try { // Create a temporary directory Directory.CreateDirectory(tempPath); FastZip fastzip = new FastZip(); fastzip.ExtractZip(dialog.FileName, tempPath, String.Empty); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } // Check for the prims.xml file string primsFile = System.IO.Path.Combine(tempPath, "prims.xml"); if (!File.Exists(primsFile)) { MessageBox.Show("prims.xml not found in the archive"); return; } LLSD llsd = null; try { llsd = LLSDParser.DeserializeXml(File.ReadAllText(primsFile)); } catch (Exception ex) { MessageBox.Show(ex.Message); } if (llsd != null && llsd.Type == LLSDType.Map) { List <Primitive> primList = Helpers.LLSDToPrimList(llsd); Prims = new List <FacetedMesh>(primList.Count); for (int i = 0; i < primList.Count; i++) { // TODO: Can't render sculpted prims without the textures if (primList[i].Sculpt.SculptTexture != UUID.Zero) { continue; } Primitive prim = primList[i]; FacetedMesh mesh = Render.Plugin.GenerateFacetedMesh(prim, DetailLevel.Highest); // Create a FaceData struct for each face that stores the 3D data // in a Tao.OpenGL friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; FaceData data = new FaceData(); // Vertices for this face data.Vertices = 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; } // Indices for this face data.Indices = face.Indices.ToArray(); // Texture transform for this face Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j); Render.Plugin.TransformTexCoords(face.Vertices, face.Center, teFace); // 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; } // Texture for this face if (LoadTexture(tempPath, teFace.TextureID, ref data.Texture)) { Bitmap bitmap = new Bitmap(data.Texture); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); Gl.glGenTextures(1, out data.TexturePointer); Gl.glBindTexture(Gl.GL_TEXTURE_2D, data.TexturePointer); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_GENERATE_MIPMAP, Gl.GL_TRUE); Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, Gl.GL_RGB8, bitmap.Width, bitmap.Height, Gl.GL_BGR, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0); bitmap.UnlockBits(bitmapData); bitmap.Dispose(); } // Set the UserData for this face to our FaceData struct face.UserData = data; mesh.Faces[j] = face; } Prims.Add(mesh); } // Setup the dropdown list of prims PopulatePrimCombobox(); glControl.Invalidate(); } else { MessageBox.Show("Failed to load LLSD formatted primitive data from " + dialog.FileName); } Directory.Delete(tempPath); } }
private void LoadPrimPackage(string filename) { string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); try { // Create a temporary directory Directory.CreateDirectory(tempPath); FastZip fastzip = new FastZip(); fastzip.ExtractZip(filename, tempPath, String.Empty); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } // Check for the prims.xml file string primsFile = System.IO.Path.Combine(tempPath, "prims.xml"); if (!File.Exists(primsFile)) { MessageBox.Show("prims.xml not found in the archive"); return; } OSD osd = null; try { osd = OSDParser.DeserializeLLSDXml(File.ReadAllText(primsFile)); } catch (Exception ex) { MessageBox.Show(ex.Message); } if (osd != null && osd.Type == OSDType.Map) { List <Primitive> primList = Helpers.OSDToPrimList(osd); Prims = new List <FacetedMesh>(primList.Count); for (int i = 0; i < primList.Count; i++) { Primitive prim = primList[i]; FacetedMesh mesh = null; if (prim.Sculpt.SculptTexture != UUID.Zero) { Image sculptTexture = null; if (LoadTexture(tempPath, prim.Sculpt.SculptTexture, ref sculptTexture)) { mesh = Render.Plugin.GenerateFacetedSculptMesh(prim, (Bitmap)sculptTexture, DetailLevel.Highest); } } else { mesh = Render.Plugin.GenerateFacetedMesh(prim, DetailLevel.Highest); } if (mesh != null) { LoadMesh(mesh, tempPath); } } // Setup the dropdown list of prims PopulatePrimCombobox(); glControl.Invalidate(); } else { MessageBox.Show("Failed to load LLSD formatted primitive data from " + filename); } Directory.Delete(tempPath); }
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 LoadMesh(FacetedMesh mesh, string basePath) { // Create a FaceData struct for each face that stores the 3D data // in a Tao.OpenGL friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; FaceData data = new FaceData(); // Vertices for this face data.Vertices = 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; } // Indices for this face data.Indices = face.Indices.ToArray(); // Texture transform for this face Primitive.TextureEntryFace teFace = mesh.Prim.Textures.GetFace((uint)j); Render.Plugin.TransformTexCoords(face.Vertices, face.Center, teFace, mesh.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; } // Texture for this face if (!String.IsNullOrEmpty(basePath) && LoadTexture(basePath, teFace.TextureID, ref data.Texture)) { Bitmap bitmap = new Bitmap(data.Texture); bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); Gl.glGenTextures(1, out data.TexturePointer); Gl.glBindTexture(Gl.GL_TEXTURE_2D, data.TexturePointer); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR_MIPMAP_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_GENERATE_MIPMAP, Gl.GL_TRUE); Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D, Gl.GL_RGB8, bitmap.Width, bitmap.Height, Gl.GL_BGR, Gl.GL_UNSIGNED_BYTE, bitmapData.Scan0); bitmap.UnlockBits(bitmapData); bitmap.Dispose(); } // Set the UserData for this face to our FaceData struct face.UserData = data; mesh.Faces[j] = face; } Prims.Add(mesh); }
public void Export(string Filename) { FileName = Filename; MeshedPrims.Clear(); if (string.IsNullOrEmpty(FileName)) { return; } WorkPool.QueueUserWorkItem(sync => { if (ExportTextures) { SaveTextures(); } for (int i = 0; i < Prims.Count; i++) { if (!CanExport(Prims[i])) { continue; } FacetedMesh mesh = MeshPrim(Prims[i]); if (mesh == null) { continue; } for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; Primitive.TextureEntryFace teFace = mesh.Faces[j].TextureFace; if (teFace == null) { continue; } // Sculpt UV vertically flipped compared to prims. Flip back if (Prims[i].Sculpt != null && Prims[i].Sculpt.SculptTexture != UUID.Zero && Prims[i].Sculpt.Type != SculptType.Mesh) { teFace = (Primitive.TextureEntryFace)teFace.Clone(); teFace.RepeatV *= -1; } // Texture transform for this face Mesher.TransformTexCoords(face.Vertices, face.Center, teFace, Prims[i].Scale); } MeshedPrims.Add(mesh); } string msg; if (MeshedPrims.Count == 0) { msg = string.Format("Can export 0 out of {0} prims.{1}{1}Skipping.", Prims.Count, Environment.NewLine); } else { msg = string.Format("Exported {0} out of {1} objects to{2}{2}{3}", MeshedPrims.Count, Prims.Count, Environment.NewLine, FileName); } GenerateCollada(); File.WriteAllText(FileName, DocToString(Doc)); OnProgress(msg); }); }
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 }); }
public static bool MeshesToOBJ(List <FacetedMesh> meshes, string filename) { StringBuilder obj = new StringBuilder(); StringBuilder mtl = new StringBuilder(); FileInfo objFileInfo = new FileInfo(filename); string mtlFilename = objFileInfo.FullName.Substring(objFileInfo.DirectoryName.Length + 1, objFileInfo.FullName.Length - (objFileInfo.DirectoryName.Length + 1) - 4) + ".mtl"; obj.AppendLine("# Created by libprimrender"); obj.AppendLine("mtllib ./" + mtlFilename); obj.AppendLine(); mtl.AppendLine("# Created by libprimrender"); mtl.AppendLine(); for (int i = 0; i < meshes.Count; i++) { FacetedMesh mesh = meshes[i]; for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; if (face.Vertices.Count > 2) { string mtlName = String.Format("material{0}-{1}", i, face.ID); Primitive.TextureEntryFace tex = face.TextureFace; string texName = tex.TextureID.ToString() + ".tga"; // FIXME: Convert the source to TGA (if needed) and copy to the destination float shiny = 0.00f; switch (tex.Shiny) { case Shininess.High: shiny = 1.00f; break; case Shininess.Medium: shiny = 0.66f; break; case Shininess.Low: shiny = 0.33f; break; } obj.AppendFormat("g face{0}-{1}{2}", i, face.ID, Environment.NewLine); mtl.AppendLine("newmtl " + mtlName); mtl.AppendFormat("Ka {0} {1} {2}{3}", tex.RGBA.R, tex.RGBA.G, tex.RGBA.B, Environment.NewLine); mtl.AppendFormat("Kd {0} {1} {2}{3}", tex.RGBA.R, tex.RGBA.G, tex.RGBA.B, Environment.NewLine); //mtl.AppendFormat("Ks {0} {1} {2}{3}"); mtl.AppendLine("Tr " + tex.RGBA.A); mtl.AppendLine("Ns " + shiny); mtl.AppendLine("illum 1"); if (tex.TextureID != UUID.Zero && tex.TextureID != Primitive.TextureEntry.WHITE_TEXTURE) { mtl.AppendLine("map_Kd ./" + texName); } mtl.AppendLine(); // Write the vertices, texture coordinates, and vertex normals for this side for (int k = 0; k < face.Vertices.Count; k++) { Vertex vertex = face.Vertices[k]; #region Vertex Vector3 pos = vertex.Position; // Apply scaling pos *= mesh.Prim.Scale; // Apply rotation pos *= mesh.Prim.Rotation; // The root prim position is sim-relative, while child prim positions are // parent-relative. We want to apply parent-relative translations but not // sim-relative ones if (mesh.Prim.ParentID != 0) { pos += mesh.Prim.Position; } obj.AppendFormat("v {0} {1} {2}{3}", pos.X, pos.Y, pos.Z, Environment.NewLine); #endregion Vertex #region Texture Coord obj.AppendFormat("vt {0} {1}{2}", vertex.TexCoord.X, vertex.TexCoord.Y, Environment.NewLine); #endregion Texture Coord #region Vertex Normal // HACK: Sometimes normals are getting set to <NaN,NaN,NaN> if (!Single.IsNaN(vertex.Normal.X) && !Single.IsNaN(vertex.Normal.Y) && !Single.IsNaN(vertex.Normal.Z)) { obj.AppendFormat("vn {0} {1} {2}{3}", vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z, Environment.NewLine); } else { obj.AppendLine("vn 0.0 1.0 0.0"); } #endregion Vertex Normal } obj.AppendFormat("# {0} vertices{1}", face.Vertices.Count, Environment.NewLine); obj.AppendLine(); obj.AppendLine("usemtl " + mtlName); #region Elements // Write all of the faces (triangles) for this side for (int k = 0; k < face.Indices.Count / 3; k++) { obj.AppendFormat("f -{0}/-{0}/-{0} -{1}/-{1}/-{1} -{2}/-{2}/-{2}{3}", face.Vertices.Count - face.Indices[k * 3 + 0], face.Vertices.Count - face.Indices[k * 3 + 1], face.Vertices.Count - face.Indices[k * 3 + 2], Environment.NewLine); } obj.AppendFormat("# {0} elements{1}", face.Indices.Count / 3, Environment.NewLine); obj.AppendLine(); #endregion Elements } } } try { File.WriteAllText(filename, obj.ToString()); File.WriteAllText(mtlFilename, mtl.ToString()); } catch (Exception) { return(false); } return(true); }
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); } }
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); } }
void AddPolygons(XmlNode mesh, string geomID, string materialID, FacetedMesh obj, List <int> faces_to_include) { var polylist = mesh.AppendChild(Doc.CreateElement("polylist")); polylist.Attributes.Append(Doc.CreateAttribute("material")).InnerText = materialID; // Vertices semantic { var input = polylist.AppendChild(Doc.CreateElement("input")); input.Attributes.Append(Doc.CreateAttribute("semantic")).InnerText = "VERTEX"; input.Attributes.Append(Doc.CreateAttribute("offset")).InnerText = "0"; input.Attributes.Append(Doc.CreateAttribute("source")).InnerText = string.Format("#{0}-{1}", geomID, "vertices"); } // Normals semantic { var input = polylist.AppendChild(Doc.CreateElement("input")); input.Attributes.Append(Doc.CreateAttribute("semantic")).InnerText = "NORMAL"; input.Attributes.Append(Doc.CreateAttribute("offset")).InnerText = "0"; input.Attributes.Append(Doc.CreateAttribute("source")).InnerText = string.Format("#{0}-{1}", geomID, "normals"); } // UV semantic { var input = polylist.AppendChild(Doc.CreateElement("input")); input.Attributes.Append(Doc.CreateAttribute("semantic")).InnerText = "TEXCOORD"; input.Attributes.Append(Doc.CreateAttribute("offset")).InnerText = "0"; input.Attributes.Append(Doc.CreateAttribute("source")).InnerText = string.Format("#{0}-{1}", geomID, "map0"); } // Save indices var vcount = polylist.AppendChild(Doc.CreateElement("vcount")); var p = polylist.AppendChild(Doc.CreateElement("p")); int index_offset = 0; int num_tris = 0; StringBuilder pBuilder = new StringBuilder(); StringBuilder vcountBuilder = new StringBuilder(); for (int face_num = 0; face_num < obj.Faces.Count; face_num++) { var face = obj.Faces[face_num]; if (faces_to_include == null || faces_to_include.Contains(face_num)) { for (int i = 0; i < face.Indices.Count; i++) { int index = index_offset + face.Indices[i]; pBuilder.Append(index); pBuilder.Append(" "); if (i % 3 == 0) { vcountBuilder.Append("3 "); num_tris++; } } } index_offset += face.Vertices.Count; } p.InnerText = pBuilder.ToString().TrimEnd(); vcount.InnerText = vcountBuilder.ToString().TrimEnd(); polylist.Attributes.Append(Doc.CreateAttribute("count")).InnerText = num_tris.ToString(); }
void ProcessPrim(FacetedMesh mesh) { if (objects.ContainsKey(mesh.Prim.LocalID)) { return; } GameObject parent = null; if (mesh.Prim.ParentID != 0) { if (!objects.ContainsKey(mesh.Prim.ParentID)) { if (newPrims.ContainsKey(mesh.Prim.ParentID) == false) { return; //temperarily ignore the prim } ProcessPrim(newPrims[mesh.Prim.ParentID]); } parent = objects[mesh.Prim.ParentID]; } else { parent = primObjects; } GameObject obj = new GameObject(mesh.Prim.LocalID.ToString()); // Create vertices, uv, triangles for EACH FACE that stores the 3D data in Unity3D friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; GameObject faceObj = new GameObject("face" + j.ToString()); faceObj.transform.parent = obj.transform; MeshRenderer mr = (faceObj.AddComponent("MeshRenderer") as MeshRenderer); if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) { UnityEngine.Material mat = m_textures.GetMaterial(face.TextureFace.TextureID); //Texture2D tex = m_textures.GetTexture2D(face.TextureFace.TextureID); if (mat != null) { mr.material = mat; } else { mr.material = m_defaultObjectMat; } } else { mr.material = m_defaultObjectMat; } UnityEngine.Mesh unityMesh = (faceObj.AddComponent("MeshFilter") as MeshFilter).mesh; Utility.MakeMesh(unityMesh, face, 0, face.Vertices.Count - 1, 0, face.Indices.Count - 1, 0); } //second life's child object's position and rotation is local, but scale are global. //So we have to set parent when setting position, and unset parent when setting rotation and scale. //Radegast explains well: //pos = parentPos + obj.InterpolatedPosition * parentRot; //rot = parentRot * obj.InterpolatedRotation; obj.transform.position = parent.transform.position + parent.transform.rotation * new UnityEngine.Vector3(mesh.Prim.Position.X, mesh.Prim.Position.Y, -mesh.Prim.Position.Z); //we invert the z axis, and Second Life rotatation is about right hand, but Unity rotation is about left hand, so we negate the x and y part of the quaternion. //You have to deeply understand the quaternion to understand this. obj.transform.rotation = parent.transform.rotation * new UnityEngine.Quaternion(-mesh.Prim.Rotation.X, -mesh.Prim.Rotation.Y, mesh.Prim.Rotation.Z, mesh.Prim.Rotation.W); obj.transform.localScale = new UnityEngine.Vector3(mesh.Prim.Scale.X, mesh.Prim.Scale.Y, mesh.Prim.Scale.Z); objects[mesh.Prim.LocalID] = obj; obj.transform.parent = primObjects.transform; //Debug.Log("prim " + mesh.Prim.LocalID.ToString() + ": Pos,"+mesh.Prim.Position.ToString() + " Rot,"+mesh.Prim.Rotation.ToString() + " Scale,"+mesh.Prim.Scale.ToString()); //Sadly, when it comes to non-uniform scale parent, Unity will skew the child, so we cannot make hierachy of the objects. }
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); } }
void ProcessPrim(FacetedMesh mesh) { if (objects.ContainsKey(mesh.Prim.LocalID)) { return; } GameObject obj = new GameObject(mesh.Prim.LocalID.ToString()); GameObject parent = null; if (mesh.Prim.ParentID != 0) { if (!objects.ContainsKey(mesh.Prim.ParentID)) { if (newPrims.ContainsKey(mesh.Prim.ParentID) == false) { Debug.Break(); } ProcessPrim(newPrims[mesh.Prim.ParentID]); //it seems that the parent is received before children } parent = objects[mesh.Prim.ParentID]; } else { parent = primObjects; } // Create vertices, uv, triangles for EACH FACE that stores the 3D data in Unity3D friendly format for (int j = 0; j < mesh.Faces.Count; j++) { Face face = mesh.Faces[j]; GameObject faceObj = new GameObject("face" + j.ToString()); faceObj.transform.parent = obj.transform; UnityEngine.Material mat = (faceObj.AddComponent("MeshRenderer") as MeshRenderer).material; if (textures.ContainsKey(face.TextureFace.TextureID)) { mat.mainTexture = textures[face.TextureFace.TextureID]; } else if (bitmaps.ContainsKey(face.TextureFace.TextureID)) { Texture2D tex = Bitmap2Texture2D(bitmaps[face.TextureFace.TextureID]); tex.wrapMode = TextureWrapMode.Repeat; textures[face.TextureFace.TextureID] = tex; mat.mainTexture = tex; bitmaps.Remove(face.TextureFace.TextureID); } else { mat = m; } UnityEngine.Mesh unityMesh = (faceObj.AddComponent("MeshFilter") as MeshFilter).mesh; MakeMesh(unityMesh, face, 0, face.Vertices.Count - 1, 0, face.Indices.Count - 1, 0); } //second life's child object's position and rotation is local, but scale are global. //So we have to set parent when setting position, and unset parent when setting rotation and scale. //Radegast explains well: //pos = parentPos + obj.InterpolatedPosition * parentRot; //rot = parentRot * obj.InterpolatedRotation; obj.transform.position = parent.transform.position + parent.transform.rotation * new UnityEngine.Vector3(mesh.Prim.Position.X, mesh.Prim.Position.Y, -mesh.Prim.Position.Z); //we invert the z axis, and Second Life rotatation is about right hand, but Unity rotation is about left hand, so we negate the x and y part of the quaternion. //You have to deeply understand the quaternion to understand this. obj.transform.rotation = parent.transform.rotation * new UnityEngine.Quaternion(-mesh.Prim.Rotation.X, -mesh.Prim.Rotation.Y, mesh.Prim.Rotation.Z, mesh.Prim.Rotation.W); obj.transform.localScale = new UnityEngine.Vector3(mesh.Prim.Scale.X, mesh.Prim.Scale.Y, mesh.Prim.Scale.Z); objects[mesh.Prim.LocalID] = obj; obj.transform.parent = primObjects.transform; //Debug.Log("prim " + mesh.Prim.LocalID.ToString() + ": Pos,"+mesh.Prim.Position.ToString() + " Rot,"+mesh.Prim.Rotation.ToString() + " Scale,"+mesh.Prim.Scale.ToString()); //Sadly, when it comes to non-uniform scale parent, Unity will skew the child, so we cannot make hierachy of the objects. }