Merge branch 'master' into master
commit
ed5d38b975
28
Build.md
28
Build.md
|
@ -1,17 +1,31 @@
|
||||||
# Build Instructions
|
# Build Instructions
|
||||||
## Install CMake
|
|
||||||
|
## Build on all platforms using vcpkg
|
||||||
|
You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Microsoft/vcpkg.git
|
||||||
|
cd vcpkg
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
./vcpkg integrate install
|
||||||
|
vcpkg install assimp
|
||||||
|
```
|
||||||
|
The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||||
|
|
||||||
|
## Manual build instructions
|
||||||
|
|
||||||
|
### Install CMake
|
||||||
Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
|
Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install cmake
|
sudo apt-get install cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
## Get the source
|
### Get the source
|
||||||
Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
|
Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/assimp/assimp.git
|
git clone https://github.com/assimp/assimp.git
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build instructions for Windows with Visual-Studio
|
### Build instructions for Windows with Visual-Studio
|
||||||
|
|
||||||
First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
|
First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
|
||||||
To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
|
To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
|
||||||
|
@ -20,10 +34,10 @@ cmake CMakeLists.txt
|
||||||
```
|
```
|
||||||
This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
|
This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
|
||||||
|
|
||||||
## Build instructions for Windows with UWP
|
### Build instructions for Windows with UWP
|
||||||
See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
|
See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
|
||||||
|
|
||||||
## Build instructions for Linux / Unix
|
### Build instructions for Linux / Unix
|
||||||
Open a terminal and got to your repository. You can generate the makefiles and build the library via:
|
Open a terminal and got to your repository. You can generate the makefiles and build the library via:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -34,7 +48,7 @@ The option -j descripes the number of parallel processes for the build. In this
|
||||||
|
|
||||||
If you want to use a IDE for linux you can try QTCreator for instance.
|
If you want to use a IDE for linux you can try QTCreator for instance.
|
||||||
|
|
||||||
## Build instructions for MinGW
|
### Build instructions for MinGW
|
||||||
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
|
Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag
|
||||||
required to compile some of assimp's files, especially for debug builds.
|
required to compile some of assimp's files, especially for debug builds.
|
||||||
Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
|
Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
|
||||||
|
@ -50,7 +64,7 @@ The following toolchain may or may not be helpful for building assimp using MinG
|
||||||
|
|
||||||
Besides the toolchain, compilation should be the same as for Linux / Unix.
|
Besides the toolchain, compilation should be the same as for Linux / Unix.
|
||||||
|
|
||||||
## CMake build options
|
### CMake build options
|
||||||
The cmake-build-environment provides options to configure the build. The following options can be used:
|
The cmake-build-environment provides options to configure the build. The following options can be used:
|
||||||
- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
|
- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
|
||||||
- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle
|
- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle
|
||||||
|
|
|
@ -120,7 +120,7 @@ __Exporters__:
|
||||||
- FBX ( experimental )
|
- FBX ( experimental )
|
||||||
|
|
||||||
### Building ###
|
### Building ###
|
||||||
Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
|
Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
|
||||||
|
|
||||||
### Ports ###
|
### Ports ###
|
||||||
* [Android](port/AndroidJNI/README.md)
|
* [Android](port/AndroidJNI/README.md)
|
||||||
|
|
|
@ -16,6 +16,7 @@ matrix:
|
||||||
image:
|
image:
|
||||||
- Visual Studio 2015
|
- Visual Studio 2015
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
|
- Visual Studio 2019
|
||||||
- MinGW
|
- MinGW
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
|
@ -30,8 +31,8 @@ install:
|
||||||
- if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH%
|
- if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH%
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
|
||||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
|
||||||
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" set CMAKE_GENERATOR_NAME=Visual Studio 16 2019
|
||||||
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" .
|
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" -A %platform% .
|
||||||
# Rename sh.exe as sh.exe in PATH interferes with MinGW
|
# Rename sh.exe as sh.exe in PATH interferes with MinGW
|
||||||
- rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe"
|
- rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe"
|
||||||
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
|
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
|
||||||
|
|
|
@ -1196,6 +1196,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
|
||||||
|
|
||||||
// and reallocate all arrays
|
// and reallocate all arrays
|
||||||
CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
|
CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
|
||||||
|
CopyPtrArray( dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1215,6 +1216,26 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
|
||||||
GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
|
GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) {
|
||||||
|
if ( nullptr == _dest || nullptr == src ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
|
||||||
|
|
||||||
|
// get a flat copy
|
||||||
|
::memcpy(dest,src,sizeof(aiMeshMorphAnim));
|
||||||
|
|
||||||
|
// and reallocate all arrays
|
||||||
|
GetArrayCopy( dest->mKeys, dest->mNumKeys );
|
||||||
|
for (ai_uint i = 0; i < dest->mNumKeys;++i) {
|
||||||
|
dest->mKeys[i].mValues = new unsigned int[dest->mKeys[i].mNumValuesAndWeights];
|
||||||
|
dest->mKeys[i].mWeights = new double[dest->mKeys[i].mNumValuesAndWeights];
|
||||||
|
::memcpy(dest->mKeys[i].mValues, src->mKeys[i].mValues, dest->mKeys[i].mNumValuesAndWeights * sizeof(unsigned int));
|
||||||
|
::memcpy(dest->mKeys[i].mWeights, src->mKeys[i].mWeights, dest->mKeys[i].mNumValuesAndWeights * sizeof(double));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) {
|
void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) {
|
||||||
if ( nullptr == _dest || nullptr == src ) {
|
if ( nullptr == _dest || nullptr == src ) {
|
||||||
|
|
|
@ -1289,7 +1289,7 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
|
for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
|
||||||
{
|
{
|
||||||
FBX::Node layerExtra("Layer", int32_t(1));
|
FBX::Node layerExtra("Layer", int32_t(lr));
|
||||||
layerExtra.AddChild("Version", int32_t(100));
|
layerExtra.AddChild("Version", int32_t(100));
|
||||||
FBX::Node leExtra("LayerElement");
|
FBX::Node leExtra("LayerElement");
|
||||||
leExtra.AddChild("Type", "LayerElementUV");
|
leExtra.AddChild("Type", "LayerElementUV");
|
||||||
|
|
|
@ -538,13 +538,17 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
|
||||||
{
|
{
|
||||||
Validate(&pAnimation->mName);
|
Validate(&pAnimation->mName);
|
||||||
|
|
||||||
// validate all materials
|
// validate all animations
|
||||||
if (pAnimation->mNumChannels)
|
if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels)
|
||||||
{
|
{
|
||||||
if (!pAnimation->mChannels) {
|
if (!pAnimation->mChannels && pAnimation->mNumChannels) {
|
||||||
ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
|
ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
|
||||||
pAnimation->mNumChannels);
|
pAnimation->mNumChannels);
|
||||||
}
|
}
|
||||||
|
if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) {
|
||||||
|
ReportError("aiAnimation::mMorphMeshChannels is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
|
||||||
|
pAnimation->mNumMorphMeshChannels);
|
||||||
|
}
|
||||||
for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
|
for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
|
||||||
{
|
{
|
||||||
if (!pAnimation->mChannels[i])
|
if (!pAnimation->mChannels[i])
|
||||||
|
@ -554,6 +558,15 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
|
||||||
}
|
}
|
||||||
Validate(pAnimation, pAnimation->mChannels[i]);
|
Validate(pAnimation, pAnimation->mChannels[i]);
|
||||||
}
|
}
|
||||||
|
for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels;++i)
|
||||||
|
{
|
||||||
|
if (!pAnimation->mMorphMeshChannels[i])
|
||||||
|
{
|
||||||
|
ReportError("aiAnimation::mMorphMeshChannels[%i] is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
|
||||||
|
i, pAnimation->mNumMorphMeshChannels);
|
||||||
|
}
|
||||||
|
Validate(pAnimation, pAnimation->mMorphMeshChannels[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
|
ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
|
||||||
|
@ -903,6 +916,48 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
|
||||||
|
const aiMeshMorphAnim* pMeshMorphAnim)
|
||||||
|
{
|
||||||
|
Validate(&pMeshMorphAnim->mName);
|
||||||
|
|
||||||
|
if (!pMeshMorphAnim->mNumKeys) {
|
||||||
|
ReportError("Empty mesh morph animation channel");
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise check whether one of the keys exceeds the total duration of the animation
|
||||||
|
if (pMeshMorphAnim->mNumKeys)
|
||||||
|
{
|
||||||
|
if (!pMeshMorphAnim->mKeys)
|
||||||
|
{
|
||||||
|
ReportError("aiMeshMorphAnim::mKeys is NULL (aiMeshMorphAnim::mNumKeys is %i)",
|
||||||
|
pMeshMorphAnim->mNumKeys);
|
||||||
|
}
|
||||||
|
double dLast = -10e10;
|
||||||
|
for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys;++i)
|
||||||
|
{
|
||||||
|
// ScenePreprocessor will compute the duration if still the default value
|
||||||
|
// (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
|
||||||
|
// seems to be due the compilers register usage/width.
|
||||||
|
if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration+0.001)
|
||||||
|
{
|
||||||
|
ReportError("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is larger "
|
||||||
|
"than aiAnimation::mDuration (which is %.5f)",i,
|
||||||
|
(float)pMeshMorphAnim->mKeys[i].mTime,
|
||||||
|
(float)pAnimation->mDuration);
|
||||||
|
}
|
||||||
|
if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast)
|
||||||
|
{
|
||||||
|
ReportWarning("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is smaller "
|
||||||
|
"than aiMeshMorphAnim::mKeys[%i] (which is %.5f)",i,
|
||||||
|
(float)pMeshMorphAnim->mKeys[i].mTime,
|
||||||
|
i-1, (float)dLast);
|
||||||
|
}
|
||||||
|
dLast = pMeshMorphAnim->mKeys[i].mTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ValidateDSProcess::Validate( const aiNode* pNode)
|
void ValidateDSProcess::Validate( const aiNode* pNode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct aiBone;
|
||||||
struct aiMesh;
|
struct aiMesh;
|
||||||
struct aiAnimation;
|
struct aiAnimation;
|
||||||
struct aiNodeAnim;
|
struct aiNodeAnim;
|
||||||
|
struct aiMeshMorphAnim;
|
||||||
struct aiTexture;
|
struct aiTexture;
|
||||||
struct aiMaterial;
|
struct aiMaterial;
|
||||||
struct aiNode;
|
struct aiNode;
|
||||||
|
@ -150,6 +151,13 @@ protected:
|
||||||
void Validate( const aiAnimation* pAnimation,
|
void Validate( const aiAnimation* pAnimation,
|
||||||
const aiNodeAnim* pBoneAnim);
|
const aiNodeAnim* pBoneAnim);
|
||||||
|
|
||||||
|
/** Validates a mesh morph animation channel.
|
||||||
|
* @param pAnimation Input animation.
|
||||||
|
* @param pMeshMorphAnim Mesh morph animation channel.
|
||||||
|
* */
|
||||||
|
void Validate( const aiAnimation* pAnimation,
|
||||||
|
const aiMeshMorphAnim* pMeshMorphAnim);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Validates a node and all of its subnodes
|
/** Validates a node and all of its subnodes
|
||||||
* @param Node Input node*/
|
* @param Node Input node*/
|
||||||
|
|
|
@ -1005,13 +1005,15 @@ struct AnimationSamplers {
|
||||||
AnimationSamplers()
|
AnimationSamplers()
|
||||||
: translation(nullptr)
|
: translation(nullptr)
|
||||||
, rotation(nullptr)
|
, rotation(nullptr)
|
||||||
, scale(nullptr) {
|
, scale(nullptr)
|
||||||
|
, weight(nullptr) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::Sampler* translation;
|
Animation::Sampler* translation;
|
||||||
Animation::Sampler* rotation;
|
Animation::Sampler* rotation;
|
||||||
Animation::Sampler* scale;
|
Animation::Sampler* scale;
|
||||||
|
Animation::Sampler* weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
|
aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
|
||||||
|
@ -1036,7 +1038,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
|
||||||
delete[] values;
|
delete[] values;
|
||||||
} else if (node.translation.isPresent) {
|
} else if (node.translation.isPresent) {
|
||||||
anim->mNumPositionKeys = 1;
|
anim->mNumPositionKeys = 1;
|
||||||
anim->mPositionKeys = new aiVectorKey();
|
anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
|
||||||
anim->mPositionKeys->mTime = 0.f;
|
anim->mPositionKeys->mTime = 0.f;
|
||||||
anim->mPositionKeys->mValue.x = node.translation.value[0];
|
anim->mPositionKeys->mValue.x = node.translation.value[0];
|
||||||
anim->mPositionKeys->mValue.y = node.translation.value[1];
|
anim->mPositionKeys->mValue.y = node.translation.value[1];
|
||||||
|
@ -1094,6 +1096,43 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
|
||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
|
||||||
|
{
|
||||||
|
aiMeshMorphAnim* anim = new aiMeshMorphAnim();
|
||||||
|
anim->mName = GetNodeName(node);
|
||||||
|
|
||||||
|
static const float kMillisecondsFromSeconds = 1000.f;
|
||||||
|
|
||||||
|
if (nullptr != samplers.weight) {
|
||||||
|
float* times = nullptr;
|
||||||
|
samplers.weight->input->ExtractData(times);
|
||||||
|
float* values = nullptr;
|
||||||
|
samplers.weight->output->ExtractData(values);
|
||||||
|
anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
|
||||||
|
|
||||||
|
const unsigned int numMorphs = samplers.weight->output->count / anim->mNumKeys;
|
||||||
|
|
||||||
|
anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
|
||||||
|
unsigned int k = 0u;
|
||||||
|
for (unsigned int i = 0u; i < anim->mNumKeys; ++i) {
|
||||||
|
anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
|
||||||
|
anim->mKeys[i].mNumValuesAndWeights = numMorphs;
|
||||||
|
anim->mKeys[i].mValues = new unsigned int[numMorphs];
|
||||||
|
anim->mKeys[i].mWeights = new double[numMorphs];
|
||||||
|
|
||||||
|
for (unsigned int j = 0u; j < numMorphs; ++j, ++k) {
|
||||||
|
anim->mKeys[i].mValues[j] = j;
|
||||||
|
anim->mKeys[i].mWeights[j] = ( 0.f > values[k] ) ? 0.f : values[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] times;
|
||||||
|
delete[] values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anim;
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& anim)
|
std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& anim)
|
||||||
{
|
{
|
||||||
std::unordered_map<unsigned int, AnimationSamplers> samplers;
|
std::unordered_map<unsigned int, AnimationSamplers> samplers;
|
||||||
|
@ -1112,6 +1151,8 @@ std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& an
|
||||||
sampler.rotation = &anim.samplers[channel.sampler];
|
sampler.rotation = &anim.samplers[channel.sampler];
|
||||||
} else if (channel.target.path == AnimationPath_SCALE) {
|
} else if (channel.target.path == AnimationPath_SCALE) {
|
||||||
sampler.scale = &anim.samplers[channel.sampler];
|
sampler.scale = &anim.samplers[channel.sampler];
|
||||||
|
} else if (channel.target.path == AnimationPath_WEIGHTS) {
|
||||||
|
sampler.weight = &anim.samplers[channel.sampler];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,13 +1179,39 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r)
|
||||||
|
|
||||||
std::unordered_map<unsigned int, AnimationSamplers> samplers = GatherSamplers(anim);
|
std::unordered_map<unsigned int, AnimationSamplers> samplers = GatherSamplers(anim);
|
||||||
|
|
||||||
ai_anim->mNumChannels = static_cast<uint32_t>(samplers.size());
|
uint32_t numChannels = 0u;
|
||||||
|
uint32_t numMorphMeshChannels = 0u;
|
||||||
|
|
||||||
|
for (auto& iter : samplers) {
|
||||||
|
if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
|
||||||
|
++numChannels;
|
||||||
|
}
|
||||||
|
if (nullptr != iter.second.weight) {
|
||||||
|
++numMorphMeshChannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_anim->mNumChannels = numChannels;
|
||||||
if (ai_anim->mNumChannels > 0) {
|
if (ai_anim->mNumChannels > 0) {
|
||||||
ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels];
|
ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels];
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (auto& iter : samplers) {
|
for (auto& iter : samplers) {
|
||||||
ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second);
|
if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
|
||||||
++j;
|
ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_anim->mNumMorphMeshChannels = numMorphMeshChannels;
|
||||||
|
if (ai_anim->mNumMorphMeshChannels > 0) {
|
||||||
|
ai_anim->mMorphMeshChannels = new aiMeshMorphAnim*[ai_anim->mNumMorphMeshChannels];
|
||||||
|
int j = 0;
|
||||||
|
for (auto& iter : samplers) {
|
||||||
|
if (nullptr != iter.second.weight) {
|
||||||
|
ai_anim->mMorphMeshChannels[j] = CreateMeshMorphAnim(r, r.nodes[iter.first], iter.second);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1175,8 +1242,21 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r)
|
||||||
maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys);
|
maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < ai_anim->mNumMorphMeshChannels; ++j) {
|
||||||
|
const auto* const chan = ai_anim->mMorphMeshChannels[j];
|
||||||
|
|
||||||
|
if (0u != chan->mNumKeys) {
|
||||||
|
const auto& lastKey = chan->mKeys[chan->mNumKeys - 1u];
|
||||||
|
if (lastKey.mTime > maxDuration) {
|
||||||
|
maxDuration = lastKey.mTime;
|
||||||
|
}
|
||||||
|
maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumKeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ai_anim->mDuration = maxDuration;
|
ai_anim->mDuration = maxDuration;
|
||||||
ai_anim->mTicksPerSecond = (maxNumberOfKeys > 0 && maxDuration > 0) ? (maxNumberOfKeys / (maxDuration/1000)) : 30;
|
ai_anim->mTicksPerSecond = 1000.0;
|
||||||
|
|
||||||
mScene->mAnimations[i] = ai_anim;
|
mScene->mAnimations[i] = ai_anim;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct aiMesh;
|
||||||
struct aiAnimMesh;
|
struct aiAnimMesh;
|
||||||
struct aiAnimation;
|
struct aiAnimation;
|
||||||
struct aiNodeAnim;
|
struct aiNodeAnim;
|
||||||
|
struct aiMeshMorphAnim;
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
@ -372,6 +373,7 @@ public:
|
||||||
static void Copy (aiBone** dest, const aiBone* src);
|
static void Copy (aiBone** dest, const aiBone* src);
|
||||||
static void Copy (aiLight** dest, const aiLight* src);
|
static void Copy (aiLight** dest, const aiLight* src);
|
||||||
static void Copy (aiNodeAnim** dest, const aiNodeAnim* src);
|
static void Copy (aiNodeAnim** dest, const aiNodeAnim* src);
|
||||||
|
static void Copy (aiMeshMorphAnim** dest, const aiMeshMorphAnim* src);
|
||||||
static void Copy (aiMetadata** dest, const aiMetadata* src);
|
static void Copy (aiMetadata** dest, const aiMetadata* src);
|
||||||
|
|
||||||
// recursive, of course
|
// recursive, of course
|
||||||
|
|
Loading…
Reference in New Issue