Merge branch 'master' into fbx_export_squashed

pull/1804/head
Kim Kulling 2018-02-23 23:33:43 +01:00 committed by GitHub
commit 5e4b2b898f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 517 additions and 277 deletions

View File

@ -45,6 +45,7 @@ namespace Assimp {
namespace D3MF {
namespace XmlTag {
// Model-data specific tags
static const std::string model = "model";
static const std::string model_unit = "unit";
static const std::string metadata = "metadata";
@ -62,6 +63,8 @@ namespace XmlTag {
static const std::string v2 = "v2";
static const std::string v3 = "v3";
static const std::string id = "id";
static const std::string pid = "pid";
static const std::string p1 = "p1";
static const std::string name = "name";
static const std::string type = "type";
static const std::string build = "build";
@ -69,6 +72,13 @@ namespace XmlTag {
static const std::string objectid = "objectid";
static const std::string transform = "transform";
// Material definitions
static const std::string basematerials = "basematerials";
static const std::string basematerials_base = "base";
static const std::string basematerials_name = "name";
static const std::string basematerials_displaycolor = "displaycolor";
// Meta info tags
static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
@ -83,7 +93,6 @@ namespace XmlTag {
static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
}
} // Namespace D3MF

View File

@ -205,7 +205,7 @@ enum ErrorPolicy {
// -------------------------------------------------------------------------------
/** Represents a data structure in a BLEND file. A Structure defines n fields
* and their locatios and encodings the input stream. Usually, every
* and their locations and encodings the input stream. Usually, every
* Structure instance pertains to one equally-named data structure in the
* BlenderScene.h header. This class defines various utilities to map a
* binary `blob` read from the file to such a structure instance with

View File

@ -502,7 +502,7 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv
{
// the file blocks appear in list sorted by
// with ascending base addresses so we can run a
// binary search to locate the pointee quickly.
// binary search to locate the pointer quickly.
// NOTE: Blender seems to distinguish between side-by-side
// data (stored in the same data block) and far pointers,

View File

@ -116,7 +116,7 @@ template <> void Structure :: Convert<MTex> (
ReadField<ErrorPolicy_Igno>(temp,"projy",db);
dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
ReadField<ErrorPolicy_Igno>(temp,"projz",db);
dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
dest.projz = static_cast<Assimp::Blender::MTex::Projection>(temp);
ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);

View File

@ -61,6 +61,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unzip.h>
#include <assimp/irrXMLWrapper.h>
#include "3MFXmlTags.h"
#include <assimp/fast_atof.h>
#include <iomanip>
namespace Assimp {
namespace D3MF {
@ -68,7 +71,9 @@ namespace D3MF {
class XmlSerializer {
public:
XmlSerializer(XmlReader* xmlReader)
: xmlReader(xmlReader) {
: mMeshes()
, mMaterials()
, xmlReader(xmlReader){
// empty
}
@ -77,14 +82,21 @@ public:
}
void ImportXml(aiScene* scene) {
if ( nullptr == scene ) {
return;
}
scene->mRootNode = new aiNode();
std::vector<aiNode*> children;
while(ReadToEndElement(D3MF::XmlTag::model)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
const std::string nodeName( xmlReader->getNodeName() );
if( nodeName == D3MF::XmlTag::object) {
children.push_back(ReadObject(scene));
} else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
} else if( nodeName == D3MF::XmlTag::build) {
//
} else if ( nodeName == D3MF::XmlTag::basematerials ) {
ReadBaseMaterials();
}
}
@ -92,11 +104,16 @@ public:
scene->mRootNode->mName.Set( "3MF" );
}
scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
std::copy(meshes.begin(), meshes.end(), scene->mMeshes);
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
scene->mNumMaterials = mMaterials.size();
if ( 0 != scene->mNumMaterials ) {
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials );
}
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
@ -104,8 +121,7 @@ public:
}
private:
aiNode* ReadObject(aiScene* scene)
{
aiNode* ReadObject(aiScene* scene) {
std::unique_ptr<aiNode> node(new aiNode());
std::vector<unsigned long> meshIds;
@ -124,19 +140,16 @@ private:
node->mParent = scene->mRootNode;
node->mName.Set(name);
size_t meshIdx = meshes.size();
size_t meshIdx = mMeshes.size();
while(ReadToEndElement(D3MF::XmlTag::object))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::mesh)
{
while(ReadToEndElement(D3MF::XmlTag::object)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh();
mesh->mName.Set(name);
meshes.push_back(mesh);
mMeshes.push_back(mesh);
meshIds.push_back(static_cast<unsigned long>(meshIdx));
meshIdx++;
++meshIdx;
}
}
@ -147,19 +160,14 @@ private:
std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
return node.release();
}
aiMesh* ReadMesh() {
aiMesh* mesh = new aiMesh();
while(ReadToEndElement(D3MF::XmlTag::mesh))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
{
while(ReadToEndElement(D3MF::XmlTag::mesh)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
ImportVertices(mesh);
}
else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles)
{
} else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) {
ImportTriangles(mesh);
}
}
@ -167,14 +175,11 @@ private:
return mesh;
}
void ImportVertices(aiMesh* mesh)
{
void ImportVertices(aiMesh* mesh) {
std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
{
while(ReadToEndElement(D3MF::XmlTag::vertices)) {
if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
vertices.push_back(ReadVertex());
}
}
@ -182,11 +187,9 @@ private:
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
}
aiVector3D ReadVertex()
{
aiVector3D ReadVertex() {
aiVector3D vertex;
vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
@ -196,16 +199,18 @@ private:
return vertex;
}
void ImportTriangles(aiMesh* mesh)
{
void ImportTriangles(aiMesh* mesh) {
std::vector<aiFace> faces;
while(ReadToEndElement(D3MF::XmlTag::triangles))
{
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle)
{
while(ReadToEndElement(D3MF::XmlTag::triangles)) {
const std::string nodeName( xmlReader->getNodeName() );
if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
faces.push_back(ReadTriangle());
const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) );
if ( nullptr != pidToken ) {
int matIdx( std::atoi( pidToken ) );
mesh->mMaterialIndex = matIdx;
}
}
}
@ -216,8 +221,7 @@ private:
std::copy(faces.begin(), faces.end(), mesh->mFaces);
}
aiFace ReadTriangle()
{
aiFace ReadTriangle() {
aiFace face;
face.mNumIndices = 3;
@ -229,45 +233,113 @@ private:
return face;
}
private:
bool ReadToStartElement(const std::string& startTag)
{
while(xmlReader->read())
{
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag)
{
return true;
}
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END &&
xmlReader->getNodeName() == startTag)
{
return false;
void ReadBaseMaterials() {
while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) {
mMaterials.push_back( readMaterialDef() );
xmlReader->read();
}
}
//DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
bool parseColor( const char *color, aiColor4D &diffuse ) {
if ( nullptr == color ) {
return false;
}
bool ReadToEndElement(const std::string& closeTag)
{
while(xmlReader->read())
{
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
const size_t len( strlen( color ) );
if ( 9 != len ) {
return false;
}
const char *buf( color );
if ( '#' != *buf ) {
return false;
}
++buf;
char comp[ 3 ] = { 0,0,'\0' };
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
comp[ 0 ] = *buf;
++buf;
comp[ 1 ] = *buf;
++buf;
diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
return true;
}
else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END
&& xmlReader->getNodeName() == closeTag)
{
aiMaterial *readMaterialDef() {
aiMaterial *mat( nullptr );
const char *name( nullptr );
const char *color( nullptr );
const std::string nodeName( xmlReader->getNodeName() );
if ( nodeName == D3MF::XmlTag::basematerials_base ) {
name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() );
aiString matName;
matName.Set( name );
mat = new aiMaterial;
mat->AddProperty( &matName, AI_MATKEY_NAME );
color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() );
aiColor4D diffuse;
if ( parseColor( color, diffuse ) ) {
mat->AddProperty<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
}
}
return mat;
}
private:
bool ReadToStartElement(const std::string& startTag) {
while(xmlReader->read()) {
const std::string &nodeName( xmlReader->getNodeName() );
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
return true;
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
return false;
}
}
return false;
}
bool ReadToEndElement(const std::string& closeTag) {
while(xmlReader->read()) {
const std::string &nodeName( xmlReader->getNodeName() );
if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
return true;
} else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
return false;
}
}
DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
return false;
}
private:
std::vector<aiMesh*> meshes;
std::vector<aiMesh*> mMeshes;
std::vector<aiMaterial*> mMaterials;
XmlReader* xmlReader;
};

View File

@ -142,6 +142,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
nodes.reserve( conns.size() );
std::vector<aiNode*> nodes_chain;
std::vector<aiNode*> post_nodes_chain;
try {
for( const Connection* con : conns ) {
@ -161,6 +162,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
if ( model ) {
nodes_chain.clear();
post_nodes_chain.clear();
aiMatrix4x4 new_abs_transform = parent_transform;
@ -168,7 +170,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
// 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 );
GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain );
ai_assert( nodes_chain.size() );
@ -213,8 +215,25 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
// attach geometry
ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
// now link the geometric transform inverse nodes,
// before we attach any child nodes
for( aiNode* postnode : post_nodes_chain ) {
ai_assert( postnode );
if ( last_parent != &parent ) {
last_parent->mNumChildren = 1;
last_parent->mChildren = new aiNode*[ 1 ];
last_parent->mChildren[ 0 ] = postnode;
}
postnode->mParent = last_parent;
last_parent = postnode;
new_abs_transform *= postnode->mTransformation;
}
// attach sub-nodes
ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform );
ConvertNodes( model->ID(), *last_parent, new_abs_transform );
if ( doc.Settings().readLights ) {
ConvertLights( *model );
@ -396,6 +415,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
return "GeometricRotation";
case TransformationComp_GeometricTranslation:
return "GeometricTranslation";
case TransformationComp_GeometricScalingInverse:
return "GeometricScalingInverse";
case TransformationComp_GeometricRotationInverse:
return "GeometricRotationInverse";
case TransformationComp_GeometricTranslationInverse:
return "GeometricTranslationInverse";
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
default:
break;
@ -437,6 +462,12 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp )
return "GeometricRotation";
case TransformationComp_GeometricTranslation:
return "GeometricTranslation";
case TransformationComp_GeometricScalingInverse:
return "GeometricScalingInverse";
case TransformationComp_GeometricRotationInverse:
return "GeometricRotationInverse";
case TransformationComp_GeometricTranslationInverse:
return "GeometricTranslationInverse";
case TransformationComp_MAXIMUM: // this is to silence compiler warnings
break;
}
@ -548,18 +579,26 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
bool ok;
const float zero_epsilon = 1e-6f;
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) {
const TransformationComp comp = static_cast< TransformationComp >( i );
if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ) {
continue;
}
bool scale_compare = ( comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling );
const aiVector3D& v = PropertyGet<aiVector3D>( props, NameTransformationCompProperty( comp ), ok );
if ( ok && v.SquareLength() > zero_epsilon ) {
if ( ok && scale_compare ) {
if ( (v - all_ones).SquareLength() > zero_epsilon ) {
return true;
}
} else if ( ok ) {
if ( v.SquareLength() > zero_epsilon ) {
return true;
}
}
}
return false;
@ -570,7 +609,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
}
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes )
{
const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder();
@ -582,6 +621,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
// generate transformation matrices for all the different transformation components
const float zero_epsilon = 1e-6f;
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
bool is_complex = false;
const aiVector3D& PreRotation = PropertyGet<aiVector3D>( props, "PreRotation", ok );
@ -634,7 +674,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
}
const aiVector3D& Scaling = PropertyGet<aiVector3D>( props, "Lcl Scaling", ok );
if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) {
if ( ok && (Scaling - all_ones).SquareLength() > zero_epsilon ) {
aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] );
}
@ -644,18 +684,38 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
}
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>( props, "GeometricScaling", ok );
if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) {
if ( ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon ) {
is_complex = true;
aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
aiVector3D GeometricScalingInverse = GeometricScaling;
bool canscale = true;
for (size_t i = 0; i < 3; ++i) {
if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) {
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
} else {
FBXImporter::LogError( "cannot invert geometric scaling matrix with a 0.0 scale component" );
canscale = false;
break;
}
}
if (canscale) {
aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] );
}
}
const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>( props, "GeometricRotation", ok );
if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) {
is_complex = true;
GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] );
GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] );
chain[ TransformationComp_GeometricRotationInverse ].Inverse();
}
const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>( props, "GeometricTranslation", ok );
if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) {
is_complex = true;
aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] );
aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] );
}
// is_complex needs to be consistent with NeedsComplexTransformationChain()
@ -690,10 +750,18 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
}
aiNode* nd = new aiNode();
output_nodes.push_back( nd );
nd->mName.Set( NameTransformationChainNode( name, comp ) );
nd->mTransformation = chain[ i ];
// geometric inverses go in a post-node chain
if ( comp == TransformationComp_GeometricScalingInverse ||
comp == TransformationComp_GeometricRotationInverse ||
comp == TransformationComp_GeometricTranslationInverse
) {
post_output_nodes.push_back( nd );
} else {
output_nodes.push_back( nd );
}
}
ai_assert( output_nodes.size() );
@ -2209,8 +2277,7 @@ void Converter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
has_any = true;
if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation &&
comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation )
if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation )
{
has_complex = true;
}

View File

@ -82,7 +82,10 @@ public:
* The different parts that make up the final local transformation of a fbx-node
*/
enum TransformationComp {
TransformationComp_Translation = 0,
TransformationComp_GeometricScalingInverse = 0,
TransformationComp_GeometricRotationInverse,
TransformationComp_GeometricTranslationInverse,
TransformationComp_Translation,
TransformationComp_RotationOffset,
TransformationComp_RotationPivot,
TransformationComp_PreRotation,
@ -153,7 +156,7 @@ private:
/**
* note: memory for output_nodes will be managed by the caller
*/
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes);
void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes, std::vector<aiNode*>& post_output_nodes);
// ------------------------------------------------------------------------------------------------
void SetupNodeMetadata(const Model& model, aiNode& nd);

View File

@ -428,16 +428,19 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
const std::vector<unsigned int>& mapping_offsets,
const std::vector<unsigned int>& mappings)
{
bool isDirect = ReferenceInformationType == "Direct";
bool isIndexToDirect = ReferenceInformationType == "IndexToDirect";
// fallback to direct data if there is no index data element
if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) {
isDirect = true;
isIndexToDirect = false;
}
// handle permutations of Mapping and Reference type - it would be nice to
// deal with this more elegantly and with less redundancy, but right
// now it seems unavoidable.
if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {
if ( !HasElement( source, indexDataElementName ) ) {
return;
}
if (MappingInformationType == "ByVertice" && isDirect) {
std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
@ -450,14 +453,11 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
}
}
}
else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
else if (MappingInformationType == "ByVertice" && isIndexToDirect) {
std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
data_out.resize(vertex_count);
if ( !HasElement( source, indexDataElementName ) ) {
return;
}
std::vector<int> uvIndices;
ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));
@ -472,7 +472,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
}
}
}
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
else if (MappingInformationType == "ByPolygonVertex" && isDirect) {
std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
@ -485,7 +485,7 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
data_out.swap(tempData);
}
else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) {
std::vector<T> tempData;
ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));

View File

@ -42,13 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implements a filter system to filter calls to Exists() and Open()
* in order to improve the success rate of file opening ...
*/
#pragma once
#ifndef AI_FILESYSTEMFILTER_H_INC
#define AI_FILESYSTEMFILTER_H_INC
#include "../include/assimp/IOSystem.hpp"
#include "../include/assimp/DefaultLogger.hpp"
#include "../include/assimp/fast_atof.h"
#include "../include/assimp/ParsingUtils.h"
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/fast_atof.h>
#include <assimp/ParsingUtils.h>
namespace Assimp {
@ -64,90 +65,89 @@ class FileSystemFilter : public IOSystem
public:
/** Constructor. */
FileSystemFilter(const std::string& file, IOSystem* old)
: wrapped (old)
, src_file (file)
, sep(wrapped->getOsSeparator())
{
ai_assert(NULL != wrapped);
: mWrapped (old)
, mSrc_file(file)
, sep(mWrapped->getOsSeparator()) {
ai_assert(nullptr != mWrapped);
// Determine base directory
base = src_file;
mBase = mSrc_file;
std::string::size_type ss2;
if (std::string::npos != (ss2 = base.find_last_of("\\/"))) {
base.erase(ss2,base.length()-ss2);
}
else {
base = "";
// return;
if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) {
mBase.erase(ss2,mBase.length()-ss2);
} else {
mBase = "";
}
// make sure the directory is terminated properly
char s;
if (base.length() == 0) {
base = ".";
base += getOsSeparator();
}
else if ((s = *(base.end()-1)) != '\\' && s != '/') {
base += getOsSeparator();
if ( mBase.empty() ) {
mBase = ".";
mBase += getOsSeparator();
} else if ((s = *(mBase.end()-1)) != '\\' && s != '/') {
mBase += getOsSeparator();
}
DefaultLogger::get()->info("Import root directory is \'" + base + "\'");
DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'");
}
/** Destructor. */
~FileSystemFilter()
{
// haha
~FileSystemFilter() {
// empty
}
// -------------------------------------------------------------------
/** Tests for the existence of a file at the given path. */
bool Exists( const char* pFile) const
{
bool Exists( const char* pFile) const {
ai_assert( nullptr != mWrapped );
std::string tmp = pFile;
// Currently this IOSystem is also used to open THE ONE FILE.
if (tmp != src_file) {
if (tmp != mSrc_file) {
BuildPath(tmp);
Cleanup(tmp);
}
return wrapped->Exists(tmp);
return mWrapped->Exists(tmp);
}
// -------------------------------------------------------------------
/** Returns the directory separator. */
char getOsSeparator() const
{
char getOsSeparator() const {
return sep;
}
// -------------------------------------------------------------------
/** Open a new file with a given path. */
IOStream* Open( const char* pFile, const char* pMode = "rb")
{
ai_assert(pFile);
ai_assert(pMode);
IOStream* Open( const char* pFile, const char* pMode = "rb") {
ai_assert( nullptr != mWrapped );
if ( nullptr == pFile || nullptr == pMode ) {
return nullptr;
}
ai_assert( nullptr != pFile );
ai_assert( nullptr != pMode );
// First try the unchanged path
IOStream* s = wrapped->Open(pFile,pMode);
IOStream* s = mWrapped->Open(pFile,pMode);
if (!s) {
if (nullptr == s) {
std::string tmp = pFile;
// Try to convert between absolute and relative paths
BuildPath(tmp);
s = wrapped->Open(tmp,pMode);
s = mWrapped->Open(tmp,pMode);
if (!s) {
if (nullptr == s) {
// Finally, look for typical issues with paths
// and try to correct them. This is our last
// resort.
tmp = pFile;
Cleanup(tmp);
BuildPath(tmp);
s = wrapped->Open(tmp,pMode);
s = mWrapped->Open(tmp,pMode);
}
}
@ -156,27 +156,75 @@ public:
// -------------------------------------------------------------------
/** Closes the given file and releases all resources associated with it. */
void Close( IOStream* pFile)
{
return wrapped->Close(pFile);
void Close( IOStream* pFile) {
ai_assert( nullptr != mWrapped );
return mWrapped->Close(pFile);
}
// -------------------------------------------------------------------
/** Compare two paths */
bool ComparePaths (const char* one, const char* second) const
{
return wrapped->ComparePaths (one,second);
bool ComparePaths (const char* one, const char* second) const {
ai_assert( nullptr != mWrapped );
return mWrapped->ComparePaths (one,second);
}
// -------------------------------------------------------------------
/** Pushes a new directory onto the directory stack. */
bool PushDirectory(const std::string &path ) {
ai_assert( nullptr != mWrapped );
return mWrapped->PushDirectory(path);
}
// -------------------------------------------------------------------
/** Returns the top directory from the stack. */
const std::string &CurrentDirectory() const {
ai_assert( nullptr != mWrapped );
return mWrapped->CurrentDirectory();
}
// -------------------------------------------------------------------
/** Returns the number of directories stored on the stack. */
size_t StackSize() const {
ai_assert( nullptr != mWrapped );
return mWrapped->StackSize();
}
// -------------------------------------------------------------------
/** Pops the top directory from the stack. */
bool PopDirectory() {
ai_assert( nullptr != mWrapped );
return mWrapped->PopDirectory();
}
// -------------------------------------------------------------------
/** Creates an new directory at the given path. */
bool CreateDirectory(const std::string &path) {
ai_assert( nullptr != mWrapped );
return mWrapped->CreateDirectory(path);
}
// -------------------------------------------------------------------
/** Will change the current directory to the given path. */
bool ChangeDirectory(const std::string &path) {
ai_assert( nullptr != mWrapped );
return mWrapped->ChangeDirectory(path);
}
// -------------------------------------------------------------------
/** Delete file. */
bool DeleteFile(const std::string &file) {
ai_assert( nullptr != mWrapped );
return mWrapped->DeleteFile(file);
}
private:
// -------------------------------------------------------------------
/** Build a valid path from a given relative or absolute path.
*/
void BuildPath (std::string& in) const
{
void BuildPath (std::string& in) const {
ai_assert( nullptr != mWrapped );
// if we can already access the file, great.
if (in.length() < 3 || wrapped->Exists(in)) {
if (in.length() < 3 || mWrapped->Exists(in)) {
return;
}
@ -184,8 +232,8 @@ private:
if (in[1] != ':') {
// append base path and try
const std::string tmp = base + in;
if (wrapped->Exists(tmp)) {
const std::string tmp = mBase + in;
if (mWrapped->Exists(tmp)) {
in = tmp;
return;
}
@ -207,7 +255,7 @@ private:
std::string::size_type last_dirsep = std::string::npos;
while(true) {
tmp = base;
tmp = mBase;
tmp += sep;
std::string::size_type dirsep = in.rfind('/', last_dirsep);
@ -223,7 +271,7 @@ private:
last_dirsep = dirsep-1;
tmp += in.substr(dirsep+1, in.length()-pos);
if (wrapped->Exists(tmp)) {
if (mWrapped->Exists(tmp)) {
in = tmp;
return;
}
@ -236,15 +284,14 @@ private:
// -------------------------------------------------------------------
/** Cleanup the given path
*/
void Cleanup (std::string& in) const
{
char last = 0;
void Cleanup (std::string& in) const {
if(in.empty()) {
return;
}
// Remove a very common issue when we're parsing file names: spaces at the
// beginning of the path.
char last = 0;
std::string::iterator it = in.begin();
while (IsSpaceOrNewLine( *it ))++it;
if (it != in.begin()) {
@ -274,9 +321,7 @@ private:
it = in.erase(it);
--it;
}
}
else if (*it == '%' && in.end() - it > 2) {
} else if (*it == '%' && in.end() - it > 2) {
// Hex sequence in URIs
if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) {
*it = HexOctetToDecimal(&*it);
@ -290,8 +335,8 @@ private:
}
private:
IOSystem* wrapped;
std::string src_file, base;
IOSystem *mWrapped;
std::string mSrc_file, mBase;
char sep;
};

View File

@ -60,9 +60,9 @@ namespace Assimp {
* @param in Input mesh
* @return Hash.
*/
inline uint64_t GetMeshHash(aiMesh* in)
{
ai_assert(NULL != in);
inline
uint64_t GetMeshHash(aiMesh* in) {
ai_assert(nullptr != in);
// ... get an unique value representing the vertex format of the mesh
const unsigned int fhash = GetMeshVFormatUnique(in);
@ -78,14 +78,14 @@ inline uint64_t GetMeshHash(aiMesh* in)
/** @brief Perform a component-wise comparison of two arrays
*
* @param first First array
* @param second Second aray
* @param second Second array
* @param size Size of both arrays
* @param e Epsilon
* @return true if the arrays are identical
*/
inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
unsigned int size, float e)
{
inline
bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
unsigned int size, float e) {
for (const aiVector3D* end = first+size; first != end; ++first,++second) {
if ( (*first - *second).SquareLength() >= e)
return false;

View File

@ -731,17 +731,22 @@ enum MeshAttribute {
TexCoord
};
static const std::string PosToken = "position";
static const std::string ColToken = "color";
static const std::string NormalToken = "normal";
static const std::string TexCoordToken = "texcoord";
//------------------------------------------------------------------------------------------------
static MeshAttribute getAttributeByName( const char *attribName ) {
ai_assert( nullptr != attribName );
if ( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
if ( 0 == strncmp( PosToken.c_str(), attribName, PosToken.size() ) ) {
return Position;
} else if ( 0 == strncmp( "color", attribName, strlen( "color" ) ) ) {
} else if ( 0 == strncmp( ColToken.c_str(), attribName, ColToken.size() ) ) {
return Color;
} else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) {
} else if( 0 == strncmp( NormalToken.c_str(), attribName, NormalToken.size() ) ) {
return Normal;
} else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) {
} else if( 0 == strncmp( TexCoordToken.c_str(), attribName, TexCoordToken.size() ) ) {
return TexCoord;
}
@ -1098,17 +1103,15 @@ void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene * /*pS
return;
}
const float floatVal( val->getFloat() );
if ( prop->m_value != nullptr ) {
if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) {
m_currentCamera->mHorizontalFOV = floatVal;
} else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 3 ) ) {
} else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 4 ) ) {
m_currentCamera->mClipPlaneNear = floatVal;
} else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) {
m_currentCamera->mClipPlaneFar = floatVal;
}
}
}
}
//------------------------------------------------------------------------------------------------
void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) {

View File

@ -125,6 +125,9 @@ corresponding preprocessor flag to selectively disable steps.
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
# include "DeboneProcess.h"
#endif
#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS)
# include "ScaleProcess.h"
#endif
namespace Assimp {
@ -136,7 +139,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
// of sequence it is executed. Steps that are added here are not
// validated - as RegisterPPStep() does - all dependencies must be given.
// ----------------------------------------------------------------------------
out.reserve(30);
out.reserve(31);
#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
out.push_back( new MakeLeftHandedProcess());
#endif
@ -197,7 +200,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
#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 ..
// XXX this is actually a design weakness that dates back to the time

View File

@ -39,6 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS
#include "ScaleProcess.h"
#include <assimp/scene.h>
@ -104,3 +106,5 @@ void ScaleProcess::applyScaling( aiNode *currentNode ) {
}
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS

View File

@ -1279,6 +1279,7 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) {
break;
default:
ai_assert(false);
break;
}
}
}

View File

@ -294,7 +294,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
index++;
// Now start iterating from there until the first position lays outside of the distance range.
// Add all positions inside the distance range within the tolerance to the result aray
// Add all positions inside the distance range within the tolerance to the result array
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
while( ToBinary(it->mDistance) < maxDistBinary)
{

View File

@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "VertexTriangleAdjacency.h"
#include <assimp/mesh.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
@ -60,8 +59,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
// compute the number of referenced vertices if it wasn't specified by the caller
const aiFace* const pcFaceEnd = pcFaces + iNumFaces;
if (!iNumVertices) {
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
ai_assert( nullptr != pcFace );
ai_assert(3 == pcFace->mNumIndices);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
@ -69,19 +68,18 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
}
}
this->iNumVertices = iNumVertices;
mNumVertices = iNumVertices;
unsigned int* pi;
// allocate storage
if (bComputeNumTriangles) {
pi = mLiveTriangles = new unsigned int[iNumVertices+1];
memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1));
mOffsetTable = new unsigned int[iNumVertices+2]+1;
}
else {
} else {
pi = mOffsetTable = new unsigned int[iNumVertices+2]+1;
memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1));
mLiveTriangles = NULL; // important, otherwise the d'tor would crash
}
@ -90,8 +88,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces,
*piEnd++ = 0u;
// first pass: compute the number of faces referencing each vertex
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace)
{
for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) {
pi[pcFace->mIndices[0]]++;
pi[pcFace->mIndices[1]]++;
pi[pcFace->mIndices[2]]++;

View File

@ -60,10 +60,8 @@ namespace Assimp {
* @note Although it is called #VertexTriangleAdjacency, the current version does also
* support arbitrary polygons. */
// --------------------------------------------------------------------------------------------
class ASSIMP_API VertexTriangleAdjacency
{
class ASSIMP_API VertexTriangleAdjacency {
public:
// ----------------------------------------------------------------------------
/** @brief Construction from an existing index buffer
* @param pcFaces Index buffer
@ -77,39 +75,30 @@ public:
unsigned int iNumVertices = 0,
bool bComputeNumTriangles = true);
// ----------------------------------------------------------------------------
/** @brief Destructor */
~VertexTriangleAdjacency();
public:
// ----------------------------------------------------------------------------
/** @brief Get all triangles adjacent to a vertex
* @param iVertIndex Index of the vertex
* @return A pointer to the adjacency list. */
unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const
{
ai_assert(iVertIndex < iNumVertices);
unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const {
ai_assert(iVertIndex < mNumVertices);
return &mAdjacencyTable[ mOffsetTable[iVertIndex]];
}
// ----------------------------------------------------------------------------
/** @brief Get the number of triangles that are referenced by
* a vertex. This function returns a reference that can be modified
* @param iVertIndex Index of the vertex
* @return Number of referenced triangles */
unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex)
{
ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles);
unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) {
ai_assert( iVertIndex < mNumVertices );
ai_assert( nullptr != mLiveTriangles );
return mLiveTriangles[iVertIndex];
}
public:
//! Offset table
unsigned int* mOffsetTable;
@ -120,9 +109,9 @@ public:
unsigned int* mLiveTriangles;
//! Debug: Number of referenced vertices
unsigned int iNumVertices;
unsigned int mNumVertices;
};
}
} //! ns Assimp
#endif // !! AI_VTADJACENCY_H_INC

View File

@ -248,9 +248,9 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
}
}
bool continuationFound( false ), endOfDataLine( false );
bool continuationFound( false );
size_t i = 0;
while ( !endOfDataLine ) {
for( ;; ) {
if ( continuationToken == m_cache[ m_cachePos ] ) {
continuationFound = true;
++m_cachePos;

View File

@ -66,49 +66,50 @@ static const unsigned int BufferSize = 4096;
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToLower( char_t in)
{
AI_FORCE_INLINE
char_t ToLower( char_t in ) {
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToUpper( char_t in) {
AI_FORCE_INLINE
char_t ToUpper( char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in)
{
AI_FORCE_INLINE
bool IsUpper( char_t in) {
return (in >= (char_t)'A' && in <= (char_t)'Z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in)
{
AI_FORCE_INLINE
bool IsLower( char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in)
{
AI_FORCE_INLINE
bool IsSpace( char_t in) {
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( char_t in)
{
AI_FORCE_INLINE
bool IsLineEnd( char_t in) {
return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
}
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{
AI_FORCE_INLINE
bool IsSpaceOrNewLine( char_t in) {
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}

View File

@ -14,8 +14,8 @@
// ------------------------------------------------------------------------------------
#ifndef __FAST_A_TO_F_H_INCLUDED__
#define __FAST_A_TO_F_H_INCLUDED__
#ifndef FAST_A_TO_F_H_INCLUDED
#define FAST_A_TO_F_H_INCLUDED
#include <cmath>
#include <limits>
@ -26,15 +26,13 @@
#include "StringComparison.h"
#include <assimp/DefaultLogger.hpp>
#ifdef _MSC_VER
# include <stdint.h>
#else
# include <assimp/Compiler/pstdint.h>
#endif
namespace Assimp
{
namespace Assimp {
const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
0.0,
@ -64,8 +62,9 @@ unsigned int strtoul10( const char* in, const char** out=0) {
unsigned int value = 0;
for ( ;; ) {
if ( *in < '0' || *in > '9' )
if ( *in < '0' || *in > '9' ) {
break;
}
value = ( value * 10 ) + ( *in - '0' );
++in;
@ -109,8 +108,7 @@ unsigned int strtoul16( const char* in, const char** out=0) {
value = ( value << 4u ) + ( *in - 'A' ) + 10;
} else if (*in >= 'a' && *in <= 'f') {
value = ( value << 4u ) + ( *in - 'a' ) + 10;
}
else {
} else {
break;
}
++in;
@ -205,7 +203,6 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
return 0;
}
//throw std::overflow_error();
value = new_value;
@ -213,21 +210,23 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
++cur;
if (max_inout && *max_inout == cur) {
if (out) { /* skip to end */
while (*in >= '0' && *in <= '9')
while ( *in >= '0' && *in <= '9' ) {
++in;
}
*out = in;
}
return value;
}
}
if (out)
if ( out ) {
*out = in;
}
if (max_inout)
if ( max_inout ) {
*max_inout = cur;
}
return value;
}
@ -249,7 +248,6 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou
return value;
}
// Number of relevant decimals for floating-point parsing.
#define AI_FAST_ATOF_RELAVANT_DECIMALS 15
@ -322,7 +320,6 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
if (*c == 'e' || *c == 'E') {
++c;
const bool einv = (*c=='-');
if (einv || *c=='+') {
@ -352,6 +349,7 @@ inline
ai_real fast_atof(const char* c) {
ai_real ret(0.0);
fast_atoreal_move<ai_real>(c, ret);
return ret;
}
@ -374,4 +372,4 @@ ai_real fast_atof( const char** inout) {
} //! namespace Assimp
#endif // __FAST_A_TO_F_H_INCLUDED__
#endif // FAST_A_TO_F_H_INCLUDED

View File

@ -243,20 +243,31 @@ struct aiVertexWeight {
*
* A bone has a name by which it can be found in the frame hierarchy and by
* which it can be addressed by animations. In addition it has a number of
* influences on vertices.
* influences on vertices, and a matrix relating the mesh position to the
* position of the bone at the time of binding.
*/
struct aiBone {
//! The name of the bone.
C_STRUCT aiString mName;
//! The number of vertices affected by this bone
//! The number of vertices affected by this bone.
//! The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
unsigned int mNumWeights;
//! The vertices affected by this bone
//! The influence weights of this bone, by vertex index.
C_STRUCT aiVertexWeight* mWeights;
//! Matrix that transforms from mesh space to bone space in bind pose
/** Matrix that transforms from bone space to mesh space in bind pose.
*
* This matrix describes the position of the mesh
* in the local space of this bone when the skeleton was bound.
* Thus it can be used directly to determine a desired vertex position,
* given the world-space transform of the bone when animated,
* and the position of the vertex in mesh space.
*
* It is sometimes called an inverse-bind matrix,
* or inverse bind pose matrix.
*/
C_STRUCT aiMatrix4x4 mOffsetMatrix;
#ifdef __cplusplus

View File

@ -47,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Main.h"
const char* AICMD_MSG_INFO_HELP_E =
"assimp info <file> [-r]\n"
"assimp info <file> [-r] [-v]\n"
"\tPrint basic structure of a 3D model\n"
"\t-r,--raw: No postprocessing, do a raw import\n";
"\t-r,--raw: No postprocessing, do a raw import\n"
"\t-v,--verbose: Print verbose info such as node transform data\n";
// -----------------------------------------------------------------------------------
@ -184,7 +185,7 @@ std::string FindPTypes(const aiScene* scene)
// -----------------------------------------------------------------------------------
void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline,
unsigned int cline, unsigned int cnest=0)
unsigned int cline, bool verbose, unsigned int cnest=0)
{
if (cline++ >= maxline || cnest >= maxnest) {
return;
@ -194,8 +195,29 @@ void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxli
printf("-- ");
}
printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes);
if (verbose) {
// print the actual transform
//printf(",");
aiVector3D s, r, t;
root->mTransformation.Decompose(s, r, t);
if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) {
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
printf(" S:[%f %f %f]\n", s.x, s.y, s.z);
}
if (r.x || r.y || r.z) {
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
printf(" R:[%f %f %f]\n", r.x, r.y, r.z);
}
if (t.x || t.y || t.z) {
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
printf(" T:[%f %f %f]\n", t.x, t.y, t.z);
}
}
//printf("\n");
for (unsigned int i = 0; i < root->mNumChildren; ++i ) {
PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,cnest+1);
PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1);
if(i == root->mNumChildren-1) {
for(unsigned int i = 0; i < cnest; ++i) {
printf(" ");
@ -230,10 +252,23 @@ int Assimp_Info (const char* const* params, unsigned int num)
const std::string in = std::string(params[0]);
// get -r and -v arguments
bool raw = false;
bool verbose = false;
for(unsigned int i = 1; i < num; ++i) {
if (!strcmp(params[i],"--raw")||!strcmp(params[i],"-r")) {
raw = true;
}
if (!strcmp(params[i],"--verbose")||!strcmp(params[i],"-v")) {
verbose = true;
}
}
// do maximum post-processing unless -r was specified
ImportData import;
import.ppFlags = num>1&&(!strcmp(params[1],"--raw")||!strcmp(params[1],"-r")) ? 0
: aiProcessPreset_TargetRealtime_MaxQuality;
if (!raw) {
import.ppFlags = aiProcessPreset_TargetRealtime_MaxQuality;
}
// import the main model
const aiScene* scene = ImportModel(import,in);
@ -346,7 +381,7 @@ int Assimp_Info (const char* const* params, unsigned int num)
printf("\nNode hierarchy:\n");
unsigned int cline=0;
PrintHierarchy(scene->mRootNode,20,1000,cline);
PrintHierarchy(scene->mRootNode,20,1000,cline,verbose);
printf("\n");
return 0;