diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files
index f7fd57b8538c9aec0c911c605476ddcf1b4f46fe..9e4e434eb7cf0fbee06c5f0b6e4ca3534fb0626c 100644
--- a/src/fileFormats/Make/files
+++ b/src/fileFormats/Make/files
@@ -29,6 +29,14 @@ abaqus/ABAQUSCore.C
 nastran/NASCore.C
 obj/OBJstream.C
 fire/FIRECore.C
+
+gltf/foamGltfAccessor.C
+gltf/foamGltfAnimation.C
+gltf/foamGltfBufferView.C
+gltf/foamGltfMesh.C
+gltf/foamGltfObject.C
+gltf/foamGltfScene.C
+
 starcd/STARCDCore.C
 stl/STLCore.C
 stl/STLReader.C
@@ -76,5 +84,6 @@ $(setWriters)/vtk/vtkSetWriterRunTime.C
 $(setWriters)/xmgrace/xmgraceSetWriterRunTime.C
 $(setWriters)/csv/csvSetWriterRunTime.C
 $(setWriters)/nastran/nastranSetWriterRunTime.C
+$(setWriters)/gltf/gltfSetWriterRunTime.C
 
 LIB = $(FOAM_LIBBIN)/libfileFormats
diff --git a/src/fileFormats/gltf/foamGltfAccessor.C b/src/fileFormats/gltf/foamGltfAccessor.C
new file mode 100644
index 0000000000000000000000000000000000000000..ac28337a15f3459014808c283a75429422f310fa
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfAccessor.C
@@ -0,0 +1,119 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfAccessor.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::accessor::accessor()
+:
+    base(),
+    bufferViewId_(-1),
+    byteOffset_(0),
+    componentType_(-1),
+    count_(-1),
+    type_(""),
+    max_(""),
+    min_(""),
+    minMax_(false)
+{}
+
+
+Foam::glTF::accessor::accessor(const word& name)
+:
+    base("Accessor:"+name),
+    bufferViewId_(-1),
+    byteOffset_(0),
+    componentType_(-1),
+    count_(-1),
+    type_(""),
+    max_(""),
+    min_(""),
+    minMax_(false)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::label& Foam::glTF::accessor::bufferViewId() noexcept
+{
+    return bufferViewId_;
+}
+
+
+Foam::label& Foam::glTF::accessor::byteOffset() noexcept
+{
+    return byteOffset_;
+}
+
+
+Foam::label& Foam::glTF::accessor::componentType() noexcept
+{
+    return componentType_;
+}
+
+
+Foam::label& Foam::glTF::accessor::count() noexcept
+{
+    return count_;
+}
+
+
+Foam::string& Foam::glTF::accessor::type() noexcept
+{
+    return type_;
+}
+
+
+void Foam::glTF::accessor::write(Ostream& os) const
+{
+    os  << indent << "\"bufferView\" : " << bufferViewId_ << ',' << nl
+        << indent << "\"byteOffset\" : " << byteOffset_ << ',' << nl
+        << indent << "\"componentType\" : " << componentType_ << ',' << nl
+        << indent << "\"count\" : " << count_ << ',' << nl
+        << indent << "\"type\" : " << type_;
+
+    if (minMax_)
+    {
+        os  << ',' << nl
+            << indent << "\"max\" : " << max_.c_str() << ',' << nl
+            << indent << "\"min\" : " << min_.c_str();
+    }
+
+    base::write(os);
+}
+
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const glTF::accessor& acc)
+{
+    acc.write(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfAccessor.H b/src/fileFormats/gltf/foamGltfAccessor.H
new file mode 100644
index 0000000000000000000000000000000000000000..76244c458606c22b6c44268d014c4094a3599df0
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfAccessor.H
@@ -0,0 +1,167 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::accessor
+
+Description
+    glTF accessor
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfAccessor.C
+    foamGltfAccessorTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_accessor_H
+#define foam_gltf_accessor_H
+
+#include "foamGltfBase.H"
+#include "Field.H"
+#include "label.H"
+#include "string.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+    class accessor;
+}
+
+Ostream& operator<<(Ostream& os, const glTF::accessor& acc);
+
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class glTF::accessor Declaration
+\*---------------------------------------------------------------------------*/
+
+class accessor
+:
+    public base
+{
+protected:
+
+    // Protected Data
+
+        //- Buffer view index
+        label bufferViewId_;
+
+        //- Byte offset
+        label byteOffset_;
+
+        //- Component type
+        label componentType_;
+
+        //- Data size
+        label count_;
+
+        //- Data type
+        string type_;
+
+        //- Max value.  Note: stored as a string for convenience
+        string max_;
+
+        //- Min value.  Note: stored as a string for convenience
+        string min_;
+
+        //- Flag to indicate whether min and max values are available
+        bool minMax_;
+
+
+    // Protected Member Functions
+
+        //- Return the glTF value type for the given OpenFOAM type
+        template<class Type>
+        static string getValueType();
+
+        //- Stringify the value
+        template<class Type>
+        static string toString(const Type& val);
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        accessor();
+
+        //- Construct from name
+        explicit accessor(const word& name);
+
+
+    //- Destructor
+    ~accessor() = default;
+
+
+    // Public Member Functions
+
+        //- Return the buffer view index
+        label& bufferViewId() noexcept;
+
+        //- Return the byte offset
+        label& byteOffset() noexcept;
+
+        //- Return the component type
+        label& componentType() noexcept;
+
+        //- Return the data size
+        label& count() noexcept;
+
+        //- Return the type
+        string& type() noexcept;
+
+        //- Set the accessor
+        template<class Type>
+        void set(const Field<Type>& fld, bool calcMinMax = true);
+
+        //- Write
+        void write(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "foamGltfAccessorTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfAccessorTemplates.C b/src/fileFormats/gltf/foamGltfAccessorTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..9070964a579f44145e14f0422b98c200467bf554
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfAccessorTemplates.C
@@ -0,0 +1,107 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfAccessor.H"
+#include "exprTraits.H"
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+template<class Type>
+Foam::string Foam::glTF::accessor::getValueType()
+{
+    switch (exprTypeTraits<Type>::value)
+    {
+        case exprTypeTraits<label>::value :
+        case exprTypeTraits<scalar>::value :
+        {
+            return "SCALAR";
+        }
+
+        case exprTypeTraits<vector>::value :
+        {
+            return "VEC3";
+        }
+
+        case exprTypeTraits<tensor>::value :
+        {
+            return "MAT3";
+        }
+
+        default:
+        {
+            FatalErrorInFunction
+                << "Unable to process "
+                << pTraits<Type>::typeName << " fields"
+                << abort(FatalError);
+        }
+    }
+
+    return string();
+}
+
+
+template<class Type>
+Foam::string Foam::glTF::accessor::toString(const Type& val)
+{
+    OStringStream buf;
+    buf << "[ ";
+    for (direction dir = 0; dir < pTraits<Type>::nComponents; ++dir)
+    {
+        if (dir) buf << ", ";
+        buf << float(component(val, dir));
+    }
+    buf << " ]";
+
+    return buf.str();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+void Foam::glTF::accessor::set(const Field<Type>& fld, bool calcMinMax)
+{
+    count_ = fld.size();
+
+    type_ = accessor::getValueType<Type>();
+
+    componentType_ = key(componentTypes::FLOAT);
+
+    minMax_ = calcMinMax;
+
+    if (minMax_)
+    {
+        Type minValue = min(fld);
+        Type maxValue = max(fld);
+
+        min_ = accessor::toString(minValue);
+        max_ = accessor::toString(maxValue);
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfAnimation.C b/src/fileFormats/gltf/foamGltfAnimation.C
new file mode 100644
index 0000000000000000000000000000000000000000..e5cd97a1e3bf3b8a3f09ebd92766bddfb7f579bf
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfAnimation.C
@@ -0,0 +1,121 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfAnimation.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::animation::animation()
+:
+    base(),
+    samplers_(),
+    channels_()
+{}
+
+
+Foam::glTF::animation::animation(const word& name)
+:
+    base(name),
+    samplers_(),
+    channels_()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::glTF::animation::addTranslation
+(
+    const label inputId,
+    const label outputId,
+    const label nodeId,
+    const string& interpolation
+)
+{
+    glTFSampler sampler;
+    sampler.input = inputId;
+    sampler.output = outputId;
+    sampler.interpolation = interpolation;
+    samplers_.append(sampler);
+
+    glTFChannel channel;
+    channel.samplerId = samplers_.size() - 1;
+    channel.target.node = nodeId;
+    channel.target.path = "translation";
+    channels_.append(channel);
+}
+
+
+void Foam::glTF::animation::write(Ostream& os) const
+{
+    os  << indent << "\"samplers\" : [" << nl << incrIndent;
+
+    forAll(samplers_, i)
+    {
+        const auto& sampler = samplers_[i];
+
+        os  << indent << "{" << nl << incrIndent
+            << indent << "\"input\" : " << sampler.input << "," << nl
+            << indent << "\"interpolation\" : " << sampler.interpolation
+            << "," << nl
+            << indent << "\"output\" : " << sampler.output << nl
+            << decrIndent << indent << "}";
+
+        if (i != samplers_.size() - 1) os  << "," << nl;
+    }
+
+    os  << nl << decrIndent << indent << "]," << nl;
+
+    os  << indent << "\"channels\" : [" << nl << incrIndent;
+
+    forAll(channels_, i)
+    {
+        const auto& channel = channels_[i];
+
+        os  << indent << "{" << nl << incrIndent
+            << indent << "\"sampler\" : " << channel.samplerId << "," << nl
+            << indent << "\"target\" : {" << incrIndent << nl
+            << indent << "\"node\" : " << channel.target.node << "," << nl
+            << indent << "\"path\" : " << channel.target.path << nl
+            << decrIndent << indent << "}" << nl
+            << decrIndent << indent << "}";
+
+        if (i != channels_.size() - 1) os  << "," << nl;
+    }
+
+    os  << nl << decrIndent << indent << "]";
+}
+
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const glTF::animation& animation)
+{
+    animation.write(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfAnimation.H b/src/fileFormats/gltf/foamGltfAnimation.H
new file mode 100644
index 0000000000000000000000000000000000000000..71a118a41ac6a421bc1b71f9c8eefcdd0eff7d2c
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfAnimation.H
@@ -0,0 +1,147 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::animation
+
+Description
+    glTF animation
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfAnimation.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_animation_H
+#define foam_gltf_animation_H
+
+#include "foamGltfBase.H"
+#include "DynamicList.H"
+#include "Tuple2.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+    class animation;
+}
+
+Ostream& operator<<(Ostream& os, const glTF::animation& animation);
+
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class glTF::animation Declaration
+\*---------------------------------------------------------------------------*/
+
+
+class animation
+:
+    public base
+{
+protected:
+
+    // Local Helpers
+
+        // Sampler
+        struct glTFSampler
+        {
+            label input;
+            string interpolation;
+            label output;
+        };
+
+        // Channel target
+        struct glTFTarget
+        {
+            label node;
+            string path;
+        };
+
+        // Channel
+        struct glTFChannel
+        {
+            label samplerId;
+            glTFTarget target;
+        };
+
+
+
+    // Protected Member Data
+
+        //- Samplers
+        DynamicList<glTFSampler> samplers_;
+
+        //- Channels
+        DynamicList<glTFChannel> channels_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        animation();
+
+        //- Construct with name
+        explicit animation(const word& name);
+
+
+    //- Destructor
+    ~animation() = default;
+
+
+    // Public Member Functions
+
+        //- Add translation
+        void addTranslation
+        (
+            const label inputId,
+            const label outputId,
+            const label nodeId,
+            const string& interpolation
+        );
+
+        //- Write
+        void write(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfBase.H b/src/fileFormats/gltf/foamGltfBase.H
new file mode 100644
index 0000000000000000000000000000000000000000..ba00201007d4ba365521ece7a0bc7c41ea71478a
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfBase.H
@@ -0,0 +1,198 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Namespace
+    Foam::glTF
+
+Description
+    Namespace for handling glTF creation.
+    https://www.khronos.org/registry/glTF/
+
+Class
+    Foam::glTF::base
+
+Description
+    Base class for glTF entities
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_base_H
+#define foam_gltf_base_H
+
+#include "word.H"
+#include "label.H"
+#include "Ostream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+
+    enum class componentTypes : int
+    {
+        BYTE            = 5120, //!< 1 byte
+        UNSIGNED_BYTE   = 5121, //!< 1 byte
+        SHORT           = 5122, //!< 2 bytes
+        UNSIGNED_SHORT  = 5123, //!< 2 bytes
+        UNSIGNED_INT    = 5125, //!< 4 bytes
+        FLOAT           = 5126  //!< 4 bytes
+    };
+
+    // accessor
+    enum class dataTypes
+    {
+        SCALAR, //!< 1 component
+        VEC2,   //!< 2 components
+        VEC3,   //!< 3 components
+        VEC4,   //!< 4 components
+        MAT2,   //!< 4 components
+        MAT3,   //!< 9 components
+        MAT4    //!< 16 components
+    };
+
+    enum class attributeTypes
+    {
+        POSITION,   //!< VEC3 XYZ vertex positions; requires 'min' and 'max'
+        NORMAL,     //!< VEC3 Normalised XYZ vertex normals
+        TANGENT,    //!< VEC4 XYZW vertex tangents
+        TEXCOORD_0, //!< VEC2 UV texture coordinates
+        TEXCOORD_1, //!< VEC2 UV texture coordinates
+        COLOR_0,    //!< VEC3 (rgb), VEC4 (rgba)
+        JOINTS_0,   //!< VEC4
+        WEIGHTS_0   //!< VEC4
+    };
+
+    // bufferView
+    enum class targetTypes : int
+    {
+        ARRAY_BUFFER = 34962, //!< vertex attributes
+        ELEMENT_ARRAY_BUFFER = 34963 //!< vertex indices
+    };
+
+    enum class primitiveModes : int
+    {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6
+    };
+
+    // Helper function to return the enum value
+    template<class Type>
+    auto key(const Type& t) -> typename std::enable_if
+    <
+        std::is_enum<Type>::value,
+        typename std::underlying_type<Type>::type
+    >::type
+    {
+        return static_cast<typename std::underlying_type<Type>::type>(t);
+    }
+
+/*---------------------------------------------------------------------------*\
+                          Class base Declaration
+\*---------------------------------------------------------------------------*/
+
+class base
+{
+protected:
+
+    // Protected Data
+
+        //- Name
+        word name_;
+
+        //- ID
+        label id_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        base()
+        :
+            id_(-1)
+        {}
+
+        //- Construct with name
+        explicit base(const word& name)
+        :
+            name_(name),
+            id_(-1)
+        {}
+
+
+    //- Destructor
+    ~base() = default;
+
+
+    // Member Functions
+
+        //- Return access to the ID
+        label& id() noexcept
+        {
+            return id_;
+        }
+
+        //- Return const access to the name
+        const word& name() const noexcept
+        {
+            return name_;
+        }
+
+        //- Write
+        void write(Ostream& os) const
+        {
+            os  << "," << nl
+                << indent << "\"name\" : \"" << name_ << "\"";
+        }
+
+
+    // Member Operators
+
+        void operator=(const base& gltf)
+        {
+            name_ = gltf.name_;
+            id_ = gltf.id_;
+        }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfBufferView.C b/src/fileFormats/gltf/foamGltfBufferView.C
new file mode 100644
index 0000000000000000000000000000000000000000..30b423c6a420e3d698cb3eac763a51412e164529
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfBufferView.C
@@ -0,0 +1,113 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfBufferView.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::bufferView::bufferView()
+:
+    base(),
+    buffer_(0),
+    byteOffset_(-1),
+    byteLength_(-1),
+    target_(-1)
+{}
+
+
+Foam::glTF::bufferView::bufferView(const word& name)
+:
+    base("BufferView:"+name),
+    buffer_(0),
+    byteOffset_(-1),
+    byteLength_(-1),
+    target_(-1)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::label& Foam::glTF::bufferView::buffer() noexcept
+{
+    return buffer_;
+}
+
+
+Foam::label& Foam::glTF::bufferView::byteOffset() noexcept
+{
+    return byteOffset_;
+}
+
+
+Foam::label& Foam::glTF::bufferView::byteLength() noexcept
+{
+    return byteLength_;
+}
+
+
+Foam::label& Foam::glTF::bufferView::target() noexcept
+{
+    return target_;
+}
+
+
+void Foam::glTF::bufferView::write(Ostream& os) const
+{
+    os  << indent << "\"buffer\" : " << buffer_ << "," << nl
+        << indent << "\"byteOffset\" : " << byteOffset_ << "," << nl
+        << indent << "\"byteLength\" : " << byteLength_;
+
+    if (target_ != -1)
+    {
+        os  << "," << nl
+            << indent << "\"target\" : " << target_;
+    }
+
+    base::write(os);
+}
+
+
+void Foam::glTF::bufferView::operator=(const glTF::bufferView& bv)
+{
+    base::operator=(bv);
+
+    buffer_ = bv.buffer_;
+    byteOffset_ = bv.byteOffset_;
+    byteLength_ = bv.byteLength_;
+    target_ = bv.target_;
+}
+
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const glTF::bufferView& bv)
+{
+    bv.write(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfBufferView.H b/src/fileFormats/gltf/foamGltfBufferView.H
new file mode 100644
index 0000000000000000000000000000000000000000..080a6c0f72230c314320a0f01b5f145035d72e2e
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfBufferView.H
@@ -0,0 +1,133 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::bufferView
+
+Description
+    glTF buffer view - provides a view/slice of the glTF buffer
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfBufferView.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_bufferview_H
+#define foam_gltf_bufferview_H
+
+#include "foamGltfBase.H"
+#include "Ostream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+    class bufferView;
+}
+
+Ostream& operator<<(Ostream&, const glTF::bufferView& bv);
+
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class glTF::bufferView Declaration
+\*---------------------------------------------------------------------------*/
+
+class bufferView
+:
+    public base
+{
+protected:
+
+    // Protected Data
+
+        //- Buffer index
+        label buffer_;
+
+        //- Byte offset
+        label byteOffset_;
+
+        //- Byte length
+        label byteLength_;
+
+        //- Target
+        label target_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        bufferView();
+
+        //- Construct with name
+        explicit bufferView(const word& name);
+
+
+    //- Destructor
+    ~bufferView() = default;
+
+
+    // Public Member Functions
+
+        //- Return the buffer index
+        label& buffer() noexcept;
+
+        //- Return the byte offset
+        label& byteOffset() noexcept;
+
+        //- Return the byte length
+        label& byteLength() noexcept;
+
+        //- Return the target
+        label& target() noexcept;
+
+        //- Write
+        void write(Ostream& os) const;
+
+
+    // Member Operators
+
+        void operator=(const bufferView& bv);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfList.C b/src/fileFormats/gltf/foamGltfList.C
new file mode 100644
index 0000000000000000000000000000000000000000..c38f6aec69eaa8a4378cd45a0ab1989a51409fe1
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfList.C
@@ -0,0 +1,122 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfList.H"
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+Type& Foam::glTF::List<Type>::create(const word& name)
+{
+    Type obj(name);
+    obj.id() = data_.size();
+    data_.append(obj);
+
+    return data_.last();
+}
+
+
+template<class Type>
+const Foam::DynamicList<Type>& Foam::glTF::List<Type>::data() const noexcept
+{
+    return data_;
+}
+
+
+template<class Type>
+bool Foam::glTF::List<Type>::empty() const noexcept
+{
+    return data_.empty();
+}
+
+
+template<class Type>
+Foam::label Foam::glTF::List<Type>::size() const noexcept
+{
+    return data_.size();
+}
+
+
+template<class Type>
+void Foam::glTF::List<Type>::write
+(
+    Ostream& os,
+    const word& keyword,
+    bool firstEntry
+)
+{
+    if (empty())
+    {
+        return;
+    }
+
+    if (!firstEntry)
+    {
+        os  << "," << nl;
+    }
+
+    os  << indent << "\"" << keyword << "\" : [" << nl << incrIndent;
+
+    write(os);
+
+    os  << decrIndent << nl << indent << "]";
+}
+
+
+template<class Type>
+void Foam::glTF::List<Type>::write(Ostream& os) const
+{
+    forAll(data_, i)
+    {
+        os  << indent << "{"
+            << nl << incrIndent
+            << data_[i]
+            << nl << decrIndent
+            << indent << "}";
+
+        if (i != data_.size() - 1) os  << "," << nl;
+    }
+}
+
+
+template<class Type>
+Type& Foam::glTF::List<Type>::operator[](const label i)
+{
+    return data_[i];
+}
+
+
+template<class Type>
+Foam::Ostream& Foam::operator<<(Ostream& os, const glTF::List<Type>& lst)
+{
+    lst.write(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfList.H b/src/fileFormats/gltf/foamGltfList.H
new file mode 100644
index 0000000000000000000000000000000000000000..09464a176c172e27ef199c86e0629249807c2bdc
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfList.H
@@ -0,0 +1,125 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::List
+
+Description
+    Container for glTF entities
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfList.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_list_H
+#define foam_gltf_list_H
+
+#include "DynamicList.H"
+#include "Ostream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+    template<class Type> class List;
+}
+
+template<class Type>
+Ostream& operator<<(Ostream& os, const glTF::List<Type>& lst);
+
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class glTF::List Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class List
+{
+    // Private Data
+
+        //- Storage
+        DynamicList<Type> data_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        List() = default;
+
+
+    //- Destructor
+    ~List() = default;
+
+
+    // Public Member Functions
+
+        //- Helper to create a new Type on the list and set the ID
+        Type& create(const word& name);
+
+        //- Return const access to the underlying list
+        const DynamicList<Type>& data() const noexcept;
+
+        //- List contains no data
+        bool empty() const noexcept;
+
+        //- Return the list size
+        label size() const noexcept;
+
+        //- Write
+        void write(Ostream& os, const word& keyword, bool firstEntry = false);
+
+        //- Write
+        void write(Ostream& os) const;
+
+        Type& operator[](const label i);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "foamGltfList.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfMesh.C b/src/fileFormats/gltf/foamGltfMesh.C
new file mode 100644
index 0000000000000000000000000000000000000000..dd54ad525c3bff10eb73739b098ca02b8c809e36
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfMesh.C
@@ -0,0 +1,109 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfMesh.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::mesh::mesh()
+:
+    base(),
+    fields_(),
+    colours_(),
+    accessorId_(-1)
+{}
+
+
+Foam::glTF::mesh::mesh(const word& name)
+:
+    base(name),
+    fields_(),
+    colours_(),
+    accessorId_(-1)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::label& Foam::glTF::mesh::accessorId() noexcept
+{
+    return accessorId_;
+}
+
+
+void Foam::glTF::mesh::addField(const word& name, const label accessorId)
+{
+    fields_.append(Tuple2<string, label>("_field:" + name, accessorId));
+}
+
+
+void Foam::glTF::mesh::addColour(const label accessorId)
+{
+    colours_.append
+    (
+        Tuple2<string, label>
+        (
+            "COLOR_" + Foam::name(colours_.size()),
+            accessorId
+        )
+    );
+}
+
+
+void Foam::glTF::mesh::write(Ostream& os) const
+{
+    os  << indent << "\"primitives\" : [{" << nl << incrIndent
+        << indent << "\"attributes\" : {" << nl  << incrIndent
+        << indent << "\"POSITION\" : " << accessorId_;
+
+    for (const auto& f : fields_)
+    {
+        os  << "," << nl << indent << f.first() << " : " << f.second();
+    }
+
+    for (const auto& c : colours_)
+    {
+        os  << "," << nl << indent << c.first() <<  " : " << c.second();
+    }
+
+    os  << nl << decrIndent << indent << "}," << nl
+        << indent << "\"mode\" : " << 0 << nl << decrIndent// 0 = POINTS
+        << indent << "}]";
+
+    base::write(os);
+}
+
+
+Foam::Ostream& Foam::operator<<(Ostream& os, const glTF::mesh& mesh)
+{
+    mesh.write(os);
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfMesh.H b/src/fileFormats/gltf/foamGltfMesh.H
new file mode 100644
index 0000000000000000000000000000000000000000..c4ef24a362c492cf81f240f61396fa1d336af8a8
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfMesh.H
@@ -0,0 +1,121 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::mesh
+
+Description
+    glTF mesh
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfMesh.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_mesh_H
+#define foam_gltf_mesh_H
+
+#include "foamGltfBase.H"
+#include "DynamicList.H"
+#include "Tuple2.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+    class mesh;
+}
+
+Ostream& operator<<(Ostream& os, const glTF::mesh& mesh);
+
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class glTF::mesh Declaration
+\*---------------------------------------------------------------------------*/
+
+class mesh
+:
+    public base
+{
+    // Private Data
+
+        //- List of fields (name, accessor ID)
+        DynamicList<Tuple2<string, label>> fields_;
+
+        //- List of colours (name, accessor ID)
+        DynamicList<Tuple2<string, label>> colours_;
+
+        //- Accessor ID
+        label accessorId_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        mesh();
+
+        //- Construct from name
+        explicit mesh(const word& name);
+
+
+    //- Destructor
+    ~mesh() = default;
+
+
+    // Public Member Functions
+
+        //- Return the accessor ID
+        label& accessorId() noexcept;
+
+        //- Add a field to the mesh
+        void addField(const word& name, const label accessorId);
+
+        //- Add a colour to the mesh
+        void addColour(const label accessorId);
+
+        //- Write
+        void write(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfObject.C b/src/fileFormats/gltf/foamGltfObject.C
new file mode 100644
index 0000000000000000000000000000000000000000..4290e606ce7537479171e45f451be5e68e157cda
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfObject.C
@@ -0,0 +1,69 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfObject.H"
+#include "endian.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::object::object()
+:
+    base(),
+    data_()
+{
+    #ifdef WM_LITTLE_ENDIAN
+    #else
+    FatalErrorInFunction
+        << "Big-endian buffer support is not available"
+        << abort(FatalError);
+    #endif
+}
+
+
+Foam::glTF::object::object(const word& name)
+:
+    base(name),
+    data_()
+{
+    #ifdef WM_LITTLE_ENDIAN
+    #else
+    FatalErrorInFunction
+        << "Big-endian buffer support is not available"
+        << abort(FatalError);
+    #endif
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+const Foam::List<float>& Foam::glTF::object::data() const noexcept
+{
+    return data_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfObject.H b/src/fileFormats/gltf/foamGltfObject.H
new file mode 100644
index 0000000000000000000000000000000000000000..614d00451ad6d568bcf4e0c9dd5e471f5cf82373
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfObject.H
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::object
+
+Description
+    glTF binary object
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfObject.C
+    foamGltfObjectTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_object_H
+#define foam_gltf_object_H
+
+#include "foamGltfBase.H"
+#include "List.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class glTF::object Declaration
+\*---------------------------------------------------------------------------*/
+
+class object
+:
+    public base
+{
+    // Private Data
+
+        //- Buffer storage
+        Foam::List<float> data_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        object();
+
+        //- Construct with name
+        explicit object(const word& name);
+
+
+    // Public Member Functions
+
+        //- Add data to the buffer
+        template<class Type>
+        void addData(const Type& fld);
+
+        //- Add data to the buffer from 2 containers of the same size
+        //  E.g. to combine vector and scalar to create RGBA data
+        template<class Type1, class Type2>
+        void addData(const Type1& fld1, const Type2& fld2);
+
+        //- Return const access to the data buffer
+        const Foam::List<float>& data() const noexcept;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "foamGltfObjectTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfObjectTemplates.C b/src/fileFormats/gltf/foamGltfObjectTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..df8247e5ca1cc18446937d55260cf7c88dbd296c
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfObjectTemplates.C
@@ -0,0 +1,85 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+void Foam::glTF::object::addData(const Type& fld)
+{
+    const label nComponents =
+        pTraits<typename Type::value_type>::nComponents;
+
+    label count = data_.size();
+    data_.setSize(data_.size() + fld.size()*nComponents);
+
+    forAll(fld, fieldi)
+    {
+        for (direction d = 0; d < nComponents; ++d)
+        {
+            data_[count++] = component(fld[fieldi], d);
+        }
+    }
+}
+
+
+template<class Type1, class Type2>
+void Foam::glTF::object::addData(const Type1& fld1, const Type2&fld2)
+{
+    if (fld1.size() != fld2.size())
+    {
+        FatalErrorInFunction
+            << "Field lengths must be the same. Field1:"
+            << fld1.size() << " Field2:" << fld2.size()
+            << abort(FatalError);
+    }
+
+    const label nComponents1 =
+        pTraits<typename Type1::value_type>::nComponents;
+
+    const label nComponents2 =
+        pTraits<typename Type2::value_type>::nComponents;
+
+    label count = data_.size();
+    data_.setSize
+    (
+        data_.size() + fld1.size()*(nComponents1 + nComponents2)
+    );
+
+    forAll(fld1, fieldi)
+    {
+        for (direction d = 0; d < nComponents1; ++d)
+        {
+            data_[count++] = component(fld1[fieldi], d);
+        }
+
+        for (direction d = 0; d < nComponents2; ++d)
+        {
+            data_[count++] = component(fld2[fieldi], d);
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfScene.C b/src/fileFormats/gltf/foamGltfScene.C
new file mode 100644
index 0000000000000000000000000000000000000000..ba003ce3a38ecfcd04f82cdf0b7aad108f15c0d6
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfScene.C
@@ -0,0 +1,241 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "foamGltfScene.H"
+#include "fileName.H"
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::glTF::scene::scene()
+:
+    objects_(),
+    meshes_(),
+    bufferViews_(),
+    accessors_(),
+    animations_(),
+    bytes_(0)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::label Foam::glTF::scene::addColourToMesh
+(
+    const vectorField& fld,
+    const word& name,
+    const label meshi,
+    const scalarField& alpha
+)
+{
+    if (meshi > meshes_.size() - 1)
+    {
+        FatalErrorInFunction
+            << "Mesh " << meshi << " out of range "
+            << (meshes_.size() - 1)
+            << abort(FatalError);
+    }
+
+    auto& bv = bufferViews_.create(name);
+    bv.byteOffset() = bytes_;
+    bv.byteLength() = fld.size()*3*sizeof(float); // 3 components
+    bv.target() = key(targetTypes::ARRAY_BUFFER);
+    bytes_ += bv.byteLength();
+
+    auto& acc = accessors_.create(name);
+    acc.bufferViewId() = bv.id();
+    acc.set(fld, false); // no min-max
+
+    auto& obj = objects_.create(name);
+
+    if (alpha.size())
+    {
+        bv.byteLength() += fld.size()*sizeof(float);
+        bytes_ += fld.size()*sizeof(float);
+
+        acc.type() = "VEC4";
+
+        obj.addData(fld, alpha);
+    }
+    else
+    {
+        obj.addData(fld);
+    }
+
+    meshes_[meshi].addColour(acc.id());
+
+    return acc.id();
+}
+
+
+Foam::label Foam::glTF::scene::createAnimation(const word& name)
+{
+    animations_.create(name);
+    return animations_.size() - 1;
+}
+
+
+void Foam::glTF::scene::addToAnimation
+(
+    const label animationi,
+    const label inputId,
+    const label outputId,
+    const label meshId,
+    const string& interpolation
+)
+{
+    if (animationi > animations_.size() - 1)
+    {
+        FatalErrorInFunction
+            << "Animation " << animationi << " out of range "
+            << (animations_.size() - 1)
+            << abort(FatalError);
+    }
+
+    const label nodeId = meshId + 1; // offset by 1 for parent node
+
+    // Note
+    // using 1 mesh per node +1 parent node => meshes_.size() nodes in total
+    if (nodeId > meshes_.size())
+    {
+        FatalErrorInFunction
+            << "Node " << nodeId << " out of range " << meshes_.size()
+            << abort(FatalError);
+    }
+
+    animations_[animationi].addTranslation
+    (
+        inputId,
+        outputId,
+        nodeId,
+        interpolation
+    );
+}
+
+
+void Foam::glTF::scene::write(Ostream& os)
+{
+    const fileName base(os.name().lessExt());
+    const fileName binFile
+    (
+        fileName::concat(base.path(), fileName::name(base) + ".bin")
+    );
+
+    // Write binary file
+    // Note: using stdStream
+    OFstream bin(binFile, IOstream::BINARY);
+    auto& osbin = bin.stdStream();
+
+    label totalBytes = 0;
+    for (const auto& object : objects_.data())
+    {
+        for (const auto& data : object.data())
+        {
+            osbin.write
+            (
+                reinterpret_cast<const char*>(&data),
+                sizeof(float)
+            );
+
+            totalBytes += sizeof(float);
+        }
+    }
+
+    // Write json file
+    os << "{" << nl << incrIndent;
+
+    os  << indent << "\"asset\" : {" << nl << incrIndent
+        << indent << "\"generator\" : \"OpenFOAM - www.openfoam.com\"," << nl
+        << indent << "\"version\" : \"2.0\"" << nl << decrIndent
+        << indent << "}," << nl;
+
+    os  << indent << "\"extras\" : {" << nl << incrIndent
+        /* << content */
+        << decrIndent
+        << indent << "}," << nl;
+
+    os  << indent << "\"scene\": 0," << nl;
+
+    os  << indent << "\"scenes\": [{" << nl << incrIndent
+        << indent << "\"nodes\" : [0]" << nl << decrIndent
+        << indent << "}]," << nl;
+
+    os  << indent << "\"buffers\" : [{" << nl << incrIndent
+        << indent << "\"uri\" : " << string(fileName::name(binFile))
+        << "," << nl
+        << indent << "\"byteLength\" : " << totalBytes << nl << decrIndent
+        << indent << "}]," << nl;
+
+    os  << indent << "\"nodes\" : [" << nl << incrIndent
+        << indent << "{" << nl << incrIndent
+        << indent << "\"children\" : [" << nl << incrIndent;
+
+    // List of child node indices
+    os  << indent;
+    forAll(meshes_, meshi)
+    {
+        const label nodeId = meshi + 1;
+
+        os  <<  nodeId;
+
+        if (meshi != meshes_.size() - 1) os  << ", ";
+
+        if ((meshi+1) % 10 == 0) os << nl << indent;
+    }
+
+    os  << decrIndent << nl << indent << "]," << nl
+        << indent << "\"name\" : \"parent\"" << nl << decrIndent
+        << indent << "}," << nl;
+
+    // List of child meshes
+    forAll(meshes_, meshi)
+    {
+        os  << indent << "{" << nl << incrIndent
+            << indent << "\"mesh\" : " << meshi << nl << decrIndent
+            << indent << "}";
+
+        if (meshi != meshes_.size() - 1) os  << ",";
+
+        os  << nl;
+    }
+
+    os  << decrIndent << indent << "]";
+
+    meshes_.write(os, "meshes");
+
+    bufferViews_.write(os, "bufferViews");
+
+    accessors_.write(os, "accessors");
+
+    animations_.write(os, "animations");
+
+    os  << nl;
+
+    os  << decrIndent << "}" << endl;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfScene.H b/src/fileFormats/gltf/foamGltfScene.H
new file mode 100644
index 0000000000000000000000000000000000000000..27f85f9ad032e524eb685cda84f79e0d7c35d880
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfScene.H
@@ -0,0 +1,162 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::glTF::scene
+
+Description
+    Main class to assemble glTF components into a scene
+
+Note
+    Implements the glTF v2 specification
+
+SourceFiles
+    foamGltfScene.C
+    foamGltfSceneTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef foam_gltf_scene_H
+#define foam_gltf_scene_H
+
+#include "foamGltfList.H"
+#include "foamGltfObject.H"
+#include "foamGltfMesh.H"
+#include "foamGltfBufferView.H"
+#include "foamGltfAccessor.H"
+#include "foamGltfAnimation.H"
+#include "scalarField.H"
+#include "vectorField.H"
+#include "OFstream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace glTF
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class glTF::scene Declaration
+\*---------------------------------------------------------------------------*/
+
+class scene
+{
+    // Private Data
+
+        //- List of binary objects
+        glTF::List<object> objects_;
+
+        //- List of meshes
+        glTF::List<mesh> meshes_;
+
+        //- List of buffer views
+        glTF::List<bufferView> bufferViews_;
+
+        //- List of accessors
+        glTF::List<accessor> accessors_;
+
+        //- List of animations
+        glTF::List<animation> animations_;
+
+        //- Accumulative size in bytes
+        label bytes_;
+
+
+public:
+
+    // Constructors
+
+        //- Default construct
+        scene();
+
+
+    // Public Member Functions
+
+        //- Returns accessor index
+        template<class Type>
+        label addField
+        (
+            const Type& fld,
+            const word& name,
+            const label target = -1
+        );
+
+        //- Returns index of last mesh
+        template<class Type>
+        label addMesh(const Type& fld, const word& name);
+
+        //- Returns accessor index
+        template<class Type>
+        label addFieldToMesh
+        (
+            const Type& fld,
+            const word& name,
+            const label meshi
+        );
+
+        //- Returns accessor index
+        label addColourToMesh
+        (
+            const vectorField& fld,
+            const word& name,
+            const label meshi,
+            const scalarField& alpha = scalarField()
+        );
+
+        //- Returns index of last animation
+        label createAnimation(const word& name);
+
+        //- Add to existing animation
+        void addToAnimation
+        (
+            const label animationi,
+            const label inputId,
+            const label outputId,
+            const label meshId,
+            const string& interpolation = "LINEAR"
+        );
+
+        //- Write to stream (JSON and binary data)
+        void write(Ostream& os);
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace glTF
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "foamGltfSceneTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/gltf/foamGltfSceneTemplates.C b/src/fileFormats/gltf/foamGltfSceneTemplates.C
new file mode 100644
index 0000000000000000000000000000000000000000..7ab03f2f8f5d532c60aa6e9542527840f722cb09
--- /dev/null
+++ b/src/fileFormats/gltf/foamGltfSceneTemplates.C
@@ -0,0 +1,95 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+Foam::label Foam::glTF::scene::addField
+(
+    const Type& fld,
+    const word& name,
+    const label target
+)
+{
+    const label nComponents = pTraits<typename Type::value_type>::nComponents;
+
+    auto& bv = bufferViews_.create(name);
+    bv.byteOffset() = bytes_;
+    bv.byteLength() = fld.size()*nComponents*sizeof(float);
+    if (target != -1)
+    {
+        bv.target() = target;
+    }
+    bytes_ += bv.byteLength();
+
+    auto& acc = accessors_.create(name);
+    acc.bufferViewId() = bv.id();
+    acc.set(fld);
+
+    auto& obj = objects_.create(name);
+    obj.addData(fld);
+
+    return acc.id();
+}
+
+
+template<class Type>
+Foam::label Foam::glTF::scene::addMesh(const Type& fld, const word& name)
+{
+    const label accessorId =
+        addField(fld, name, key(targetTypes::ARRAY_BUFFER));
+
+    auto& mesh = meshes_.create(name);
+    mesh.accessorId() = accessorId;
+
+    return meshes_.size() - 1;
+}
+
+
+template<class Type>
+Foam::label Foam::glTF::scene::addFieldToMesh
+(
+    const Type& fld,
+    const word& name,
+    const label meshi
+)
+{
+    if (meshi > meshes_.size() - 1)
+    {
+        FatalErrorInFunction
+            << "Mesh " << meshi << " out of range "
+            << (meshes_.size() - 1)
+            << abort(FatalError);
+    }
+
+    const label accessorId = addField(fld, name);
+
+    meshes_[meshi].addField(name, accessorId);
+
+    return accessorId;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.C b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.C
new file mode 100644
index 0000000000000000000000000000000000000000..295d1902dd78ab70e2e6186f6d924e2c290eb655
--- /dev/null
+++ b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.C
@@ -0,0 +1,625 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "gltfSetWriter.H"
+#include "coordSet.H"
+#include "fileName.H"
+#include "OFstream.H"
+#include "floatVector.H"
+#include "foamGltfScene.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+template<class Type>
+const Foam::Enum<typename Foam::gltfSetWriter<Type>::fieldOption>
+Foam::gltfSetWriter<Type>::fieldOptionNames_
+({
+    { fieldOption::UNIFORM, "uniform" },
+    { fieldOption::FIELD, "field" },
+});
+
+
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+template<class Type>
+Foam::word Foam::gltfSetWriter<Type>::getColourMap
+(
+    const dictionary& dict
+) const
+{
+    word colourMap = colourTable::predefinedNames.names()[0];
+    dict.readIfPresent("colourMap", colourMap);
+
+    return colourMap;
+}
+
+
+template<class Type>
+const Foam::colourTable& Foam::gltfSetWriter<Type>::getColourTable
+(
+    const dictionary& dict
+) const
+{
+    return colourTable::ref(getColourMap(dict));
+}
+
+
+template<class Type>
+Foam::scalar Foam::gltfSetWriter<Type>::getFieldMin
+(
+    const word& fieldName
+) const
+{
+    const dictionary fieldDict = fieldInfoDict_.subOrEmptyDict(fieldName);
+
+    return fieldDict.getOrDefault("min", -GREAT);
+}
+
+
+template<class Type>
+Foam::scalar Foam::gltfSetWriter<Type>::getFieldMax
+(
+    const word& fieldName
+) const
+{
+    const dictionary fieldDict = fieldInfoDict_.subOrEmptyDict(fieldName);
+
+    return fieldDict.getOrDefault("max", GREAT);
+}
+
+
+template<class Type>
+Foam::tmp<Foam::scalarField> Foam::gltfSetWriter<Type>::getAlphaField
+(
+    const dictionary& dict,
+    const wordList& valueSetNames,
+    const List<const Field<Type>*>& valueSets
+) const
+{
+    if (dict.found("alpha"))
+    {
+        const auto option = fieldOptionNames_.get("alpha", dict);
+
+        switch (option)
+        {
+            case fieldOption::UNIFORM:
+            {
+                const scalar value = dict.getScalar("alphaValue");
+                return tmp<scalarField>::New(valueSets[0]->size(), value);
+            }
+            case fieldOption::FIELD:
+            {
+                const word alphaFieldName = dict.get<word>("alphaField");
+                const bool normalise = dict.get<bool>("normalise");
+                const label i = valueSetNames.find(alphaFieldName);
+                if (i == -1)
+                {
+                    FatalErrorInFunction
+                        << "Unable to find field " << alphaFieldName
+                        << ". Valid field names are:" << valueSetNames
+                        << exit(FatalError);
+                }
+
+                auto tresult =
+                    tmp<scalarField>::New(valueSets[i]->component(0));
+
+                if (normalise)
+                {
+                    tresult.ref() /= mag(tresult() + ROOTVSMALL);
+                }
+
+                return tresult;
+            }
+        }
+    }
+
+    return tmp<scalarField>::New(valueSets[0]->size(), Zero);
+}
+
+
+template<class Type>
+Foam::tmp<Foam::scalarField> Foam::gltfSetWriter<Type>::getTrackAlphaField
+(
+    const dictionary& dict,
+    const wordList& valueSetNames,
+    const List<List<Field<Type>>>& valueSets,
+    const label tracki
+) const
+{
+    if (dict.found("alpha"))
+    {
+        const auto option = fieldOptionNames_.get("alpha", dict);
+
+        switch (option)
+        {
+            case fieldOption::UNIFORM:
+            {
+                const scalar value = dict.getScalar("alphaValue");
+                return tmp<scalarField>::New
+                (
+                    valueSets[0][tracki].size(), value
+                );
+            }
+            case fieldOption::FIELD:
+            {
+                const word alphaFieldName = dict.get<word>("alphaField");
+                const bool normalise = dict.get<bool>("normalise");
+                const label fieldi = valueSetNames.find(alphaFieldName);
+                if (fieldi == -1)
+                {
+                    FatalErrorInFunction
+                        << "Unable to find field " << alphaFieldName
+                        << ". Valid field names are:" << valueSetNames
+                        << exit(FatalError);
+                }
+
+                // Note: selecting the first component!
+                auto tresult =
+                    tmp<scalarField>::New
+                    (
+                        valueSets[fieldi][tracki].component(0)
+                    );
+
+                if (normalise)
+                {
+                    tresult.ref() /= mag(tresult() + ROOTVSMALL);
+                }
+
+                return tresult;
+            }
+        }
+    }
+
+    return tmp<scalarField>::New(valueSets[0][tracki].size(), Zero);
+}
+
+
+template<class Type>
+Foam::vector Foam::gltfSetWriter<Type>::getTrackAnimationColour
+(
+    const colourTable& colours,
+    const wordList& valueSetNames,
+    const List<List<Field<Type>>>& valueSets,
+    const label tracki
+) const
+{
+    if (!colour_)
+    {
+        FatalErrorInFunction
+            << "Attempting to get colour when colour option is off"
+            << abort(FatalError);
+    }
+
+    const auto option = fieldOptionNames_.get("colour", animationDict_);
+
+    switch (option)
+    {
+        case fieldOption::UNIFORM:
+        {
+            return animationDict_.get<vector>("colourValue");
+        }
+        case fieldOption::FIELD:
+        {
+            const word fieldName = animationDict_.get<word>("colourField");
+            const label fieldi = valueSetNames.find(fieldName);
+            if (fieldi == -1)
+            {
+                FatalErrorInFunction
+                    << "Unable to find field " << fieldName
+                    << ". Valid field names are:" << valueSetNames
+                    << exit(FatalError);
+            }
+
+            // Note: selecting the first component!
+
+            scalar minValue;
+            scalar maxValue;
+            if (!animationDict_.readIfPresent("min", minValue))
+            {
+                minValue = min(valueSets[fieldi][tracki].component(0));
+            }
+            if (!animationDict_.readIfPresent("max", maxValue))
+            {
+                maxValue = max(valueSets[fieldi][tracki].component(0));
+            }
+            const scalar refValue = component(valueSets[fieldi][tracki][0], 0);
+            const scalar fraction =
+                (refValue - minValue)/(maxValue - minValue + ROOTVSMALL);
+
+            return (colours.value(max(0, min(1, fraction))));
+        }
+    }
+
+    return vector::zero;
+}
+
+
+template<class Type>
+Foam::tmp<Foam::vectorField> Foam::gltfSetWriter<Type>::directions
+(
+    const coordSet& points
+) const
+{
+    auto tresult = tmp<vectorField>::New(points.size(), Zero);
+    auto& result = tresult.ref();
+
+    if (points.size() > 1)
+    {
+        for (label i = 1; i < points.size(); ++i)
+        {
+            result[i-1] = points[i] - points[i-1];
+            result[i-1].normalise();
+        }
+
+        result.last() = result[points.size()-2];
+    }
+
+
+    return tresult;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::gltfSetWriter<Type>::gltfSetWriter()
+:
+    writer<Type>(),
+    animate_(false),
+    colour_(false),
+    fieldInfoDict_(),
+    animationDict_()
+{}
+
+
+template<class Type>
+Foam::gltfSetWriter<Type>::gltfSetWriter(const dictionary& dict)
+:
+    writer<Type>(dict),
+    animate_(dict.getOrDefault("animate", false)),
+    colour_(dict.getOrDefault("colour", false)),
+    fieldInfoDict_(dict.subOrEmptyDict("fieldInfo")),
+    animationDict_(dict.subOrEmptyDict("animationInfo"))
+{
+    // fieldInfo
+    // {
+    //     U
+    //     {
+    //         colourMap       coolToWarm; // others...
+    //         min             10;
+    //         max             100;
+    //         alpha           field; // uniform|field
+    //         alphaField      ageOfAir;
+    //     }
+    // }
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+template<class Type>
+Foam::fileName Foam::gltfSetWriter<Type>::getFileName
+(
+    const coordSet& points,
+    const wordList& valueSetNames
+) const
+{
+    return this->getBaseName(points, valueSetNames) + ".gltf";
+}
+
+
+template<class Type>
+void Foam::gltfSetWriter<Type>::write
+(
+    const coordSet& points,
+    const wordList& valueSetNames,
+    const List<const Field<Type>*>& valueSets,
+    Ostream& os
+) const
+{
+    if (valueSets.size() != valueSetNames.size())
+    {
+        FatalErrorInFunction
+            << "Number of variables:" << valueSetNames.size() << endl
+            << "Number of valueSets:" << valueSets.size()
+            << exit(FatalError);
+    }
+
+    glTF::scene scene;
+    const label meshi = scene.addMesh(points, "points");
+    forAll(valueSetNames, i)
+    {
+        scene.addFieldToMesh(*valueSets[i], valueSetNames[i], meshi);
+    }
+
+    if (colour_)
+    {
+        forAll(valueSets, fieldi)
+        {
+            const auto& field = *valueSets[fieldi];
+            const word& fieldName = valueSetNames[fieldi];
+            const dictionary dict = fieldInfoDict_.subOrEmptyDict(fieldName);
+            const auto& colours = getColourTable(dict);
+
+            const auto talpha =
+                 getAlphaField(dict, valueSetNames, valueSets);
+            const scalarField& alpha = talpha();
+
+            const Type maxValue = max(field);
+            const Type minValue = min(field);
+
+            const scalar minValueLimit = getFieldMin(fieldName);
+            const scalar maxValueLimit = getFieldMax(fieldName);
+
+            for (direction cmpti=0; cmpti < pTraits<Type>::nComponents; ++cmpti)
+            {
+                vectorField fieldColour(field.size());
+
+                forAll(field, i)
+                {
+                    const Type& v = field[i];
+                    float f = component(v, cmpti);
+                    float minf = max(component(minValue, cmpti), minValueLimit);
+                    float maxf = min(component(maxValue, cmpti), maxValueLimit);
+                    float deltaf = (maxf - minf + SMALL);
+
+                    fieldColour[i] =
+                        colours.value(min(max((f - minf)/deltaf, 0), 1));
+                }
+
+                scene.addColourToMesh
+                (
+                    fieldColour,
+                    "Colour:" + fieldName + Foam::name(cmpti),
+                    meshi,
+                    alpha
+                );
+            }
+        }
+    }
+
+    scene.write(os);
+}
+
+
+template<class Type>
+void Foam::gltfSetWriter<Type>::write
+(
+    const bool writeTracks,
+    const List<scalarField>& times,
+    const PtrList<coordSet>& tracks,
+    const wordList& valueSetNames,
+    const List<List<Field<Type>>>& valueSets,
+    Ostream& os
+) const
+{
+    if (valueSets.size() != valueSetNames.size())
+    {
+        FatalErrorInFunction
+            << "Number of variables:" << valueSetNames.size() << endl
+            << "Number of valueSets:" << valueSets.size()
+            << exit(FatalError);
+    }
+
+    if (animate_)
+    {
+        writeAnimateTracks
+        (
+            writeTracks,
+            times,
+            tracks,
+            valueSetNames,
+            valueSets,
+            os
+        );
+    }
+    else
+    {
+        writeStaticTracks
+        (
+            writeTracks,
+            times,
+            tracks,
+            valueSetNames,
+            valueSets,
+            os
+        );
+    }
+}
+
+
+template<class Type>
+void Foam::gltfSetWriter<Type>::writeStaticTracks
+(
+    const bool writeTracks,
+    const List<scalarField>& times,
+    const PtrList<coordSet>& tracks,
+    const wordList& valueSetNames,
+    const List<List<Field<Type>>>& valueSets,
+    Ostream& os
+) const
+{
+    glTF::scene scene;
+    forAll(tracks, tracki)
+    {
+        const vectorField& track = tracks[tracki];
+        const label meshi = scene.addMesh(track, "track:" + Foam::name(tracki));
+        forAll(valueSetNames, fieldi)
+        {
+            const word& fieldName = valueSetNames[fieldi];
+            const auto& field = valueSets[fieldi][tracki];
+            scene.addFieldToMesh(field, fieldName, meshi);
+        }
+
+        if (colour_)
+        {
+            forAll(valueSets, fieldi)
+            {
+                const auto& field = valueSets[fieldi][tracki];
+                const word& fieldName = valueSetNames[fieldi];
+                const dictionary dict =
+                    fieldInfoDict_.subOrEmptyDict(fieldName);
+                const auto& colours = getColourTable(dict);
+
+                const auto talpha =
+                    getTrackAlphaField(dict, valueSetNames, valueSets, tracki);
+                const scalarField& alpha = talpha();
+
+                const Type maxValue = max(field);
+                const Type minValue = min(field);
+
+                const scalar minValueLimit = getFieldMin(fieldName);
+                const scalar maxValueLimit = getFieldMax(fieldName);
+
+                for
+                (
+                    direction cmpti=0;
+                    cmpti < pTraits<Type>::nComponents;
+                    ++cmpti
+                )
+                {
+                    vectorField fieldColour(field.size(), Zero);
+
+                    forAll(field, i)
+                    {
+                        const Type& v = field[i];
+                        float f = component(v, cmpti);
+                        float minf =
+                            max(component(minValue, cmpti), minValueLimit);
+                        float maxf =
+                            min(component(maxValue, cmpti), maxValueLimit);
+                        float deltaf = (maxf - minf + SMALL);
+
+                        fieldColour[i] =
+                           colours.value(min(max((f - minf)/deltaf, 0), 1));
+                    }
+
+                    scene.addColourToMesh
+                    (
+                        fieldColour,
+                        "Colour:" + fieldName + Foam::name(cmpti),
+                        meshi,
+                        alpha
+                    );
+                }
+            }
+        }
+    }
+
+    scene.write(os);
+}
+
+
+template<class Type>
+void Foam::gltfSetWriter<Type>::writeAnimateTracks
+(
+    const bool writeTracks,
+    const List<scalarField>& times,
+    const PtrList<coordSet>& tracks,
+    const wordList& valueSetNames,
+    const List<List<Field<Type>>>& valueSets,
+    Ostream& os
+) const
+{
+    const auto& colours = getColourTable(animationDict_);
+
+    glTF::scene scene;
+    const label animationi = scene.createAnimation("animation");
+
+    forAll(tracks, tracki)
+    {
+        const auto& track = tracks[tracki];
+
+        if (track.empty())
+        {
+            continue;
+        }
+
+        // Seed starting positions and field values
+        const label meshi =
+            scene.addMesh
+            (
+                vectorField(1, track[0]),
+                "track:" + Foam::name(tracki)
+            );
+
+        forAll(valueSetNames, fieldi)
+        {
+            const Field<Type>& field = valueSets[fieldi][tracki];
+            const word& fieldName = valueSetNames[fieldi];
+            scene.addFieldToMesh(Field<Type>(1, field[0]), fieldName, meshi);
+        }
+
+        // Time frames
+        const label timeId =
+            scene.addField(times[tracki], "time:" + Foam::name(tracki));
+
+        // Translations
+        const vectorField translation(track - track[0]);
+        const label translationId = scene.addField(translation, "translation");
+
+        scene.addToAnimation(animationi, timeId, translationId, meshi);
+
+        // Note: colours cannot be animated... setting a fixed value
+        if (colour_)
+        {
+            const vector colour =
+                getTrackAnimationColour
+                (
+                    colours,
+                    valueSetNames,
+                    valueSets,
+                    tracki
+                );
+
+            const auto talpha =
+                getTrackAlphaField
+                (
+                    animationDict_,
+                    valueSetNames,
+                    valueSets,
+                    tracki
+                );
+
+            const scalarField& alpha = talpha();
+
+            scene.addColourToMesh
+            (
+                vectorField(1, colour),
+                "Colour:fixed",
+                meshi,
+                scalarField(1, alpha[0])
+            );
+        }
+    }
+
+    scene.write(os);
+}
+
+
+// ************************************************************************* //
diff --git a/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.H b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.H
new file mode 100644
index 0000000000000000000000000000000000000000..b4936440f9530cd9e78fb661621c608e80e2596a
--- /dev/null
+++ b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriter.H
@@ -0,0 +1,312 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::gltfSetWriter
+
+Description
+    Writes point data in glTF v2 format
+
+    Two files are generated:
+    - filename.bin  : a binary file containing all scene entities
+    - filename.gltf : a JSON file that ties fields to the binary data
+
+    The output can contain both geometry and fields, with additional support
+    for colours using a user-supplied colour map, and animation of particle
+    tracks.
+
+    Controls are provided via the optional formatOptions dictionary.
+
+    For non-particle track data:
+
+    \verbatim
+    formatOptions
+    {
+        // Apply colours flag (yes | no ) [optional]
+        colours     yes;
+
+        // List of options per field
+        fieldInfo
+        {
+            p
+            {
+                // Colour map [optional]
+                colourMap       <colourMap>;
+
+                // Colour map minimum and maximum limits [optional]
+                // Uses field min and max if not specified
+                min             0;
+                max             1;
+
+                // Alpha channel [optional] (uniform | field)
+                alpha           uniform;
+                alphaValue      0.5;
+
+                //alpha           field;
+                //alphaField      T;
+                //normalise       yes;
+            }
+        }
+    }
+    \verbatim
+
+    For particle tracks:
+
+    \verbatim
+    formatOptions
+    {
+        // Apply colours flag (yes | no) [optional]
+        colours     yes;
+
+        // Animate tracks (yes | no) [optional]
+        animate     yes;
+
+        // Animation properties [optional]
+        animationInfo
+        {
+            // Colour map [optional]
+            colourMap       <colourMap>;
+
+            // Colour [optional] (uniform | field)
+            colour          uniform;
+            colourValue     (1 0 0); // RGB in range [0-1]
+
+            //colour          field;
+            //colourField     d;
+
+            // Colour map minimum and maximum limits [optional]
+            // Note: for colour = field option
+            // Uses field min and max if not specified
+            min             0;
+            max             1;
+
+            // Alpha channel [optional] (uniform | field)
+            alpha           uniform;
+            alphaValue      0.5;
+
+            //alpha           field;
+            //alphaField      T;
+            //normalise       yes;
+        }
+    }
+    \endverbatim
+
+Note
+    When writing particle animations, the particle field and colour properties
+    correspond to initial particle state (first data point) and cannot be
+    animated (limitation of the file format).
+
+    For more information on the specification see
+    https://www.khronos.org/registry/glTF/
+
+SourceFiles
+    gltfSetWriter.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef writers_gltfSetWriter_H
+#define writers_gltfSetWriter_H
+
+#include "writer.H"
+#include "colourTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                        Class gltfSetWriter Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class Type>
+class gltfSetWriter
+:
+    public writer<Type>
+{
+public:
+
+    // Enumerations
+
+        //- Field option used for colours
+        enum class fieldOption
+        {
+            UNIFORM,    //!< Uniform value
+            FIELD       //!< field value
+        };
+
+
+    //- Strings corresponding to the field options
+    static const Enum<fieldOption> fieldOptionNames_;
+
+
+private:
+
+    // Private Data
+
+        //- Flag to animate - for particle tracks only
+        bool animate_;
+
+        //- Flag to add field colours
+        bool colour_;
+
+        //- Local field information
+        const dictionary fieldInfoDict_;
+
+        //- Animation information
+        const dictionary animationDict_;
+
+
+    // Private Member Functions
+
+        //- Return the colour map name
+        word getColourMap(const dictionary& dict) const;
+
+        //- Return the colour table corresponding to the colour map
+        const colourTable& getColourTable(const dictionary& dict) const;
+
+        //- Return the field minimum value
+        scalar getFieldMin(const word& fieldName) const;
+
+        //- Return the field maximum value
+        scalar getFieldMax(const word& fieldName) const;
+
+        //- Return the alpha field for mesh values
+        tmp<scalarField> getAlphaField
+        (
+            const dictionary& dict,
+            const wordList& valueSetNames,
+            const List<const Field<Type>*>& valueSets
+        ) const;
+
+        //- Return the alpha field for tracks
+        tmp<scalarField> getTrackAlphaField
+        (
+            const dictionary& dict,
+            const wordList& valueSetNames,
+            const List<List<Field<Type>>>& valueSets,
+            const label tracki
+        ) const;
+
+        //- Return the animation colour when animating tracks
+        vector getTrackAnimationColour
+        (
+            const colourTable& colours,
+            const wordList& valueSetNames,
+            const List<List<Field<Type>>>& valueSets,
+            const label tracki
+        ) const;
+
+        //- Return track orientation/dirrections
+        tmp<vectorField> directions(const coordSet& points) const;
+
+
+public:
+
+    //- Runtime type information
+    TypeName("gltf");
+
+
+    // Constructors
+
+        //- Default construct
+        gltfSetWriter();
+
+        //- Construct from dictionary
+        explicit gltfSetWriter(const dictionary& dict);
+
+
+    //- Destructor
+    virtual ~gltfSetWriter() = default;
+
+
+    // Member Functions
+
+        //- Return the file name
+        virtual fileName getFileName
+        (
+            const coordSet&,
+            const wordList&
+        ) const;
+
+        //- Write
+        virtual void write
+        (
+            const coordSet&,
+            const wordList&,
+            const List<const Field<Type>*>&,
+            Ostream&
+        ) const;
+
+        //- Write tracks (main entry point)
+        virtual void write
+        (
+            const bool writeTracks,
+            const List<scalarField>& times,
+            const PtrList<coordSet>&,
+            const wordList& valueSetNames,
+            const List<List<Field<Type>>>&,
+            Ostream&
+        ) const;
+
+        //- Write animated tracks
+        virtual void writeAnimateTracks
+        (
+            const bool writeTracks,
+            const List<scalarField>& times,
+            const PtrList<coordSet>& tracks,
+            const wordList& valueSetNames,
+            const List<List<Field<Type>>>& valueSets,
+            Ostream&
+        ) const;
+
+        //- Write static tracks
+        virtual void writeStaticTracks
+        (
+            const bool writeTracks,
+            const List<scalarField>& times,
+            const PtrList<coordSet>& tracks,
+            const wordList& valueSetNames,
+            const List<List<Field<Type>>>& valueSets,
+            Ostream&
+        ) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+    #include "gltfSetWriter.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/sampledSetWriters/gltf/gltfSetWriterRunTime.C b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriterRunTime.C
new file mode 100644
index 0000000000000000000000000000000000000000..aeb390b4e9bc48d8b978796507efa1afafe7a2a7
--- /dev/null
+++ b/src/fileFormats/sampledSetWriters/gltf/gltfSetWriterRunTime.C
@@ -0,0 +1,39 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "gltfSetWriter.H"
+#include "writers.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    makeSetWriters(gltfSetWriter);
+}
+
+// ************************************************************************* //