Skip to content

Commit

Permalink
GLTF Loader: enabled normalized accessors
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Jan 20, 2024
1 parent 36fe848 commit 169a569
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 40 deletions.
37 changes: 26 additions & 11 deletions AssetLoader/interface/GLTFBuilder.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -129,15 +129,20 @@ class ModelBuilder
template <typename GltfModelType>
bool LoadAnimationAndSkin(const GltfModelType& GltfModel);

static void WriteGltfData(const void* pSrc,
VALUE_TYPE SrcType,
Uint32 NumSrcComponents,
Uint32 SrcElemStride,
std::vector<Uint8>::iterator dst_it,
VALUE_TYPE DstType,
Uint32 NumDstComponents,
Uint32 DstElementStride,
Uint32 NumElements);
struct WriteGltfDataAttribs
{
const void* pSrc;
VALUE_TYPE SrcType;
Uint32 NumSrcComponents;
Uint32 SrcElemStride;
std::vector<Uint8>::iterator dst_it;
VALUE_TYPE DstType;
Uint32 NumDstComponents;
Uint32 DstElementStride;
Uint32 NumElements;
bool IsNormalized;
};
static void WriteGltfData(const WriteGltfDataAttribs& Attribs);

static void WriteDefaultAttibuteValue(const void* pDefaultValue,
std::vector<Uint8>::iterator dst_it,
Expand Down Expand Up @@ -676,12 +681,22 @@ Uint32 ModelBuilder::ConvertVertexData(const GltfModelType& GltfModel,
const auto ValueType = GltfVerts.Accessor.GetComponentType();
const auto NumComponents = GltfVerts.Accessor.GetNumComponents();
const auto SrcStride = GltfVerts.ByteStride;
const bool IsNormalized = GltfVerts.Accessor.IsNormalized();
VERIFY_EXPR(SrcStride > 0);

auto dst_it = VertexData.begin() + DataOffset + Attrib.RelativeOffset;

VERIFY_EXPR(static_cast<Uint32>(GltfVerts.Count) == VertexCount);
WriteGltfData(GltfVerts.pData, ValueType, NumComponents, SrcStride, dst_it, Attrib.ValueType, Attrib.NumComponents, VertexStride, VertexCount);
WriteGltfData({GltfVerts.pData,
ValueType,
static_cast<Uint32>(NumComponents),
static_cast<Uint32>(SrcStride),
dst_it,
Attrib.ValueType,
Attrib.NumComponents,
VertexStride,
VertexCount,
IsNormalized});

m_Model.VertexData.EnabledAttributeFlags |= (1u << i);
}
Expand Down
103 changes: 75 additions & 28 deletions AssetLoader/src/GLTFBuilder.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,26 +57,68 @@ size_t ModelBuilder::PrimitiveKey::Hasher::operator()(const PrimitiveKey& Key) c
return Key.Hash;
}

template <typename SrcType, typename DstType>
inline void ConvertElement(DstType& Dst, const SrcType& Src)
template <typename DstType, bool Normalize, typename SrcType>
inline DstType ConvertElement(SrcType Src)
{
Dst = static_cast<DstType>(Src);
return static_cast<DstType>(Src);
}

// =========================== float -> Int8/Uint8 ============================
template <>
inline void ConvertElement<float, Uint8>(Uint8& Dst, const float& Src)
inline Uint8 ConvertElement<Uint8, true, float>(float Src)
{
Dst = static_cast<Uint8>(clamp(Src * 255.f + 0.5f, 0.f, 255.f));
return static_cast<Uint8>(clamp(Src * 255.f + 0.5f, 0.f, 255.f));
}

template <>
inline void ConvertElement<float, Int8>(Int8& Dst, const float& Src)
inline Uint8 ConvertElement<Uint8, false, float>(float Src)
{
return ConvertElement<Uint8, true>(Src);
}

template <>
inline Int8 ConvertElement<Int8, true, float>(float Src)
{
auto r = Src > 0.f ? +0.5f : -0.5f;
Dst = static_cast<Int8>(clamp(Src * 127.f + r, -127.f, 127.f));
return static_cast<Int8>(clamp(Src * 127.f + r, -127.f, 127.f));
}

template <>
inline Int8 ConvertElement<Int8, false, float>(float Src)
{
return ConvertElement<Int8, true>(Src);
}


// =========================== Int8/Uint8 -> float ============================
template <>
inline float ConvertElement<float, true, Int8>(Int8 Src)
{
return std::max(static_cast<float>(Src), -127.f) / 127.f;
}

template <>
inline float ConvertElement<float, true, Uint8>(Uint8 Src)
{
return static_cast<float>(Src) / 255.f;
}


// ========================== Int16/Uint16 -> float ===========================
template <>
inline float ConvertElement<float, true, Int16>(Int16 Src)
{
return std::max(static_cast<float>(Src), -32767.f) / 32767.f;
}

template <typename SrcType, typename DstType>
template <>
inline float ConvertElement<float, true, Uint16>(Uint16 Src)
{
return static_cast<float>(Src) / 65535.f;
}


template <typename SrcType, typename DstType, bool IsNormalized>
inline void WriteGltfData(const void* pSrc,
Uint32 NumComponents,
Uint32 SrcElemStride,
Expand All @@ -91,33 +133,38 @@ inline void WriteGltfData(const void* pSrc,
auto comp_it = dst_it + DstElementStride * elem;
for (Uint32 cmp = 0; cmp < NumComponents; ++cmp, comp_it += sizeof(DstType))
{
ConvertElement(reinterpret_cast<DstType&>(*comp_it), pSrcCmp[cmp]);
reinterpret_cast<DstType&>(*comp_it) = ConvertElement<DstType, IsNormalized>(pSrcCmp[cmp]);
}
}
}

void ModelBuilder::WriteGltfData(const void* pSrc,
VALUE_TYPE SrcType,
Uint32 NumSrcComponents,
Uint32 SrcElemStride,
std::vector<Uint8>::iterator dst_it,
VALUE_TYPE DstType,
Uint32 NumDstComponents,
Uint32 DstElementStride,
Uint32 NumElements)
void ModelBuilder::WriteGltfData(const WriteGltfDataAttribs& Attribs)
{
const auto NumComponentsToCopy = std::min(NumSrcComponents, NumDstComponents);

#define INNER_CASE(SrcType, DstType) \
case DstType: \
GLTF::WriteGltfData<typename VALUE_TYPE2CType<SrcType>::CType, \
typename VALUE_TYPE2CType<DstType>::CType>( \
pSrc, NumComponentsToCopy, SrcElemStride, dst_it, DstElementStride, NumElements); \
const auto NumComponentsToCopy = std::min(Attribs.NumSrcComponents, Attribs.NumDstComponents);

#define INNER_CASE(SrcType, DstType) \
case DstType: \
if (Attribs.IsNormalized) \
{ \
GLTF::WriteGltfData<typename VALUE_TYPE2CType<SrcType>::CType, \
typename VALUE_TYPE2CType<DstType>::CType, \
true>( \
Attribs.pSrc, NumComponentsToCopy, Attribs.SrcElemStride, \
Attribs.dst_it, Attribs.DstElementStride, Attribs.NumElements); \
} \
else \
{ \
GLTF::WriteGltfData<typename VALUE_TYPE2CType<SrcType>::CType, \
typename VALUE_TYPE2CType<DstType>::CType, \
false>( \
Attribs.pSrc, NumComponentsToCopy, Attribs.SrcElemStride, \
Attribs.dst_it, Attribs.DstElementStride, Attribs.NumElements); \
} \
break

#define CASE(SrcType) \
case SrcType: \
switch (DstType) \
switch (Attribs.DstType) \
{ \
INNER_CASE(SrcType, VT_INT8); \
INNER_CASE(SrcType, VT_INT16); \
Expand All @@ -133,7 +180,7 @@ void ModelBuilder::WriteGltfData(const void* pSrc,
} \
break

switch (SrcType)
switch (Attribs.SrcType)
{
CASE(VT_INT8);
CASE(VT_INT16);
Expand Down
3 changes: 2 additions & 1 deletion AssetLoader/src/GLTFLoader.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2019-2024 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -174,6 +174,7 @@ struct TinyGltfAccessorWrapper
auto GetByteOffset() const { return Accessor.byteOffset; }
auto GetComponentType() const { return TinyGltfComponentTypeToValueType(Accessor.componentType); }
auto GetNumComponents() const { return tinygltf::GetNumComponentsInType(Accessor.type); }
bool IsNormalized() const { return Accessor.normalized; }
// clang-format on
auto GetByteStride(const TinyGltfBufferViewWrapper& View) const;
};
Expand Down

0 comments on commit 169a569

Please sign in to comment.