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); +} + +// ************************************************************************* //