-
-
Notifications
You must be signed in to change notification settings - Fork 234
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements GLTF Draco extension support (#1287)
- Loading branch information
Showing
20 changed files
with
385 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
be69fa3a50de292857e69702885576ac6f114805 | ||
697646db54ce4de95ff5adb500799e49feee4935 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
void applyCustomReader(vtkAlgorithm* algo, const std::string&) const override | ||
{ | ||
vtkGLTFReader* gltfReader = vtkGLTFReader::SafeDownCast(algo); | ||
|
||
// Enable all animations in the GLTFReader | ||
// Specifying a non-zero framerate in the next call is not needed after VTK 9.2.20230603 : VTK_VERSION_CHECK(9, 2, 20230603) | ||
gltfReader->SetFrameRate(30); | ||
gltfReader->ApplyDeformationsToGeometryOn(); | ||
gltfReader->UpdateInformation(); // Read model metadata to get the number of animations | ||
for (vtkIdType i = 0; i < gltfReader->GetNumberOfAnimations(); i++) | ||
{ | ||
gltfReader->EnableAnimation(i); | ||
} | ||
// It is needed to update the information directly in order to recover it later | ||
// Not entirely understood, TODO | ||
gltfReader->UpdateInformation(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include "vtkF3DGLTFDocumentLoader.h" | ||
|
||
#include <vtkObjectFactory.h> | ||
|
||
#include <algorithm> | ||
|
||
#include "draco/compression/decode.h" | ||
|
||
namespace | ||
{ | ||
|
||
//---------------------------------------------------------------------------- | ||
template<typename T> | ||
std::vector<char> DecodeIndexBuffer(const std::unique_ptr<draco::Mesh>& mesh) | ||
{ | ||
std::vector<char> outBuffer(mesh->num_faces() * 3 * sizeof(T)); | ||
|
||
for (draco::FaceIndex f(0); f < mesh->num_faces(); ++f) | ||
{ | ||
const draco::Mesh::Face& face = mesh->face(f); | ||
|
||
T indices[3] = { static_cast<T>(face[0].value()), static_cast<T>(face[1].value()), | ||
static_cast<T>(face[2].value()) }; | ||
|
||
std::copy( | ||
indices, indices + 3, reinterpret_cast<T*>(outBuffer.data() + f.value() * sizeof(indices))); | ||
} | ||
|
||
return outBuffer; | ||
} | ||
|
||
//---------------------------------------------------------------------------- | ||
std::vector<char> DecodeIndexBuffer( | ||
const std::unique_ptr<draco::Mesh>& mesh, vtkGLTFDocumentLoader::ComponentType compType) | ||
{ | ||
// indexing using float does not make sense | ||
assert(compType != vtkGLTFDocumentLoader::ComponentType::FLOAT); | ||
|
||
switch (compType) | ||
{ | ||
case vtkGLTFDocumentLoader::ComponentType::BYTE: | ||
return DecodeIndexBuffer<int8_t>(mesh); | ||
case vtkGLTFDocumentLoader::ComponentType::UNSIGNED_BYTE: | ||
return DecodeIndexBuffer<uint16_t>(mesh); | ||
case vtkGLTFDocumentLoader::ComponentType::SHORT: | ||
return DecodeIndexBuffer<int16_t>(mesh); | ||
case vtkGLTFDocumentLoader::ComponentType::UNSIGNED_SHORT: | ||
return DecodeIndexBuffer<uint16_t>(mesh); | ||
case vtkGLTFDocumentLoader::ComponentType::UNSIGNED_INT: | ||
return DecodeIndexBuffer<uint32_t>(mesh); | ||
default: | ||
break; | ||
} | ||
|
||
return {}; | ||
} | ||
|
||
//---------------------------------------------------------------------------- | ||
template<typename T> | ||
std::vector<char> DecodeVertexBuffer( | ||
const std::unique_ptr<draco::Mesh>& mesh, const draco::PointAttribute* attribute) | ||
{ | ||
std::vector<char> outBuffer(mesh->num_points() * attribute->num_components() * sizeof(T)); | ||
std::vector<T> values(attribute->num_components()); | ||
|
||
size_t byteOffset = 0; | ||
for (draco::PointIndex i(0); i < mesh->num_points(); ++i) | ||
{ | ||
attribute->ConvertValue<T>( | ||
attribute->mapped_index(i), attribute->num_components(), values.data()); | ||
|
||
std::copy(values.begin(), values.end(), reinterpret_cast<T*>(outBuffer.data() + byteOffset)); | ||
|
||
byteOffset += sizeof(T) * attribute->num_components(); | ||
} | ||
|
||
return outBuffer; | ||
} | ||
|
||
//---------------------------------------------------------------------------- | ||
std::vector<char> DecodeVertexBuffer(vtkGLTFDocumentLoader::ComponentType compType, | ||
const std::unique_ptr<draco::Mesh>& mesh, int attIndex) | ||
{ | ||
(void)compType; | ||
|
||
const draco::PointAttribute* attribute = mesh->GetAttributeByUniqueId(attIndex); | ||
|
||
assert(compType == vtkGLTFDocumentLoader::ComponentType::FLOAT); | ||
|
||
return DecodeVertexBuffer<float>(mesh, attribute); | ||
} | ||
} | ||
|
||
//---------------------------------------------------------------------------- | ||
vtkStandardNewMacro(vtkF3DGLTFDocumentLoader); | ||
|
||
//---------------------------------------------------------------------------- | ||
std::vector<std::string> vtkF3DGLTFDocumentLoader::GetSupportedExtensions() | ||
{ | ||
std::vector<std::string> extensions = this->Superclass::GetSupportedExtensions(); | ||
extensions.emplace_back("KHR_draco_mesh_compression"); | ||
return extensions; | ||
} | ||
|
||
//---------------------------------------------------------------------------- | ||
void vtkF3DGLTFDocumentLoader::PrepareData() | ||
{ | ||
std::shared_ptr<Model> model = this->GetInternalModel(); | ||
|
||
for (size_t i = 0; i < model->Meshes.size(); i++) | ||
{ | ||
for (Primitive& primitive : model->Meshes[i].Primitives) | ||
{ | ||
// check if Draco metadata is present | ||
auto& dracoMetaData = primitive.ExtensionMetaData.KHRDracoMetaData; | ||
if (dracoMetaData.BufferView >= 0) | ||
{ | ||
auto& view = model->BufferViews[primitive.ExtensionMetaData.KHRDracoMetaData.BufferView]; | ||
auto& buffer = model->Buffers[view.Buffer]; | ||
|
||
draco::DecoderBuffer decoderBuffer; | ||
decoderBuffer.Init(buffer.data() + view.ByteOffset, view.ByteLength); | ||
auto decodeResult = draco::Decoder().DecodeMeshFromBuffer(&decoderBuffer); | ||
if (decodeResult.ok()) | ||
{ | ||
const std::unique_ptr<draco::Mesh>& mesh = decodeResult.value(); | ||
|
||
// handle index buffer | ||
if (primitive.IndicesId >= 0) | ||
{ | ||
auto& accessor = model->Accessors[primitive.IndicesId]; | ||
|
||
model->Buffers.emplace_back(::DecodeIndexBuffer(mesh, accessor.ComponentTypeValue)); | ||
|
||
vtkGLTFDocumentLoader::BufferView decodedIndexBufferView; | ||
decodedIndexBufferView.Buffer = static_cast<int>(model->Buffers.size() - 1); | ||
decodedIndexBufferView.ByteLength = model->Buffers.back().size(); | ||
decodedIndexBufferView.ByteOffset = 0; | ||
decodedIndexBufferView.ByteStride = 0; | ||
decodedIndexBufferView.Target = | ||
static_cast<int>(vtkGLTFDocumentLoader::Target::ARRAY_BUFFER); | ||
model->BufferViews.emplace_back(std::move(decodedIndexBufferView)); | ||
|
||
accessor.BufferView = static_cast<int>(model->BufferViews.size() - 1); | ||
accessor.Count = static_cast<int>(mesh->num_faces() * 3); | ||
} | ||
|
||
// handle vertex attributes | ||
for (const auto& attrib : dracoMetaData.AttributeIndices) | ||
{ | ||
auto& attrAccessor = model->Accessors[primitive.AttributeIndices[attrib.first]]; | ||
|
||
model->Buffers.emplace_back( | ||
::DecodeVertexBuffer(attrAccessor.ComponentTypeValue, mesh, attrib.second)); | ||
|
||
vtkGLTFDocumentLoader::BufferView decodedBufferView; | ||
decodedBufferView.Buffer = static_cast<int>(model->Buffers.size() - 1); | ||
decodedBufferView.ByteLength = model->Buffers.back().size(); | ||
decodedBufferView.ByteOffset = 0; | ||
decodedBufferView.ByteStride = 0; | ||
decodedBufferView.Target = | ||
static_cast<int>(vtkGLTFDocumentLoader::Target::ELEMENT_ARRAY_BUFFER); | ||
model->BufferViews.emplace_back(std::move(decodedBufferView)); | ||
|
||
attrAccessor.BufferView = static_cast<int>(model->BufferViews.size() - 1); | ||
attrAccessor.Count = static_cast<int>(mesh->num_points()); | ||
attrAccessor.ByteOffset = 0; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* @class vtkF3DGLTFDocumentLoader | ||
* @brief Specialized GLTF document loader with Draco buffer decoding | ||
* | ||
* This class subclasses vtkGLTFDocumentLoader to handle Draco metadata | ||
*/ | ||
|
||
#ifndef vtkF3DGLTFDocumentLoader_h | ||
#define vtkF3DGLTFDocumentLoader_h | ||
|
||
#include <vtkGLTFDocumentLoader.h> | ||
|
||
class vtkF3DGLTFDocumentLoader : public vtkGLTFDocumentLoader | ||
{ | ||
public: | ||
static vtkF3DGLTFDocumentLoader* New(); | ||
vtkTypeMacro(vtkF3DGLTFDocumentLoader, vtkGLTFDocumentLoader); | ||
|
||
/** | ||
* Overridden to add KHR_draco_mesh_compression support | ||
*/ | ||
std::vector<std::string> GetSupportedExtensions() override; | ||
|
||
/** | ||
* Overridden to handle Draco metadata and modify the GLTF model. | ||
* This will take information in metadata to decode buffers and replace | ||
* the buffer view in the accessors to point to the new decoded buffers. | ||
*/ | ||
void PrepareData() override; | ||
|
||
protected: | ||
vtkF3DGLTFDocumentLoader() = default; | ||
~vtkF3DGLTFDocumentLoader() override = default; | ||
|
||
private: | ||
vtkF3DGLTFDocumentLoader(const vtkF3DGLTFDocumentLoader&) = delete; | ||
void operator=(const vtkF3DGLTFDocumentLoader&) = delete; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include "vtkF3DGLTFImporter.h" | ||
|
||
#include "vtkF3DGLTFDocumentLoader.h" | ||
|
||
#include <vtkObjectFactory.h> | ||
|
||
//---------------------------------------------------------------------------- | ||
vtkStandardNewMacro(vtkF3DGLTFImporter); | ||
|
||
//---------------------------------------------------------------------------- | ||
void vtkF3DGLTFImporter::InitializeLoader() | ||
{ | ||
this->Loader = vtkSmartPointer<vtkF3DGLTFDocumentLoader>::New(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* @class vtkF3DGLTFImporter | ||
* @brief VTK GLTF importer with Draco support | ||
* | ||
* Subclasses the native importer to initialize our own loader. | ||
* @sa vtkF3DGLTFDocumentLoader | ||
*/ | ||
|
||
#ifndef vtkF3DGLTFImporter_h | ||
#define vtkF3DGLTFImporter_h | ||
|
||
#include <vtkGLTFImporter.h> | ||
|
||
class vtkF3DGLTFImporter : public vtkGLTFImporter | ||
{ | ||
public: | ||
static vtkF3DGLTFImporter* New(); | ||
vtkTypeMacro(vtkF3DGLTFImporter, vtkGLTFImporter); | ||
|
||
protected: | ||
vtkF3DGLTFImporter() = default; | ||
~vtkF3DGLTFImporter() override = default; | ||
|
||
/** | ||
* Overridden to instantiate our own document loader | ||
*/ | ||
void InitializeLoader() override; | ||
|
||
private: | ||
vtkF3DGLTFImporter(const vtkF3DGLTFImporter&) = delete; | ||
void operator=(const vtkF3DGLTFImporter&) = delete; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include "vtkF3DGLTFReader.h" | ||
|
||
#include "vtkF3DGLTFDocumentLoader.h" | ||
|
||
#include <vtkObjectFactory.h> | ||
|
||
//---------------------------------------------------------------------------- | ||
vtkStandardNewMacro(vtkF3DGLTFReader); | ||
|
||
//---------------------------------------------------------------------------- | ||
void vtkF3DGLTFReader::InitializeLoader() | ||
{ | ||
this->Loader = vtkSmartPointer<vtkF3DGLTFDocumentLoader>::New(); | ||
} |
Oops, something went wrong.