OSDN Git Service

* Implemented loadStuffReallyFast() :P
authorLatif Khalifa <latifer@streamgrid.net>
Wed, 27 Jul 2011 10:18:13 +0000 (10:18 +0000)
committerLatif Khalifa <latifer@streamgrid.net>
Wed, 27 Jul 2011 10:18:13 +0000 (10:18 +0000)
* Reenabled avatar rendering
* Fixed nuking of opengl memeory while loading textures

git-svn-id: https://radegast.googlecode.com/svn/trunk@1012 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/GUI/Rendering/Rendering.cs
Radegast/GUI/Rendering/RenderingHelpers.cs

index e06f160..140dd1f 100644 (file)
@@ -105,7 +105,7 @@ namespace Radegast.Rendering
         /// <summary>\r
         /// Render avatars\r
         /// </summary>\r
-        public bool AvatarRenderingEnabled = false;\r
+        public bool AvatarRenderingEnabled = true;\r
 \r
         /// <summary>\r
         /// Show avatar skeloton\r
@@ -131,6 +131,11 @@ namespace Radegast.Rendering
         MeshmerizerR renderer;\r
         OpenTK.Graphics.GraphicsMode GLMode = null;\r
         AutoResetEvent TextureThreadContextReady = new AutoResetEvent(false);\r
+        \r
+        delegate void GenericTask();\r
+        BlockingQueue<GenericTask> PendingTasks = new BlockingQueue<GenericTask>();\r
+        Thread genericTaskThread;\r
+\r
         BlockingQueue<TextureLoadItem> PendingTextures = new BlockingQueue<TextureLoadItem>();\r
 \r
         bool hasMipmap;\r
@@ -176,6 +181,11 @@ namespace Radegast.Rendering
 \r
             this.instance = instance;\r
 \r
+            genericTaskThread = new Thread(new ThreadStart(GenericTaskRunner));\r
+            genericTaskThread.IsBackground = true;\r
+            genericTaskThread.Name = "Generic task queue";\r
+            genericTaskThread.Start();\r
+\r
             renderer = new MeshmerizerR();\r
             renderTimer = new System.Diagnostics.Stopwatch();\r
             renderTimer.Start();\r
@@ -217,6 +227,13 @@ namespace Radegast.Rendering
             Client.Avatars.AvatarAppearance -= new EventHandler<AvatarAppearanceEventArgs>(Avatars_AvatarAppearance);\r
             Client.Appearance.AppearanceSet -= new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);\r
 \r
+            PendingTasks.Close();\r
+            if (genericTaskThread != null)\r
+            {\r
+                genericTaskThread.Join(2000);\r
+                genericTaskThread = null;\r
+            }\r
+\r
             if (instance.Netcom != null)\r
             {\r
                 Instance.Netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);\r
@@ -970,6 +987,7 @@ namespace Radegast.Rendering
 \r
                     bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);\r
                     item.Data.TextureInfo.TexturePointer = GLLoadImage(bitmap, item.Data.TextureInfo.HasAlpha);\r
+                    GL.Flush();\r
                     bitmap.Dispose();\r
                 }\r
 \r
@@ -983,6 +1001,20 @@ namespace Radegast.Rendering
         }\r
         #endregion Texture thread\r
 \r
+        void GenericTaskRunner()\r
+        {\r
+            PendingTasks.Open();\r
+            Logger.DebugLog("Started generic task thread");\r
+\r
+            while (true)\r
+            {\r
+                GenericTask task = null;\r
+                if (!PendingTasks.Dequeue(Timeout.Infinite, ref task)) break;\r
+                task.Invoke();\r
+            }\r
+            Logger.DebugLog("Generic task thread exited");\r
+        }\r
+\r
         void LoadCurrentPrims()\r
         {\r
             if (!Client.Network.Connected) return;\r
@@ -1193,7 +1225,11 @@ namespace Radegast.Rendering
             // This is a FIR filter known as a MMA or Modified Mean Average, using a 20 point sampling width\r
             advTimerTick = ((19 * advTimerTick) + lastFrameTime) / 20;\r
             // Stats in window title for now\r
-            Text = String.Format("Scene Viewer: FPS {0:000.00} Texture decode queue: {1}", 1d / advTimerTick, PendingTextures.Count);\r
+            Text = String.Format("Scene Viewer: FPS {0:000.00} Texture decode queue: {1}, Sculpt queue: {2}",\r
+                1d / advTimerTick,\r
+                PendingTextures.Count,\r
+                PendingTasks.Count);\r
+\r
 #if TURNS_OUT_PRINTER_IS_EXPENISVE\r
             int posX = glControl.Width - 100;\r
             int posY = 0;\r
@@ -2099,6 +2135,17 @@ namespace Radegast.Rendering
                 {\r
                     if (obj.BasePrim.ParentID != 0) continue;\r
                     if (!obj.Initialized) obj.Initialize();\r
+\r
+                    if (!obj.Meshed)\r
+                    {\r
+                        if (!obj.Meshing && meshingsRequestedThisFrame < 2)\r
+                        {\r
+                            meshingsRequestedThisFrame++;\r
+                            MeshPrim(obj);\r
+                        }\r
+                        continue;\r
+                    }\r
+\r
                     obj.Step(lastFrameTime);\r
 \r
                     if (!obj.PositionCalculated)\r
@@ -2146,6 +2193,17 @@ namespace Radegast.Rendering
                 {\r
                     if (obj.BasePrim.ParentID == 0) continue;\r
                     if (!obj.Initialized) obj.Initialize();\r
+\r
+                    if (!obj.Meshed)\r
+                    {\r
+                        if (!obj.Meshing && meshingsRequestedThisFrame < 2)\r
+                        {\r
+                            meshingsRequestedThisFrame++;\r
+                            MeshPrim(obj);\r
+                        }\r
+                        continue;\r
+                    }\r
+\r
                     obj.Step(lastFrameTime);\r
 \r
                     if (!obj.PositionCalculated)\r
@@ -2327,6 +2385,7 @@ namespace Radegast.Rendering
         }\r
 \r
         int texturesRequestedThisFrame;\r
+        int meshingsRequestedThisFrame;\r
 \r
         private void Render(bool picking)\r
         {\r
@@ -2386,6 +2445,7 @@ namespace Radegast.Rendering
             else\r
             {\r
                 texturesRequestedThisFrame = 0;\r
+                meshingsRequestedThisFrame = 0;\r
 \r
                 // Alpha mask elements, no blending, alpha test for A > 0.5\r
                 GL.Enable(EnableCap.AlphaTest);\r
@@ -2552,8 +2612,10 @@ namespace Radegast.Rendering
             }\r
         }\r
 \r
-        private void MeshPrim(Primitive prim, RenderPrimitive rprim)\r
+        private void CalculateBoundingBox(RenderPrimitive rprim)\r
         {\r
+            Primitive prim = rprim.BasePrim;\r
+\r
             // Calculate bounding volumes for each prim and adjust textures\r
             rprim.BoundingVolume = new BoundingVolume();\r
             for (int j = 0; j < rprim.Faces.Count; j++)\r
@@ -2599,121 +2661,128 @@ namespace Radegast.Rendering
                 // Set the UserData for this face to our FaceData struct\r
                 face.UserData = data;\r
                 rprim.Faces[j] = face;\r
-\r
-                //DownloadTexture(new TextureLoadItem()\r
-                //{\r
-                //    Data = data,\r
-                //    Prim = prim,\r
-                //    TeFace = teFace\r
-                //});\r
-            }\r
-\r
-            lock (Prims)\r
-            {\r
-                Prims[prim.LocalID] = rprim;\r
             }\r
         }\r
 \r
-        private void UpdatePrimBlocking(Primitive prim)\r
+        private void MeshPrim(RenderPrimitive rprim)\r
         {\r
-            if (!RenderingEnabled) return;\r
+            if (rprim.Meshing) return;\r
 \r
-            if (AvatarRenderingEnabled && prim.PrimData.PCode == PCode.Avatar)\r
-            {\r
-                AddAvatarToScene(Client.Network.CurrentSim.ObjectsAvatars[prim.LocalID]);\r
-                return;\r
-            }\r
-\r
-            // Skip foliage\r
-            if (prim.PrimData.PCode != PCode.Prim) return;\r
-            if (!PrimitiveRenderingEnabled) return;\r
-\r
-            if (prim.Textures == null) return;\r
-\r
-            RenderPrimitive rPrim = null;\r
-            if (Prims.TryGetValue(prim.LocalID, out rPrim))\r
-            {\r
-                rPrim.AttachedStateKnown = false;\r
-            }\r
-            else\r
-            {\r
-                rPrim = new RenderPrimitive();\r
-            }\r
+            rprim.Meshing = true;\r
+            Primitive prim = rprim.BasePrim;\r
 \r
             // Regular prim\r
             if (prim.Sculpt == null || prim.Sculpt.SculptTexture == UUID.Zero)\r
             {\r
                 FacetedMesh mesh = renderer.GenerateFacetedMesh(prim, DetailLevel.High);\r
-                rPrim.Faces = mesh.Faces;\r
-                rPrim.Prim = prim;\r
-                MeshPrim(prim, rPrim);\r
+                rprim.Faces = mesh.Faces;\r
+                CalculateBoundingBox(rprim);\r
+                rprim.Meshed = true;\r
+                rprim.Meshing = false;\r
             }\r
             else\r
             {\r
-                try\r
+                PendingTasks.Enqueue(new GenericTask(() =>\r
                 {\r
                     FacetedMesh mesh = null;\r
 \r
-                    if (prim.Sculpt.Type != SculptType.Mesh)\r
-                    { // Regular sculptie\r
-                        Image img = null;\r
+                    try\r
+                    {\r
+                        if (prim.Sculpt.Type != SculptType.Mesh)\r
+                        { // Regular sculptie\r
+                            Image img = null;\r
 \r
-                        lock (sculptCache)\r
-                        {\r
-                            if (sculptCache.ContainsKey(prim.Sculpt.SculptTexture))\r
+                            lock (sculptCache)\r
                             {\r
-                                img = sculptCache[prim.Sculpt.SculptTexture];\r
+                                if (sculptCache.ContainsKey(prim.Sculpt.SculptTexture))\r
+                                {\r
+                                    img = sculptCache[prim.Sculpt.SculptTexture];\r
+                                }\r
                             }\r
-                        }\r
 \r
-                        if (img == null)\r
-                        {\r
-                            if (LoadTexture(prim.Sculpt.SculptTexture, ref img, true))\r
-                            {\r
-                                sculptCache[prim.Sculpt.SculptTexture] = (Bitmap)img;\r
-                            }\r
-                            else\r
+                            if (img == null)\r
                             {\r
-                                return;\r
+                                if (LoadTexture(prim.Sculpt.SculptTexture, ref img, true))\r
+                                {\r
+                                    sculptCache[prim.Sculpt.SculptTexture] = (Bitmap)img;\r
+                                }\r
+                                else\r
+                                {\r
+                                    return;\r
+                                }\r
                             }\r
-                        }\r
 \r
-                        mesh = renderer.GenerateFacetedSculptMesh(prim, (Bitmap)img, DetailLevel.High);\r
-                    }\r
-                    else\r
-                    { // Mesh\r
-                        AutoResetEvent gotMesh = new AutoResetEvent(false);\r
-                        bool meshSuccess = false;\r
+                            mesh = renderer.GenerateFacetedSculptMesh(prim, (Bitmap)img, DetailLevel.High);\r
+                        }\r
+                        else\r
+                        { // Mesh\r
+                            AutoResetEvent gotMesh = new AutoResetEvent(false);\r
 \r
-                        Client.Assets.RequestMesh(prim.Sculpt.SculptTexture, (success, meshAsset) =>\r
+                            Client.Assets.RequestMesh(prim.Sculpt.SculptTexture, (success, meshAsset) =>\r
                             {\r
                                 if (!success || !FacetedMesh.TryDecodeFromAsset(prim, meshAsset, DetailLevel.Highest, out mesh))\r
                                 {\r
                                     Logger.Log("Failed to fetch or decode the mesh asset", Helpers.LogLevel.Warning, Client);\r
                                 }\r
-                                else\r
-                                {\r
-                                    meshSuccess = true;\r
-                                }\r
                                 gotMesh.Set();\r
                             });\r
 \r
-                        if (!gotMesh.WaitOne(20 * 1000, false)) return;\r
-                        if (!meshSuccess) return;\r
+                            gotMesh.WaitOne(20 * 1000, false);\r
+                        }\r
                     }\r
+                    catch\r
+                    { }\r
 \r
                     if (mesh != null)\r
                     {\r
-                        rPrim.Faces = mesh.Faces;\r
-                        rPrim.Prim = prim;\r
-                        MeshPrim(prim, rPrim);\r
+                        rprim.Faces = mesh.Faces;\r
+                        CalculateBoundingBox(rprim);\r
+                        rprim.Meshed = true;\r
+                        rprim.Meshing = false;\r
                     }\r
-                }\r
-                catch\r
-                { }\r
+                    else\r
+                    {\r
+                        lock (Prims)\r
+                        {\r
+                            Prims.Remove(rprim.BasePrim.LocalID);\r
+                        }\r
+                    }\r
+                }));\r
+                return;\r
             }\r
         }\r
 \r
+        private void UpdatePrimBlocking(Primitive prim)\r
+        {\r
+            if (!RenderingEnabled) return;\r
+\r
+            if (AvatarRenderingEnabled && prim.PrimData.PCode == PCode.Avatar)\r
+            {\r
+                AddAvatarToScene(Client.Network.CurrentSim.ObjectsAvatars[prim.LocalID]);\r
+                return;\r
+            }\r
+\r
+            // Skip foliage\r
+            if (prim.PrimData.PCode != PCode.Prim) return;\r
+            if (!PrimitiveRenderingEnabled) return;\r
+\r
+            if (prim.Textures == null) return;\r
+\r
+            RenderPrimitive rPrim = null;\r
+            if (Prims.TryGetValue(prim.LocalID, out rPrim))\r
+            {\r
+                rPrim.AttachedStateKnown = false;\r
+            }\r
+            else\r
+            {\r
+                rPrim = new RenderPrimitive();\r
+            }\r
+\r
+            rPrim.Prim = prim;\r
+            rPrim.Meshed = false;\r
+            lock (Prims) Prims[prim.LocalID] = rPrim;\r
+        }\r
+\r
         private bool LoadTexture(UUID textureID, ref Image texture, bool removeAlpha)\r
         {\r
             ManualResetEvent gotImage = new ManualResetEvent(false);\r
index 7ed6e01..1e16733 100644 (file)
@@ -499,6 +499,10 @@ namespace Radegast.Rendering
         public bool Attached;\r
         /// <summary>Do we know if object is attached</summary>\r
         public bool AttachedStateKnown;\r
+        /// <summary>Are meshes constructed and ready for this prim</summary>\r
+        public bool Meshed;\r
+        /// <summary>Process of creating a mesh is underway</summary>\r
+        public bool Meshing;\r
 \r
         public RenderPrimitive()\r
         {\r