Merge branch 'master' into fix_obj_progress_reporting

pull/2296/head
Kim Kulling 2019-01-09 22:09:25 +01:00 committed by GitHub
commit 19c3cea0db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 3474 additions and 2921 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,9 +364,51 @@ 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++)
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]);
}
}
}
}
}
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS

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) {

View File

@ -53,10 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXUtil.h"
#include "FBXProperties.h"
#include "FBXImporter.h"
#include <assimp/StringComparison.h>
#include <assimp/scene.h>
#include <assimp/CreateAnimMesh.h>
#include <tuple>
#include <memory>
#include <iterator>
@ -188,7 +191,8 @@ void FBXConverter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4&
std::string old_original_name = original_name;
GetUniqueName(old_original_name, original_name);
nodes_chain.push_back(new aiNode(original_name));
} else {
}
else {
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;
}
} else {
}
else {
// free the nodes we allocated as we don't need them
Util::delete_fun<aiNode> deleter;
std::for_each(
@ -622,7 +627,8 @@ bool FBXConverter::NeedsComplexTransformationChain( const Model& model )
if ((v - all_ones).SquareLength() > zero_epsilon) {
return true;
}
} else if ( ok ) {
}
else if (ok) {
if (v.SquareLength() > zero_epsilon) {
return true;
}
@ -720,7 +726,8 @@ void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vec
for (unsigned int i = 0; i < 3; ++i) {
if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) {
GeometricScalingInverse[i] = 1.0f / GeometricScaling[i];
} else {
}
else {
FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component");
canscale = false;
break;
@ -787,7 +794,8 @@ void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vec
comp == TransformationComp_GeometricTranslationInverse
) {
post_output_nodes.push_back(nd);
} else {
}
else {
output_nodes.push_back(nd);
}
}
@ -830,17 +838,23 @@ void FBXConverter::SetupNodeMetadata( const Model& model, aiNode& nd )
// Interpret the property as a concrete type
if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >()) {
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());
} 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());
} 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());
} 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()));
} 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());
} else {
}
else {
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);
}
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);
}
@ -1559,7 +1612,8 @@ void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMa
}
const Texture* const tex = (*it).second;
if ( tex != nullptr ) {
if (tex != 0)
{
aiString path = GetTexturePath(tex);
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, "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, "TransparencyFactor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh);
TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, 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)
{
TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, 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, "TransparencyFactor", aiTextureType_OPACITY, mesh );
TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh);
TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh);
TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, 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,
@ -2039,6 +2105,16 @@ std::string FBXConverter::FixNodeName( const std::string& 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)
{
const AnimationLayerList& layers = st.Layers();
@ -2071,26 +2147,28 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
const char* prop_whitelist[] = {
"Lcl Scaling",
"Lcl Rotation",
"Lcl Translation"
"Lcl Translation",
"DeformPercent"
};
std::map<std::string, morphAnimData*> morphAnimDatas;
for (const AnimationLayer* layer : layers) {
ai_assert(layer);
const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 );
const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 4);
for (const AnimationCurveNode* node : nodes) {
ai_assert(node);
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 ) {
continue;
}
if (model) {
const std::string& name = FixNodeName(model->Name());
node_map[name].push_back(node);
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;
}
if (node_anims.size() || morphAnimDatas.size()) {
if (node_anims.size()) {
anim->mChannels = new aiNodeAnim*[node_anims.size()]();
anim->mNumChannels = static_cast<unsigned int>(node_anims.size());
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 {
// empty animations would fail validation, so drop them
delete anim;
@ -2146,13 +2254,22 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
// adjust relative timing for animation
for (unsigned int c = 0; c < anim->mNumChannels; 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;
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;
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;
}
}
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
// validator always assumes animations to start at zero.
@ -2160,6 +2277,68 @@ void FBXConverter::ConvertAnimationStack( const AnimationStack& st )
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
// ------------------------------------------------------------------------------------------------
// 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;
}
bool FBXConverter::IsRedundantAnimationData(const Model& target,
TransformationComp comp,
const std::vector<const AnimationCurveNode*>& curves) {
@ -3019,10 +3199,22 @@ void FBXConverter::ConvertGlobalSettings() {
return;
}
out->mMetaData = aiMetadata::Alloc(1);
unsigned int index(0);
const double unitScalFactor(doc.GlobalSettings().UnitScaleFactor());
out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor);
out->mMetaData = aiMetadata::Alloc(15);
out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis());
out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign());
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()

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

@ -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

@ -208,9 +208,20 @@ 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);
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

@ -118,7 +118,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

View File

@ -1,6 +1,7 @@
#include "jassimp.h"
#include <assimp/Importer.hpp>
#include <assimp/ProgressHandler.hpp>
#include <assimp/scene.h>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
@ -248,7 +249,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char*
return false;
}
jboolean jReturnValue = env->CallBooleanMethod(object, mid, params[0].l);
jboolean jReturnValue = env->CallBooleanMethodA(object, mid, params);
return (bool)jReturnValue;
}
@ -591,6 +592,24 @@ class JavaIOSystem : public Assimp::IOSystem {
};
class JavaProgressHandler : public Assimp::ProgressHandler {
private:
JNIEnv* mJniEnv;
jobject& mJavaProgressHandler;
public:
JavaProgressHandler(JNIEnv* env, jobject& javaProgressHandler) :
mJniEnv(env),
mJavaProgressHandler(javaProgressHandler)
{};
bool Update(float percentage)
{
jvalue params[1];
params[0].f = percentage;
return call(mJniEnv, mJavaProgressHandler, "jassimp/AiProgressHandler", "update", "(F)Z", params);
}
};
static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
{
@ -1880,7 +1899,7 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
(JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem)
(JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem, jobject progressHandler)
{
jobject jScene = NULL;
@ -1896,6 +1915,11 @@ JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
lprintf("Created aiFileIO\n");
}
if(progressHandler != NULL)
{
imp.SetProgressHandler(new JavaProgressHandler(env, progressHandler));
}
lprintf("opening file: %s\n", cFilename);
/* do import */

View File

@ -39,7 +39,7 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
* Signature: (Ljava/lang/String;J)Ljassimp/AiScene;
*/
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
(JNIEnv *, jclass, jstring, jlong, jobject);
(JNIEnv *, jclass, jstring, jlong, jobject, jobject);
#ifdef __cplusplus
}

View File

@ -457,7 +457,7 @@ public final class AiMaterial {
*
* @return the data
*/
private Object getData() {
public Object getData() {
return m_data;
}
}

View File

@ -0,0 +1,46 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library - Java Binding (jassimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
package jassimp;
public interface AiProgressHandler
{
boolean update(float percentage);
}

View File

@ -47,11 +47,6 @@ import java.util.Set;
* Status flags for {@link AiScene}s.
*/
public enum AiSceneFlag {
/**
* The mapped c/c++ integer enum value.
*/
private final int m_rawValue;
/**
* Specifies that the scene data structure that was imported is not
* complete.<p>
@ -120,6 +115,10 @@ public enum AiSceneFlag {
*/
TERRAIN(0x10);
/**
* The mapped c/c++ integer enum value.
*/
private final int m_rawValue;
/**
* Utility method for converting from c/c++ based integer enums to java

View File

@ -69,7 +69,8 @@ public final class Jassimp {
* @throws IOException if an error occurs
*/
private static native AiScene aiImportFile(String filename,
long postProcessing, AiIOSystem<?> ioSystem) throws IOException;
long postProcessing, AiIOSystem<?> ioSystem,
AiProgressHandler progressHandler) throws IOException;
/**
@ -158,11 +159,26 @@ public final class Jassimp {
public static AiScene importFile(String filename,
Set<AiPostProcessSteps> postProcessing, AiIOSystem<?> ioSystem)
throws IOException {
return importFile(filename, postProcessing, ioSystem, null);
}
/**
* Imports a file via assimp.
*
* @param filename the file to import
* @param postProcessing post processing flags
* @param ioSystem ioSystem to load files, or null for default
* @return the loaded scene, or null if an error occurred
* @throws IOException if an error occurs
*/
public static AiScene importFile(String filename,
Set<AiPostProcessSteps> postProcessing, AiIOSystem<?> ioSystem,
AiProgressHandler progressHandler) throws IOException {
loadLibrary();
return aiImportFile(filename, AiPostProcessSteps.toRawValue(
postProcessing), ioSystem);
postProcessing), ioSystem, progressHandler);
}