Merge pull request #1015 from ascandal/feature/fix-glTF-validator-errors

Fix glTF validator errors
pull/1019/head
Kim Kulling 2016-10-04 23:10:30 +02:00 committed by GitHub
commit f94b7287fc
6 changed files with 203 additions and 23 deletions

16
CHANGES
View File

@ -2,6 +2,22 @@
CHANGELOG
----------------------------------------------------------------------
3.2.1 (2016-10-01)
FEATURES:
- Updated glTF exporter to meet 1.0 specification.
FIXES/HOUSEKEEPING:
- Fixed glTF Validator errors for exported glTF format.
ISSUES:
- Hard coded sampler setting for
- magFilter
- minFilter
- void* in ExportData for accessor max and min.
3.2.0 (2015-11-03)
FEATURES:

View File

@ -236,6 +236,32 @@ namespace glTF
BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
};
//! Values for the Sampler::magFilter field
enum SamplerMagFilter
{
SamplerMagFilter_Nearest = 9728,
SamplerMagFilter_Linear = 9729
};
//! Values for the Sampler::minFilter field
enum SamplerMinFilter
{
SamplerMinFilter_Nearest = 9728,
SamplerMinFilter_Linear = 9729,
SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
SamplerMinFilter_Linear_Mipmap_Linear = 9987
};
//! Values for the Sampler::wrapS and Sampler::wrapT field
enum SamplerWrap
{
SamplerWrap_Clamp_To_Edge = 33071,
SamplerWrap_Mirrored_Repeat = 33648,
SamplerWrap_Repeat = 10497
};
//! Values for the Texture::format and Texture::internalFormat fields
enum TextureFormat
{
@ -377,8 +403,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<float> max; //!< Maximum value of each component in this attribute.
std::vector<float> min; //!< Minimum value of each component in this attribute.
unsigned int GetNumComponents();
unsigned int GetBytesPerComponent();
@ -812,8 +838,14 @@ namespace glTF
struct Sampler : public Object
{
SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
SamplerMinFilter minFilter; //!< The texture minification filter. (required)
SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
Sampler() {}
void Read(Value& obj, Asset& r);
void SetDefaults();
};
struct Scene : public Object
@ -860,8 +892,8 @@ namespace glTF
//! A texture and its sampler.
struct Texture : public Object
{
//Ref<Sampler> source; //!< The ID of the sampler used by this texture. (required)
Ref<Image> source; //!< The ID of the image used by this texture. (required)
Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
Ref<Image> source; //!< The ID of the image used by this texture. (required)
//TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
//TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
@ -921,7 +953,7 @@ namespace glTF
//! (Implemented in glTFAssetWriter.h)
template<class T>
void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
//! It is the owner the loaded objects, so when it is destroyed it also deletes them
@ -983,7 +1015,7 @@ namespace glTF
int version; //!< The glTF format version (should be 1)
void Read(Document& doc);
AssetMetadata()
: premultipliedAlpha(false)
, version(0)
@ -1049,7 +1081,7 @@ namespace glTF
LazyDict<Mesh> meshes;
LazyDict<Node> nodes;
//LazyDict<Program> programs;
//LazyDict<Sampler> samplers;
LazyDict<Sampler> samplers;
LazyDict<Scene> scenes;
//LazyDict<Shader> shaders;
//LazyDict<Skin> skins;
@ -1074,7 +1106,7 @@ namespace glTF
, meshes (*this, "meshes")
, nodes (*this, "nodes")
//, programs (*this, "programs")
//, samplers (*this, "samplers")
, samplers (*this, "samplers")
, scenes (*this, "scenes")
//, shaders (*this, "shaders")
//, skins (*this, "skins")

View File

@ -53,7 +53,7 @@ using namespace Assimp;
namespace glTF {
namespace {
//
// JSON Value reading helpers
//
@ -62,7 +62,7 @@ namespace {
struct ReadHelper { static bool Read(Value& val, T& out) {
return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
}};
template<> struct ReadHelper<bool> { static bool Read(Value& val, bool& out) {
return val.IsBool() ? out = val.GetBool(), true : false;
}};
@ -70,7 +70,7 @@ namespace {
template<> struct ReadHelper<float> { static bool Read(Value& val, float& out) {
return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
}};
template<unsigned int N> struct ReadHelper<float[N]> { static bool Read(Value& val, float (&out)[N]) {
if (!val.IsArray() || val.Size() != N) return false;
for (unsigned int i = 0; i < N; ++i) {
@ -312,7 +312,7 @@ inline void Buffer::Read(Value& obj, Asset& r)
if (file) {
bool ok = LoadFromStream(*file, byteLength);
delete file;
if (!ok)
throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" );
}
@ -439,7 +439,7 @@ inline void BufferView::Read(Value& obj, Asset& r)
if (bufferId) {
buffer = r.buffers.Get(bufferId);
}
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
byteLength = MemberOrDefault(obj, "byteLength", 0u);
}
@ -599,7 +599,7 @@ inline Image::Image()
inline void Image::Read(Value& obj, Asset& r)
{
// Check for extensions first (to detect binary embedded data)
// Check for extensions first (to detect binary embedded data)
if (Value* extensions = FindObject(obj, "extensions")) {
if (r.extensionsUsed.KHR_binary_glTF) {
if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
@ -665,12 +665,35 @@ inline void Image::SetData(uint8_t* data, size_t length, Asset& r)
}
}
inline void Sampler::Read(Value& obj, Asset& r)
{
SetDefaults();
ReadMember(obj, "magFilter", magFilter);
ReadMember(obj, "minFilter", minFilter);
ReadMember(obj, "wrapS", wrapS);
ReadMember(obj, "wrapT", wrapT);
}
inline void Sampler::SetDefaults()
{
magFilter = SamplerMagFilter_Linear;
minFilter = SamplerMinFilter_Linear;
wrapS = SamplerWrap_Repeat;
wrapT = SamplerWrap_Repeat;
}
inline void Texture::Read(Value& obj, Asset& r)
{
const char* sourcestr;
if (ReadMember(obj, "source", sourcestr)) {
source = r.images.Get(sourcestr);
}
const char* samplerstr;
if (ReadMember(obj, "sampler", samplerstr)) {
sampler = r.samplers.Get(samplerstr);
}
}
namespace {
@ -1132,7 +1155,7 @@ inline void Node::Read(Value& obj, Asset& r)
}
}
if (Value* matrix = FindArray(obj, "matrix")) {
ReadValue(*matrix, this->matrix);
}
@ -1408,13 +1431,13 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
id = buffer;
it = mUsedIds.find(id);
}
return id;
}
namespace Util {
inline
inline
bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
if ( NULL == const_uri ) {
return false;

View File

@ -56,7 +56,16 @@ namespace glTF {
inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(N, al);
for (decltype(N) i = 0; i < N; ++i) {
for (decltype(N) i = 0; i < N; ++i) {
val.PushBack(r[i], al);
}
return val;
}
inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(r.size(), al);
for (int i = 0; i < r.size(); ++i) {
val.PushBack(r[i], al);
}
return val;
@ -85,6 +94,10 @@ namespace glTF {
obj.AddMember("componentType", int(a.componentType), w.mAl);
obj.AddMember("count", a.count, w.mAl);
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);
}
inline void Write(Value& obj, Animation& a, AssetWriter& w)
@ -285,7 +298,7 @@ namespace glTF {
}
primitives.PushBack(prim, w.mAl);
}
obj.AddMember("primitives", primitives, w.mAl);
}
@ -323,7 +336,18 @@ namespace glTF {
inline void Write(Value& obj, Sampler& b, AssetWriter& w)
{
if (b.wrapS) {
obj.AddMember("wrapS", b.wrapS, w.mAl);
}
if (b.wrapT) {
obj.AddMember("wrapT", b.wrapT, w.mAl);
}
if (b.magFilter) {
obj.AddMember("magFilter", b.magFilter, w.mAl);
}
if (b.minFilter) {
obj.AddMember("minFilter", b.minFilter, w.mAl);
}
}
inline void Write(Value& scene, Scene& s, AssetWriter& w)
@ -351,6 +375,9 @@ namespace glTF {
if (tex.source) {
obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl);
}
if (tex.sampler) {
obj.AddMember("sampler", Value(tex.sampler->id, w.mAl).Move(), w.mAl);
}
}
inline void Write(Value& obj, Light& b, AssetWriter& w)
@ -487,13 +514,15 @@ namespace glTF {
}
}
inline void AssetWriter::WriteMetadata()
{
Value asset;
asset.SetObject();
{
asset.AddMember("version", mAsset.asset.version, mAl);
char versionChar[10];
ai_snprintf(versionChar, sizeof(versionChar), "%d", mAsset.asset.version);
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
}

View File

@ -193,6 +193,36 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
acc->count = count;
acc->type = typeOut;
// calculate min and max values
{
// Allocate and initialize with large values.
float float_MAX = 10000000000000;
for (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 (int i = 0 ; i < count ; i++) {
for (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;
}
}
}
}
// copy the data
acc->WriteData(count, data, numCompsIn*bytesPerComp);
@ -205,6 +235,52 @@ namespace {
}
}
void glTFExporter::GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop)
{
std::string samplerId = mAsset->FindUniqueID("", "sampler");
prop.texture->sampler = mAsset->samplers.Create(samplerId);
aiTextureMapMode mapU, mapV;
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
switch (mapU) {
case aiTextureMapMode_Wrap:
prop.texture->sampler->wrapS = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
prop.texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
prop.texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
prop.texture->sampler->wrapS = SamplerWrap_Repeat;
break;
};
switch (mapV) {
case aiTextureMapMode_Wrap:
prop.texture->sampler->wrapT = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
prop.texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
prop.texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
prop.texture->sampler->wrapT = SamplerWrap_Repeat;
break;
};
// Hard coded Texture filtering options because I do not know where to find them in the aiMaterial.
prop.texture->sampler->magFilter = SamplerMagFilter_Linear;
prop.texture->sampler->minFilter = SamplerMinFilter_Linear;
}
void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
{
aiString tex;
@ -244,6 +320,8 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
else {
prop.texture->source->uri = path;
}
GetTexSampler(mat, prop);
}
}
}
@ -254,6 +332,7 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
}
}
void glTFExporter::ExportMaterials()
{
aiString aiName;
@ -369,7 +448,7 @@ void glTFExporter::ExportMeshes()
if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, true);
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
if (tc) p.attributes.texcoord.push_back(tc);
}
}

View File

@ -94,6 +94,7 @@ namespace Assimp
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop);
void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
void ExportMetadata();
void ExportMaterials();