Browse Source

Improving runtime APIs

Vicente Penades 5 years ago
parent
commit
6d29079c1a

+ 12 - 10
src/PackageInfo.props

@@ -2,31 +2,33 @@
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
   <PropertyGroup>
-    
+
     <Authors>Vicente Penades</Authors>
     <Copyright>Copyright (c) 2020 Vicente Penades</Copyright>
     <Description>SharpGLTF is a C# library for reading and writing glTF2 3D models</Description>
-    
+
     <RepositoryUrl>https://github.com/vpenades/SharpGLTF</RepositoryUrl>
     <RepositoryType>git</RepositoryType>
-    
+
     <PackageTags>C# glTF 3D</PackageTags>
     <PackageProjectUrl>https://github.com/vpenades/SharpGLTF</PackageProjectUrl>
     <PackageIcon>glTF2Sharp.png</PackageIcon>
-    
+
     <DocumentationFile>bin\$(Configuration)\$(AssemblyName).xml</DocumentationFile>
-    
+
   </PropertyGroup>
-  
+
   <!-- https://github.com/NuGet/Home/wiki/Packaging-License-within-the-nupkg#project-properties -->
 
   <PropertyGroup>
     <PackageLicenseExpression>MIT</PackageLicenseExpression>
-  </PropertyGroup>  
-  
+  </PropertyGroup>
+
   <ItemGroup>
-    <None Include="$(MsBuildThisFileDirectory)..\build\Icons\glTF2Sharp.png" Pack="true" Visible="false" PackagePath="" />  
+    <None Include="$(MsBuildThisFileDirectory)..\build\Icons\glTF2Sharp.png" Pack="true" Visible="false" PackagePath="" />
   </ItemGroup>
+
   
-	
+
+
 </Project>

+ 11 - 12
src/SharpGLTF.Core/Runtime/ArmatureInstance.cs

@@ -15,30 +15,29 @@ namespace SharpGLTF.Runtime
 
         internal ArmatureInstance(ArmatureTemplate template)
         {
-            _AnimationTracks = template.Tracks;
-
             _NodeTemplates = template.Nodes;
-            _NodeInstances = new NodeInstance[_NodeTemplates.Length];
 
-            for (var i = 0; i < _NodeInstances.Length; ++i)
+            var ni = new NodeInstance[_NodeTemplates.Count];
+
+            for (var i = 0; i < ni.Length; ++i)
             {
                 var n = _NodeTemplates[i];
-                var pidx = _NodeTemplates[i].ParentIndex;
+                var p = n.ParentIndex < 0 ? null : ni[n.ParentIndex];
 
-                if (pidx >= i) throw new ArgumentException("invalid parent index", nameof(template.Nodes));
+                ni[i] = new NodeInstance(n, p);
+            }
 
-                var p = pidx < 0 ? null : _NodeInstances[pidx];
+            _NodeInstances = ni;
 
-                _NodeInstances[i] = new NodeInstance(n, p);
-            }
+            _AnimationTracks = template.Tracks;
         }
 
         #endregion
 
         #region data
 
-        private readonly NodeTemplate[] _NodeTemplates;
-        private readonly NodeInstance[] _NodeInstances;
+        private readonly IReadOnlyList<NodeTemplate> _NodeTemplates;
+        private readonly IReadOnlyList<NodeInstance> _NodeInstances;
 
         private readonly AnimationTrackInfo[] _AnimationTracks;
 
@@ -81,7 +80,7 @@ namespace SharpGLTF.Runtime
         {
             var n = LogicalNodes.FirstOrDefault(item => item.Name == name);
             if (n == null) return;
-            n.WorldMatrix = worldMatrix;
+            n.ModelMatrix = worldMatrix;
         }
 
         public void SetPoseTransforms()

+ 30 - 5
src/SharpGLTF.Core/Runtime/ArmatureTemplate.cs

@@ -5,15 +5,24 @@ using System.Text;
 
 namespace SharpGLTF.Runtime
 {
+    /// <summary>
+    /// Represents a flattened collection of nodes/joints/bones, which define a Skeleton when correlated.
+    /// </summary>
+    /// /// <remarks>
+    /// Only the nodes used by a given <see cref="Schema2.Scene"/> will be copied.
+    /// Also, nodes will be reordered so children nodes always come after their parents (for fast evaluation),
+    /// so it's important to keek in mind that <see cref="NodeTemplate"/> indices will differ from those
+    /// in <see cref="Schema2.Scene"/>.
+    /// </remarks>
     class ArmatureTemplate
     {
         #region lifecycle
 
         /// <summary>
-        /// Creates a new <see cref="ArmatureTemplate"/> from a given <see cref="Schema2.Scene"/>.
+        /// Creates a new <see cref="ArmatureTemplate"/> based on the nodes of <see cref="Schema2.Scene"/>.
         /// </summary>
-        /// <param name="srcScene">The source <see cref="Schema2.Scene"/> to templatize.</param>
-        /// <param name="isolateMemory">True if we want to copy data instead of sharing it.</param>
+        /// <param name="srcScene">The source <see cref="Schema2.Scene"/> from where to take the nodes.</param>
+        /// <param name="isolateMemory">True if we want to copy the source data instead of share it.</param>
         /// <returns>A new <see cref="ArmatureTemplate"/> instance.</returns>
         public static ArmatureTemplate Create(Schema2.Scene srcScene, bool isolateMemory)
         {
@@ -41,7 +50,6 @@ namespace SharpGLTF.Runtime
 
                 // parent index
                 var pidx = indexSolver(srcNode.Key.VisualParent);
-                if (pidx >= nidx) throw new InvalidOperationException("parent indices should be below child indices");
 
                 // child indices
                 var cidx = srcNode.Key.VisualChildren
@@ -63,6 +71,23 @@ namespace SharpGLTF.Runtime
 
         private ArmatureTemplate(NodeTemplate[] nodes, AnimationTrackInfo[] animTracks)
         {
+            // check that child nodes always follow parent nodes
+
+            for (int idx = 0; idx < nodes.Length; ++idx)
+            {
+                var n = nodes[idx];
+
+                if (n == null) throw new ArgumentNullException(nameof(nodes));
+                if (n.ParentIndex >= idx) throw new ArgumentOutOfRangeException(nameof(nodes), $"[{idx}].ParentIndex must be lower than {idx}, but found {n.ParentIndex}");
+
+                for (int j = 0; j < n.ChildIndices.Count; ++j)
+                {
+                    var cidx = n.ChildIndices[j];
+                    if (cidx >= nodes.Length) throw new ArgumentOutOfRangeException(nameof(nodes), $"[{idx}].ChildIndices[{j}] must be lower than {nodes.Length}, but found {cidx}");
+                    if (cidx <= idx) throw new ArgumentOutOfRangeException(nameof(nodes), $"[{idx}].ChildIndices[{j}] must be heigher than {idx}, but found {cidx}");
+                }
+            }
+
             _NodeTemplates = nodes;
             _AnimationTracks = animTracks;
         }
@@ -78,7 +103,7 @@ namespace SharpGLTF.Runtime
 
         #region properties
 
-        public NodeTemplate[] Nodes => _NodeTemplates;
+        public IReadOnlyList<NodeTemplate> Nodes => _NodeTemplates;
 
         public AnimationTrackInfo[] Tracks => _AnimationTracks;
 

+ 7 - 7
src/SharpGLTF.Core/Runtime/DrawableTemplate.cs

@@ -51,7 +51,7 @@ namespace SharpGLTF.Runtime
 
         public abstract Transforms.IGeometryTransform CreateGeometryTransform();
 
-        public abstract void UpdateGeometryTransform(Transforms.IGeometryTransform geoxform, IReadOnlyList<NodeInstance> instances);
+        public abstract void UpdateGeometryTransform(Transforms.IGeometryTransform geoxform, ArmatureInstance armature);
 
         #endregion
     }
@@ -81,12 +81,12 @@ namespace SharpGLTF.Runtime
 
         public override Transforms.IGeometryTransform CreateGeometryTransform() { return new Transforms.RigidTransform(); }
 
-        public override void UpdateGeometryTransform(Transforms.IGeometryTransform rigidTransform, IReadOnlyList<NodeInstance> instances)
+        public override void UpdateGeometryTransform(Transforms.IGeometryTransform rigidTransform, ArmatureInstance armature)
         {
-            var node = instances[_NodeIndex];
+            var node = armature.LogicalNodes[_NodeIndex];
 
             var statxform = (Transforms.RigidTransform)rigidTransform;
-            statxform.Update(node.WorldMatrix);
+            statxform.Update(node.ModelMatrix);
             statxform.Update(node.MorphWeights, false);
         }
 
@@ -133,11 +133,11 @@ namespace SharpGLTF.Runtime
 
         public override Transforms.IGeometryTransform CreateGeometryTransform() { return new Transforms.SkinnedTransform(); }
 
-        public override void UpdateGeometryTransform(Transforms.IGeometryTransform skinnedTransform, IReadOnlyList<NodeInstance> instances)
+        public override void UpdateGeometryTransform(Transforms.IGeometryTransform skinnedTransform, ArmatureInstance armature)
         {
             var skinxform = (Transforms.SkinnedTransform)skinnedTransform;
-            skinxform.Update(_JointsNodeIndices.Length, idx => _BindMatrices[idx], idx => instances[_JointsNodeIndices[idx]].WorldMatrix);
-            skinxform.Update(instances[_MorphNodeIndex].MorphWeights, false);
+            skinxform.Update(_JointsNodeIndices.Length, idx => _BindMatrices[idx], idx => armature.LogicalNodes[_JointsNodeIndices[idx]].ModelMatrix);
+            skinxform.Update(armature.LogicalNodes[_MorphNodeIndex].MorphWeights, false);
         }
 
         #endregion

+ 13 - 7
src/SharpGLTF.Core/Runtime/NodeInstance.cs

@@ -48,6 +48,9 @@ namespace SharpGLTF.Runtime
             set => _MorphWeights = value;
         }
 
+        /// <summary>
+        /// Gets or sets the transform matrix of this node in Local Space.
+        /// </summary>
         public XFORM LocalMatrix
         {
             get => _LocalMatrix;
@@ -58,10 +61,13 @@ namespace SharpGLTF.Runtime
             }
         }
 
-        public XFORM WorldMatrix
+        /// <summary>
+        /// Gets or sets the transform matrix of this node in Model Space.
+        /// </summary>
+        public XFORM ModelMatrix
         {
-            get => _GetWorldMatrix();
-            set => _SetWorldMatrix(value);
+            get => _GetModelMatrix();
+            set => _SetModelMatrix(value);
         }
 
         /// <summary>
@@ -81,20 +87,20 @@ namespace SharpGLTF.Runtime
 
         #region API
 
-        private XFORM _GetWorldMatrix()
+        private XFORM _GetModelMatrix()
         {
             if (!TransformChainIsDirty) return _WorldMatrix.Value;
 
-            _WorldMatrix = _Parent == null ? _LocalMatrix : XFORM.Multiply(_LocalMatrix, _Parent.WorldMatrix);
+            _WorldMatrix = _Parent == null ? _LocalMatrix : XFORM.Multiply(_LocalMatrix, _Parent.ModelMatrix);
 
             return _WorldMatrix.Value;
         }
 
-        private void _SetWorldMatrix(XFORM xform)
+        private void _SetModelMatrix(XFORM xform)
         {
             if (_Parent == null) { LocalMatrix = xform; return; }
 
-            XFORM.Invert(_Parent._GetWorldMatrix(), out XFORM ipwm);
+            XFORM.Invert(_Parent._GetModelMatrix(), out XFORM ipwm);
 
             LocalMatrix = XFORM.Multiply(xform, ipwm);
         }

+ 7 - 18
src/SharpGLTF.Core/Runtime/SceneInstance.cs

@@ -19,6 +19,9 @@ namespace SharpGLTF.Runtime
 
         internal SceneInstance(ArmatureTemplate armature, DrawableTemplate[] drawables)
         {
+            Guard.NotNull(armature, nameof(armature));
+            Guard.NotNull(drawables, nameof(drawables));
+
             _Armature = new ArmatureInstance(armature);
 
             _DrawableReferences = drawables;
@@ -34,6 +37,9 @@ namespace SharpGLTF.Runtime
 
         #region data
 
+        /// <summary>
+        /// Represents the skeleton that's going to be used by each drawing command to draw the model matrices.
+        /// </summary>
         private readonly ArmatureInstance _Armature;
 
         private readonly DrawableTemplate[] _DrawableReferences;
@@ -68,23 +74,6 @@ namespace SharpGLTF.Runtime
 
         #region API
 
-        /// <summary>
-        /// Gets a drawable reference pair, where:
-        /// - MeshIndex is the logical Index of a <see cref="Schema2.Mesh"/> in <see cref="Schema2.ModelRoot.LogicalMeshes"/>.
-        /// - Transform is an <see cref="IGeometryTransform"/> that can be used to transform the <see cref="Schema2.Mesh"/> into world space.
-        /// </summary>
-        /// <param name="index">The index of the drawable reference, from 0 to <see cref="DrawableInstancesCount"/></param>
-        /// <returns>A drawable reference</returns>
-        [Obsolete("Use GetDrawableInstance")]
-        public (int MeshIndex, IGeometryTransform Transform) GetDrawableReference(int index)
-        {
-            var dref = _DrawableReferences[index];
-
-            dref.UpdateGeometryTransform(_DrawableTransforms[index], _Armature.LogicalNodes);
-
-            return (dref.LogicalMeshIndex, _DrawableTransforms[index]);
-        }
-
         /// <summary>
         /// Gets a <see cref="DrawableInstance"/> object, where:
         /// - Name is the name of this drawable instance. Originally, it was the name of <see cref="Schema2.Node"/>.
@@ -97,7 +86,7 @@ namespace SharpGLTF.Runtime
         {
             var dref = _DrawableReferences[index];
 
-            dref.UpdateGeometryTransform(_DrawableTransforms[index], _Armature.LogicalNodes);
+            dref.UpdateGeometryTransform(_DrawableTransforms[index], _Armature);
 
             return new DrawableInstance(dref, _DrawableTransforms[index]);
         }

+ 3 - 3
src/SharpGLTF.Core/SharpGLTF.Core.csproj

@@ -6,10 +6,10 @@
     <RootNamespace>SharpGLTF</RootNamespace>
     <LangVersion>7.3</LangVersion>
     <DebugSymbols>true</DebugSymbols>    
-  </PropertyGroup>  
-  
-  <Import Project="..\Version.props" />  
+  </PropertyGroup>
+
   <Import Project="..\PackageInfo.props" />
+  <Import Project="..\Version.props" />
   <Import Project="..\Analyzers.props" />
   
   <ItemGroup>

+ 1 - 1
src/SharpGLTF.Toolkit/SharpGLTF.Toolkit.csproj

@@ -9,8 +9,8 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>    
   </PropertyGroup>
 
-  <Import Project="..\Version.props" />
   <Import Project="..\PackageInfo.props" />
+  <Import Project="..\Version.props" />
   <Import Project="..\Analyzers.props" />
 
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">

+ 15 - 1
src/Version.props

@@ -10,9 +10,19 @@
   </PropertyGroup>
 
   <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+    
+    <!-- Optional: Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
+    <PublishRepositoryUrl>true</PublishRepositoryUrl>
+    
+    <!-- Optional: Embed source files that are not tracked by the source control manager in the PDB -->
+    <EmbedUntrackedSources>false</EmbedUntrackedSources>
+
+    <!-- Optional: Build symbol package (.snupkg) to distribute the PDB containing Source Link -->
     <IncludeSymbols>true</IncludeSymbols>
     <SymbolPackageFormat>snupkg</SymbolPackageFormat>
+    
+    <!-- Required -->
+    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>    
   </PropertyGroup>
 
   <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
@@ -21,6 +31,10 @@
     <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)SharpGLTF.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
 
+  <ItemGroup Condition=" '$(Configuration)' == 'Release' ">
+    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
+  </ItemGroup>
+
 
   <!--
   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">