Merge branch 'master' into parse_obj_anisotropy
commit
72888c49f6
|
@ -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,
|
||||||
|
@ -68,23 +67,13 @@ namespace FBX {
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
|
LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
|
||||||
: doc(doc)
|
doc(doc), element(element), id(id), flags() {
|
||||||
, element(element)
|
|
||||||
, id(id)
|
|
||||||
, flags() {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LazyObject::~LazyObject()
|
const Object* LazyObject::Get(bool dieOnError) {
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
const Object* LazyObject::Get(bool dieOnError)
|
|
||||||
{
|
|
||||||
if(IsBeingConstructed() || FailedToConstruct()) {
|
if(IsBeingConstructed() || FailedToConstruct()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -234,17 +223,8 @@ const Object* LazyObject::Get(bool dieOnError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Object::Object(uint64_t id, const Element& element, const std::string& name)
|
Object::Object(uint64_t id, const Element& element, const std::string& name) :
|
||||||
: element(element)
|
element(element), name(name), id(id) {
|
||||||
, name(name)
|
|
||||||
, id(id)
|
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Object::~Object()
|
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,16 +235,8 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
FileGlobalSettings::~FileGlobalSettings()
|
Document::Document(const Parser& parser, const ImportSettings& settings) :
|
||||||
{
|
settings(settings), parser(parser) {
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Document::Document(const Parser& parser, const ImportSettings& settings)
|
|
||||||
: settings(settings)
|
|
||||||
, parser(parser)
|
|
||||||
{
|
|
||||||
ASSIMP_LOG_DEBUG("Creating FBX Document");
|
ASSIMP_LOG_DEBUG("Creating FBX Document");
|
||||||
|
|
||||||
// Cannot use array default initialization syntax because vc8 fails on it
|
// Cannot use array default initialization syntax because vc8 fails on it
|
||||||
|
@ -285,8 +257,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Document::~Document()
|
Document::~Document() {
|
||||||
{
|
|
||||||
for(ObjectMap::value_type& v : objects) {
|
for(ObjectMap::value_type& v : objects) {
|
||||||
delete v.second;
|
delete v.second;
|
||||||
}
|
}
|
||||||
|
@ -348,8 +319,7 @@ void Document::ReadHeader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Document::ReadGlobalSettings()
|
void Document::ReadGlobalSettings() {
|
||||||
{
|
|
||||||
const Scope& sc = parser.GetRootScope();
|
const Scope& sc = parser.GetRootScope();
|
||||||
const Element* const ehead = sc["GlobalSettings"];
|
const Element* const ehead = sc["GlobalSettings"];
|
||||||
if ( nullptr == ehead || !ehead->Compound() ) {
|
if ( nullptr == ehead || !ehead->Compound() ) {
|
||||||
|
@ -370,8 +340,7 @@ void Document::ReadGlobalSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Document::ReadObjects()
|
void Document::ReadObjects() {
|
||||||
{
|
|
||||||
// read ID objects from "Objects" section
|
// read ID objects from "Objects" section
|
||||||
const Scope& sc = parser.GetRootScope();
|
const Scope& sc = parser.GetRootScope();
|
||||||
const Element* const eobjects = sc["Objects"];
|
const Element* const eobjects = sc["Objects"];
|
||||||
|
@ -418,8 +387,7 @@ void Document::ReadObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Document::ReadPropertyTemplates()
|
void Document::ReadPropertyTemplates() {
|
||||||
{
|
|
||||||
const Scope& sc = parser.GetRootScope();
|
const Scope& sc = parser.GetRootScope();
|
||||||
// read property templates from "Definitions" section
|
// read property templates from "Definitions" section
|
||||||
const Element* const edefs = sc["Definitions"];
|
const Element* const edefs = sc["Definitions"];
|
||||||
|
@ -476,8 +444,7 @@ void Document::ReadPropertyTemplates()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Document::ReadConnections()
|
void Document::ReadConnections() {
|
||||||
{
|
|
||||||
const Scope& sc = parser.GetRootScope();
|
const Scope& sc = parser.GetRootScope();
|
||||||
// read property templates from "Definitions" section
|
// read property templates from "Definitions" section
|
||||||
const Element* const econns = sc["Connections"];
|
const Element* const econns = sc["Connections"];
|
||||||
|
@ -524,8 +491,7 @@ void Document::ReadConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<const AnimationStack*>& Document::AnimationStacks() const
|
const std::vector<const AnimationStack*>& Document::AnimationStacks() const {
|
||||||
{
|
|
||||||
if (!animationStacksResolved.empty() || animationStacks.empty()) {
|
if (!animationStacksResolved.empty() || animationStacks.empty()) {
|
||||||
return animationStacksResolved;
|
return animationStacksResolved;
|
||||||
}
|
}
|
||||||
|
@ -545,17 +511,15 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LazyObject* Document::GetObject(uint64_t id) const
|
LazyObject* Document::GetObject(uint64_t id) const {
|
||||||
{
|
|
||||||
ObjectMap::const_iterator it = objects.find(id);
|
ObjectMap::const_iterator it = objects.find(id);
|
||||||
return it == objects.end() ? nullptr : (*it).second;
|
return it == objects.end() ? nullptr : (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_CLASSNAMES 6
|
constexpr size_t MAX_CLASSNAMES = 6;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
|
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const {
|
||||||
{
|
|
||||||
std::vector<const Connection*> temp;
|
std::vector<const Connection*> temp;
|
||||||
|
|
||||||
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
|
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
|
||||||
|
@ -573,11 +537,9 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, co
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
|
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
|
||||||
const ConnectionMap& conns,
|
const ConnectionMap& conns,
|
||||||
const char* const* classnames,
|
const char* const* classnames,
|
||||||
size_t count) const
|
size_t count) const {
|
||||||
|
|
||||||
{
|
|
||||||
ai_assert(classnames);
|
ai_assert(classnames);
|
||||||
ai_assert( count != 0 );
|
ai_assert( count != 0 );
|
||||||
ai_assert( count <= MAX_CLASSNAMES);
|
ai_assert( count <= MAX_CLASSNAMES);
|
||||||
|
@ -622,95 +584,72 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
|
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const {
|
||||||
{
|
|
||||||
return GetConnectionsSequenced(source, ConnectionsBySource());
|
return GetConnectionsSequenced(source, ConnectionsBySource());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const
|
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const {
|
||||||
{
|
|
||||||
const char* arr[] = {classname};
|
const char* arr[] = {classname};
|
||||||
return GetConnectionsBySourceSequenced(src, arr,1);
|
return GetConnectionsBySourceSequenced(src, arr,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
|
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
|
||||||
const char* const* classnames, size_t count) const
|
const char* const* classnames, size_t count) const {
|
||||||
{
|
|
||||||
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
|
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
||||||
const char* classname) const
|
const char* classname) const {
|
||||||
{
|
|
||||||
const char* arr[] = {classname};
|
const char* arr[] = {classname};
|
||||||
return GetConnectionsByDestinationSequenced(dest, arr,1);
|
return GetConnectionsByDestinationSequenced(dest, arr,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
|
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const {
|
||||||
{
|
|
||||||
return GetConnectionsSequenced(dest, ConnectionsByDestination());
|
return GetConnectionsSequenced(dest, ConnectionsByDestination());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
||||||
const char* const* classnames, size_t count) const
|
const char* const* classnames, size_t count) const {
|
||||||
|
|
||||||
{
|
|
||||||
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
|
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
|
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
|
||||||
const Document& doc)
|
const Document& doc) :
|
||||||
|
insertionOrder(insertionOrder), prop(prop), src(src), dest(dest), doc(doc) {
|
||||||
: insertionOrder(insertionOrder)
|
|
||||||
, prop(prop)
|
|
||||||
, src(src)
|
|
||||||
, dest(dest)
|
|
||||||
, doc(doc)
|
|
||||||
{
|
|
||||||
ai_assert(doc.Objects().find(src) != doc.Objects().end());
|
ai_assert(doc.Objects().find(src) != doc.Objects().end());
|
||||||
// dest may be 0 (root node)
|
// dest may be 0 (root node)
|
||||||
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
|
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Connection::~Connection()
|
LazyObject& Connection::LazySourceObject() const {
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
LazyObject& Connection::LazySourceObject() const
|
|
||||||
{
|
|
||||||
LazyObject* const lazy = doc.GetObject(src);
|
LazyObject* const lazy = doc.GetObject(src);
|
||||||
ai_assert(lazy);
|
ai_assert(lazy);
|
||||||
return *lazy;
|
return *lazy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
LazyObject& Connection::LazyDestinationObject() const
|
LazyObject& Connection::LazyDestinationObject() const {
|
||||||
{
|
|
||||||
LazyObject* const lazy = doc.GetObject(dest);
|
LazyObject* const lazy = doc.GetObject(dest);
|
||||||
ai_assert(lazy);
|
ai_assert(lazy);
|
||||||
return *lazy;
|
return *lazy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const Object* Connection::SourceObject() const
|
const Object* Connection::SourceObject() const {
|
||||||
{
|
|
||||||
LazyObject* const lazy = doc.GetObject(src);
|
LazyObject* const lazy = doc.GetObject(src);
|
||||||
ai_assert(lazy);
|
ai_assert(lazy);
|
||||||
return lazy->Get();
|
return lazy->Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const Object* Connection::DestinationObject() const
|
const Object* Connection::DestinationObject() const {
|
||||||
{
|
|
||||||
LazyObject* const lazy = doc.GetObject(dest);
|
LazyObject* const lazy = doc.GetObject(dest);
|
||||||
ai_assert(lazy);
|
ai_assert(lazy);
|
||||||
return lazy->Get();
|
return lazy->Get();
|
||||||
|
@ -719,4 +658,4 @@ const Object* Connection::DestinationObject() const
|
||||||
} // !FBX
|
} // !FBX
|
||||||
} // !Assimp
|
} // !Assimp
|
||||||
|
|
||||||
#endif
|
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -89,7 +88,7 @@ class LazyObject {
|
||||||
public:
|
public:
|
||||||
LazyObject(uint64_t id, const Element& element, const Document& doc);
|
LazyObject(uint64_t id, const Element& element, const Document& doc);
|
||||||
|
|
||||||
~LazyObject();
|
~LazyObject() = default;
|
||||||
|
|
||||||
const Object* Get(bool dieOnError = false);
|
const Object* Get(bool dieOnError = false);
|
||||||
|
|
||||||
|
@ -139,7 +138,7 @@ class Object {
|
||||||
public:
|
public:
|
||||||
Object(uint64_t id, const Element& element, const std::string& name);
|
Object(uint64_t id, const Element& element, const std::string& name);
|
||||||
|
|
||||||
virtual ~Object();
|
virtual ~Object() = default;
|
||||||
|
|
||||||
const Element& SourceElement() const {
|
const Element& SourceElement() const {
|
||||||
return element;
|
return element;
|
||||||
|
@ -267,8 +266,7 @@ public:
|
||||||
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
virtual ~Light();
|
virtual ~Light();
|
||||||
|
|
||||||
enum Type
|
enum Type {
|
||||||
{
|
|
||||||
Type_Point,
|
Type_Point,
|
||||||
Type_Directional,
|
Type_Directional,
|
||||||
Type_Spot,
|
Type_Spot,
|
||||||
|
@ -278,8 +276,7 @@ public:
|
||||||
Type_MAX // end-of-enum sentinel
|
Type_MAX // end-of-enum sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Decay
|
enum Decay {
|
||||||
{
|
|
||||||
Decay_None,
|
Decay_None,
|
||||||
Decay_Linear,
|
Decay_Linear,
|
||||||
Decay_Quadratic,
|
Decay_Quadratic,
|
||||||
|
@ -347,7 +344,7 @@ public:
|
||||||
|
|
||||||
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
|
||||||
virtual ~Model();
|
virtual ~Model() = default;
|
||||||
|
|
||||||
fbx_simple_property(QuaternionInterpolate, int, 0)
|
fbx_simple_property(QuaternionInterpolate, int, 0)
|
||||||
|
|
||||||
|
@ -578,31 +575,27 @@ public:
|
||||||
BlendMode_BlendModeCount
|
BlendMode_BlendModeCount
|
||||||
};
|
};
|
||||||
|
|
||||||
const Texture* getTexture(int index=0) const
|
const Texture* getTexture(int index=0) const {
|
||||||
{
|
|
||||||
return textures[index];
|
return textures[index];
|
||||||
|
|
||||||
}
|
}
|
||||||
int textureCount() const {
|
int textureCount() const {
|
||||||
return static_cast<int>(textures.size());
|
return static_cast<int>(textures.size());
|
||||||
}
|
}
|
||||||
BlendMode GetBlendMode() const
|
BlendMode GetBlendMode() const {
|
||||||
{
|
|
||||||
return blendMode;
|
return blendMode;
|
||||||
}
|
}
|
||||||
float Alpha()
|
float Alpha() {
|
||||||
{
|
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<const Texture*> textures;
|
std::vector<const Texture*> textures;
|
||||||
BlendMode blendMode;
|
BlendMode blendMode;
|
||||||
float alpha;
|
float alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::fbx_unordered_map<std::string, const Texture*> TextureMap;
|
using TextureMap = std::fbx_unordered_map<std::string, const Texture*>;
|
||||||
typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextureMap;
|
using LayeredTextureMap = std::fbx_unordered_map<std::string, const LayeredTexture*>;
|
||||||
|
|
||||||
|
|
||||||
/** DOM class for generic FBX videos */
|
/** DOM class for generic FBX videos */
|
||||||
class Video : public Object {
|
class Video : public Object {
|
||||||
|
@ -690,8 +683,8 @@ private:
|
||||||
LayeredTextureMap layeredTextures;
|
LayeredTextureMap layeredTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<int64_t> KeyTimeList;
|
using KeyTimeList = std::vector<int64_t>;
|
||||||
typedef std::vector<float> KeyValueList;
|
using KeyValueList = std::vector<float>;
|
||||||
|
|
||||||
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
|
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
|
||||||
class AnimationCurve : public Object {
|
class AnimationCurve : public Object {
|
||||||
|
@ -727,7 +720,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// property-name -> animation curve
|
// property-name -> animation curve
|
||||||
typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
|
using AnimationCurveMap = std::map<std::string, const AnimationCurve*>;
|
||||||
|
|
||||||
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
|
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
|
||||||
class AnimationCurveNode : public Object {
|
class AnimationCurveNode : public Object {
|
||||||
|
@ -777,7 +770,7 @@ private:
|
||||||
const Document& doc;
|
const Document& doc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
|
using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
|
||||||
|
|
||||||
/** Represents a FBX animation layer (i.e. a list of node animations) */
|
/** Represents a FBX animation layer (i.e. a list of node animations) */
|
||||||
class AnimationLayer : public Object {
|
class AnimationLayer : public Object {
|
||||||
|
@ -800,7 +793,7 @@ private:
|
||||||
const Document& doc;
|
const Document& doc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<const AnimationLayer*> AnimationLayerList;
|
using AnimationLayerList = std::vector<const AnimationLayer*>;
|
||||||
|
|
||||||
/** Represents a FBX animation stack (i.e. a list of animation layers) */
|
/** Represents a FBX animation stack (i.e. a list of animation layers) */
|
||||||
class AnimationStack : public Object {
|
class AnimationStack : public Object {
|
||||||
|
@ -843,8 +836,8 @@ private:
|
||||||
std::shared_ptr<const PropertyTable> props;
|
std::shared_ptr<const PropertyTable> props;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<float> WeightArray;
|
using WeightArray = std::vector<float>;
|
||||||
typedef std::vector<unsigned int> WeightIndexArray;
|
using WeightIndexArray = std::vector<unsigned int>;
|
||||||
|
|
||||||
|
|
||||||
/** DOM class for BlendShapeChannel deformers */
|
/** DOM class for BlendShapeChannel deformers */
|
||||||
|
@ -956,7 +949,7 @@ class Connection {
|
||||||
public:
|
public:
|
||||||
Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
|
Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
|
||||||
|
|
||||||
~Connection();
|
~Connection() = default;
|
||||||
|
|
||||||
// note: a connection ensures that the source and dest objects exist, but
|
// note: a connection ensures that the source and dest objects exist, but
|
||||||
// not that they have DOM representations, so the return value of one of
|
// not that they have DOM representations, so the return value of one of
|
||||||
|
@ -1011,10 +1004,9 @@ public:
|
||||||
// during their entire lifetime (Document). FBX files have
|
// during their entire lifetime (Document). FBX files have
|
||||||
// up to many thousands of objects (most of which we never use),
|
// up to many thousands of objects (most of which we never use),
|
||||||
// so the memory overhead for them should be kept at a minimum.
|
// so the memory overhead for them should be kept at a minimum.
|
||||||
typedef std::fbx_unordered_map<uint64_t, LazyObject*> ObjectMap;
|
using ObjectMap = std::fbx_unordered_map<uint64_t, LazyObject*> ;
|
||||||
typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
|
using PropertyTemplateMap = std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > ;
|
||||||
|
using ConnectionMap = std::fbx_unordered_multimap<uint64_t, const Connection*>;
|
||||||
typedef std::fbx_unordered_multimap<uint64_t, const Connection*> ConnectionMap;
|
|
||||||
|
|
||||||
/** DOM class for global document settings, a single instance per document can
|
/** DOM class for global document settings, a single instance per document can
|
||||||
* be accessed via Document.Globals(). */
|
* be accessed via Document.Globals(). */
|
||||||
|
@ -1022,7 +1014,7 @@ class FileGlobalSettings {
|
||||||
public:
|
public:
|
||||||
FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
|
FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
|
||||||
|
|
||||||
~FileGlobalSettings();
|
~FileGlobalSettings() = default;
|
||||||
|
|
||||||
const PropertyTable& Props() const {
|
const PropertyTable& Props() const {
|
||||||
ai_assert(props.get());
|
ai_assert(props.get());
|
||||||
|
|
|
@ -140,11 +140,32 @@ Material::~Material() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aiVector2D uvTrans;
|
||||||
|
aiVector2D uvScaling;
|
||||||
|
ai_real uvRotation;
|
||||||
|
|
||||||
|
std::string type;
|
||||||
|
std::string relativeFileName;
|
||||||
|
std::string fileName;
|
||||||
|
std::string alphaSource;
|
||||||
|
std::shared_ptr<const PropertyTable> props;
|
||||||
|
|
||||||
|
unsigned int crop[4]{};
|
||||||
|
|
||||||
|
const Video* media;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
||||||
Object(id,element,name),
|
Object(id,element,name),
|
||||||
|
uvTrans(0.0f, 0.0f),
|
||||||
uvScaling(1.0f,1.0f),
|
uvScaling(1.0f,1.0f),
|
||||||
media(0) {
|
uvRotation(0.0f),
|
||||||
|
type(),
|
||||||
|
relativeFileName(),
|
||||||
|
fileName(),
|
||||||
|
alphaSource(),
|
||||||
|
props(),
|
||||||
|
media(nullptr) {
|
||||||
const Scope& sc = GetRequiredScope(element);
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
|
||||||
const Element* const Type = sc["Type"];
|
const Element* const Type = sc["Type"];
|
||||||
|
|
|
@ -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,10 +75,6 @@ Model::Model(uint64_t id, const Element &element, const Document &doc, const std
|
||||||
ResolveLinks(element, doc);
|
ResolveLinks(element, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Model::~Model() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Model::ResolveLinks(const Element&, const Document &doc) {
|
void Model::ResolveLinks(const Element&, const Document &doc) {
|
||||||
const char *const arr[] = { "Geometry", "Material", "NodeAttribute" };
|
const char *const arr[] = { "Geometry", "Material", "NodeAttribute" };
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace LWO {
|
||||||
|
|
||||||
#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L', 'W', 'O', 'B')
|
#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L', 'W', 'O', 'B')
|
||||||
#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L', 'W', 'O', '2')
|
#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L', 'W', 'O', '2')
|
||||||
|
#define AI_LWO_FOURCC_LWO3 AI_IFF_FOURCC('L', 'W', 'O', '3')
|
||||||
#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L', 'X', 'O', 'B')
|
#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L', 'X', 'O', 'B')
|
||||||
|
|
||||||
// chunks specific to the LWOB format
|
// chunks specific to the LWOB format
|
||||||
|
@ -248,6 +249,57 @@ namespace LWO {
|
||||||
#define AI_LWO_SPOT AI_IFF_FOURCC('S', 'P', 'O', 'T')
|
#define AI_LWO_SPOT AI_IFF_FOURCC('S', 'P', 'O', 'T')
|
||||||
#define AI_LWO_PICK AI_IFF_FOURCC('P', 'I', 'C', 'K')
|
#define AI_LWO_PICK AI_IFF_FOURCC('P', 'I', 'C', 'K')
|
||||||
|
|
||||||
|
// Surface Part
|
||||||
|
#define AI_LWO_NODS AI_IFF_FOURCC('N', 'O', 'D', 'S')
|
||||||
|
#define AI_LWO_NNDS AI_IFF_FOURCC('N', 'N', 'D', 'S')
|
||||||
|
#define AI_LWO_NTAG AI_IFF_FOURCC('N', 'T', 'A', 'G')
|
||||||
|
#define AI_LWO_NRNM AI_IFF_FOURCC('N', 'R', 'N', 'M')
|
||||||
|
#define AI_LWO_NRME AI_IFF_FOURCC('N', 'R', 'M', 'E')
|
||||||
|
#define AI_LWO_NDTA AI_IFF_FOURCC('N', 'D', 'T', 'A')
|
||||||
|
#define AI_LWO_ATTR AI_IFF_FOURCC('A', 'T', 'T', 'R')
|
||||||
|
#define AI_LWO_VERS AI_IFF_FOURCC('V', 'E', 'R', 'S')
|
||||||
|
#define AI_LWO_ENUM AI_IFF_FOURCC('E', 'N', 'U', 'M')
|
||||||
|
#define AI_LWO_ENTR AI_IFF_FOURCC('E', 'N', 'T', 'R')
|
||||||
|
#define AI_LWO_NAME AI_IFF_FOURCC('N', 'A', 'M', 'E')
|
||||||
|
#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G')
|
||||||
|
#define AI_LWO_TAG AI_IFF_FOURCC('T', 'A', 'G', ' ')
|
||||||
|
#define AI_LWO_VALU AI_IFF_FOURCC('V', 'A', 'L', 'U')
|
||||||
|
#define AI_LWO_IBGC AI_IFF_FOURCC('I', 'B', 'G', 'C')
|
||||||
|
#define AI_LWO_IOPC AI_IFF_FOURCC('I', 'O', 'P', 'C')
|
||||||
|
#define AI_LWO_IIMG AI_IFF_FOURCC('I', 'I', 'M', 'G')
|
||||||
|
#define AI_LWO_TXTR AI_IFF_FOURCC('T', 'X', 'T', 'R')
|
||||||
|
|
||||||
|
#define AI_LWO_IFAL AI_IFF_FOURCC('I', 'F', 'A', 'L')
|
||||||
|
#define AI_LWO_ISCL AI_IFF_FOURCC('I', 'S', 'C', 'L')
|
||||||
|
#define AI_LWO_IPOS AI_IFF_FOURCC('I', 'P', 'O', 'S')
|
||||||
|
#define AI_LWO_IROT AI_IFF_FOURCC('I', 'R', 'O', 'T')
|
||||||
|
#define AI_LWO_IBMP AI_IFF_FOURCC('I', 'B', 'M', 'P')
|
||||||
|
#define AI_LWO_IUTD AI_IFF_FOURCC('I', 'U', 'T', 'D')
|
||||||
|
#define AI_LWO_IVTD AI_IFF_FOURCC('I', 'V', 'T', 'D')
|
||||||
|
|
||||||
|
#define AI_LWO_IPIX AI_IFF_FOURCC('I', 'P', 'I', 'X')
|
||||||
|
#define AI_LWO_IMIP AI_IFF_FOURCC('I', 'M', 'I', 'P')
|
||||||
|
#define AI_LWO_IMOD AI_IFF_FOURCC('I', 'M', 'O', 'D')
|
||||||
|
#define AI_LWO_AMOD AI_IFF_FOURCC('A', 'M', 'O', 'D')
|
||||||
|
#define AI_LWO_IINV AI_IFF_FOURCC('I', 'I', 'N', 'V')
|
||||||
|
#define AI_LWO_INCR AI_IFF_FOURCC('I', 'N', 'C', 'R')
|
||||||
|
#define AI_LWO_IAXS AI_IFF_FOURCC('I', 'A', 'X', 'S')
|
||||||
|
#define AI_LWO_IFOT AI_IFF_FOURCC('I', 'F', 'O', 'T')
|
||||||
|
#define AI_LWO_ITIM AI_IFF_FOURCC('I', 'T', 'I', 'M')
|
||||||
|
#define AI_LWO_IWRL AI_IFF_FOURCC('I', 'W', 'R', 'L')
|
||||||
|
#define AI_LWO_IUTI AI_IFF_FOURCC('I', 'U', 'T', 'I')
|
||||||
|
#define AI_LWO_IINX AI_IFF_FOURCC('I', 'I', 'N', 'X')
|
||||||
|
#define AI_LWO_IINY AI_IFF_FOURCC('I', 'I', 'N', 'Y')
|
||||||
|
#define AI_LWO_IINZ AI_IFF_FOURCC('I', 'I', 'N', 'Z')
|
||||||
|
#define AI_LWO_IREF AI_IFF_FOURCC('I', 'R', 'E', 'F')
|
||||||
|
#define AI_LWO_IMST AI_IFF_FOURCC('I', 'M', 'S', 'T')
|
||||||
|
#define AI_LWO_VPVL AI_IFF_FOURCC('V', 'P', 'V', 'L')
|
||||||
|
#define AI_LWO_VPRM AI_IFF_FOURCC('V', 'P', 'R', 'M')
|
||||||
|
#define AI_LWO_IMAP AI_IFF_FOURCC('I', 'M', 'A', 'P')
|
||||||
|
#define AI_LWO_IUVI AI_IFF_FOURCC('I', 'U', 'V', 'I')
|
||||||
|
#define AI_LWO_IUTL AI_IFF_FOURCC('I', 'U', 'T', 'L')
|
||||||
|
#define AI_LWO_IVTL AI_IFF_FOURCC('I', 'V', 'T', 'L')
|
||||||
|
|
||||||
// MODO extension - per-vertex normal vectors
|
// MODO extension - per-vertex normal vectors
|
||||||
#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M')
|
#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M')
|
||||||
|
|
||||||
|
@ -555,6 +607,31 @@ struct Surface {
|
||||||
float mAdditiveTransparency;
|
float mAdditiveTransparency;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Data structure for a LWO node
|
||||||
|
*/
|
||||||
|
struct Node {
|
||||||
|
// Name of node
|
||||||
|
std::string mName;
|
||||||
|
|
||||||
|
// RefName of node
|
||||||
|
std::string mRefName;
|
||||||
|
|
||||||
|
// Ref FileName
|
||||||
|
std::string fileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NodeAttribute {
|
||||||
|
//! Color of the surface
|
||||||
|
aiColor3D mColor;
|
||||||
|
|
||||||
|
//! true for two-sided materials
|
||||||
|
bool bDoubleSided;
|
||||||
|
|
||||||
|
//! Various material parameters
|
||||||
|
float mDiffuseValue, mSpecularValue, mTransparency, mGlossiness, mLuminosity, mColorHighlights;
|
||||||
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length, name, size) \
|
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length, name, size) \
|
||||||
if (length < size) { \
|
if (length < size) { \
|
||||||
|
|
|
@ -83,6 +83,7 @@ static const aiImporterDesc desc = {
|
||||||
LWOImporter::LWOImporter() :
|
LWOImporter::LWOImporter() :
|
||||||
mIsLWO2(),
|
mIsLWO2(),
|
||||||
mIsLXOB(),
|
mIsLXOB(),
|
||||||
|
mIsLWO3(),
|
||||||
mLayers(),
|
mLayers(),
|
||||||
mCurLayer(),
|
mCurLayer(),
|
||||||
mTags(),
|
mTags(),
|
||||||
|
@ -182,16 +183,19 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
||||||
mCurLayer->mIndex = (uint16_t) -1;
|
mCurLayer->mIndex = (uint16_t) -1;
|
||||||
|
|
||||||
// old lightwave file format (prior to v6)
|
// old lightwave file format (prior to v6)
|
||||||
|
mIsLWO2 = false;
|
||||||
|
mIsLWO3 = false;
|
||||||
|
mIsLXOB = false;
|
||||||
|
|
||||||
if (AI_LWO_FOURCC_LWOB == fileType) {
|
if (AI_LWO_FOURCC_LWOB == fileType) {
|
||||||
ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)");
|
ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)");
|
||||||
|
|
||||||
mIsLWO2 = false;
|
|
||||||
mIsLXOB = false;
|
|
||||||
LoadLWOBFile();
|
LoadLWOBFile();
|
||||||
} else if (AI_LWO_FOURCC_LWO2 == fileType) {
|
} else if (AI_LWO_FOURCC_LWO2 == fileType) {
|
||||||
// New lightwave format
|
// New lightwave format
|
||||||
mIsLXOB = false;
|
|
||||||
ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)");
|
ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)");
|
||||||
|
} else if ( AI_LWO_FOURCC_LWO3 == fileType ) {
|
||||||
|
ASSIMP_LOG_INFO("LWO file format: LWO3 (>= LightWave 2018)");
|
||||||
} else if (AI_LWO_FOURCC_LXOB == fileType) {
|
} else if (AI_LWO_FOURCC_LXOB == fileType) {
|
||||||
// MODO file format
|
// MODO file format
|
||||||
mIsLXOB = true;
|
mIsLXOB = true;
|
||||||
|
@ -207,8 +211,13 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
||||||
throw DeadlyImportError("Unknown LWO sub format: ", szBuff);
|
throw DeadlyImportError("Unknown LWO sub format: ", szBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AI_LWO_FOURCC_LWOB != fileType) {
|
if (AI_LWO_FOURCC_LWOB != fileType) { //
|
||||||
mIsLWO2 = true;
|
if( AI_LWO_FOURCC_LWO3 == fileType ) {
|
||||||
|
mIsLWO3 = true;
|
||||||
|
} else {
|
||||||
|
mIsLWO2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
LoadLWO2File();
|
LoadLWO2File();
|
||||||
|
|
||||||
// The newer lightwave format allows the user to configure the
|
// The newer lightwave format allows the user to configure the
|
||||||
|
@ -442,6 +451,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
|
||||||
|
|
||||||
// The RemoveRedundantMaterials step will clean this up later
|
// The RemoveRedundantMaterials step will clean this up later
|
||||||
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
|
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
|
||||||
|
|
||||||
for (unsigned int mat = 0; mat < pScene->mNumMaterials; ++mat) {
|
for (unsigned int mat = 0; mat < pScene->mNumMaterials; ++mat) {
|
||||||
aiMaterial *pcMat = new aiMaterial();
|
aiMaterial *pcMat = new aiMaterial();
|
||||||
pScene->mMaterials[mat] = pcMat;
|
pScene->mMaterials[mat] = pcMat;
|
||||||
|
@ -687,7 +697,7 @@ void LWOImporter::ResolveClips() {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::AdjustTexturePath(std::string &out) {
|
void LWOImporter::AdjustTexturePath(std::string &out) {
|
||||||
// --- this function is used for both LWO2 and LWOB
|
// --- this function is used for both LWO2 and LWOB
|
||||||
if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) {
|
if (!mIsLWO2 && !mIsLWO3 && ::strstr(out.c_str(), "(sequence)")) {
|
||||||
|
|
||||||
// remove the (sequence) and append 000
|
// remove the (sequence) and append 000
|
||||||
ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored");
|
ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored");
|
||||||
|
@ -730,7 +740,7 @@ void LWOImporter::LoadLWOPoints(unsigned int length) {
|
||||||
throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)");
|
throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)");
|
||||||
}
|
}
|
||||||
unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
||||||
if (mIsLWO2) {
|
if (mIsLWO2 || mIsLWO3) {
|
||||||
mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u));
|
mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u));
|
||||||
mCurLayer->mTempPoints.resize(regularSize);
|
mCurLayer->mTempPoints.resize(regularSize);
|
||||||
|
|
||||||
|
@ -1155,6 +1165,76 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LWOImporter::LoadLWO3Clip(unsigned int length) {
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 12);
|
||||||
|
|
||||||
|
mClips.push_back(LWO::Clip());
|
||||||
|
LWO::Clip &clip = mClips.back();
|
||||||
|
|
||||||
|
// first - get the index of the clip
|
||||||
|
clip.idx = GetU4();
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_STIL:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, STIL, 1);
|
||||||
|
|
||||||
|
// "Normal" texture
|
||||||
|
GetS0(clip.path, head.length);
|
||||||
|
clip.type = Clip::STILL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_LWO_ISEQ:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ISEQ, 16);
|
||||||
|
// Image sequence. We'll later take the first.
|
||||||
|
{
|
||||||
|
uint8_t digits = GetU1();
|
||||||
|
mFileBuffer++;
|
||||||
|
int16_t offset = GetU2();
|
||||||
|
mFileBuffer += 4;
|
||||||
|
int16_t start = GetU2();
|
||||||
|
mFileBuffer += 4;
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
std::ostringstream ss;
|
||||||
|
GetS0(s, head.length);
|
||||||
|
|
||||||
|
head.length -= (uint16_t)s.length() + 1;
|
||||||
|
ss << s;
|
||||||
|
ss << std::setw(digits) << offset + start;
|
||||||
|
GetS0(s, head.length);
|
||||||
|
ss << s;
|
||||||
|
clip.path = ss.str();
|
||||||
|
clip.type = Clip::SEQ;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_LWO_STCC:
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Color shifted images are not supported");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_LWO_ANIM:
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Animated textures are not supported");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_LWO_XREF:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, XREF, 4);
|
||||||
|
|
||||||
|
// Just a cross-reference to another CLIp
|
||||||
|
clip.type = Clip::REF;
|
||||||
|
clip.clipRef = GetU4();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_LWO_NEGA:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, NEGA, 2);
|
||||||
|
clip.negate = (0 != GetU2());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Encountered unknown CLIP sub-chunk");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Load envelope description
|
// Load envelope description
|
||||||
void LWOImporter::LoadLWO2Envelope(unsigned int length) {
|
void LWOImporter::LoadLWO2Envelope(unsigned int length) {
|
||||||
|
@ -1265,6 +1345,104 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LWOImporter::LoadLWO3Envelope(unsigned int length) {
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + length;
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
|
||||||
|
|
||||||
|
mEnvelopes.push_back(LWO::Envelope());
|
||||||
|
LWO::Envelope &envelope = mEnvelopes.back();
|
||||||
|
|
||||||
|
// Get the index of the envelope
|
||||||
|
envelope.index = ReadVSizedIntLWO2(mFileBuffer);
|
||||||
|
|
||||||
|
// ... and read all blocks
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end) break;
|
||||||
|
LE_NCONST IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end)
|
||||||
|
throw DeadlyImportError("LWO3: Invalid envelope chunk length");
|
||||||
|
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
switch (head.type) {
|
||||||
|
// Type & representation of the envelope
|
||||||
|
case AI_LWO_TYPE:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TYPE, 4);
|
||||||
|
mFileBuffer++; // skip user format
|
||||||
|
|
||||||
|
// Determine type of envelope
|
||||||
|
envelope.type = (LWO::EnvelopeType)*mFileBuffer;
|
||||||
|
++mFileBuffer;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// precondition
|
||||||
|
case AI_LWO_PRE:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, PRE, 4);
|
||||||
|
envelope.pre = (LWO::PrePostBehaviour)GetU2();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// postcondition
|
||||||
|
case AI_LWO_POST:
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, POST, 4);
|
||||||
|
envelope.post = (LWO::PrePostBehaviour)GetU2();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// keyframe
|
||||||
|
case AI_LWO_KEY: {
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 10);
|
||||||
|
|
||||||
|
envelope.keys.push_back(LWO::Key());
|
||||||
|
LWO::Key &key = envelope.keys.back();
|
||||||
|
|
||||||
|
key.time = GetF4();
|
||||||
|
key.value = GetF4();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interval interpolation
|
||||||
|
case AI_LWO_SPAN: {
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPAN, 6);
|
||||||
|
if (envelope.keys.size() < 2)
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Unexpected SPAN chunk");
|
||||||
|
else {
|
||||||
|
LWO::Key &key = envelope.keys.back();
|
||||||
|
switch (GetU4()) {
|
||||||
|
case AI_LWO_STEP:
|
||||||
|
key.inter = LWO::IT_STEP;
|
||||||
|
break;
|
||||||
|
case AI_LWO_LINE:
|
||||||
|
key.inter = LWO::IT_LINE;
|
||||||
|
break;
|
||||||
|
case AI_LWO_TCB:
|
||||||
|
key.inter = LWO::IT_TCB;
|
||||||
|
break;
|
||||||
|
case AI_LWO_HERM:
|
||||||
|
key.inter = LWO::IT_HERM;
|
||||||
|
break;
|
||||||
|
case AI_LWO_BEZI:
|
||||||
|
key.inter = LWO::IT_BEZI;
|
||||||
|
break;
|
||||||
|
case AI_LWO_BEZ2:
|
||||||
|
key.inter = LWO::IT_BEZ2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Unknown interval interpolation mode");
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo ... read params
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Encountered unknown ENVL subchunk");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// regardless how much we did actually read, go to the next chunk
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Load file - master function
|
// Load file - master function
|
||||||
void LWOImporter::LoadLWO2File() {
|
void LWOImporter::LoadLWO2File() {
|
||||||
|
@ -1272,16 +1450,25 @@ void LWOImporter::LoadLWO2File() {
|
||||||
|
|
||||||
LE_NCONST uint8_t *const end = mFileBuffer + fileSize;
|
LE_NCONST uint8_t *const end = mFileBuffer + fileSize;
|
||||||
unsigned int iUnnamed = 0;
|
unsigned int iUnnamed = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break;
|
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break;
|
||||||
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
|
||||||
|
int bufOffset = 0;
|
||||||
|
if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
if (mFileBuffer + head.length > end) {
|
if (mFileBuffer + head.length > end) {
|
||||||
throw DeadlyImportError("LWO2: Chunk length points behind the file");
|
throw DeadlyImportError("LWO2: Chunk length points behind the file");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint8_t *const next = mFileBuffer + head.length;
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
if (!head.length) {
|
if (!head.length) {
|
||||||
mFileBuffer = next;
|
mFileBuffer = next;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1337,7 +1524,6 @@ void LWOImporter::LoadLWO2File() {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vertex list
|
// vertex list
|
||||||
case AI_LWO_PNTS: {
|
case AI_LWO_PNTS: {
|
||||||
if (skip)
|
if (skip)
|
||||||
|
@ -1399,19 +1585,29 @@ void LWOImporter::LoadLWO2File() {
|
||||||
|
|
||||||
// surface chunk
|
// surface chunk
|
||||||
case AI_LWO_SURF: {
|
case AI_LWO_SURF: {
|
||||||
LoadLWO2Surface(head.length);
|
if( mIsLWO3 )
|
||||||
|
LoadLWO3Surface(head.length);
|
||||||
|
else
|
||||||
|
LoadLWO2Surface(head.length);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clip chunk
|
// clip chunk
|
||||||
case AI_LWO_CLIP: {
|
case AI_LWO_CLIP: {
|
||||||
LoadLWO2Clip(head.length);
|
if( mIsLWO3 )
|
||||||
|
LoadLWO3Clip(head.length);
|
||||||
|
else
|
||||||
|
LoadLWO2Clip(head.length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// envelope chunk
|
// envelope chunk
|
||||||
case AI_LWO_ENVL: {
|
case AI_LWO_ENVL: {
|
||||||
LoadLWO2Envelope(head.length);
|
if( mIsLWO3 )
|
||||||
|
LoadLWO3Envelope(head.length);
|
||||||
|
else
|
||||||
|
LoadLWO2Envelope(head.length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,8 @@ private:
|
||||||
*/
|
*/
|
||||||
inline void GetS0(std::string &out, unsigned int max);
|
inline void GetS0(std::string &out, unsigned int max);
|
||||||
inline float GetF4();
|
inline float GetF4();
|
||||||
|
inline float GetF8();
|
||||||
|
inline uint64_t GetU8();
|
||||||
inline uint32_t GetU4();
|
inline uint32_t GetU4();
|
||||||
inline uint16_t GetU2();
|
inline uint16_t GetU2();
|
||||||
inline uint8_t GetU1();
|
inline uint8_t GetU1();
|
||||||
|
@ -131,6 +133,7 @@ private:
|
||||||
* @param size Maximum size to be read, in bytes.
|
* @param size Maximum size to be read, in bytes.
|
||||||
*/
|
*/
|
||||||
void LoadLWO2Surface(unsigned int size);
|
void LoadLWO2Surface(unsigned int size);
|
||||||
|
void LoadLWO3Surface(unsigned int size);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Loads a texture block from a LWO2 file.
|
/** Loads a texture block from a LWO2 file.
|
||||||
|
@ -197,12 +200,23 @@ private:
|
||||||
* @param length Size of the chunk
|
* @param length Size of the chunk
|
||||||
*/
|
*/
|
||||||
void LoadLWO2Clip(unsigned int length);
|
void LoadLWO2Clip(unsigned int length);
|
||||||
|
void LoadLWO3Clip(unsigned int length);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Load an envelope from an EVL chunk
|
/** Load an envelope from an EVL chunk
|
||||||
* @param length Size of the chunk
|
* @param length Size of the chunk
|
||||||
*/
|
*/
|
||||||
void LoadLWO2Envelope(unsigned int length);
|
void LoadLWO2Envelope(unsigned int length);
|
||||||
|
void LoadLWO3Envelope(unsigned int length);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Load an nodal blocks from surface form
|
||||||
|
* @param length Size of the chunk
|
||||||
|
*/
|
||||||
|
void LoadNodalBlocks(unsigned int length);
|
||||||
|
void LoadNodes(unsigned int length);
|
||||||
|
void LoadNodeTag(unsigned int length);
|
||||||
|
void LoadNodeData(unsigned int length);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Count vertices and faces in a LWOB/LWO2 file
|
/** Count vertices and faces in a LWOB/LWO2 file
|
||||||
|
@ -347,6 +361,8 @@ protected:
|
||||||
/** true if the file is a LXOB file*/
|
/** true if the file is a LXOB file*/
|
||||||
bool mIsLXOB;
|
bool mIsLXOB;
|
||||||
|
|
||||||
|
bool mIsLWO3;
|
||||||
|
|
||||||
/** Temporary list of layers from the file */
|
/** Temporary list of layers from the file */
|
||||||
LayerList *mLayers;
|
LayerList *mLayers;
|
||||||
|
|
||||||
|
@ -400,6 +416,22 @@ inline float LWOImporter::GetF4() {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float LWOImporter::GetF8() {
|
||||||
|
double f;
|
||||||
|
::memcpy(&f, mFileBuffer, 8);
|
||||||
|
mFileBuffer += 8;
|
||||||
|
AI_LSWAP8(f);
|
||||||
|
return (float)f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t LWOImporter::GetU8() {
|
||||||
|
uint64_t f;
|
||||||
|
::memcpy(&f, mFileBuffer, 8);
|
||||||
|
mFileBuffer += 8;
|
||||||
|
AI_LSWAP8(f);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
inline uint32_t LWOImporter::GetU4() {
|
inline uint32_t LWOImporter::GetU4() {
|
||||||
uint32_t f;
|
uint32_t f;
|
||||||
|
|
|
@ -159,7 +159,7 @@ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTex
|
||||||
|
|
||||||
// The older LWOB format does not use indirect references to clips.
|
// The older LWOB format does not use indirect references to clips.
|
||||||
// The file name of a texture is directly specified in the tex chunk.
|
// The file name of a texture is directly specified in the tex chunk.
|
||||||
if (mIsLWO2) {
|
if (mIsLWO2 || mIsLWO3) {
|
||||||
// find the corresponding clip (take the last one if multiple
|
// find the corresponding clip (take the last one if multiple
|
||||||
// share the same index)
|
// share the same index)
|
||||||
ClipList::iterator end = mClips.end(), candidate = end;
|
ClipList::iterator end = mClips.end(), candidate = end;
|
||||||
|
@ -270,7 +270,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
|
||||||
aiShadingMode m;
|
aiShadingMode m;
|
||||||
if (surf.mSpecularValue && surf.mGlossiness) {
|
if (surf.mSpecularValue && surf.mGlossiness) {
|
||||||
float fGloss;
|
float fGloss;
|
||||||
if (mIsLWO2) {
|
if (mIsLWO2 || mIsLWO3) {
|
||||||
fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0));
|
fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0));
|
||||||
} else {
|
} else {
|
||||||
if (16.0 >= surf.mGlossiness)
|
if (16.0 >= surf.mGlossiness)
|
||||||
|
@ -688,6 +688,252 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/,
|
||||||
surf.mShaders.push_back(shader);
|
surf.mShaders.push_back(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadNodalBlocks(unsigned int size) {
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset = 0;
|
||||||
|
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: cannot read length; LoadNodalBlocks");
|
||||||
|
}
|
||||||
|
int node_idx = 0;
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_NNDS:
|
||||||
|
node_idx++;
|
||||||
|
LoadNodes(head.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadNodes(unsigned int size) {
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset = 0;
|
||||||
|
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: cannot read length; LoadNodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_NTAG:
|
||||||
|
LoadNodeTag(head.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadNodeTag(unsigned int size) {
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset = 0;
|
||||||
|
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: cannot read length; LoadNodeTag");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
|
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_NDTA:
|
||||||
|
LoadNodeData(head.length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadNodeData(unsigned int size) {
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||||
|
|
||||||
|
LWO::Surface &surf = mSurfaces->back();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset = 0;
|
||||||
|
if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: INVALID LENGTH; LoadNodeData");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_VERS:
|
||||||
|
case AI_LWO_ENUM:
|
||||||
|
case AI_LWO_IBGC:
|
||||||
|
case AI_LWO_IOPC:
|
||||||
|
case AI_LWO_IIMG:
|
||||||
|
case AI_LWO_TXTR:
|
||||||
|
case AI_LWO_IFAL:
|
||||||
|
case AI_LWO_ISCL:
|
||||||
|
case AI_LWO_IPOS:
|
||||||
|
case AI_LWO_IROT:
|
||||||
|
case AI_LWO_IBMP:
|
||||||
|
case AI_LWO_IUTD:
|
||||||
|
case AI_LWO_IVTD:
|
||||||
|
|
||||||
|
case AI_LWO_IPIX:
|
||||||
|
case AI_LWO_IMIP:
|
||||||
|
case AI_LWO_IMOD:
|
||||||
|
case AI_LWO_AMOD:
|
||||||
|
case AI_LWO_IINV:
|
||||||
|
case AI_LWO_INCR:
|
||||||
|
case AI_LWO_IAXS:
|
||||||
|
case AI_LWO_IFOT:
|
||||||
|
case AI_LWO_ITIM:
|
||||||
|
case AI_LWO_IWRL:
|
||||||
|
case AI_LWO_IUTI:
|
||||||
|
case AI_LWO_IUVI:
|
||||||
|
case AI_LWO_IINX:
|
||||||
|
case AI_LWO_IINY:
|
||||||
|
case AI_LWO_IINZ:
|
||||||
|
case AI_LWO_IREF:
|
||||||
|
case AI_LWO_IMST:
|
||||||
|
case AI_LWO_IMAP:
|
||||||
|
case AI_LWO_IUTL:
|
||||||
|
case AI_LWO_IVTL:
|
||||||
|
case AI_LWO_VPVL:
|
||||||
|
case AI_LWO_VPRM:
|
||||||
|
mFileBuffer = next;
|
||||||
|
break;
|
||||||
|
case AI_LWO_ENTR:
|
||||||
|
std::string attrName;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= next)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head1 = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset1 = 0;
|
||||||
|
if (head1.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head1 = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset1 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head1.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: cannot read length;");
|
||||||
|
}
|
||||||
|
uint8_t *const next1 = mFileBuffer + head1.length;
|
||||||
|
mFileBuffer += bufOffset1;
|
||||||
|
|
||||||
|
switch (head1.type) {
|
||||||
|
case AI_LWO_FLAG:
|
||||||
|
case AI_LWO_TAG:
|
||||||
|
mFileBuffer = next1;
|
||||||
|
break;
|
||||||
|
case AI_LWO_NAME:
|
||||||
|
GetS0(attrName, head1.length);
|
||||||
|
break;
|
||||||
|
case AI_LWO_VALU:
|
||||||
|
mFileBuffer += 8;
|
||||||
|
|
||||||
|
std::string valueType;
|
||||||
|
GetS0(valueType, 8);
|
||||||
|
|
||||||
|
if (valueType == "int") {
|
||||||
|
static_cast<void>(GetU4());
|
||||||
|
} else if (valueType == "double") {
|
||||||
|
static_cast<void>(GetU8());
|
||||||
|
} else if (valueType == "vparam") {
|
||||||
|
mFileBuffer += 24;
|
||||||
|
|
||||||
|
float value = GetF8();
|
||||||
|
if (attrName == "Diffuse") {
|
||||||
|
surf.mDiffuseValue = value;
|
||||||
|
} else if (attrName == "Specular") {
|
||||||
|
surf.mSpecularValue = value;
|
||||||
|
} else if (attrName == "Transparency") {
|
||||||
|
surf.mTransparency = value;
|
||||||
|
} else if (attrName == "Glossiness") {
|
||||||
|
surf.mGlossiness = value;
|
||||||
|
} else if (attrName == "Luminosity") {
|
||||||
|
surf.mLuminosity = value;
|
||||||
|
} else if (attrName == "Color Highlight") {
|
||||||
|
surf.mColorHighlights = value;
|
||||||
|
} else if (attrName == "Refraction Index") {
|
||||||
|
surf.mIOR = value;
|
||||||
|
} else if (attrName == "Bump Height") {
|
||||||
|
surf.mBumpIntensity = value;
|
||||||
|
}
|
||||||
|
} else if (valueType == "vparam3") {
|
||||||
|
mFileBuffer += 24;
|
||||||
|
|
||||||
|
float value1, value2, value3;
|
||||||
|
value1 = GetF8();
|
||||||
|
value2 = GetF8();
|
||||||
|
value3 = GetF8();
|
||||||
|
|
||||||
|
if (attrName == "Color") {
|
||||||
|
surf.mColor.r = value1;
|
||||||
|
surf.mColor.g = value2;
|
||||||
|
surf.mColor.b = value3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFileBuffer = next1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWO2Surface(unsigned int size) {
|
void LWOImporter::LoadLWO2Surface(unsigned int size) {
|
||||||
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
LE_NCONST uint8_t *const end = mFileBuffer + size;
|
||||||
|
@ -841,4 +1087,69 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LWOImporter::LoadLWO3Surface(unsigned int size) {
|
||||||
|
mFileBuffer += 8;
|
||||||
|
LE_NCONST uint8_t *const end = mFileBuffer + size - 12;
|
||||||
|
|
||||||
|
mSurfaces->push_back(LWO::Surface());
|
||||||
|
LWO::Surface &surf = mSurfaces->back();
|
||||||
|
|
||||||
|
GetS0(surf.mName, size);
|
||||||
|
|
||||||
|
// check whether this surface was derived from any other surface
|
||||||
|
std::string derived;
|
||||||
|
GetS0(derived, (unsigned int)(end - mFileBuffer));
|
||||||
|
if (derived.length()) {
|
||||||
|
// yes, find this surface
|
||||||
|
for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) {
|
||||||
|
if ((*it).mName == derived) {
|
||||||
|
// we have it ...
|
||||||
|
surf = *it;
|
||||||
|
derived.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (derived.size()) {
|
||||||
|
ASSIMP_LOG_WARN("LWO3: Unable to find source surface: ", derived);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
if (mFileBuffer + 8 >= end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
|
||||||
|
int bufOffset = 0;
|
||||||
|
if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form
|
||||||
|
mFileBuffer -= 8;
|
||||||
|
head = IFF::LoadForm(mFileBuffer);
|
||||||
|
bufOffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFileBuffer + head.length > end) {
|
||||||
|
throw DeadlyImportError("LWO3: cannot read length; LoadLWO3Surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *const next = mFileBuffer + head.length;
|
||||||
|
mFileBuffer += bufOffset;
|
||||||
|
switch (head.type) {
|
||||||
|
case AI_LWO_NODS:
|
||||||
|
LoadNodalBlocks(head.length);
|
||||||
|
break;
|
||||||
|
// polygon sidedness
|
||||||
|
case AI_LWO_SIDE: {
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2);
|
||||||
|
surf.bDoubleSided = (3 == GetU2());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// maximum smoothing angle
|
||||||
|
case AI_LWO_SMAN: {
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4);
|
||||||
|
surf.mMaximumSmoothAngle = std::fabs(GetF4());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
|
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
|
||||||
|
|
|
@ -117,6 +117,7 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
|
||||||
unsigned int processed = 0;
|
unsigned int processed = 0;
|
||||||
size_t lastFilePos(0);
|
size_t lastFilePos(0);
|
||||||
|
|
||||||
|
bool insideCstype = false;
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
while (streamBuffer.getNextDataLine(buffer, '\\')) {
|
while (streamBuffer.getNextDataLine(buffer, '\\')) {
|
||||||
m_DataIt = buffer.begin();
|
m_DataIt = buffer.begin();
|
||||||
|
@ -131,6 +132,18 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
|
||||||
m_progress->UpdateFileRead(processed, progressTotal);
|
m_progress->UpdateFileRead(processed, progressTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle cstype section end (http://paulbourke.net/dataformats/obj/)
|
||||||
|
if (insideCstype) {
|
||||||
|
switch (*m_DataIt) {
|
||||||
|
case 'e': {
|
||||||
|
std::string name;
|
||||||
|
getNameNoSpace(m_DataIt, m_DataItEnd, name);
|
||||||
|
insideCstype = name != "end";
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
goto pf_skip_line;
|
||||||
|
}
|
||||||
|
|
||||||
// parse line
|
// parse line
|
||||||
switch (*m_DataIt) {
|
switch (*m_DataIt) {
|
||||||
case 'v': // Parse a vertex texture coordinate
|
case 'v': // Parse a vertex texture coordinate
|
||||||
|
@ -219,6 +232,14 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
|
||||||
getObjectName();
|
getObjectName();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case 'c': // handle cstype section start
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
getNameNoSpace(m_DataIt, m_DataItEnd, name);
|
||||||
|
insideCstype = name == "cstype";
|
||||||
|
goto pf_skip_line;
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
pf_skip_line:
|
pf_skip_line:
|
||||||
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
|
||||||
|
|
|
@ -35,6 +35,17 @@ struct SubChunkHeader
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! Describes an IFF form header
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct FormHeader
|
||||||
|
{
|
||||||
|
//! Length of the chunk data, in bytes
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
|
//! Type of the chunk header - FourCC
|
||||||
|
uint32_t type;
|
||||||
|
};
|
||||||
|
|
||||||
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
|
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
|
||||||
((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
|
((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
|
||||||
|
@ -77,6 +88,24 @@ inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//! Load a chunk header
|
||||||
|
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||||
|
//! @return Copy of the chunk header
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
inline ChunkHeader LoadForm(uint8_t*& outFile)
|
||||||
|
{
|
||||||
|
ChunkHeader head;
|
||||||
|
outFile += 4;
|
||||||
|
::memcpy(&head.length, outFile, 4);
|
||||||
|
outFile += 4;
|
||||||
|
::memcpy(&head.type, outFile, 4);
|
||||||
|
|
||||||
|
AI_LSWAP4(head.length);
|
||||||
|
AI_LSWAP4(head.type);
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
//! Read the file header and return the type of the file and its size
|
//! Read the file header and return the type of the file and its size
|
||||||
//! @param outFile Pointer to the file data. The buffer must at
|
//! @param outFile Pointer to the file data. The buffer must at
|
||||||
|
|
|
@ -122,15 +122,15 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) {
|
||||||
voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) {
|
voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) {
|
||||||
ZipFile *io_stream = (ZipFile *)stream;
|
ZipFile *io_stream = (ZipFile *)stream;
|
||||||
voidpf ret = NULL;
|
voidpf ret = NULL;
|
||||||
size_t i;
|
int i;
|
||||||
|
|
||||||
char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1);
|
char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1);
|
||||||
strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1);
|
strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1);
|
||||||
for (i = io_stream->m_Filename.length() - 1; i >= 0; i -= 1)
|
for (i = (int)io_stream->m_Filename.length() - 1; i >= 0; i -= 1)
|
||||||
{
|
{
|
||||||
if (disk_filename[i] != '.')
|
if (disk_filename[i] != '.')
|
||||||
continue;
|
continue;
|
||||||
snprintf(&disk_filename[i], io_stream->m_Filename.length() - i, ".z%02u", number_disk + 1);
|
snprintf(&disk_filename[i], io_stream->m_Filename.length() - size_t(i), ".z%02u", number_disk + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -331,7 +331,7 @@ enum aiTextureType {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN
|
#define AI_TEXTURE_TYPE_MAX aiTextureType_TRANSMISSION
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Get a string for a given aiTextureType
|
// Get a string for a given aiTextureType
|
||||||
|
|
|
@ -130,7 +130,54 @@ AI_FORCE_INLINE aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
AI_FORCE_INLINE aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
// Specialisation for a single bool.
|
||||||
|
// Casts floating point and integer to bool
|
||||||
|
template <>
|
||||||
|
AI_FORCE_INLINE
|
||||||
|
aiReturn
|
||||||
|
aiMaterial::Get(const char *pKey, unsigned int type,
|
||||||
|
unsigned int idx, bool &pOut) const {
|
||||||
|
const aiMaterialProperty *prop;
|
||||||
|
const aiReturn ret = ::aiGetMaterialProperty(this, pKey, type, idx,
|
||||||
|
(const aiMaterialProperty **)&prop);
|
||||||
|
if (AI_SUCCESS == ret) {
|
||||||
|
|
||||||
|
switch (prop->mType) {
|
||||||
|
// Type cannot be converted
|
||||||
|
default: return AI_FAILURE;
|
||||||
|
|
||||||
|
case aiPTI_Buffer: {
|
||||||
|
// Native bool value storage
|
||||||
|
if (prop->mDataLength < sizeof(bool)) {
|
||||||
|
return AI_FAILURE;
|
||||||
|
}
|
||||||
|
::memcpy(&pOut, prop->mData, sizeof(bool));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case aiPTI_Float:
|
||||||
|
case aiPTI_Double: {
|
||||||
|
// Read as float and cast to bool
|
||||||
|
float value = 0.0f;
|
||||||
|
if (AI_SUCCESS == ::aiGetMaterialFloat(this, pKey, type, idx, &value)) {
|
||||||
|
pOut = static_cast<bool>(value);
|
||||||
|
return AI_SUCCESS;
|
||||||
|
}
|
||||||
|
return AI_FAILURE;
|
||||||
|
}
|
||||||
|
case aiPTI_Integer: {
|
||||||
|
// Cast to bool
|
||||||
|
const int value = static_cast<int>(*prop->mData);
|
||||||
|
pOut = static_cast<bool>(value);
|
||||||
|
return AI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
AI_FORCE_INLINE
|
||||||
|
aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||||
unsigned int idx,ai_real* pOut,
|
unsigned int idx,ai_real* pOut,
|
||||||
unsigned int* pMax) const {
|
unsigned int* pMax) const {
|
||||||
return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
|
return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
|
||||||
|
|
|
@ -61,7 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR AI_MATKEY_METALLIC_FACTOR
|
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR AI_MATKEY_METALLIC_FACTOR
|
||||||
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR AI_MATKEY_ROUGHNESS_FACTOR
|
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR AI_MATKEY_ROUGHNESS_FACTOR
|
||||||
|
|
||||||
//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
|
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS AI_MATKEY_GLOSSINESS_FACTOR
|
||||||
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR AI_MATKEY_GLOSSINESS_FACTOR
|
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR AI_MATKEY_GLOSSINESS_FACTOR
|
||||||
|
|
||||||
// Use AI_MATKEY_SHADING_MODEL == aiShadingMode_Unlit instead
|
// Use AI_MATKEY_SHADING_MODEL == aiShadingMode_Unlit instead
|
||||||
|
|
|
@ -125,13 +125,154 @@ TEST_F(MaterialSystemTest, testStringProperty) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
TEST_F(MaterialSystemTest, testMaterialNameAccess) {
|
TEST_F(MaterialSystemTest, testDefaultMaterialName) {
|
||||||
aiMaterial *mat = new aiMaterial();
|
aiString name = pcMat->GetName();
|
||||||
EXPECT_NE(nullptr, mat);
|
|
||||||
|
|
||||||
aiString name = mat->GetName();
|
|
||||||
const int retValue(strncmp(name.C_Str(), AI_DEFAULT_MATERIAL_NAME, name.length));
|
const int retValue(strncmp(name.C_Str(), AI_DEFAULT_MATERIAL_NAME, name.length));
|
||||||
EXPECT_EQ(0, retValue);
|
EXPECT_EQ(0, retValue);
|
||||||
|
|
||||||
delete mat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
TEST_F(MaterialSystemTest, testBoolProperty) {
|
||||||
|
const bool valTrue = true;
|
||||||
|
const bool valFalse = false;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valTrue, 1, "bool_true"));
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valFalse, 1, "bool_false"));
|
||||||
|
|
||||||
|
bool read = false;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_true", 0, 0, read));
|
||||||
|
EXPECT_TRUE(read) << "read true bool";
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_false", 0, 0, read));
|
||||||
|
EXPECT_FALSE(read) << "read false bool";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
TEST_F(MaterialSystemTest, testCastIntProperty) {
|
||||||
|
int value = 10;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "integer"));
|
||||||
|
value = 0;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
|
||||||
|
value = -1;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "negative"));
|
||||||
|
|
||||||
|
// To float
|
||||||
|
float valFloat = 0.0f;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valFloat));
|
||||||
|
EXPECT_EQ(10.0f, valFloat);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valFloat));
|
||||||
|
EXPECT_EQ(0.0f, valFloat);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valFloat));
|
||||||
|
EXPECT_EQ(-1.0f, valFloat);
|
||||||
|
|
||||||
|
// To bool
|
||||||
|
bool valBool = false;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(true, valBool);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(false, valBool);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(true, valBool);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
TEST_F(MaterialSystemTest, testCastFloatProperty) {
|
||||||
|
float value = 150392.63f;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float"));
|
||||||
|
value = 0;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
|
||||||
|
|
||||||
|
// To int
|
||||||
|
int valInt = 0.0f;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt));
|
||||||
|
EXPECT_EQ(150392, valInt);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt));
|
||||||
|
EXPECT_EQ(0, valInt);
|
||||||
|
|
||||||
|
// To bool
|
||||||
|
bool valBool = false;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(true, valBool);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(false, valBool);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
TEST_F(MaterialSystemTest, testCastSmallFloatProperty) {
|
||||||
|
float value = 0.0078125f;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float"));
|
||||||
|
value = 0;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero"));
|
||||||
|
|
||||||
|
// To int
|
||||||
|
int valInt = 0.0f;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt));
|
||||||
|
EXPECT_EQ(0, valInt);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt));
|
||||||
|
EXPECT_EQ(0, valInt);
|
||||||
|
|
||||||
|
// To bool
|
||||||
|
bool valBool = false;
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(true, valBool);
|
||||||
|
EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool));
|
||||||
|
EXPECT_EQ(false, valBool);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// Refuse to compile on Windows if any enum values are not explicitly handled in the switch
|
||||||
|
// TODO: Move this into assimp/Compiler as a macro and add clang/gcc versions so other code can use it
|
||||||
|
__pragma(warning(push));
|
||||||
|
__pragma(warning(error : 4061)); // enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label
|
||||||
|
__pragma(warning(error : 4062)); // enumerator 'identifier' in switch of enum 'enumeration' is not handled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_F(MaterialSystemTest, testMaterialTextureTypeEnum) {
|
||||||
|
// Verify that AI_TEXTURE_TYPE_MAX equals the largest 'real' value in the enum
|
||||||
|
|
||||||
|
int32_t maxTextureType = 0;
|
||||||
|
static constexpr int32_t bigNumber = 255;
|
||||||
|
EXPECT_GT(bigNumber, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX too large for valid enum test, increase bigNumber";
|
||||||
|
|
||||||
|
// Loop until a value larger than any enum
|
||||||
|
for (int32_t i = 0; i < bigNumber; ++i) {
|
||||||
|
aiTextureType texType = static_cast<aiTextureType>(i);
|
||||||
|
switch (texType) {
|
||||||
|
default: break;
|
||||||
|
#ifndef SWIG
|
||||||
|
case _aiTextureType_Force32Bit: break;
|
||||||
|
#endif
|
||||||
|
// All the real values
|
||||||
|
case aiTextureType_NONE:
|
||||||
|
case aiTextureType_DIFFUSE:
|
||||||
|
case aiTextureType_SPECULAR:
|
||||||
|
case aiTextureType_AMBIENT:
|
||||||
|
case aiTextureType_EMISSIVE:
|
||||||
|
case aiTextureType_HEIGHT:
|
||||||
|
case aiTextureType_NORMALS:
|
||||||
|
case aiTextureType_SHININESS:
|
||||||
|
case aiTextureType_OPACITY:
|
||||||
|
case aiTextureType_DISPLACEMENT:
|
||||||
|
case aiTextureType_LIGHTMAP:
|
||||||
|
case aiTextureType_REFLECTION:
|
||||||
|
case aiTextureType_BASE_COLOR:
|
||||||
|
case aiTextureType_NORMAL_CAMERA:
|
||||||
|
case aiTextureType_EMISSION_COLOR:
|
||||||
|
case aiTextureType_METALNESS:
|
||||||
|
case aiTextureType_DIFFUSE_ROUGHNESS:
|
||||||
|
case aiTextureType_AMBIENT_OCCLUSION:
|
||||||
|
case aiTextureType_SHEEN:
|
||||||
|
case aiTextureType_CLEARCOAT:
|
||||||
|
case aiTextureType_TRANSMISSION:
|
||||||
|
case aiTextureType_UNKNOWN:
|
||||||
|
if (i > maxTextureType)
|
||||||
|
maxTextureType = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(maxTextureType, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX macro must be equal to the largest valid aiTextureType_XXX";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
__pragma (warning(pop))
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue