Merge pull request #1804 from mydidimo/fbx_export_squashed
Initial FBX Export Support, sponsored by MyDidimo.pull/1814/head
commit
9287adb735
17
CREDITS
17
CREDITS
|
@ -157,12 +157,27 @@ Contributed ExportProperties interface
|
||||||
Contributed X File exporter
|
Contributed X File exporter
|
||||||
Contributed Step (stp) exporter
|
Contributed Step (stp) exporter
|
||||||
|
|
||||||
|
- Thomas Iorns (mesilliac)
|
||||||
|
Initial FBX Export support
|
||||||
|
|
||||||
For a more detailed list just check: https://github.com/assimp/assimp/network/members
|
For a more detailed list just check: https://github.com/assimp/assimp/network/members
|
||||||
|
|
||||||
Patreons:
|
|
||||||
|
========
|
||||||
|
Patreons
|
||||||
|
========
|
||||||
|
|
||||||
|
Huge thanks to our Patreons!
|
||||||
|
|
||||||
- migenius
|
- migenius
|
||||||
- Marcus
|
- Marcus
|
||||||
- Cort
|
- Cort
|
||||||
- elect
|
- elect
|
||||||
- Steffen
|
- Steffen
|
||||||
|
|
||||||
|
|
||||||
|
===================
|
||||||
|
Commercial Sponsors
|
||||||
|
===================
|
||||||
|
|
||||||
|
- MyDidimo (mydidimo.com): Sponsored development of FBX Export support
|
||||||
|
|
|
@ -522,6 +522,13 @@ ADD_ASSIMP_IMPORTER( FBX
|
||||||
FBXDeformer.cpp
|
FBXDeformer.cpp
|
||||||
FBXBinaryTokenizer.cpp
|
FBXBinaryTokenizer.cpp
|
||||||
FBXDocumentUtil.cpp
|
FBXDocumentUtil.cpp
|
||||||
|
FBXExporter.h
|
||||||
|
FBXExporter.cpp
|
||||||
|
FBXExportNode.h
|
||||||
|
FBXExportNode.cpp
|
||||||
|
FBXExportProperty.h
|
||||||
|
FBXExportProperty.cpp
|
||||||
|
FBXCommon.h
|
||||||
)
|
)
|
||||||
|
|
||||||
SET( PostProcessing_SRCS
|
SET( PostProcessing_SRCS
|
||||||
|
@ -641,7 +648,7 @@ ADD_ASSIMP_IMPORTER( X
|
||||||
XFileExporter.cpp
|
XFileExporter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_ASSIMP_IMPORTER(X3D
|
ADD_ASSIMP_IMPORTER( X3D
|
||||||
X3DExporter.cpp
|
X3DExporter.cpp
|
||||||
X3DExporter.hpp
|
X3DExporter.hpp
|
||||||
X3DImporter.cpp
|
X3DImporter.cpp
|
||||||
|
|
|
@ -97,6 +97,8 @@ void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportPropert
|
||||||
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
|
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
|
//void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -169,6 +171,11 @@ Exporter::ExportFormatEntry gExporters[] =
|
||||||
Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
|
Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
|
||||||
|
//Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||||
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
|
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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 FBXCommon.h
|
||||||
|
* Some useful constants and enums for dealing with FBX files.
|
||||||
|
*/
|
||||||
|
#ifndef AI_FBXCOMMON_H_INC
|
||||||
|
#define AI_FBXCOMMON_H_INC
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
|
||||||
|
namespace FBX
|
||||||
|
{
|
||||||
|
const std::string NULL_RECORD = { // 13 null bytes
|
||||||
|
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'
|
||||||
|
}; // who knows why
|
||||||
|
const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings
|
||||||
|
const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
|
||||||
|
const int64_t SECOND = 46186158000; // FBX's kTime unit
|
||||||
|
|
||||||
|
// rotation order. We'll probably use EulerXYZ for everything
|
||||||
|
enum RotOrder {
|
||||||
|
RotOrder_EulerXYZ = 0,
|
||||||
|
RotOrder_EulerXZY,
|
||||||
|
RotOrder_EulerYZX,
|
||||||
|
RotOrder_EulerYXZ,
|
||||||
|
RotOrder_EulerZXY,
|
||||||
|
RotOrder_EulerZYX,
|
||||||
|
|
||||||
|
RotOrder_SphericXYZ,
|
||||||
|
|
||||||
|
RotOrder_MAX // end-of-enum sentinel
|
||||||
|
};
|
||||||
|
|
||||||
|
// transformation inheritance method. Most of the time RSrs
|
||||||
|
enum TransformInheritance {
|
||||||
|
TransformInheritance_RrSs = 0,
|
||||||
|
TransformInheritance_RSrs,
|
||||||
|
TransformInheritance_Rrs,
|
||||||
|
|
||||||
|
TransformInheritance_MAX // end-of-enum sentinel
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#endif // AI_FBXCOMMON_H_INC
|
|
@ -215,24 +215,38 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
// attach geometry
|
// attach geometry
|
||||||
ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
|
ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
|
||||||
|
|
||||||
// now link the geometric transform inverse nodes,
|
// check if there will be any child nodes
|
||||||
|
const std::vector<const Connection*>& child_conns
|
||||||
|
= doc.GetConnectionsByDestinationSequenced( model->ID(), "Model" );
|
||||||
|
|
||||||
|
// if so, link the geometric transform inverse nodes
|
||||||
// before we attach any child nodes
|
// before we attach any child nodes
|
||||||
for( aiNode* postnode : post_nodes_chain ) {
|
if (child_conns.size()) {
|
||||||
ai_assert( postnode );
|
for( aiNode* postnode : post_nodes_chain ) {
|
||||||
|
ai_assert( postnode );
|
||||||
|
|
||||||
if ( last_parent != &parent ) {
|
if ( last_parent != &parent ) {
|
||||||
last_parent->mNumChildren = 1;
|
last_parent->mNumChildren = 1;
|
||||||
last_parent->mChildren = new aiNode*[ 1 ];
|
last_parent->mChildren = new aiNode*[ 1 ];
|
||||||
last_parent->mChildren[ 0 ] = postnode;
|
last_parent->mChildren[ 0 ] = postnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
postnode->mParent = last_parent;
|
||||||
|
last_parent = postnode;
|
||||||
|
|
||||||
|
new_abs_transform *= postnode->mTransformation;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
postnode->mParent = last_parent;
|
// free the nodes we allocated as we don't need them
|
||||||
last_parent = postnode;
|
Util::delete_fun<aiNode> deleter;
|
||||||
|
std::for_each(
|
||||||
new_abs_transform *= postnode->mTransformation;
|
post_nodes_chain.begin(),
|
||||||
|
post_nodes_chain.end(),
|
||||||
|
deleter
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach sub-nodes
|
// attach sub-nodes (if any)
|
||||||
ConvertNodes( model->ID(), *last_parent, new_abs_transform );
|
ConvertNodes( model->ID(), *last_parent, new_abs_transform );
|
||||||
|
|
||||||
if ( doc.Settings().readLights ) {
|
if ( doc.Settings().readLights ) {
|
||||||
|
@ -259,6 +273,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
Util::delete_fun<aiNode> deleter;
|
Util::delete_fun<aiNode> deleter;
|
||||||
std::for_each( nodes.begin(), nodes.end(), deleter );
|
std::for_each( nodes.begin(), nodes.end(), deleter );
|
||||||
std::for_each( nodes_chain.begin(), nodes_chain.end(), deleter );
|
std::for_each( nodes_chain.begin(), nodes_chain.end(), deleter );
|
||||||
|
std::for_each( post_nodes_chain.begin(), post_nodes_chain.end(), deleter );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#include "FBXExportNode.h"
|
||||||
|
#include "FBXCommon.h"
|
||||||
|
|
||||||
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
|
||||||
|
// AddP70<type> helpers... there's no usable pattern here,
|
||||||
|
// so all are defined as separate functions.
|
||||||
|
// Even "animatable" properties are often completely different
|
||||||
|
// from the standard (nonanimated) property definition,
|
||||||
|
// so they are specified with an 'A' suffix.
|
||||||
|
|
||||||
|
void FBX::Node::AddP70int(
|
||||||
|
const std::string& name, int32_t value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "int", "Integer", "", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70bool(
|
||||||
|
const std::string& name, bool value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "bool", "", "", int32_t(value));
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70double(
|
||||||
|
const std::string& name, double value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "double", "Number", "", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70numberA(
|
||||||
|
const std::string& name, double value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "Number", "", "A", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70color(
|
||||||
|
const std::string& name, double r, double g, double b
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "ColorRGB", "Color", "", r, g, b);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70colorA(
|
||||||
|
const std::string& name, double r, double g, double b
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "Color", "", "A", r, g, b);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70vector(
|
||||||
|
const std::string& name, double x, double y, double z
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "Vector3D", "Vector", "", x, y, z);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70vectorA(
|
||||||
|
const std::string& name, double x, double y, double z
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "Vector", "", "A", x, y, z);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70string(
|
||||||
|
const std::string& name, const std::string& value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "KString", "", "", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70enum(
|
||||||
|
const std::string& name, int32_t value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "enum", "", "", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::AddP70time(
|
||||||
|
const std::string& name, int64_t value
|
||||||
|
) {
|
||||||
|
FBX::Node n("P");
|
||||||
|
n.AddProperties(name, "KTime", "Time", "", value);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public member functions for writing to binary fbx
|
||||||
|
|
||||||
|
void FBX::Node::Dump(std::shared_ptr<Assimp::IOStream> outfile)
|
||||||
|
{
|
||||||
|
Assimp::StreamWriterLE outstream(outfile);
|
||||||
|
Dump(outstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::Dump(Assimp::StreamWriterLE &s)
|
||||||
|
{
|
||||||
|
// write header section (with placeholders for some things)
|
||||||
|
Begin(s);
|
||||||
|
|
||||||
|
// write properties
|
||||||
|
DumpProperties(s);
|
||||||
|
|
||||||
|
// go back and fill in property related placeholders
|
||||||
|
EndProperties(s, properties.size());
|
||||||
|
|
||||||
|
// write children
|
||||||
|
DumpChildren(s);
|
||||||
|
|
||||||
|
// finish, filling in end offset placeholder
|
||||||
|
End(s, !children.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::Begin(Assimp::StreamWriterLE &s)
|
||||||
|
{
|
||||||
|
// remember start pos so we can come back and write the end pos
|
||||||
|
this->start_pos = s.Tell();
|
||||||
|
|
||||||
|
// placeholders for end pos and property section info
|
||||||
|
s.PutU4(0); // end pos
|
||||||
|
s.PutU4(0); // number of properties
|
||||||
|
s.PutU4(0); // total property section length
|
||||||
|
|
||||||
|
// node name
|
||||||
|
s.PutU1(name.size()); // length of node name
|
||||||
|
s.PutString(name); // node name as raw bytes
|
||||||
|
|
||||||
|
// property data comes after here
|
||||||
|
this->property_start = s.Tell();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::DumpProperties(Assimp::StreamWriterLE& s)
|
||||||
|
{
|
||||||
|
for (auto &p : properties) {
|
||||||
|
p.Dump(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::DumpChildren(Assimp::StreamWriterLE& s)
|
||||||
|
{
|
||||||
|
for (FBX::Node& child : children) {
|
||||||
|
child.Dump(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndProperties(Assimp::StreamWriterLE &s)
|
||||||
|
{
|
||||||
|
EndProperties(s, properties.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndProperties(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
size_t num_properties
|
||||||
|
) {
|
||||||
|
if (num_properties == 0) { return; }
|
||||||
|
size_t pos = s.Tell();
|
||||||
|
ai_assert(pos > property_start);
|
||||||
|
size_t property_section_size = pos - property_start;
|
||||||
|
s.Seek(start_pos + 4);
|
||||||
|
s.PutU4(num_properties);
|
||||||
|
s.PutU4(property_section_size);
|
||||||
|
s.Seek(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::End(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool has_children
|
||||||
|
) {
|
||||||
|
// if there were children, add a null record
|
||||||
|
if (has_children) { s.PutString(FBX::NULL_RECORD); }
|
||||||
|
|
||||||
|
// now go back and write initial pos
|
||||||
|
this->end_pos = s.Tell();
|
||||||
|
s.Seek(start_pos);
|
||||||
|
s.PutU4(end_pos);
|
||||||
|
s.Seek(end_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static member functions
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
// TODO: optional zip compression!
|
||||||
|
void FBX::Node::WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
){
|
||||||
|
Node node(name);
|
||||||
|
node.Begin(s);
|
||||||
|
s.PutU1('d');
|
||||||
|
s.PutU4(v.size()); // number of elements
|
||||||
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
|
s.PutU4(v.size() * 8); // data size
|
||||||
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
|
||||||
|
node.EndProperties(s, 1);
|
||||||
|
node.End(s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
// TODO: optional zip compression!
|
||||||
|
void FBX::Node::WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
){
|
||||||
|
Node node(name);
|
||||||
|
node.Begin(s);
|
||||||
|
s.PutU1('i');
|
||||||
|
s.PutU4(v.size()); // number of elements
|
||||||
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
|
s.PutU4(v.size() * 4); // data size
|
||||||
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
|
||||||
|
node.EndProperties(s, 1);
|
||||||
|
node.End(s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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 FBXExportNode.h
|
||||||
|
* Declares the FBX::Node helper class for fbx export.
|
||||||
|
*/
|
||||||
|
#ifndef AI_FBXEXPORTNODE_H_INC
|
||||||
|
#define AI_FBXEXPORTNODE_H_INC
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#include "FBXExportProperty.h"
|
||||||
|
|
||||||
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace FBX {
|
||||||
|
class Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FBX::Node
|
||||||
|
{
|
||||||
|
public: // public data members
|
||||||
|
// TODO: accessors
|
||||||
|
std::string name; // node name
|
||||||
|
std::vector<FBX::Property> properties; // node properties
|
||||||
|
std::vector<FBX::Node> children; // child nodes
|
||||||
|
|
||||||
|
public: // constructors
|
||||||
|
Node() = default;
|
||||||
|
Node(const std::string& n) : name(n) {}
|
||||||
|
Node(const std::string& n, const FBX::Property &p)
|
||||||
|
: name(n)
|
||||||
|
{ properties.push_back(p); }
|
||||||
|
Node(const std::string& n, const std::vector<FBX::Property> &pv)
|
||||||
|
: name(n), properties(pv) {}
|
||||||
|
|
||||||
|
public: // functions to add properties or children
|
||||||
|
// add a single property to the node
|
||||||
|
template <typename T>
|
||||||
|
void AddProperty(T value) {
|
||||||
|
properties.emplace_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convenience function to add multiple properties at once
|
||||||
|
template <typename T, typename... More>
|
||||||
|
void AddProperties(T value, More... more) {
|
||||||
|
properties.emplace_back(value);
|
||||||
|
AddProperties(more...);
|
||||||
|
}
|
||||||
|
void AddProperties() {}
|
||||||
|
|
||||||
|
// add a child node directly
|
||||||
|
void AddChild(const Node& node) { children.push_back(node); }
|
||||||
|
|
||||||
|
// convenience function to add a child node with a single property
|
||||||
|
template <typename... More>
|
||||||
|
void AddChild(
|
||||||
|
const std::string& name,
|
||||||
|
More... more
|
||||||
|
) {
|
||||||
|
FBX::Node c(name);
|
||||||
|
c.AddProperties(more...);
|
||||||
|
children.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // support specifically for dealing with Properties70 nodes
|
||||||
|
|
||||||
|
// it really is simpler to make these all separate functions.
|
||||||
|
// the versions with 'A' suffixes are for animatable properties.
|
||||||
|
// those often follow a completely different format internally in FBX.
|
||||||
|
void AddP70int(const std::string& name, int32_t value);
|
||||||
|
void AddP70bool(const std::string& name, bool value);
|
||||||
|
void AddP70double(const std::string& name, double value);
|
||||||
|
void AddP70numberA(const std::string& name, double value);
|
||||||
|
void AddP70color(const std::string& name, double r, double g, double b);
|
||||||
|
void AddP70colorA(const std::string& name, double r, double g, double b);
|
||||||
|
void AddP70vector(const std::string& name, double x, double y, double z);
|
||||||
|
void AddP70vectorA(const std::string& name, double x, double y, double z);
|
||||||
|
void AddP70string(const std::string& name, const std::string& value);
|
||||||
|
void AddP70enum(const std::string& name, int32_t value);
|
||||||
|
void AddP70time(const std::string& name, int64_t value);
|
||||||
|
|
||||||
|
// template for custom P70 nodes.
|
||||||
|
// anything that doesn't fit in the above can be created manually.
|
||||||
|
template <typename... More>
|
||||||
|
void AddP70(
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& type,
|
||||||
|
const std::string& type2,
|
||||||
|
const std::string& flags,
|
||||||
|
More... more
|
||||||
|
) {
|
||||||
|
Node n("P");
|
||||||
|
n.AddProperties(name, type, type2, flags, more...);
|
||||||
|
AddChild(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // member functions for writing data to a file or stream
|
||||||
|
|
||||||
|
// write the full node as binary data to the given file or stream
|
||||||
|
void Dump(std::shared_ptr<Assimp::IOStream> outfile);
|
||||||
|
void Dump(Assimp::StreamWriterLE &s);
|
||||||
|
|
||||||
|
// these other functions are for writing data piece by piece.
|
||||||
|
// they must be used carefully.
|
||||||
|
// for usage examples see FBXExporter.cpp.
|
||||||
|
void Begin(Assimp::StreamWriterLE &s);
|
||||||
|
void DumpProperties(Assimp::StreamWriterLE& s);
|
||||||
|
void EndProperties(Assimp::StreamWriterLE &s);
|
||||||
|
void EndProperties(Assimp::StreamWriterLE &s, size_t num_properties);
|
||||||
|
void DumpChildren(Assimp::StreamWriterLE& s);
|
||||||
|
void End(Assimp::StreamWriterLE &s, bool has_children);
|
||||||
|
|
||||||
|
private: // data used for binary dumps
|
||||||
|
size_t start_pos; // starting position in stream
|
||||||
|
size_t end_pos; // ending position in stream
|
||||||
|
size_t property_start; // starting position of property section
|
||||||
|
|
||||||
|
public: // static member functions
|
||||||
|
|
||||||
|
// convenience function to create a node with a single property,
|
||||||
|
// and write it to the stream.
|
||||||
|
template <typename T>
|
||||||
|
static void WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const T value,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
) {
|
||||||
|
FBX::Property p(value);
|
||||||
|
FBX::Node node(name, p);
|
||||||
|
node.Dump(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
static void WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
);
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
static void WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#endif // AI_FBXEXPORTNODE_H_INC
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#include "FBXExportProperty.h"
|
||||||
|
|
||||||
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
|
||||||
|
|
||||||
|
// constructors for single element properties
|
||||||
|
|
||||||
|
FBX::Property::Property(bool v)
|
||||||
|
: type('C'), data(1)
|
||||||
|
{
|
||||||
|
data = {uint8_t(v)};
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(int16_t v) : type('Y'), data(2)
|
||||||
|
{
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
(reinterpret_cast<int16_t*>(d))[0] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(int32_t v) : type('I'), data(4)
|
||||||
|
{
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
(reinterpret_cast<int32_t*>(d))[0] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(float v) : type('F'), data(4)
|
||||||
|
{
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
(reinterpret_cast<float*>(d))[0] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(double v) : type('D'), data(8)
|
||||||
|
{
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
(reinterpret_cast<double*>(d))[0] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(int64_t v) : type('L'), data(8)
|
||||||
|
{
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
(reinterpret_cast<int64_t*>(d))[0] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// constructors for array-type properties
|
||||||
|
|
||||||
|
FBX::Property::Property(const char* c, bool raw)
|
||||||
|
: Property(std::string(c), raw)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// strings can either be saved as "raw" (R) data, or "string" (S) data
|
||||||
|
FBX::Property::Property(const std::string& s, bool raw)
|
||||||
|
: type(raw ? 'R' : 'S'), data(s.size())
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < s.size(); ++i) {
|
||||||
|
data[i] = uint8_t(s[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(const std::vector<uint8_t>& r)
|
||||||
|
: type('R'), data(r)
|
||||||
|
{}
|
||||||
|
|
||||||
|
FBX::Property::Property(const std::vector<int32_t>& va)
|
||||||
|
: type('i'), data(4*va.size())
|
||||||
|
{
|
||||||
|
int32_t* d = reinterpret_cast<int32_t*>(data.data());
|
||||||
|
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(const std::vector<double>& va)
|
||||||
|
: type('d'), data(8*va.size())
|
||||||
|
{
|
||||||
|
double* d = reinterpret_cast<double*>(data.data());
|
||||||
|
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
FBX::Property::Property(const aiMatrix4x4& vm)
|
||||||
|
: type('d'), data(8*16)
|
||||||
|
{
|
||||||
|
double* d = reinterpret_cast<double*>(data.data());
|
||||||
|
for (size_t c = 0; c < 4; ++c) {
|
||||||
|
for (size_t r = 0; r < 4; ++r) {
|
||||||
|
d[4*c+r] = vm[r][c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public member functions
|
||||||
|
|
||||||
|
size_t FBX::Property::size()
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case 'C': case 'Y': case 'I': case 'F': case 'D': case 'L':
|
||||||
|
return data.size() + 1;
|
||||||
|
case 'S': case 'R':
|
||||||
|
return data.size() + 5;
|
||||||
|
case 'i': case 'd':
|
||||||
|
return data.size() + 13;
|
||||||
|
default:
|
||||||
|
throw DeadlyExportError("Requested size on property of unknown type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
|
{
|
||||||
|
s.PutU1(type);
|
||||||
|
uint8_t* d;
|
||||||
|
size_t N;
|
||||||
|
switch (type) {
|
||||||
|
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(data.data()))); return;
|
||||||
|
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(data.data()))); return;
|
||||||
|
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(data.data()))); return;
|
||||||
|
case 'F': s.PutF4(*(reinterpret_cast<float*>(data.data()))); return;
|
||||||
|
case 'D': s.PutF8(*(reinterpret_cast<double*>(data.data()))); return;
|
||||||
|
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
|
||||||
|
case 'S':
|
||||||
|
case 'R':
|
||||||
|
s.PutU4(data.size());
|
||||||
|
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
|
||||||
|
return;
|
||||||
|
case 'i':
|
||||||
|
N = data.size() / 4;
|
||||||
|
s.PutU4(N); // number of elements
|
||||||
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
|
// TODO: compress if large?
|
||||||
|
s.PutU4(data.size()); // data size
|
||||||
|
d = data.data();
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 'd':
|
||||||
|
N = data.size() / 8;
|
||||||
|
s.PutU4(N); // number of elements
|
||||||
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
|
// TODO: compress if large?
|
||||||
|
s.PutU4(data.size()); // data size
|
||||||
|
d = data.data();
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
std::stringstream err;
|
||||||
|
err << "Tried to dump property with invalid type '";
|
||||||
|
err << type << "'!";
|
||||||
|
throw DeadlyExportError(err.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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 FBXExportProperty.h
|
||||||
|
* Declares the FBX::Property helper class for fbx export.
|
||||||
|
*/
|
||||||
|
#ifndef AI_FBXEXPORTPROPERTY_H_INC
|
||||||
|
#define AI_FBXEXPORTPROPERTY_H_INC
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
|
||||||
|
#include <assimp/types.h> // aiMatrix4x4
|
||||||
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <type_traits> // is_void
|
||||||
|
|
||||||
|
namespace FBX {
|
||||||
|
class Property;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** FBX::Property
|
||||||
|
*
|
||||||
|
* Holds a value of any of FBX's recognized types,
|
||||||
|
* each represented by a particular one-character code.
|
||||||
|
* C : 1-byte uint8, usually 0x00 or 0x01 to represent boolean false and true
|
||||||
|
* Y : 2-byte int16
|
||||||
|
* I : 4-byte int32
|
||||||
|
* F : 4-byte float
|
||||||
|
* D : 8-byte double
|
||||||
|
* L : 8-byte int64
|
||||||
|
* i : array of int32
|
||||||
|
* f : array of float
|
||||||
|
* d : array of double
|
||||||
|
* l : array of int64
|
||||||
|
* b : array of 1-byte booleans (0x00 or 0x01)
|
||||||
|
* S : string (array of 1-byte char)
|
||||||
|
* R : raw data (array of bytes)
|
||||||
|
*/
|
||||||
|
class FBX::Property
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors for basic types.
|
||||||
|
// all explicit to avoid accidental typecasting
|
||||||
|
explicit Property(bool v);
|
||||||
|
// TODO: determine if there is actually a byte type,
|
||||||
|
// or if this always means <bool>. 'C' seems to imply <char>,
|
||||||
|
// so possibly the above was intended to represent both.
|
||||||
|
explicit Property(int16_t v);
|
||||||
|
explicit Property(int32_t v);
|
||||||
|
explicit Property(float v);
|
||||||
|
explicit Property(double v);
|
||||||
|
explicit Property(int64_t v);
|
||||||
|
// strings can either be stored as 'R' (raw) or 'S' (string) type
|
||||||
|
explicit Property(const char* c, bool raw=false);
|
||||||
|
explicit Property(const std::string& s, bool raw=false);
|
||||||
|
explicit Property(const std::vector<uint8_t>& r);
|
||||||
|
explicit Property(const std::vector<int32_t>& va);
|
||||||
|
explicit Property(const std::vector<double>& va);
|
||||||
|
explicit Property(const aiMatrix4x4& vm);
|
||||||
|
|
||||||
|
// this will catch any type not defined above,
|
||||||
|
// so that we don't accidentally convert something we don't want.
|
||||||
|
// for example (const char*) --> (bool)... seriously wtf C++
|
||||||
|
template <class T>
|
||||||
|
explicit Property(T v) : type('X') {
|
||||||
|
static_assert(std::is_void<T>::value, "TRIED TO CREATE FBX PROPERTY WITH UNSUPPORTED TYPE, CHECK YOUR PROPERTY INSTANTIATION");
|
||||||
|
} // note: no line wrap so it appears verbatim on the compiler error
|
||||||
|
|
||||||
|
// the size of this property node in a binary file, in bytes
|
||||||
|
size_t size();
|
||||||
|
|
||||||
|
// write this property node as binary data to the given stream
|
||||||
|
void Dump(Assimp::StreamWriterLE &s);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char type;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#endif // AI_FBXEXPORTPROPERTY_H_INC
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, 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 FBXExporter.h
|
||||||
|
* Declares the exporter class to write a scene to an fbx file
|
||||||
|
*/
|
||||||
|
#ifndef AI_FBXEXPORTER_H_INC
|
||||||
|
#define AI_FBXEXPORTER_H_INC
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#include "FBXExportNode.h" // FBX::Node
|
||||||
|
|
||||||
|
#include <assimp/types.h>
|
||||||
|
//#include <assimp/material.h>
|
||||||
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <memory> // shared_ptr
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
|
||||||
|
struct aiScene;
|
||||||
|
struct aiNode;
|
||||||
|
//struct aiMaterial;
|
||||||
|
|
||||||
|
namespace Assimp
|
||||||
|
{
|
||||||
|
class IOSystem;
|
||||||
|
class IOStream;
|
||||||
|
class ExportProperties;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
/** Helper class to export a given scene to an FBX file. */
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
class FBXExporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Constructor for a specific scene to export
|
||||||
|
FBXExporter(const aiScene* pScene, const ExportProperties* pProperties);
|
||||||
|
|
||||||
|
// call one of these methods to export
|
||||||
|
void ExportBinary(const char* pFile, IOSystem* pIOSystem);
|
||||||
|
void ExportAscii(const char* pFile, IOSystem* pIOSystem);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool binary; // whether current export is in binary or ascii format
|
||||||
|
const aiScene* mScene; // the scene to export
|
||||||
|
const ExportProperties* mProperties; // currently unused
|
||||||
|
std::shared_ptr<IOStream> outfile; // file to write to
|
||||||
|
|
||||||
|
std::vector<FBX::Node> connections; // conection storage
|
||||||
|
|
||||||
|
std::vector<int64_t> mesh_uids;
|
||||||
|
std::vector<int64_t> material_uids;
|
||||||
|
std::map<const aiNode*,int64_t> node_uids;
|
||||||
|
|
||||||
|
// this crude unique-ID system is actually fine
|
||||||
|
int64_t last_uid = 999999;
|
||||||
|
int64_t generate_uid() { return ++last_uid; }
|
||||||
|
|
||||||
|
// binary files have a specific header and footer,
|
||||||
|
// in addition to the actual data
|
||||||
|
void WriteBinaryHeader();
|
||||||
|
void WriteBinaryFooter();
|
||||||
|
|
||||||
|
// WriteAllNodes does the actual export.
|
||||||
|
// It just calls all the Write<Section> methods below in order.
|
||||||
|
void WriteAllNodes();
|
||||||
|
|
||||||
|
// Methods to write individual sections.
|
||||||
|
// The order here matches the order inside an FBX file.
|
||||||
|
// Each method corresponds to a top-level FBX section,
|
||||||
|
// except WriteHeader which also includes some binary-only sections
|
||||||
|
// and WriteFooter which is binary data only.
|
||||||
|
void WriteHeaderExtension();
|
||||||
|
// WriteFileId(); // binary-only, included in WriteHeader
|
||||||
|
// WriteCreationTime(); // binary-only, included in WriteHeader
|
||||||
|
// WriteCreator(); // binary-only, included in WriteHeader
|
||||||
|
void WriteGlobalSettings();
|
||||||
|
void WriteDocuments();
|
||||||
|
void WriteReferences();
|
||||||
|
void WriteDefinitions();
|
||||||
|
void WriteObjects();
|
||||||
|
void WriteConnections();
|
||||||
|
// WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
void WriteModelNodes(
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
const aiNode* node,
|
||||||
|
int64_t parent_uid,
|
||||||
|
const std::map<std::string,int64_t>& bone_uids
|
||||||
|
);
|
||||||
|
void WriteModelNodes( // usually don't call this directly
|
||||||
|
StreamWriterLE& s,
|
||||||
|
const aiNode* node,
|
||||||
|
int64_t parent_uid,
|
||||||
|
const std::map<std::string,int64_t>& bone_uids,
|
||||||
|
std::vector<std::pair<std::string,aiVector3D>>& transform_chain
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
|
#endif // AI_FBXEXPORTER_H_INC
|
Loading…
Reference in New Issue