Commit d19535e9 authored by Adrien Boucaud's avatar Adrien Boucaud

Add support for the glTF KHR_lights_punctual extension in vtkGLTFImporter.

parent 24e2ae20
......@@ -75,11 +75,15 @@ std::string value_to_string(const T& val)
}
}
//----------------------------------------------------------------------------
const std::vector<std::string> vtkGLTFDocumentLoader::SupportedExtensions = {
"KHR_lights_punctual"
};
//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkGLTFDocumentLoader);
/** Metadata loading **/
//----------------------------------------------------------------------------
bool vtkGLTFDocumentLoader::LoadModelMetaDataFromFile(std::string fileName)
{
......@@ -95,7 +99,7 @@ bool vtkGLTFDocumentLoader::LoadModelMetaDataFromFile(std::string fileName)
}
this->InternalModel->FileName = fileName;
if (!impl.LoadModelMetaDataFromFile(fileName))
if (!impl.LoadModelMetaDataFromFile(fileName, this->UsedExtensions))
{
return false;
}
......@@ -1210,6 +1214,18 @@ std::shared_ptr<vtkGLTFDocumentLoader::Model> vtkGLTFDocumentLoader::GetInternal
return std::shared_ptr<Model>(this->InternalModel);
}
//----------------------------------------------------------------------------
const std::vector<std::string>& vtkGLTFDocumentLoader::GetSupportedExtensions()
{
return vtkGLTFDocumentLoader::SupportedExtensions;
}
//----------------------------------------------------------------------------
const std::vector<std::string>& vtkGLTFDocumentLoader::GetUsedExtensions()
{
return this->UsedExtensions;
}
/** types and enums **/
//----------------------------------------------------------------------------
unsigned int vtkGLTFDocumentLoader::GetNumberOfComponentsForType(
......
......@@ -43,6 +43,7 @@
#include <map> // For std::map
#include <memory> // For std::shared_ptr
#include <string> // For std::string
#include <vector> // For std::vector
class vtkDataArray;
......@@ -229,6 +230,18 @@ public:
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();
......@@ -449,6 +462,42 @@ public:
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
*/
......@@ -468,6 +517,8 @@ public:
std::vector<Skin> Skins;
std::vector<Texture> Textures;
Extensions ExtensionMetaData;
std::string BufferMetaData;
int DefaultScene;
std::string FileName;
......@@ -511,6 +562,16 @@ public:
*/
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;
......@@ -570,6 +631,9 @@ private:
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
......@@ -27,6 +27,7 @@
#include "vtk_jsoncpp_fwd.h" // For Json forward declaration
#include <string> // For string
#include <vector> // For vector
class vtkGLTFDocumentLoaderInternals
{
......@@ -35,9 +36,10 @@ public:
/**
* Reset internal Model struct, and serialize glTF metadata (all json information) into it.
* Fill usedExtensions vector with the list of used and supported extensions in the glTF file.
* To load buffers, use LoadModelData
*/
bool LoadModelMetaDataFromFile(std::string& FileName);
bool LoadModelMetaDataFromFile(std::string& FileName, std::vector<std::string>& usedExtensions);
vtkGLTFDocumentLoader* Self;
/**
......@@ -54,6 +56,17 @@ public:
static const unsigned short GL_TRIANGLE_FAN = 0x0006;
private:
/**
* Load node-level extension metadata into the Node::Extensions struct.
*/
bool LoadNodeExtensions(
const Json::Value& root, vtkGLTFDocumentLoader::Node::Extensions& nodeExtensions);
/**
* Load root-level extension metadata into the Extensions struct.
*/
bool LoadExtensions(const Json::Value& root, vtkGLTFDocumentLoader::Extensions& extensions);
/**
* Reads a Json value describing a glTF buffer object, then uses this information to load the
* corresponding binary buffer into an std::vector<char> array.
......@@ -61,6 +74,7 @@ private:
*/
bool LoadBuffer(
const Json::Value& root, std::vector<char>& buffer, const std::string& glTFFileName);
/**
* Load a glTF file and parse it into a Json value. File extension can be either .gltf
* or .glb. In case of a binary glTF file, only the Json part will be read.
......@@ -169,6 +183,26 @@ private:
*/
vtkGLTFDocumentLoader::Material::AlphaModeType MaterialAlphaModeStringToEnum(
std::string alphaModeString);
/**
* Load node-specific KHR_lights_punctual metadata into the Node::Extensions::KHRLightsPunctual
* struct (load light indices).
*/
bool LoadKHRLightsPunctualNodeExtension(const Json::Value& root,
vtkGLTFDocumentLoader::Node::Extensions::KHRLightsPunctual& lightsExtension);
/**
* Load root-level KHR_lights_punctual metadata into the Extensions::KHRLightsPunctual struct
* (load all lights).
*/
bool LoadKHRLightsPunctualExtension(
const Json::Value& root, vtkGLTFDocumentLoader::Extensions::KHRLightsPunctual& lights);
/**
* Load a KHR_lights_punctual light object into the Extensions::KHRLightsPunctual::Light struct.
*/
bool LoadKHRLightsPunctualExtensionLight(
const Json::Value& root, vtkGLTFDocumentLoader::Extensions::KHRLightsPunctual::Light& light);
};
#endif
......
......@@ -66,5 +66,9 @@ vtk_add_test_cxx(vtkIOImportCxxTests tests
TestGLTFImporter,TestGLTFImporter.cxx DATA{../Data/glTF/Avocado/Avocado.glb}
)
vtk_add_test_cxx(vtkIOImportCxxTests tests
TestGLTFImporterKHRLightsPunctual,TestGLTFImporter.cxx DATA{../Data/glTF/Lights/lights.gltf}
)
vtk_test_cxx_executable(vtkIOImportCxxTests tests
RENDERING_FACTORY)
7e74b711fce2d4e03c6823cdaf93c281bb82d0ae75371274f91f234347ada93fa6412f8a2739d74dc0402a6d8e68bb62f6f435932d93762fbd2319d84626e695
dfc2e8e0b9d1e1c5888ab26b3fed6e21826f3d6a60e82900bc09854806ee8fde4dcee1a932c7d3cb871505ae71161978f759745ae3ec076caf2f18782658d791
......@@ -31,12 +31,16 @@
#include "vtkTransform.h"
#include "vtksys/SystemTools.hxx"
#include <algorithm>
#include <stack>
vtkStandardNewMacro(vtkGLTFImporter);
namespace
{
// Desired attenuation value when distanceToLight == lightRange
static const float MIN_LIGHT_ATTENUATION = 0.01;
/**
* Builds a new vtkCamera object with properties from a glTF Camera struct
*/
......@@ -48,7 +52,7 @@ vtkSmartPointer<vtkCamera> GLTFCameraToVTKCamera(const vtkGLTFDocumentLoader::Ca
if (gltfCam.IsPerspective)
{
vtkCam->SetParallelProjection(false);
vtkCam->SetViewAngle(gltfCam.Yfov);
vtkCam->SetViewAngle(vtkMath::DegreesFromRadians(gltfCam.Yfov));
}
else
{
......@@ -352,6 +356,78 @@ void vtkGLTFImporter::ImportCameras(vtkRenderer* renderer)
}
}
//----------------------------------------------------------------------------
void vtkGLTFImporter::ImportLights(vtkRenderer* renderer)
{
// Check that lights extension is enabled
const auto& extensions = this->Loader->GetUsedExtensions();
if (std::find(extensions.begin(), extensions.end(), "KHR_lights_punctual") == extensions.end())
{
return;
}
// List of nodes to import
std::stack<int> nodeIdStack;
const auto& model = this->Loader->GetInternalModel();
const auto& lights = model->ExtensionMetaData.KHRLightsPunctualMetaData.Lights;
// Add root nodes to the stack
for (int nodeId : model->Scenes[model->DefaultScene].Nodes)
{
nodeIdStack.push(nodeId);
}
// Iterate over tree
while (!nodeIdStack.empty())
{
// Get current node
int nodeId = nodeIdStack.top();
nodeIdStack.pop();
const vtkGLTFDocumentLoader::Node& node = model->Nodes[nodeId];
const auto lightId = node.ExtensionMetaData.KHRLightsPunctualMetaData.Light;
if (lightId >= 0 && lightId < static_cast<int>(lights.size()))
{
const auto& glTFLight = lights[lightId];
// Add light
vtkNew<vtkLight> light;
light->SetColor(glTFLight.Color.data());
light->SetTransformMatrix(node.GlobalTransform->GetMatrix());
// Handle range
if (glTFLight.Range > 0)
{
// Set quadratic values to get attenuation(range) ~= MIN_LIGHT_ATTENUATION
light->SetAttenuationValues(
1, 0, 1.0 / (glTFLight.Range * glTFLight.Range * MIN_LIGHT_ATTENUATION));
}
light->SetIntensity(glTFLight.Intensity);
switch (glTFLight.Type)
{
case vtkGLTFDocumentLoader::Extensions::KHRLightsPunctual::Light::LightType::DIRECTIONAL:
light->SetPositional(false);
break;
case vtkGLTFDocumentLoader::Extensions::KHRLightsPunctual::Light::LightType::POINT:
light->SetPositional(true);
// Set as point light
light->SetConeAngle(180);
break;
case vtkGLTFDocumentLoader::Extensions::KHRLightsPunctual::Light::LightType::SPOT:
light->SetPositional(true);
light->SetConeAngle(vtkMath::DegreesFromRadians(glTFLight.SpotOuterConeAngle));
break;
}
renderer->AddLight(light);
}
// Add node's children to stack
for (int childNodeId : node.Children)
{
nodeIdStack.push(childNodeId);
}
}
}
//----------------------------------------------------------------------------
void vtkGLTFImporter::PrintSelf(ostream& os, vtkIndent indent)
{
......
......@@ -37,6 +37,12 @@
* https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
*
* Note: array sizes should not exceed INT_MAX
*
* Supported extensions:
* - KHR_lights_punctual :
* The importer supports the KHR_lights_punctual extension except for this feature:
* - VTK does not support changing the falloff of the cone with innerConeAngle and outerConeAngle.
* The importer uses outerConeAngle and ignores innerConeAngle as specified for this situation.
*/
#ifndef vtkGLTFImporter_h
......@@ -88,6 +94,7 @@ protected:
int ImportBegin() override;
void ImportActors(vtkRenderer* renderer) override;
void ImportCameras(vtkRenderer* renderer) override;
void ImportLights(vtkRenderer* renderer) override;
char* FileName;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment