You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
643 lines
17 KiB
C++
643 lines
17 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkGLTFDocumentLoader.h
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
/**
|
|
* @class vtkGLTFDocumentLoader
|
|
* @brief Deserialize a GLTF model file.
|
|
*
|
|
*
|
|
* vtkGLTFDocument loader is an internal utility class which defines data structures and functions
|
|
* with the purpose of deserializing a glTF model from a glTF file, loading its data from binary
|
|
* buffers and creating vtk objects with the extracted geometry.
|
|
* It contains an internal Model structure into which all loading is performed.
|
|
*
|
|
* The GL Transmission Format (glTF) is an API-neutral runtime asset delivery format.
|
|
* A glTF asset is represented by:
|
|
* - A JSON-formatted file (.gltf) containing a full scene description: node hierarchy, materials,
|
|
* cameras, as well as descriptor information for meshes, animations, and other constructs
|
|
* - Binary files (.bin) containing geometry and animation data, and other buffer-based data
|
|
* - Image files (.jpg, .png) for textures
|
|
*
|
|
* For the full specification, see:
|
|
* https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
|
|
*/
|
|
|
|
#ifndef vtkGLTFDocumentLoader_h
|
|
#define vtkGLTFDocumentLoader_h
|
|
|
|
#include "vtkIOGeometryModule.h" // For export macro
|
|
#include "vtkObject.h"
|
|
#include "vtkSmartPointer.h" // For SmartPointer
|
|
|
|
#include <map> // For std::map
|
|
#include <memory> // For std::shared_ptr
|
|
#include <string> // For std::string
|
|
#include <vector> // For std::vector
|
|
|
|
class vtkCellArray;
|
|
class vtkDataArray;
|
|
class vtkFloatArray;
|
|
class vtkImageData;
|
|
class vtkMatrix4x4;
|
|
class vtkPoints;
|
|
class vtkPolyData;
|
|
class vtkTransform;
|
|
class vtkUnsignedShortArray;
|
|
|
|
class VTKIOGEOMETRY_EXPORT vtkGLTFDocumentLoader : public vtkObject
|
|
{
|
|
public:
|
|
static vtkGLTFDocumentLoader* New();
|
|
vtkTypeMacro(vtkGLTFDocumentLoader, vtkObject);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
/**
|
|
* Define an openGL draw target.
|
|
*/
|
|
enum class Target : unsigned short
|
|
{
|
|
ARRAY_BUFFER = 34962,
|
|
ELEMENT_ARRAY_BUFFER = 34963
|
|
};
|
|
|
|
/**
|
|
* Defines an accessor's type. These are defined as strings in the glTF specification.
|
|
* Each type implies a specific number of components.
|
|
*/
|
|
enum class AccessorType : unsigned char
|
|
{
|
|
SCALAR,
|
|
VEC2,
|
|
VEC3,
|
|
VEC4,
|
|
MAT2,
|
|
MAT3,
|
|
MAT4,
|
|
INVALID
|
|
};
|
|
|
|
/**
|
|
* Define a type for different data components. Values match with the corresponding GLenum, as
|
|
* they are used in the glTF specification.
|
|
*/
|
|
enum class ComponentType : unsigned short
|
|
{
|
|
BYTE = 5120,
|
|
UNSIGNED_BYTE = 5121,
|
|
SHORT = 5122,
|
|
UNSIGNED_SHORT = 5123,
|
|
UNSIGNED_INT = 5125,
|
|
FLOAT = 5126
|
|
};
|
|
|
|
/* The following structs help deserialize a glTF document, representing each object. As such,
|
|
* their members mostly match with the specification. Default values and boundaries are set
|
|
* according to the specification.
|
|
* Most of these structs contain a name property, which is optional, and, while being loaded, is
|
|
* not currently exploited by the loader.
|
|
* They are mostly root-level properties, and once created, are stored into vectors in the Model
|
|
* structure.
|
|
*/
|
|
|
|
/**
|
|
* This struct describes a glTF bufferView object.
|
|
* A bufferView represents a subset of a glTF binary buffer
|
|
*/
|
|
struct BufferView
|
|
{
|
|
int Buffer;
|
|
int ByteOffset;
|
|
int ByteLength;
|
|
int ByteStride;
|
|
int Target;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes an accessor glTF object.
|
|
* An accessor defines a method for retrieving data as typed arrays from a bufferView.
|
|
* They contain type information, as well as the location and size of of the data within the
|
|
* bufferView.
|
|
*/
|
|
struct Accessor
|
|
{
|
|
/**
|
|
* This struct describes an accessor.sparse glTF object.
|
|
* This object describes the elements that deviate from their initialization value.
|
|
*/
|
|
struct Sparse
|
|
{
|
|
int Count;
|
|
int IndicesBufferView;
|
|
int IndicesByteOffset;
|
|
ComponentType IndicesComponentType;
|
|
int ValuesBufferView;
|
|
int ValuesByteOffset;
|
|
};
|
|
int BufferView;
|
|
int ByteOffset;
|
|
ComponentType ComponentTypeValue;
|
|
bool Normalized;
|
|
int Count;
|
|
unsigned int NumberOfComponents;
|
|
AccessorType Type;
|
|
std::vector<double> Max;
|
|
std::vector<double> Min;
|
|
bool IsSparse;
|
|
Sparse SparseObject;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF Morph Target object.
|
|
* A Morph Target is a morphable Mesh where primitives' attributes are obtained by adding the
|
|
* original attributes to a weighted sum of targets attributes.
|
|
* Only three attributes (position, normals and tangents) are supported.
|
|
*/
|
|
struct MorphTarget
|
|
{
|
|
// accessor indices from the .gltf file, the map's keys correspond to attribute names
|
|
std::map<std::string, int> AttributeIndices;
|
|
// attribute values
|
|
std::map<std::string, vtkSmartPointer<vtkFloatArray> > AttributeValues;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF primitive object.
|
|
* primitives specify vertex attributes, as well as connectivity information for a draw call.
|
|
* A primitive also specifies a material and GPU primitive type (e.g: triangle set)
|
|
* Data is first stored as integer indices, pointing to different accessors, then extracted into
|
|
* vtk data structures and finally used to build a vtkPolyData object.
|
|
*/
|
|
struct Primitive
|
|
{
|
|
// accessor indices from the .glTF file, the map's keys correspond to attribute names
|
|
std::map<std::string, int> AttributeIndices;
|
|
int IndicesId;
|
|
vtkSmartPointer<vtkCellArray> Indices;
|
|
|
|
// attribute values from buffer data
|
|
std::map<std::string, vtkSmartPointer<vtkDataArray> > AttributeValues;
|
|
|
|
vtkSmartPointer<vtkPolyData> Geometry;
|
|
|
|
std::vector<MorphTarget> Targets;
|
|
|
|
int Material;
|
|
int Mode;
|
|
int CellSize; // 1, 2 or 3, depending on draw mode
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF node object.
|
|
* A node represents an object within a scene.
|
|
* Nodes can contain transform properties (stored as vtkTransform objects) as well as indices to
|
|
* children nodes, forming a hierarchy. No node may be a direct descendant of more than one node.
|
|
*/
|
|
struct Node
|
|
{
|
|
std::vector<int> Children;
|
|
int Camera;
|
|
int Mesh;
|
|
int Skin;
|
|
|
|
vtkSmartPointer<vtkTransform> Transform;
|
|
vtkSmartPointer<vtkTransform> GlobalTransform;
|
|
|
|
bool TRSLoaded;
|
|
|
|
vtkSmartPointer<vtkMatrix4x4> Matrix;
|
|
|
|
std::vector<float> InitialRotation;
|
|
std::vector<float> InitialTranslation;
|
|
std::vector<float> InitialScale;
|
|
std::vector<float> InitialWeights;
|
|
std::vector<float> Rotation;
|
|
std::vector<float> Translation;
|
|
std::vector<float> Scale;
|
|
std::vector<float> Weights;
|
|
|
|
// Object-specific extension metadata
|
|
struct Extensions
|
|
{
|
|
// KHR_lights_punctual extension
|
|
struct KHRLightsPunctual
|
|
{
|
|
int Light = -1;
|
|
};
|
|
Node::Extensions::KHRLightsPunctual KHRLightsPunctualMetaData;
|
|
};
|
|
Node::Extensions ExtensionMetaData;
|
|
|
|
std::string Name;
|
|
|
|
void UpdateTransform();
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF mesh object.
|
|
* A mesh contains an array of primitives.
|
|
*/
|
|
struct Mesh
|
|
{
|
|
std::vector<struct Primitive> Primitives;
|
|
std::vector<float> Weights;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF textureInfo object, mostly used in material descriptions
|
|
* They contain two indexes, one to a texture object, and the second being used to construct a
|
|
* string with the format TEXCOORD_<index>, which references a key in mesh.primitives.attributes.
|
|
*/
|
|
struct TextureInfo
|
|
{
|
|
int Index = -1;
|
|
int TexCoord;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF image object.
|
|
* Images can be referenced either by URI or with a bufferView. mimeType is required in this case.
|
|
*/
|
|
struct Image
|
|
{
|
|
int BufferView;
|
|
std::string MimeType;
|
|
std::string Uri;
|
|
|
|
vtkSmartPointer<vtkImageData> ImageData;
|
|
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF material object.
|
|
* glTF materials are defined using the metallic-roughness model. The values for most properties
|
|
* can be defined using either factors or textures (via textureInfo).
|
|
* Materials also define normal, occlusion and emissive maps.
|
|
*/
|
|
struct Material
|
|
{
|
|
enum class AlphaModeType : unsigned char
|
|
{
|
|
OPAQUE,
|
|
MASK,
|
|
BLEND
|
|
};
|
|
|
|
struct PbrMetallicRoughness
|
|
{
|
|
TextureInfo BaseColorTexture;
|
|
std::vector<double> BaseColorFactor;
|
|
|
|
TextureInfo MetallicRoughnessTexture;
|
|
float MetallicFactor;
|
|
float RoughnessFactor;
|
|
};
|
|
|
|
PbrMetallicRoughness PbrMetallicRoughness;
|
|
|
|
TextureInfo NormalTexture;
|
|
double NormalTextureScale;
|
|
TextureInfo OcclusionTexture;
|
|
double OcclusionTextureStrength;
|
|
TextureInfo EmissiveTexture;
|
|
std::vector<double> EmissiveFactor;
|
|
|
|
AlphaModeType AlphaMode;
|
|
double AlphaCutoff;
|
|
|
|
bool DoubleSided;
|
|
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF texture object.
|
|
* A texture is defined two indexes, one to an image resource, and the second to a sampler index.
|
|
*/
|
|
struct Texture
|
|
{
|
|
int Sampler;
|
|
int Source;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF sampler object.
|
|
* Samplers specify filter and wrapping options corresponding to GL types.
|
|
*/
|
|
struct Sampler
|
|
{
|
|
enum FilterType : unsigned short
|
|
{
|
|
NEAREST = 9728,
|
|
LINEAR = 9729,
|
|
NEAREST_MIPMAP_NEAREST = 9984,
|
|
LINEAR_MIPMAP_NEAREST = 9985,
|
|
NEAREST_MIPMAP_LINEAR = 9986,
|
|
LINEAR_MIPMAP_LINEAR = 9987
|
|
};
|
|
enum WrapType : unsigned short
|
|
{
|
|
CLAMP_TO_EDGE = 33071,
|
|
MIRRORED_REPEAT = 33648,
|
|
REPEAT = 10497
|
|
};
|
|
FilterType MagFilter;
|
|
FilterType MinFilter;
|
|
WrapType WrapS;
|
|
WrapType WrapT;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF scene object.
|
|
* A scene contains a set of indices of nodes to render.
|
|
* Scene.Nodes can be empty, in which case nothing is required to be rendered
|
|
*/
|
|
struct Scene
|
|
{
|
|
std::vector<unsigned int> Nodes;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF asset.
|
|
* It is meant to mimic a .glTF file, containing all its root-level properties, stored as arrays
|
|
* when relevant.
|
|
*/
|
|
struct Skin
|
|
{
|
|
std::vector<vtkSmartPointer<vtkMatrix4x4> > InverseBindMatrices;
|
|
std::vector<int> Joints;
|
|
int InverseBindMatricesAccessorId;
|
|
int Skeleton;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF animation object.
|
|
* Animations contain multiple channel and sampler objects.
|
|
* Channels define the target node and value to be animated.
|
|
* Samplers define keyframes and how to interpolate in between them.
|
|
*/
|
|
struct Animation
|
|
{
|
|
struct Sampler
|
|
{
|
|
enum class InterpolationMode : unsigned char
|
|
{
|
|
LINEAR,
|
|
STEP,
|
|
CUBICSPLINE
|
|
};
|
|
InterpolationMode Interpolation;
|
|
unsigned int Input;
|
|
unsigned int Output;
|
|
int NumberOfComponents;
|
|
|
|
vtkSmartPointer<vtkFloatArray> InputData;
|
|
vtkSmartPointer<vtkFloatArray> OutputData;
|
|
|
|
/**
|
|
* Get the interpolated animation output at time t
|
|
*/
|
|
void GetInterpolatedData(float t, size_t numberOfComponents, std::vector<float>* output,
|
|
bool forceStep = false, bool isRotation = false) const;
|
|
};
|
|
|
|
struct Channel
|
|
{
|
|
enum class PathType : unsigned char
|
|
{
|
|
ROTATION,
|
|
TRANSLATION,
|
|
SCALE,
|
|
WEIGHTS
|
|
};
|
|
int Sampler;
|
|
int TargetNode;
|
|
PathType TargetPath;
|
|
};
|
|
|
|
float Duration; // In seconds
|
|
std::vector<Animation::Channel> Channels;
|
|
std::vector<Animation::Sampler> Samplers;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct describes a glTF camera object.
|
|
* glTF can define both perpective or orthographic cameras.
|
|
* Some of the struct's members will be unused depending on the camera type.
|
|
*/
|
|
struct Camera
|
|
{
|
|
// common properties
|
|
double Znear;
|
|
double Zfar;
|
|
bool IsPerspective; // if not, camera mode is orthographic
|
|
// perspective
|
|
double Xmag;
|
|
double Ymag;
|
|
// orthographic
|
|
double Yfov;
|
|
double AspectRatio;
|
|
std::string Name;
|
|
};
|
|
|
|
/**
|
|
* This struct contains extension metadata.
|
|
* This is for extension properties in the root-level 'extensions' object.
|
|
* Object-specific extension metadata is added directly to the extended object (see Node for an
|
|
* example)
|
|
*/
|
|
struct Extensions
|
|
{
|
|
// KHR_lights_punctual extension
|
|
struct KHRLightsPunctual
|
|
{
|
|
struct Light
|
|
{
|
|
enum class LightType : unsigned char
|
|
{
|
|
DIRECTIONAL,
|
|
POINT,
|
|
SPOT
|
|
};
|
|
LightType Type;
|
|
|
|
std::vector<double> Color;
|
|
double Intensity;
|
|
double Range;
|
|
|
|
// Type-specific parameters
|
|
double SpotInnerConeAngle;
|
|
double SpotOuterConeAngle;
|
|
|
|
std::string Name;
|
|
};
|
|
std::vector<Light> Lights;
|
|
};
|
|
KHRLightsPunctual KHRLightsPunctualMetaData;
|
|
};
|
|
|
|
/**
|
|
* This struct contains all data from a gltf asset
|
|
*/
|
|
struct Model
|
|
{
|
|
std::vector<Accessor> Accessors;
|
|
std::vector<Animation> Animations;
|
|
std::vector<std::vector<char> > Buffers;
|
|
std::vector<BufferView> BufferViews;
|
|
std::vector<Camera> Cameras;
|
|
std::vector<Image> Images;
|
|
std::vector<Material> Materials;
|
|
std::vector<Mesh> Meshes;
|
|
std::vector<Node> Nodes;
|
|
std::vector<Sampler> Samplers;
|
|
std::vector<Scene> Scenes;
|
|
std::vector<Skin> Skins;
|
|
std::vector<Texture> Textures;
|
|
|
|
Extensions ExtensionMetaData;
|
|
|
|
std::string BufferMetaData;
|
|
int DefaultScene;
|
|
std::string FileName;
|
|
};
|
|
|
|
/**
|
|
* Apply the specified animation, at the specified time, to the internal Model. Changes node
|
|
* transforms and morphing weights.
|
|
*/
|
|
bool ApplyAnimation(float t, int animationId, bool forceStep = false);
|
|
|
|
/**
|
|
* Restore the transforms that were modified by an animation to their initial state
|
|
*/
|
|
void ResetAnimation(int animationId);
|
|
|
|
/**
|
|
* Load the binary part of a binary glTF (.glb) file. Returns false if no valid binary part was
|
|
* found.
|
|
*/
|
|
bool LoadFileBuffer(const std::string& fileName, std::vector<char>& glbBuffer);
|
|
|
|
/**
|
|
* Reset internal Model struct, and serialize glTF metadata (all json information) into it.
|
|
* To load buffers, use LoadModelData
|
|
*/
|
|
bool LoadModelMetaDataFromFile(std::string FileName);
|
|
|
|
/**
|
|
* Load buffer data into the internal Model.
|
|
*/
|
|
bool LoadModelData(const std::vector<char>& glbBuffer);
|
|
|
|
/**
|
|
* Converts the internal Model's loaded data into more convenient vtk objects.
|
|
*/
|
|
bool BuildModelVTKGeometry();
|
|
|
|
/**
|
|
* Get the internal Model.
|
|
*/
|
|
std::shared_ptr<Model> GetInternalModel();
|
|
|
|
/**
|
|
* Returns the number of components for a given accessor type.
|
|
*/
|
|
static unsigned int GetNumberOfComponentsForType(vtkGLTFDocumentLoader::AccessorType type);
|
|
|
|
/**
|
|
* Get the list of extensions that are supported by this loader
|
|
*/
|
|
const std::vector<std::string>& GetSupportedExtensions();
|
|
|
|
/**
|
|
* Get the list of extensions that are used by the current model
|
|
*/
|
|
const std::vector<std::string>& GetUsedExtensions();
|
|
|
|
protected:
|
|
vtkGLTFDocumentLoader() = default;
|
|
~vtkGLTFDocumentLoader() override = default;
|
|
|
|
private:
|
|
struct AccessorLoadingWorker;
|
|
|
|
struct SparseAccessorLoadingWorker;
|
|
|
|
template <typename Type>
|
|
struct BufferDataExtractionWorker;
|
|
|
|
vtkGLTFDocumentLoader(const vtkGLTFDocumentLoader&) = delete;
|
|
void operator=(const vtkGLTFDocumentLoader&) = delete;
|
|
|
|
/**
|
|
* Load inverse bind matrices from buffers into the model's Skin structs.
|
|
*/
|
|
bool LoadSkinMatrixData();
|
|
|
|
/**
|
|
* Uses the Primitive's attributeIndices member to extract all vertex attributes from accessors
|
|
* into the Primitive's corresponding vtk arrays.
|
|
*/
|
|
bool ExtractPrimitiveAttributes(Primitive& primitive);
|
|
|
|
/**
|
|
* Uses all the primitive's different accessor indices to extract the corresponding data from
|
|
* binary buffers. These arrays are then stored in the primitive's different vtk arrays.
|
|
* Extracts connectivity information then calls ExtractPrimitiveAttributes for the vertex
|
|
* attributes
|
|
*/
|
|
bool ExtractPrimitiveAccessorData(Primitive& primitive);
|
|
|
|
/**
|
|
* Creates and populates the Primitive's geometry vtkPolyData member with all the vertex attribute
|
|
* and connectivity information the Primitive contains.
|
|
*/
|
|
bool BuildPolyDataFromPrimitive(Primitive& primitive);
|
|
|
|
/**
|
|
* Load keyframes from buffers.
|
|
*/
|
|
bool LoadAnimationData();
|
|
|
|
/**
|
|
* Load Model's Images into vtkImageData objects, from filesystem and bufferView when specified.
|
|
*/
|
|
bool LoadImageData();
|
|
|
|
/**
|
|
* Concatenate the current node's local transform to its parent's global transform, storing
|
|
* the resulting transform in the node's globalTransform field. Then does the same for the current
|
|
* node's children.
|
|
* Recursive.
|
|
*/
|
|
void BuildGlobalTransforms(unsigned int nodeIndex, vtkSmartPointer<vtkTransform> parentTransform);
|
|
|
|
std::shared_ptr<Model> InternalModel;
|
|
|
|
static const std::vector<std::string> SupportedExtensions;
|
|
std::vector<std::string> UsedExtensions;
|
|
};
|
|
|
|
#endif
|