Merge branch 'master' into kimkulling-patch-3

This commit is contained in:
Kim Kulling
2019-06-08 09:09:37 +02:00
committed by GitHub
163 changed files with 13041 additions and 5043 deletions
+9 -7
View File
@@ -249,13 +249,14 @@ void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene)
// Reads a new chunk from the file
void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut)
{
ai_assert(pcOut != NULL);
ai_assert(pcOut != nullptr);
pcOut->Flag = stream->GetI2();
pcOut->Size = stream->GetI4();
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) {
throw DeadlyImportError("Chunk is too large");
}
if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
ASSIMP_LOG_ERROR("3DS: Chunk overflow");
@@ -1343,15 +1344,16 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
// ------------------------------------------------------------------------------------------------
// Read a percentage chunk
ai_real Discreet3DSImporter::ParsePercentageChunk()
{
ai_real Discreet3DSImporter::ParsePercentageChunk() {
Discreet3DS::Chunk chunk;
ReadChunk(&chunk);
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag)
return stream->GetF4();
else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag)
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) {
return stream->GetF4() * ai_real(100) / ai_real(0xFFFF);
} else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) {
return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF;
}
return get_qnan();
}
+1 -1
View File
@@ -1299,7 +1299,7 @@ void ASEImporter::BuildMaterialIndices()
}
}
// Dekete our temporary array
// Delete our temporary array
delete[] pcIntMaterials;
}
-1
View File
@@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the ASE parser class
*/
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+5 -5
View File
@@ -188,10 +188,11 @@ struct Animation {
} mRotationType, mScalingType, mPositionType;
Animation() AI_NO_EXCEPT
: mRotationType (TRACK)
, mScalingType (TRACK)
, mPositionType (TRACK)
{}
: mRotationType (TRACK)
, mScalingType (TRACK)
, mPositionType (TRACK) {
// empty
}
//! List of track rotation keyframes
std::vector< aiQuatKey > akeyRotations;
@@ -243,7 +244,6 @@ struct BaseNode {
mTargetPosition.x = qnan;
}
//! Name of the mesh
std::string mName;
+2 -2
View File
@@ -68,7 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
static const aiImporterDesc desc = {
".assbin Importer",
"Assimp Binary Importer",
"Gargaj / Conspiracy",
"",
"",
@@ -708,7 +708,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
int res = uncompress( uncompressedData, &uncompressedSize, compressedData, len );
int res = uncompress( uncompressedData, &uncompressedSize, compressedData, (uLong) len );
if(res != Z_OK)
{
delete [] uncompressedData;
-2
View File
@@ -555,8 +555,6 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
mesh->mNormals[n].z);
}
}
else {
}
ioprintf(io,"\t\t</Normals>\n");
}
+1 -1
View File
@@ -416,7 +416,7 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
void operator ()(T& /*out*/,const char* = "") {
// obviously, it is crucial that _DefaultInitializer is used
// only from within a catch clause.
throw;
throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error");
}
};
+27
View File
@@ -1225,6 +1225,16 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
case Lamp::Type_Local:
out->mType = aiLightSource_POINT;
break;
case Lamp::Type_Spot:
out->mType = aiLightSource_SPOT;
// blender orients directional lights as facing toward -z
out->mDirection = aiVector3D(0.f, 0.f, -1.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f);
out->mAngleInnerCone = lamp->spotsize * (1.0f - lamp->spotblend);
out->mAngleOuterCone = lamp->spotsize;
break;
case Lamp::Type_Sun:
out->mType = aiLightSource_DIRECTIONAL;
@@ -1255,6 +1265,23 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
// If default values are supplied, compute the coefficients from light's max distance
// Read this: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
//
if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f)
{
out->mAttenuationConstant = 1.0f;
out->mAttenuationLinear = 2.0f / lamp->dist;
out->mAttenuationQuadratic = 1.0f / (lamp->dist * lamp->dist);
}
else
{
out->mAttenuationConstant = lamp->constant_coefficient;
out->mAttenuationLinear = lamp->linear_coefficient;
out->mAttenuationQuadratic = lamp->quadratic_coefficient;
}
return out.release();
}
+4 -1
View File
@@ -211,9 +211,12 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db);
ReadField<ErrorPolicy_Igno>(dest.dist,"dist",db);
ReadField<ErrorPolicy_Warn>(dest.dist,"dist",db);
ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db);
ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
ReadField<ErrorPolicy_Warn>(dest.constant_coefficient, "coeff_const", db);
ReadField<ErrorPolicy_Warn>(dest.linear_coefficient, "coeff_lin", db);
ReadField<ErrorPolicy_Warn>(dest.quadratic_coefficient, "coeff_quad", db);
ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);
+4
View File
@@ -538,6 +538,10 @@ struct Lamp : ElemBase {
float energy, dist, spotsize, spotblend;
//float haint;
float constant_coefficient;
float linear_coefficient;
float quadratic_coefficient;
float att1, att2;
//struct CurveMapping *curfalloff;
FalloffType falloff_type;
+63 -92
View File
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -68,8 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace melange;
// overload this function and fill in your own unique data
void GetWriterInfo(int &id, String &appname)
{
void GetWriterInfo(int &id, String &appname) {
id = 2424226;
appname = "Open Asset Import Library";
}
@@ -78,7 +77,10 @@ using namespace Assimp;
using namespace Assimp::Formatter;
namespace Assimp {
template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
template<> const char* LogFunctions<C4DImporter>::Prefix() {
static auto prefix = "C4D: ";
return prefix;
}
}
static const aiImporterDesc desc = {
@@ -97,47 +99,44 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter()
{}
: BaseImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter()
{}
C4DImporter::~C4DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile);
if (extension == "c4d") {
return true;
}
else if ((!extension.length() || checkSig) && pIOHandler) {
} else if ((!extension.length() || checkSig) && pIOHandler) {
// TODO
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* C4DImporter::GetInfo () const
{
const aiImporterDesc* C4DImporter::GetInfo () const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::SetupProperties(const Importer* /*pImp*/)
{
void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
// nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void C4DImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
if( file.get() == NULL) {
if( file.get() == nullptr ) {
ThrowException("failed to open file " + pFile);
}
@@ -151,7 +150,7 @@ void C4DImporter::InternReadFile( const std::string& pFile,
// open document first
BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
if(doc == NULL) {
if(doc == nullptr ) {
ThrowException("failed to read document " + pFile);
}
@@ -160,11 +159,10 @@ void C4DImporter::InternReadFile( const std::string& pFile,
// first convert all materials
ReadMaterials(doc->GetFirstMaterial());
// process C4D scenegraph recursively
// process C4D scene-graph recursively
try {
RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
}
catch(...) {
} catch(...) {
for(aiMesh* mesh : meshes) {
delete mesh;
}
@@ -201,8 +199,7 @@ void C4DImporter::InternReadFile( const std::string& pFile,
// ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
{
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
// based on Melange sample code (C4DImportExport.cpp)
while(shader) {
if(shader->GetType() == Xlayer) {
@@ -220,15 +217,12 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
// Ignore the actual layer blending - models for real-time rendering should not
// use them in a non-trivial way. Just try to find textures that we can apply
// to the model.
while (lsl)
{
if (lsl->GetType() == TypeFolder)
{
while (lsl) {
if (lsl->GetType() == TypeFolder) {
BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
while (subLsl)
{
while (subLsl) {
if (subLsl->GetType() == TypeShader) {
BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
@@ -238,8 +232,7 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
subLsl = subLsl->GetNext();
}
}
else if (lsl->GetType() == TypeShader) {
} else if (lsl->GetType() == TypeShader) {
BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
return true;
@@ -248,33 +241,27 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
lsl = lsl->GetNext();
}
}
else if ( shader->GetType() == Xbitmap )
{
} else if ( shader->GetType() == Xbitmap ) {
aiString path;
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
path.length = ::strlen(path.data);
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
return true;
}
else {
} else {
LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
}
shader = shader->GetNext();
}
return false;
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
{
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
// based on Melange sample code
while (mat)
{
while (mat) {
const String& name = mat->GetName();
if (mat->GetType() == Mmaterial)
{
if (mat->GetType() == Mmaterial) {
aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out);
@@ -286,8 +273,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
Material& m = dynamic_cast<Material&>(*mat);
if (m.GetChannelState(CHANNEL_COLOR))
{
if (m.GetChannelState(CHANNEL_COLOR)) {
GeData data;
mat->GetParameter(MATERIAL_COLOR_COLOR, data);
Vector color = data.GetVector();
@@ -307,9 +293,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
if(shader) {
ReadShader(out, shader);
}
}
else
{
} else {
LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
}
mat = mat->GetNext();
@@ -317,14 +301,12 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
{
ai_assert(parent != NULL);
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
ai_assert(parent != nullptr );
std::vector<aiNode*> nodes;
// based on Melange sample code
while (object)
{
while (object) {
const String& name = object->GetName();
const LONG type = object->GetType();
const Matrix& ml = object->GetMl();
@@ -356,26 +338,20 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
nodes.push_back(nd);
GeData data;
if (type == Ocamera)
{
if (type == Ocamera) {
object->GetParameter(CAMERAOBJECT_FOV, data);
// TODO: read camera
}
else if (type == Olight)
{
} else if (type == Olight) {
// TODO: read light
}
else if (type == Opolygon)
{
} else if (type == Opolygon) {
aiMesh* const mesh = ReadMesh(object);
if(mesh != NULL) {
if(mesh != nullptr) {
nd->mNumMeshes = 1;
nd->mMeshes = new unsigned int[1];
nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
meshes.push_back(mesh);
}
}
else {
} else {
LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
}
@@ -389,28 +365,27 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
std::copy(nodes.begin(), nodes.end(), parent->mChildren);
}
// ------------------------------------------------------------------------------------------------
aiMesh* C4DImporter::ReadMesh(BaseObject* object)
{
ai_assert(object != NULL && object->GetType() == Opolygon);
aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
ai_assert(object != nullptr);
ai_assert( object->GetType() == Opolygon );
// based on Melange sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != NULL);
ai_assert(polyObject != nullptr);
const LONG pointCount = polyObject->GetPointCount();
const LONG polyCount = polyObject->GetPolygonCount();
if(!polyObject || !pointCount) {
LogWarn("ignoring mesh with zero vertices or faces");
return NULL;
return nullptr;
}
const Vector* points = polyObject->GetPointR();
ai_assert(points != NULL);
ai_assert(points != nullptr);
const CPolygon* polys = polyObject->GetPolygonR();
ai_assert(polys != NULL);
ai_assert(polys != nullptr);
std::unique_ptr<aiMesh> mesh(new aiMesh());
mesh->mNumFaces = static_cast<unsigned int>(polyCount);
@@ -443,14 +418,14 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
// check if there are normals, tangents or UVW coordinates
BaseTag* tag = object->GetTag(Tnormal);
NormalTag* normals_src = NULL;
NormalTag* normals_src = nullptr;
if(tag) {
normals_src = dynamic_cast<NormalTag*>(tag);
normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
}
tag = object->GetTag(Ttangent);
TangentTag* tangents_src = NULL;
TangentTag* tangents_src = nullptr;
if(tag) {
tangents_src = dynamic_cast<TangentTag*>(tag);
tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
@@ -458,15 +433,14 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
}
tag = object->GetTag(Tuvw);
UVWTag* uvs_src = NULL;
UVWTag* uvs_src = nullptr;
if(tag) {
uvs_src = dynamic_cast<UVWTag*>(tag);
uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
}
// copy vertices and extra channels over and populate faces
for (LONG i = 0; i < polyCount; ++i, ++face)
{
for (LONG i = 0; i < polyCount; ++i, ++face) {
ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
const Vector& pointA = points[polys[i].a];
verts->x = pointA.x;
@@ -489,8 +463,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
++verts;
// TODO: do we also need to handle lines or points with similar checks?
if (polys[i].c != polys[i].d)
{
if (polys[i].c != polys[i].d) {
ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
face->mNumIndices = 4;
@@ -500,8 +473,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
verts->y = pointD.y;
verts->z = pointD.z;
++verts;
}
else {
} else {
face->mNumIndices = 3;
}
face->mIndices = new unsigned int[face->mNumIndices];
@@ -513,8 +485,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
if (normals_src) {
if(i >= normals_src->GetDataCount()) {
LogError("unexpected number of normals, ignoring");
}
else {
} else {
ConstNormalHandle normal_handle = normals_src->GetDataAddressR();
NormalStruct nor;
NormalTag::Get(normal_handle, i, nor);
@@ -616,26 +587,25 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
}
mesh->mMaterialIndex = ResolveMaterial(polyObject);
return mesh.release();
}
// ------------------------------------------------------------------------------------------------
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
{
ai_assert(obj != NULL);
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
ai_assert(obj != nullptr);
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
BaseTag* tag = obj->GetTag(Ttexture);
if(tag == NULL) {
if(tag == nullptr) {
return mat_count;
}
TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
BaseMaterial* const mat = ttag.GetMaterial();
ai_assert(mat != NULL);
ai_assert(mat != nullptr);
const MaterialMap::const_iterator it = material_mapping.find(mat);
if(it == material_mapping.end()) {
@@ -643,6 +613,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
}
ai_assert((*it).second < mat_count);
return (*it).second;
}
+6 -12
View File
@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
Copyright (c) 2006-2019, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/LogAux.h>
#include <map>
// Forward declarations
struct aiNode;
struct aiMesh;
struct aiMaterial;
@@ -61,8 +63,7 @@ namespace melange {
class BaseShader;
}
namespace Assimp {
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
@@ -75,17 +76,10 @@ namespace Assimp {
*
* Note that Melange is not free software. */
// -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
{
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public:
C4DImporter();
~C4DImporter();
public:
// --------------------
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
@@ -119,5 +113,5 @@ private:
}; // !class C4DImporter
} // end of namespace Assimp
#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
+156 -34
View File
@@ -47,6 +47,11 @@
cmake_minimum_required( VERSION 2.6 )
SET( HEADER_PATH ../include/assimp )
if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
message(WARNING "Requesting Android JNI I/O-System in non-Android toolchain. Resetting ASSIMP_ANDROID_JNIIOSYSTEM to OFF.")
set(ASSIMP_ANDROID_JNIIOSYSTEM OFF)
endif(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
SET( COMPILER_HEADERS
${HEADER_PATH}/Compiler/pushpack1.h
${HEADER_PATH}/Compiler/poppack1.h
@@ -140,6 +145,10 @@ SET( Core_SRCS
Assimp.cpp
)
IF(MSVC)
list(APPEND Core_SRCS "res/assimp.rc")
ENDIF(MSVC)
SET( Logging_SRCS
${HEADER_PATH}/DefaultLogger.hpp
${HEADER_PATH}/LogStream.hpp
@@ -211,7 +220,7 @@ ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
# ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer
# if this variable is set to FALSE, the user can manually enable importers by setting
# ASSIMP_BUILD_XXX_IMPORTER to TRUE for each importer
OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_IMPORTER value" TRUE)
OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_IMPORTER values" TRUE)
# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
# this way selective loaders can be compiled (reduces filesize + compile time)
@@ -227,19 +236,51 @@ MACRO(ADD_ASSIMP_IMPORTER name)
IF (ASSIMP_IMPORTER_ENABLED)
LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
SET(${name}_SRCS ${ARGN})
SOURCE_GROUP(${name} FILES ${ARGN})
ELSE()
SET(${name}_SRC "")
SET(ASSIMP_IMPORTERS_DISABLED "${ASSIMP_IMPORTERS_DISABLED} ${name}")
add_definitions(-DASSIMP_BUILD_NO_${name}_IMPORTER)
ENDIF()
ENDMACRO()
# if this variable is set to TRUE, the user can manually disable exporters by setting
# ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter
# if this variable is set to FALSE, the user can manually enable exporters by setting
# ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter
OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE)
# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
# this way selective loaders can be compiled (reduces filesize + compile time)
MACRO(ADD_ASSIMP_EXPORTER name)
IF (ASSIMP_NO_EXPORT)
set(ASSIMP_EXPORTER_ENABLED FALSE)
ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT)
set(ASSIMP_EXPORTER_ENABLED TRUE)
IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER)
set(ASSIMP_EXPORTER_ENABLED FALSE)
ENDIF ()
ELSE ()
set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER})
ENDIF ()
IF (ASSIMP_EXPORTER_ENABLED)
SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}")
LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN})
SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN})
ELSE()
SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}")
add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER)
ENDIF()
ENDMACRO()
SET(ASSIMP_LOADER_SRCS "")
SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
SET(ASSIMP_IMPORTERS_DISABLED "") # disabled list (used to print)
SET(ASSIMP_IMPORTERS_DISABLED "") # disabled importers list (used to print)
SET(ASSIMP_EXPORTER_SRCS "")
SET(ASSIMP_EXPORTERS_ENABLED "") # list of enabled exporters
SET(ASSIMP_EXPORTERS_DISABLED "") # disabled exporters list (used to print)
ADD_ASSIMP_IMPORTER( AMF
AMFImporter.hpp
@@ -256,6 +297,9 @@ ADD_ASSIMP_IMPORTER( 3DS
3DSHelper.h
3DSLoader.cpp
3DSLoader.h
)
ADD_ASSIMP_EXPORTER( 3DS
3DSExporter.h
3DSExporter.cpp
)
@@ -273,12 +317,15 @@ ADD_ASSIMP_IMPORTER( ASE
)
ADD_ASSIMP_IMPORTER( ASSBIN
AssbinExporter.h
AssbinExporter.cpp
AssbinLoader.h
AssbinLoader.cpp
)
ADD_ASSIMP_EXPORTER( ASSBIN
AssbinExporter.h
AssbinExporter.cpp
)
ADD_ASSIMP_IMPORTER( ASSXML
AssxmlExporter.h
AssxmlExporter.cpp
@@ -300,6 +347,9 @@ ADD_ASSIMP_IMPORTER( COLLADA
ColladaLoader.h
ColladaParser.cpp
ColladaParser.h
)
ADD_ASSIMP_EXPORTER( COLLADA
ColladaExporter.h
ColladaExporter.cpp
)
@@ -416,6 +466,9 @@ ADD_ASSIMP_IMPORTER( OBJ
ObjFileParser.cpp
ObjFileParser.h
ObjTools.h
)
ADD_ASSIMP_EXPORTER( OBJ
ObjExporter.h
ObjExporter.cpp
)
@@ -434,18 +487,24 @@ ADD_ASSIMP_IMPORTER( OGRE
)
ADD_ASSIMP_IMPORTER( OPENGEX
OpenGEXExporter.cpp
OpenGEXExporter.h
OpenGEXImporter.cpp
OpenGEXImporter.h
OpenGEXStructs.h
)
ADD_ASSIMP_EXPORTER( OPENGEX
OpenGEXExporter.cpp
OpenGEXExporter.h
)
ADD_ASSIMP_IMPORTER( PLY
PlyLoader.cpp
PlyLoader.h
PlyParser.cpp
PlyParser.h
)
ADD_ASSIMP_EXPORTER( PLY
PlyExporter.cpp
PlyExporter.h
)
@@ -536,13 +595,16 @@ ADD_ASSIMP_IMPORTER( FBX
FBXDeformer.cpp
FBXBinaryTokenizer.cpp
FBXDocumentUtil.cpp
FBXCommon.h
)
ADD_ASSIMP_EXPORTER( FBX
FBXExporter.h
FBXExporter.cpp
FBXExportNode.h
FBXExportNode.cpp
FBXExportProperty.h
FBXExportProperty.cpp
FBXCommon.h
)
SET( PostProcessing_SRCS
@@ -642,6 +704,9 @@ ADD_ASSIMP_IMPORTER( SMD
ADD_ASSIMP_IMPORTER( STL
STLLoader.cpp
STLLoader.h
)
ADD_ASSIMP_EXPORTER( STL
STLExporter.h
STLExporter.cpp
)
@@ -662,13 +727,14 @@ ADD_ASSIMP_IMPORTER( X
XFileImporter.h
XFileParser.cpp
XFileParser.h
)
ADD_ASSIMP_EXPORTER( X
XFileExporter.h
XFileExporter.cpp
)
ADD_ASSIMP_IMPORTER( X3D
X3DExporter.cpp
X3DExporter.hpp
X3DImporter.cpp
X3DImporter.hpp
X3DImporter_Geometry2D.cpp
@@ -688,6 +754,11 @@ ADD_ASSIMP_IMPORTER( X3D
X3DVocabulary.cpp
)
ADD_ASSIMP_EXPORTER( X3D
X3DExporter.cpp
X3DExporter.hpp
)
ADD_ASSIMP_IMPORTER( GLTF
glTFAsset.h
glTFAsset.inl
@@ -695,28 +766,34 @@ ADD_ASSIMP_IMPORTER( GLTF
glTFAssetWriter.inl
glTFImporter.cpp
glTFImporter.h
glTFExporter.h
glTFExporter.cpp
glTF2Asset.h
glTF2Asset.inl
glTF2AssetWriter.h
glTF2AssetWriter.inl
glTF2Importer.cpp
glTF2Importer.h
)
ADD_ASSIMP_EXPORTER( GLTF
glTFExporter.h
glTFExporter.cpp
glTF2Exporter.h
glTF2Exporter.cpp
)
ADD_ASSIMP_IMPORTER( 3MF
D3MFImporter.h
D3MFImporter.h
D3MFImporter.cpp
D3MFExporter.h
D3MFExporter.cpp
D3MFOpcPackage.h
D3MFOpcPackage.h
D3MFOpcPackage.cpp
3MFXmlTags.h
)
ADD_ASSIMP_EXPORTER( 3MF
D3MFExporter.h
D3MFExporter.cpp
)
ADD_ASSIMP_IMPORTER( MMD
MMDCpp14.h
MMDImporter.cpp
@@ -727,6 +804,18 @@ ADD_ASSIMP_IMPORTER( MMD
MMDVmdParser.h
)
# Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error
# Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any
# optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate
# Also, I'm not positive if both link & compile flags are needed, but this hopefully ensures that the issue should not
# recur for edge cases such as static builds.
if ((CMAKE_COMPILER_IS_MINGW) AND (CMAKE_BUILD_TYPE MATCHES Debug))
message("-- Applying MinGW StepFileGen1.cpp Debug Workaround")
SET_SOURCE_FILES_PROPERTIES(Importer/StepFile/StepFileGen1.cpp PROPERTIES COMPILE_FLAGS -Os )
SET_SOURCE_FILES_PROPERTIES(Importer/StepFile/StepFileGen1.cpp PROPERTIES LINK_FLAGS -Os )
SET_SOURCE_FILES_PROPERTIES(Importer/StepFile/StepFileGen1.cpp PROPERTIES STATIC_LIBRARY_FLAGS -Os )
endif()
ADD_ASSIMP_IMPORTER( STEP
STEPFile.h
Importer/StepFile/StepFileImporter.h
@@ -735,28 +824,32 @@ ADD_ASSIMP_IMPORTER( STEP
Importer/StepFile/StepFileGen2.cpp
Importer/StepFile/StepFileGen3.cpp
Importer/StepFile/StepReaderGen.h
)
ADD_ASSIMP_EXPORTER( STEP
StepExporter.h
StepExporter.cpp
)
SET( Exporter_SRCS
Exporter.cpp
AssimpCExport.cpp
${HEADER_PATH}/BlobIOSystem.h
)
SOURCE_GROUP( Exporter FILES ${Exporter_SRCS})
if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
SET( Exporter_SRCS
Exporter.cpp
AssimpCExport.cpp
${HEADER_PATH}/BlobIOSystem.h
)
SOURCE_GROUP( Exporter FILES ${Exporter_SRCS})
endif()
SET( Extra_SRCS
MD4FileData.h
)
SOURCE_GROUP( Extra FILES ${Extra_SRCS})
SET( Clipper_SRCS
../contrib/clipper/clipper.hpp
../contrib/clipper/clipper.cpp
)
SOURCE_GROUP( Clipper FILES ${Clipper_SRCS})
SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS})
SET( Poly2Tri_SRCS
../contrib/poly2tri/poly2tri/common/shapes.cc
@@ -771,7 +864,7 @@ SET( Poly2Tri_SRCS
../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
../contrib/poly2tri/poly2tri/sweep/sweep_context.h
)
SOURCE_GROUP( Poly2Tri FILES ${Poly2Tri_SRCS})
SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS})
SET( unzip_SRCS
../contrib/unzip/crypt.h
@@ -780,7 +873,7 @@ SET( unzip_SRCS
../contrib/unzip/unzip.c
../contrib/unzip/unzip.h
)
SOURCE_GROUP( unzip FILES ${unzip_SRCS})
SOURCE_GROUP(Contrib\\unzip FILES ${unzip_SRCS})
SET( ziplib_SRCS
../contrib/zip/src/miniz.h
@@ -788,6 +881,13 @@ SET( ziplib_SRCS
../contrib/zip/src/zip.h
)
# TODO if cmake required version has been updated to >3.12.0, collapse this to the second case only
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
add_definitions(-DMINIZ_USE_UNALIGNED_LOADS_AND_STORES=0)
else()
add_compile_definitions(MINIZ_USE_UNALIGNED_LOADS_AND_STORES=0)
endif()
SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} )
SET ( openddl_parser_SRCS
@@ -805,7 +905,7 @@ SET ( openddl_parser_SRCS
../contrib/openddlparser/include/openddlparser/DDLNode.h
../contrib/openddlparser/include/openddlparser/Value.h
)
SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
SOURCE_GROUP( Contrib\\openddl_parser FILES ${openddl_parser_SRCS})
SET ( open3dgc_SRCS
../contrib/Open3DGC/o3dgcAdjacencyInfo.h
@@ -838,7 +938,7 @@ SET ( open3dgc_SRCS
../contrib/Open3DGC/o3dgcVector.h
../contrib/Open3DGC/o3dgcVector.inl
)
SOURCE_GROUP( open3dgc FILES ${open3dgc_SRCS})
SOURCE_GROUP( Contrib\\open3dgc FILES ${open3dgc_SRCS})
# Check dependencies for glTF importer with Open3DGC-compression.
# RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
@@ -878,8 +978,11 @@ else (UNZIP_FOUND)
INCLUDE_DIRECTORIES( "../contrib/unzip/" )
endif (UNZIP_FOUND)
MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")
MESSAGE(STATUS "Disabled formats:${ASSIMP_IMPORTERS_DISABLED}")
MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}")
MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}")
MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
SET( assimp_src
# Assimp Files
@@ -894,6 +997,7 @@ SET( assimp_src
# Model Support
${ASSIMP_LOADER_SRCS}
${ASSIMP_EXPORTER_SRCS}
# Third-party libraries
${IrrXML_SRCS}
@@ -907,7 +1011,6 @@ SET( assimp_src
${PUBLIC_HEADERS}
${COMPILER_HEADERS}
)
ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
@@ -932,11 +1035,11 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
if(ASSIMP_ANDROID_JNIIOSYSTEM)
set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
target_link_libraries(assimp android_jniiosystem)
endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
endif(ASSIMP_ANDROID_JNIIOSYSTEM)
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARIES})
@@ -946,6 +1049,10 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
if( MSVC )
# in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
# CMake 3.12 added a variable for this
if(MSVC_TOOLSET_VERSION)
set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
else()
if( MSVC70 OR MSVC71 )
set(MSVC_PREFIX "vc70")
elseif( MSVC80 )
@@ -960,14 +1067,19 @@ if( MSVC )
set(MSVC_PREFIX "vc120")
elseif( MSVC14 )
set(MSVC_PREFIX "vc140")
elseif( MSVC15 )
set(MSVC_PREFIX "vc141")
else()
set(MSVC_PREFIX "vc150")
endif()
endif()
set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
endif()
if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
set(WindowsStore TRUE)
target_compile_definitions(assimp PUBLIC WindowsStore)
TARGET_LINK_LIBRARIES(assimp advapi32)
#set(WindowsStore TRUE)
endif()
SET_TARGET_PROPERTIES( assimp PROPERTIES
VERSION ${ASSIMP_VERSION}
@@ -1028,6 +1140,16 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM)
ENDIF(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB)
# When only the static library is built, these properties must
# be set to ensure the static lib .pdb is staged for installation.
IF(NOT BUILD_SHARED_LIBS)
SET_TARGET_PROPERTIES( assimp PROPERTIES
COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMPILE_PDB_NAME assimp${LIBRARY_SUFFIX}
COMPILE_PDB_NAME_DEBUG assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}
)
ENDIF()
IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+5 -5
View File
@@ -144,7 +144,7 @@ void COBImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// check header
char head[32];
stream->CopyAndAdvance(head,32);
if (strncmp(head,"Caligari ",9)) {
if (strncmp(head,"Caligari ",9) != 0) {
ThrowException("Could not found magic id: `Caligari`");
}
@@ -656,14 +656,14 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
ReadFloat3Tuple_Ascii(msh.color ,&rgb);
SkipSpaces(&rgb);
if (strncmp(rgb,"cone angle",10)) {
if (strncmp(rgb,"cone angle",10) != 0) {
ASSIMP_LOG_WARN_F( "Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id );
}
SkipSpaces(rgb+10,&rgb);
msh.angle = fast_atof(&rgb);
SkipSpaces(&rgb);
if (strncmp(rgb,"inner angle",11)) {
if (strncmp(rgb,"inner angle",11) != 0) {
ASSIMP_LOG_WARN_F( "Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
}
SkipSpaces(rgb+11,&rgb);
@@ -903,7 +903,7 @@ public:
if(nfo.size != static_cast<unsigned int>(-1)) {
try {
reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
} catch ( DeadlyImportError e ) {
} catch (const DeadlyImportError& e ) {
// out of limit so correct the value
reader.IncPtr( reader.GetReadLimit() );
}
@@ -1214,7 +1214,7 @@ void COBImporter::ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const
const chunk_guard cn(nfo,reader);
out.nodes.push_back(std::shared_ptr<Group>(new Group()));
out.nodes.push_back(std::make_shared<Group>());
Group& msh = (Group&)(*out.nodes.back().get());
msh = nfo;
+73 -39
View File
@@ -64,13 +64,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
namespace Assimp
{
namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
{
void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
@@ -93,12 +91,12 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
} // end of namespace Assimp
// ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
{
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file)
: mIOSystem(pIOSystem)
, mPath(path)
, mFile(file) {
// make sure that all formatting happens using the standard, C locale and not the user's current locale
mOutput.imbue( std::locale("C") );
mOutput.precision(16);
@@ -115,17 +113,15 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co
// ------------------------------------------------------------------------------------------------
// Destructor
ColladaExporter::~ColladaExporter()
{
if(mSceneOwned) {
ColladaExporter::~ColladaExporter() {
if ( mSceneOwned ) {
delete mScene;
}
}
// ------------------------------------------------------------------------------------------------
// Starts writing the contents
void ColladaExporter::WriteFile()
{
void ColladaExporter::WriteFile() {
// write the DTD
mOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" << endstr;
// COLLADA element start
@@ -158,8 +154,7 @@ void ColladaExporter::WriteFile()
// ------------------------------------------------------------------------------------------------
// Writes the asset header
void ColladaExporter::WriteHeader()
{
void ColladaExporter::WriteHeader() {
static const ai_real epsilon = ai_real( 0.00001 );
static const aiQuaternion x_rot(aiMatrix3x3(
0, -1, 0,
@@ -238,25 +233,64 @@ void ColladaExporter::WriteHeader()
mOutput << startstr << "<contributor>" << endstr;
PushTag();
aiMetadata* meta = mScene->mRootNode->mMetaData;
// If no Scene metadata, use root node metadata
aiMetadata* meta = mScene->mMetaData;
if (nullptr == meta) {
meta = mScene->mRootNode->mMetaData;
}
aiString value;
if (!meta || !meta->Get("Author", value))
if (!meta || !meta->Get("Author", value)) {
mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
else
} else {
mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
}
if (!meta || !meta->Get("AuthoringTool", value))
if (nullptr == meta || !meta->Get("AuthoringTool", value)) {
mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
else
} else {
mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
}
//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
if (meta) {
if (meta->Get("Comments", value)) {
mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr;
}
if (meta->Get("Copyright", value)) {
mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr;
}
if (meta->Get("SourceData", value)) {
mOutput << startstr << "<source_data>" << XMLEscape(value.C_Str()) << "</source_data>" << endstr;
}
}
PopTag();
mOutput << startstr << "</contributor>" << endstr;
mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
if (nullptr == meta || !meta->Get("Created", value)) {
mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
} else {
mOutput << startstr << "<created>" << XMLEscape(value.C_Str()) << "</created>" << endstr;
}
// Modified date is always the date saved
mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
if (meta) {
if (meta->Get("Keywords", value)) {
mOutput << startstr << "<keywords>" << XMLEscape(value.C_Str()) << "</keywords>" << endstr;
}
if (meta->Get("Revision", value)) {
mOutput << startstr << "<revision>" << XMLEscape(value.C_Str()) << "</revision>" << endstr;
}
if (meta->Get("Subject", value)) {
mOutput << startstr << "<subject>" << XMLEscape(value.C_Str()) << "</subject>" << endstr;
}
if (meta->Get("Title", value)) {
mOutput << startstr << "<title>" << XMLEscape(value.C_Str()) << "</title>" << endstr;
}
}
mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
PopTag();
@@ -269,12 +303,15 @@ void ColladaExporter::WriteTextures() {
static const unsigned int buffer_size = 1024;
char str[buffer_size];
if(mScene->HasTextures()) {
if (mScene->HasTextures()) {
for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
// It would be great to be able to create a directory in portable standard C++, but it's not the case,
// so we just write the textures in the current directory.
aiTexture* texture = mScene->mTextures[i];
if ( nullptr == texture ) {
continue;
}
ASSIMP_itoa10(str, buffer_size, i + 1);
@@ -428,6 +465,7 @@ void ColladaExporter::WritePointLight(const aiLight *const light){
mOutput << startstr << "</point>" << endstr;
}
void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
const aiColor3D &color= light->mColorDiffuse;
mOutput << startstr << "<directional>" << endstr;
@@ -440,6 +478,7 @@ void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
mOutput << startstr << "</directional>" << endstr;
}
void ColladaExporter::WriteSpotLight(const aiLight *const light){
const aiColor3D &color= light->mColorDiffuse;
@@ -496,18 +535,16 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light){
// ------------------------------------------------------------------------------------------------
// Reads a single surface entry from the given material keys
void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex)
{
if( pSrcMat->GetTextureCount( pTexture) > 0 )
{
void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat,
aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) {
if( pSrcMat->GetTextureCount( pTexture) > 0 ) {
aiString texfile;
unsigned int uvChannel = 0;
pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel);
std::string index_str(texfile.C_Str());
if(index_str.size() != 0 && index_str[0] == '*')
{
if(index_str.size() != 0 && index_str[0] == '*') {
unsigned int index;
index_str = index_str.substr(1, std::string::npos);
@@ -525,15 +562,13 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
} else {
throw DeadlyExportError("could not find embedded texture at index " + index_str);
}
} else
{
} else {
poSurface.texture = texfile.C_Str();
}
poSurface.channel = uvChannel;
poSurface.exist = true;
} else
{
} else {
if( pKey )
poSurface.exist = pSrcMat->Get( pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
}
@@ -541,15 +576,13 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
// ------------------------------------------------------------------------------------------------
// Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version.
static bool isalnum_C(char c)
{
static bool isalnum_C(char c) {
return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) );
}
// ------------------------------------------------------------------------------------------------
// Writes an image entry for the given surface
void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd)
{
void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) {
if( !pSurface.texture.empty() )
{
mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
@@ -803,8 +836,9 @@ void ColladaExporter::WriteControllerLibrary()
mOutput << startstr << "<library_controllers>" << endstr;
PushTag();
for( size_t a = 0; a < mScene->mNumMeshes; ++a)
for( size_t a = 0; a < mScene->mNumMeshes; ++a) {
WriteController( a);
}
PopTag();
mOutput << startstr << "</library_controllers>" << endstr;
+41 -21
View File
@@ -109,13 +109,13 @@ ColladaLoader::~ColladaLoader() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
// check file extension
std::string extension = GetExtension(pFile);
if( extension == "dae")
if (extension == "dae") {
return true;
}
// XML - too generic, we need to open the file and search for typical keywords
if( extension == "xml" || !extension.length() || checkSig) {
@@ -123,10 +123,13 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
* support a specific file extension in general pIOHandler
* might be NULL and it's our duty to return true here.
*/
if (!pIOHandler)return true;
if (!pIOHandler) {
return true;
}
const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
}
@@ -147,8 +150,7 @@ const aiImporterDesc* ColladaLoader::GetInfo () const
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
mFileName = pFile;
// clean all member arrays - just for safety, it should work even if we did not
@@ -184,7 +186,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// ... then fill the materials with the now adjusted settings
FillMaterials(parser, pScene);
// Apply unitsize scale calculation
// Apply unit-size scale calculation
pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
0, parser.mUnitSize, 0, 0,
0, 0, parser.mUnitSize, 0,
@@ -205,6 +207,17 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
0, 0, 0, 1);
}
// Store scene metadata
if (!parser.mAssetMetaData.empty()) {
const size_t numMeta(parser.mAssetMetaData.size());
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
size_t i = 0;
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i)
{
pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
}
}
// store all meshes
StoreSceneMeshes( pScene);
@@ -1924,21 +1937,28 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
{
// If explicitly requested, just use the collada name.
if (useColladaName) {
return pNode->mName;
}
// Now setup the name of the assimp node. The collada name might not be
// unique, so we use the collada ID.
if (!pNode->mID.empty())
return pNode->mID;
else if (!pNode->mSID.empty())
return pNode->mSID;
else
if (useColladaName)
{
// No need to worry. Unnamed nodes are no problem at all, except
// if cameras or lights need to be assigned to them.
return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
if (!pNode->mName.empty()) {
return pNode->mName;
} else {
return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
}
}
else
{
// Now setup the name of the assimp node. The collada name might not be
// unique, so we use the collada ID.
if (!pNode->mID.empty())
return pNode->mID;
else if (!pNode->mSID.empty())
return pNode->mSID;
else
{
// No need to worry. Unnamed nodes are no problem at all, except
// if cameras or lights need to be assigned to them.
return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
}
}
}
+77 -3
View File
@@ -264,14 +264,19 @@ void ColladaParser::ReadAssetInfo()
// check element end
TestClosing( "up_axis");
} else
}
else if(IsElement("contributor"))
{
SkipElement();
ReadContributorInfo();
}
else
{
ReadMetaDataItem(mAssetMetaData);
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "asset") != 0)
if (strcmp( mReader->getNodeName(), "asset") != 0)
ThrowException( "Expected end of <asset> element.");
break;
@@ -279,6 +284,75 @@ void ColladaParser::ReadAssetInfo()
}
}
// ------------------------------------------------------------------------------------------------
// Reads the contributor info
void ColladaParser::ReadContributorInfo()
{
if (mReader->isEmptyElement())
return;
while (mReader->read())
{
if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
ReadMetaDataItem(mAssetMetaData);
}
else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if (strcmp(mReader->getNodeName(), "contributor") != 0)
ThrowException("Expected end of <contributor> element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a single string metadata item
void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
{
// Metadata such as created, keywords, subject etc
const char* key_char = mReader->getNodeName();
if (key_char != nullptr)
{
const std::string key_str(key_char);
const char* value_char = TestTextContent();
if (value_char != nullptr)
{
std::string camel_key_str = key_str;
ToCamelCase(camel_key_str);
aiString aistr;
aistr.Set(value_char);
metadata.emplace(camel_key_str, aistr);
TestClosing(key_str.c_str());
}
else
SkipElement();
}
else
SkipElement();
}
// ------------------------------------------------------------------------------------------------
// Convert underscore_seperated to CamelCase: "authoring_tool" becomes "AuthoringTool"
void ColladaParser::ToCamelCase(std::string &text)
{
if (text.empty())
return;
// Capitalise first character
text[0] = ToUpper(text[0]);
for (auto it = text.begin(); it != text.end(); /*iterated below*/)
{
if ((*it) == '_')
{
it = text.erase(it);
if (it != text.end())
(*it) = ToUpper(*it);
}
else
++it;
}
}
// ------------------------------------------------------------------------------------------------
// Reads the animation clips
void ColladaParser::ReadAnimationClipLibrary()
+15
View File
@@ -66,6 +66,9 @@ namespace Assimp
friend class ColladaLoader;
protected:
/** Map for generic metadata as aiString */
typedef std::map<std::string, aiString> StringMetaData;
/** Constructor from XML file */
ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
@@ -81,6 +84,15 @@ namespace Assimp
/** Reads asset information such as coordinate system information and legal blah */
void ReadAssetInfo();
/** Reads contributor information such as author and legal blah */
void ReadContributorInfo();
/** Reads generic metadata into provided map */
void ReadMetaDataItem(StringMetaData &metadata);
/** Convert underscore_seperated to CamelCase "authoring_tool" becomes "AuthoringTool" */
static void ToCamelCase(std::string &text);
/** Reads the animation library */
void ReadAnimationLibrary();
@@ -343,6 +355,9 @@ namespace Assimp
/** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection;
/** Asset metadata (global for scene) */
StringMetaData mAssetMetaData;
/** Collada file format version */
Collada::FormatVersion mFormat;
};
+4 -1
View File
@@ -476,8 +476,11 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
mZipArchive->Close( fileStream );
} else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file);
} else {
ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file);
}
}
}
+2 -2
View File
@@ -288,7 +288,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) {
// ------------------------------------------------------------------------------------------------
const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
unsigned int, const ExportProperties* /*pProperties*/ ) {
unsigned int pPreprocessing, const ExportProperties* pProperties) {
if (pimpl->blob) {
delete pimpl->blob;
pimpl->blob = nullptr;
@@ -298,7 +298,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha
BlobIOSystem* blobio = new BlobIOSystem();
pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) {
pimpl->mIOSystem = old;
return nullptr;
}
+13 -9
View File
@@ -83,7 +83,7 @@ namespace FBX {
// e_unknown_21 = 1 << 21,
// e_unknown_22 = 1 << 22,
// e_unknown_23 = 1 << 23,
// e_flag_field_size_64_bit = 1 << 24, // Not sure what is
// e_flag_field_size_64_bit = 1 << 24, // Not sure what is
// e_unknown_25 = 1 << 25,
// e_unknown_26 = 1 << 26,
// e_unknown_27 = 1 << 27,
@@ -98,7 +98,7 @@ namespace FBX {
// return (flags & to_check) != 0;
//}
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
Token::Token(const char* sbegin, const char* send, TokenType type, size_t offset)
:
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
@@ -122,18 +122,18 @@ namespace {
// ------------------------------------------------------------------------------------------------
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void TokenizeError(const std::string& message, size_t offset)
{
throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
}
// ------------------------------------------------------------------------------------------------
uint32_t Offset(const char* begin, const char* cursor) {
size_t Offset(const char* begin, const char* cursor) {
ai_assert(begin <= cursor);
return static_cast<unsigned int>(cursor - begin);
return cursor - begin;
}
// ------------------------------------------------------------------------------------------------
@@ -276,8 +276,8 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
case 'f':
case 'd':
case 'l':
case 'i': {
case 'i':
case 'c': {
const uint32_t length = ReadWord(input, cursor, end);
const uint32_t encoding = ReadWord(input, cursor, end);
@@ -298,6 +298,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
stride = 8;
break;
case 'c':
stride = 1;
break;
default:
ai_assert(false);
};
@@ -420,7 +424,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// ------------------------------------------------------------------------------------------------
// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
{
ai_assert(input);
+2 -2
View File
@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
namespace Assimp {
namespace FBX
{
const std::string NULL_RECORD = { // 13 null bytes
@@ -80,7 +80,7 @@ namespace FBX
TransformInheritance_MAX // end-of-enum sentinel
};
}
}
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXCOMMON_H_INC
+164 -73
View File
@@ -67,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
#include <iomanip>
namespace Assimp {
namespace FBX {
@@ -76,10 +77,21 @@ namespace Assimp {
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
FBXConverter::FBXConverter(aiScene* out, const Document& doc)
: defaultMaterialIndex()
, out(out)
, doc(doc) {
FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit )
: defaultMaterialIndex()
, lights()
, cameras()
, textures()
, materials_converted()
, textures_converted()
, meshes_converted()
, node_anim_chain_bits()
, mNodeNames()
, anim_fps()
, out(out)
, doc(doc)
, mRemoveEmptyBones( removeEmptyBones )
, mCurrentUnit(FbxUnit::cm) {
// animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated.
@@ -107,6 +119,7 @@ namespace Assimp {
ConvertGlobalSettings();
TransferDataToScene();
ConvertToUnitScale(unit);
// if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
// to make sure the scene passes assimp's validation. FBX files
@@ -128,12 +141,46 @@ namespace Assimp {
void FBXConverter::ConvertRootNode() {
out->mRootNode = new aiNode();
out->mRootNode->mName.Set("RootNode");
std::string unique_name;
GetUniqueName("RootNode", unique_name);
out->mRootNode->mName.Set(unique_name);
// root has ID 0
ConvertNodes(0L, *out->mRootNode);
}
static std::string getAncestorBaseName(const aiNode* node)
{
const char* nodeName = nullptr;
size_t length = 0;
while (node && (!nodeName || length == 0))
{
nodeName = node->mName.C_Str();
length = node->mName.length;
node = node->mParent;
}
if (!nodeName || length == 0)
{
return {};
}
// could be std::string_view if c++17 available
return std::string(nodeName, length);
}
// Make unique name
std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent)
{
std::string original_name = FixNodeName(model->Name());
if (original_name.empty())
{
original_name = getAncestorBaseName(&parent);
}
std::string unique_name;
GetUniqueName(original_name, unique_name);
return unique_name;
}
void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
@@ -165,35 +212,18 @@ namespace Assimp {
aiMatrix4x4 new_abs_transform = parent_transform;
std::string unique_name = MakeUniqueNodeName(model, parent);
// even though there is only a single input node, the design of
// assimp (or rather: the complicated transformation chain that
// is employed by fbx) means that we may need multiple aiNode's
// to represent a fbx node's transformation.
GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain);
const bool need_additional_node = GenerateTransformationNodeChain(*model, unique_name, nodes_chain, post_nodes_chain);
ai_assert(nodes_chain.size());
std::string original_name = FixNodeName(model->Name());
// check if any of the nodes in the chain has the name the fbx node
// is supposed to have. If there is none, add another node to
// preserve the name - people might have scripts etc. that rely
// on specific node names.
aiNode* name_carrier = NULL;
for (aiNode* prenode : nodes_chain) {
if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) {
name_carrier = prenode;
break;
}
}
if (!name_carrier) {
std::string old_original_name = original_name;
GetUniqueName(old_original_name, original_name);
nodes_chain.push_back(new aiNode(original_name));
}
else {
original_name = nodes_chain.back()->mName.C_Str();
if (need_additional_node) {
nodes_chain.push_back(new aiNode(unique_name));
}
//setup metadata on newest node
@@ -255,11 +285,11 @@ namespace Assimp {
ConvertNodes(model->ID(), *last_parent, new_abs_transform);
if (doc.Settings().readLights) {
ConvertLights(*model, original_name);
ConvertLights(*model, unique_name);
}
if (doc.Settings().readCameras) {
ConvertCameras(*model, original_name);
ConvertCameras(*model, unique_name);
}
nodes.push_back(nodes_chain.front());
@@ -377,6 +407,7 @@ namespace Assimp {
break;
default:
ai_assert(false);
break;
}
}
@@ -390,9 +421,18 @@ namespace Assimp {
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
//cameras are defined along positive x direction
out_camera->mPosition = cam.Position();
/*out_camera->mPosition = cam.Position();
out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize();
out_camera->mUp = cam.UpVector();
out_camera->mUp = cam.UpVector();*/
out_camera->mPosition = aiVector3D(0.0f);
out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
out_camera->mClipPlaneNear = cam.NearPlane();
out_camera->mClipPlaneFar = cam.FarPlane();
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
out_camera->mClipPlaneNear = cam.NearPlane();
@@ -401,19 +441,19 @@ namespace Assimp {
void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
{
int i = 0;
uniqueName = name;
while (mNodeNames.find(uniqueName) != mNodeNames.end())
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
unsigned int& i = it_pair.first->second;
while (!it_pair.second)
{
++i;
std::stringstream ext;
i++;
std::ostringstream ext;
ext << name << std::setfill('0') << std::setw(3) << i;
uniqueName = ext.str();
it_pair = mNodeNames.insert({ uniqueName, 0 });
}
mNodeNames.insert(uniqueName);
}
const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
switch (comp) {
case TransformationComp_Translation:
@@ -643,7 +683,7 @@ namespace Assimp {
return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
}
void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes,
bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes,
std::vector<aiNode*>& post_output_nodes) {
const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder();
@@ -758,8 +798,6 @@ namespace Assimp {
// not be guaranteed.
ai_assert(NeedsComplexTransformationChain(model) == is_complex);
std::string name = FixNodeName(model.Name());
// now, if we have more than just Translation, Scaling and Rotation,
// we need to generate a full node chain to accommodate for assimp's
// lack to express pivots and offsets.
@@ -801,20 +839,20 @@ namespace Assimp {
}
ai_assert(output_nodes.size());
return;
return true;
}
// else, we can just multiply the matrices together
aiNode* nd = new aiNode();
output_nodes.push_back(nd);
std::string uniqueName;
GetUniqueName(name, uniqueName);
nd->mName.Set(uniqueName);
// name passed to the method is already unique
nd->mName.Set(name);
for (const auto &transform : chain) {
nd->mTransformation = nd->mTransformation * transform;
}
return false;
}
void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd)
@@ -953,9 +991,11 @@ namespace Assimp {
unsigned int epcount = 0;
for (unsigned i = 0; i < indices.size(); i++)
{
if (indices[i] < 0) epcount++;
if (indices[i] < 0) {
epcount++;
}
}
unsigned int pcount = indices.size();
unsigned int pcount = static_cast<unsigned int>( indices.size() );
unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
aiFace* fac = out_mesh->mFaces = new aiFace[scount]();
@@ -1151,7 +1191,7 @@ namespace Assimp {
}
}
}
size_t numAnimMeshes = animMeshes.size();
const size_t numAnimMeshes = animMeshes.size();
if (numAnimMeshes > 0) {
out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
@@ -1291,8 +1331,7 @@ namespace Assimp {
unsigned int cursor = 0, in_cursor = 0;
itf = faces.begin();
for (MatIndexArray::const_iterator it = mindices.begin(),
end = mindices.end(); it != end; ++it, ++itf)
for (MatIndexArray::const_iterator it = mindices.begin(), end = mindices.end(); it != end; ++it, ++itf)
{
const unsigned int pcount = *itf;
if ((*it) != index) {
@@ -1384,7 +1423,7 @@ namespace Assimp {
const WeightIndexArray& indices = cluster->GetIndices();
if (indices.empty()) {
if (indices.empty() && mRemoveEmptyBones ) {
continue;
}
@@ -1416,13 +1455,11 @@ namespace Assimp {
if (index_out_indices.back() == no_index_sentinel) {
index_out_indices.back() = out_indices.size();
}
if (no_mat_check) {
out_indices.push_back(out_idx[i]);
}
else {
} else {
// this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn)
const std::vector<unsigned int>::iterator it = std::lower_bound(
outputVertStartIndices->begin(),
@@ -1438,11 +1475,11 @@ namespace Assimp {
}
}
}
// if we found at least one, generate the output bones
// XXX this could be heavily simplified by collecting the bone
// data in a single step.
if (ok) {
if (ok && mRemoveEmptyBones) {
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
count_out_indices, node_global_transform);
}
@@ -1573,6 +1610,13 @@ namespace Assimp {
out_mat->AddProperty(&str, AI_MATKEY_NAME);
}
// Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum.
if (material.GetShadingModel() == "phong")
{
aiShadingMode shadingMode = aiShadingMode_Phong;
out_mat->AddProperty<aiShadingMode>(&shadingMode, 1, AI_MATKEY_SHADING_MODEL);
}
// shading stuff and colors
SetShadingPropertiesCommon(out_mat, props);
SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh );
@@ -1704,22 +1748,22 @@ namespace Assimp {
if (!mesh)
{
for (const MeshMap::value_type& v : meshes_converted) {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
if (!mesh) {
const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
if (!meshGeom) {
continue;
}
const MatIndexArray& mats = mesh->GetMaterialIndices();
const MatIndexArray& mats = meshGeom->GetMaterialIndices();
if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
continue;
}
int index = -1;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (mesh->GetTextureCoords(i).empty()) {
if (meshGeom->GetTextureCoords(i).empty()) {
break;
}
const std::string& name = mesh->GetTextureCoordChannelName(i);
const std::string& name = meshGeom->GetTextureCoordChannelName(i);
if (name == uvSet) {
index = static_cast<int>(i);
break;
@@ -1827,22 +1871,22 @@ namespace Assimp {
if (!mesh)
{
for (const MeshMap::value_type& v : meshes_converted) {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
if (!mesh) {
const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
if (!meshGeom) {
continue;
}
const MatIndexArray& mats = mesh->GetMaterialIndices();
const MatIndexArray& mats = meshGeom->GetMaterialIndices();
if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
continue;
}
int index = -1;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (mesh->GetTextureCoords(i).empty()) {
if (meshGeom->GetTextureCoords(i).empty()) {
break;
}
const std::string& name = mesh->GetTextureCoordChannelName(i);
const std::string& name = meshGeom->GetTextureCoordChannelName(i);
if (name == uvSet) {
index = static_cast<int>(i);
break;
@@ -2033,6 +2077,12 @@ namespace Assimp {
CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
}
// try to get the transparency factor
const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok);
if (ok) {
out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR);
}
// use of TransparencyFactor is inconsistent.
// Maya always stores it as 1.0,
// so we can't use it to set AI_MATKEY_OPACITY.
@@ -2183,22 +2233,22 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
if (!mesh)
{
for (const MeshMap::value_type& v : meshes_converted) {
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(v.first);
if (!mesh) {
const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*>(v.first);
if (!meshGeom) {
continue;
}
const MatIndexArray& mats = mesh->GetMaterialIndices();
const MatIndexArray& mats = meshGeom->GetMaterialIndices();
if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
continue;
}
int index = -1;
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (mesh->GetTextureCoords(i).empty()) {
if (meshGeom->GetTextureCoords(i).empty()) {
break;
}
const std::string& name = mesh->GetTextureCoordChannelName(i);
const std::string& name = meshGeom->GetTextureCoordChannelName(i);
if (name == uvSet) {
index = static_cast<int>(i);
break;
@@ -3378,8 +3428,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
na->mScalingKeys = new aiVectorKey[keys.size()];
if (keys.size() > 0)
if (keys.size() > 0) {
InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime);
}
}
void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
@@ -3443,6 +3494,46 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
}
void FBXConverter::ConvertToUnitScale( FbxUnit unit ) {
if (mCurrentUnit == unit) {
return;
}
ai_real scale = 1.0;
if (mCurrentUnit == FbxUnit::cm) {
if (unit == FbxUnit::m) {
scale = (ai_real)0.01;
} else if (unit == FbxUnit::km) {
scale = (ai_real)0.00001;
}
} else if (mCurrentUnit == FbxUnit::m) {
if (unit == FbxUnit::cm) {
scale = (ai_real)100.0;
} else if (unit == FbxUnit::km) {
scale = (ai_real)0.001;
}
} else if (mCurrentUnit == FbxUnit::km) {
if (unit == FbxUnit::cm) {
scale = (ai_real)100000.0;
} else if (unit == FbxUnit::m) {
scale = (ai_real)1000.0;
}
}
for (auto mesh : meshes) {
if (nullptr == mesh) {
continue;
}
if (mesh->HasPositions()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D &pos = mesh->mVertices[i];
pos *= scale;
}
}
}
}
void FBXConverter::TransferDataToScene()
{
ai_assert(!out->mMeshes);
@@ -3496,9 +3587,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
}
// ------------------------------------------------------------------------------------------------
void ConvertToAssimpScene(aiScene* out, const Document& doc)
void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit)
{
FBXConverter converter(out, doc);
FBXConverter converter(out, doc, removeEmptyBones, unit);
}
} // !FBX
+35 -11
View File
@@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/texture.h>
#include <assimp/camera.h>
#include <assimp/StringComparison.h>
#include <unordered_map>
#include <unordered_set>
struct aiScene;
struct aiNode;
@@ -74,14 +76,22 @@ namespace FBX {
class Document;
using NodeNameCache = std::set<std::string>;
enum class FbxUnit {
cm = 0,
m,
km,
NumUnits,
Undefined
};
/**
* Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated
* @param doc Parsed FBX document
* @param doc Parsed FBX document
* @param removeEmptyBones Will remove bones, which do not have any references to vertices.
*/
void ConvertToAssimpScene(aiScene* out, const Document& doc);
void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
/** Dummy class to encapsulate the conversion process */
class FBXConverter {
@@ -112,7 +122,7 @@ public:
};
public:
FBXConverter(aiScene* out, const Document& doc);
FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
~FBXConverter();
private:
@@ -144,6 +154,11 @@ private:
// while these would be allowed, they are a potential trouble spot so better not use them).
const char* NameTransformationComp(TransformationComp comp);
// ------------------------------------------------------------------------------------------------
// Returns an unique name for a node or traverses up a hierarchy until a non-empty name is found and
// then makes this name unique
std::string MakeUniqueNodeName(const Model* const model, const aiNode& parent);
// ------------------------------------------------------------------------------------------------
// note: this returns the REAL fbx property names
const char* NameTransformationCompProperty(TransformationComp comp);
@@ -167,7 +182,7 @@ private:
/**
* note: memory for output_nodes will be managed by the caller
*/
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
bool GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
// ------------------------------------------------------------------------------------------------
void SetupNodeMetadata(const Model& model, aiNode& nd);
@@ -414,12 +429,15 @@ private:
void ConvertGlobalSettings();
// ------------------------------------------------------------------------------------------------
// Will perform the conversion from a given unit to the requested unit.
void ConvertToUnitScale(FbxUnit unit);
// ------------------------------------------------------------------------------------------------
// copy generated meshes, animations, lights, cameras and textures to the output scene
void TransferDataToScene();
private:
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
@@ -429,26 +447,32 @@ private:
std::vector<aiLight*> lights;
std::vector<aiCamera*> cameras;
std::vector<aiTexture*> textures;
typedef std::map<const Material*, unsigned int> MaterialMap;
using MaterialMap = std::map<const Material*, unsigned int>;
MaterialMap materials_converted;
typedef std::map<const Video*, unsigned int> VideoMap;
using VideoMap = std::map<const Video*, unsigned int>;
VideoMap textures_converted;
typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >;
MeshMap meshes_converted;
// fixed node name -> which trafo chain components have animations?
typedef std::map<std::string, unsigned int> NodeAnimBitMap;
using NodeAnimBitMap = std::map<std::string, unsigned int> ;
NodeAnimBitMap node_anim_chain_bits;
// number of nodes with the same name
using NodeNameCache = std::unordered_map<std::string, unsigned int>;
NodeNameCache mNodeNames;
double anim_fps;
aiScene* const out;
const FBX::Document& doc;
bool mRemoveEmptyBones;
FbxUnit mCurrentUnit;
};
}
+4 -5
View File
@@ -69,8 +69,7 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
: doc(doc)
, element(element)
, id(id)
, flags()
{
, flags() {
// empty
}
@@ -84,7 +83,7 @@ LazyObject::~LazyObject()
const Object* LazyObject::Get(bool dieOnError)
{
if(IsBeingConstructed() || FailedToConstruct()) {
return NULL;
return nullptr;
}
if (object.get()) {
@@ -553,7 +552,7 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
LazyObject* Document::GetObject(uint64_t id) const
{
ObjectMap::const_iterator it = objects.find(id);
return it == objects.end() ? NULL : (*it).second;
return it == objects.end() ? nullptr : (*it).second;
}
#define MAX_CLASSNAMES 6
@@ -610,7 +609,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
for (size_t i = 0; i < c; ++i) {
ai_assert(classnames[i]);
if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
obtype = NULL;
obtype = nullptr;
break;
}
}
+46 -77
View File
@@ -85,13 +85,11 @@ class Cluster;
/** Represents a delay-parsed FBX objects. Many objects in the scene
* are not needed by assimp, so it makes no sense to parse them
* upfront. */
class LazyObject
{
class LazyObject {
public:
LazyObject(uint64_t id, const Element& element, const Document& doc);
~LazyObject();
public:
~LazyObject();
const Object* Get(bool dieOnError = false);
@@ -136,11 +134,8 @@ private:
unsigned int flags;
};
/** Base class for in-memory (DOM) representations of FBX objects */
class Object
{
class Object {
public:
Object(uint64_t id, const Element& element, const std::string& name);
@@ -164,14 +159,12 @@ protected:
const uint64_t id;
};
/** DOM class for generic FBX NoteAttribute blocks. NoteAttribute's just hold a property table,
* fixed members are added by deriving classes. */
class NodeAttribute : public Object
{
class NodeAttribute : public Object {
public:
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~NodeAttribute();
const PropertyTable& Props() const {
@@ -183,12 +176,11 @@ private:
std::shared_ptr<const PropertyTable> props;
};
/** DOM base class for FBX camera settings attached to a node */
class CameraSwitcher : public NodeAttribute
{
class CameraSwitcher : public NodeAttribute {
public:
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~CameraSwitcher();
int CameraID() const {
@@ -209,7 +201,6 @@ private:
std::string cameraIndexName;
};
#define fbx_stringize(a) #a
#define fbx_simple_property(name, type, default_value) \
@@ -230,13 +221,12 @@ private:
/** DOM base class for FBX cameras attached to a node */
class Camera : public NodeAttribute
{
class Camera : public NodeAttribute {
public:
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Camera();
public:
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0))
@@ -256,33 +246,26 @@ public:
fbx_simple_property(FocalLength, float, 1.0f)
};
/** DOM base class for FBX null markers attached to a node */
class Null : public NodeAttribute
{
class Null : public NodeAttribute {
public:
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Null();
};
/** DOM base class for FBX limb node markers attached to a node */
class LimbNode : public NodeAttribute
{
class LimbNode : public NodeAttribute {
public:
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~LimbNode();
};
/** DOM base class for FBX lights attached to a node */
class Light : public NodeAttribute
{
class Light : public NodeAttribute {
public:
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Light();
public:
enum Type
{
Type_Point,
@@ -304,7 +287,6 @@ public:
Decay_MAX // end-of-enum sentinel
};
public:
fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1))
fbx_simple_enum_property(LightType, Type, 0)
fbx_simple_property(CastLightOnObject, bool, false)
@@ -338,10 +320,8 @@ public:
fbx_simple_property(EnableBarnDoor, bool, true)
};
/** DOM base class for FBX models (even though its semantics are more "node" than "model" */
class Model : public Object
{
class Model : public Object {
public:
enum RotOrder {
RotOrder_EulerXYZ = 0,
@@ -356,7 +336,6 @@ public:
RotOrder_MAX // end-of-enum sentinel
};
enum TransformInheritance {
TransformInheritance_RrSs = 0,
TransformInheritance_RSrs,
@@ -490,13 +469,12 @@ private:
};
/** DOM class for generic FBX textures */
class Texture : public Object
{
class Texture : public Object {
public:
Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Texture();
public:
const std::string& Type() const {
return type;
}
@@ -551,17 +529,15 @@ private:
};
/** DOM class for layered FBX textures */
class LayeredTexture : public Object
{
class LayeredTexture : public Object {
public:
LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~LayeredTexture();
//Can only be called after construction of the layered texture object due to construction flag.
// Can only be called after construction of the layered texture object due to construction flag.
void fillTexture(const Document& doc);
enum BlendMode
{
enum BlendMode {
BlendMode_Translucent,
BlendMode_Additive,
BlendMode_Modulate,
@@ -623,13 +599,12 @@ typedef std::fbx_unordered_map<std::string, const LayeredTexture*> LayeredTextur
/** DOM class for generic FBX videos */
class Video : public Object
{
class Video : public Object {
public:
Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Video();
public:
const std::string& Type() const {
return type;
}
@@ -668,15 +643,15 @@ private:
std::string fileName;
std::shared_ptr<const PropertyTable> props;
uint32_t contentLength;
uint64_t contentLength;
uint8_t* content;
};
/** DOM class for generic FBX materials */
class Material : public Object
{
class Material : public Object {
public:
Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Material();
const std::string& GetShadingModel() const {
@@ -713,8 +688,7 @@ typedef std::vector<int64_t> KeyTimeList;
typedef std::vector<float> KeyValueList;
/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
class AnimationCurve : public Object
{
class AnimationCurve : public Object {
public:
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationCurve();
@@ -725,14 +699,12 @@ public:
return keys;
}
/** get list of keyframe values.
* Invariant: |GetKeys()| == |GetValues()| && |GetKeys()| > 0*/
const KeyValueList& GetValues() const {
return values;
}
const std::vector<float>& GetAttributes() const {
return attributes;
}
@@ -751,10 +723,8 @@ private:
// property-name -> animation curve
typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
/** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */
class AnimationCurveNode : public Object
{
class AnimationCurveNode : public Object {
public:
/* the optional white list specifies a list of property names for which the caller
wants animations for. If the curve node does not match one of these, std::range_error
@@ -804,8 +774,7 @@ private:
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
/** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object
{
class AnimationLayer : public Object {
public:
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationLayer();
@@ -818,7 +787,7 @@ public:
/* the optional white list specifies a list of property names for which the caller
wants animations for. Curves not matching this list will not be added to the
animation layer. */
AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0) const;
AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = nullptr, size_t whitelist_size = 0) const;
private:
std::shared_ptr<const PropertyTable> props;
@@ -828,8 +797,7 @@ private:
typedef std::vector<const AnimationLayer*> AnimationLayerList;
/** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object
{
class AnimationStack : public Object {
public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack();
@@ -855,8 +823,7 @@ private:
/** DOM class for deformers */
class Deformer : public Object
{
class Deformer : public Object {
public:
Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Deformer();
@@ -875,10 +842,10 @@ typedef std::vector<unsigned int> WeightIndexArray;
/** DOM class for BlendShapeChannel deformers */
class BlendShapeChannel : public Deformer
{
class BlendShapeChannel : public Deformer {
public:
BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~BlendShapeChannel();
float DeformPercent() const {
@@ -892,6 +859,7 @@ public:
const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
return shapeGeometries;
}
private:
float percent;
WeightArray fullWeights;
@@ -899,10 +867,10 @@ private:
};
/** DOM class for BlendShape deformers */
class BlendShape : public Deformer
{
class BlendShape : public Deformer {
public:
BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~BlendShape();
const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
@@ -913,11 +881,11 @@ private:
std::vector<const BlendShapeChannel*> blendShapeChannels;
};
/** DOM class for skin deformer clusters (aka subdeformers) */
class Cluster : public Deformer
{
/** DOM class for skin deformer clusters (aka sub-deformers) */
class Cluster : public Deformer {
public:
Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Cluster();
/** get the list of deformer weights associated with this cluster.
@@ -958,10 +926,10 @@ private:
};
/** DOM class for skin deformers */
class Skin : public Deformer
{
class Skin : public Deformer {
public:
Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Skin();
float DeformAccuracy() const {
@@ -978,10 +946,10 @@ private:
};
/** Represents a link between two FBX objects. */
class Connection
{
class Connection {
public:
Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc);
~Connection();
// note: a connection ensures that the source and dest objects exist, but
@@ -1006,7 +974,7 @@ public:
}
int CompareTo(const Connection* c) const {
ai_assert( NULL != c );
ai_assert( nullptr != c );
// note: can't subtract because this would overflow uint64_t
if(InsertionOrder() > c->InsertionOrder()) {
@@ -1019,7 +987,7 @@ public:
}
bool Compare(const Connection* c) const {
ai_assert( NULL != c );
ai_assert( nullptr != c );
return InsertionOrder() < c->InsertionOrder();
}
@@ -1047,6 +1015,7 @@ typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
class FileGlobalSettings {
public:
FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props);
~FileGlobalSettings();
const PropertyTable& Props() const {
@@ -1103,10 +1072,10 @@ private:
};
/** DOM root for a FBX file */
class Document
{
class Document {
public:
Document(const Parser& parser, const ImportSettings& settings);
~Document();
LazyObject* GetObject(uint64_t id) const;
+6 -8
View File
@@ -56,7 +56,6 @@ namespace Assimp {
namespace FBX {
namespace Util {
/* DOM/Parse error reporting - does not return */
AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
@@ -73,28 +72,28 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
const Scope& sc,
bool no_warn = false);
// ------------------------------------------------------------------------------------------------
template <typename T>
inline const T* ProcessSimpleConnection(const Connection& con,
inline
const T* ProcessSimpleConnection(const Connection& con,
bool is_object_property_conn,
const char* name,
const Element& element,
const char** propNameOut = NULL)
const char** propNameOut = nullptr)
{
if (is_object_property_conn && !con.PropertyName().length()) {
DOMWarning("expected incoming " + std::string(name) +
" link to be an object-object connection, ignoring",
&element
);
return NULL;
return nullptr;
}
else if (!is_object_property_conn && con.PropertyName().length()) {
DOMWarning("expected incoming " + std::string(name) +
" link to be an object-property connection, ignoring",
&element
);
return NULL;
return nullptr;
}
if(is_object_property_conn && propNameOut) {
@@ -108,13 +107,12 @@ inline const T* ProcessSimpleConnection(const Connection& con,
DOMWarning("failed to read source object for incoming " + std::string(name) +
" link, ignoring",
&element);
return NULL;
return nullptr;
}
return dynamic_cast<const T*>(ob);
}
} //!Util
} //!FBX
} //!Assimp
+9 -6
View File
@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream> // ostringstream
#include <memory> // shared_ptr
namespace Assimp {
// AddP70<type> helpers... there's no usable pattern here,
// so all are defined as separate functions.
// Even "animatable" properties are often completely different
@@ -252,7 +253,8 @@ void FBX::Node::DumpChildren(
} else {
std::ostringstream ss;
DumpChildrenAscii(ss, indent);
s.PutString(ss.str());
if (ss.tellp() > 0)
s.PutString(ss.str());
}
}
@@ -266,7 +268,8 @@ void FBX::Node::End(
} else {
std::ostringstream ss;
EndAscii(ss, indent, has_children);
s.PutString(ss.str());
if (ss.tellp() > 0)
s.PutString(ss.str());
}
}
@@ -367,7 +370,7 @@ void FBX::Node::EndBinary(
bool has_children
) {
// 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
this->end_pos = s.Tell();
@@ -432,7 +435,7 @@ void FBX::Node::WritePropertyNodeAscii(
char buffer[32];
FBX::Node node(name);
node.Begin(s, false, indent);
std::string vsize = std::to_string(v.size());
std::string vsize = to_string(v.size());
// *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1
@@ -468,7 +471,7 @@ void FBX::Node::WritePropertyNodeAscii(
char buffer[32];
FBX::Node node(name);
node.Begin(s, false, indent);
std::string vsize = std::to_string(v.size());
std::string vsize = to_string(v.size());
// *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1
@@ -563,6 +566,6 @@ void FBX::Node::WritePropertyNode(
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
}
}
}
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT
+6 -6
View File
@@ -54,16 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
namespace Assimp {
namespace FBX {
class Node;
}
class FBX::Node
{
public: // public data members
class FBX::Node {
public:
// TODO: accessors
std::string name; // node name
std::vector<FBX::Property> properties; // node properties
std::vector<FBX::FBXExportProperty> properties; // node properties
std::vector<FBX::Node> children; // child nodes
// some nodes always pretend they have children...
@@ -214,7 +214,7 @@ public: // static member functions
Assimp::StreamWriterLE& s,
bool binary, int indent
) {
FBX::Property p(value);
FBX::FBXExportProperty p(value);
FBX::Node node(name, p);
node.Dump(s, binary, indent);
}
@@ -264,7 +264,7 @@ private: // static helper functions
);
};
}
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
+141 -116
View File
@@ -52,187 +52,210 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <locale>
#include <sstream> // ostringstream
namespace Assimp {
namespace FBX {
// constructors for single element properties
FBX::Property::Property(bool v)
: type('C'), data(1)
{
data = {uint8_t(v)};
FBXExportProperty::FBXExportProperty(bool v)
: type('C')
, data(1) {
data = {
uint8_t(v)
};
}
FBX::Property::Property(int16_t v) : type('Y'), data(2)
{
FBXExportProperty::FBXExportProperty(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)
{
FBXExportProperty::FBXExportProperty(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)
{
FBXExportProperty::FBXExportProperty(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)
{
FBXExportProperty::FBXExportProperty(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)
{
FBXExportProperty::FBXExportProperty(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)
{}
FBXExportProperty::FBXExportProperty(const char* c, bool raw)
: FBXExportProperty(std::string(c), raw) {
// empty
}
// 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())
{
FBXExportProperty::FBXExportProperty(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)
{}
FBXExportProperty::FBXExportProperty(const std::vector<uint8_t>& r)
: type('R')
, data(r) {
// empty
}
FBX::Property::Property(const std::vector<int32_t>& va)
: type('i'), data(4*va.size())
{
FBXExportProperty::FBXExportProperty(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]; }
for (size_t i = 0; i < va.size(); ++i) {
d[i] = va[i];
}
}
FBX::Property::Property(const std::vector<int64_t>& va)
: type('l'), data(8*va.size())
{
FBXExportProperty::FBXExportProperty(const std::vector<int64_t>& va)
: type('l')
, data(8 * va.size()) {
int64_t* d = reinterpret_cast<int64_t*>(data.data());
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
for (size_t i = 0; i < va.size(); ++i) {
d[i] = va[i];
}
}
FBX::Property::Property(const std::vector<float>& va)
: type('f'), data(4*va.size())
{
FBXExportProperty::FBXExportProperty(const std::vector<float>& va)
: type('f')
, data(4 * va.size()) {
float* d = reinterpret_cast<float*>(data.data());
for (size_t i = 0; i < va.size(); ++i) { d[i] = va[i]; }
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())
{
FBXExportProperty::FBXExportProperty(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]; }
for (size_t i = 0; i < va.size(); ++i) {
d[i] = va[i];
}
}
FBX::Property::Property(const aiMatrix4x4& vm)
: type('d'), data(8*16)
{
FBXExportProperty::FBXExportProperty(const aiMatrix4x4& vm)
: type('d')
, data(8 * 16) {
double* d = reinterpret_cast<double*>(data.data());
for (unsigned int c = 0; c < 4; ++c) {
for (unsigned int r = 0; r < 4; ++r) {
d[4*c+r] = vm[r][c];
d[4 * c + r] = vm[r][c];
}
}
}
// public member functions
size_t FBX::Property::size()
{
size_t FBXExportProperty::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");
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::DumpBinary(Assimp::StreamWriterLE &s)
{
void FBXExportProperty::DumpBinary(Assimp::StreamWriterLE& s) {
s.PutU1(type);
uint8_t* d = data.data();
size_t N;
switch (type) {
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
case 'S':
case 'R':
s.PutU4(uint32_t(data.size()));
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
return;
case 'i':
N = data.size() / 4;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
}
return;
case 'l':
N = data.size() / 8;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
}
return;
case 'f':
N = data.size() / 4;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutF4((reinterpret_cast<float*>(d))[i]);
}
return;
case 'd':
N = data.size() / 8;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutF8((reinterpret_cast<double*>(d))[i]);
}
return;
default:
std::ostringstream err;
err << "Tried to dump property with invalid type '";
err << type << "'!";
throw DeadlyExportError(err.str());
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
case 'S':
case 'R':
s.PutU4(uint32_t(data.size()));
for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); }
return;
case 'i':
N = data.size() / 4;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
}
return;
case 'l':
N = data.size() / 8;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
}
return;
case 'f':
N = data.size() / 4;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutF4((reinterpret_cast<float*>(d))[i]);
}
return;
case 'd':
N = data.size() / 8;
s.PutU4(uint32_t(N)); // number of elements
s.PutU4(0); // no encoding (1 would be zip-compressed)
// TODO: compress if large?
s.PutU4(uint32_t(data.size())); // data size
for (size_t i = 0; i < N; ++i) {
s.PutF8((reinterpret_cast<double*>(d))[i]);
}
return;
default:
std::ostringstream err;
err << "Tried to dump property with invalid type '";
err << type << "'!";
throw DeadlyExportError(err.str());
}
}
void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
{
void FBXExportProperty::DumpAscii(Assimp::StreamWriterLE& outstream, int indent) {
std::ostringstream ss;
ss.imbue(std::locale::classic());
ss.precision(15); // this seems to match official FBX SDK exports
@@ -240,8 +263,7 @@ void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
outstream.PutString(ss.str());
}
void FBX::Property::DumpAscii(std::ostream& s, int indent)
{
void FBXExportProperty::DumpAscii(std::ostream& s, int indent) {
// no writing type... or anything. just shove it into the stream.
uint8_t* d = data.data();
size_t N;
@@ -360,5 +382,8 @@ void FBX::Property::DumpAscii(std::ostream& s, int indent)
}
}
} // Namespace FBX
} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT
+24 -24
View File
@@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
#include <assimp/types.h> // aiMatrix4x4
#include <assimp/StreamWriter.h> // StreamWriterLE
@@ -56,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ostream>
#include <type_traits> // is_void
namespace Assimp {
namespace FBX {
class Property;
}
/** FBX::Property
/** @brief FBX::Property
*
* Holds a value of any of FBX's recognized types,
* each represented by a particular one-character code.
@@ -78,35 +76,34 @@ namespace FBX {
* S : string (array of 1-byte char)
* R : raw data (array of bytes)
*/
class FBX::Property
{
class FBXExportProperty {
public:
// constructors for basic types.
// all explicit to avoid accidental typecasting
explicit Property(bool v);
explicit FBXExportProperty(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);
explicit FBXExportProperty(int16_t v);
explicit FBXExportProperty(int32_t v);
explicit FBXExportProperty(float v);
explicit FBXExportProperty(double v);
explicit FBXExportProperty(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<int64_t>& va);
explicit Property(const std::vector<double>& va);
explicit Property(const std::vector<float>& va);
explicit Property(const aiMatrix4x4& vm);
explicit FBXExportProperty(const char* c, bool raw = false);
explicit FBXExportProperty(const std::string& s, bool raw = false);
explicit FBXExportProperty(const std::vector<uint8_t>& r);
explicit FBXExportProperty(const std::vector<int32_t>& va);
explicit FBXExportProperty(const std::vector<int64_t>& va);
explicit FBXExportProperty(const std::vector<double>& va);
explicit FBXExportProperty(const std::vector<float>& va);
explicit FBXExportProperty(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') {
explicit FBXExportProperty(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
@@ -114,9 +111,9 @@ public:
size_t size();
// write this property node as binary data to the given stream
void DumpBinary(Assimp::StreamWriterLE &s);
void DumpAscii(Assimp::StreamWriterLE &s, int indent=0);
void DumpAscii(std::ostream &s, int indent=0);
void DumpBinary(Assimp::StreamWriterLE& s);
void DumpAscii(Assimp::StreamWriterLE& s, int indent = 0);
void DumpAscii(std::ostream& s, int indent = 0);
// note: make sure the ostream is in classic "C" locale
private:
@@ -124,6 +121,9 @@ private:
std::vector<uint8_t> data;
};
} // Namespace FBX
} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
#endif // AI_FBXEXPORTPROPERTY_H_INC
+59 -25
View File
@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXExportNode.h"
#include "FBXExportProperty.h"
#include "FBXCommon.h"
#include "FBXUtil.h"
#include <assimp/version.h> // aiGetVersion
#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
using namespace Assimp;
using namespace Assimp::FBX;
// some constants that we'll use for writing metadata
namespace Assimp {
namespace FBX {
const std::string EXPORT_VERSION_STR = "7.4.0";
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.
// Prototyped and registered in Exporter.cpp
@@ -121,6 +121,7 @@ namespace Assimp {
IOSystem* pIOSystem,
const aiScene* pScene,
const ExportProperties* pProperties
){
// initialize the exporter
FBXExporter exporter(pScene, pProperties);
@@ -1393,10 +1394,6 @@ void FBXExporter::WriteObjects ()
// FbxVideo - stores images used by textures.
for (const auto &it : uid_by_image) {
if (it.first.compare(0, 1, "*") == 0) {
// TODO: embedded textures
continue;
}
FBX::Node n("Video");
const int64_t& uid = it.second;
const std::string name = ""; // TODO: ... name???
@@ -1406,7 +1403,33 @@ void FBXExporter::WriteObjects ()
// TODO: get full path... relative path... etc... ugh...
// for now just use the same path for everything,
// 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);
n.AddChild(p);
n.AddChild("UseMipMap", int32_t(0));
@@ -1419,17 +1442,17 @@ void FBXExporter::WriteObjects ()
// referenced by material_index/texture_type pairs.
std::map<std::pair<size_t,size_t>,int64_t> texture_uids;
const std::map<aiTextureType,std::string> prop_name_by_tt = {
{aiTextureType_DIFFUSE, "DiffuseColor"},
{aiTextureType_SPECULAR, "SpecularColor"},
{aiTextureType_AMBIENT, "AmbientColor"},
{aiTextureType_EMISSIVE, "EmissiveColor"},
{aiTextureType_HEIGHT, "Bump"},
{aiTextureType_NORMALS, "NormalMap"},
{aiTextureType_SHININESS, "ShininessExponent"},
{aiTextureType_OPACITY, "TransparentColor"},
{aiTextureType_DIFFUSE, "DiffuseColor"},
{aiTextureType_SPECULAR, "SpecularColor"},
{aiTextureType_AMBIENT, "AmbientColor"},
{aiTextureType_EMISSIVE, "EmissiveColor"},
{aiTextureType_HEIGHT, "Bump"},
{aiTextureType_NORMALS, "NormalMap"},
{aiTextureType_SHININESS, "ShininessExponent"},
{aiTextureType_OPACITY, "TransparentColor"},
{aiTextureType_DISPLACEMENT, "DisplacementColor"},
//{aiTextureType_LIGHTMAP, "???"},
{aiTextureType_REFLECTION, "ReflectionColor"}
{aiTextureType_REFLECTION, "ReflectionColor"}
//{aiTextureType_UNKNOWN, ""}
};
for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
@@ -1575,11 +1598,22 @@ void FBXExporter::WriteObjects ()
// one sticky point is that the number of vertices may not match,
// because assimp splits vertices by normal, uv, etc.
// functor for aiNode sorting
struct SortNodeByName
{
bool operator()(const aiNode *lhs, const aiNode *rhs) const
{
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
}
};
// first we should mark the skeleton for each mesh.
// the skeleton must include not only the aiBones,
// but also all their parent nodes.
// anything that affects the position of any bone node must be included.
std::vector<std::set<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
// Use SorNodeByName to make sure the exported result will be the same across all systems
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
// at the same time we can build a list of all the skeleton nodes,
// which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes;
@@ -1587,7 +1621,7 @@ void FBXExporter::WriteObjects ()
std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
std::set<const aiNode*> skeleton;
std::set<const aiNode*, SortNodeByName> skeleton;
for (size_t bi =0; bi < m->mNumBones; ++bi) {
const aiBone* b = m->mBones[bi];
const std::string name(b->mName.C_Str());
@@ -1728,7 +1762,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
// now make a subdeformer for each bone in the skeleton
const std::set<const aiNode*> &skeleton = skeleton_by_mesh[mi];
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
for (const aiNode* bone_node : skeleton) {
// if there's a bone for this node, find it
const aiBone* b = nullptr;
@@ -2237,8 +2271,8 @@ void FBXExporter::WriteModelNode(
// not sure what these are for,
// but they seem to be omnipresent
m.AddChild("Shading", Property(true));
m.AddChild("Culling", Property("CullingOff"));
m.AddChild("Shading", FBXExportProperty(true));
m.AddChild("Culling", FBXExportProperty("CullingOff"));
m.Dump(outstream, binary, 1);
}
@@ -2351,7 +2385,7 @@ void FBXExporter::WriteModelNodes(
na.AddProperties(
node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
);
na.AddChild("TypeFlags", Property("Skeleton"));
na.AddChild("TypeFlags", FBXExportProperty("Skeleton"));
na.Dump(outstream, binary, 1);
// and connect them
connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
+25 -14
View File
@@ -53,19 +53,22 @@ namespace FBX {
struct ImportSettings
{
ImportSettings()
: strictMode(true)
, readAllLayers(true)
, readAllMaterials(false)
, readMaterials(true)
, readTextures(true)
, readCameras(true)
, readLights(true)
, readAnimations(true)
, readWeights(true)
, preservePivots(true)
, optimizeEmptyAnimationCurves(true)
, useLegacyEmbeddedTextureNaming(false)
{}
: strictMode(true)
, readAllLayers(true)
, readAllMaterials(false)
, readMaterials(true)
, readTextures(true)
, readCameras(true)
, readLights(true)
, readAnimations(true)
, readWeights(true)
, preservePivots(true)
, optimizeEmptyAnimationCurves(true)
, useLegacyEmbeddedTextureNaming(false)
, removeEmptyBones( true )
, convertToMeters( false ) {
// empty
}
/** enable strict mode:
@@ -141,8 +144,16 @@ struct ImportSettings
bool optimizeEmptyAnimationCurves;
/** use legacy naming for embedded textures eg: (*0, *1, *2)
**/
*/
bool useLegacyEmbeddedTextureNaming;
/** Empty bones shall be removed
*/
bool removeEmptyBones;
/** Set to true to perform a conversion from cm to meter after the import
*/
bool convertToMeters;
};
+16 -7
View File
@@ -60,11 +60,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/importerdesc.h>
namespace Assimp {
template<> const char* LogFunctions<FBXImporter>::Prefix()
{
static auto prefix = "FBX: ";
return prefix;
}
template<>
const char* LogFunctions<FBXImporter>::Prefix() {
static auto prefix = "FBX: ";
return prefix;
}
}
using namespace Assimp;
@@ -72,6 +74,7 @@ using namespace Assimp::Formatter;
using namespace Assimp::FBX;
namespace {
static const aiImporterDesc desc = {
"Autodesk FBX Importer",
"",
@@ -137,6 +140,8 @@ void FBXImporter::SetupProperties(const Importer* pImp)
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
}
// ------------------------------------------------------------------------------------------------
@@ -167,7 +172,7 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
bool is_binary = false;
if (!strncmp(begin,"Kaydara FBX Binary",18)) {
is_binary = true;
TokenizeBinary(tokens,begin,static_cast<unsigned int>(contents.size()));
TokenizeBinary(tokens,begin,contents.size());
}
else {
Tokenize(tokens,begin);
@@ -180,8 +185,12 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// take the raw parse-tree and convert it to a FBX DOM
Document doc(parser,settings);
FbxUnit unit(FbxUnit::cm);
if (settings.convertToMeters) {
unit = FbxUnit::m;
}
// convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene,doc);
ConvertToAssimpScene(pScene,doc, settings.removeEmptyBones, unit);
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
}
+60 -3
View File
@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h>
#include <algorithm> // std::transform
#include "FBXUtil.h"
namespace Assimp {
namespace FBX {
@@ -206,6 +207,20 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
// 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
bool ok;
const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
if (ok) {
uvScaling.x = scaling.x;
uvScaling.y = scaling.y;
}
const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
if (ok) {
uvTrans.x = trans.x;
uvTrans.y = trans.y;
}
// resolve video links
if(doc.Settings().readTextures) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@@ -301,13 +316,52 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
}
if(Content) {
if(Content && !Content->Tokens().empty()) {
//this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
try {
const Token& token = GetRequiredToken(*Content, 0);
const char* data = token.begin();
if (!token.IsBinary()) {
DOMWarning("video content is not binary data, ignoring", &element);
if (*data != '"') {
DOMError("embedded content is not surrounded by quotation marks", &element);
}
else {
size_t targetLength = 0;
auto numTokens = Content->Tokens().size();
// First time compute size (it could be large like 64Gb and it is good to allocate it once)
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
{
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1;
const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
if (outLength == 0)
{
DOMError("Corrupted embedded content found", &element);
}
targetLength += outLength;
}
if (targetLength == 0)
{
DOMError("Corrupted embedded content found", &element);
}
content = new uint8_t[targetLength];
contentLength = static_cast<uint64_t>(targetLength);
size_t dst_offset = 0;
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx)
{
const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1;
dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
}
if (targetLength != dst_offset)
{
delete[] content;
contentLength = 0;
DOMError("Corrupted embedded content found", &element);
}
}
}
else if (static_cast<size_t>(token.end() - data) < 5) {
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
@@ -326,8 +380,11 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
content = new uint8_t[len];
::memcpy(content, data + 5, len);
}
} catch (runtime_error runtimeError) {
} catch (const runtime_error& runtimeError)
{
//we don't need the content data for contents that has already been loaded
ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
runtimeError.what());
}
}
+6 -5
View File
@@ -568,15 +568,15 @@ void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, cons
}
// ------------------------------------------------------------------------------------------------
static const std::string TangentIndexToken = "TangentIndex";
static const std::string TangentsIndexToken = "TangentsIndex";
static const char *TangentIndexToken = "TangentIndex";
static const char *TangentsIndexToken = "TangentsIndex";
void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
const std::string& MappingInformationType,
const std::string& ReferenceInformationType)
{
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str();
const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken : TangentIndexToken;
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
str,
strIdx,
@@ -630,10 +630,11 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
materials_out.clear();
}
m_materials.assign(m_vertices.size(),materials_out[0]);
materials_out.resize(m_vertices.size());
std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
}
else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
m_materials.resize(face_count);
materials_out.resize(face_count);
if(materials_out.size() != face_count) {
FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
+4 -4
View File
@@ -117,7 +117,7 @@ namespace FBX {
Element::Element(const Token& key_token, Parser& parser)
: key_token(key_token)
{
TokenPtr n = NULL;
TokenPtr n = nullptr;
do {
n = parser.AdvanceToNextToken();
if(!n) {
@@ -643,9 +643,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
if (type == 'd') {
const double* d = reinterpret_cast<const double*>(&buff[0]);
for (unsigned int i = 0; i < count3; ++i, d += 3) {
out.push_back(aiVector3D(static_cast<float>(d[0]),
static_cast<float>(d[1]),
static_cast<float>(d[2])));
out.push_back(aiVector3D(static_cast<ai_real>(d[0]),
static_cast<ai_real>(d[1]),
static_cast<ai_real>(d[2])));
}
// for debugging
/*for ( size_t i = 0; i < out.size(); i++ ) {
+6 -6
View File
@@ -93,7 +93,7 @@ public:
Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column);
/** construct a binary token */
Token(const char* sbegin, const char* send, TokenType type, unsigned int offset);
Token(const char* sbegin, const char* send, TokenType type, size_t offset);
~Token();
@@ -118,14 +118,14 @@ public:
return type;
}
unsigned int Offset() const {
size_t Offset() const {
ai_assert(IsBinary());
return offset;
}
unsigned int Line() const {
ai_assert(!IsBinary());
return line;
return static_cast<unsigned int>(line);
}
unsigned int Column() const {
@@ -147,8 +147,8 @@ private:
const TokenType type;
union {
const unsigned int line;
unsigned int offset;
size_t line;
size_t offset;
};
const unsigned int column;
};
@@ -178,7 +178,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
* @param input_buffer Binary input buffer to be processed.
* @param length Length of input buffer, in bytes. There is no 0-terminal.
* @throw DeadlyImportError if something goes wrong */
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length);
void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
} // ! FBX
+124 -1
View File
@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/TinyFormatter.h>
#include <string>
#include <cstring>
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -85,7 +86,7 @@ const char* TokenTypeString(TokenType t)
// ------------------------------------------------------------------------------------------------
std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset)
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset)
{
return static_cast<std::string>( (Formatter::format() << prefix << " (offset 0x" << std::hex << offset << ") " << text) );
}
@@ -113,6 +114,128 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
text) );
}
// Generated by this formula: T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;
static const uint8_t base64DecodeTable[128] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
};
uint8_t DecodeBase64(char ch)
{
const auto idx = static_cast<uint8_t>(ch);
if (idx > 127)
return 255;
return base64DecodeTable[idx];
}
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength)
{
if (inLength < 2)
{
return 0;
}
const size_t equals = size_t(in[inLength - 1] == '=') + size_t(in[inLength - 2] == '=');
const size_t full_length = (inLength * 3) >> 2; // div by 4
if (full_length < equals)
{
return 0;
}
return full_length - equals;
}
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength)
{
if (maxOutLength == 0 || inLength < 2) {
return 0;
}
const size_t realLength = inLength - size_t(in[inLength - 1] == '=') - size_t(in[inLength - 2] == '=');
size_t dst_offset = 0;
int val = 0, valb = -8;
for (size_t src_offset = 0; src_offset < realLength; ++src_offset)
{
const uint8_t table_value = Util::DecodeBase64(in[src_offset]);
if (table_value == 255)
{
return 0;
}
val = (val << 6) + table_value;
valb += 6;
if (valb >= 0)
{
out[dst_offset++] = static_cast<uint8_t>((val >> valb) & 0xFF);
valb -= 8;
val &= 0xFFF;
}
}
return dst_offset;
}
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
} // !FBX
} // !Assimp
+33 -1
View File
@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXCompileConfig.h"
#include "FBXTokenizer.h"
#include <stdint.h>
namespace Assimp {
namespace FBX {
@@ -77,7 +78,7 @@ const char* TokenTypeString(TokenType t);
* @param line Line index, 1-based
* @param column Column index, 1-based
* @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/
std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset);
std::string AddOffset(const std::string& prefix, const std::string& text, size_t offset);
/** Format log/error messages using a given line location in the source file.
@@ -98,6 +99,37 @@ std::string AddLineAndColumn(const std::string& prefix, const std::string& text,
* @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
/** Decode a single Base64-encoded character.
*
* @param ch Character to decode (from base64 to binary).
* @return decoded byte value*/
uint8_t DecodeBase64(char ch);
/** Compute decoded size of a Base64-encoded string
*
* @param in Characters to decode.
* @param inLength Number of characters to decode.
* @return size of the decoded data (number of bytes)*/
size_t ComputeDecodedSizeBase64(const char* in, size_t inLength);
/** Decode a Base64-encoded string
*
* @param in Characters to decode.
* @param inLength Number of characters to decode.
* @param out Pointer where we will store the decoded data.
* @param maxOutLength Size of output buffer.
* @return size of the decoded data (number of bytes)*/
size_t DecodeBase64(const char* in, size_t inLength, uint8_t* out, size_t maxOutLength);
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);
}
}
}
Executable → Regular
View File
+1
View File
@@ -228,6 +228,7 @@ bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
if ( area < 1e-6 ) {
if ( mConfigRemoveDegenerates ) {
remove_me[ a ] = true;
++deg;
goto evil_jump_outside;
}
+16 -16
View File
@@ -137,6 +137,11 @@ void FindInstancesProcess::Execute( aiScene* pScene)
aiMesh* inst = pScene->mMeshes[i];
hashes[i] = GetMeshHash(inst);
// Find an appropriate epsilon
// to compare position differences against
float epsilon = ComputePositionEpsilon(inst);
epsilon *= epsilon;
for (int a = i-1; a >= 0; --a) {
if (hashes[i] == hashes[a])
{
@@ -154,12 +159,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
orig->mPrimitiveTypes != inst->mPrimitiveTypes)
continue;
// up to now the meshes are equal. find an appropriate
// epsilon to compare position differences against
float epsilon = ComputePositionEpsilon(inst);
epsilon *= epsilon;
// now compare vertex positions, normals,
// up to now the meshes are equal. Now compare vertex positions, normals,
// tangents and bitangents using this epsilon.
if (orig->HasPositions()) {
if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))
@@ -178,30 +178,30 @@ void FindInstancesProcess::Execute( aiScene* pScene)
// use a constant epsilon for colors and UV coordinates
static const float uvEpsilon = 10e-4f;
{
unsigned int i, end = orig->GetNumUVChannels();
for(i = 0; i < end; ++i) {
if (!orig->mTextureCoords[i]) {
unsigned int j, end = orig->GetNumUVChannels();
for(j = 0; j < end; ++j) {
if (!orig->mTextureCoords[j]) {
continue;
}
if(!CompareArrays(orig->mTextureCoords[i],inst->mTextureCoords[i],orig->mNumVertices,uvEpsilon)) {
if(!CompareArrays(orig->mTextureCoords[j],inst->mTextureCoords[j],orig->mNumVertices,uvEpsilon)) {
break;
}
}
if (i != end) {
if (j != end) {
continue;
}
}
{
unsigned int i, end = orig->GetNumColorChannels();
for(i = 0; i < end; ++i) {
if (!orig->mColors[i]) {
unsigned int j, end = orig->GetNumColorChannels();
for(j = 0; j < end; ++j) {
if (!orig->mColors[j]) {
continue;
}
if(!CompareArrays(orig->mColors[i],inst->mColors[i],orig->mNumVertices,uvEpsilon)) {
if(!CompareArrays(orig->mColors[j],inst->mColors[j],orig->mNumVertices,uvEpsilon)) {
break;
}
}
if (i != end) {
if (j != end) {
continue;
}
}
+6 -4
View File
@@ -282,9 +282,11 @@ void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) {
// ------------------------------------------------------------------------------------------------
void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) {
ai_assert( 0 != anim->mPositionKeys );
ai_assert( 0 != anim->mRotationKeys );
ai_assert( 0 != anim->mScalingKeys );
ai_assert( nullptr != anim );
if (anim->mNumPositionKeys == 0 && anim->mNumRotationKeys == 0 && anim->mNumScalingKeys == 0) {
ai_assert_entry();
return;
}
// Check whether all values in a tracks are identical - in this case
// we can remove al keys except one.
@@ -328,7 +330,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) {
// ------------------------------------------------------------------------------------------------
// Search a mesh for invalid contents
int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
int FindInvalidDataProcess::ProcessMesh(aiMesh* pMesh)
{
bool ret = false;
std::vector<bool> dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces != 0);
+12 -13
View File
@@ -300,13 +300,10 @@ int ClampSpline(int idx, int size) {
// ------------------------------------------------------------------------------------------------
inline void FindSuitableMultiple(int& angle)
{
if (angle < 3)angle = 3;
if (angle < 3) angle = 3;
else if (angle < 10) angle = 10;
else if (angle < 20) angle = 20;
else if (angle < 30) angle = 30;
else
{
}
}
// ------------------------------------------------------------------------------------------------
@@ -317,6 +314,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
// XXX totally WIP - doesn't produce proper results, need to evaluate
// whether there's any use for Irrlicht's proprietary scene format
// outside Irrlicht ...
// This also applies to the above function of FindSuitableMultiple and ClampSpline which are
// solely used in this function
if (root->animators.empty()) {
return;
@@ -674,38 +673,38 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
// Get the loaded mesh from the scene and add it to
// the list of all scenes to be attached to the
// graph we're currently building
aiScene* scene = batch.GetImport(root->id);
if (!scene) {
aiScene* localScene = batch.GetImport(root->id);
if (!localScene) {
ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
break;
}
attach.push_back(AttachmentInfo(scene,rootOut));
attach.push_back(AttachmentInfo(localScene,rootOut));
// Now combine the material we've loaded for this mesh
// with the real materials we got from the file. As we
// don't execute any pp-steps on the file, the numbers
// should be equal. If they are not, we can impossibly
// do this ...
if (root->materials.size() != (unsigned int)scene->mNumMaterials) {
if (root->materials.size() != (unsigned int)localScene->mNumMaterials) {
ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
"with the materials found in the IRR scene file");
break;
}
for (unsigned int i = 0; i < scene->mNumMaterials;++i) {
for (unsigned int i = 0; i < localScene->mNumMaterials;++i) {
// Delete the old material, we don't need it anymore
delete scene->mMaterials[i];
delete localScene->mMaterials[i];
std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
scene->mMaterials[i] = src.first;
localScene->mMaterials[i] = src.first;
}
// NOTE: Each mesh should have exactly one material assigned,
// but we do it in a separate loop if this behaviour changes
// in future.
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
for (unsigned int i = 0; i < localScene->mNumMeshes;++i) {
// Process material flags
aiMesh* mesh = scene->mMeshes[i];
aiMesh* mesh = localScene->mMeshes[i];
// If "trans_vertex_alpha" mode is enabled, search all vertex colors
+1 -1
View File
@@ -256,7 +256,7 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
IfcVector3 b01 = boundary[(i + 1) % bcount] - boundary[i];
IfcVector3 b12 = boundary[(i + 2) % bcount] - boundary[(i + 1) % bcount];
IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
// Warning: rough estimate only. A concave poly with lots of small segments each featuring a small counter rotation
// could fool the accumulation. Correct implementation would be sum( acos( b01 * b2) * sign( b12 * b1_side))
windingOrder += (b1_side.x*b12.x + b1_side.y*b12.y);
+3 -3
View File
@@ -278,10 +278,10 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char> );
const char* sz = scheme.GetStaticStringForToken(type);
if(sz) {
const std::string::size_type len = n2-n1+1;
char* const copysz = new char[len+1];
const std::string::size_type szLen = n2-n1+1;
char* const copysz = new char[szLen+1];
std::copy(s.c_str()+n1,s.c_str()+n2+1,copysz);
copysz[len] = '\0';
copysz[szLen] = '\0';
db.InternInsert(new LazyObject(db,id,line,sz,copysz));
}
if(!has_next) {
+3 -1
View File
@@ -112,7 +112,9 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
}
}
if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf," faces). Average output ACMR is ", out / numf );
if (numf > 0) {
ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf, " faces). Average output ACMR is ", out / numf);
}
ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. ");
}
}
+1 -4
View File
@@ -320,13 +320,10 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
// opacity ... either additive or default-blended, please
if (0.0 != surf.mAdditiveTransparency) {
const int add = aiBlendMode_Additive;
pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
}
else if (10e10f != surf.mTransparency) {
} else if (10e10f != surf.mTransparency) {
const int def = aiBlendMode_Default;
const float f = 1.0f-surf.mTransparency;
pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
+5 -5
View File
@@ -59,7 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Compiler/pushpack1.h>
namespace Assimp {
namespace Assimp {
namespace MD3 {
// to make it easier for us, we test the magic word against both "endianesses"
@@ -303,12 +303,12 @@ inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut )
b = int(57.2957795f * ( std::acos( p_vIn[2] ) ) * ( 255.0f / 360.0f ));
b &= 0xff;
((unsigned char*)&p_iOut)[0] = b; // longitude
((unsigned char*)&p_iOut)[1] = a; // latitude
((unsigned char*)&p_iOut)[0] = (unsigned char) b; // longitude
((unsigned char*)&p_iOut)[1] = (unsigned char) a; // latitude
}
}
}
}
} // Namespace MD3
} // Namespace Assimp
#endif // !! AI_MD3FILEHELPER_H_INC
+27 -25
View File
@@ -258,10 +258,10 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
continue;
fill.textures.push_back(SkinData::TextureEntry());
SkinData::TextureEntry& s = fill.textures.back();
SkinData::TextureEntry &entry = fill.textures.back();
s.first = ss;
s.second = GetNextToken(buff);
entry.first = ss;
entry.second = GetNextToken(buff);
}
return true;
}
@@ -718,9 +718,7 @@ void MD3Importer::ConvertPath(const char* texture_name, const char* header_name,
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void MD3Importer::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
void MD3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
mFile = pFile;
mScene = pScene;
mIOHandler = pIOHandler;
@@ -730,11 +728,13 @@ void MD3Importer::InternReadFile( const std::string& pFile,
std::string::size_type s = mFile.find_last_of("/\\");
if (s == std::string::npos) {
s = 0;
} else {
++s;
}
filename = mFile.substr(s), path = mFile.substr(0, s);
for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) {
*it = static_cast<char>( tolower(*it) );
}
else ++s;
filename = mFile.substr(s), path = mFile.substr(0,s);
for( std::string::iterator it = filename .begin(); it != filename.end(); ++it)
*it = tolower( *it);
// Load multi-part model file, if necessary
if (configHandleMP) {
@@ -905,15 +905,15 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// Now search the current shader for a record with this name (
// excluding texture file extension)
if (!shaders.blocks.empty()) {
std::string::size_type sh = convertedPath.find_last_of('.');
if (sh == std::string::npos) {
sh = convertedPath.length();
}
std::string::size_type s = convertedPath.find_last_of('.');
if (s == std::string::npos)
s = convertedPath.length();
const std::string without_ext = convertedPath.substr(0,s);
const std::string without_ext = convertedPath.substr(0,sh);
std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext);
if (dit != shaders.blocks.end()) {
// Hurra, wir haben einen. Tolle Sache.
// We made it!
shader = &*dit;
ASSIMP_LOG_INFO("Found shader record for " +without_ext );
} else {
@@ -945,8 +945,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
aiString szString;
if (convertedPath.length()) {
szString.Set(convertedPath);
}
else {
} else {
ASSIMP_LOG_WARN("Texture file name has zero length. Using default name");
szString.Set("dummy_texture.bmp");
}
@@ -955,8 +954,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
// prevent transparency by default
int no_alpha = aiTextureFlags_IgnoreAlpha;
pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0));
}
else {
} else {
Q3Shader::ConvertShaderToMaterial(pcHelper,*shader);
}
@@ -1026,7 +1024,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
if (!shader || shader->cull == Q3Shader::CULL_CW) {
std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]);
}
pcTriangles++;
++pcTriangles;
}
// Go to the next surface
@@ -1042,8 +1040,9 @@ void MD3Importer::InternReadFile( const std::string& pFile,
}
}
if (!pScene->mNumMeshes)
if (!pScene->mNumMeshes) {
throw DeadlyImportError( "MD3: File contains no valid mesh");
}
pScene->mNumMaterials = iNumMaterials;
// Now we need to generate an empty node graph
@@ -1057,7 +1056,6 @@ void MD3Importer::InternReadFile( const std::string& pFile,
pScene->mRootNode->mChildren = new aiNode*[pcHeader->NUM_TAGS];
for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) {
aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
nd->mName.Set((const char*)pcTags->NAME);
nd->mParent = pScene->mRootNode;
@@ -1085,8 +1083,12 @@ void MD3Importer::InternReadFile( const std::string& pFile,
pScene->mRootNode->mMeshes[i] = i;
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f,0.f,0.f,0.f,
0.f,0.f,1.f,0.f,
0.f,-1.f,0.f,0.f,
0.f,0.f,0.f,1.f
);
}
#endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER
+9 -9
View File
@@ -443,10 +443,10 @@ void MD5Importer::LoadMD5MeshFile ()
for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
{
MD5::WeightDesc& desc = meshSrc.mWeights[w];
MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
/* FIX for some invalid exporters */
if (!(desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
++piCount[desc.mBone];
if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
++piCount[weightDesc.mBone];
}
}
@@ -493,20 +493,20 @@ void MD5Importer::LoadMD5MeshFile ()
if (w >= meshSrc.mWeights.size())
throw DeadlyImportError("MD5MESH: Invalid weight index");
MD5::WeightDesc& desc = meshSrc.mWeights[w];
if ( desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
if ( weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
continue;
}
const ai_real fNewWeight = desc.mWeight / fSum;
const ai_real fNewWeight = weightDesc.mWeight / fSum;
// transform the local position into worldspace
MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone];
const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (desc.vOffsetPosition);
MD5::BoneDesc& boneSrc = meshParser.mJoints[weightDesc.mBone];
const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (weightDesc.vOffsetPosition);
// use the original weight to compute the vertex position
// (some MD5s seem to depend on the invalid weight values ...)
*pv += ((boneSrc.mPositionXYZ+v)* (ai_real)desc.mWeight);
*pv += ((boneSrc.mPositionXYZ+v)* (ai_real)weightDesc.mWeight);
aiBone* bone = mesh->mBones[boneSrc.mMap];
*bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
+3
View File
@@ -281,6 +281,8 @@ struct Model {
std::string m_strActiveGroup;
//! Vector with generated texture coordinates
std::vector<aiVector3D> m_TextureCoord;
//! Maximum dimension of texture coordinates
unsigned int m_TextureCoordDim;
//! Current mesh instance
Mesh *m_pCurrentMesh;
//! Vector with stored meshes
@@ -296,6 +298,7 @@ struct Model {
m_pDefaultMaterial(NULL),
m_pGroupFaceIDs(NULL),
m_strActiveGroup(""),
m_TextureCoordDim(0),
m_pCurrentMesh(NULL)
{
// empty
+31 -10
View File
@@ -442,11 +442,12 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
// Allocate buffer for texture coordinates
if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
{
pMesh->mNumUVComponents[ 0 ] = 2;
pMesh->mNumUVComponents[ 0 ] = pModel->m_TextureCoordDim;
pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
}
// Copy vertices, normals and textures into aiMesh instance
bool normalsok = true, uvok = true;
unsigned int newIndex = 0, outIndex = 0;
for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ ) {
// Get source face
@@ -466,12 +467,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
// Copy all normals
if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) {
if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) {
const unsigned int normal = pSourceFace->m_normals.at( vertexIndex );
if ( normal >= pModel->m_Normals.size() ) {
throw DeadlyImportError( "OBJ: vertex normal index out of range" );
if ( normal >= pModel->m_Normals.size() )
{
normalsok = false;
}
else
{
pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
}
pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
}
// Copy all vertex colors
@@ -482,15 +487,19 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
}
// Copy all texture coordinates
if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size())
if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size())
{
const unsigned int tex = pSourceFace->m_texturCoords.at( vertexIndex );
if ( tex >= pModel->m_TextureCoord.size() )
throw DeadlyImportError("OBJ: texture coordinate index out of range");
const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
{
uvok = false;
}
else
{
const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
}
}
// Get destination face
@@ -534,6 +543,18 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
++newIndex;
}
}
if (!normalsok)
{
delete [] pMesh->mNormals;
pMesh->mNormals = nullptr;
}
if (!uvok)
{
delete [] pMesh->mTextureCoords[0];
pMesh->mTextureCoords[0] = nullptr;
}
}
// ------------------------------------------------------------------------------------------------
+30 -10
View File
@@ -151,7 +151,8 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
} else if (*m_DataIt == 't') {
// read in texture coordinate ( 2D or 3D )
++m_DataIt;
getVector( m_pModel->m_TextureCoord );
size_t dim = getTexCoordVector(m_pModel->m_TextureCoord);
m_pModel->m_TextureCoordDim = std::max(m_pModel->m_TextureCoordDim, (unsigned int)dim);
} else if (*m_DataIt == 'n') {
// Read in normal vector definition
++m_DataIt;
@@ -271,6 +272,17 @@ static bool isDataDefinitionEnd( const char *tmp ) {
return false;
}
static bool isNanOrInf(const char * in) {
// Look for "nan" or "inf", case insensitive
if ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) {
return true;
}
else if ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0) {
return true;
}
return false;
}
size_t ObjFileParser::getNumComponentsInDataDefinition() {
size_t numComponents( 0 );
const char* tmp( &m_DataIt[0] );
@@ -284,7 +296,7 @@ size_t ObjFileParser::getNumComponentsInDataDefinition() {
if ( !SkipSpaces( &tmp ) ) {
break;
}
const bool isNum( IsNumeric( *tmp ) );
const bool isNum( IsNumeric( *tmp ) || isNanOrInf(tmp));
SkipToken( tmp );
if ( isNum ) {
++numComponents;
@@ -296,7 +308,7 @@ size_t ObjFileParser::getNumComponentsInDataDefinition() {
return numComponents;
}
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
size_t ObjFileParser::getTexCoordVector( std::vector<aiVector3D> &point3d_array ) {
size_t numComponents = getNumComponentsInDataDefinition();
ai_real x, y, z;
if( 2 == numComponents ) {
@@ -318,8 +330,20 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
} else {
throw DeadlyImportError( "OBJ: Invalid number of components" );
}
// Coerce nan and inf to 0 as is the OBJ default value
if (!std::isfinite(x))
x = 0;
if (!std::isfinite(y))
y = 0;
if (!std::isfinite(z))
z = 0;
point3d_array.push_back( aiVector3D( x, y, z ) );
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
return numComponents;
}
void ObjFileParser::getVector3( std::vector<aiVector3D> &point3d_array ) {
@@ -427,13 +451,6 @@ void ObjFileParser::getFace( aiPrimitiveType type ) {
if (type == aiPrimitiveType_POINT) {
ASSIMP_LOG_ERROR("Obj: Separator unexpected in point statement");
}
if (iPos == 0) {
//if there are no texture coordinates in the file, but normals
if (!vt && vn) {
iPos = 1;
iStep++;
}
}
iPos++;
} else if( IsSpaceOrNewLine( *m_DataIt ) ) {
iPos = 0;
@@ -450,6 +467,9 @@ void ObjFileParser::getFace( aiPrimitiveType type ) {
++iStep;
}
if (iPos == 1 && !vt && vn)
iPos = 2; // skip texture coords for normals if there are no tex coords
if ( iVal > 0 ) {
// Store parsed index
if ( 0 == iPos ) {
+1 -1
View File
@@ -96,7 +96,7 @@ protected:
/// Get the number of components in a line.
size_t getNumComponentsInDataDefinition();
/// Stores the vector
void getVector( std::vector<aiVector3D> &point3d_array );
size_t getTexCoordVector( std::vector<aiVector3D> &point3d_array );
/// Stores the following 3d vector.
void getVector3( std::vector<aiVector3D> &point3d_array );
/// Stores the following homogeneous vector as a 3D vector
+3 -3
View File
@@ -173,6 +173,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
out.push_back( new TextureTransformStep());
#endif
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
out.push_back( new ScaleProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
out.push_back( new PretransformVertices());
#endif
@@ -208,9 +211,6 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#endif
#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
out.push_back( new GenFaceNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
out.push_back( new ScaleProcess());
#endif
// .........................................................................
// DON'T change the order of these five ..
+2 -2
View File
@@ -486,7 +486,7 @@ void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIO
if (bLoadAnimationList) {
GetAnimationFileList(pFile, pIOHandler, animFileList);
}
int animCount = animFileList.size() + 1;
int animCount = static_cast<int>( animFileList.size() + 1u );
pScene->mNumAnimations = 1;
pScene->mAnimations = new aiAnimation*[animCount];
memset(pScene->mAnimations, 0, sizeof(aiAnimation*)*animCount);
@@ -510,7 +510,7 @@ void SMDImporter::CreateOutputAnimation(int index, const std::string &name) {
anim->mName.Set(name.c_str());
}
anim->mDuration = dLengthOfAnim;
anim->mNumChannels = asBones.size();
anim->mNumChannels = static_cast<unsigned int>( asBones.size() );
anim->mTicksPerSecond = 25.0; // FIXME: is this correct?
aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+1 -1
View File
@@ -127,7 +127,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo
mOutput.write((char *)&meshnum, 4);
if (exportPointClouds) {
throw DeadlyExportError("This functionality is not yet implemented for binary output.");
}
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+1
View File
@@ -278,6 +278,7 @@ void STLImporter::LoadASCIIFile( aiNode *root ) {
}
std::string name( szMe, temp );
node->mName.Set( name.c_str() );
pMesh->mName.Set( name.c_str() );
//pScene->mRootNode->mName.length = temp;
//memcpy(pScene->mRootNode->mName.data,szMe,temp);
//pScene->mRootNode->mName.data[temp] = '\0';
+19 -18
View File
@@ -228,36 +228,37 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL);
aiVector3D *vert(nullptr), *nor(nullptr), *tan(nullptr), *bit(nullptr);
aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
if (mesh->mVertices)
if (mesh->mVertices) {
vert = out->mVertices = new aiVector3D[out->mNumVertices];
}
if (mesh->mNormals)
nor = out->mNormals = new aiVector3D[out->mNumVertices];
if (mesh->mNormals) {
nor = out->mNormals = new aiVector3D[out->mNumVertices];
}
if (mesh->mTangents)
{
if (mesh->mTangents) {
tan = out->mTangents = new aiVector3D[out->mNumVertices];
bit = out->mBitangents = new aiVector3D[out->mNumVertices];
}
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
{
if (mesh->mTextureCoords[i])
uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices];
else uv[i] = NULL;
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_TEXTURECOORDS;++j) {
uv[j] = nullptr;
if (mesh->mTextureCoords[j]) {
uv[j] = out->mTextureCoords[j] = new aiVector3D[out->mNumVertices];
}
out->mNumUVComponents[i] = mesh->mNumUVComponents[i];
out->mNumUVComponents[j] = mesh->mNumUVComponents[j];
}
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
{
if (mesh->mColors[i])
cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices];
else cols[i] = NULL;
for (unsigned int j = 0; j < AI_MAX_NUMBER_OF_COLOR_SETS;++j) {
cols[j] = nullptr;
if (mesh->mColors[j]) {
cols[j] = out->mColors[j] = new aiColor4D[out->mNumVertices];
}
}
typedef std::vector< aiVertexWeight > TempBoneInfo;
@@ -323,7 +324,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) {
in.mIndices[q] = outIdx++;
}
in.mIndices = NULL;
in.mIndices = nullptr;
++outFaces;
}
ai_assert(outFaces == out->mFaces + out->mNumFaces);
+20 -20
View File
@@ -127,35 +127,35 @@ aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
// Determine which kinds of primitives the mesh consists of
aiMesh* out = new aiMesh();
switch (numIndices)
{
case 1:
out->mPrimitiveTypes = aiPrimitiveType_POINT;
break;
case 2:
out->mPrimitiveTypes = aiPrimitiveType_LINE;
break;
case 3:
out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
break;
default:
out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
break;
switch (numIndices) {
case 1:
out->mPrimitiveTypes = aiPrimitiveType_POINT;
break;
case 2:
out->mPrimitiveTypes = aiPrimitiveType_LINE;
break;
case 3:
out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
break;
default:
out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
break;
};
out->mNumFaces = (unsigned int)positions.size() / numIndices;
out->mFaces = new aiFace[out->mNumFaces];
for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i)
{
for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) {
aiFace& f = out->mFaces[i];
f.mNumIndices = numIndices;
f.mIndices = new unsigned int[numIndices];
for (unsigned int i = 0; i < numIndices;++i,++a)
f.mIndices[i] = a;
for (unsigned int j = 0; i < numIndices; ++i, ++a) {
f.mIndices[j] = a;
}
}
out->mNumVertices = (unsigned int)positions.size();
out->mVertices = new aiVector3D[out->mNumVertices];
::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
return out;
}
@@ -466,8 +466,8 @@ void StandardShapes::MakeCone(ai_real height,ai_real radius1,
// Need to flip face order?
if ( SIZE_MAX != old ) {
for (size_t s = old; s < positions.size();s += 3) {
std::swap(positions[s],positions[s+1]);
for (size_t p = old; p < positions.size();p += 3) {
std::swap(positions[p],positions[p+1]);
}
}
}
+59 -52
View File
@@ -46,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* the data structure returned by Assimp.
*/
// internal headers
#include "ValidateDataStructure.h"
#include <assimp/BaseImporter.h>
@@ -110,8 +108,8 @@ void ValidateDSProcess::ReportWarning(const char* msg,...)
}
// ------------------------------------------------------------------------------------------------
inline int HasNameMatch(const aiString& in, aiNode* node)
{
inline
int HasNameMatch(const aiString& in, aiNode* node) {
int result = (node->mName == in ? 1 : 0 );
for (unsigned int i = 0; i < node->mNumChildren;++i) {
result += HasNameMatch(in,node->mChildren[i]);
@@ -121,9 +119,8 @@ inline int HasNameMatch(const aiString& in, aiNode* node)
// ------------------------------------------------------------------------------------------------
template <typename T>
inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
const char* firstName, const char* secondName)
{
inline
void ValidateDSProcess::DoValidation(T** parray, unsigned int size, const char* firstName, const char* secondName) {
// validate all entries
if (size)
{
@@ -160,7 +157,7 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
{
if (!parray[i])
{
ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
ReportError("aiScene::%s[%u] is NULL (aiScene::%s is %u)",
firstName,i,secondName,size);
}
Validate(parray[i]);
@@ -170,8 +167,8 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
{
if (parray[i]->mName == parray[a]->mName)
{
this->ReportError("aiScene::%s[%i] has the same name as "
"aiScene::%s[%i]",firstName, i,secondName, a);
ReportError("aiScene::%s[%u] has the same name as "
"aiScene::%s[%u]",firstName, i,secondName, a);
}
}
}
@@ -181,7 +178,8 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
// ------------------------------------------------------------------------------------------------
template <typename T>
inline
void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) {
void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName,
const char* secondName) {
// validate all entries
DoValidationEx(array,size,firstName,secondName);
@@ -201,9 +199,8 @@ void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size,
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void ValidateDSProcess::Execute( aiScene* pScene)
{
this->mScene = pScene;
void ValidateDSProcess::Execute( aiScene* pScene) {
mScene = pScene;
ASSIMP_LOG_DEBUG("ValidateDataStructureProcess begin");
// validate the node graph of the scene
@@ -330,6 +327,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
{
case 0:
ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i);
break;
case 1:
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
{
@@ -422,7 +420,9 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
if (!abRefList[i])b = true;
}
abRefList.clear();
if (b)ReportWarning("There are unreferenced vertices");
if (b) {
ReportWarning("There are unreferenced vertices");
}
// texture channel 2 may not be set if channel 1 is zero ...
{
@@ -513,13 +513,11 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh,
const aiBone* pBone,float* afSum)
{
void ValidateDSProcess::Validate( const aiMesh* pMesh, const aiBone* pBone,float* afSum) {
this->Validate(&pBone->mName);
if (!pBone->mNumWeights) {
ReportError("aiBone::mNumWeights is zero");
//ReportError("aiBone::mNumWeights is zero");
}
// check whether all vertices affected by this bone are valid
@@ -557,10 +555,9 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
Validate(pAnimation, pAnimation->mChannels[i]);
}
}
else ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
// Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
// if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
else {
ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
}
}
// ------------------------------------------------------------------------------------------------
@@ -577,15 +574,16 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
int iNumIndices = 0;
int iIndex = -1;
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{
aiMaterialProperty* prop = pMaterial->mProperties[i];
if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type) {
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) {
aiMaterialProperty* prop = pMaterial->mProperties[ i ];
ai_assert(nullptr != prop);
if ( !::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == static_cast<unsigned int>(type)) {
iIndex = std::max(iIndex, (int) prop->mIndex);
++iNumIndices;
if (aiPTI_String != prop->mType)
ReportError("Material property %s is expected to be a string",prop->mKey.data);
if (aiPTI_String != prop->mType) {
ReportError("Material property %s is expected to be a string", prop->mKey.data);
}
}
}
if (iIndex +1 != iNumIndices) {
@@ -740,8 +738,9 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
"AI_MATKEY_SHININESS_STRENGTH key is 0.0");
}
break;
default: ;
};
default:
break;
}
}
if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01)) {
@@ -773,8 +772,10 @@ void ValidateDSProcess::Validate( const aiTexture* pTexture)
}
if (pTexture->mHeight)
{
if (!pTexture->mWidth)ReportError("aiTexture::mWidth is zero "
"(aiTexture::mHeight is %i, uncompressed texture)",pTexture->mHeight);
if (!pTexture->mWidth){
ReportError("aiTexture::mWidth is zero (aiTexture::mHeight is %i, uncompressed texture)",
pTexture->mHeight);
}
}
else
{
@@ -805,15 +806,15 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
{
Validate(&pNodeAnim->mNodeName);
if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys)
if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys) {
ReportError("Empty node animation channel");
}
// otherwise check whether one of the keys exceeds the total duration of the animation
if (pNodeAnim->mNumPositionKeys)
{
if (!pNodeAnim->mPositionKeys)
{
this->ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)",
ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)",
pNodeAnim->mNumPositionKeys);
}
double dLast = -10e10;
@@ -844,7 +845,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
{
if (!pNodeAnim->mRotationKeys)
{
this->ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)",
ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)",
pNodeAnim->mNumRotationKeys);
}
double dLast = -10e10;
@@ -905,19 +906,23 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiNode* pNode)
{
if (!pNode)ReportError("A node of the scenegraph is NULL");
if (pNode != mScene->mRootNode && !pNode->mParent)
this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
if (!pNode) {
ReportError("A node of the scenegraph is NULL");
}
// Validate node name string first so that it's safe to use in below expressions
this->Validate(&pNode->mName);
const char* nodeName = (&pNode->mName)->C_Str();
if (pNode != mScene->mRootNode && !pNode->mParent){
ReportError("Non-root node %s lacks a valid parent (aiNode::mParent is NULL) ", nodeName);
}
// validate all meshes
if (pNode->mNumMeshes)
{
if (!pNode->mMeshes)
{
ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
pNode->mNumMeshes);
ReportError("aiNode::mMeshes is NULL for node %s (aiNode::mNumMeshes is %i)",
nodeName, pNode->mNumMeshes);
}
std::vector<bool> abHadMesh;
abHadMesh.resize(mScene->mNumMeshes,false);
@@ -925,13 +930,13 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
{
if (pNode->mMeshes[i] >= mScene->mNumMeshes)
{
ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
pNode->mMeshes[i],mScene->mNumMeshes-1);
ReportError("aiNode::mMeshes[%i] is out of range for node %s (maximum is %i)",
pNode->mMeshes[i], nodeName, mScene->mNumMeshes-1);
}
if (abHadMesh[pNode->mMeshes[i]])
{
ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)",
i,pNode->mMeshes[i]);
ReportError("aiNode::mMeshes[%i] is already referenced by this node %s (value: %i)",
i, nodeName, pNode->mMeshes[i]);
}
abHadMesh[pNode->mMeshes[i]] = true;
}
@@ -939,8 +944,8 @@ void ValidateDSProcess::Validate( const aiNode* pNode)
if (pNode->mNumChildren)
{
if (!pNode->mChildren) {
ReportError("aiNode::mChildren is NULL (aiNode::mNumChildren is %i)",
pNode->mNumChildren);
ReportError("aiNode::mChildren is NULL for node %s (aiNode::mNumChildren is %i)",
nodeName, pNode->mNumChildren);
}
for (unsigned int i = 0; i < pNode->mNumChildren;++i) {
Validate(pNode->mChildren[i]);
@@ -953,7 +958,7 @@ void ValidateDSProcess::Validate( const aiString* pString)
{
if (pString->length > MAXLEN)
{
this->ReportError("aiString::length is too large (%i, maximum is %lu)",
ReportError("aiString::length is too large (%lu, maximum is %lu)",
pString->length,MAXLEN);
}
const char* sz = pString->data;
@@ -961,12 +966,14 @@ void ValidateDSProcess::Validate( const aiString* pString)
{
if ('\0' == *sz)
{
if (pString->length != (unsigned int)(sz-pString->data))
if (pString->length != (unsigned int)(sz-pString->data)) {
ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
}
break;
}
else if (sz >= &pString->data[MAXLEN])
else if (sz >= &pString->data[MAXLEN]) {
ReportError("aiString::data is invalid. There is no terminal character");
}
++sz;
}
}
+4 -3
View File
@@ -223,7 +223,8 @@ namespace glTF2
ComponentType_FLOAT = 5126
};
inline unsigned int ComponentTypeSize(ComponentType t)
inline
unsigned int ComponentTypeSize(ComponentType t)
{
switch (t) {
case ComponentType_SHORT:
@@ -250,7 +251,7 @@ namespace glTF2
};
//! Values for the Sampler::magFilter field
enum class SamplerMagFilter: unsigned int
enum class SamplerMagFilter : unsigned int
{
UNSET = 0,
SamplerMagFilter_Nearest = 9728,
@@ -258,7 +259,7 @@ namespace glTF2
};
//! Values for the Sampler::minFilter field
enum class SamplerMinFilter: unsigned int
enum class SamplerMinFilter : unsigned int
{
UNSET = 0,
SamplerMinFilter_Nearest = 9728,
Executable → Regular
View File
Executable → Regular
+7 -4
View File
@@ -789,13 +789,16 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector<std
delete[] indices16;
}
static std::string GetNodeName(const Node& node)
{
return node.name.empty() ? node.id : node.name;
}
aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
{
Node& node = *ptr;
std::string nameOrId = node.name.empty() ? node.id : node.name;
aiNode* ainode = new aiNode(nameOrId);
aiNode* ainode = new aiNode(GetNodeName(node));
if (!node.children.empty()) {
ainode->mNumChildren = unsigned(node.children.size());
@@ -921,7 +924,7 @@ struct AnimationSamplers {
aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
{
aiNodeAnim* anim = new aiNodeAnim();
anim->mNodeName = node.name;
anim->mNodeName = GetNodeName(node);
static const float kMillisecondsFromSeconds = 1000.f;
+4 -4
View File
@@ -294,17 +294,17 @@ namespace glTF {
// filling object "compressedData"
json_comp_data.SetObject();
json_comp_data.AddMember("buffer", ptr_ext_comp->Buffer, w.mAl);
json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl);
json_comp_data.AddMember("byteOffset", static_cast<uint64_t>(ptr_ext_comp->Offset), w.mAl);
json_comp_data.AddMember("componentType", 5121, w.mAl);
json_comp_data.AddMember("type", "SCALAR", w.mAl);
json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl);
json_comp_data.AddMember("count", static_cast<uint64_t>(ptr_ext_comp->Count), w.mAl);
if(ptr_ext_comp->Binary)
json_comp_data.AddMember("mode", "binary", w.mAl);
else
json_comp_data.AddMember("mode", "ascii", w.mAl);
json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl);
json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl);
json_comp_data.AddMember("indicesCount", static_cast<uint64_t>(ptr_ext_comp->IndicesCount), w.mAl);
json_comp_data.AddMember("verticesCount", static_cast<uint64_t>(ptr_ext_comp->VerticesCount), w.mAl);
// filling object "Open3DGC-compression"
Value json_o3dgc;
+1 -1
View File
@@ -245,7 +245,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
namespace {
void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
ai_assert(mat->Get(propName, type, idx, val) == AI_SUCCESS);
}
}
Executable → Regular
View File
-105
View File
@@ -1,105 +0,0 @@
### USE OF THIS MAKEFILE IS NOT RECOMMENDED.
### It is no longer maintained. Use CMAKE instead.
# ---------------------------------------------------------------------------
# Makefile for Open Asset Import Library (MinGW32-make)
# aramis_acg@users.sourceforge.net
# - just a quick'n'dirty one, could be buggy ...
#
# Usage: mingw32-make -f makefile.mingw <target> <macros>
# TARGETS:
# all Build a shared so from the whole library
# clean Cleanup object files, prepare for rebuild
# static Build a static library (*.a)
# MACROS: (make clean before you change one)
# NOBOOST=1 Build against boost workaround
# SINGLETHREADED=1 Build single-threaded library
# DEBUG=1 Build debug build of library
#
# ---------------------------------------------------------------------------
# C++ object files
OBJECTS := $(patsubst %.cpp,%.o, $(wildcard *.cpp))
OBJECTS += $(patsubst %.cpp,%.o, $(wildcard extra/*.cpp))
OBJECTS += $(patsubst %.cpp,%.o, $(wildcard ./../contrib/irrXML/*.cpp))
# C object files
OBJECTSC := $(patsubst %.c,%.oc, $(wildcard ./../contrib/zlib/*.c))
OBJECTSC += $(patsubst %.c,%.oc, $(wildcard ./../contrib/ConvertUTF/*.c))
OBJECTSC += $(patsubst %.c,%.oc, $(wildcard ./../contrib/unzip/*.c))
# Include flags for gcc
INCLUDEFLAGS =
# Preprocessor defines for gcc
DEFINEFLAGS =
# Suffix for the output binary, represents build type
NAMESUFFIX =
# Output path for binaries
BINPATH = ../bin/mingw/
# GCC compiler flags
CPPFLAGS=-Wall
# Setup environment for noboost build
ifeq ($(NOBOOST),1)
SINGLETHREADED = 1
INCLUDEFLAGS += -I./BoostWorkaround/
DEFINEFLAGS += -DASSIMP_BUILD_BOOST_WORKAROUND
# NAMESUFFIX += -noboost
else
# adjust this manually if your boost is stored elsewhere
INCLUDEFLAGS += -I"C:/Program Files/boost/boost_1_38"
#INCLUDEFLAGS += -I"$(BOOST_DIR)"
endif
# Setup environment for st build
ifeq ($(SINGLETHREADED),1)
DEFINEFLAGS += -DASSIMP_BUILD_SINGLETHREADED
# NAMESUFFIX += -st
endif
# Setup environment for debug build
ifeq ($(DEBUG),1)
DEFINEFLAGS += -D_DEBUG -DDEBUG
CPPFLAGS += -g
# NAMESUFFIX += -debug
else
CPPFLAGS += -O2 -s
DEFINEFLAGS += -DNDEBUG -D_NDEBUG
endif
# Output name of shared library
SHARED_TARGET = $(BINPATH)/libassimp$(NAMESUFFIX).so
# Output name of static library
STATIC = $(BINPATH)/libassimp$(NAMESUFFIX).a
# target: all
# usage : build a shared library (*.so)
all: $(SHARED_TARGET)
$(SHARED_TARGET): $(OBJECTS) $(OBJECTSC)
gcc -o $@ $(OBJECTS) $(OBJECTSC) -shared -lstdc++
%.o:%.cpp
$(CXX) -c $(CPPFLAGS) $? -o $@ $(INCLUDEFLAGS) $(DEFINEFLAGS)
%.oc:%.c
$(CXX) -x c -c -ansi $(CPPFLAGS) $? -o $@
# target: clean
# usage : cleanup all object files, prepare for a rebuild
.PHONY: clean
clean:
-del *.o .\..\contrib\irrXML\*.o .\..\contrib\zlib\*.oc .\..\contrib\unzip\*.oc .\..\contrib\ConvertUTF\*.oc
# target: static
# usage : build a static library (*.a)
static: $(STATIC)
$(STATIC): $(OBJECTS) $(OBJECTSC)
ar rcs $@ $(OBJECTS) $(OBJECTSC)
+5 -5
View File
@@ -1,7 +1,7 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#include "..\..\revision.h"
#include "revision.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
@@ -31,8 +31,8 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,SVNRevision, 0
PRODUCTVERSION 1,1,SVNRevision,0
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_FILEVERSION
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -50,12 +50,12 @@ BEGIN
VALUE "Comments", "Licensed under a 3-clause BSD license"
VALUE "CompanyName", "assimp team"
VALUE "FileDescription", "Open Asset Import Library"
VALUE "FileVersion", 1,1,SVNRevision,0
VALUE "FileVersion", VER_FILEVERSION
VALUE "InternalName", "assimp "
VALUE "LegalCopyright", "Copyright (C) 2006-2010"
VALUE "OriginalFilename", "assimpNN.dll"
VALUE "ProductName", "Open Asset Import Library"
VALUE "ProductVersion", 1,1,SVNRevision,0
VALUE "ProductVersion", VER_FILEVERSION_STR
,0
END
END
+2 -2
View File
@@ -2,8 +2,8 @@
// Microsoft Visual C++ generated include file.
// Used by assimp.rc
// Nächste Standardwerte für neue Objekte
//
// Next standard values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101