Fix glTF Accessor min and max values
parent
2d2889f73f
commit
91e6d3abeb
|
@ -362,8 +362,8 @@ namespace glTF
|
|||
ComponentType componentType; //!< The datatype of components in the attribute. (required)
|
||||
unsigned int count; //!< The number of attributes referenced by this accessor. (required)
|
||||
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
|
||||
std::vector<float> max; //!< Maximum value of each component in this attribute.
|
||||
std::vector<float> min; //!< Minimum 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.
|
||||
|
||||
unsigned int GetNumComponents();
|
||||
unsigned int GetBytesPerComponent();
|
||||
|
|
|
@ -54,9 +54,9 @@ namespace glTF {
|
|||
|
||||
namespace {
|
||||
|
||||
template<size_t N>
|
||||
template<typename T, size_t N>
|
||||
inline
|
||||
Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
|
||||
Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(N, al);
|
||||
for (decltype(N) i = 0; i < N; ++i) {
|
||||
|
@ -65,8 +65,9 @@ namespace glTF {
|
|||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
|
||||
Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
|
||||
for (unsigned int i = 0; i < r.size(); ++i) {
|
||||
|
@ -75,6 +76,16 @@ namespace glTF {
|
|||
return val;
|
||||
}
|
||||
|
||||
template<typename C, typename T>
|
||||
inline Value& MakeValueCast(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
|
||||
for (unsigned int i = 0; i < r.size(); ++i) {
|
||||
val.PushBack(static_cast<C>(r[i]), al);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
|
||||
if (v.empty()) return;
|
||||
|
@ -100,8 +111,13 @@ namespace glTF {
|
|||
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
|
||||
|
||||
Value vTmpMax, vTmpMin;
|
||||
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
if (a.componentType == ComponentType_FLOAT) {
|
||||
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
} else {
|
||||
obj.AddMember("max", MakeValueCast<int64_t>(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValueCast<int64_t>(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Write(Value& obj, Animation& a, AssetWriter& w)
|
||||
|
|
|
@ -173,6 +173,62 @@ static void IdentityMatrix4(glTF::mat4& o)
|
|||
o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SetAccessorRange(Ref<Accessor> acc, void* data, unsigned int count,
|
||||
unsigned int numCompsIn, unsigned int numCompsOut)
|
||||
{
|
||||
ai_assert(numCompsOut <= numCompsIn);
|
||||
|
||||
// Allocate and initialize with large values.
|
||||
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
|
||||
acc->min.push_back(DBL_MAX);
|
||||
acc->max.push_back(DBL_MIN);
|
||||
}
|
||||
|
||||
size_t totalComps = count * numCompsIn;
|
||||
T* buffer_ptr = static_cast<T*>(data);
|
||||
T* buffer_end = buffer_ptr + totalComps;
|
||||
|
||||
// Search and set extreme values.
|
||||
for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) {
|
||||
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
|
||||
double valueTmp = buffer_ptr[j];
|
||||
|
||||
if (valueTmp < acc->min[j]) {
|
||||
acc->min[j] = valueTmp;
|
||||
}
|
||||
if (valueTmp > acc->max[j]) {
|
||||
acc->max[j] = valueTmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* data,
|
||||
unsigned int count, unsigned int numCompsIn, unsigned int numCompsOut)
|
||||
{
|
||||
switch (compType) {
|
||||
case ComponentType_SHORT:
|
||||
SetAccessorRange<short>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_SHORT:
|
||||
SetAccessorRange<unsigned short>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_INT:
|
||||
SetAccessorRange<unsigned int>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_FLOAT:
|
||||
SetAccessorRange<float>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_BYTE:
|
||||
SetAccessorRange<int8_t>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_BYTE:
|
||||
SetAccessorRange<uint8_t>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
|
||||
unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
|
||||
{
|
||||
|
@ -206,33 +262,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
|
|||
acc->type = typeOut;
|
||||
|
||||
// calculate min and max values
|
||||
{
|
||||
// Allocate and initialize with large values.
|
||||
float float_MAX = 10000000000000.0f;
|
||||
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
|
||||
acc->min.push_back( float_MAX);
|
||||
acc->max.push_back(-float_MAX);
|
||||
}
|
||||
|
||||
// Search and set extreme values.
|
||||
float valueTmp;
|
||||
for (unsigned int i = 0 ; i < count ; i++) {
|
||||
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
|
||||
if (numCompsOut == 1) {
|
||||
valueTmp = static_cast<unsigned short*>(data)[i];
|
||||
} else {
|
||||
valueTmp = static_cast<aiVector3D*>(data)[i][j];
|
||||
}
|
||||
|
||||
if (valueTmp < acc->min[j]) {
|
||||
acc->min[j] = valueTmp;
|
||||
}
|
||||
if (valueTmp > acc->max[j]) {
|
||||
acc->max[j] = valueTmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut);
|
||||
|
||||
// copy the data
|
||||
acc->WriteData(count, data, numCompsIn*bytesPerComp);
|
||||
|
|
|
@ -387,8 +387,8 @@ namespace glTF2
|
|||
ComponentType componentType; //!< The datatype of components in the attribute. (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)
|
||||
std::vector<float> max; //!< Maximum value of each component in this attribute.
|
||||
std::vector<float> min; //!< Minimum 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.
|
||||
|
||||
unsigned int GetNumComponents();
|
||||
unsigned int GetBytesPerComponent();
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace glTF2 {
|
|||
|
||||
namespace {
|
||||
|
||||
template<size_t N>
|
||||
inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
|
||||
template<typename T, size_t N>
|
||||
inline Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(N, al);
|
||||
for (decltype(N) i = 0; i < N; ++i) {
|
||||
|
@ -64,7 +64,8 @@ namespace glTF2 {
|
|||
return val;
|
||||
}
|
||||
|
||||
inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
|
||||
template<typename T>
|
||||
inline Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
|
||||
for (unsigned int i = 0; i < r.size(); ++i) {
|
||||
|
@ -73,8 +74,19 @@ namespace glTF2 {
|
|||
return val;
|
||||
}
|
||||
|
||||
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) {
|
||||
val.SetDouble(r);
|
||||
template<typename C, typename T>
|
||||
inline Value& MakeValueCast(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
|
||||
val.SetArray();
|
||||
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
|
||||
for (unsigned int i = 0; i < r.size(); ++i) {
|
||||
val.PushBack(static_cast<C>(r[i]), al);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Value& MakeValue(Value& val, T r, MemoryPoolAllocator<>& /*al*/) {
|
||||
val.Set(r);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -104,8 +116,13 @@ namespace glTF2 {
|
|||
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
|
||||
|
||||
Value vTmpMax, vTmpMin;
|
||||
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
if (a.componentType == ComponentType_FLOAT) {
|
||||
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
} else {
|
||||
obj.AddMember("max", MakeValueCast<int64_t>(vTmpMax, a.max, w.mAl), w.mAl);
|
||||
obj.AddMember("min", MakeValueCast<int64_t>(vTmpMin, a.min, w.mAl), w.mAl);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Write(Value& obj, Animation& a, AssetWriter& w)
|
||||
|
|
|
@ -152,6 +152,62 @@ static void IdentityMatrix4(mat4& o) {
|
|||
o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SetAccessorRange(Ref<Accessor> acc, void* data, size_t count,
|
||||
unsigned int numCompsIn, unsigned int numCompsOut)
|
||||
{
|
||||
ai_assert(numCompsOut <= numCompsIn);
|
||||
|
||||
// Allocate and initialize with large values.
|
||||
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
|
||||
acc->min.push_back(DBL_MAX);
|
||||
acc->max.push_back(DBL_MIN);
|
||||
}
|
||||
|
||||
size_t totalComps = count * numCompsIn;
|
||||
T* buffer_ptr = static_cast<T*>(data);
|
||||
T* buffer_end = buffer_ptr + totalComps;
|
||||
|
||||
// Search and set extreme values.
|
||||
for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) {
|
||||
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
|
||||
double valueTmp = buffer_ptr[j];
|
||||
|
||||
if (valueTmp < acc->min[j]) {
|
||||
acc->min[j] = valueTmp;
|
||||
}
|
||||
if (valueTmp > acc->max[j]) {
|
||||
acc->max[j] = valueTmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* data,
|
||||
size_t count, unsigned int numCompsIn, unsigned int numCompsOut)
|
||||
{
|
||||
switch (compType) {
|
||||
case ComponentType_SHORT:
|
||||
SetAccessorRange<short>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_SHORT:
|
||||
SetAccessorRange<unsigned short>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_INT:
|
||||
SetAccessorRange<unsigned int>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_FLOAT:
|
||||
SetAccessorRange<float>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_BYTE:
|
||||
SetAccessorRange<int8_t>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
case ComponentType_UNSIGNED_BYTE:
|
||||
SetAccessorRange<uint8_t>(acc, data, count, numCompsIn, numCompsOut);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
|
||||
size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
|
||||
{
|
||||
|
@ -187,33 +243,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
|
|||
acc->type = typeOut;
|
||||
|
||||
// calculate min and max values
|
||||
{
|
||||
// Allocate and initialize with large values.
|
||||
float float_MAX = 10000000000000.0f;
|
||||
for (unsigned int i = 0 ; i < numCompsOut ; i++) {
|
||||
acc->min.push_back( float_MAX);
|
||||
acc->max.push_back(-float_MAX);
|
||||
}
|
||||
|
||||
// Search and set extreme values.
|
||||
float valueTmp;
|
||||
for (unsigned int i = 0 ; i < count ; i++) {
|
||||
for (unsigned int j = 0 ; j < numCompsOut ; j++) {
|
||||
if (numCompsOut == 1) {
|
||||
valueTmp = static_cast<unsigned short*>(data)[i];
|
||||
} else {
|
||||
valueTmp = static_cast<aiVector3D*>(data)[i][j];
|
||||
}
|
||||
|
||||
if (valueTmp < acc->min[j]) {
|
||||
acc->min[j] = valueTmp;
|
||||
}
|
||||
if (valueTmp > acc->max[j]) {
|
||||
acc->max[j] = valueTmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut);
|
||||
|
||||
// copy the data
|
||||
acc->WriteData(count, data, numCompsIn*bytesPerComp);
|
||||
|
|
Loading…
Reference in New Issue