Merge pull request #3219 from thomasbiang/gltf2_sparseAccessor_import
Gltf2 Support Importing sparse accessorpull/3262/head
commit
1427e67b54
|
@ -318,9 +318,11 @@ class Ref {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ref() :
|
Ref() :
|
||||||
vector(0), index(0) {}
|
vector(0),
|
||||||
|
index(0) {}
|
||||||
Ref(std::vector<T *> &vec, unsigned int idx) :
|
Ref(std::vector<T *> &vec, unsigned int idx) :
|
||||||
vector(&vec), index(idx) {}
|
vector(&vec),
|
||||||
|
index(idx) {}
|
||||||
|
|
||||||
inline unsigned int GetIndex() const { return index; }
|
inline unsigned int GetIndex() const { return index; }
|
||||||
|
|
||||||
|
@ -340,7 +342,8 @@ struct Nullable {
|
||||||
Nullable() :
|
Nullable() :
|
||||||
isPresent(false) {}
|
isPresent(false) {}
|
||||||
Nullable(T &val) :
|
Nullable(T &val) :
|
||||||
value(val), isPresent(true) {}
|
value(val),
|
||||||
|
isPresent(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Base class for all glTF top-level objects
|
//! Base class for all glTF top-level objects
|
||||||
|
@ -363,49 +366,28 @@ struct Object {
|
||||||
// Classes for each glTF top-level object type
|
// Classes for each glTF top-level object type
|
||||||
//
|
//
|
||||||
|
|
||||||
//! Base class for types that access binary data from a BufferView, such as accessors
|
|
||||||
//! or sparse accessors' indices.
|
|
||||||
//! N.B. not a virtual class. All owned pointers to BufferViewClient instances should
|
|
||||||
//! be to their most derived types (which may of course be just BufferViewClient).
|
|
||||||
struct BufferViewClient : public Object {
|
|
||||||
Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
|
|
||||||
size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
|
|
||||||
|
|
||||||
inline uint8_t *GetPointer();
|
|
||||||
|
|
||||||
void Read(Value &obj, Asset &r);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! BufferViewClient with component type information.
|
|
||||||
//! N.B. not a virtual class. All owned pointers to ComponentTypedBufferViewClient
|
|
||||||
//! instances should be to their most derived types (which may of course be just
|
|
||||||
//! ComponentTypedBufferViewClient).
|
|
||||||
struct ComponentTypedBufferViewClient : public BufferViewClient {
|
|
||||||
ComponentType componentType; //!< The datatype of components in the attribute. (required)
|
|
||||||
|
|
||||||
unsigned int GetBytesPerComponent();
|
|
||||||
|
|
||||||
void Read(Value &obj, Asset &r);
|
|
||||||
};
|
|
||||||
|
|
||||||
//! A typed view into a BufferView. A BufferView contains raw binary data.
|
//! A typed view into a BufferView. A BufferView contains raw binary data.
|
||||||
//! An accessor provides a typed view into a BufferView or a subset of a BufferView
|
//! An accessor provides a typed view into a BufferView or a subset of a BufferView
|
||||||
//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
|
//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
|
||||||
struct Accessor : public ComponentTypedBufferViewClient {
|
struct Accessor : public Object {
|
||||||
struct Sparse;
|
struct Sparse;
|
||||||
|
|
||||||
|
Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
|
||||||
|
size_t byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
|
||||||
|
ComponentType componentType; //!< The datatype of components in the attribute. (required)
|
||||||
size_t count; //!< The number of attributes referenced by this accessor. (required)
|
size_t count; //!< The number of attributes referenced by this accessor. (required)
|
||||||
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
|
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
|
||||||
std::vector<double> max; //!< Maximum value of each component in this attribute.
|
std::vector<double> max; //!< Maximum value of each component in this attribute.
|
||||||
std::vector<double> min; //!< Minimum value of each component in this attribute.
|
std::vector<double> min; //!< Minimum value of each component in this attribute.
|
||||||
std::unique_ptr<Sparse> sparse; //!< Sparse accessor information
|
std::unique_ptr<Sparse> sparse;
|
||||||
|
|
||||||
unsigned int GetNumComponents();
|
unsigned int GetNumComponents();
|
||||||
|
unsigned int GetBytesPerComponent();
|
||||||
unsigned int GetElementSize();
|
unsigned int GetElementSize();
|
||||||
|
|
||||||
inline uint8_t *GetPointer();
|
inline uint8_t *GetPointer();
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
void ExtractData(T *&outData);
|
void ExtractData(T *&outData);
|
||||||
|
|
||||||
void WriteData(size_t count, const void *src_buffer, size_t src_stride);
|
void WriteData(size_t count, const void *src_buffer, size_t src_stride);
|
||||||
|
@ -425,7 +407,6 @@ struct Accessor : public ComponentTypedBufferViewClient {
|
||||||
|
|
||||||
Indexer(Accessor &acc);
|
Indexer(Accessor &acc);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! Accesses the i-th value as defined by the accessor
|
//! Accesses the i-th value as defined by the accessor
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -441,62 +422,27 @@ struct Accessor : public ComponentTypedBufferViewClient {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Sparse accessor information
|
|
||||||
struct Sparse {
|
|
||||||
size_t count;
|
|
||||||
ComponentTypedBufferViewClient indices;
|
|
||||||
BufferViewClient values;
|
|
||||||
|
|
||||||
std::vector<uint8_t> data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it.
|
|
||||||
|
|
||||||
inline void PopulateData(size_t numBytes, uint8_t *bytes) {
|
|
||||||
if (bytes) {
|
|
||||||
data.assign(bytes, bytes + numBytes);
|
|
||||||
} else {
|
|
||||||
data.resize(numBytes, 0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void PatchData(unsigned int elementSize)
|
|
||||||
{
|
|
||||||
uint8_t *pIndices = indices.GetPointer();
|
|
||||||
const unsigned int indexSize = indices.GetBytesPerComponent();
|
|
||||||
uint8_t *indicesEnd = pIndices + count * indexSize;
|
|
||||||
|
|
||||||
uint8_t *pValues = values.GetPointer();
|
|
||||||
while (pIndices != indicesEnd) {
|
|
||||||
size_t offset;
|
|
||||||
switch (indices.componentType) {
|
|
||||||
case ComponentType_UNSIGNED_BYTE:
|
|
||||||
offset = *pIndices;
|
|
||||||
break;
|
|
||||||
case ComponentType_UNSIGNED_SHORT:
|
|
||||||
offset = *reinterpret_cast<uint16_t *>(pIndices);
|
|
||||||
break;
|
|
||||||
case ComponentType_UNSIGNED_INT:
|
|
||||||
offset = *reinterpret_cast<uint32_t *>(pIndices);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// have fun with float and negative values from signed types as indices.
|
|
||||||
throw DeadlyImportError("Unsupported component type in index.");
|
|
||||||
}
|
|
||||||
|
|
||||||
offset *= elementSize;
|
|
||||||
std::memcpy(data.data() + offset, pValues, elementSize);
|
|
||||||
|
|
||||||
pValues += elementSize;
|
|
||||||
pIndices += indexSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Indexer GetIndexer() {
|
inline Indexer GetIndexer() {
|
||||||
return Indexer(*this);
|
return Indexer(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Accessor() {}
|
Accessor() {}
|
||||||
|
|
||||||
void Read(Value &obj, Asset &r);
|
void Read(Value &obj, Asset &r);
|
||||||
|
|
||||||
|
//sparse
|
||||||
|
struct Sparse {
|
||||||
|
size_t count;
|
||||||
|
ComponentType indicesType;
|
||||||
|
Ref<BufferView> indices;
|
||||||
|
size_t indicesByteOffset;
|
||||||
|
Ref<BufferView> values;
|
||||||
|
size_t valuesByteOffset;
|
||||||
|
|
||||||
|
std::vector<uint8_t> data; //!< Actual data, which may be defaulted to an array of zeros or the original data, with the sparse buffer view applied on top of it.
|
||||||
|
|
||||||
|
void PopulateData(size_t numBytes, uint8_t *bytes);
|
||||||
|
void PatchData(unsigned int elementSize);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//! A buffer points to binary geometry, animation, or skins.
|
//! A buffer points to binary geometry, animation, or skins.
|
||||||
|
@ -525,7 +471,11 @@ public:
|
||||||
/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
|
/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
|
||||||
/// \param [in] pID - ID of the region.
|
/// \param [in] pID - ID of the region.
|
||||||
SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string pID) :
|
SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string pID) :
|
||||||
Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
|
Offset(pOffset),
|
||||||
|
EncodedData_Length(pEncodedData_Length),
|
||||||
|
DecodedData(pDecodedData),
|
||||||
|
DecodedData_Length(pDecodedData_Length),
|
||||||
|
ID(pID) {}
|
||||||
|
|
||||||
/// \fn ~SEncodedRegion()
|
/// \fn ~SEncodedRegion()
|
||||||
/// Destructor.
|
/// Destructor.
|
||||||
|
@ -629,6 +579,7 @@ struct BufferView : public Object {
|
||||||
BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
|
BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
|
||||||
|
|
||||||
void Read(Value &obj, Asset &r);
|
void Read(Value &obj, Asset &r);
|
||||||
|
uint8_t *GetPointer(size_t accOffset);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Camera : public Object {
|
struct Camera : public Object {
|
||||||
|
@ -656,7 +607,8 @@ struct Camera : public Object {
|
||||||
} cameraProperties;
|
} cameraProperties;
|
||||||
|
|
||||||
Camera() :
|
Camera() :
|
||||||
type(Perspective), cameraProperties() {
|
type(Perspective),
|
||||||
|
cameraProperties() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
void Read(Value &obj, Asset &r);
|
void Read(Value &obj, Asset &r);
|
||||||
|
@ -1075,7 +1027,22 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Asset(IOSystem *io = 0) :
|
Asset(IOSystem *io = 0) :
|
||||||
mIOSystem(io), asset(), accessors(*this, "accessors"), animations(*this, "animations"), buffers(*this, "buffers"), bufferViews(*this, "bufferViews"), cameras(*this, "cameras"), lights(*this, "lights", "KHR_lights_punctual"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes"), samplers(*this, "samplers"), scenes(*this, "scenes"), skins(*this, "skins"), textures(*this, "textures") {
|
mIOSystem(io),
|
||||||
|
asset(),
|
||||||
|
accessors(*this, "accessors"),
|
||||||
|
animations(*this, "animations"),
|
||||||
|
buffers(*this, "buffers"),
|
||||||
|
bufferViews(*this, "bufferViews"),
|
||||||
|
cameras(*this, "cameras"),
|
||||||
|
lights(*this, "lights", "KHR_lights_punctual"),
|
||||||
|
images(*this, "images"),
|
||||||
|
materials(*this, "materials"),
|
||||||
|
meshes(*this, "meshes"),
|
||||||
|
nodes(*this, "nodes"),
|
||||||
|
samplers(*this, "samplers"),
|
||||||
|
scenes(*this, "scenes"),
|
||||||
|
skins(*this, "skins"),
|
||||||
|
textures(*this, "textures") {
|
||||||
memset(&extensionsUsed, 0, sizeof(extensionsUsed));
|
memset(&extensionsUsed, 0, sizeof(extensionsUsed));
|
||||||
memset(&extensionsRequired, 0, sizeof(extensionsRequired));
|
memset(&extensionsRequired, 0, sizeof(extensionsRequired));
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,10 @@ inline Value *FindObject(Value &val, const char *id) {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline LazyDict<T>::LazyDict(Asset &asset, const char *dictId, const char *extId) :
|
inline LazyDict<T>::LazyDict(Asset &asset, const char *dictId, const char *extId) :
|
||||||
mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset) {
|
mDictId(dictId),
|
||||||
|
mExtId(extId),
|
||||||
|
mDict(0),
|
||||||
|
mAsset(asset) {
|
||||||
asset.mDicts.push_back(this); // register to the list of dictionaries
|
asset.mDicts.push_back(this); // register to the list of dictionaries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +345,10 @@ Ref<T> LazyDict<T>::Create(const char *id) {
|
||||||
//
|
//
|
||||||
|
|
||||||
inline Buffer::Buffer() :
|
inline Buffer::Buffer() :
|
||||||
byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) {}
|
byteLength(0),
|
||||||
|
type(Type_arraybuffer),
|
||||||
|
EncodedRegion_Current(nullptr),
|
||||||
|
mIsSpecial(false) {}
|
||||||
|
|
||||||
inline Buffer::~Buffer() {
|
inline Buffer::~Buffer() {
|
||||||
for (SEncodedRegion *reg : EncodedRegion_List)
|
for (SEncodedRegion *reg : EncodedRegion_List)
|
||||||
|
@ -550,11 +556,130 @@ inline void BufferView::Read(Value &obj, Asset &r) {
|
||||||
byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
inline uint8_t *BufferView::GetPointer(size_t accOffset) {
|
||||||
// struct BufferViewClient
|
if (!buffer) return 0;
|
||||||
//
|
uint8_t *basePtr = buffer->GetPointer();
|
||||||
|
if (!basePtr) return 0;
|
||||||
|
|
||||||
|
size_t offset = accOffset + byteOffset;
|
||||||
|
if (buffer->EncodedRegion_Current != nullptr) {
|
||||||
|
const size_t begin = buffer->EncodedRegion_Current->Offset;
|
||||||
|
const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length;
|
||||||
|
if ((offset >= begin) && (offset < end))
|
||||||
|
return &buffer->EncodedRegion_Current->DecodedData[offset - begin];
|
||||||
|
}
|
||||||
|
|
||||||
|
return basePtr + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct Accessor
|
||||||
|
//
|
||||||
|
inline void Accessor::Sparse::PopulateData(size_t numBytes, uint8_t *bytes) {
|
||||||
|
if (bytes) {
|
||||||
|
data.assign(bytes, bytes + numBytes);
|
||||||
|
} else {
|
||||||
|
data.resize(numBytes, 0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Accessor::Sparse::PatchData(unsigned int elementSize) {
|
||||||
|
uint8_t *pIndices = indices->GetPointer(indicesByteOffset);
|
||||||
|
const unsigned int indexSize = int(ComponentTypeSize(indicesType));
|
||||||
|
uint8_t *indicesEnd = pIndices + count * indexSize;
|
||||||
|
|
||||||
|
uint8_t *pValues = values->GetPointer(valuesByteOffset);
|
||||||
|
while (pIndices != indicesEnd) {
|
||||||
|
size_t offset;
|
||||||
|
switch (indicesType) {
|
||||||
|
case ComponentType_UNSIGNED_BYTE:
|
||||||
|
offset = *pIndices;
|
||||||
|
break;
|
||||||
|
case ComponentType_UNSIGNED_SHORT:
|
||||||
|
offset = *reinterpret_cast<uint16_t *>(pIndices);
|
||||||
|
break;
|
||||||
|
case ComponentType_UNSIGNED_INT:
|
||||||
|
offset = *reinterpret_cast<uint32_t *>(pIndices);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// have fun with float and negative values from signed types as indices.
|
||||||
|
throw DeadlyImportError("Unsupported component type in index.");
|
||||||
|
}
|
||||||
|
|
||||||
|
offset *= elementSize;
|
||||||
|
std::memcpy(data.data() + offset, pValues, elementSize);
|
||||||
|
|
||||||
|
pValues += elementSize;
|
||||||
|
pIndices += indexSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Accessor::Read(Value &obj, Asset &r) {
|
||||||
|
|
||||||
|
if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
|
||||||
|
bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
|
||||||
|
}
|
||||||
|
|
||||||
|
byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0));
|
||||||
|
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
|
||||||
|
count = MemberOrDefault(obj, "count", size_t(0));
|
||||||
|
|
||||||
|
const char *typestr;
|
||||||
|
type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
|
||||||
|
|
||||||
|
if (Value *sparseValue = FindObject(obj, "sparse")) {
|
||||||
|
sparse.reset(new Sparse);
|
||||||
|
// count
|
||||||
|
ReadMember(*sparseValue, "count", sparse->count);
|
||||||
|
|
||||||
|
// indices
|
||||||
|
if (Value *indicesValue = FindObject(*sparseValue, "indices")) {
|
||||||
|
//indices bufferView
|
||||||
|
Value *indiceViewID = FindUInt(*indicesValue, "bufferView");
|
||||||
|
sparse->indices = r.bufferViews.Retrieve(indiceViewID->GetUint());
|
||||||
|
//indices byteOffset
|
||||||
|
sparse->indicesByteOffset = MemberOrDefault(*indicesValue, "byteOffset", size_t(0));
|
||||||
|
//indices componentType
|
||||||
|
sparse->indicesType = MemberOrDefault(*indicesValue, "componentType", ComponentType_BYTE);
|
||||||
|
//sparse->indices->Read(*indicesValue, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// value
|
||||||
|
if (Value *valuesValue = FindObject(*sparseValue, "values")) {
|
||||||
|
//value bufferView
|
||||||
|
Value *valueViewID = FindUInt(*valuesValue, "bufferView");
|
||||||
|
sparse->values = r.bufferViews.Retrieve(valueViewID->GetUint());
|
||||||
|
//value byteOffset
|
||||||
|
sparse->valuesByteOffset = MemberOrDefault(*valuesValue, "byteOffset", size_t(0));
|
||||||
|
//sparse->values->Read(*valuesValue, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// indicesType
|
||||||
|
sparse->indicesType = MemberOrDefault(*sparseValue, "componentType", ComponentType_UNSIGNED_SHORT);
|
||||||
|
|
||||||
|
const unsigned int elementSize = GetElementSize();
|
||||||
|
const size_t dataSize = count * elementSize;
|
||||||
|
sparse->PopulateData(dataSize, bufferView ? bufferView->GetPointer(byteOffset) : 0);
|
||||||
|
sparse->PatchData(elementSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int Accessor::GetNumComponents() {
|
||||||
|
return AttribType::GetNumComponents(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int Accessor::GetBytesPerComponent() {
|
||||||
|
return int(ComponentTypeSize(componentType));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int Accessor::GetElementSize() {
|
||||||
|
return GetNumComponents() * GetBytesPerComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t *Accessor::GetPointer() {
|
||||||
|
if (sparse)
|
||||||
|
return sparse->data.data();
|
||||||
|
|
||||||
inline uint8_t *BufferViewClient::GetPointer() {
|
|
||||||
if (!bufferView || !bufferView->buffer) return 0;
|
if (!bufferView || !bufferView->buffer) return 0;
|
||||||
uint8_t *basePtr = bufferView->buffer->GetPointer();
|
uint8_t *basePtr = bufferView->buffer->GetPointer();
|
||||||
if (!basePtr) return 0;
|
if (!basePtr) return 0;
|
||||||
|
@ -573,76 +698,6 @@ inline uint8_t *BufferViewClient::GetPointer() {
|
||||||
return basePtr + offset;
|
return basePtr + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BufferViewClient::Read(Value &obj, Asset &r) {
|
|
||||||
|
|
||||||
if (Value *bufferViewVal = FindUInt(obj, "bufferView")) {
|
|
||||||
bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
|
|
||||||
}
|
|
||||||
|
|
||||||
byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// struct ComponentTypedBufferViewClient
|
|
||||||
//
|
|
||||||
|
|
||||||
inline unsigned int ComponentTypedBufferViewClient::GetBytesPerComponent() {
|
|
||||||
return int(ComponentTypeSize(componentType));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ComponentTypedBufferViewClient::Read(Value &obj, Asset &r) {
|
|
||||||
|
|
||||||
BufferViewClient::Read(obj, r);
|
|
||||||
|
|
||||||
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// struct Accessor
|
|
||||||
//
|
|
||||||
|
|
||||||
inline uint8_t *Accessor::GetPointer() {
|
|
||||||
if (!sparse) return BufferViewClient::GetPointer();
|
|
||||||
|
|
||||||
return sparse->data.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Accessor::Read(Value &obj, Asset &r) {
|
|
||||||
|
|
||||||
ComponentTypedBufferViewClient::Read(obj, r);
|
|
||||||
|
|
||||||
count = MemberOrDefault(obj, "count", size_t(0));
|
|
||||||
|
|
||||||
const char *typestr;
|
|
||||||
type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
|
|
||||||
|
|
||||||
if (Value *sparseValue = FindObject(obj, "sparse")) {
|
|
||||||
sparse.reset(new Sparse);
|
|
||||||
ReadMember(*sparseValue, "count", sparse->count);
|
|
||||||
|
|
||||||
if (Value *indicesValue = FindObject(*sparseValue, "indices")) {
|
|
||||||
sparse->indices.Read(*indicesValue, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Value *valuesValue = FindObject(*sparseValue, "values")) {
|
|
||||||
sparse->values.Read(*valuesValue, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int elementSize = GetElementSize();
|
|
||||||
const size_t dataSize = count * elementSize;
|
|
||||||
sparse->PopulateData(dataSize, BufferViewClient::GetPointer());
|
|
||||||
sparse->PatchData(elementSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int Accessor::GetNumComponents() {
|
|
||||||
return AttribType::GetNumComponents(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int Accessor::GetElementSize() {
|
|
||||||
return GetNumComponents() * GetBytesPerComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
inline void CopyData(size_t count,
|
inline void CopyData(size_t count,
|
||||||
const uint8_t *src, size_t src_stride,
|
const uint8_t *src, size_t src_stride,
|
||||||
|
@ -663,10 +718,9 @@ inline void CopyData(size_t count,
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
void Accessor::ExtractData(T *&outData)
|
void Accessor::ExtractData(T *&outData) {
|
||||||
{
|
uint8_t *data = GetPointer();
|
||||||
uint8_t* data = GetPointer();
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
throw DeadlyImportError("GLTF: data is NULL");
|
throw DeadlyImportError("GLTF: data is NULL");
|
||||||
}
|
}
|
||||||
|
@ -678,7 +732,6 @@ void Accessor::ExtractData(T *&outData)
|
||||||
|
|
||||||
const size_t targetElemSize = sizeof(T);
|
const size_t targetElemSize = sizeof(T);
|
||||||
ai_assert(elemSize <= targetElemSize);
|
ai_assert(elemSize <= targetElemSize);
|
||||||
|
|
||||||
ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size()));
|
ai_assert(count * stride <= (bufferView ? bufferView->byteLength : sparse->data.size()));
|
||||||
|
|
||||||
outData = new T[count];
|
outData = new T[count];
|
||||||
|
@ -705,7 +758,10 @@ inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t sr
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Accessor::Indexer::Indexer(Accessor &acc) :
|
inline Accessor::Indexer::Indexer(Accessor &acc) :
|
||||||
accessor(acc), data(acc.GetPointer()), elemSize(acc.GetElementSize()), stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) {
|
accessor(acc),
|
||||||
|
data(acc.GetPointer()),
|
||||||
|
elemSize(acc.GetElementSize()),
|
||||||
|
stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Accesses the i-th value as defined by the accessor
|
//! Accesses the i-th value as defined by the accessor
|
||||||
|
@ -720,7 +776,9 @@ T Accessor::Indexer::GetValue(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Image::Image() :
|
inline Image::Image() :
|
||||||
width(0), height(0), mDataLength(0) {
|
width(0),
|
||||||
|
height(0),
|
||||||
|
mDataLength(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Image::Read(Value &obj, Asset &r) {
|
inline void Image::Read(Value &obj, Asset &r) {
|
||||||
|
@ -958,8 +1016,8 @@ inline int Compare(const char *attr, const char (&str)[N]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# pragma warning(push)
|
#pragma warning(push)
|
||||||
# pragma warning(disable : 4706)
|
#pragma warning(disable : 4706)
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) {
|
inline bool GetAttribVector(Mesh::Primitive &p, const char *attr, Mesh::AccessorList *&v, int &pos) {
|
||||||
|
@ -1079,11 +1137,11 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *extras = FindObject(pJSON_Object, "extras");
|
Value *extras = FindObject(pJSON_Object, "extras");
|
||||||
if (nullptr != extras ) {
|
if (nullptr != extras) {
|
||||||
if (Value* curTargetNames = FindArray(*extras, "targetNames")) {
|
if (Value *curTargetNames = FindArray(*extras, "targetNames")) {
|
||||||
this->targetNames.resize(curTargetNames->Size());
|
this->targetNames.resize(curTargetNames->Size());
|
||||||
for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
|
for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
|
||||||
Value& targetNameValue = (*curTargetNames)[i];
|
Value &targetNameValue = (*curTargetNames)[i];
|
||||||
if (targetNameValue.IsString()) {
|
if (targetNameValue.IsString()) {
|
||||||
this->targetNames[i] = targetNameValue.GetString();
|
this->targetNames[i] = targetNameValue.GetString();
|
||||||
}
|
}
|
||||||
|
@ -1188,8 +1246,6 @@ inline void Node::Read(Value &obj, Asset &r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not retrieve a skin here, just take a reference, to avoid infinite recursion
|
|
||||||
// Skins will be properly loaded later
|
|
||||||
Value *curSkin = FindUInt(obj, "skin");
|
Value *curSkin = FindUInt(obj, "skin");
|
||||||
if (nullptr != curSkin) {
|
if (nullptr != curSkin) {
|
||||||
this->skin = r.skins.Get(curSkin->GetUint());
|
this->skin = r.skins.Get(curSkin->GetUint());
|
||||||
|
@ -1597,7 +1653,7 @@ inline std::string Asset::FindUniqueID(const std::string &str, const char *suffi
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
} // namespace glTF2
|
} // namespace glTF2
|
||||||
|
|
Loading…
Reference in New Issue