Merge branch 'master' into add_progresshandler_support_jassimp
commit
64c40a576f
|
@ -966,6 +966,9 @@ if( MSVC )
|
||||||
set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
|
set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
|
||||||
|
set(WindowsStore TRUE)
|
||||||
|
endif()
|
||||||
SET_TARGET_PROPERTIES( assimp PROPERTIES
|
SET_TARGET_PROPERTIES( assimp PROPERTIES
|
||||||
VERSION ${ASSIMP_VERSION}
|
VERSION ${ASSIMP_VERSION}
|
||||||
SOVERSION ${ASSIMP_SOVERSION} # use full version
|
SOVERSION ${ASSIMP_SOVERSION} # use full version
|
||||||
|
|
|
@ -728,8 +728,11 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
std::vector<aiAnimMesh*> animMeshes;
|
std::vector<aiAnimMesh*> animMeshes;
|
||||||
for (unsigned int i = 0; i < targetMeshes.size(); i++)
|
for (unsigned int i = 0; i < targetMeshes.size(); i++)
|
||||||
{
|
{
|
||||||
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i));
|
aiMesh* targetMesh = targetMeshes.at(i);
|
||||||
animMesh->mWeight = targetWeights[i];
|
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
|
||||||
|
float weight = targetWeights[i];
|
||||||
|
animMesh->mWeight = weight == 0 ? 1.0f : weight;
|
||||||
|
animMesh->mName = targetMesh->mName;
|
||||||
animMeshes.push_back(animMesh);
|
animMeshes.push_back(animMesh);
|
||||||
}
|
}
|
||||||
dstMesh->mMethod = (method == Collada::Relative)
|
dstMesh->mMethod = (method == Collada::Relative)
|
||||||
|
|
|
@ -166,8 +166,9 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||||
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
|
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
|
||||||
{
|
{
|
||||||
pMesh->mVertices[a].z *= -1.0f;
|
pMesh->mVertices[a].z *= -1.0f;
|
||||||
if( pMesh->HasNormals())
|
if (pMesh->HasNormals()) {
|
||||||
pMesh->mNormals[a].z *= -1.0f;
|
pMesh->mNormals[a].z *= -1.0f;
|
||||||
|
}
|
||||||
if( pMesh->HasTangentsAndBitangents())
|
if( pMesh->HasTangentsAndBitangents())
|
||||||
{
|
{
|
||||||
pMesh->mTangents[a].z *= -1.0f;
|
pMesh->mTangents[a].z *= -1.0f;
|
||||||
|
@ -175,6 +176,23 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mirror anim meshes positions, normals and stuff along the Z axis
|
||||||
|
for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m)
|
||||||
|
{
|
||||||
|
for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a)
|
||||||
|
{
|
||||||
|
pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f;
|
||||||
|
if (pMesh->mAnimMeshes[m]->HasNormals()) {
|
||||||
|
pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f;
|
||||||
|
}
|
||||||
|
if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents())
|
||||||
|
{
|
||||||
|
pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f;
|
||||||
|
pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// mirror offset matrices of all bones
|
// mirror offset matrices of all bones
|
||||||
for( size_t a = 0; a < pMesh->mNumBones; ++a)
|
for( size_t a = 0; a < pMesh->mNumBones; ++a)
|
||||||
{
|
{
|
||||||
|
@ -346,9 +364,51 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
|
||||||
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
|
||||||
{
|
{
|
||||||
aiFace& face = pMesh->mFaces[a];
|
aiFace& face = pMesh->mFaces[a];
|
||||||
for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
|
for (unsigned int b = 0; b < face.mNumIndices / 2; b++) {
|
||||||
std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
|
std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// invert the order of all components in this mesh anim meshes
|
||||||
|
for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) {
|
||||||
|
aiAnimMesh* animMesh = pMesh->mAnimMeshes[m];
|
||||||
|
unsigned int numVertices = animMesh->mNumVertices;
|
||||||
|
if (animMesh->HasPositions()) {
|
||||||
|
for (unsigned int a = 0; a < numVertices; a++)
|
||||||
|
{
|
||||||
|
std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (animMesh->HasNormals()) {
|
||||||
|
for (unsigned int a = 0; a < numVertices; a++)
|
||||||
|
{
|
||||||
|
std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
|
||||||
|
if (animMesh->HasTextureCoords(i)) {
|
||||||
|
for (unsigned int a = 0; a < numVertices; a++)
|
||||||
|
{
|
||||||
|
std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (animMesh->HasTangentsAndBitangents()) {
|
||||||
|
for (unsigned int a = 0; a < numVertices; a++)
|
||||||
|
{
|
||||||
|
std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]);
|
||||||
|
std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) {
|
||||||
|
if (animMesh->HasVertexColors(v)) {
|
||||||
|
for (unsigned int a = 0; a < numVertices; a++)
|
||||||
|
{
|
||||||
|
std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
|
||||||
|
|
|
@ -76,6 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t fileName16[PATHLIMIT];
|
wchar_t fileName16[PATHLIMIT];
|
||||||
|
|
||||||
|
#ifndef WindowsStore
|
||||||
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
|
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
|
|
||||||
|
@ -85,12 +86,15 @@ bool DefaultIOSystem::Exists( const char* pFile) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#endif
|
||||||
FILE* file = ::fopen(pFile, "rb");
|
FILE* file = ::fopen(pFile, "rb");
|
||||||
if (!file)
|
if (!file)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
::fclose(file);
|
::fclose(file);
|
||||||
|
#ifndef WindowsStore
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
FILE* file = ::fopen( pFile, "rb");
|
FILE* file = ::fopen( pFile, "rb");
|
||||||
if( !file)
|
if( !file)
|
||||||
|
@ -110,14 +114,18 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
|
||||||
FILE* file;
|
FILE* file;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
wchar_t fileName16[PATHLIMIT];
|
wchar_t fileName16[PATHLIMIT];
|
||||||
|
#ifndef WindowsStore
|
||||||
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
|
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
|
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
|
||||||
std::string mode8(strMode);
|
std::string mode8(strMode);
|
||||||
file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
|
file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
|
||||||
} else {
|
} else {
|
||||||
|
#endif
|
||||||
file = ::fopen(strFile, strMode);
|
file = ::fopen(strFile, strMode);
|
||||||
|
#ifndef WindowsStore
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
file = ::fopen(strFile, strMode);
|
file = ::fopen(strFile, strMode);
|
||||||
#endif
|
#endif
|
||||||
|
@ -158,6 +166,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
||||||
{
|
{
|
||||||
ai_assert(in && _out);
|
ai_assert(in && _out);
|
||||||
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
#if defined( _MSC_VER ) || defined( __MINGW32__ )
|
||||||
|
#ifndef WindowsStore
|
||||||
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
|
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
|
||||||
if (isUnicode) {
|
if (isUnicode) {
|
||||||
wchar_t out16[PATHLIMIT];
|
wchar_t out16[PATHLIMIT];
|
||||||
|
@ -175,6 +184,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
#endif
|
||||||
char* ret = :: _fullpath(_out, in, PATHLIMIT);
|
char* ret = :: _fullpath(_out, in, PATHLIMIT);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
// preserve the input path, maybe someone else is able to fix
|
// preserve the input path, maybe someone else is able to fix
|
||||||
|
@ -182,7 +192,9 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
|
||||||
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
|
ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
|
||||||
strcpy(_out, in);
|
strcpy(_out, in);
|
||||||
}
|
}
|
||||||
|
#ifndef WindowsStore
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
// use realpath
|
// use realpath
|
||||||
char* ret = realpath(in, _out);
|
char* ret = realpath(in, _out);
|
||||||
|
|
|
@ -105,8 +105,8 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
|
||||||
const Scope& sc = GetRequiredScope(element);
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
|
||||||
// find target node
|
// find target node
|
||||||
const char* whitelist[] = {"Model","NodeAttribute"};
|
const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
|
||||||
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
|
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
|
||||||
|
|
||||||
for(const Connection* con : conns) {
|
for(const Connection* con : conns) {
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "FBXUtil.h"
|
#include "FBXUtil.h"
|
||||||
#include "FBXProperties.h"
|
#include "FBXProperties.h"
|
||||||
#include "FBXImporter.h"
|
#include "FBXImporter.h"
|
||||||
|
|
||||||
#include <assimp/StringComparison.h>
|
#include <assimp/StringComparison.h>
|
||||||
|
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
|
#include <assimp/CreateAnimMesh.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@ -188,7 +191,8 @@ void FBXConverter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4&
|
||||||
std::string old_original_name = original_name;
|
std::string old_original_name = original_name;
|
||||||
GetUniqueName(old_original_name, original_name);
|
GetUniqueName(old_original_name, original_name);
|
||||||
nodes_chain.push_back(new aiNode(original_name));
|
nodes_chain.push_back(new aiNode(original_name));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
original_name = nodes_chain.back()->mName.C_Str();
|
original_name = nodes_chain.back()->mName.C_Str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +240,8 @@ void FBXConverter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4&
|
||||||
|
|
||||||
new_abs_transform *= postnode->mTransformation;
|
new_abs_transform *= postnode->mTransformation;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// free the nodes we allocated as we don't need them
|
// free the nodes we allocated as we don't need them
|
||||||
Util::delete_fun<aiNode> deleter;
|
Util::delete_fun<aiNode> deleter;
|
||||||
std::for_each(
|
std::for_each(
|
||||||
|
@ -622,7 +627,8 @@ bool FBXConverter::NeedsComplexTransformationChain( const Model& model )
|
||||||
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if ( ok ) {
|
}
|
||||||
|
else if (ok) {
|
||||||
if (v.SquareLength() > zero_epsilon) {
|
if (v.SquareLength() > zero_epsilon) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -720,7 +726,8 @@ void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vec
|
||||||
for (unsigned int i = 0; i < 3; ++i) {
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) {
|
if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) {
|
||||||
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
|
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component");
|
FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component");
|
||||||
canscale = false;
|
canscale = false;
|
||||||
break;
|
break;
|
||||||
|
@ -787,7 +794,8 @@ void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vec
|
||||||
comp == TransformationComp_GeometricTranslationInverse
|
comp == TransformationComp_GeometricTranslationInverse
|
||||||
) {
|
) {
|
||||||
post_output_nodes.push_back(nd);
|
post_output_nodes.push_back(nd);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
output_nodes.push_back(nd);
|
output_nodes.push_back(nd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -830,17 +838,23 @@ void FBXConverter::SetupNodeMetadata( const Model& model, aiNode& nd )
|
||||||
// Interpret the property as a concrete type
|
// Interpret the property as a concrete type
|
||||||
if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >()) {
|
if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >()) {
|
||||||
data->Set(index++, prop.first, interpreted->Value());
|
data->Set(index++, prop.first, interpreted->Value());
|
||||||
} else if ( const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >() ) {
|
}
|
||||||
|
else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >()) {
|
||||||
data->Set(index++, prop.first, interpreted->Value());
|
data->Set(index++, prop.first, interpreted->Value());
|
||||||
} else if ( const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >() ) {
|
}
|
||||||
|
else if (const TypedProperty<uint64_t>* interpreted = prop.second->As<TypedProperty<uint64_t> >()) {
|
||||||
data->Set(index++, prop.first, interpreted->Value());
|
data->Set(index++, prop.first, interpreted->Value());
|
||||||
} else if ( const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >() ) {
|
}
|
||||||
|
else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >()) {
|
||||||
data->Set(index++, prop.first, interpreted->Value());
|
data->Set(index++, prop.first, interpreted->Value());
|
||||||
} else if ( const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >() ) {
|
}
|
||||||
|
else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >()) {
|
||||||
data->Set(index++, prop.first, aiString(interpreted->Value()));
|
data->Set(index++, prop.first, aiString(interpreted->Value()));
|
||||||
} else if ( const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >() ) {
|
}
|
||||||
|
else if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >()) {
|
||||||
data->Set(index++, prop.first, interpreted->Value());
|
data->Set(index++, prop.first, interpreted->Value());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ai_assert(false);
|
ai_assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1055,6 +1069,45 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial( const MeshGeometry& mesh,
|
||||||
ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION);
|
ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<aiAnimMesh*> animMeshes;
|
||||||
|
for (const BlendShape* blendShape : mesh.GetBlendShapes()) {
|
||||||
|
for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) {
|
||||||
|
const std::vector<const ShapeGeometry*>& shapeGeometries = blendShapeChannel->GetShapeGeometries();
|
||||||
|
for (size_t i = 0; i < shapeGeometries.size(); i++) {
|
||||||
|
aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
|
||||||
|
const ShapeGeometry* shapeGeometry = shapeGeometries.at(i);
|
||||||
|
const std::vector<aiVector3D>& vertices = shapeGeometry->GetVertices();
|
||||||
|
const std::vector<aiVector3D>& normals = shapeGeometry->GetNormals();
|
||||||
|
const std::vector<unsigned int>& indices = shapeGeometry->GetIndices();
|
||||||
|
animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
|
||||||
|
for (size_t j = 0; j < indices.size(); j++) {
|
||||||
|
unsigned int index = indices.at(j);
|
||||||
|
aiVector3D vertex = vertices.at(j);
|
||||||
|
aiVector3D normal = normals.at(j);
|
||||||
|
unsigned int count = 0;
|
||||||
|
const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count);
|
||||||
|
for (unsigned int k = 0; k < count; k++) {
|
||||||
|
unsigned int index = outIndices[k];
|
||||||
|
animMesh->mVertices[index] += vertex;
|
||||||
|
if (animMesh->mNormals != nullptr) {
|
||||||
|
animMesh->mNormals[index] += normal;
|
||||||
|
animMesh->mNormals[index].NormalizeSafe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f;
|
||||||
|
animMeshes.push_back(animMesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t numAnimMeshes = animMeshes.size();
|
||||||
|
if (numAnimMeshes > 0) {
|
||||||
|
out_mesh->mNumAnimMeshes = static_cast<unsigned int>(numAnimMeshes);
|
||||||
|
out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes];
|
||||||
|
for (size_t i = 0; i < numAnimMeshes; i++) {
|
||||||
|
out_mesh->mAnimMeshes[i] = animMeshes.at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
return static_cast<unsigned int>(meshes.size() - 1);
|
return static_cast<unsigned int>(meshes.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1559,7 +1612,8 @@ void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMa
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture* const tex = (*it).second;
|
const Texture* const tex = (*it).second;
|
||||||
if ( tex != nullptr ) {
|
if (tex != 0)
|
||||||
|
{
|
||||||
aiString path = GetTexturePath(tex);
|
aiString path = GetTexturePath(tex);
|
||||||
out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0);
|
out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0);
|
||||||
|
|
||||||
|
@ -1793,28 +1847,40 @@ void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const TextureMap&
|
||||||
{
|
{
|
||||||
TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
|
TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh);
|
TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh);
|
||||||
TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
|
TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
|
TrySetTextureProperties(out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
|
||||||
TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
|
TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
|
TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
|
TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
|
TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh);
|
TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh);
|
||||||
TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
||||||
|
TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
|
||||||
|
TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
|
||||||
|
//Maya counterparts
|
||||||
|
TrySetTextureProperties(out_mat, textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
|
void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
|
||||||
{
|
{
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh);
|
||||||
TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
|
TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh);
|
||||||
|
TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh);
|
||||||
TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
|
TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh);
|
||||||
TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
||||||
|
TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh );
|
||||||
|
TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh );
|
||||||
}
|
}
|
||||||
|
|
||||||
aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
|
aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
|
||||||
|
@ -2039,6 +2105,16 @@ std::string FBXConverter::FixNodeName( const std::string& name ) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FBXConverter::FixAnimMeshName(const std::string& name) {
|
||||||
|
if (name.length()) {
|
||||||
|
size_t indexOf = name.find_first_of("::");
|
||||||
|
if (indexOf != std::string::npos && indexOf < name.size() - 2) {
|
||||||
|
return name.substr(indexOf + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name.length() ? name : "AnimMesh";
|
||||||
|
}
|
||||||
|
|
||||||
void FBXConverter::ConvertAnimationStack(const AnimationStack& st)
|
void FBXConverter::ConvertAnimationStack(const AnimationStack& st)
|
||||||
{
|
{
|
||||||
const AnimationLayerList& layers = st.Layers();
|
const AnimationLayerList& layers = st.Layers();
|
||||||
|
@ -2071,26 +2147,28 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
|
||||||
const char* prop_whitelist[] = {
|
const char* prop_whitelist[] = {
|
||||||
"Lcl Scaling",
|
"Lcl Scaling",
|
||||||
"Lcl Rotation",
|
"Lcl Rotation",
|
||||||
"Lcl Translation"
|
"Lcl Translation",
|
||||||
|
"DeformPercent"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::map<std::string, morphAnimData*> morphAnimDatas;
|
||||||
|
|
||||||
for (const AnimationLayer* layer : layers) {
|
for (const AnimationLayer* layer : layers) {
|
||||||
ai_assert(layer);
|
ai_assert(layer);
|
||||||
|
const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 4);
|
||||||
const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 );
|
|
||||||
for (const AnimationCurveNode* node : nodes) {
|
for (const AnimationCurveNode* node : nodes) {
|
||||||
ai_assert(node);
|
ai_assert(node);
|
||||||
|
|
||||||
const Model* const model = dynamic_cast<const Model*>(node->Target());
|
const Model* const model = dynamic_cast<const Model*>(node->Target());
|
||||||
// this can happen - it could also be a NodeAttribute (i.e. for camera animations)
|
if (model) {
|
||||||
if ( !model ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& name = FixNodeName(model->Name());
|
const std::string& name = FixNodeName(model->Name());
|
||||||
node_map[name].push_back(node);
|
node_map[name].push_back(node);
|
||||||
|
|
||||||
layer_map[node] = layer;
|
layer_map[node] = layer;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const BlendShapeChannel* const bsc = dynamic_cast<const BlendShapeChannel*>(node->Target());
|
||||||
|
if (bsc) {
|
||||||
|
ProcessMorphAnimDatas(&morphAnimDatas, bsc, node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2126,12 +2204,42 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node_anims.size() || morphAnimDatas.size()) {
|
||||||
if (node_anims.size()) {
|
if (node_anims.size()) {
|
||||||
anim->mChannels = new aiNodeAnim*[node_anims.size()]();
|
anim->mChannels = new aiNodeAnim*[node_anims.size()]();
|
||||||
anim->mNumChannels = static_cast<unsigned int>(node_anims.size());
|
anim->mNumChannels = static_cast<unsigned int>(node_anims.size());
|
||||||
|
|
||||||
std::swap_ranges(node_anims.begin(), node_anims.end(), anim->mChannels);
|
std::swap_ranges(node_anims.begin(), node_anims.end(), anim->mChannels);
|
||||||
}
|
}
|
||||||
|
if (morphAnimDatas.size()) {
|
||||||
|
unsigned int numMorphMeshChannels = static_cast<unsigned int>(morphAnimDatas.size());
|
||||||
|
anim->mMorphMeshChannels = new aiMeshMorphAnim*[numMorphMeshChannels];
|
||||||
|
anim->mNumMorphMeshChannels = numMorphMeshChannels;
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (auto morphAnimIt : morphAnimDatas) {
|
||||||
|
morphAnimData* animData = morphAnimIt.second;
|
||||||
|
unsigned int numKeys = static_cast<unsigned int>(animData->size());
|
||||||
|
aiMeshMorphAnim* meshMorphAnim = new aiMeshMorphAnim();
|
||||||
|
meshMorphAnim->mName.Set(morphAnimIt.first);
|
||||||
|
meshMorphAnim->mNumKeys = numKeys;
|
||||||
|
meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
|
||||||
|
unsigned int j = 0;
|
||||||
|
for (auto animIt : *animData) {
|
||||||
|
morphKeyData* keyData = animIt.second;
|
||||||
|
unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
|
||||||
|
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
||||||
|
meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights];
|
||||||
|
meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights];
|
||||||
|
meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps;
|
||||||
|
for (unsigned int k = 0; k < numValuesAndWeights; k++) {
|
||||||
|
meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k);
|
||||||
|
meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
anim->mMorphMeshChannels[i++] = meshMorphAnim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// empty animations would fail validation, so drop them
|
// empty animations would fail validation, so drop them
|
||||||
delete anim;
|
delete anim;
|
||||||
|
@ -2146,13 +2254,22 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
|
||||||
// adjust relative timing for animation
|
// adjust relative timing for animation
|
||||||
for (unsigned int c = 0; c < anim->mNumChannels; c++) {
|
for (unsigned int c = 0; c < anim->mNumChannels; c++) {
|
||||||
aiNodeAnim* channel = anim->mChannels[c];
|
aiNodeAnim* channel = anim->mChannels[c];
|
||||||
for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ )
|
for (uint32_t i = 0; i < channel->mNumPositionKeys; i++) {
|
||||||
channel->mPositionKeys[i].mTime -= start_time_fps;
|
channel->mPositionKeys[i].mTime -= start_time_fps;
|
||||||
for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ )
|
}
|
||||||
|
for (uint32_t i = 0; i < channel->mNumRotationKeys; i++) {
|
||||||
channel->mRotationKeys[i].mTime -= start_time_fps;
|
channel->mRotationKeys[i].mTime -= start_time_fps;
|
||||||
for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ )
|
}
|
||||||
|
for (uint32_t i = 0; i < channel->mNumScalingKeys; i++) {
|
||||||
channel->mScalingKeys[i].mTime -= start_time_fps;
|
channel->mScalingKeys[i].mTime -= start_time_fps;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (unsigned int c = 0; c < anim->mNumMorphMeshChannels; c++) {
|
||||||
|
aiMeshMorphAnim* channel = anim->mMorphMeshChannels[c];
|
||||||
|
for (uint32_t i = 0; i < channel->mNumKeys; i++) {
|
||||||
|
channel->mKeys[i].mTime -= start_time_fps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// for some mysterious reason, mDuration is simply the maximum key -- the
|
// for some mysterious reason, mDuration is simply the maximum key -- the
|
||||||
// validator always assumes animations to start at zero.
|
// validator always assumes animations to start at zero.
|
||||||
|
@ -2160,6 +2277,68 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
|
||||||
anim->mTicksPerSecond = anim_fps;
|
anim->mTicksPerSecond = anim_fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node) {
|
||||||
|
std::vector<const Connection*> bscConnections = doc.GetConnectionsBySourceSequenced(bsc->ID(), "Deformer");
|
||||||
|
for (const Connection* bscConnection : bscConnections) {
|
||||||
|
auto bs = dynamic_cast<const BlendShape*>(bscConnection->DestinationObject());
|
||||||
|
if (bs) {
|
||||||
|
auto channelIt = std::find(bs->BlendShapeChannels().begin(), bs->BlendShapeChannels().end(), bsc);
|
||||||
|
if (channelIt != bs->BlendShapeChannels().end()) {
|
||||||
|
auto channelIndex = static_cast<unsigned int>(std::distance(bs->BlendShapeChannels().begin(), channelIt));
|
||||||
|
std::vector<const Connection*> bsConnections = doc.GetConnectionsBySourceSequenced(bs->ID(), "Geometry");
|
||||||
|
for (const Connection* bsConnection : bsConnections) {
|
||||||
|
auto geo = dynamic_cast<const Geometry*>(bsConnection->DestinationObject());
|
||||||
|
if (geo) {
|
||||||
|
std::vector<const Connection*> geoConnections = doc.GetConnectionsBySourceSequenced(geo->ID(), "Model");
|
||||||
|
for (const Connection* geoConnection : geoConnections) {
|
||||||
|
auto model = dynamic_cast<const Model*>(geoConnection->DestinationObject());
|
||||||
|
if (model) {
|
||||||
|
auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
|
||||||
|
auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
|
||||||
|
auto name = aiString(FixNodeName(model->Name() + "*"));
|
||||||
|
name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
|
||||||
|
morphAnimData* animData;
|
||||||
|
auto animIt = morphAnimDatas->find(name.C_Str());
|
||||||
|
if (animIt == morphAnimDatas->end()) {
|
||||||
|
animData = new morphAnimData();
|
||||||
|
morphAnimDatas->insert(std::make_pair(name.C_Str(), animData));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
animData = animIt->second;
|
||||||
|
}
|
||||||
|
for (std::pair<std::string, const AnimationCurve*> curvesIt : node->Curves()) {
|
||||||
|
if (curvesIt.first == "d|DeformPercent") {
|
||||||
|
const AnimationCurve* animationCurve = curvesIt.second;
|
||||||
|
const KeyTimeList& keys = animationCurve->GetKeys();
|
||||||
|
const KeyValueList& values = animationCurve->GetValues();
|
||||||
|
unsigned int k = 0;
|
||||||
|
for (auto key : keys) {
|
||||||
|
morphKeyData* keyData;
|
||||||
|
auto keyIt = animData->find(key);
|
||||||
|
if (keyIt == animData->end()) {
|
||||||
|
keyData = new morphKeyData();
|
||||||
|
animData->insert(std::make_pair(key, keyData));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keyData = keyIt->second;
|
||||||
|
}
|
||||||
|
keyData->values.push_back(channelIndex);
|
||||||
|
keyData->weights.push_back(values.at(k) / 100.0f);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
#ifdef ASSIMP_BUILD_DEBUG
|
#ifdef ASSIMP_BUILD_DEBUG
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// sanity check whether the input is ok
|
// sanity check whether the input is ok
|
||||||
|
@ -2415,6 +2594,7 @@ void FBXConverter::GenerateNodeAnimations( std::vector<aiNodeAnim*>& node_anims,
|
||||||
node_anim_chain_bits[fixed_name] = flags;
|
node_anim_chain_bits[fixed_name] = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FBXConverter::IsRedundantAnimationData(const Model& target,
|
bool FBXConverter::IsRedundantAnimationData(const Model& target,
|
||||||
TransformationComp comp,
|
TransformationComp comp,
|
||||||
const std::vector<const AnimationCurveNode*>& curves) {
|
const std::vector<const AnimationCurveNode*>& curves) {
|
||||||
|
@ -3019,10 +3199,22 @@ void FBXConverter::ConvertGlobalSettings() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->mMetaData = aiMetadata::Alloc(1);
|
out->mMetaData = aiMetadata::Alloc(15);
|
||||||
unsigned int index(0);
|
out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis());
|
||||||
const double unitScalFactor(doc.GlobalSettings().UnitScaleFactor());
|
out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign());
|
||||||
out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor);
|
out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis());
|
||||||
|
out->mMetaData->Set(3, "FrontAxisSign", doc.GlobalSettings().FrontAxisSign());
|
||||||
|
out->mMetaData->Set(4, "CoordAxis", doc.GlobalSettings().CoordAxis());
|
||||||
|
out->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign());
|
||||||
|
out->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis());
|
||||||
|
out->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign());
|
||||||
|
out->mMetaData->Set(8, "UnitScaleFactor", (double)doc.GlobalSettings().UnitScaleFactor());
|
||||||
|
out->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor());
|
||||||
|
out->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor());
|
||||||
|
out->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode());
|
||||||
|
out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
|
||||||
|
out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
|
||||||
|
out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::TransferDataToScene()
|
void FBXConverter::TransferDataToScene()
|
||||||
|
|
|
@ -63,6 +63,12 @@ struct aiScene;
|
||||||
struct aiNode;
|
struct aiNode;
|
||||||
struct aiMaterial;
|
struct aiMaterial;
|
||||||
|
|
||||||
|
struct morphKeyData {
|
||||||
|
std::vector<unsigned int> values;
|
||||||
|
std::vector<float> weights;
|
||||||
|
};
|
||||||
|
typedef std::map<int64_t, morphKeyData*> morphAnimData;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
|
||||||
|
@ -272,6 +278,7 @@ private:
|
||||||
// the function is guaranteed to provide consistent results over multiple invocations
|
// the function is guaranteed to provide consistent results over multiple invocations
|
||||||
// UNLESS RenameNode() is called for a particular node name.
|
// UNLESS RenameNode() is called for a particular node name.
|
||||||
std::string FixNodeName(const std::string& name);
|
std::string FixNodeName(const std::string& name);
|
||||||
|
std::string FixAnimMeshName(const std::string& name);
|
||||||
|
|
||||||
typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
|
typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
|
||||||
|
|
||||||
|
@ -281,6 +288,9 @@ private:
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAnimationStack(const AnimationStack& st);
|
void ConvertAnimationStack(const AnimationStack& st);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
||||||
const std::string& fixed_name,
|
const std::string& fixed_name,
|
||||||
|
|
|
@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "FBXParser.h"
|
#include "FBXParser.h"
|
||||||
#include "FBXDocument.h"
|
#include "FBXDocument.h"
|
||||||
|
#include "FBXMeshGeometry.h"
|
||||||
#include "FBXImporter.h"
|
#include "FBXImporter.h"
|
||||||
#include "FBXDocumentUtil.h"
|
#include "FBXDocumentUtil.h"
|
||||||
|
|
||||||
|
@ -158,9 +159,55 @@ Skin::~Skin()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||||
|
: Deformer(id, element, doc, name)
|
||||||
|
{
|
||||||
|
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer");
|
||||||
|
blendShapeChannels.reserve(conns.size());
|
||||||
|
for (const Connection* con : conns) {
|
||||||
|
const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
|
||||||
|
if (bspc) {
|
||||||
|
blendShapeChannels.push_back(bspc);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
BlendShape::~BlendShape()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||||
|
: Deformer(id, element, doc, name)
|
||||||
|
{
|
||||||
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
const Element* const DeformPercent = sc["DeformPercent"];
|
||||||
|
if (DeformPercent) {
|
||||||
|
percent = ParseTokenAsFloat(GetRequiredToken(*DeformPercent, 0));
|
||||||
|
}
|
||||||
|
const Element* const FullWeights = sc["FullWeights"];
|
||||||
|
if (FullWeights) {
|
||||||
|
ParseVectorDataArray(fullWeights, *FullWeights);
|
||||||
|
}
|
||||||
|
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Geometry");
|
||||||
|
shapeGeometries.reserve(conns.size());
|
||||||
|
for (const Connection* con : conns) {
|
||||||
|
const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
|
||||||
|
if (sg) {
|
||||||
|
shapeGeometries.push_back(sg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
BlendShapeChannel::~BlendShapeChannel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,9 @@ const Object* LazyObject::Get(bool dieOnError)
|
||||||
if (!strcmp(classtag.c_str(),"Mesh")) {
|
if (!strcmp(classtag.c_str(),"Mesh")) {
|
||||||
object.reset(new MeshGeometry(id,element,name,doc));
|
object.reset(new MeshGeometry(id,element,name,doc));
|
||||||
}
|
}
|
||||||
|
if (!strcmp(classtag.c_str(), "Shape")) {
|
||||||
|
object.reset(new ShapeGeometry(id, element, name, doc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp(obtype,"NodeAttribute",length)) {
|
else if (!strncmp(obtype,"NodeAttribute",length)) {
|
||||||
if (!strcmp(classtag.c_str(),"Camera")) {
|
if (!strcmp(classtag.c_str(),"Camera")) {
|
||||||
|
@ -171,6 +174,12 @@ const Object* LazyObject::Get(bool dieOnError)
|
||||||
else if (!strcmp(classtag.c_str(),"Skin")) {
|
else if (!strcmp(classtag.c_str(),"Skin")) {
|
||||||
object.reset(new Skin(id,element,doc,name));
|
object.reset(new Skin(id,element,doc,name));
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(classtag.c_str(), "BlendShape")) {
|
||||||
|
object.reset(new BlendShape(id, element, doc, name));
|
||||||
|
}
|
||||||
|
else if (!strcmp(classtag.c_str(), "BlendShapeChannel")) {
|
||||||
|
object.reset(new BlendShapeChannel(id, element, doc, name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( !strncmp( obtype, "Model", length ) ) {
|
else if ( !strncmp( obtype, "Model", length ) ) {
|
||||||
// FK and IK effectors are not supported
|
// FK and IK effectors are not supported
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct ImportSettings;
|
||||||
class PropertyTable;
|
class PropertyTable;
|
||||||
class Document;
|
class Document;
|
||||||
class Material;
|
class Material;
|
||||||
|
class ShapeGeometry;
|
||||||
class Geometry;
|
class Geometry;
|
||||||
|
|
||||||
class Video;
|
class Video;
|
||||||
|
@ -74,6 +75,8 @@ class AnimationCurveNode;
|
||||||
class AnimationLayer;
|
class AnimationLayer;
|
||||||
class AnimationStack;
|
class AnimationStack;
|
||||||
|
|
||||||
|
class BlendShapeChannel;
|
||||||
|
class BlendShape;
|
||||||
class Skin;
|
class Skin;
|
||||||
class Cluster;
|
class Cluster;
|
||||||
|
|
||||||
|
@ -869,6 +872,46 @@ private:
|
||||||
typedef std::vector<float> WeightArray;
|
typedef std::vector<float> WeightArray;
|
||||||
typedef std::vector<unsigned int> WeightIndexArray;
|
typedef std::vector<unsigned int> WeightIndexArray;
|
||||||
|
|
||||||
|
|
||||||
|
/** DOM class for BlendShapeChannel deformers */
|
||||||
|
class BlendShapeChannel : public Deformer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
virtual ~BlendShapeChannel();
|
||||||
|
|
||||||
|
float DeformPercent() const {
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WeightArray& GetFullWeights() const {
|
||||||
|
return fullWeights;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
|
||||||
|
return shapeGeometries;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
float percent;
|
||||||
|
WeightArray fullWeights;
|
||||||
|
std::vector<const ShapeGeometry*> shapeGeometries;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** DOM class for BlendShape deformers */
|
||||||
|
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 {
|
||||||
|
return blendShapeChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<const BlendShapeChannel*> blendShapeChannels;
|
||||||
|
};
|
||||||
|
|
||||||
/** DOM class for skin deformer clusters (aka subdeformers) */
|
/** DOM class for skin deformer clusters (aka subdeformers) */
|
||||||
class Cluster : public Deformer
|
class Cluster : public Deformer
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,18 +70,26 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
||||||
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
||||||
if(sk) {
|
if(sk) {
|
||||||
skin = sk;
|
skin = sk;
|
||||||
break;
|
}
|
||||||
|
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
||||||
|
if (bsp) {
|
||||||
|
blendShapes.push_back(bsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Geometry::~Geometry()
|
Geometry::~Geometry()
|
||||||
{
|
{
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||||
|
return blendShapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
const Skin* Geometry::DeformerSkin() const {
|
const Skin* Geometry::DeformerSkin() const {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +240,6 @@ const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index
|
||||||
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
|
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
|
||||||
return m_materials;
|
return m_materials;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
|
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
|
||||||
if ( in_index >= m_mapping_counts.size() ) {
|
if ( in_index >= m_mapping_counts.size() ) {
|
||||||
|
@ -640,9 +647,39 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
|
||||||
<< MappingInformationType << "," << ReferenceInformationType);
|
<< MappingInformationType << "," << ReferenceInformationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||||
|
: Geometry(id, element, name, doc)
|
||||||
|
{
|
||||||
|
const Scope* sc = element.Compound();
|
||||||
|
if (!sc) {
|
||||||
|
DOMError("failed to read Geometry object (class: Shape), no data scope found");
|
||||||
|
}
|
||||||
|
const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element);
|
||||||
|
const Element& Normals = GetRequiredElement(*sc, "Normals", &element);
|
||||||
|
const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element);
|
||||||
|
ParseVectorDataArray(m_indices, Indexes);
|
||||||
|
ParseVectorDataArray(m_vertices, Vertices);
|
||||||
|
ParseVectorDataArray(m_normals, Normals);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
ShapeGeometry::~ShapeGeometry() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
|
||||||
|
return m_vertices;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
|
||||||
|
return m_normals;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
|
||||||
|
return m_indices;
|
||||||
|
}
|
||||||
} // !FBX
|
} // !FBX
|
||||||
} // !Assimp
|
} // !Assimp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,13 @@ public:
|
||||||
/** Get the Skin attached to this geometry or NULL */
|
/** Get the Skin attached to this geometry or NULL */
|
||||||
const Skin* DeformerSkin() const;
|
const Skin* DeformerSkin() const;
|
||||||
|
|
||||||
|
/** Get the BlendShape attached to this geometry or NULL */
|
||||||
|
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Skin* skin;
|
const Skin* skin;
|
||||||
|
std::vector<const BlendShape*> blendShapes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<int> MatIndexArray;
|
typedef std::vector<int> MatIndexArray;
|
||||||
|
@ -125,7 +130,6 @@ public:
|
||||||
/** Determine the face to which a particular output vertex index belongs.
|
/** Determine the face to which a particular output vertex index belongs.
|
||||||
* This mapping is always unique. */
|
* This mapping is always unique. */
|
||||||
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadLayer( const Scope& layer );
|
void ReadLayer( const Scope& layer );
|
||||||
void ReadLayerElement( const Scope& layerElement );
|
void ReadLayerElement( const Scope& layerElement );
|
||||||
|
@ -174,6 +178,34 @@ private:
|
||||||
std::vector<unsigned int> m_mappings;
|
std::vector<unsigned int> m_mappings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOM class for FBX geometry of type "Shape"
|
||||||
|
*/
|
||||||
|
class ShapeGeometry : public Geometry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** The class constructor */
|
||||||
|
ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||||
|
|
||||||
|
/** The class destructor */
|
||||||
|
virtual ~ShapeGeometry();
|
||||||
|
|
||||||
|
/** Get a list of all vertex points, non-unique*/
|
||||||
|
const std::vector<aiVector3D>& GetVertices() const;
|
||||||
|
|
||||||
|
/** Get a list of all vertex normals or an empty array if
|
||||||
|
* no normals are specified. */
|
||||||
|
const std::vector<aiVector3D>& GetNormals() const;
|
||||||
|
|
||||||
|
/** Return list of vertex indices. */
|
||||||
|
const std::vector<unsigned int>& GetIndices() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<aiVector3D> m_vertices;
|
||||||
|
std::vector<aiVector3D> m_normals;
|
||||||
|
std::vector<unsigned int> m_indices;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,9 +208,20 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||||
uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
|
uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
|
||||||
LogInfo("Decompressing IFCZIP file");
|
LogInfo("Decompressing IFCZIP file");
|
||||||
unzOpenCurrentFile(zip);
|
unzOpenCurrentFile(zip);
|
||||||
const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
|
size_t total = 0;
|
||||||
|
int read = 0;
|
||||||
|
do {
|
||||||
|
int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX;
|
||||||
|
void* buffer = malloc(bufferSize);
|
||||||
|
read = unzReadCurrentFile(zip, buffer, bufferSize);
|
||||||
|
if (read > 0) {
|
||||||
|
memcpy((char*)buff + total, buffer, read);
|
||||||
|
total += read;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
} while (read > 0);
|
||||||
size_t filesize = fileInfo.uncompressed_size;
|
size_t filesize = fileInfo.uncompressed_size;
|
||||||
if ( ret < 0 || size_t(ret) != filesize )
|
if (total == 0 || size_t(total) != filesize)
|
||||||
{
|
{
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
ThrowException("Failed to decompress IFC ZIP file");
|
ThrowException("Failed to decompress IFC ZIP file");
|
||||||
|
|
|
@ -119,7 +119,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
size_t lastFilePos( 0 );
|
size_t lastFilePos( 0 );
|
||||||
|
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
|
while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) {
|
||||||
m_DataIt = buffer.begin();
|
m_DataIt = buffer.begin();
|
||||||
m_DataItEnd = buffer.end();
|
m_DataItEnd = buffer.end();
|
||||||
|
|
||||||
|
|
|
@ -438,13 +438,16 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
|
for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
|
||||||
if (!attr.texcoord[tc]) {
|
if (attr.color[c]->count != aim->mNumVertices) {
|
||||||
DefaultLogger::get()->warn("NULL texcoord encountered in mesh \"" + mesh.name +
|
DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name +
|
||||||
"\" and will be ignored");
|
"\" does not match the vertex count");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
aim->mColors[c] = new aiColor4D[attr.color[c]->count];
|
||||||
|
attr.color[c]->ExtractData(aim->mColors[c]);
|
||||||
|
}
|
||||||
|
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
|
||||||
if (attr.texcoord[tc]->count != aim->mNumVertices) {
|
if (attr.texcoord[tc]->count != aim->mNumVertices) {
|
||||||
DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name +
|
DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name +
|
||||||
"\" does not match the vertex count");
|
"\" does not match the vertex count");
|
||||||
|
|
|
@ -243,7 +243,7 @@ template<class T>
|
||||||
inline
|
inline
|
||||||
bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
|
bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
|
||||||
buffer.resize( m_cacheSize );
|
buffer.resize( m_cacheSize );
|
||||||
if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
|
if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) {
|
||||||
if ( !readNextBlock() ) {
|
if ( !readNextBlock() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -273,6 +273,9 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
|
||||||
buffer[ i ] = m_cache[ m_cachePos ];
|
buffer[ i ] = m_cache[ m_cachePos ];
|
||||||
++m_cachePos;
|
++m_cachePos;
|
||||||
++i;
|
++i;
|
||||||
|
if (m_cachePos >= size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if ( m_cachePos >= m_cacheSize ) {
|
if ( m_cachePos >= m_cacheSize ) {
|
||||||
if ( !readNextBlock() ) {
|
if ( !readNextBlock() ) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -402,7 +402,7 @@ enum aiPrimitiveType
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief NOT CURRENTLY IN USE. An AnimMesh is an attachment to an #aiMesh stores per-vertex
|
/** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
|
||||||
* animations for a particular frame.
|
* animations for a particular frame.
|
||||||
*
|
*
|
||||||
* You may think of an #aiAnimMesh as a `patch` for the host mesh, which
|
* You may think of an #aiAnimMesh as a `patch` for the host mesh, which
|
||||||
|
@ -414,6 +414,9 @@ enum aiPrimitiveType
|
||||||
*/
|
*/
|
||||||
struct aiAnimMesh
|
struct aiAnimMesh
|
||||||
{
|
{
|
||||||
|
/**Anim Mesh name */
|
||||||
|
C_STRUCT aiString mName;
|
||||||
|
|
||||||
/** Replacement for aiMesh::mVertices. If this array is non-NULL,
|
/** Replacement for aiMesh::mVertices. If this array is non-NULL,
|
||||||
* it *must* contain mNumVertices entries. The corresponding
|
* it *must* contain mNumVertices entries. The corresponding
|
||||||
* array in the host mesh must be non-NULL as well - animation
|
* array in the host mesh must be non-NULL as well - animation
|
||||||
|
|
Loading…
Reference in New Issue