diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c0de99b30..7ac14a920 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -418,6 +418,7 @@ SET(FBX_SRCS FBXNodeAttribute.cpp FBXDeformer.cpp FBXBinaryTokenizer.cpp + FBXDocumentUtil.cpp ) SOURCE_GROUP( FBX FILES ${FBX_SRCS}) diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 1151b5786..da8841d08 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -57,393 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { -namespace Util { - -// ------------------------------------------------------------------------------------------------ -// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. -void DOMError(const std::string& message, const Token& token) -{ - throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token)); -} - -// ------------------------------------------------------------------------------------------------ -void DOMError(const std::string& message, const Element* element /*= NULL*/) -{ - if(element) { - DOMError(message,element->KeyToken()); - } - throw DeadlyImportError("FBX-DOM " + message); -} - - -// ------------------------------------------------------------------------------------------------ -// print warning, do return -void DOMWarning(const std::string& message, const Token& token) -{ - if(DefaultLogger::get()) { - DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token)); - } -} - -// ------------------------------------------------------------------------------------------------ -void DOMWarning(const std::string& message, const Element* element /*= NULL*/) -{ - if(element) { - DOMWarning(message,element->KeyToken()); - return; - } - if(DefaultLogger::get()) { - DefaultLogger::get()->warn("FBX-DOM: " + message); - } -} - - -// ------------------------------------------------------------------------------------------------ -// extract required compound scope -const Scope& GetRequiredScope(const Element& el) -{ - const Scope* const s = el.Compound(); - if(!s) { - DOMError("expected compound scope",&el); - } - - return *s; -} - - -// ------------------------------------------------------------------------------------------------ -// get token at a particular index -const Token& GetRequiredToken(const Element& el, unsigned int index) -{ - const TokenList& t = el.Tokens(); - if(index >= t.size()) { - DOMError(Formatter::format( "missing token at index " ) << index,&el); - } - - return *t[index]; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsID() with DOMError handling -uint64_t ParseTokenAsID(const Token& t) -{ - const char* err; - const uint64_t i = ParseTokenAsID(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsDim() with DOMError handling -size_t ParseTokenAsDim(const Token& t) -{ - const char* err; - const size_t i = ParseTokenAsDim(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsFloat() with DOMError handling -float ParseTokenAsFloat(const Token& t) -{ - const char* err; - const float i = ParseTokenAsFloat(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsInt() with DOMError handling -int ParseTokenAsInt(const Token& t) -{ - const char* err; - const int i = ParseTokenAsInt(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - - -// ------------------------------------------------------------------------------------------------ -// wrapper around ParseTokenAsString() with DOMError handling -std::string ParseTokenAsString(const Token& t) -{ - const char* err; - const std::string& i = ParseTokenAsString(t,err); - if(err) { - DOMError(err,t); - } - return i; -} - -// ------------------------------------------------------------------------------------------------ -// extract a required element from a scope, abort if the element cannot be found -const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) -{ - const Element* el = sc[index]; - if(!el) { - DOMError("did not find required element \"" + index + "\"",element); - } - return *el; -} - -// XXX: tacke code duplication in the various ReadVectorDataArray() overloads below. -// could use a type traits based solution. - -// ------------------------------------------------------------------------------------------------ -// read an array of float3 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // may throw bad_alloc if the input is rubbish, but this need - // not to be prevented - importing would fail but we wouldn't - // crash since assimp handles this case properly. - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 3 != 0) { - DOMError("number of floats is not a multiple of three (3)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiVector3D v; - v.x = ParseTokenAsFloat(**it++); - v.y = ParseTokenAsFloat(**it++); - v.z = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of color4 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() above - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 4 != 0) { - DOMError("number of floats is not a multiple of four (4)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiColor4D v; - v.r = ParseTokenAsFloat(**it++); - v.g = ParseTokenAsFloat(**it++); - v.b = ParseTokenAsFloat(**it++); - v.a = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of float2 tuples -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() above - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - if (a.Tokens().size() % 2 != 0) { - DOMError("number of floats is not a multiple of two (2)",&el); - } - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - aiVector2D v; - v.x = ParseTokenAsFloat(**it++); - v.y = ParseTokenAsFloat(**it++); - - out.push_back(v); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of ints -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const int ival = ParseTokenAsInt(**it++); - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of floats -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const float ival = ParseTokenAsFloat(**it++); - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of uints -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const int ival = ParseTokenAsInt(**it++); - if(ival < 0) { - DOMError("encountered negative integer index"); - } - out.push_back(static_cast(ival)); - } -} - - -// ------------------------------------------------------------------------------------------------ -// read an array of uint64_ts -void ReadVectorDataArray(std::vector& out, const Element& el) -{ - out.clear(); - const TokenList& tok = el.Tokens(); - const size_t dim = ParseTokenAsDim(*tok[0]); - - // see notes in ReadVectorDataArray() - out.reserve(dim); - - const Scope& scope = GetRequiredScope(el); - const Element& a = GetRequiredElement(scope,"a",&el); - - for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { - const uint64_t ival = ParseTokenAsID(**it++); - - out.push_back(ival); - } -} - - -// ------------------------------------------------------------------------------------------------ -aiMatrix4x4 ReadMatrix(const Element& element) -{ - std::vector values; - ReadVectorDataArray(values,element); - - if(values.size() != 16) { - DOMError("expected 16 matrix elements"); - } - - aiMatrix4x4 result; - - - result.a1 = values[0]; - result.a2 = values[1]; - result.a3 = values[2]; - result.a4 = values[3]; - - result.b1 = values[4]; - result.b2 = values[5]; - result.b3 = values[6]; - result.b4 = values[7]; - - result.c1 = values[8]; - result.c2 = values[9]; - result.c3 = values[10]; - result.c4 = values[11]; - - result.d1 = values[12]; - result.d2 = values[13]; - result.d3 = values[14]; - result.d4 = values[15]; - - result.Transpose(); - return result; -} - - -// ------------------------------------------------------------------------------------------------ -// fetch a property table and the corresponding property template -boost::shared_ptr GetPropertyTable(const Document& doc, - const std::string& templateName, - const Element &element, - const Scope& sc) -{ - const Element* const Properties70 = sc["Properties70"]; - boost::shared_ptr templateProps = boost::shared_ptr( - static_cast(NULL)); - - if(templateName.length()) { - PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName); - if(it != doc.Templates().end()) { - templateProps = (*it).second; - } - } - - if(!Properties70) { - DOMWarning("material property table (Properties70) not found",&element); - if(templateProps) { - return templateProps; - } - else { - return boost::make_shared(); - } - } - return boost::make_shared(*Properties70,templateProps); -} -} // !Util using namespace Util; diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp new file mode 100644 index 000000000..7a2718a9a --- /dev/null +++ b/code/FBXDocumentUtil.cpp @@ -0,0 +1,448 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXDocumentUtil.cpp + * @brief Implementation of the FBX DOM utility functions declared in FBXDocumentUtil.h + */ +#include "AssimpPCH.h" + +#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER + +#include + +#include "FBXParser.h" +#include "FBXDocument.h" +#include "FBXUtil.h" +#include "FBXDocumentUtil.h" +#include "FBXProperties.h" + +namespace Assimp { +namespace FBX { +namespace Util { + +// ------------------------------------------------------------------------------------------------ +// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError. +void DOMError(const std::string& message, const Token& token) +{ + throw DeadlyImportError(Util::AddTokenText("FBX-DOM",message,&token)); +} + +// ------------------------------------------------------------------------------------------------ +void DOMError(const std::string& message, const Element* element /*= NULL*/) +{ + if(element) { + DOMError(message,element->KeyToken()); + } + throw DeadlyImportError("FBX-DOM " + message); +} + + +// ------------------------------------------------------------------------------------------------ +// print warning, do return +void DOMWarning(const std::string& message, const Token& token) +{ + if(DefaultLogger::get()) { + DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token)); + } +} + +// ------------------------------------------------------------------------------------------------ +void DOMWarning(const std::string& message, const Element* element /*= NULL*/) +{ + if(element) { + DOMWarning(message,element->KeyToken()); + return; + } + if(DefaultLogger::get()) { + DefaultLogger::get()->warn("FBX-DOM: " + message); + } +} + + +// ------------------------------------------------------------------------------------------------ +// extract required compound scope +const Scope& GetRequiredScope(const Element& el) +{ + const Scope* const s = el.Compound(); + if(!s) { + DOMError("expected compound scope",&el); + } + + return *s; +} + + +// ------------------------------------------------------------------------------------------------ +// get token at a particular index +const Token& GetRequiredToken(const Element& el, unsigned int index) +{ + const TokenList& t = el.Tokens(); + if(index >= t.size()) { + DOMError(Formatter::format( "missing token at index " ) << index,&el); + } + + return *t[index]; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsID() with DOMError handling +uint64_t ParseTokenAsID(const Token& t) +{ + const char* err; + const uint64_t i = ParseTokenAsID(t,err); + if(err) { + DOMError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsDim() with DOMError handling +size_t ParseTokenAsDim(const Token& t) +{ + const char* err; + const size_t i = ParseTokenAsDim(t,err); + if(err) { + DOMError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsFloat() with DOMError handling +float ParseTokenAsFloat(const Token& t) +{ + const char* err; + const float i = ParseTokenAsFloat(t,err); + if(err) { + DOMError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsInt() with DOMError handling +int ParseTokenAsInt(const Token& t) +{ + const char* err; + const int i = ParseTokenAsInt(t,err); + if(err) { + DOMError(err,t); + } + return i; +} + + +// ------------------------------------------------------------------------------------------------ +// wrapper around ParseTokenAsString() with DOMError handling +std::string ParseTokenAsString(const Token& t) +{ + const char* err; + const std::string& i = ParseTokenAsString(t,err); + if(err) { + DOMError(err,t); + } + return i; +} + +// ------------------------------------------------------------------------------------------------ +// extract a required element from a scope, abort if the element cannot be found +const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/) +{ + const Element* el = sc[index]; + if(!el) { + DOMError("did not find required element \"" + index + "\"",element); + } + return *el; +} + +// XXX: tacke code duplication in the various ReadVectorDataArray() overloads below. +// could use a type traits based solution. + +// ------------------------------------------------------------------------------------------------ +// read an array of float3 tuples +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // may throw bad_alloc if the input is rubbish, but this need + // not to be prevented - importing would fail but we wouldn't + // crash since assimp handles this case properly. + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 3 != 0) { + DOMError("number of floats is not a multiple of three (3)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiVector3D v; + v.x = ParseTokenAsFloat(**it++); + v.y = ParseTokenAsFloat(**it++); + v.z = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of color4 tuples +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() above + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 4 != 0) { + DOMError("number of floats is not a multiple of four (4)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiColor4D v; + v.r = ParseTokenAsFloat(**it++); + v.g = ParseTokenAsFloat(**it++); + v.b = ParseTokenAsFloat(**it++); + v.a = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of float2 tuples +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() above + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + if (a.Tokens().size() % 2 != 0) { + DOMError("number of floats is not a multiple of two (2)",&el); + } + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + aiVector2D v; + v.x = ParseTokenAsFloat(**it++); + v.y = ParseTokenAsFloat(**it++); + + out.push_back(v); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of ints +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const int ival = ParseTokenAsInt(**it++); + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of floats +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const float ival = ParseTokenAsFloat(**it++); + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of uints +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const int ival = ParseTokenAsInt(**it++); + if(ival < 0) { + DOMError("encountered negative integer index"); + } + out.push_back(static_cast(ival)); + } +} + + +// ------------------------------------------------------------------------------------------------ +// read an array of uint64_ts +void ReadVectorDataArray(std::vector& out, const Element& el) +{ + out.clear(); + const TokenList& tok = el.Tokens(); + const size_t dim = ParseTokenAsDim(*tok[0]); + + // see notes in ReadVectorDataArray() + out.reserve(dim); + + const Scope& scope = GetRequiredScope(el); + const Element& a = GetRequiredElement(scope,"a",&el); + + for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) { + const uint64_t ival = ParseTokenAsID(**it++); + + out.push_back(ival); + } +} + + +// ------------------------------------------------------------------------------------------------ +aiMatrix4x4 ReadMatrix(const Element& element) +{ + std::vector values; + ReadVectorDataArray(values,element); + + if(values.size() != 16) { + DOMError("expected 16 matrix elements"); + } + + aiMatrix4x4 result; + + + result.a1 = values[0]; + result.a2 = values[1]; + result.a3 = values[2]; + result.a4 = values[3]; + + result.b1 = values[4]; + result.b2 = values[5]; + result.b3 = values[6]; + result.b4 = values[7]; + + result.c1 = values[8]; + result.c2 = values[9]; + result.c3 = values[10]; + result.c4 = values[11]; + + result.d1 = values[12]; + result.d2 = values[13]; + result.d3 = values[14]; + result.d4 = values[15]; + + result.Transpose(); + return result; +} + + +// ------------------------------------------------------------------------------------------------ +// fetch a property table and the corresponding property template +boost::shared_ptr GetPropertyTable(const Document& doc, + const std::string& templateName, + const Element &element, + const Scope& sc) +{ + const Element* const Properties70 = sc["Properties70"]; + boost::shared_ptr templateProps = boost::shared_ptr( + static_cast(NULL)); + + if(templateName.length()) { + PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName); + if(it != doc.Templates().end()) { + templateProps = (*it).second; + } + } + + if(!Properties70) { + DOMWarning("material property table (Properties70) not found",&element); + if(templateProps) { + return templateProps; + } + else { + return boost::make_shared(); + } + } + return boost::make_shared(*Properties70,templateProps); +} +} // !Util +} // !FBX +} // !Assimp + +#endif diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 999d6cdaf..900c4b4b2 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -2087,6 +2087,10 @@ RelativePath="..\..\code\FBXDocument.h" > + +