public Animation_NodeMisc(List <string> imageList)
        {
            Runtime.Image baseColorTextureImage = UseTexture(imageList, "BaseColor_Cube");

            // There are no common properties in this model group that are reported in the readme.

            Model CreateModel(Action <List <Property>, List <Runtime.AnimationChannel>, List <Runtime.Node>, List <Runtime.Animation> > setProperties)
            {
                var properties        = new List <Property>();
                var cubeMeshPrimitive = MeshPrimitive.CreateCube();

                // Apply the common properties to the gltf.
                cubeMeshPrimitive.Material = new Runtime.Material
                {
                    MetallicRoughnessMaterial = new Runtime.PbrMetallicRoughness
                    {
                        BaseColorTexture = new Runtime.Texture {
                            Source = baseColorTextureImage
                        },
                    },
                };
                var channels = new List <Runtime.AnimationChannel>
                {
                    new Runtime.AnimationChannel()
                };
                var nodes = new List <Runtime.Node>
                {
                    new Runtime.Node(),
                };
                var animations = new List <Runtime.Animation>
                {
                    new Runtime.Animation
                    {
                        Channels = channels
                    }
                };

                // Apply the properties that are specific to this gltf.
                setProperties(properties, channels, nodes, animations);

                // Create the gltf object.
                foreach (var node in nodes)
                {
                    node.Mesh = new Runtime.Mesh
                    {
                        MeshPrimitives = new List <Runtime.MeshPrimitive>
                        {
                            cubeMeshPrimitive
                        }
                    };
                }
                Runtime.GLTF gltf = CreateGLTF(() => new Runtime.Scene
                {
                    Nodes = nodes
                });
                gltf.Animations = animations;
                return(new Model
                {
                    Properties = properties,
                    GLTF = gltf,
                    Animated = true,
                });
            }

            void SetTranslationChannelTarget(Runtime.AnimationChannel channel, Runtime.Node node)
            {
                channel.Target = new Runtime.AnimationChannelTarget
                {
                    Node = node,
                    Path = Runtime.AnimationChannelTarget.PathEnum.TRANSLATION,
                };
            }

            void SetRotationChannelTarget(Runtime.AnimationChannel channel, Runtime.Node node)
            {
                channel.Target = new Runtime.AnimationChannelTarget
                {
                    Node = node,
                    Path = Runtime.AnimationChannelTarget.PathEnum.ROTATION,
                };
            }

            void SetLinearSamplerForTranslation(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                    2.0f,
                    4.0f,
                },
                    new[]
                {
                    new Vector3(-0.1f, 0.0f, 0.0f),
                    new Vector3(0.1f, 0.0f, 0.0f),
                    new Vector3(-0.1f, 0.0f, 0.0f),
                }
                                  );
            }

            void SetLinearSamplerForHorizontalRotation(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                },
                    new[]
                {
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                }
                                  );
            }

            void SetLinearSamplerForVerticalRotation(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                },
                    new[]
                {
                    Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(90.0f), 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(-90.0f), 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(90.0f), 0.0f),
                }
                                  );
            }

            void SetLinearSamplerForConstantRotation(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    0.0f,
                    6.0f,
                },
                    new[]
                {
                    Quaternion.CreateFromYawPitchRoll(-FloatMath.Pi / 3.0f, 0.0f, 0.0f),
                    Quaternion.CreateFromYawPitchRoll(-FloatMath.Pi / 3.0f, 0.0f, 0.0f),
                }
                                  );
            }

            void SetLinearSamplerForTranslationStartsAboveZero(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    2.0f,
                    4.0f,
                    6.0f,
                },
                    new[]
                {
                    new Vector3(0.0f, -0.1f, 0.0f),
                    new Vector3(0.0f, 0.1f, 0.0f),
                    new Vector3(0.0f, -0.1f, 0.0f),
                }
                                  );
            }

            void SetLinearSamplerWithOneKey(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                },
                    new[]
                {
                    new Vector3(-0.1f, 0.0f, 0.0f),
                }
                                  );
            }

            void SetLinearSamplerForRotationThatStartsAboveZero(Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                    5.0f,
                },
                    new[]
                {
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                }
                                  );
            }

            void CreateMultipleChannelsWithUniqueTargets(List <Runtime.AnimationChannel> channels, Runtime.Node node)
            {
                // The first channel is already added as a common property.
                channels.Add(new Runtime.AnimationChannel());

                SetTranslationChannelTarget(channels[0], node);
                SetRotationChannelTarget(channels[1], node);

                var samplerPropertiesList = new List <Property>();

                SetLinearSamplerForTranslation(channels[0]);
                SetLinearSamplerForHorizontalRotation(channels[1]);
            }

            void CreateMultipleChannelsWithDifferentTimes(List <Runtime.AnimationChannel> channels, Runtime.Node node)
            {
                // The first channel is already added as a common property.
                channels.Add(new Runtime.AnimationChannel());

                SetTranslationChannelTarget(channels[0], node);
                SetRotationChannelTarget(channels[1], node);

                SetLinearSamplerForTranslationStartsAboveZero(channels[0]);
                SetLinearSamplerForRotationThatStartsAboveZero(channels[1]);
            }

            void CreateMultipleChannelsForDifferentNodes(List <Runtime.AnimationChannel> channels, Runtime.Node node0, Runtime.Node node1)
            {
                // The first channel is already added as a common property.
                channels.Add(new Runtime.AnimationChannel());

                SetRotationChannelTarget(channels[0], node0);
                SetRotationChannelTarget(channels[1], node1);

                SetLinearSamplerForHorizontalRotation(channels[0]);
                SetLinearSamplerForVerticalRotation(channels[1]);
            }

            Models = new List <Model>
            {
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Multiple channels
                    CreateMultipleChannelsWithUniqueTargets(channels, nodes[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There are two channels. The first channel targets translation. The second channel targets rotation. The start and end times of both channels are `0.0` and `4.0` respectively."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Curve that doesn't start at zero
                    SetRotationChannelTarget(channels[0], nodes[0]);
                    SetLinearSamplerForRotationThatStartsAboveZero(channels[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There is one channel with a non-zero start time. The channel targets rotation. The start time is `1.0`."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Two channels with different start/end times
                    CreateMultipleChannelsWithDifferentTimes(channels, nodes[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There are two channels with different start and end times. The first channel targets translation with start and end times of `2.0` and `6.0` respectively. The second channel targets rotation with start and end times of `1.0` and `5.0` respectively."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Has only one key
                    SetTranslationChannelTarget(channels[0], nodes[0]);
                    SetLinearSamplerWithOneKey(channels[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There is one channel with only one keyframe. The channel targets translation with a value of <code>[-0.1,&nbsp;0.0,&nbsp;0.0]</code>."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Creates a second node based on the existing node, and applies a transform to help differentiate them.
                    nodes.Add(DeepCopy.CloneObject(nodes[0]));
                    nodes[0].Translation = new Vector3(-0.2f, 0.0f, 0.0f);
                    nodes[1].Translation = new Vector3(0.2f, 0.0f, 0.0f);
                    nodes[0].Scale       = new Vector3(0.5f, 0.5f, 0.5f);
                    nodes[1].Scale       = new Vector3(0.5f, 0.5f, 0.5f);

                    // One animation, two channels for two nodes.
                    CreateMultipleChannelsForDifferentNodes(channels, nodes[0], nodes[1]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There are two channels with different nodes. The first channel targets the left node and rotation along the X axis. The second channel targets the right node and rotation along the Y axis."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Rotate the model, and then apply the same target animation to it (Animation overrides)
                    nodes[0].Rotation = Quaternion.CreateFromYawPitchRoll(FloatMath.Pi / 3.0f, 0.0f, 0.0f);
                    SetRotationChannelTarget(channels[0], nodes[0]);
                    SetLinearSamplerForConstantRotation(channels[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There is one channel that targets a node. The node has a rotation of <code>[0.0,&nbsp;0.5,&nbsp;0.0,&nbsp;0.866]</code>. The channel overrides the rotation of the node to a different constant value of <code>[0.0,&nbsp;-0.5,&nbsp;0.0,&nbsp;0.866]</code>."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Rotate the model, and then apply an translation animation to it (Animation doesn't override rotation)
                    nodes[0].Rotation = Quaternion.CreateFromYawPitchRoll(FloatMath.Pi / 3.0f, 0.0f, 0.0f);
                    SetTranslationChannelTarget(channels[0], nodes[0]);
                    SetLinearSamplerForTranslation(channels[0]);
                    properties.Add(new Property(PropertyName.Description,
                                                "There is one channel that targets a node. The node has a rotation of <code>[0.0,&nbsp;0.5,&nbsp;0.0,&nbsp;0.866]</code>. The channel targets the translation of the node."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Two animations. One rotates, the other translates. They should not interact or bleed across.
                    var channel = new Runtime.AnimationChannel();
                    SetTranslationChannelTarget(channel, nodes[0]);
                    SetLinearSamplerForTranslation(channel);
                    animations.Add(new Runtime.Animation
                    {
                        Channels = new[]
                        {
                            channel
                        }
                    });

                    // The first animation is already added as an empty common property.
                    SetRotationChannelTarget(channels[0], nodes[0]);
                    SetLinearSamplerForHorizontalRotation(channels[0]);

                    properties.Add(new Property(PropertyName.Description,
                                                "There are two animations, each with one channel. The first animation's channel targets rotation. The second animation's channel targets translation."));
                }),
                CreateModel((properties, channels, nodes, animations) =>
                {
                    // Multiple channels, but one omits node (the channel with no target node is ignored per the spec).
                    CreateMultipleChannelsForDifferentNodes(channels, null, nodes[0]);

                    properties.Add(new Property(PropertyName.Description,
                                                "There are two channels. The first channel has a rotation along the X axis but does not specify a node. The second channel does target the node and has a rotation along the Y axis."));
                }),
            };

            GenerateUsedPropertiesList();
        }
        public Instancing(List <string> imageList)
        {
            var baseColorImageA    = UseTexture(imageList, "BaseColor_A");
            var baseColorImageB    = UseTexture(imageList, "BaseColor_B");
            var baseColorImageCube = UseTexture(imageList, "BaseColor_Cube");
            var distantCamera      = new Manifest.Camera(new Vector3(0.0f, 0.0f, 2.7f));

            // There are no common properties in this model group that are reported in the readme.

            TextureInfo CreateTextureInfo(Image source)
            {
                return(new TextureInfo
                {
                    Texture = new Texture
                    {
                        Source = source,
                    }
                });
            }

            Model CreateModel(Action <List <Property>, List <Node>, List <Animation> > setProperties, Action <Model> setCamera)
            {
                var properties = new List <Property>();
                var animations = new List <Animation>();
                var animated   = true;
                var nodes      = new List <Node>();

                // Apply the properties that are specific to this gltf.
                setProperties(properties, nodes, animations);

                // If no animations are used, null out that property.
                if (!animations.Any())
                {
                    animations = null;
                    animated   = false;
                }

                // Create the gltf object.
                var model = new Model
                {
                    Properties = properties,
                    GLTF       = CreateGLTF(() => new Scene {
                        Nodes = nodes
                    }, animations: animations),
                    Animated = animated,
                };

                setCamera(model);

                return(model);
            }

            var samplerInputLinear = Data.Create(new[]
            {
                0.0f,
                1.0f,
                2.0f,
                3.0f,
                4.0f,
            });

            var samplerInputCurve = Data.Create(new[]
            {
                0.0f,
                0.5f,
                1.0f,
                2.0f,
                4.0f,
            });

            var samplerOutput = Data.Create(new[]
            {
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(90.0f), 0.0f),
                Quaternion.Identity,
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(-90.0f), 0.0f),
                Quaternion.Identity,
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(90.0f), 0.0f),
            });

            var samplerOutputReverse = Data.Create(new[]
            {
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(-90.0f), 0.0f),
                Quaternion.Identity,
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(90.0f), 0.0f),
                Quaternion.Identity,
                Quaternion.CreateFromYawPitchRoll(0.0f, FloatMath.ToRadians(-90.0f), 0.0f),
            });

            Runtime.Material CreateMaterial(TextureInfo textureInfo)
            {
                return(new Runtime.Material
                {
                    PbrMetallicRoughness = new PbrMetallicRoughness
                    {
                        BaseColorTexture = textureInfo
                    }
                });
            }

            void AddMeshPrimitivesToSingleNode(List <Node> nodes, List <Runtime.MeshPrimitive> meshPrimitives)
            {
                // If there are multiple mesh primitives, offset their position so they don't overlap.
                if (meshPrimitives.Count > 1)
                {
                    meshPrimitives[0].Positions.Values = meshPrimitives[0].Positions.Values.Select(position => { return(new Vector3(position.X - 0.6f, position.Y, position.Z)); });
                    meshPrimitives[1].Positions.Values = meshPrimitives[1].Positions.Values.Select(position => { return(new Vector3(position.X + 0.6f, position.Y, position.Z)); });
                }

                nodes.Add(
                    new Node
                {
                    Mesh = new Runtime.Mesh
                    {
                        MeshPrimitives = meshPrimitives
                    }
                }
                    );
            }

            void AddMeshPrimitivesToMultipleNodes(List <Node> nodes, Runtime.MeshPrimitive meshPrimitives0, Runtime.MeshPrimitive meshPrimitives1)
            {
                nodes.AddRange(new[]
                {
                    new Node
                    {
                        Translation = new Vector3(-0.6f, 0.0f, 0.0f),
                        Mesh        = new Runtime.Mesh
                        {
                            MeshPrimitives = new List <Runtime.MeshPrimitive>
                            {
                                meshPrimitives0
                            }
                        }
                    },
                    new Node
                    {
                        Translation = new Vector3(0.6f, 0.0f, 0.0f),
                        Mesh        = new Runtime.Mesh
                        {
                            MeshPrimitives = new List <Runtime.MeshPrimitive>
                            {
                                meshPrimitives1
                            }
                        }
                    }
                }
                               );
            }

            void AddAnimation(List <Animation> animations, List <Node> nodes, AnimationSampler sampler0, AnimationSampler sampler1, bool samplerInstanced)
            {
                animations.Add(new Animation
                {
                    Channels = new List <AnimationChannel>
                    {
                        new AnimationChannel
                        {
                            Target = new AnimationChannelTarget
                            {
                                Node = nodes[0],
                                Path = AnimationChannelTargetPath.Rotation,
                            },
                            Sampler = sampler0
                        },
                        new AnimationChannel
                        {
                            Target = new AnimationChannelTarget
                            {
                                Node = nodes[1],
                                Path = AnimationChannelTargetPath.Rotation,
                            },
                            Sampler = sampler1
                        },
                    }
                });
            }

            Models = new List <Model>
            {
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitives = new List <Runtime.MeshPrimitive>
                    {
                        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false),
                        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false)
                    };

                    foreach (Runtime.MeshPrimitive meshPrimitive in meshPrimitives)
                    {
                        // This non-standard set of texture coordinates is larger than the texture but not an exact multiple, so it allows texture sampler settings to be visible.
                        meshPrimitive.TexCoords0 = Data.Create <Vector2>
                                                   (
                            new[]
                        {
                            new Vector2(1.3f, 1.3f),
                            new Vector2(-0.3f, 1.3f),
                            new Vector2(-0.3f, -0.3f),
                            new Vector2(1.3f, -0.3f),
                        }
                                                   );
                    }

                    meshPrimitives[0].Material = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    meshPrimitives[1].Material = CreateMaterial(CreateTextureInfo(baseColorImageA));

                    meshPrimitives[0].Material.PbrMetallicRoughness.BaseColorTexture.Texture.Sampler = new Sampler
                    {
                        WrapT = SamplerWrap.ClampToEdge,
                        WrapS = SamplerWrap.ClampToEdge
                    };
                    meshPrimitives[1].Material.PbrMetallicRoughness.BaseColorTexture.Texture.Sampler = new Sampler
                    {
                        WrapT = SamplerWrap.MirroredRepeat,
                        WrapS = SamplerWrap.MirroredRepeat
                    };

                    AddMeshPrimitivesToSingleNode(nodes, meshPrimitives);

                    properties.Add(new Property(PropertyName.Description, "Two textures using the same image as their source."));
                    properties.Add(new Property(PropertyName.Difference, "The texture sampler `WrapT` and `WrapS` are set to `CLAMP_TO_EDGE` for one and `MIRRORED_REPEAT` for the other."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitives = new List <Runtime.MeshPrimitive>
                    {
                        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false),
                        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false)
                    };

                    meshPrimitives[0].Material = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    meshPrimitives[1].Material = CreateMaterial(CreateTextureInfo(baseColorImageB));

                    var sampler = new Sampler
                    {
                        WrapT = SamplerWrap.ClampToEdge,
                        WrapS = SamplerWrap.ClampToEdge
                    };
                    foreach (Runtime.MeshPrimitive meshPrimitive in meshPrimitives)
                    {
                        meshPrimitive.Material.PbrMetallicRoughness.BaseColorTexture.Texture.Sampler = sampler;
                        // This non-standard set of texture coordinates is larger than the texture but not an exact multiple, so it allows texture sampler settings to be visible.
                        meshPrimitive.TexCoords0 = Data.Create <Vector2>
                                                   (
                            new[]
                        {
                            new Vector2(1.3f, 1.3f),
                            new Vector2(-0.3f, 1.3f),
                            new Vector2(-0.3f, -0.3f),
                            new Vector2(1.3f, -0.3f),
                        }
                                                   );
                    }

                    AddMeshPrimitivesToSingleNode(nodes, meshPrimitives);

                    properties.Add(new Property(PropertyName.Description, "Two textures using the same sampler."));
                    properties.Add(new Property(PropertyName.Difference, "One texture uses image A while the other uses image B."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitives = new List <Runtime.MeshPrimitive>
                    {
                        MeshPrimitive.CreateSinglePlane(),
                        MeshPrimitive.CreateSinglePlane()
                    };

                    var texture = CreateTextureInfo(baseColorImageA);
                    foreach (Runtime.MeshPrimitive meshPrimitive in meshPrimitives)
                    {
                        meshPrimitive.Material = CreateMaterial(texture);
                    }
                    meshPrimitives[0].Material.PbrMetallicRoughness.BaseColorTexture = meshPrimitives[1].Material.PbrMetallicRoughness.BaseColorTexture;
                    meshPrimitives[1].Material.PbrMetallicRoughness.BaseColorFactor  = new Vector4(0.5f, 0.5f, 1.0f, 1.0f);

                    AddMeshPrimitivesToSingleNode(nodes, meshPrimitives);

                    properties.Add(new Property(PropertyName.Description, "Two textures using the same source image."));
                    properties.Add(new Property(PropertyName.Difference, "One material does not have a baseColorFactor and the other has a blue baseColorFactor."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitives = new List <Runtime.MeshPrimitive>
                    {
                        MeshPrimitive.CreateSinglePlane(),
                        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false)
                    };
                    var material = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    foreach (Runtime.MeshPrimitive meshPrimitive in meshPrimitives)
                    {
                        meshPrimitive.Material = material;
                    }

                    // One of the primitives has a 'zoomed in' texture coordinate set.
                    meshPrimitives[1].TexCoords0 = Data.Create <Vector2>
                                                   (
                        new[]
                    {
                        new Vector2(0.9f, 0.9f),
                        new Vector2(0.1f, 0.9f),
                        new Vector2(0.1f, 0.1f),
                        new Vector2(0.9f, 0.1f),
                    }
                                                   );

                    AddMeshPrimitivesToSingleNode(nodes, meshPrimitives);

                    properties.Add(new Property(PropertyName.Description, "Two primitives using the same material."));
                    properties.Add(new Property(PropertyName.Difference, "One primitive has texture coordinates that displays all of texture A, while the other primitive has textures coordinates that don't display the border."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive0      = MeshPrimitive.CreateSinglePlane();
                    var meshPrimitive1      = MeshPrimitive.CreateSinglePlane();
                    meshPrimitive0.Material = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    meshPrimitive1.Material = CreateMaterial(CreateTextureInfo(baseColorImageB));

                    meshPrimitive0.Positions = meshPrimitive1.Positions;

                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive0, meshPrimitive1);

                    properties.Add(new Property(PropertyName.Description, "Two primitives using the same accessors for the `POSITION` attribute."));
                    properties.Add(new Property(PropertyName.Difference, "One primitive uses texture A while the other primitive uses texture B."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive0      = MeshPrimitive.CreateSinglePlane(includeIndices: false);
                    var meshPrimitive1      = MeshPrimitive.CreateSinglePlane();
                    meshPrimitive0.Material = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    meshPrimitive1.Material = CreateMaterial(CreateTextureInfo(baseColorImageB));

                    meshPrimitive0.Indices = meshPrimitive1.Indices;

                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive0, meshPrimitive1);

                    properties.Add(new Property(PropertyName.Description, "Two primitives using the same accessors for indices."));
                    properties.Add(new Property(PropertyName.Difference, "One primitive uses texture A while the other primitive uses texture B."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive      = MeshPrimitive.CreateSinglePlane();
                    meshPrimitive.Material = CreateMaterial(CreateTextureInfo(baseColorImageA));

                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive, meshPrimitive);
                    nodes[1].Mesh = nodes[0].Mesh;

                    properties.Add(new Property(PropertyName.Description, "Two nodes using the same mesh."));
                    properties.Add(new Property(PropertyName.Difference, "The two nodes have different translations."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    nodes.AddRange(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3));
                    nodes[0].Name = "plane0";
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());

                    // Adds just the node containing the mesh, dropping the data for a second set of joints.
                    nodes.Add(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3)[0]);
                    nodes[2].Name = "plane1";
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageB));
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());
                    nodes[2].Skin = nodes[0].Skin;

                    // Offsets the position of both meshes so they don't overlap.
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).Positions.Values = nodes[0].Mesh.MeshPrimitives.ElementAt(0).Positions.Values.Select(position => { return(new Vector3(position.X - 0.3f, position.Y, position.Z)); });
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).Positions.Values = nodes[2].Mesh.MeshPrimitives.ElementAt(0).Positions.Values.Select(position => { return(new Vector3(position.X + 0.3f, position.Y, position.Z)); });

                    properties.Add(new Property(PropertyName.Description, "Two nodes using the same skin."));
                    properties.Add(new Property(PropertyName.Difference, "The two mesh primitives have different `POSITION` values."));
                }, (model) => { model.Camera = null; }),
                CreateModel((properties, nodes, animations) =>
                {
                    nodes.AddRange(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3));
                    nodes[0].Name = "plane0";
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());

                    // Adds just the node containing the mesh, dropping the data for a second set of joints.
                    nodes.Add(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3)[0]);
                    nodes[2].Name = "plane1";
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageB));
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());
                    nodes[2].Skin.Joints = nodes[0].Skin.Joints;

                    // Creates new inverseBindMatrices for the second skin, rotating the flap further than the default value would.
                    nodes[2].Skin.InverseBindMatrices = Data.Create(new[]
                    {
                        nodes[2].Skin.InverseBindMatrices.Values.First(),
                        Matrix4x4.Multiply(nodes[2].Skin.InverseBindMatrices.Values.ElementAt(1), Matrix4x4.CreateRotationX(FloatMath.ToRadians(-30))),
                    });

                    // Offsets the position of both meshes so they don't overlap.
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).Positions.Values = nodes[0].Mesh.MeshPrimitives.ElementAt(0).Positions.Values.Select(position => new Vector3(position.X - 0.3f, position.Y, position.Z));
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).Positions.Values = nodes[2].Mesh.MeshPrimitives.ElementAt(0).Positions.Values.Select(position => new Vector3(position.X + 0.3f, position.Y, position.Z));

                    properties.Add(new Property(PropertyName.Description, "Two skins using the same joints."));
                    properties.Add(new Property(PropertyName.Difference, "The skin with texture B has inverseBindMatrices that fold twice as far as the skin with texture A."));
                }, (model) => { model.Camera = null; }),
                CreateModel((properties, nodes, animations) =>
                {
                    nodes.AddRange(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3));
                    nodes[0].Name = "plane0";
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageA));
                    nodes[0].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());
                    nodes[1].Translation = Vector3.Add((Vector3)nodes[1].Translation, new Vector3(-0.3f, 0.0f, 0.0f));

                    nodes.AddRange(Nodes.CreateFoldingPlaneSkin("skinA", 2, 3));
                    nodes[2].Name = "plane1";
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).Material   = CreateMaterial(CreateTextureInfo(baseColorImageB));
                    nodes[2].Mesh.MeshPrimitives.ElementAt(0).TexCoords0 = Data.Create(Nodes.GetSkinATexCoords());
                    nodes[3].Translation = Vector3.Add((Vector3)nodes[3].Translation, new Vector3(0.3f, 0.0f, 0.0f));

                    nodes[2].Skin.InverseBindMatrices = nodes[0].Skin.InverseBindMatrices;

                    properties.Add(new Property(PropertyName.Description, "Two skins using the same inverseBindMatrices."));
                    properties.Add(new Property(PropertyName.Difference, "The base joint for the two skins have different translations."));
                }, (model) => { model.Camera = null; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive0      = MeshPrimitive.CreateCube();
                    var meshPrimitive1      = MeshPrimitive.CreateCube();
                    var textureInfo         = CreateTextureInfo(baseColorImageCube);
                    meshPrimitive0.Material = CreateMaterial(textureInfo);
                    meshPrimitive1.Material = CreateMaterial(textureInfo);
                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive0, meshPrimitive1);

                    var sampler = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = samplerInputLinear,
                        Output        = samplerOutput,
                    };

                    AddAnimation(animations, nodes, sampler, sampler, true);

                    properties.Add(new Property(PropertyName.Description, "Two animation channels using the same sampler."));
                    properties.Add(new Property(PropertyName.Difference, "The two animation channels target different nodes."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive0      = MeshPrimitive.CreateCube();
                    var meshPrimitive1      = MeshPrimitive.CreateCube();
                    var textureInfo         = CreateTextureInfo(baseColorImageCube);
                    meshPrimitive0.Material = CreateMaterial(textureInfo);
                    meshPrimitive1.Material = CreateMaterial(textureInfo);
                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive0, meshPrimitive1);

                    var sampler0 = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = samplerInputLinear,
                        Output        = samplerOutput,
                    };

                    var sampler1 = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = samplerInputLinear,
                        Output        = samplerOutputReverse,
                    };

                    AddAnimation(animations, nodes, sampler0, sampler1, false);

                    properties.Add(new Property(PropertyName.Description, "Two animation samplers using the same input accessors."));
                    properties.Add(new Property(PropertyName.Difference, "The two animation samplers have different output values."));
                }, (model) => { model.Camera = distantCamera; }),
                CreateModel((properties, nodes, animations) =>
                {
                    var meshPrimitive0      = MeshPrimitive.CreateCube();
                    var meshPrimitive1      = MeshPrimitive.CreateCube();
                    var textureInfo         = CreateTextureInfo(baseColorImageCube);
                    meshPrimitive0.Material = CreateMaterial(textureInfo);
                    meshPrimitive1.Material = CreateMaterial(textureInfo);
                    AddMeshPrimitivesToMultipleNodes(nodes, meshPrimitive0, meshPrimitive1);

                    var sampler0 = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = samplerInputLinear,
                        Output        = samplerOutput,
                    };

                    var sampler1 = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = samplerInputCurve,
                        Output        = samplerOutput,
                    };

                    AddAnimation(animations, nodes, sampler0, sampler1, false);

                    properties.Add(new Property(PropertyName.Description, "Two animation samplers using the same output accessors."));
                    properties.Add(new Property(PropertyName.Difference, "The two animation samplers have different input values."));
                }, (model) => { model.Camera = distantCamera; }),
                // To be implemented later. Needs to work as a type of interleaving.
                //CreateModel((properties, nodes, animations) =>
                //{
                //    var meshPrimitives = new List<Runtime.MeshPrimitive>
                //    {
                //        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false),
                //        MeshPrimitive.CreateSinglePlane(includeTextureCoords: false)
                //    };
                //    meshPrimitives[0].TexCoords0 = meshPrimitives[1].TexCoords0 = MeshPrimitive.GetSinglePlaneTextureCoordSets();
                //    meshPrimitives[0].Normals = meshPrimitives[1].Normals = MeshPrimitive.GetSinglePlaneNormals();

                //   foreach (Runtime.MeshPrimitive meshPrimitive in meshPrimitives)
                //    {
                //        meshPrimitive.BufferViewsInstanced = true;
                //        meshPrimitive.Material = CreateMaterial();
                //    }
                //    AddMeshPrimitivesToSingleNode(nodes, meshPrimitives);

                //    properties.Add(new Property(PropertyName.Description, "Two accessors using the same buffer view."));
                //}, (model) => { model.Camera = null; }),
            };

            GenerateUsedPropertiesList();
        }
Exemple #3
0
        public Animation_Node(List <string> imageList)
        {
            Runtime.Image baseColorTextureImage = UseTexture(imageList, "BaseColor_Cube");

            // There are no common properties in this model group that are reported in the readme.

            Model CreateModel(Action <List <Property>, List <Runtime.AnimationChannel>, Runtime.Node> setProperties)
            {
                var properties        = new List <Property>();
                var cubeMeshPrimitive = MeshPrimitive.CreateCube();

                // Apply the common properties to the gltf.
                cubeMeshPrimitive.Material = new Runtime.Material
                {
                    MetallicRoughnessMaterial = new Runtime.PbrMetallicRoughness
                    {
                        BaseColorTexture = new Runtime.Texture {
                            Source = baseColorTextureImage
                        },
                    },
                };
                var channels = new List <Runtime.AnimationChannel>
                {
                    new Runtime.AnimationChannel()
                };
                var node = new Runtime.Node();

                // Apply the properties that are specific to this gltf.
                setProperties(properties, channels, node);

                // Create the gltf object.
                node.Mesh = new Runtime.Mesh
                {
                    MeshPrimitives = new[]
                    {
                        cubeMeshPrimitive
                    }
                };
                Runtime.GLTF gltf = CreateGLTF(() => new Runtime.Scene()
                {
                    Nodes = new[]
                    {
                        node
                    },
                });
                gltf.Animations = new[]
                {
                    new Runtime.Animation
                    {
                        Channels = channels
                    }
                };
                return(new Model
                {
                    Properties = properties,
                    GLTF = gltf,
                    Animated = true,
                });
            }

            void SetTranslationChannelTarget(List <Property> properties, Runtime.AnimationChannel channel, Runtime.Node node)
            {
                channel.Target = new Runtime.AnimationChannelTarget
                {
                    Node = node,
                    Path = Runtime.AnimationChannelTarget.PathEnum.TRANSLATION,
                };
                properties.Add(new Property(PropertyName.Target, "Translation"));
            }

            void SetRotationChannelTarget(List <Property> properties, Runtime.AnimationChannel channel, Runtime.Node node)
            {
                channel.Target = new Runtime.AnimationChannelTarget
                {
                    Node = node,
                    Path = Runtime.AnimationChannelTarget.PathEnum.ROTATION,
                };
                properties.Add(new Property(PropertyName.Target, "Rotation"));
            }

            void SetScaleChannelTarget(List <Property> properties, Runtime.AnimationChannel channel, Runtime.Node node)
            {
                channel.Target = new Runtime.AnimationChannelTarget
                {
                    Node = node,
                    Path = Runtime.AnimationChannelTarget.PathEnum.SCALE,
                };
                properties.Add(new Property(PropertyName.Target, "Scale"));
            }

            void SetLinearSamplerForTranslation(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                },
                    new[]
                {
                    new Vector3(-0.1f, 0.0f, 0.0f),
                    new Vector3(0.1f, 0.0f, 0.0f),
                    new Vector3(-0.1f, 0.0f, 0.0f),
                }
                                  );

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetLinearSamplerForScale(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                },
                    new[]
                {
                    new Vector3(0.8f, 0.8f, 0.8f),
                    new Vector3(1.2f, 1.2f, 1.2f),
                    new Vector3(0.8f, 0.8f, 0.8f),
                }
                                  );

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetLinearSamplerForRotation(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                },
                    new[]
                {
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                    Quaternion.Identity,
                    Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                }
                                  );

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetStepSamplerForTranslation(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.StepAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                },
                    new[]
                {
                    new Vector3(-0.1f, 0.0f, 0.0f),
                    new Vector3(0.0f, 0.0f, 0.0f),
                    new Vector3(0.1f, 0.0f, 0.0f),
                    new Vector3(0.0f, 0.0f, 0.0f),
                    new Vector3(-0.1f, 0.0f, 0.0f),
                }
                                  );

                properties.Add(new Property(PropertyName.Interpolation, "Step"));
            }

            void SetCubicSplineSamplerForTranslation(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.CubicSplineAnimationSampler <Vector3>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                },
                    new[]
                {
                    new Runtime.CubicSplineAnimationSampler <Vector3> .Key
                    {
                        InTangent  = new Vector3(0.0f, 0.0f, 0.0f),
                        Value      = new Vector3(-0.1f, 0.0f, 0.0f),
                        OutTangent = new Vector3(0.0f, 0.0f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Vector3> .Key
                    {
                        InTangent  = new Vector3(0.0f, 0.0f, 0.0f),
                        Value      = new Vector3(0.1f, 0.0f, 0.0f),
                        OutTangent = new Vector3(0.0f, -0.3f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Vector3> .Key
                    {
                        InTangent  = new Vector3(0.0f, 0.0f, 0.0f),
                        Value      = new Vector3(-0.1f, 0.0f, 0.0f),
                        OutTangent = new Vector3(0.0f, 0.0f, 0.0f)
                    }
                }
                                  );

                properties.Add(new Property(PropertyName.Interpolation, "Cubic Spline"));
            }

            void CreateCubicSplineSamplerForRotation(List <Property> properties, Runtime.AnimationChannel channel)
            {
                channel.Sampler = new Runtime.CubicSplineAnimationSampler <Quaternion>
                                  (
                    new[]
                {
                    0.0f,
                    1.0f,
                    2.0f,
                    3.0f,
                    4.0f,
                },
                    new[]
                {
                    new Runtime.CubicSplineAnimationSampler <Quaternion> .Key
                    {
                        InTangent  = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Value      = Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        OutTangent = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Quaternion> .Key
                    {
                        InTangent  = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Value      = Quaternion.Identity,
                        OutTangent = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Quaternion> .Key
                    {
                        InTangent  = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Value      = Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                        OutTangent = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Quaternion> .Key
                    {
                        InTangent  = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Value      = Quaternion.Identity,
                        OutTangent = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f)
                    },
                    new Runtime.CubicSplineAnimationSampler <Quaternion> .Key
                    {
                        InTangent  = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Value      = Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        OutTangent = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f)
                    },
                }
                                  );
                properties.Add(new Property(PropertyName.Interpolation, "Cubic Spline"));
            }

            Models = new List <Model>
            {
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetRotationChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForRotation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetScaleChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForScale(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetStepSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetCubicSplineSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetRotationChannelTarget(properties, channels[0], node);
                    CreateCubicSplineSamplerForRotation(properties, channels[0]);
                }),
            };

            GenerateUsedPropertiesList();
        }
Exemple #4
0
        public Animation_SamplerType(List <string> imageList)
        {
            var baseColorTexture = new Texture {
                Source = UseTexture(imageList, "BaseColor_Cube")
            };

            CommonProperties.Add(new Property(PropertyName.Target, "Rotation"));
            CommonProperties.Add(new Property(PropertyName.Interpolation, "Linear"));

            Model CreateModel(DataType outputType)
            {
                var properties        = new List <Property>();
                var cubeMeshPrimitive = MeshPrimitive.CreateCube();

                // Apply the common properties to the gltf.
                cubeMeshPrimitive.Material = new Runtime.Material
                {
                    PbrMetallicRoughness = new PbrMetallicRoughness
                    {
                        BaseColorTexture = new TextureInfo {
                            Texture = baseColorTexture
                        },
                    },
                };
                var node = new Node
                {
                    Mesh = new Runtime.Mesh
                    {
                        MeshPrimitives = new[]
                        {
                            cubeMeshPrimitive
                        }
                    }
                };
                var channel = new AnimationChannel
                {
                    Target = new AnimationChannelTarget
                    {
                        Node = node,
                        Path = AnimationChannelTargetPath.Rotation,
                    },
                    Sampler = new AnimationSampler
                    {
                        Interpolation = AnimationSamplerInterpolation.Linear,
                        Input         = Data.Create(new[]
                        {
                            0.0f,
                            1.0f,
                            2.0f,
                            3.0f,
                            4.0f,
                        }),
                        Output = Data.Create(new[]
                        {
                            Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                            Quaternion.Identity,
                            Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                            Quaternion.Identity,
                            Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        }, outputType),
                    },
                };

                // Apply the properties that are specific to this gltf.
                properties.Add(new Property(PropertyName.SamplerOutputComponentType, outputType.ToReadmeString()));

                // Create the gltf object.
                GLTF gltf = CreateGLTF(() => new Scene
                {
                    Nodes = new[]
                    {
                        node
                    },
                });

                gltf.Animations = new[]
                {
                    new Animation
                    {
                        Channels = new List <AnimationChannel>
                        {
                            channel
                        }
                    }
                };
                return(new Model
                {
                    Properties = properties,
                    GLTF = gltf,
                    Animated = true,
                });
            }

            Models = new List <Model>
            {
                CreateModel(DataType.Float),
                CreateModel(DataType.NormalizedByte),
                CreateModel(DataType.NormalizedShort),
            };

            GenerateUsedPropertiesList();
        }
Exemple #5
0
        public Animation_Node(List <string> imageList)
        {
            var baseColorTexture = new Texture {
                Source = UseTexture(imageList, "BaseColor_Cube")
            };

            // There are no common properties in this model group that are reported in the readme.

            Model CreateModel(Action <List <Property>, List <AnimationChannel>, Node> setProperties)
            {
                var properties        = new List <Property>();
                var cubeMeshPrimitive = MeshPrimitive.CreateCube();

                // Apply the common properties to the gltf.
                cubeMeshPrimitive.Material = new Runtime.Material
                {
                    PbrMetallicRoughness = new PbrMetallicRoughness
                    {
                        BaseColorTexture = new TextureInfo {
                            Texture = baseColorTexture
                        },
                    },
                };
                var channels = new List <AnimationChannel>
                {
                    new AnimationChannel()
                };
                var node = new Node();

                // Apply the properties that are specific to this gltf.
                setProperties(properties, channels, node);

                // Create the gltf object.
                node.Mesh = new Runtime.Mesh
                {
                    MeshPrimitives = new[]
                    {
                        cubeMeshPrimitive
                    }
                };
                GLTF gltf = CreateGLTF(() => new Scene
                {
                    Nodes = new[]
                    {
                        node
                    },
                });

                gltf.Animations = new[]
                {
                    new Animation
                    {
                        Channels = channels
                    }
                };
                return(new Model
                {
                    Properties = properties,
                    GLTF = gltf,
                    Animated = true,
                });
            }

            void SetTranslationChannelTarget(List <Property> properties, AnimationChannel channel, Node node)
            {
                channel.Target = new AnimationChannelTarget
                {
                    Node = node,
                    Path = AnimationChannelTargetPath.Translation,
                };
                properties.Add(new Property(PropertyName.Target, channel.Target.Path.ToReadmeString()));
            }

            void SetRotationChannelTarget(List <Property> properties, AnimationChannel channel, Node node)
            {
                channel.Target = new AnimationChannelTarget
                {
                    Node = node,
                    Path = AnimationChannelTargetPath.Rotation,
                };
                properties.Add(new Property(PropertyName.Target, channel.Target.Path.ToReadmeString()));
            }

            void SetScaleChannelTarget(List <Property> properties, AnimationChannel channel, Node node)
            {
                channel.Target = new AnimationChannelTarget
                {
                    Node = node,
                    Path = AnimationChannelTargetPath.Scale,
                };
                properties.Add(new Property(PropertyName.Target, channel.Target.Path.ToReadmeString()));
            }

            void SetLinearSamplerForTranslation(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.Linear,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        new Vector3(-0.1f, 0.0f, 0.0f),
                        new Vector3(0.1f, 0.0f, 0.0f),
                        new Vector3(-0.1f, 0.0f, 0.0f),
                    }),
                };

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetLinearSamplerForScale(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.Linear,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        new Vector3(0.8f, 0.8f, 0.8f),
                        new Vector3(1.2f, 1.2f, 1.2f),
                        new Vector3(0.8f, 0.8f, 0.8f),
                    }),
                };

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetLinearSamplerForRotation(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.Linear,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                        3.0f,
                        4.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        Quaternion.Identity,
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                        Quaternion.Identity,
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                    }),
                };

                properties.Add(new Property(PropertyName.Interpolation, "Linear"));
            }

            void SetStepSamplerForTranslation(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.Step,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                        3.0f,
                        4.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        new Vector3(-0.1f, 0.0f, 0.0f),
                        new Vector3(0.0f, 0.0f, 0.0f),
                        new Vector3(0.1f, 0.0f, 0.0f),
                        new Vector3(0.0f, 0.0f, 0.0f),
                        new Vector3(-0.1f, 0.0f, 0.0f),
                    }),
                };

                properties.Add(new Property(PropertyName.Interpolation, "Step"));
            }

            void SetCubicSplineSamplerForTranslation(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.CubicSpline,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        new Vector3(0.0f, 0.0f, 0.0f),
                        new Vector3(-0.1f, 0.0f, 0.0f),
                        new Vector3(0.0f, 0.0f, 0.0f),

                        new Vector3(0.0f, 0.0f, 0.0f),
                        new Vector3(0.1f, 0.0f, 0.0f),
                        new Vector3(0.0f, -0.3f, 0.0f),

                        new Vector3(0.0f, 0.0f, 0.0f),
                        new Vector3(-0.1f, 0.0f, 0.0f),
                        new Vector3(0.0f, 0.0f, 0.0f),
                    }),
                };

                properties.Add(new Property(PropertyName.Interpolation, "Cubic Spline"));
            }

            void CreateCubicSplineSamplerForRotation(List <Property> properties, AnimationChannel channel)
            {
                channel.Sampler = new AnimationSampler
                {
                    Interpolation = AnimationSamplerInterpolation.CubicSpline,
                    Input         = Data.Create(new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                        3.0f,
                        4.0f,
                    }),
                    Output = Data.Create(new[]
                    {
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),

                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Quaternion.Identity,
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),

                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),

                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Quaternion.Identity,
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),

                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        new Quaternion(0.0f, 0.0f, 0.0f, 0.0f),
                    }),
                };
                properties.Add(new Property(PropertyName.Interpolation, "Cubic Spline"));
            }

            Models = new List <Model>
            {
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetRotationChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForRotation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetScaleChannelTarget(properties, channels[0], node);
                    SetLinearSamplerForScale(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetStepSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetTranslationChannelTarget(properties, channels[0], node);
                    SetCubicSplineSamplerForTranslation(properties, channels[0]);
                }),
                CreateModel((properties, channels, node) =>
                {
                    SetRotationChannelTarget(properties, channels[0], node);
                    CreateCubicSplineSamplerForRotation(properties, channels[0]);
                }),
            };

            GenerateUsedPropertiesList();
        }
        public Animation_SamplerType(List <string> imageList)
        {
            Runtime.Image baseColorTextureImage = UseTexture(imageList, "BaseColor_Cube");

            CommonProperties.Add(new Property(PropertyName.Target, "Rotation"));
            CommonProperties.Add(new Property(PropertyName.Interpolation, "Linear"));

            Model CreateModel(AnimationSampler.ComponentTypeEnum samplerOutputComponentType, string samplerOutputComponentTypeDisplayValue)
            {
                var properties        = new List <Property>();
                var cubeMeshPrimitive = MeshPrimitive.CreateCube();

                // Apply the common properties to the gltf.
                cubeMeshPrimitive.Material = new Runtime.Material
                {
                    MetallicRoughnessMaterial = new Runtime.PbrMetallicRoughness
                    {
                        BaseColorTexture = new Runtime.Texture {
                            Source = baseColorTextureImage
                        },
                    },
                };
                var node = new Runtime.Node
                {
                    Mesh = new Runtime.Mesh
                    {
                        MeshPrimitives = new[]
                        {
                            cubeMeshPrimitive
                        }
                    }
                };
                var channel = new Runtime.AnimationChannel
                {
                    Target = new Runtime.AnimationChannelTarget
                    {
                        Node = node,
                        Path = Runtime.AnimationChannelTarget.PathEnum.ROTATION,
                    },
                    Sampler = new Runtime.LinearAnimationSampler <Quaternion>
                              (
                        new[]
                    {
                        0.0f,
                        1.0f,
                        2.0f,
                        3.0f,
                        4.0f,
                    },
                        new[]
                    {
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                        Quaternion.Identity,
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(-90.0f), 0.0f, 0.0f),
                        Quaternion.Identity,
                        Quaternion.CreateFromYawPitchRoll(FloatMath.ToRadians(90.0f), 0.0f, 0.0f),
                    },
                        outputComponentType: samplerOutputComponentType
                              )
                };

                // Apply the properties that are specific to this gltf.
                properties.Add(new Property(PropertyName.SamplerOutputComponentType, samplerOutputComponentTypeDisplayValue));

                // Create the gltf object.
                Runtime.GLTF gltf = CreateGLTF(() => new Runtime.Scene
                {
                    Nodes = new[]
                    {
                        node
                    },
                });
                gltf.Animations = new[]
                {
                    new Runtime.Animation
                    {
                        Channels = new List <Runtime.AnimationChannel>
                        {
                            channel
                        }
                    }
                };
                return(new Model
                {
                    Properties = properties,
                    GLTF = gltf,
                    Animated = true,
                });
            }

            Models = new List <Model>
            {
                CreateModel(AnimationSampler.ComponentTypeEnum.FLOAT, "Float"),
                CreateModel(AnimationSampler.ComponentTypeEnum.NORMALIZED_BYTE, "Byte"),
                CreateModel(AnimationSampler.ComponentTypeEnum.NORMALIZED_SHORT, "Short"),
            };

            GenerateUsedPropertiesList();
        }