Merge pull request #2293 from rickomax/master

Various additions/fixes (FBX blend-shapes support added)
pull/2295/head^2
Kim Kulling 2019-01-08 21:53:53 +01:00 committed by GitHub
commit e26220c432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 3372 additions and 2904 deletions

View File

@ -966,6 +966,9 @@ if( MSVC )
set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
endif()
if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")
set(WindowsStore TRUE)
endif()
SET_TARGET_PROPERTIES( assimp PROPERTIES
VERSION ${ASSIMP_VERSION}
SOVERSION ${ASSIMP_SOVERSION} # use full version

View File

@ -728,8 +728,11 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
std::vector<aiAnimMesh*> animMeshes;
for (unsigned int i = 0; i < targetMeshes.size(); i++)
{
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i));
animMesh->mWeight = targetWeights[i];
aiMesh* targetMesh = targetMeshes.at(i);
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
float weight = targetWeights[i];
animMesh->mWeight = weight == 0 ? 1.0f : weight;
animMesh->mName = targetMesh->mName;
animMeshes.push_back(animMesh);
}
dstMesh->mMethod = (method == Collada::Relative)

View File

@ -166,8 +166,9 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
for( size_t a = 0; a < pMesh->mNumVertices; ++a)
{
pMesh->mVertices[a].z *= -1.0f;
if( pMesh->HasNormals())
if (pMesh->HasNormals()) {
pMesh->mNormals[a].z *= -1.0f;
}
if( pMesh->HasTangentsAndBitangents())
{
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
for( size_t a = 0; a < pMesh->mNumBones; ++a)
{
@ -346,8 +364,50 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{
aiFace& face = pMesh->mFaces[a];
for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
for (unsigned int b = 0; b < face.mNumIndices / 2; 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]);
}
}
}
}
}

View File

@ -76,6 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
#ifndef WindowsStore
bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
if (isUnicode) {
@ -85,12 +86,15 @@ bool DefaultIOSystem::Exists( const char* pFile) const
return false;
}
} else {
#endif
FILE* file = ::fopen(pFile, "rb");
if (!file)
return false;
::fclose(file);
#ifndef WindowsStore
}
#endif
#else
FILE* file = ::fopen( pFile, "rb");
if( !file)
@ -110,14 +114,18 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
FILE* file;
#ifdef _WIN32
wchar_t fileName16[PATHLIMIT];
#ifndef WindowsStore
bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
if (isUnicode) {
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
std::string mode8(strMode);
file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
} else {
#endif
file = ::fopen(strFile, strMode);
#ifndef WindowsStore
}
#endif
#else
file = ::fopen(strFile, strMode);
#endif
@ -158,6 +166,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
{
ai_assert(in && _out);
#if defined( _MSC_VER ) || defined( __MINGW32__ )
#ifndef WindowsStore
bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
if (isUnicode) {
wchar_t out16[PATHLIMIT];
@ -175,6 +184,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
}
} else {
#endif
char* ret = :: _fullpath(_out, in, PATHLIMIT);
if (!ret) {
// 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));
strcpy(_out, in);
}
#ifndef WindowsStore
}
#endif
#else
// use realpath
char* ret = realpath(in, _out);

View File

@ -105,8 +105,8 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
const Scope& sc = GetRequiredScope(element);
// find target node
const char* whitelist[] = {"Model","NodeAttribute"};
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
for(const Connection* con : conns) {

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,12 @@ struct aiScene;
struct aiNode;
struct aiMaterial;
struct morphKeyData {
std::vector<unsigned int> values;
std::vector<float> weights;
};
typedef std::map<int64_t, morphKeyData*> morphAnimData;
namespace Assimp {
namespace FBX {
@ -272,6 +278,7 @@ private:
// the function is guaranteed to provide consistent results over multiple invocations
// UNLESS RenameNode() is called for a particular node name.
std::string FixNodeName(const std::string& name);
std::string FixAnimMeshName(const std::string& name);
typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
@ -281,6 +288,9 @@ private:
// ------------------------------------------------------------------------------------------------
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,
const std::string& fixed_name,

View File

@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXParser.h"
#include "FBXDocument.h"
#include "FBXMeshGeometry.h"
#include "FBXImporter.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

View File

@ -146,6 +146,9 @@ const Object* LazyObject::Get(bool dieOnError)
if (!strcmp(classtag.c_str(),"Mesh")) {
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)) {
if (!strcmp(classtag.c_str(),"Camera")) {
@ -171,6 +174,12 @@ const Object* LazyObject::Get(bool dieOnError)
else if (!strcmp(classtag.c_str(),"Skin")) {
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 ) ) {
// FK and IK effectors are not supported

View File

@ -65,6 +65,7 @@ struct ImportSettings;
class PropertyTable;
class Document;
class Material;
class ShapeGeometry;
class Geometry;
class Video;
@ -74,6 +75,8 @@ class AnimationCurveNode;
class AnimationLayer;
class AnimationStack;
class BlendShapeChannel;
class BlendShape;
class Skin;
class Cluster;
@ -869,6 +872,46 @@ private:
typedef std::vector<float> WeightArray;
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) */
class Cluster : public Deformer
{

View File

@ -62,7 +62,7 @@ using namespace Util;
// ------------------------------------------------------------------------------------------------
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element,name)
: Object(id, element, name)
, skin()
{
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"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);
if(sk) {
skin = sk;
break;
}
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
if (bsp) {
blendShapes.push_back(bsp);
}
}
}
// ------------------------------------------------------------------------------------------------
Geometry::~Geometry()
{
// empty
}
// ------------------------------------------------------------------------------------------------
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
return blendShapes;
}
// ------------------------------------------------------------------------------------------------
const Skin* Geometry::DeformerSkin() const {
return skin;
}
@ -232,7 +240,6 @@ const std::vector<aiColor4D>& MeshGeometry::GetVertexColors( unsigned int index
const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
return m_materials;
}
// ------------------------------------------------------------------------------------------------
const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
if ( in_index >= m_mapping_counts.size() ) {
@ -640,9 +647,39 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
<< 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
} // !Assimp
#endif

View File

@ -64,8 +64,13 @@ public:
/** Get the Skin attached to this geometry or NULL */
const Skin* DeformerSkin() const;
/** Get the BlendShape attached to this geometry or NULL */
const std::vector<const BlendShape*>& GetBlendShapes() const;
private:
const Skin* skin;
std::vector<const BlendShape*> blendShapes;
};
typedef std::vector<int> MatIndexArray;
@ -125,7 +130,6 @@ public:
/** Determine the face to which a particular output vertex index belongs.
* This mapping is always unique. */
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
private:
void ReadLayer( const Scope& layer );
void ReadLayerElement( const Scope& layerElement );
@ -174,6 +178,34 @@ private:
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;
};
}
}

View File

@ -207,10 +207,21 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
}
uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
LogInfo("Decompressing IFCZIP file");
unzOpenCurrentFile( zip );
const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
unzOpenCurrentFile(zip);
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;
if ( ret < 0 || size_t(ret) != filesize )
if (total == 0 || size_t(total) != filesize)
{
delete[] buff;
ThrowException("Failed to decompress IFC ZIP file");

View File

@ -119,7 +119,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
size_t lastFilePos( 0 );
std::vector<char> buffer;
while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) {
m_DataIt = buffer.begin();
m_DataItEnd = buffer.end();

View File

@ -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) {
if (!attr.texcoord[tc]) {
DefaultLogger::get()->warn("NULL texcoord encountered in mesh \"" + mesh.name +
"\" and will be ignored");
for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
if (attr.color[c]->count != aim->mNumVertices) {
DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name +
"\" does not match the vertex count");
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) {
DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name +
"\" does not match the vertex count");

View File

@ -243,7 +243,7 @@ template<class T>
inline
bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
buffer.resize( m_cacheSize );
if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) {
if ( !readNextBlock() ) {
return false;
}
@ -273,6 +273,9 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
buffer[ i ] = m_cache[ m_cachePos ];
++m_cachePos;
++i;
if (m_cachePos >= size()) {
break;
}
if ( m_cachePos >= m_cacheSize ) {
if ( !readNextBlock() ) {
return false;

View File

@ -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.
*
* You may think of an #aiAnimMesh as a `patch` for the host mesh, which
@ -414,6 +414,9 @@ enum aiPrimitiveType
*/
struct aiAnimMesh
{
/**Anim Mesh name */
C_STRUCT aiString mName;
/** Replacement for aiMesh::mVertices. If this array is non-NULL,
* it *must* contain mNumVertices entries. The corresponding
* array in the host mesh must be non-NULL as well - animation