Merge branch 'master' into fix/obj_with_bspline_crash

pull/4403/head
Jaroslav Pribyl 2022-02-26 04:03:59 +01:00 committed by GitHub
commit 62930076af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 230 additions and 242 deletions

View File

@ -1267,7 +1267,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
const std::vector<aiVector3D> &normals = mesh.GetNormals(); const std::vector<aiVector3D> &normals = mesh.GetNormals();
if (normals.size()) { if (normals.size()) {
ai_assert(normals.size() == vertices.size()); ai_assert(normals.size() == vertices.size());
out_mesh->mNormals = new aiVector3D[vertices.size()]; out_mesh->mNormals = new aiVector3D[count_vertices];
} }
// allocate tangents, binormals. // allocate tangents, binormals.
@ -1295,8 +1295,8 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
ai_assert(tangents.size() == vertices.size()); ai_assert(tangents.size() == vertices.size());
ai_assert(binormals->size() == vertices.size()); ai_assert(binormals->size() == vertices.size());
out_mesh->mTangents = new aiVector3D[vertices.size()]; out_mesh->mTangents = new aiVector3D[count_vertices];
out_mesh->mBitangents = new aiVector3D[vertices.size()]; out_mesh->mBitangents = new aiVector3D[count_vertices];
} }
} }
@ -1308,7 +1308,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
break; break;
} }
out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; out_mesh->mTextureCoords[i] = new aiVector3D[count_vertices];
out_mesh->mNumUVComponents[i] = 2; out_mesh->mNumUVComponents[i] = 2;
} }
@ -1320,7 +1320,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
break; break;
} }
out_mesh->mColors[i] = new aiColor4D[vertices.size()]; out_mesh->mColors[i] = new aiColor4D[count_vertices];
} }
unsigned int cursor = 0, in_cursor = 0; unsigned int cursor = 0, in_cursor = 0;

View File

@ -605,6 +605,9 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
mat->AddProperty<int>(&sm, 1, AI_MATKEY_SHADING_MODEL); mat->AddProperty<int>(&sm, 1, AI_MATKEY_SHADING_MODEL);
// Preserve the original illum value
mat->AddProperty<int>(&pCurrentMaterial->illumination_model, 1, AI_MATKEY_OBJ_ILLUM);
// Adding material colors // Adding material colors
mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT); mat->AddProperty(&pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty(&pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);

View File

@ -260,20 +260,9 @@ public:
VEC4, VEC4,
MAT2, MAT2,
MAT3, MAT3,
MAT4 }; MAT4
private:
static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
struct Info {
const char *name;
unsigned int numComponents;
}; };
template <int N>
struct data { static const Info infos[NUM_VALUES]; };
public:
inline static Value FromString(const char *str) { inline static Value FromString(const char *str) {
for (size_t i = 0; i < NUM_VALUES; ++i) { for (size_t i = 0; i < NUM_VALUES; ++i) {
if (strcmp(data<0>::infos[i].name, str) == 0) { if (strcmp(data<0>::infos[i].name, str) == 0) {
@ -290,40 +279,31 @@ public:
inline static unsigned int GetNumComponents(Value type) { inline static unsigned int GetNumComponents(Value type) {
return data<0>::infos[static_cast<size_t>(type)].numComponents; return data<0>::infos[static_cast<size_t>(type)].numComponents;
} }
private:
static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
struct Info {
const char *name;
unsigned int numComponents;
};
template <int N>
struct data {
static const Info infos[NUM_VALUES];
};
}; };
// must match the order of the AttribTypeTraits::Value enum! // must match the order of the AttribTypeTraits::Value enum!
template <int N> template <int N>
const AttribType::Info const AttribType::Info AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
AttribType::data<N>::infos[AttribType::NUM_VALUES] = { { "SCALAR", 1 },
{ "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 } { "VEC2", 2 },
}; { "VEC3", 3 },
{ "VEC4", 4 },
/* { "MAT2", 4 },
//! A reference to one top-level object, which is valid { "MAT3", 9 },
//! until the Asset instance is destroyed { "MAT4", 16 }
template<class T> };
class Ref
{
std::vector<T*>* vector;
unsigned int index;
public:
Ref() : vector(0), index(0) {}
Ref(std::vector<T*>& vec, unsigned int idx) : vector(&vec), index(idx) {}
inline unsigned int GetIndex() const
{ return index; }
operator bool() const
{ return vector != 0; }
T* operator->()
{ return (*vector)[index]; }
T& operator*()
{ return *((*vector)[index]); }
};*/
//! Base class for all glTF top-level objects //! Base class for all glTF top-level objects
struct Object { struct Object {
@ -333,6 +313,7 @@ struct Object {
//! Objects marked as special are not exported (used to emulate the binary body buffer) //! Objects marked as special are not exported (used to emulate the binary body buffer)
virtual bool IsSpecial() const { return false; } virtual bool IsSpecial() const { return false; }
Object() = default;
virtual ~Object() {} virtual ~Object() {}
//! Maps special IDs to another ID, where needed. Subclasses may override it (statically) //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
@ -401,21 +382,19 @@ struct Accessor : public Object {
return Indexer(*this); return Indexer(*this);
} }
Accessor() {} Accessor() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
//! A buffer points to binary geometry, animation, or skins. //! A buffer points to binary geometry, animation, or skins.
struct Buffer : public Object { struct Buffer : public Object {
/********************* Types *********************/ /********************* Types *********************/
public:
enum Type { enum Type {
Type_arraybuffer, Type_arraybuffer,
Type_text Type_text
}; };
/// \struct SEncodedRegion /// @brief Descriptor of encoded region in "bufferView".
/// Descriptor of encoded region in "bufferView".
struct SEncodedRegion { struct SEncodedRegion {
const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes. const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
const size_t EncodedData_Length; ///< Size of encoded region, in bytes. const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
@ -423,8 +402,7 @@ public:
const size_t DecodedData_Length; ///< Size of decoded region, in bytes. const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
const std::string ID; ///< ID of the region. const std::string ID; ///< ID of the region.
/// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID) /// @brief Constructor.
/// Constructor.
/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes. /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
/// \param [in] pEncodedData_Length - size of encoded region, in bytes. /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
/// \param [in] pDecodedData - pointer to decoded data array. /// \param [in] pDecodedData - pointer to decoded data array.
@ -433,16 +411,13 @@ public:
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()
/// Destructor. /// Destructor.
~SEncodedRegion() { delete[] DecodedData; } ~SEncodedRegion() { delete[] DecodedData; }
}; };
/******************* Variables *******************/ /******************* Variables *******************/
//std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
size_t byteLength; //!< The length of the buffer in bytes. (default: 0) size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
//std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
Type type; Type type;
@ -486,7 +461,6 @@ public:
bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0); bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
/// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
/// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data. /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes. /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
/// \param [in] pEncodedData_Length - size of encoded region, in bytes. /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
@ -495,12 +469,10 @@ public:
/// \param [in] pID - ID of the region. /// \param [in] pID - ID of the region.
void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID); void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
/// \fn void EncodedRegion_SetCurrent(const std::string& pID)
/// Select current encoded region by ID. \sa EncodedRegion_Current. /// Select current encoded region by ID. \sa EncodedRegion_Current.
/// \param [in] pID - ID of the region. /// \param [in] pID - ID of the region.
void EncodedRegion_SetCurrent(const std::string &pID); void EncodedRegion_SetCurrent(const std::string &pID);
/// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
/// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions. /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
/// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed. /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
/// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced. /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
@ -558,37 +530,29 @@ struct Camera : public Object {
} ortographic; } ortographic;
}; };
Camera() {} Camera() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
//! Image data used to create a texture. //! Image data used to create a texture.
struct Image : public Object { struct Image : public Object {
std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required) std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
Ref<BufferView> bufferView; Ref<BufferView> bufferView;
std::string mimeType; std::string mimeType;
int width, height; int width, height;
private:
std::unique_ptr<uint8_t[]> mData;
size_t mDataLength;
public: public:
Image(); Image();
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
inline bool HasData() const { return mDataLength > 0; } inline bool HasData() const { return mDataLength > 0; }
inline size_t GetDataLength() const { return mDataLength; } inline size_t GetDataLength() const { return mDataLength; }
inline const uint8_t *GetData() const { return mData.get(); } inline const uint8_t *GetData() const { return mData.get(); }
inline uint8_t *StealData(); inline uint8_t *StealData();
inline void SetData(uint8_t *data, size_t length, Asset &r); inline void SetData(uint8_t *data, size_t length, Asset &r);
private:
std::unique_ptr<uint8_t[]> mData;
size_t mDataLength;
}; };
//! Holds a material property that can be a texture or a color //! Holds a material property that can be a texture or a color
@ -671,6 +635,7 @@ struct Mesh : public Object {
}; };
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \struct SCompression_Open3DGC /// \struct SCompression_Open3DGC
/// Compression of mesh data using Open3DGC algorithm. /// Compression of mesh data using Open3DGC algorithm.
struct SCompression_Open3DGC : public SExtension { struct SCompression_Open3DGC : public SExtension {
@ -703,7 +668,6 @@ struct Mesh : public Object {
Mesh() {} Mesh() {}
/// \fn ~Mesh()
/// Destructor. /// Destructor.
~Mesh() { ~Mesh() {
for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) {
@ -711,15 +675,13 @@ struct Mesh : public Object {
}; };
} }
/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) /// @brief Get mesh data from JSON-object and place them to root asset.
/// Get mesh data from JSON-object and place them to root asset.
/// \param [in] pJSON_Object - reference to pJSON-object from which data are read. /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
/// \param [out] pAsset_Root - reference to root asset where data will be stored. /// \param [out] pAsset_Root - reference to root asset where data will be stored.
void Read(Value &pJSON_Object, Asset &pAsset_Root); void Read(Value &pJSON_Object, Asset &pAsset_Root);
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root) /// @brief Decode part of "buffer" which encoded with Open3DGC algorithm.
/// Decode part of "buffer" which encoded with Open3DGC algorithm.
/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region. /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
/// \param [out] pAsset_Root - reference to root assed where data will be stored. /// \param [out] pAsset_Root - reference to root assed where data will be stored.
void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root); void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root);
@ -759,7 +721,7 @@ struct Sampler : public Object {
SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required) SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
Sampler() {} Sampler() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
void SetDefaults(); void SetDefaults();
}; };
@ -767,12 +729,12 @@ struct Sampler : public Object {
struct Scene : public Object { struct Scene : public Object {
std::vector<Ref<Node>> nodes; std::vector<Ref<Node>> nodes;
Scene() {} Scene() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
struct Shader : public Object { struct Shader : public Object {
Shader() {} Shader() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -782,7 +744,7 @@ struct Skin : public Object {
std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin. std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
std::string name; //!< The user-defined name of this object. std::string name; //!< The user-defined name of this object.
Skin() {} Skin() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -796,7 +758,7 @@ struct Technique : public Object {
struct Functions { struct Functions {
}; };
Technique() {} Technique() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -805,13 +767,7 @@ struct Texture : public Object {
Ref<Sampler> sampler; //!< The ID of the sampler 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) Ref<Image> source; //!< The ID of the image used by this texture. (required)
//TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA) Texture() = default;
//TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
//TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
//TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
Texture() {}
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -826,7 +782,6 @@ struct Light : public Object {
}; };
Type type; Type type;
vec4 color; vec4 color;
float distance; float distance;
float constantAttenuation; float constantAttenuation;
@ -835,9 +790,8 @@ struct Light : public Object {
float falloffAngle; float falloffAngle;
float falloffExponent; float falloffExponent;
Light() {} Light() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
void SetDefaults(); void SetDefaults();
}; };
@ -865,15 +819,11 @@ struct Animation : public Object {
Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors. Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
}; };
// AnimChannel Channels[3]; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
// AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
// AnimSampler Samplers[3]; //!< The parameterized inputs representing the key-frame data.
std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy. std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
AnimParameters Parameters; //!< The samplers that interpolate between the key-frames. AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data. std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
Animation() {} Animation() = default;
void Read(Value &obj, Asset &r); void Read(Value &obj, Asset &r);
}; };
@ -963,13 +913,11 @@ struct AssetMetadata {
//! Root object for a glTF asset //! Root object for a glTF asset
class Asset { class Asset {
typedef std::gltf_unordered_map<std::string, int> IdMap; using IdMap = std::gltf_unordered_map<std::string, int>;
template <class T> template <class T>
friend class LazyDict; friend class LazyDict;
friend struct Buffer; // To access OpenFile friend struct Buffer; // To access OpenFile
friend class AssetWriter; friend class AssetWriter;
private: private:
@ -1010,12 +958,9 @@ public:
LazyDict<Material> materials; LazyDict<Material> materials;
LazyDict<Mesh> meshes; LazyDict<Mesh> meshes;
LazyDict<Node> nodes; LazyDict<Node> nodes;
//LazyDict<Program> programs;
LazyDict<Sampler> samplers; LazyDict<Sampler> samplers;
LazyDict<Scene> scenes; LazyDict<Scene> scenes;
//LazyDict<Shader> shaders;
LazyDict<Skin> skins; LazyDict<Skin> skins;
//LazyDict<Technique> techniques;
LazyDict<Texture> textures; LazyDict<Texture> textures;
LazyDict<Light> lights; // KHR_materials_common ext LazyDict<Light> lights; // KHR_materials_common ext
@ -1024,16 +969,20 @@ 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"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes") mIOSystem(io),
//, programs (*this, "programs") asset(),
, accessors(*this, "accessors"),
animations(*this, "animations"),
buffers(*this, "buffers"),
bufferViews(*this, "bufferViews"),
cameras(*this, "cameras"),
images(*this, "images"),
materials(*this, "materials"),
meshes(*this, "meshes"),
nodes(*this, "nodes"),
samplers(*this, "samplers"), samplers(*this, "samplers"),
scenes(*this, "scenes") scenes(*this, "scenes"),
//, shaders (*this, "shaders") skins(*this, "skins"),
,
skins(*this, "skins")
//, techniques (*this, "techniques")
,
textures(*this, "textures"), textures(*this, "textures"),
lights(*this, "lights", "KHR_materials_common") { lights(*this, "lights", "KHR_materials_common") {
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); memset(&extensionsUsed, 0, sizeof(extensionsUsed));

View File

@ -237,8 +237,6 @@ bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out);
#define CHECK_EXT(EXT) \ #define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
//! Helper struct to represent values that might not be present //! Helper struct to represent values that might not be present
template <class T> template <class T>
struct Nullable { struct Nullable {

View File

@ -106,7 +106,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define gltf_unordered_map tr1::unordered_map # define gltf_unordered_map tr1::unordered_map
# define gltf_unordered_set tr1::unordered_set # define gltf_unordered_set tr1::unordered_set
# else # else
# define gltf_unordered_map unordered_map # define gltf_unordered_map unordered_map
# define gltf_unordered_set unordered_set # define gltf_unordered_set unordered_set
# endif # endif
#endif #endif
@ -1087,29 +1087,11 @@ class Asset {
template <class T> template <class T>
friend class LazyDict; friend class LazyDict;
friend struct Buffer; // To access OpenFile friend struct Buffer; // To access OpenFile
friend class AssetWriter; friend class AssetWriter;
private:
IOSystem *mIOSystem;
rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
std::string mCurrentAssetDir;
size_t mSceneLength;
size_t mBodyOffset, mBodyLength;
std::vector<LazyDictBase *> mDicts; std::vector<LazyDictBase *> mDicts;
IdMap mUsedIds;
Ref<Buffer> mBodyBuffer;
Asset(Asset &);
Asset &operator=(const Asset &);
public: public:
//! Keeps info about the enabled extensions //! Keeps info about the enabled extensions
struct Extensions { struct Extensions {
@ -1125,16 +1107,36 @@ public:
bool KHR_draco_mesh_compression; bool KHR_draco_mesh_compression;
bool FB_ngon_encoding; bool FB_ngon_encoding;
bool KHR_texture_basisu; bool KHR_texture_basisu;
Extensions() :
KHR_materials_pbrSpecularGlossiness(false),
KHR_materials_unlit(false),
KHR_lights_punctual(false),
KHR_texture_transform(false),
KHR_materials_sheen(false),
KHR_materials_clearcoat(false),
KHR_materials_transmission(false),
KHR_materials_volume(false),
KHR_materials_ior(false),
KHR_draco_mesh_compression(false),
FB_ngon_encoding(false),
KHR_texture_basisu(false) {
// empty
}
} extensionsUsed; } extensionsUsed;
//! Keeps info about the required extensions //! Keeps info about the required extensions
struct RequiredExtensions { struct RequiredExtensions {
bool KHR_draco_mesh_compression; bool KHR_draco_mesh_compression;
bool KHR_texture_basisu; bool KHR_texture_basisu;
RequiredExtensions() : KHR_draco_mesh_compression(false), KHR_texture_basisu(false) {
// empty
}
} extensionsRequired; } extensionsRequired;
AssetMetadata asset; AssetMetadata asset;
Value *extras = nullptr; Value *extras;
// Dictionaries for each type of object // Dictionaries for each type of object
@ -1157,9 +1159,11 @@ public:
public: public:
Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) : Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
mIOSystem(io), mDicts(),
mSchemaDocumentProvider(schemaDocumentProvider), extensionsUsed(),
extensionsRequired(),
asset(), asset(),
extras(nullptr),
accessors(*this, "accessors"), accessors(*this, "accessors"),
animations(*this, "animations"), animations(*this, "animations"),
buffers(*this, "buffers"), buffers(*this, "buffers"),
@ -1173,9 +1177,10 @@ public:
samplers(*this, "samplers"), samplers(*this, "samplers"),
scenes(*this, "scenes"), scenes(*this, "scenes"),
skins(*this, "skins"), skins(*this, "skins"),
textures(*this, "textures") { textures(*this, "textures") ,
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); mIOSystem(io),
memset(&extensionsRequired, 0, sizeof(extensionsRequired)); mSchemaDocumentProvider(schemaDocumentProvider) {
// empty
} }
//! Main function //! Main function
@ -1192,18 +1197,31 @@ public:
Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; } Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
Asset(Asset &) = delete;
Asset &operator=(const Asset &) = delete;
private: private:
void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData); void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
//! Obtain a JSON document from the stream. /// Obtain a JSON document from the stream.
// \param second argument is a buffer used by the document. It must be kept /// \param second argument is a buffer used by the document. It must be kept
// alive while the document is in use. /// alive while the document is in use.
Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData); Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
void ReadExtensionsUsed(Document &doc); void ReadExtensionsUsed(Document &doc);
void ReadExtensionsRequired(Document &doc); void ReadExtensionsRequired(Document &doc);
IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false); IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
private:
IOSystem *mIOSystem;
rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
std::string mCurrentAssetDir;
size_t mSceneLength;
size_t mBodyOffset;
size_t mBodyLength;
IdMap mUsedIds;
Ref<Buffer> mBodyBuffer;
}; };
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) { inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {

View File

@ -515,72 +515,74 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, float &prop, const char
} }
void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) { void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
if (mat.GetTextureCount(tt) > 0) { if (mat.GetTextureCount(tt) == 0) {
aiString tex; return;
}
// Read texcoord (UV map index) aiString tex;
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { // Read texcoord (UV map index)
std::string path = tex.C_Str(); mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
if (path.size() > 0) { if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path); std::string path = tex.C_Str();
if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Get(it->second);
}
bool useBasisUniversal = false; if (path.size() > 0) {
if (!texture) { std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
std::string texId = mAsset->FindUniqueID("", "texture"); if (it != mTexturesByPath.end()) {
texture = mAsset->textures.Create(texId); texture = mAsset->textures.Get(it->second);
mTexturesByPath[path] = texture.GetIndex(); }
std::string imgId = mAsset->FindUniqueID("", "image"); bool useBasisUniversal = false;
texture->source = mAsset->images.Create(imgId); if (!texture) {
std::string texId = mAsset->FindUniqueID("", "texture");
texture = mAsset->textures.Create(texId);
mTexturesByPath[path] = texture.GetIndex();
const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str()); std::string imgId = mAsset->FindUniqueID("", "image");
if (curTex != nullptr) { // embedded texture->source = mAsset->images.Create(imgId);
texture->source->name = curTex->mFilename.C_Str();
//basisu: embedded ktx2, bu const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
if (curTex->achFormatHint[0]) { if (curTex != nullptr) { // embedded
std::string mimeType = "image/"; texture->source->name = curTex->mFilename.C_Str();
if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
mimeType += "jpeg";
else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx";
} else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx2";
} else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
useBasisUniversal = true;
mimeType += "basis";
} else
mimeType += curTex->achFormatHint;
texture->source->mimeType = mimeType;
}
// The asset has its own buffer, see Image::SetData //basisu: embedded ktx2, bu
//basisu: "image/ktx2", "image/basis" as is if (curTex->achFormatHint[0]) {
texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset); std::string mimeType = "image/";
} else { if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
texture->source->uri = path; mimeType += "jpeg";
if (texture->source->uri.find(".ktx") != std::string::npos || else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
texture->source->uri.find(".basis") != std::string::npos) {
useBasisUniversal = true; useBasisUniversal = true;
} mimeType += "ktx";
} else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
useBasisUniversal = true;
mimeType += "ktx2";
} else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
useBasisUniversal = true;
mimeType += "basis";
} else
mimeType += curTex->achFormatHint;
texture->source->mimeType = mimeType;
} }
//basisu // The asset has its own buffer, see Image::SetData
if (useBasisUniversal) { //basisu: "image/ktx2", "image/basis" as is
mAsset->extensionsUsed.KHR_texture_basisu = true; texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
mAsset->extensionsRequired.KHR_texture_basisu = true; } else {
texture->source->uri = path;
if (texture->source->uri.find(".ktx") != std::string::npos ||
texture->source->uri.find(".basis") != std::string::npos) {
useBasisUniversal = true;
} }
GetTexSampler(mat, texture, tt, slot);
} }
//basisu
if (useBasisUniversal) {
mAsset->extensionsUsed.KHR_texture_basisu = true;
mAsset->extensionsRequired.KHR_texture_basisu = true;
}
GetTexSampler(mat, texture, tt, slot);
} }
} }
} }
@ -588,12 +590,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
void glTF2Exporter::GetMatTex(const aiMaterial &mat, TextureInfo &prop, aiTextureType tt, unsigned int slot = 0) { void glTF2Exporter::GetMatTex(const aiMaterial &mat, TextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
Ref<Texture> &texture = prop.texture; Ref<Texture> &texture = prop.texture;
GetMatTex(mat, texture, prop.texCoord, tt, slot); GetMatTex(mat, texture, prop.texCoord, tt, slot);
//if (texture) {
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
//}
} }
void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, aiTextureType tt, unsigned int slot = 0) { void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
@ -681,12 +678,14 @@ bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlo
bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) { bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) {
// Return true if got any valid Sheen properties or textures // Return true if got any valid Sheen properties or textures
if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) {
return false; return false;
}
// Default Sheen color factor {0,0,0} disables Sheen, so do not export // Default Sheen color factor {0,0,0} disables Sheen, so do not export
if (sheen.sheenColorFactor == defaultSheenFactor) if (sheen.sheenColorFactor == defaultSheenFactor) {
return false; return false;
}
mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
@ -781,9 +780,7 @@ void glTF2Exporter::ExportMaterials() {
aiColor4D specularColor; aiColor4D specularColor;
ai_real shininess; ai_real shininess;
if ( if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
// convert specular color to luminance // convert specular color to luminance
float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
//normalize shininess (assuming max is 1000) with an inverse exponentional curve //normalize shininess (assuming max is 1000) with an inverse exponentional curve
@ -916,7 +913,8 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
return parentNodeRef; return parentNodeRef;
} }
void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef, std::vector<aiMatrix4x4> &inverseBindMatricesData) { void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef,
std::vector<aiMatrix4x4> &inverseBindMatricesData) {
if (aimesh->mNumBones < 1) { if (aimesh->mNumBones < 1) {
return; return;
} }
@ -986,7 +984,8 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
} // End: for-loop mNumMeshes } // End: for-loop mNumMeshes
Mesh::Primitive &p = meshRef->primitives.back(); Mesh::Primitive &p = meshRef->primitives.back();
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if (vertexJointAccessor) { if (vertexJointAccessor) {
size_t offset = vertexJointAccessor->bufferView->byteOffset; size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength; size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
@ -1069,8 +1068,11 @@ void glTF2Exporter::ExportMeshes() {
p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0; p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0;
/******************* Vertices ********************/ /******************* Vertices ********************/
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3,
if (v) p.attributes.position.push_back(v); AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (v) {
p.attributes.position.push_back(v);
}
/******************** Normals ********************/ /******************** Normals ********************/
// Normalize all normals as the validator can emit a warning otherwise // Normalize all normals as the validator can emit a warning otherwise
@ -1080,13 +1082,17 @@ void glTF2Exporter::ExportMeshes() {
} }
} }
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3,
if (n) p.attributes.normal.push_back(n); AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (n) {
p.attributes.normal.push_back(n);
}
/************** Texture coordinates **************/ /************** Texture coordinates **************/
for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!aim->HasTextureCoords(i)) if (!aim->HasTextureCoords(i)) {
continue; continue;
}
// Flip UV y coords // Flip UV y coords
if (aim->mNumUVComponents[i] > 1) { if (aim->mNumUVComponents[i] > 1) {
@ -1098,16 +1104,21 @@ void glTF2Exporter::ExportMeshes() {
if (aim->mNumUVComponents[i] > 0) { if (aim->mNumUVComponents[i] > 0) {
AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i],
if (tc) p.attributes.texcoord.push_back(tc); AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (tc) {
p.attributes.texcoord.push_back(tc);
}
} }
} }
/*************** Vertex colors ****************/ /*************** Vertex colors ****************/
for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) { for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) {
Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel],
if (c) AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
if (c) {
p.attributes.color.push_back(c); p.attributes.color.push_back(c);
}
} }
/*************** Vertices indices ****************/ /*************** Vertices indices ****************/
@ -1121,7 +1132,8 @@ void glTF2Exporter::ExportMeshes() {
} }
} }
p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER); p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR,
ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
} }
switch (aim->mPrimitiveTypes) { switch (aim->mPrimitiveTypes) {
@ -1136,6 +1148,7 @@ void glTF2Exporter::ExportMeshes() {
break; break;
default: // aiPrimitiveType_TRIANGLE default: // aiPrimitiveType_TRIANGLE
p.mode = PrimitiveMode_TRIANGLES; p.mode = PrimitiveMode_TRIANGLES;
break;
} }
/*************** Skins ****************/ /*************** Skins ****************/
@ -1155,8 +1168,9 @@ void glTF2Exporter::ExportMeshes() {
p.targets.resize(aim->mNumAnimMeshes); p.targets.resize(aim->mNumAnimMeshes);
for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) { for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am]; aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am];
if (bExportTargetNames) if (bExportTargetNames) {
m->targetNames.push_back(pAnimMesh->mName.data); m->targetNames.emplace_back(pAnimMesh->mName.data);
}
// position // position
if (pAnimMesh->HasPositions()) { if (pAnimMesh->HasPositions()) {
// NOTE: in gltf it is the diff stored // NOTE: in gltf it is the diff stored
@ -1319,12 +1333,12 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
} }
for (unsigned int i = 0; i < n->mNumMeshes; ++i) { for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
} }
for (unsigned int i = 0; i < n->mNumChildren; ++i) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node); unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx)); node->children.emplace_back(mAsset->nodes.Get(idx));
} }
return node.GetIndex(); return node.GetIndex();
@ -1366,12 +1380,12 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
} }
for (unsigned int i = 0; i < n->mNumMeshes; ++i) { for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
} }
for (unsigned int i = 0; i < n->mNumChildren; ++i) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i], node); unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx)); node->children.emplace_back(mAsset->nodes.Get(idx));
} }
return node.GetIndex(); return node.GetIndex();
@ -1386,7 +1400,7 @@ void glTF2Exporter::ExportScene() {
// root node will be the first one exported (idx 0) // root node will be the first one exported (idx 0)
if (mAsset->nodes.Size() > 0) { if (mAsset->nodes.Size() > 0) {
scene->nodes.push_back(mAsset->nodes.Get(0u)); scene->nodes.emplace_back(mAsset->nodes.Get(0u));
} }
// set as the default scene // set as the default scene
@ -1521,12 +1535,6 @@ void glTF2Exporter::ExportAnimations() {
AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE);
} }
} }
// Assimp documentation states this is not used (not implemented)
// for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
// const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
// }
} // End: for-loop mNumAnimations } // End: for-loop mNumAnimations
} }

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -76,6 +75,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
inline uint32_t SuperFastHash (const char * data, uint32_t len = 0, uint32_t hash = 0) { inline uint32_t SuperFastHash (const char * data, uint32_t len = 0, uint32_t hash = 0) {
uint32_t tmp; uint32_t tmp;
int rem; int rem;
size_t offset;
if (!data) return 0; if (!data) return 0;
if (!len)len = (uint32_t)::strlen(data); if (!len)len = (uint32_t)::strlen(data);
@ -96,7 +96,11 @@ int rem;
switch (rem) { switch (rem) {
case 3: hash += get16bits (data); case 3: hash += get16bits (data);
hash ^= hash << 16; hash ^= hash << 16;
hash ^= data[sizeof (uint16_t)] << 18; offset = static_cast<size_t>(sizeof(uint16_t));
if (offset < 0) {
return 0;
}
hash ^= data[offset] << 18;
hash += hash >> 11; hash += hash >> 11;
break; break;
case 2: hash += get16bits (data); case 2: hash += get16bits (data);

View File

@ -53,6 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h> #include <assimp/material.h>
// ---------------------------------------------------------------------------
// the original illum property
#define AI_MATKEY_OBJ_ILLUM "$mat.illum", 0, 0
// ---------------------------------------------------------------------------
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Pure key names for all obj texture-related properties // Pure key names for all obj texture-related properties
//! @cond MATS_DOC_FULL //! @cond MATS_DOC_FULL

View File

@ -60,7 +60,7 @@ protected:
}; };
TEST_F(utMesh, emptyMeshHasNoContentTest) { TEST_F(utMesh, emptyMeshHasNoContentTest) {
EXPECT_EQ(0, mesh->mName.length); EXPECT_EQ(0u, mesh->mName.length);
EXPECT_FALSE(mesh->HasPositions()); EXPECT_FALSE(mesh->HasPositions());
EXPECT_FALSE(mesh->HasFaces()); EXPECT_FALSE(mesh->HasFaces());
EXPECT_FALSE(mesh->HasNormals()); EXPECT_FALSE(mesh->HasNormals());
@ -69,8 +69,8 @@ TEST_F(utMesh, emptyMeshHasNoContentTest) {
EXPECT_FALSE(mesh->HasVertexColors(AI_MAX_NUMBER_OF_COLOR_SETS)); EXPECT_FALSE(mesh->HasVertexColors(AI_MAX_NUMBER_OF_COLOR_SETS));
EXPECT_FALSE(mesh->HasTextureCoords(0)); EXPECT_FALSE(mesh->HasTextureCoords(0));
EXPECT_FALSE(mesh->HasTextureCoords(AI_MAX_NUMBER_OF_TEXTURECOORDS)); EXPECT_FALSE(mesh->HasTextureCoords(AI_MAX_NUMBER_OF_TEXTURECOORDS));
EXPECT_EQ(0, mesh->GetNumUVChannels()); EXPECT_EQ(0u, mesh->GetNumUVChannels());
EXPECT_EQ(0, mesh->GetNumColorChannels()); EXPECT_EQ(0u, mesh->GetNumColorChannels());
EXPECT_FALSE(mesh->HasBones()); EXPECT_FALSE(mesh->HasBones());
EXPECT_FALSE(mesh->HasTextureCoordsName(0)); EXPECT_FALSE(mesh->HasTextureCoordsName(0));
EXPECT_FALSE(mesh->HasTextureCoordsName(AI_MAX_NUMBER_OF_TEXTURECOORDS)); EXPECT_FALSE(mesh->HasTextureCoordsName(AI_MAX_NUMBER_OF_TEXTURECOORDS));
@ -80,8 +80,8 @@ TEST_F(utMesh, setTextureCoordsName) {
EXPECT_FALSE(mesh->HasTextureCoordsName(0)); EXPECT_FALSE(mesh->HasTextureCoordsName(0));
const aiString texcoords_name("texcoord_name"); const aiString texcoords_name("texcoord_name");
mesh->SetTextureCoordsName(0, texcoords_name); mesh->SetTextureCoordsName(0, texcoords_name);
EXPECT_TRUE(mesh->HasTextureCoordsName(0)); EXPECT_TRUE(mesh->HasTextureCoordsName(0u));
EXPECT_FALSE(mesh->HasTextureCoordsName(1)); EXPECT_FALSE(mesh->HasTextureCoordsName(1u));
ASSERT_NE(nullptr, mesh->mTextureCoordsNames); ASSERT_NE(nullptr, mesh->mTextureCoordsNames);
ASSERT_NE(nullptr, mesh->mTextureCoordsNames[0]); ASSERT_NE(nullptr, mesh->mTextureCoordsNames[0]);
EXPECT_STREQ(texcoords_name.C_Str(), mesh->mTextureCoordsNames[0]->C_Str()); EXPECT_STREQ(texcoords_name.C_Str(), mesh->mTextureCoordsNames[0]->C_Str());
@ -94,3 +94,4 @@ TEST_F(utMesh, setTextureCoordsName) {
EXPECT_EQ(nullptr, mesh->mTextureCoordsNames[0]); EXPECT_EQ(nullptr, mesh->mTextureCoordsNames[0]);
EXPECT_EQ(nullptr, mesh->GetTextureCoordsName(0)); EXPECT_EQ(nullptr, mesh->GetTextureCoordsName(0));
} }

View File

@ -124,9 +124,9 @@ TEST_F(utColladaExport, testExportLight) {
ASSERT_NE(pTest, nullptr); ASSERT_NE(pTest, nullptr);
ASSERT_TRUE(pTest->HasLights()); ASSERT_TRUE(pTest->HasLights());
const unsigned int origNumLights(pTest->mNumLights); const unsigned int origNumLights = pTest->mNumLights;
// There are FIVE!!! LIGHTS!!! // There are FIVE!!! LIGHTS!!!
EXPECT_EQ(5, origNumLights) << "lights.dae should contain five lights"; EXPECT_EQ(5u, origNumLights) << "lights.dae should contain five lights";
std::vector<aiLight> origLights(5); std::vector<aiLight> origLights(5);
for (size_t i = 0; i < origNumLights; i++) { for (size_t i = 0; i < origNumLights; i++) {