OSDN Git Service

* Implemented occlusion culling (TODO: check if graphics card support it)
authorLatif Khalifa <latifer@streamgrid.net>
Wed, 27 Jul 2011 06:14:53 +0000 (06:14 +0000)
committerLatif Khalifa <latifer@streamgrid.net>
Wed, 27 Jul 2011 06:14:53 +0000 (06:14 +0000)
* Temporarily disabled avatar rendering

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

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

index 34b39c9..5531e53 100644 (file)
@@ -93,6 +93,7 @@ namespace Radegast.Rendering
         /// </summary>\r
         Dictionary<uint, RenderPrimitive> Prims = new Dictionary<uint, RenderPrimitive>();\r
         List<SceneObject> SortedObjects;\r
+        List<SceneObject> OccludedObjects;\r
         List<RenderAvatar> VisibleAvatars;\r
         Dictionary<uint, RenderAvatar> Avatars = new Dictionary<uint, RenderAvatar>();\r
 \r
@@ -104,13 +105,23 @@ namespace Radegast.Rendering
         /// <summary>\r
         /// Render avatars\r
         /// </summary>\r
-        public bool AvatarRenderingEnabled = true;\r
+        public bool AvatarRenderingEnabled = false;\r
 \r
         /// <summary>\r
         /// Show avatar skeloton\r
         /// </summary>\r
         public bool RenderAvatarSkeleton = false;\r
 \r
+        /// <summary>\r
+        /// Should we try to optimize by not drawing objects occluded behind other objects\r
+        /// </summary>\r
+        public bool OcclusionCullingEnabled = true;\r
+\r
+        /// <summary>\r
+        /// Cache images after jpeg2000 decode. Uses a lot of disk space and can cause disk trashing\r
+        /// </summary>\r
+        public bool CacheDecodedTextures = false;\r
+\r
         #endregion Public fields\r
 \r
         #region Private fields\r
@@ -144,7 +155,6 @@ namespace Radegast.Rendering
         OpenTK.Vector4 specularColor;\r
         float drawDistance = 48f;\r
         float drawDistanceSquared = 48f * 48f;\r
-        bool useDecodedImageCache = true;\r
 \r
         GridClient Client;\r
         RadegastInstance Instance;\r
@@ -937,7 +947,7 @@ namespace Radegast.Rendering
                     item.Data.TextureInfo.IsMask = isMask;\r
 \r
                     imageBytes = mi.ExportTGA();\r
-                    if (useDecodedImageCache)\r
+                    if (CacheDecodedTextures)\r
                     {\r
                         RHelp.SaveCachedImage(imageBytes, item.TeFace.TextureID, hasAlpha, fullAlpha, isMask);\r
                     }\r
@@ -1865,73 +1875,6 @@ namespace Radegast.Rendering
             GL.PopAttrib();\r
         }\r
 \r
-\r
-        void RenderBoundingBox(SceneObject prim)\r
-        {\r
-            Vector3 scale = prim.BasePrim.Scale;\r
-            BoundingVolume bbox = prim.BoundingVolume;\r
-            GL.PushAttrib(AttribMask.AllAttribBits);\r
-            GL.Disable(EnableCap.Fog);\r
-            GL.Disable(EnableCap.Texture2D);\r
-            GL.Disable(EnableCap.Lighting);\r
-            GL.Disable(EnableCap.CullFace);\r
-            GL.Disable(EnableCap.AlphaTest);\r
-\r
-            GL.DepthMask(false);\r
-            GL.ColorMask(false, false, false, false);\r
-\r
-            GL.PushMatrix();\r
-            GL.MultMatrix(Math3D.CreateSRTMatrix(scale, prim.RenderRotation, prim.RenderPosition));\r
-            GL.Color3(1f, 0f, 0f);\r
-            GL.Begin(BeginMode.Quads);\r
-            var bmin = bbox.Min;\r
-            var bmax = bbox.Max;\r
-\r
-            //front\r
-            GL.Vertex3(bmin.X, bmin.Y, bmin.Z);\r
-            GL.Vertex3(bmax.X, bmin.Y, bmin.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmin.Z);\r
-            GL.Vertex3(bmin.X, bmax.Y, bmin.Z);\r
-\r
-            // back\r
-            GL.Vertex3(bmin.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmax.Z);\r
-            GL.Vertex3(bmin.X, bmax.Y, bmax.Z);\r
-\r
-            // up\r
-            GL.Vertex3(bmin.X, bmax.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmin.Z);\r
-            GL.Vertex3(bmin.X, bmax.Y, bmin.Z);\r
-\r
-            // down\r
-            GL.Vertex3(bmin.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmin.Y, bmin.Z);\r
-            GL.Vertex3(bmin.X, bmin.Y, bmin.Z);\r
-\r
-            // left side\r
-            GL.Vertex3(bmin.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmin.X, bmax.Y, bmax.Z);\r
-            GL.Vertex3(bmin.X, bmax.Y, bmin.Z);\r
-            GL.Vertex3(bmin.X, bmin.Y, bmin.Z);\r
-\r
-            // rigth side\r
-            GL.Vertex3(bmax.X, bmin.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmax.Z);\r
-            GL.Vertex3(bmax.X, bmax.Y, bmin.Z);\r
-            GL.Vertex3(bmax.X, bmin.Y, bmin.Z);\r
-\r
-            GL.End();\r
-            GL.PopMatrix();\r
-\r
-            GL.ColorMask(true, true, true, true);\r
-            GL.DepthMask(true);\r
-\r
-            GL.PopAttrib();\r
-        }\r
-\r
         void RenderPrim(RenderPrimitive mesh, RenderPass pass, int primNr)\r
         {\r
             if (!AvatarRenderingEnabled && mesh.Attached) return;\r
@@ -1947,6 +1890,16 @@ namespace Radegast.Rendering
             // Do we have animated texture on this face\r
             bool animatedTexture = false;\r
 \r
+            // Initialise flags tracking what type of faces this prim has\r
+            if (pass == RenderPass.Simple)\r
+            {\r
+                mesh.HasSimpleFaces = false;\r
+            }\r
+            else if (pass == RenderPass.Alpha)\r
+            {\r
+                mesh.HasAlphaFaces = false;\r
+            }\r
+\r
             // Draw the prim faces\r
             for (int j = 0; j < mesh.Faces.Count; j++)\r
             {\r
@@ -1975,6 +1928,15 @@ namespace Radegast.Rendering
                     if (belongToAlphaPass && pass != RenderPass.Alpha) continue;\r
                     if (!belongToAlphaPass && pass == RenderPass.Alpha) continue;\r
 \r
+                    if (pass == RenderPass.Simple)\r
+                    {\r
+                        mesh.HasSimpleFaces = true;\r
+                    }\r
+                    else if (pass == RenderPass.Alpha)\r
+                    {\r
+                        mesh.HasAlphaFaces = true;\r
+                    }\r
+\r
                     if (teFace.Fullbright)\r
                     {\r
                         GL.Disable(EnableCap.Lighting);\r
@@ -2102,6 +2064,10 @@ namespace Radegast.Rendering
         {\r
             SortedObjects = new List<SceneObject>();\r
             VisibleAvatars = new List<RenderAvatar>();\r
+            if (OcclusionCullingEnabled)\r
+            {\r
+                OccludedObjects = new List<SceneObject>();\r
+            }\r
 \r
             lock (Prims)\r
             {\r
@@ -2129,7 +2095,14 @@ namespace Radegast.Rendering
                     if (LODFactor(obj.DistanceSquared, obj.BasePrim.Scale, obj.BoundingVolume.R) < minLODFactor) continue;\r
 \r
                     obj.Attached = false;\r
-                    SortedObjects.Add(obj);\r
+                    if (OcclusionCullingEnabled && obj.Occluded())\r
+                    {\r
+                        OccludedObjects.Add(obj);\r
+                    }\r
+                    else\r
+                    {\r
+                        SortedObjects.Add(obj);\r
+                    }\r
                 }\r
 \r
                 // Calculate avatar positions and perform interpolation tasks\r
@@ -2174,7 +2147,14 @@ namespace Radegast.Rendering
                         obj.AttachedStateKnown = true;\r
                     }\r
 \r
-                    SortedObjects.Add(obj);\r
+                    if (OcclusionCullingEnabled && obj.Occluded())\r
+                    {\r
+                        OccludedObjects.Add(obj);\r
+                    }\r
+                    else\r
+                    {\r
+                        SortedObjects.Add(obj);\r
+                    }\r
                 }\r
             }\r
 \r
@@ -2183,6 +2163,86 @@ namespace Radegast.Rendering
             SortedObjects.Sort();\r
         }\r
 \r
+        void RenderBoundingBox(SceneObject prim)\r
+        {\r
+            Vector3 scale = prim.BasePrim.Scale;\r
+\r
+            GL.PushMatrix();\r
+            GL.MultMatrix(Math3D.CreateSRTMatrix(scale, prim.RenderRotation, prim.RenderPosition));\r
+\r
+            if (useVBO)\r
+            {\r
+                GL.DrawElements(BeginMode.Quads, RHelp.CubeIndices.Length, DrawElementsType.UnsignedShort, IntPtr.Zero);\r
+            }\r
+            else\r
+            {\r
+                GL.VertexPointer(3, VertexPointerType.Float, 0, RHelp.CubeVertices);\r
+                GL.DrawElements(BeginMode.Quads, RHelp.CubeIndices.Length, DrawElementsType.UnsignedShort, RHelp.CubeIndices);\r
+            }\r
+            GL.PopMatrix();\r
+        }\r
+\r
+        int boundingBoxVBO = -1;\r
+        int boundingBoxVIndexVBO = -1;\r
+\r
+        private void RenderOccludedObjects()\r
+        {\r
+            if (!OcclusionCullingEnabled) return;\r
+\r
+            GL.EnableClientState(ArrayCap.VertexArray);\r
+            GL.ColorMask(false, false, false, false);\r
+            GL.Disable(EnableCap.CullFace);\r
+            GL.Disable(EnableCap.Lighting);\r
+\r
+            if (useVBO)\r
+            {\r
+                if (boundingBoxVBO == -1)\r
+                {\r
+                    GL.GenBuffers(1, out boundingBoxVBO);\r
+                    GL.BindBuffer(BufferTarget.ArrayBuffer, boundingBoxVBO);\r
+                    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(sizeof(float) * RHelp.CubeVertices.Length), RHelp.CubeVertices, BufferUsageHint.StaticDraw);\r
+                }\r
+                else\r
+                {\r
+                    GL.BindBuffer(BufferTarget.ArrayBuffer, boundingBoxVBO);\r
+                }\r
+\r
+                if (boundingBoxVIndexVBO == -1)\r
+                {\r
+                    GL.GenBuffers(1, out boundingBoxVIndexVBO);\r
+                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, boundingBoxVIndexVBO);\r
+                    GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(sizeof(ushort) * RHelp.CubeIndices.Length), RHelp.CubeIndices, BufferUsageHint.StaticDraw);\r
+                }\r
+                else\r
+                {\r
+                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, boundingBoxVIndexVBO);\r
+                }\r
+\r
+                GL.VertexPointer(3, VertexPointerType.Float, 0, (IntPtr)0);\r
+            }\r
+\r
+            foreach (SceneObject obj in OccludedObjects)\r
+            {\r
+                if ((!obj.HasAlphaFaces && !obj.HasSimpleFaces)) continue;\r
+                obj.HasSimpleFaces = true;\r
+                obj.HasAlphaFaces = false;\r
+                obj.StartSimpleQuery();\r
+                RenderBoundingBox(obj);\r
+                obj.EndSimpleQuery();\r
+            }\r
+\r
+            if (useVBO)\r
+            {\r
+                GL.BindBuffer(BufferTarget.ArrayBuffer, 0);\r
+                GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);\r
+            }\r
+\r
+            GL.ColorMask(true, true, true, true);\r
+            GL.DisableClientState(ArrayCap.VertexArray);\r
+            GL.Enable(EnableCap.CullFace);\r
+            GL.Enable(EnableCap.Lighting);\r
+        }\r
+\r
         private void RenderObjects(RenderPass pass)\r
         {\r
             if (!PrimitiveRenderingEnabled) return;\r
@@ -2216,8 +2276,9 @@ namespace Radegast.Rendering
                 {\r
                     // Don't render objects that are outside the draw distane\r
                     if (Vector3.DistanceSquared(myPos, obj.RenderPosition) > drawDistanceSquared) continue;\r
-\r
+                    obj.StartQuery(pass);\r
                     RenderPrim((RenderPrimitive)obj, pass, ix);\r
+                    obj.EndQuery(pass);\r
                 }\r
             }\r
 \r
@@ -2313,9 +2374,11 @@ namespace Radegast.Rendering
                 RenderAvatars(RenderPass.Simple);\r
                 GL.Disable(EnableCap.AlphaTest);\r
 \r
+                GL.DepthMask(false);\r
+                RenderOccludedObjects();\r
+\r
                 // Alpha blending elements, disable writing to depth buffer\r
                 GL.Enable(EnableCap.Blend);\r
-                GL.DepthMask(false);\r
                 RenderWater();\r
                 RenderObjects(RenderPass.Alpha);\r
                 GL.DepthMask(true);\r
@@ -2430,7 +2493,7 @@ namespace Radegast.Rendering
                     TexturesPtrMap[item.TeFace.TextureID] = item.Data.TextureInfo;\r
                     if (item.TextureData == null && item.TGAData == null)\r
                     {\r
-                        if (useDecodedImageCache && RHelp.LoadCachedImage(item.TeFace.TextureID, out item.TGAData, out item.Data.TextureInfo.HasAlpha, out item.Data.TextureInfo.FullAlpha, out item.Data.TextureInfo.IsMask))\r
+                        if (CacheDecodedTextures && RHelp.LoadCachedImage(item.TeFace.TextureID, out item.TGAData, out item.Data.TextureInfo.HasAlpha, out item.Data.TextureInfo.FullAlpha, out item.Data.TextureInfo.IsMask))\r
                         {\r
                             PendingTextures.Enqueue(item);\r
                         }\r
@@ -2629,7 +2692,7 @@ namespace Radegast.Rendering
                 gotImage.Reset();\r
                 bool hasAlpha, fullAlpha, isMask;\r
                 byte[] tgaData;\r
-                if (useDecodedImageCache && RHelp.LoadCachedImage(textureID, out tgaData, out hasAlpha, out fullAlpha, out isMask))\r
+                if (RHelp.LoadCachedImage(textureID, out tgaData, out hasAlpha, out fullAlpha, out isMask))\r
                 {\r
                     img = LoadTGAClass.LoadTGA(new MemoryStream(tgaData));\r
                 }\r
@@ -2651,10 +2714,7 @@ namespace Radegast.Rendering
                                 }\r
                                 tgaData = mi.ExportTGA();\r
                                 img = LoadTGAClass.LoadTGA(new MemoryStream(tgaData));\r
-                                if (useDecodedImageCache)\r
-                                {\r
-                                    RHelp.SaveCachedImage(tgaData, textureID, (mi.Channels & ManagedImage.ImageChannels.Alpha) != 0, false, false);\r
-                                }\r
+                                RHelp.SaveCachedImage(tgaData, textureID, (mi.Channels & ManagedImage.ImageChannels.Alpha) != 0, false, false);\r
                             }\r
                             gotImage.Set();\r
                         }\r
@@ -2968,7 +3028,7 @@ namespace Radegast.Rendering
         private void cbMisc_CheckedChanged(object sender, EventArgs e)\r
         {\r
             miscEnabled = cbMisc.Checked;\r
-            AvatarRenderingEnabled = miscEnabled;\r
+            OcclusionCullingEnabled = miscEnabled;\r
         }\r
     }\r
 }\r
index b303e94..2ef9a3d 100644 (file)
@@ -317,6 +317,11 @@ namespace Radegast.Rendering
         public virtual Primitive BasePrim { get; set; }\r
         /// <summary>Were initial initialization tasks done</summary>\r
         public bool Initialized;\r
+        public int AlphaQueryID = -1;\r
+        public int SimpleQueryID = -1;\r
+        public bool HasAlphaFaces;\r
+        public bool HasSimpleFaces;\r
+\r
         #endregion Public fields\r
 \r
         /// <summary>\r
@@ -386,6 +391,102 @@ namespace Radegast.Rendering
             else\r
                 return 0;\r
         }\r
+\r
+        public void StartQuery(RenderPass pass)\r
+        {\r
+            if (pass == RenderPass.Simple)\r
+            {\r
+                StartSimpleQuery();\r
+            }\r
+            else if (pass == RenderPass.Alpha)\r
+            {\r
+                StartAlphaQuery();\r
+            }\r
+        }\r
+\r
+        public void EndQuery(RenderPass pass)\r
+        {\r
+            if (pass == RenderPass.Simple)\r
+            {\r
+                EndSimpleQuery();\r
+            }\r
+            else if (pass == RenderPass.Alpha)\r
+            {\r
+                EndAlphaQuery();\r
+            }\r
+        }\r
+\r
+        public void StartAlphaQuery()\r
+        {\r
+            if (AlphaQueryID == -1)\r
+            {\r
+                GL.GenQueries(1, out AlphaQueryID);\r
+            }\r
+            if (AlphaQueryID > 0)\r
+            {\r
+                GL.BeginQuery(QueryTarget.SamplesPassed, AlphaQueryID);\r
+            }\r
+        }\r
+\r
+        public void EndAlphaQuery()\r
+        {\r
+            if (AlphaQueryID > 0)\r
+            {\r
+                GL.EndQuery(QueryTarget.SamplesPassed);\r
+            }\r
+        }\r
+\r
+        public void StartSimpleQuery()\r
+        {\r
+            if (SimpleQueryID == -1)\r
+            {\r
+                GL.GenQueries(1, out SimpleQueryID);\r
+            }\r
+            if (SimpleQueryID > 0)\r
+            {\r
+                GL.BeginQuery(QueryTarget.SamplesPassed, SimpleQueryID);\r
+            }\r
+        }\r
+\r
+        public void EndSimpleQuery()\r
+        {\r
+            if (SimpleQueryID > 0)\r
+            {\r
+                GL.EndQuery(QueryTarget.SamplesPassed);\r
+            }\r
+        }\r
+\r
+        public bool Occluded()\r
+        {\r
+            if ((SimpleQueryID == -1 && AlphaQueryID == -1))\r
+            {\r
+                return false;\r
+            }\r
+\r
+            if ((!HasAlphaFaces && !HasSimpleFaces)) return true;\r
+\r
+            int samples = 1;\r
+            if (HasSimpleFaces && SimpleQueryID > 0)\r
+            {\r
+                GL.GetQueryObject(SimpleQueryID, GetQueryObjectParam.QueryResult, out samples);\r
+            }\r
+            if (HasSimpleFaces && samples > 0)\r
+            {\r
+                return false;\r
+            }\r
+\r
+            samples = 1;\r
+            if (HasAlphaFaces && AlphaQueryID > 0)\r
+            {\r
+                GL.GetQueryObject(AlphaQueryID, GetQueryObjectParam.QueryResult, out samples);\r
+            }\r
+            if (HasAlphaFaces && samples > 0)\r
+            {\r
+                return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
     }\r
 \r
     public class RenderPrimitive : SceneObject\r
@@ -586,6 +687,38 @@ namespace Radegast.Rendering
             }\r
         }\r
         #endregion Cached image save and load\r
+\r
+        #region Static vertices and indices for a cube (used for bounding box drawing)\r
+        /**********************************************\r
+          5 --- 4\r
+         /|    /|\r
+        1 --- 0 |\r
+        | 6 --| 7\r
+        |/    |/\r
+        2 --- 3\r
+        ***********************************************/\r
+        public static readonly float[] CubeVertices = new float[]\r
+        {\r
+             0.5f,  0.5f,  0.5f, // 0\r
+               -0.5f,  0.5f,  0.5f, // 1\r
+               -0.5f, -0.5f,  0.5f, // 2\r
+                0.5f, -0.5f,  0.5f, // 3\r
+                0.5f,  0.5f, -0.5f, // 4\r
+               -0.5f,  0.5f, -0.5f, // 5\r
+               -0.5f, -0.5f, -0.5f, // 6\r
+                0.5f, -0.5f, -0.5f  // 7\r
+        };\r
+\r
+        public static readonly ushort[] CubeIndices = new ushort[]\r
+        {\r
+            0, 1, 2, 3,     // Front Face\r
+               4, 5, 6, 7,     // Back Face\r
+               1, 2, 6, 5,     // Left Face\r
+               0, 3, 7, 4,     // Right Face\r
+               0, 1, 5, 4,     // Top Face\r
+               2, 3, 7, 6      // Bottom Face\r
+        };\r
+        #endregion Static vertices and indices for a cube (used for bounding box drawing)\r
     }\r
 \r
     /// <summary>\r
@@ -1103,7 +1236,7 @@ namespace Radegast.Rendering
             Array.Copy(source.RenderData.Indices, RenderData.Indices, source.RenderData.Indices.Length);\r
             Array.Copy(source.RenderData.weights, RenderData.weights, source.RenderData.weights.Length);\r
             Array.Copy(source.RenderData.skinJoints, RenderData.skinJoints, source.RenderData.skinJoints.Length);\r
-            \r
+\r
             RenderData.Center = new Vector3(source.RenderData.Center);\r
 \r
             teFaceID = source.teFaceID;\r
@@ -1289,7 +1422,7 @@ namespace Radegast.Rendering
                     }\r
                     else\r
                     {\r
-                        \r
+\r
                         ba = av.skel.mBones[jointname];\r
                     }\r
 \r
@@ -1314,7 +1447,7 @@ namespace Radegast.Rendering
                 if (bb != null)\r
                 {\r
                     lerp = Vector3.Lerp(ba.getDeltaOffset(), bb.getDeltaOffset(), weight);\r
-                    offset = Vector3.Lerp(ba.getTotalOffset(), bb.getTotalOffset(), weight);   \r
+                    offset = Vector3.Lerp(ba.getTotalOffset(), bb.getTotalOffset(), weight);\r
                 }\r
                 else\r
                 {\r
@@ -1324,7 +1457,7 @@ namespace Radegast.Rendering
                 }\r
 \r
                 Vector3 pos = new Vector3(MorphRenderData.Vertices[v], MorphRenderData.Vertices[v + 1], MorphRenderData.Vertices[v + 2]);\r
-                \r
+\r
                 //move back to mesh local coords\r
                 pos = pos - offset;\r
                 // apply LERPd offset\r
@@ -1342,9 +1475,9 @@ namespace Radegast.Rendering
 \r
         public void resetallmorphs()\r
         {\r
-            for (int i = 0; i < OrigRenderData.Vertices.Length/3; i++)\r
+            for (int i = 0; i < OrigRenderData.Vertices.Length / 3; i++)\r
             {\r
-     \r
+\r
                 MorphRenderData.Vertices[i * 3] = OrigRenderData.Vertices[i * 3];\r
                 MorphRenderData.Vertices[(i * 3) + 1] = OrigRenderData.Vertices[i * 3 + 1];\r
                 MorphRenderData.Vertices[(i * 3) + 2] = OrigRenderData.Vertices[i * 3 + 2];\r
@@ -1353,7 +1486,7 @@ namespace Radegast.Rendering
                 //MorphRenderData.Normals[(i * 3) + 1] = OrigRenderData.Normals[i * 3 + 1];\r
                 //MorphRenderData.Normals[(i * 3) + 2] = OrigRenderData.Normals[i * 3 + 2];\r
 \r
-                RenderData.TexCoords[i * 2] = OrigRenderData.TexCoords[i * 2] ;\r
+                RenderData.TexCoords[i * 2] = OrigRenderData.TexCoords[i * 2];\r
                 RenderData.TexCoords[(i * 2) + 1] = OrigRenderData.TexCoords[i * 2 + 1];\r
 \r
             }\r
@@ -1739,7 +1872,7 @@ namespace Radegast.Rendering
                     this.morphtest(av, vpe.ParamID, value);\r
 \r
                     x++;\r
-                  //  if (x > 100)\r
+                    //  if (x > 100)\r
                     //    break;\r
                 }\r
 \r
@@ -1955,7 +2088,7 @@ namespace Radegast.Rendering
                     {\r
                         //actually get the last for a pose the last frame is probably the static one once\r
                         //we have reached position\r
-                        binBVHJointKey rot = joint.rotationkeys[joint.rotationkeys.Length-1];\r
+                        binBVHJointKey rot = joint.rotationkeys[joint.rotationkeys.Length - 1];\r
 \r
                         Vector3 pos = new Vector3(0, 0, 0);\r
                         //binBVHJointKey pos = joint.positionkeys[0];\r
@@ -1997,7 +2130,7 @@ namespace Radegast.Rendering
 \r
         private bool rotdirty = true;\r
         private bool posdirty = true;\r
-        \r
+\r
         private Vector3 mTotalPos;\r
         private Quaternion mTotalRot;\r
 \r
@@ -2072,7 +2205,7 @@ namespace Radegast.Rendering
             {\r
                 b.mParentBone = parent.name;\r
                 parent.children.Add(b);\r
-            }               \r
+            }\r
 \r
             mBones.Add(b.name, b);\r
             mIndexedBones.Add(boneaddindex++, b);\r
@@ -2094,7 +2227,7 @@ namespace Radegast.Rendering
             this.scale = Bone.mBones[name].orig_scale + scale;\r
             this.rot = Bone.mBones[name].orig_rot * rot;\r
 \r
-            markdirty();        \r
+            markdirty();\r
         }\r
 \r
         // If we deform a bone mark this bone and all its children as dirty.  \r
@@ -2155,7 +2288,7 @@ namespace Radegast.Rendering
                 return mTotalPos;\r
             }\r
             else\r
-            {          \r
+            {\r
                 return getOffset();\r
             }\r
         }\r
@@ -2168,7 +2301,7 @@ namespace Radegast.Rendering
             }\r
             else\r
             {\r
-                getOffset(); \r
+                getOffset();\r
                 return mDeltaPos;\r
             }\r
         }\r