Merge branch 'master' into fbxexport_crashfix
commit
741be6f9db
|
@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
namespace FBX
|
namespace FBX
|
||||||
{
|
{
|
||||||
const std::string NULL_RECORD = { // 13 null bytes
|
const std::string NULL_RECORD = { // 13 null bytes
|
||||||
|
@ -80,7 +80,7 @@ namespace FBX
|
||||||
TransformInheritance_MAX // end-of-enum sentinel
|
TransformInheritance_MAX // end-of-enum sentinel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
#endif // AI_FBXCOMMON_H_INC
|
#endif // AI_FBXCOMMON_H_INC
|
||||||
|
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <sstream> // ostringstream
|
#include <sstream> // ostringstream
|
||||||
#include <memory> // shared_ptr
|
#include <memory> // shared_ptr
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
// AddP70<type> helpers... there's no usable pattern here,
|
// AddP70<type> helpers... there's no usable pattern here,
|
||||||
// so all are defined as separate functions.
|
// so all are defined as separate functions.
|
||||||
// Even "animatable" properties are often completely different
|
// Even "animatable" properties are often completely different
|
||||||
|
@ -369,7 +370,7 @@ void FBX::Node::EndBinary(
|
||||||
bool has_children
|
bool has_children
|
||||||
) {
|
) {
|
||||||
// if there were children, add a null record
|
// if there were children, add a null record
|
||||||
if (has_children) { s.PutString(FBX::NULL_RECORD); }
|
if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
|
||||||
|
|
||||||
// now go back and write initial pos
|
// now go back and write initial pos
|
||||||
this->end_pos = s.Tell();
|
this->end_pos = s.Tell();
|
||||||
|
@ -565,6 +566,6 @@ void FBX::Node::WritePropertyNode(
|
||||||
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
|
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
class Node;
|
class Node;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +265,7 @@ private: // static helper functions
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream> // ostringstream
|
#include <sstream> // ostringstream
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
// constructors for single element properties
|
// constructors for single element properties
|
||||||
|
|
||||||
FBX::Property::Property(bool v)
|
FBX::Property::Property(bool v)
|
||||||
|
@ -359,6 +359,6 @@ void FBX::Property::DumpAscii(std::ostream& s, int indent)
|
||||||
throw runtime_error(err.str());
|
throw runtime_error(err.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <type_traits> // is_void
|
#include <type_traits> // is_void
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
class Property;
|
class Property;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +124,7 @@ private:
|
||||||
char type;
|
char type;
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
#endif // AI_FBXEXPORTPROPERTY_H_INC
|
#endif // AI_FBXEXPORTPROPERTY_H_INC
|
||||||
|
|
|
@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "FBXExportNode.h"
|
#include "FBXExportNode.h"
|
||||||
#include "FBXExportProperty.h"
|
#include "FBXExportProperty.h"
|
||||||
#include "FBXCommon.h"
|
#include "FBXCommon.h"
|
||||||
|
#include "FBXUtil.h"
|
||||||
|
|
||||||
#include <assimp/version.h> // aiGetVersion
|
#include <assimp/version.h> // aiGetVersion
|
||||||
#include <assimp/IOSystem.hpp>
|
#include <assimp/IOSystem.hpp>
|
||||||
|
@ -73,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
|
const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
using namespace Assimp::FBX;
|
||||||
|
|
||||||
// some constants that we'll use for writing metadata
|
// some constants that we'll use for writing metadata
|
||||||
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
const std::string EXPORT_VERSION_STR = "7.4.0";
|
const std::string EXPORT_VERSION_STR = "7.4.0";
|
||||||
const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015
|
const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015
|
||||||
|
@ -92,11 +97,6 @@ namespace FBX {
|
||||||
";------------------------------------------------------------------";
|
";------------------------------------------------------------------";
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Assimp;
|
|
||||||
using namespace FBX;
|
|
||||||
|
|
||||||
namespace Assimp {
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Worker function for exporting a scene to binary FBX.
|
// Worker function for exporting a scene to binary FBX.
|
||||||
// Prototyped and registered in Exporter.cpp
|
// Prototyped and registered in Exporter.cpp
|
||||||
|
@ -121,6 +121,7 @@ namespace Assimp {
|
||||||
IOSystem* pIOSystem,
|
IOSystem* pIOSystem,
|
||||||
const aiScene* pScene,
|
const aiScene* pScene,
|
||||||
const ExportProperties* pProperties
|
const ExportProperties* pProperties
|
||||||
|
|
||||||
){
|
){
|
||||||
// initialize the exporter
|
// initialize the exporter
|
||||||
FBXExporter exporter(pScene, pProperties);
|
FBXExporter exporter(pScene, pProperties);
|
||||||
|
@ -1393,10 +1394,6 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
// FbxVideo - stores images used by textures.
|
// FbxVideo - stores images used by textures.
|
||||||
for (const auto &it : uid_by_image) {
|
for (const auto &it : uid_by_image) {
|
||||||
if (it.first.compare(0, 1, "*") == 0) {
|
|
||||||
// TODO: embedded textures
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
FBX::Node n("Video");
|
FBX::Node n("Video");
|
||||||
const int64_t& uid = it.second;
|
const int64_t& uid = it.second;
|
||||||
const std::string name = ""; // TODO: ... name???
|
const std::string name = ""; // TODO: ... name???
|
||||||
|
@ -1406,7 +1403,33 @@ void FBXExporter::WriteObjects ()
|
||||||
// TODO: get full path... relative path... etc... ugh...
|
// TODO: get full path... relative path... etc... ugh...
|
||||||
// for now just use the same path for everything,
|
// for now just use the same path for everything,
|
||||||
// and hopefully one of them will work out.
|
// and hopefully one of them will work out.
|
||||||
const std::string& path = it.first;
|
std::string path = it.first;
|
||||||
|
// try get embedded texture
|
||||||
|
const aiTexture* embedded_texture = mScene->GetEmbeddedTexture(it.first.c_str());
|
||||||
|
if (embedded_texture != nullptr) {
|
||||||
|
// change the path (use original filename, if available. If name is empty, concatenate texture index with file extension)
|
||||||
|
std::stringstream newPath;
|
||||||
|
if (embedded_texture->mFilename.length > 0) {
|
||||||
|
newPath << embedded_texture->mFilename.C_Str();
|
||||||
|
} else if (embedded_texture->achFormatHint[0]) {
|
||||||
|
int texture_index = std::stoi(path.substr(1, path.size() - 1));
|
||||||
|
newPath << texture_index << "." << embedded_texture->achFormatHint;
|
||||||
|
}
|
||||||
|
path = newPath.str();
|
||||||
|
// embed the texture
|
||||||
|
size_t texture_size = static_cast<size_t>(embedded_texture->mWidth * std::max(embedded_texture->mHeight, 1u));
|
||||||
|
if (binary) {
|
||||||
|
// embed texture as binary data
|
||||||
|
std::vector<uint8_t> tex_data;
|
||||||
|
tex_data.resize(texture_size);
|
||||||
|
memcpy(&tex_data[0], (char*)embedded_texture->pcData, texture_size);
|
||||||
|
n.AddChild("Content", tex_data);
|
||||||
|
} else {
|
||||||
|
// embed texture in base64 encoding
|
||||||
|
std::string encoded_texture = FBX::Util::EncodeBase64((char*)embedded_texture->pcData, texture_size);
|
||||||
|
n.AddChild("Content", encoded_texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
p.AddP70("Path", "KString", "XRefUrl", "", path);
|
p.AddP70("Path", "KString", "XRefUrl", "", path);
|
||||||
n.AddChild(p);
|
n.AddChild(p);
|
||||||
n.AddChild("UseMipMap", int32_t(0));
|
n.AddChild("UseMipMap", int32_t(0));
|
||||||
|
@ -1419,17 +1442,17 @@ void FBXExporter::WriteObjects ()
|
||||||
// referenced by material_index/texture_type pairs.
|
// referenced by material_index/texture_type pairs.
|
||||||
std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
|
std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
|
||||||
const std::map<aiTextureType,std::string> prop_name_by_tt = {
|
const std::map<aiTextureType,std::string> prop_name_by_tt = {
|
||||||
{aiTextureType_DIFFUSE, "DiffuseColor"},
|
{aiTextureType_DIFFUSE, "DiffuseColor"},
|
||||||
{aiTextureType_SPECULAR, "SpecularColor"},
|
{aiTextureType_SPECULAR, "SpecularColor"},
|
||||||
{aiTextureType_AMBIENT, "AmbientColor"},
|
{aiTextureType_AMBIENT, "AmbientColor"},
|
||||||
{aiTextureType_EMISSIVE, "EmissiveColor"},
|
{aiTextureType_EMISSIVE, "EmissiveColor"},
|
||||||
{aiTextureType_HEIGHT, "Bump"},
|
{aiTextureType_HEIGHT, "Bump"},
|
||||||
{aiTextureType_NORMALS, "NormalMap"},
|
{aiTextureType_NORMALS, "NormalMap"},
|
||||||
{aiTextureType_SHININESS, "ShininessExponent"},
|
{aiTextureType_SHININESS, "ShininessExponent"},
|
||||||
{aiTextureType_OPACITY, "TransparentColor"},
|
{aiTextureType_OPACITY, "TransparentColor"},
|
||||||
{aiTextureType_DISPLACEMENT, "DisplacementColor"},
|
{aiTextureType_DISPLACEMENT, "DisplacementColor"},
|
||||||
//{aiTextureType_LIGHTMAP, "???"},
|
//{aiTextureType_LIGHTMAP, "???"},
|
||||||
{aiTextureType_REFLECTION, "ReflectionColor"}
|
{aiTextureType_REFLECTION, "ReflectionColor"}
|
||||||
//{aiTextureType_UNKNOWN, ""}
|
//{aiTextureType_UNKNOWN, ""}
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
|
for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
|
||||||
|
|
|
@ -157,6 +157,66 @@ size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
|
||||||
return outLength;
|
return outLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char to_base64_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
char EncodeBase64(char byte)
|
||||||
|
{
|
||||||
|
return to_base64_string[(size_t)byte];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Encodes a block of 4 bytes to base64 encoding
|
||||||
|
*
|
||||||
|
* @param bytes Bytes to encode.
|
||||||
|
* @param out_string String to write encoded values to.
|
||||||
|
* @param string_pos Position in out_string.*/
|
||||||
|
void EncodeByteBlock(const char* bytes, std::string& out_string, size_t string_pos)
|
||||||
|
{
|
||||||
|
char b0 = (bytes[0] & 0xFC) >> 2;
|
||||||
|
char b1 = (bytes[0] & 0x03) << 4 | ((bytes[1] & 0xF0) >> 4);
|
||||||
|
char b2 = (bytes[1] & 0x0F) << 2 | ((bytes[2] & 0xC0) >> 6);
|
||||||
|
char b3 = (bytes[2] & 0x3F);
|
||||||
|
|
||||||
|
out_string[string_pos + 0] = EncodeBase64(b0);
|
||||||
|
out_string[string_pos + 1] = EncodeBase64(b1);
|
||||||
|
out_string[string_pos + 2] = EncodeBase64(b2);
|
||||||
|
out_string[string_pos + 3] = EncodeBase64(b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncodeBase64(const char* data, size_t length)
|
||||||
|
{
|
||||||
|
// calculate extra bytes needed to get a multiple of 3
|
||||||
|
size_t extraBytes = 3 - length % 3;
|
||||||
|
|
||||||
|
// number of base64 bytes
|
||||||
|
size_t encodedBytes = 4 * (length + extraBytes) / 3;
|
||||||
|
|
||||||
|
std::string encoded_string(encodedBytes, '=');
|
||||||
|
|
||||||
|
// read blocks of 3 bytes
|
||||||
|
for (size_t ib3 = 0; ib3 < length / 3; ib3++)
|
||||||
|
{
|
||||||
|
const size_t iByte = ib3 * 3;
|
||||||
|
const size_t iEncodedByte = ib3 * 4;
|
||||||
|
const char* currData = &data[iByte];
|
||||||
|
|
||||||
|
EncodeByteBlock(currData, encoded_string, iEncodedByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if size of data is not a multiple of 3, also encode the final bytes (and add zeros where needed)
|
||||||
|
if (extraBytes > 0)
|
||||||
|
{
|
||||||
|
char finalBytes[4] = { 0,0,0,0 };
|
||||||
|
memcpy(&finalBytes[0], &data[length - length % 3], length % 3);
|
||||||
|
|
||||||
|
const size_t iEncodedByte = encodedBytes - 4;
|
||||||
|
EncodeByteBlock(&finalBytes[0], encoded_string, iEncodedByte);
|
||||||
|
|
||||||
|
// add '=' at the end
|
||||||
|
for (size_t i = 0; i < 4 * extraBytes / 3; i++)
|
||||||
|
encoded_string[encodedBytes - i - 1] = '=';
|
||||||
|
}
|
||||||
|
return encoded_string;
|
||||||
|
}
|
||||||
|
|
||||||
} // !Util
|
} // !Util
|
||||||
} // !FBX
|
} // !FBX
|
||||||
} // !Assimp
|
} // !Assimp
|
||||||
|
|
|
@ -113,6 +113,15 @@ uint8_t DecodeBase64(char ch);
|
||||||
* @return size of the decoded data (number of bytes)*/
|
* @return size of the decoded data (number of bytes)*/
|
||||||
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
||||||
|
|
||||||
|
char EncodeBase64(char byte);
|
||||||
|
|
||||||
|
/** Encode bytes in base64-encoding
|
||||||
|
*
|
||||||
|
* @param data Binary data to encode.
|
||||||
|
* @param inLength Number of bytes to encode.
|
||||||
|
* @return base64-encoded string*/
|
||||||
|
std::string EncodeBase64(const char* data, size_t length);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,6 +389,14 @@ struct aiScene
|
||||||
|
|
||||||
//! Returns an embedded texture
|
//! Returns an embedded texture
|
||||||
const aiTexture* GetEmbeddedTexture(const char* filename) const {
|
const aiTexture* GetEmbeddedTexture(const char* filename) const {
|
||||||
|
// lookup using texture ID (if referenced like: "*1", "*2", etc.)
|
||||||
|
if ('*' == *filename) {
|
||||||
|
int index = std::atoi(filename + 1);
|
||||||
|
if (0 > index || mNumTextures <= static_cast<unsigned>(index))
|
||||||
|
return nullptr;
|
||||||
|
return mTextures[index];
|
||||||
|
}
|
||||||
|
// lookup using filename
|
||||||
const char* shortFilename = GetShortFilename(filename);
|
const char* shortFilename = GetShortFilename(filename);
|
||||||
for (unsigned int i = 0; i < mNumTextures; i++) {
|
for (unsigned int i = 0; i < mNumTextures; i++) {
|
||||||
const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str());
|
const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str());
|
||||||
|
|
Loading…
Reference in New Issue