From 759d46954b1e313cb36b26f8fa409fffda6e907f Mon Sep 17 00:00:00 2001 From: Latif Khalifa Date: Tue, 12 Jul 2011 14:28:42 +0000 Subject: [PATCH] Simple interpolation of object position. git-svn-id: https://radegast.googlecode.com/svn/trunk@979 f7a694da-4d33-11de-9ad6-1127a62b9fcd --- Radegast/GUI/Rendering/Rendering.Designer.cs | 34 +++-- Radegast/GUI/Rendering/Rendering.cs | 43 ++++-- Radegast/GUI/Rendering/RenderingHelpers.cs | 205 +++++++++++++++++---------- 3 files changed, 188 insertions(+), 94 deletions(-) diff --git a/Radegast/GUI/Rendering/Rendering.Designer.cs b/Radegast/GUI/Rendering/Rendering.Designer.cs index 450a425..70aa54c 100644 --- a/Radegast/GUI/Rendering/Rendering.Designer.cs +++ b/Radegast/GUI/Rendering/Rendering.Designer.cs @@ -61,6 +61,7 @@ namespace Radegast.Rendering this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SceneWindow)); this.gbZoom = new System.Windows.Forms.GroupBox(); + this.lblDrawDistance = new System.Windows.Forms.Label(); this.tbDrawDistance = new System.Windows.Forms.TrackBar(); this.button_driver = new System.Windows.Forms.Button(); this.textBox_driveramount = new System.Windows.Forms.TextBox(); @@ -96,7 +97,7 @@ namespace Radegast.Rendering this.takeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.returnToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.lblDrawDistance = new System.Windows.Forms.Label(); + this.cbMisc = new System.Windows.Forms.CheckBox(); this.gbZoom.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.tbDrawDistance)).BeginInit(); this.ctxObjects.SuspendLayout(); @@ -104,6 +105,7 @@ namespace Radegast.Rendering // // gbZoom // + this.gbZoom.Controls.Add(this.cbMisc); this.gbZoom.Controls.Add(this.lblDrawDistance); this.gbZoom.Controls.Add(this.tbDrawDistance); this.gbZoom.Controls.Add(this.button_driver); @@ -141,6 +143,16 @@ namespace Radegast.Rendering this.gbZoom.TabStop = false; this.gbZoom.Enter += new System.EventHandler(this.gbZoom_Enter); // + // lblDrawDistance + // + this.lblDrawDistance.AutoSize = true; + this.lblDrawDistance.Location = new System.Drawing.Point(542, 140); + this.lblDrawDistance.Name = "lblDrawDistance"; + this.lblDrawDistance.Size = new System.Drawing.Size(93, 13); + this.lblDrawDistance.TabIndex = 48; + this.lblDrawDistance.Text = "Draw distance: 48"; + this.lblDrawDistance.TextAlign = System.Drawing.ContentAlignment.TopRight; + // // tbDrawDistance // this.tbDrawDistance.Location = new System.Drawing.Point(358, 117); @@ -498,15 +510,18 @@ namespace Radegast.Rendering this.deleteToolStripMenuItem.Text = "Delete"; this.deleteToolStripMenuItem.Click += new System.EventHandler(this.deleteToolStripMenuItem_Click); // - // lblDrawDistance + // cbMisc // - this.lblDrawDistance.AutoSize = true; - this.lblDrawDistance.Location = new System.Drawing.Point(542, 140); - this.lblDrawDistance.Name = "lblDrawDistance"; - this.lblDrawDistance.Size = new System.Drawing.Size(93, 13); - this.lblDrawDistance.TabIndex = 48; - this.lblDrawDistance.Text = "Draw distance: 48"; - this.lblDrawDistance.TextAlign = System.Drawing.ContentAlignment.TopRight; + this.cbMisc.AutoSize = true; + this.cbMisc.Checked = true; + this.cbMisc.CheckState = System.Windows.Forms.CheckState.Checked; + this.cbMisc.Location = new System.Drawing.Point(358, 142); + this.cbMisc.Name = "cbMisc"; + this.cbMisc.Size = new System.Drawing.Size(48, 17); + this.cbMisc.TabIndex = 49; + this.cbMisc.Text = "Misc"; + this.cbMisc.UseVisualStyleBackColor = true; + this.cbMisc.CheckedChanged += new System.EventHandler(this.cbMisc_CheckedChanged); // // SceneWindow // @@ -565,6 +580,7 @@ namespace Radegast.Rendering private System.Windows.Forms.ComboBox comboBox_driver; private System.Windows.Forms.TrackBar tbDrawDistance; private System.Windows.Forms.Label lblDrawDistance; + private System.Windows.Forms.CheckBox cbMisc; } } diff --git a/Radegast/GUI/Rendering/Rendering.cs b/Radegast/GUI/Rendering/Rendering.cs index cbde29b..4bfa857 100644 --- a/Radegast/GUI/Rendering/Rendering.cs +++ b/Radegast/GUI/Rendering/Rendering.cs @@ -963,7 +963,7 @@ namespace Radegast.Rendering return pos; } - SceneObject GetParent(uint localID) + SceneObject GetSceneObject(uint localID) { RenderPrimitive parent; RenderAvatar avi; @@ -991,12 +991,12 @@ namespace Radegast.Rendering pos = new Vector3(99999f, 99999f, 99999f); rot = Quaternion.Identity; - SceneObject p = GetParent(prim.ParentID); + SceneObject p = GetSceneObject(prim.ParentID); if (p == null) return; Vector3 parentPos; Quaternion parentRot; - if (p.PositionUpdated) + if (p.PositionCalculated) { parentPos = p.SimPosition; parentRot = p.SimRotation; @@ -1008,7 +1008,7 @@ namespace Radegast.Rendering p.SimPosition = parentPos; p.SimRotation = parentRot; p.DistanceSquared = Vector3.DistanceSquared(Camera.RenderPosition, p.SimPosition); - p.PositionUpdated = true; + p.PositionCalculated = true; } if (p is RenderPrimitive) @@ -1166,7 +1166,7 @@ namespace Radegast.Rendering { lock (Avatars) { - if (Vector3.Distance(PrimPos(av), Client.Self.SimPosition) > 32) return; + if (Vector3.Distance(PrimPos(av), Client.Self.SimPosition) > DrawDistance) return; if (Avatars.ContainsKey(av.LocalID)) { @@ -1807,14 +1807,20 @@ namespace Radegast.Rendering void RenderPrim(RenderPrimitive mesh, RenderPass pass, int primNr) { + // Do the stuff we need to do the first time we encouter the object + if (!mesh.Initialized) mesh.Initialize(); + + // Do any position interpolation + mesh.Step(lastFrameTime); + Primitive prim = mesh.Prim; // Individual prim matrix GL.PushMatrix(); // Prim roation and position - GL.MultMatrix(Math3D.CreateTranslationMatrix(mesh.SimPosition)); - GL.MultMatrix(Math3D.CreateRotationMatrix(mesh.SimRotation)); + GL.MultMatrix(Math3D.CreateTranslationMatrix(mesh.RenderPosition)); + GL.MultMatrix(Math3D.CreateRotationMatrix(mesh.RenderRotation)); // Prim scaling GL.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z); @@ -1829,6 +1835,9 @@ namespace Radegast.Rendering Face face = mesh.Faces[j]; FaceData data = (FaceData)mesh.Faces[j].UserData; + if (data == null) + continue; + if (teFace == null) teFace = mesh.Prim.Textures.DefaultTexture; @@ -1983,16 +1992,16 @@ namespace Radegast.Rendering foreach (SceneObject obj in SortedObjects) { - obj.PositionUpdated = false; + obj.PositionCalculated = false; } foreach (SceneObject obj in SortedObjects) { - if (!obj.PositionUpdated) + if (!obj.PositionCalculated) { PrimPosAndRot(obj.BasePrim, out obj.SimPosition, out obj.SimRotation); obj.DistanceSquared = Vector3.DistanceSquared(Camera.RenderPosition, obj.SimPosition); - obj.PositionUpdated = true; + obj.PositionCalculated = true; } } @@ -2358,11 +2367,16 @@ namespace Radegast.Rendering if (prim.Textures == null) return; + RenderPrimitive rPrim = null; + if (!Prims.TryGetValue(prim.LocalID, out rPrim)) + { + rPrim = new RenderPrimitive(); + } + // Regular prim if (prim.Sculpt == null || prim.Sculpt.SculptTexture == UUID.Zero) { FacetedMesh mesh = renderer.GenerateFacetedMesh(prim, DetailLevel.High); - RenderPrimitive rPrim = new RenderPrimitive(); rPrim.Faces = mesh.Faces; rPrim.Prim = prim; MeshPrim(prim, rPrim); @@ -2423,7 +2437,6 @@ namespace Radegast.Rendering if (mesh != null) { - RenderPrimitive rPrim = new RenderPrimitive(); rPrim.Faces = mesh.Faces; rPrim.Prim = prim; MeshPrim(prim, rPrim); @@ -2726,6 +2739,12 @@ namespace Radegast.Rendering UpdateCamera(); } + bool miscEnabled = true; + private void cbMisc_CheckedChanged(object sender, EventArgs e) + { + miscEnabled = cbMisc.Checked; + } + } } diff --git a/Radegast/GUI/Rendering/RenderingHelpers.cs b/Radegast/GUI/Rendering/RenderingHelpers.cs index f3e8437..a7f46aa 100644 --- a/Radegast/GUI/Rendering/RenderingHelpers.cs +++ b/Radegast/GUI/Rendering/RenderingHelpers.cs @@ -289,16 +289,60 @@ namespace Radegast.Rendering Avatar, } - public abstract class SceneObject: IComparable + /// + /// Base class for all scene objects + /// + public abstract class SceneObject : IComparable, IDisposable { + /// Actual position of the object in the region public Vector3 SimPosition; + /// Actual rotation of the object in the region public Quaternion SimRotation; + /// Rendered position of the object in the region + public Vector3 RenderPosition; + /// Rendered rotationm of the object in the region + public Quaternion RenderRotation; + /// Per frame calculated square of the distance from camera public float DistanceSquared; + /// Bounding volume of the object public BoundingVolume BoundingVolume; - public bool PositionUpdated; + /// Was the sim position and distance from camera calculated during this frame + public bool PositionCalculated; + /// Scene object type public SceneObjectType Type = SceneObjectType.None; + /// Libomv primitive public virtual Primitive BasePrim { get; set; } + /// Were initial initialization tasks done + public bool Initialized; + + /// + /// Cleanup resources used + /// + public virtual void Dispose() + { + } + + /// + /// Task performed the fist time object is set for rendering + /// + public virtual void Initialize() + { + } + /// + /// Perform per frame tasks + /// + /// Time since the last call (last frame time in seconds) + public virtual void Step(double time) + { + } + + /// + /// Implementation of the IComparable interface + /// used for sorting by distance + /// + /// Object we are comparing to + /// Result of the comparison public virtual int CompareTo(object other) { SceneObject o = (SceneObject)other; @@ -311,7 +355,7 @@ namespace Radegast.Rendering } } - public class RenderPrimitive : SceneObject, IDisposable + public class RenderPrimitive : SceneObject { public Primitive Prim; public List Faces; @@ -321,16 +365,31 @@ namespace Radegast.Rendering Type = SceneObjectType.Primitive; } - public virtual void Dispose() - { - } - public override Primitive BasePrim { get { return Prim; } set { Prim = value; } } + public override void Initialize() + { + RenderPosition = SimPosition; + RenderRotation = SimRotation; + Initialized = true; + } + + public override void Step(double time) + { + if (RenderPosition != SimPosition) + { + RenderPosition = RHelp.Smoothed1stOrder(RenderPosition, SimPosition, time); + } + if (RenderRotation != SimRotation) + { + RenderRotation = SimRotation; + } + } + public override string ToString() { uint id = Prim == null ? 0 : Prim.LocalID; @@ -715,8 +774,8 @@ namespace Radegast.Rendering float wy = q.W * y2; float wz = q.W * z2; - mat[0] = (1.0f - (yy + zz))*scale.X; - mat[1] = (xy - wz)*scale.X; + mat[0] = (1.0f - (yy + zz)) * scale.X; + mat[1] = (xy - wz) * scale.X; mat[2] = (xz + wy) * scale.X; mat[3] = 0.0f; @@ -892,12 +951,12 @@ namespace Radegast.Rendering { } - public GLMesh(GLMesh source,GLAvatar av) - :base(source.Name) + public GLMesh(GLMesh source, GLAvatar av) + : base(source.Name) { this.av = av; // Make a new GLMesh copy from the supplied source - + RenderData.Vertices = new float[source.RenderData.Vertices.Length]; RenderData.Normals = new float[source.RenderData.Normals.Length]; RenderData.TexCoords = new float[source.RenderData.TexCoords.Length]; @@ -906,7 +965,7 @@ namespace Radegast.Rendering RenderData.weights = new float[source.RenderData.weights.Length]; RenderData.skinJoints = new string[source.RenderData.skinJoints.Length]; - Array.Copy(source.RenderData.Vertices,RenderData.Vertices,source.RenderData.Vertices.Length); + Array.Copy(source.RenderData.Vertices, RenderData.Vertices, source.RenderData.Vertices.Length); Array.Copy(source.RenderData.Normals, RenderData.Normals, source.RenderData.Normals.Length); Array.Copy(source.RenderData.TexCoords, RenderData.TexCoords, source.RenderData.TexCoords.Length); @@ -966,19 +1025,19 @@ namespace Radegast.Rendering RenderData.Vertices = new float[_numVertices * 3]; RenderData.Normals = new float[_numVertices * 3]; - Quaternion quat = Quaternion.CreateFromEulers(0, 0, (float)(Math.PI/4.0)); + Quaternion quat = Quaternion.CreateFromEulers(0, 0, (float)(Math.PI / 4.0)); int current = 0; for (int i = 0; i < _numVertices; i++) { - RenderData.Normals[current] = _vertices[i].Normal.X; - RenderData.Vertices[current++] = _vertices[i].Coord.X; - RenderData.Normals[current] = _vertices[i].Normal.Y; - RenderData.Vertices[current++] = _vertices[i].Coord.Y; - RenderData.Normals[current] = _vertices[i].Normal.Z; - RenderData.Vertices[current++] = _vertices[i].Coord.Z; - + RenderData.Normals[current] = _vertices[i].Normal.X; + RenderData.Vertices[current++] = _vertices[i].Coord.X; + RenderData.Normals[current] = _vertices[i].Normal.Y; + RenderData.Vertices[current++] = _vertices[i].Coord.Y; + RenderData.Normals[current] = _vertices[i].Normal.Z; + RenderData.Vertices[current++] = _vertices[i].Coord.Z; + if (_vertices[i].Coord.X < minX) minX = _vertices[i].Coord.X; else if (_vertices[i].Coord.X > maxX) @@ -1013,8 +1072,8 @@ namespace Radegast.Rendering current = 0; for (int i = 0; i < _numVertices; i++) { - RenderData.TexCoords[current++] = _vertices[i].TexCoord.X; - RenderData.TexCoords[current++] = _vertices[i].TexCoord.Y; + RenderData.TexCoords[current++] = _vertices[i].TexCoord.X; + RenderData.TexCoords[current++] = _vertices[i].TexCoord.Y; } RenderData.weights = new float[_numVertices]; @@ -1023,7 +1082,7 @@ namespace Radegast.Rendering RenderData.weights[i] = _vertices[i].Weight; } - RenderData.skinJoints = new string[_skinJoints.Length+3]; + RenderData.skinJoints = new string[_skinJoints.Length + 3]; for (int i = 1; i < _skinJoints.Length; i++) { RenderData.skinJoints[i] = _skinJoints[i]; @@ -1041,7 +1100,7 @@ namespace Radegast.Rendering public void applyjointweights() { - + /*Each weight actually contains two pieces of information. * The number to the left of the decimal point is the index of the joint and also * implicitly indexes to the following joint. The actual weight is to the right of @@ -1051,14 +1110,14 @@ namespace Radegast.Rendering * in the list for each of its children. */ - float weight=-9999; - int jointindex=0; + float weight = -9999; + int jointindex = 0; float factor; Bone ba = null; Bone bb = null; - for (int v = 0, x=0; v < RenderData.Vertices.Length; v=v+3, x++) + for (int v = 0, x = 0; v < RenderData.Vertices.Length; v = v + 3, x++) { if (weight != RenderData.weights[x]) { @@ -1067,7 +1126,7 @@ namespace Radegast.Rendering factor = RenderData.weights[x] - jointindex; weight = weight - jointindex; - string jointname="", jointname2=""; + string jointname = "", jointname2 = ""; if (this.Name == "upperBodyMesh") { @@ -1091,8 +1150,8 @@ namespace Radegast.Rendering { return; // not interested in this mesh } - - + + if (jointname == "") { //Don't yet handle this, its a split joint to two children @@ -1103,13 +1162,13 @@ namespace Radegast.Rendering ba = av.skel.mBones[jointname]; } - if(jointname2=="") + if (jointname2 == "") { - bb=null; + bb = null; } else { - bb = av.skel.mBones[jointname2]; + bb = av.skel.mBones[jointname2]; } } @@ -1131,17 +1190,17 @@ namespace Radegast.Rendering } else { - lerp = ba.getOffset()- ba.getOrigOffset(); + lerp = ba.getOffset() - ba.getOrigOffset(); offset = ba.getOffset(); rot = ba.getRotation(); } Vector3 pos = new Vector3(MorphRenderData.Vertices[v], MorphRenderData.Vertices[v + 1], MorphRenderData.Vertices[v + 2]); - pos = pos + lerp; + pos = pos + lerp; pos = pos - offset; pos = pos * rot; pos = pos + offset; - + RenderData.Vertices[v] = pos.X; RenderData.Vertices[v + 1] = pos.Y; RenderData.Vertices[v + 2] = pos.Z; @@ -1156,13 +1215,13 @@ namespace Radegast.Rendering uint i = mvx.VertexIndex; - MorphRenderData.Vertices[i * 3] = OrigRenderData.Vertices[i*3] + mvx.Coord.X * weight; + MorphRenderData.Vertices[i * 3] = OrigRenderData.Vertices[i * 3] + mvx.Coord.X * weight; MorphRenderData.Vertices[(i * 3) + 1] = OrigRenderData.Vertices[i * 3 + 1] + mvx.Coord.Y * weight; MorphRenderData.Vertices[(i * 3) + 2] = OrigRenderData.Vertices[i * 3 + 2] + mvx.Coord.Z * weight; RenderData.TexCoords[i * 2] = OrigRenderData.TexCoords[i * 2] + mvx.TexCoord.X * weight; RenderData.TexCoords[(i * 2) + 1] = OrigRenderData.TexCoords[i * 2 + 1] + mvx.TexCoord.Y * weight; - + } } } @@ -1172,7 +1231,7 @@ namespace Radegast.Rendering private static Dictionary _defaultmeshes = new Dictionary(); public Dictionary _meshes = new Dictionary(); - public skeleton skel = new skeleton(); + public skeleton skel = new skeleton(); public static Dictionary attachment_points = new Dictionary(); public bool _wireframe = true; @@ -1186,21 +1245,21 @@ namespace Radegast.Rendering public GLAvatar() { - foreach (KeyValuePair kvp in _defaultmeshes) + foreach (KeyValuePair kvp in _defaultmeshes) { - GLMesh mesh = new GLMesh(kvp.Value,this); // Instance our meshes + GLMesh mesh = new GLMesh(kvp.Value, this); // Instance our meshes _meshes.Add(kvp.Key, mesh); - + } } public static void dumptweaks() { - for(int x=0;x kvp in vpx.BoneDeforms) { - skel.deformbone(kvp.Key, new Vector3(0,0,0),kvp.Value*value,Quaternion.Identity); + skel.deformbone(kvp.Key, new Vector3(0, 0, 0), kvp.Value * value, Quaternion.Identity); } } else @@ -1504,11 +1563,11 @@ namespace Radegast.Rendering msex = VisualParamEx.EparamSex.SEX_FEMALE; } } - + foreach (byte vpvalue in av.VisualParameters) { - if (vpsent==true && VisualAppearanceParameters[x] == vpvalue) + if (vpsent == true && VisualAppearanceParameters[x] == vpvalue) { x++; continue; @@ -1532,7 +1591,7 @@ namespace Radegast.Rendering float value = (vpvalue / 255.0f); this.morphtest(av, vpe.ParamID, value); - + x++; } @@ -1599,7 +1658,7 @@ namespace Radegast.Rendering mUpperMeshMapping.Add(14, "mWristRight"); mUpperMeshMapping.Add(15, ""); - mLowerMeshMapping.Add(1,"mPelvis"); + mLowerMeshMapping.Add(1, "mPelvis"); mLowerMeshMapping.Add(2, "mHipRight"); mLowerMeshMapping.Add(3, "mKneeRight"); mLowerMeshMapping.Add(4, "mAnkleRight"); @@ -1667,7 +1726,7 @@ namespace Radegast.Rendering public Vector3 orig_scale; public Vector3 orig_piviot; - Matrix4 mDeformMatrix=Matrix4.Identity; + Matrix4 mDeformMatrix = Matrix4.Identity; public Bone parent; @@ -1732,7 +1791,7 @@ namespace Radegast.Rendering b.orig_scale = new Vector3(b.scale); - float[] deform = Math3D.CreateSRTMatrix(new Vector3(1,1,1), b.rot, b.orig_pos); + float[] deform = Math3D.CreateSRTMatrix(new Vector3(1, 1, 1), b.rot, b.orig_pos); b.mDeformMatrix = new Matrix4(deform[0], deform[1], deform[2], deform[3], deform[4], deform[5], deform[6], deform[7], deform[8], deform[9], deform[10], deform[11], deform[12], deform[13], deform[14], deform[15]); //TODO piviot @@ -1783,11 +1842,11 @@ namespace Radegast.Rendering Vector3 parento = parent.getOffset(); Vector3 mepre = pos * scale; mepre = mepre * totalrot; - return parento+ mepre; + return parento + mepre; } else { - return (pos * scale) *getRotation(); + return (pos * scale) * getRotation(); } } @@ -1841,7 +1900,7 @@ namespace Radegast.Rendering if (parent != null) { - totalrot = rot* parent.getRotation(); + totalrot = rot * parent.getRotation(); } return totalrot; @@ -1852,7 +1911,7 @@ namespace Radegast.Rendering public class VisualParamEx { - static public Dictionary allParams = new Dictionary(); + static public Dictionary allParams = new Dictionary(); static public Dictionary deformParams = new Dictionary(); static public Dictionary morphParams = new Dictionary(); static public Dictionary drivenParams = new Dictionary(); @@ -1905,7 +1964,7 @@ namespace Radegast.Rendering } public string meshname; - + /// Index of this visual param public int ParamID; /// Internal name @@ -1980,15 +2039,15 @@ namespace Radegast.Rendering public VisualParamEx(XmlNode node, ParamType pt) { pType = pt; - + ParamID = Int32.Parse(node.Attributes.GetNamedItem("id").Value); Name = node.Attributes.GetNamedItem("name").Value; Group = Int32.Parse(node.Attributes.GetNamedItem("group").Value); //These dont exist for facal expresion morphs - if(node.Attributes.GetNamedItem("wearable")!=null) + if (node.Attributes.GetNamedItem("wearable") != null) Wearable = node.Attributes.GetNamedItem("wearable").Value; - + MinValue = float.Parse(node.Attributes.GetNamedItem("value_min").Value); MaxValue = float.Parse(node.Attributes.GetNamedItem("value_max").Value); @@ -2022,11 +2081,11 @@ namespace Radegast.Rendering if (Group == (int)GroupType.VISUAL_PARAM_GROUP_TWEAKABLE) { - if(!tweakable_params.ContainsKey(ParamID)) //stupid duplicate shared params + if (!tweakable_params.ContainsKey(ParamID)) //stupid duplicate shared params { tweakable_params.Add(this.ParamID, this); } - Logger.Log(String.Format("Adding tweakable paramater ID {0} {1}", count, this.Name),Helpers.LogLevel.Info); + Logger.Log(String.Format("Adding tweakable paramater ID {0} {1}", count, this.Name), Helpers.LogLevel.Info); count++; } @@ -2045,11 +2104,11 @@ namespace Radegast.Rendering { // If we are in the skeleton section then we also have bone deforms to parse BoneDeforms = new Dictionary(); - if(node.HasChildNodes && node.ChildNodes[0].HasChildNodes) + if (node.HasChildNodes && node.ChildNodes[0].HasChildNodes) { - ParseBoneDeforms(node.ChildNodes[0].ChildNodes); + ParseBoneDeforms(node.ChildNodes[0].ChildNodes); } - deformParams.Add(ParamID,this); + deformParams.Add(ParamID, this); } if (pt == ParamType.TYPE_MORPH) @@ -2097,7 +2156,7 @@ namespace Radegast.Rendering } } - + } void ParseBoneDeforms(XmlNodeList deforms) @@ -2169,8 +2228,8 @@ namespace Radegast.Rendering d.hasMinMax = false; } - childparams.Add(d); - + childparams.Add(d); + } } } -- 2.11.0