├── .gitignore
├── FBX Importer
├── DzFbxImporter.def
├── version.h
├── DzFbxImporter.rc
├── pluginmain.cpp
├── CMakeLists.txt
├── DzFbxImporter.h
└── DzFbxImporter.cpp
├── cmake
└── DzMocFiles.cmake
├── README.md
├── CMakeLists.txt
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
34 | # FBX SDK directory
35 | FBXSDK
36 |
37 | # build directory
38 | /build
--------------------------------------------------------------------------------
/FBX Importer/DzFbxImporter.def:
--------------------------------------------------------------------------------
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 | ; Copyright (C) 2002-2022 DAZ 3D, Inc. All Rights Reserved.
3 | ;
4 | ; Licensed under the Apache License, Version 2.0 (the "License");
5 | ; you may not use this file except in compliance with the License.
6 | ; You may obtain a copy of the License at
7 | ;
8 | ; http://www.apache.org/licenses/LICENSE-2.0
9 | ;
10 | ; Unless required by applicable law or agreed to in writing, software
11 | ; distributed under the License is distributed on an "AS IS" BASIS,
12 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | ; See the License for the specific language governing permissions and
14 | ; limitations under the License.
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16 |
17 | LIBRARY dzfbximporter
18 | EXPORTS
19 | getSDKVersion @1
20 | getPluginDefinition @2
21 | SECTIONS
22 | .data READ WRITE
23 |
--------------------------------------------------------------------------------
/FBX Importer/version.h:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | Copyright (C) 2012-2022 DAZ 3D, Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | **********************************************************************/
16 |
17 | #pragma once
18 |
19 | #include "dzversion.h"
20 |
21 | // Version number for the FBX Importer plug-in
22 | #define PLUGIN_MAJOR 1
23 | #define PLUGIN_MINOR 4
24 | #define PLUGIN_REV 1
25 | #define PLUGIN_BUILD 0
26 |
27 | #define PLUGIN_VERSION DZ_MAKE_VERSION( PLUGIN_MAJOR, PLUGIN_MINOR, PLUGIN_REV, PLUGIN_BUILD )
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FBX Importer/DzFbxImporter.rc:
--------------------------------------------------------------------------------
1 | /////////////////////////////////////////////////////////////////////////////
2 | // Copyright (C) 2002-2022 DAZ 3D, Inc. All Rights Reserved.
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | /////////////////////////////////////////////////////////////////////////////
16 |
17 | #include "version.h"
18 | #include "windows.h"
19 |
20 | #ifdef _WIN32
21 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
22 | #pragma code_page(1252)
23 | #endif //_WIN32
24 |
25 | /////////////////////////////////////////////////////////////////////////////
26 | //
27 | // Version
28 | //
29 | /////////////////////////////////////////////////////////////////////////////
30 |
31 | VS_VERSION_INFO VERSIONINFO
32 | FILEVERSION PLUGIN_MAJOR, PLUGIN_MINOR, PLUGIN_REV, PLUGIN_BUILD
33 | PRODUCTVERSION DZ_VERSION_MAJOR, DZ_VERSION_MINOR, DZ_VERSION_REV, DZ_VERSION_BUILD
34 | FILEFLAGSMASK 0x17L
35 | #ifdef _DEBUG
36 | FILEFLAGS 0x1L
37 | #else
38 | FILEFLAGS 0x0L
39 | #endif
40 | FILEOS 0x4L
41 | FILETYPE 0x2L
42 | FILESUBTYPE 0x0L
43 | BEGIN
44 | BLOCK "StringFileInfo"
45 | BEGIN
46 | BLOCK "040904b0"
47 | BEGIN
48 | VALUE "CompanyName", "Daz 3D, Inc."
49 | VALUE "FileDescription", "Daz FBX Importer Plug-in"
50 | VALUE "InternalName", "DzFBXImporter"
51 | VALUE "LegalCopyright", "Copyright (C) 2002-2022 Daz 3D, Inc."
52 | VALUE "ProductName", "Daz Studio"
53 |
54 | END
55 | END
56 | BLOCK "VarFileInfo"
57 | BEGIN
58 | VALUE "Translation", 0x409, 1200
59 | END
60 | END
61 |
62 |
63 |
--------------------------------------------------------------------------------
/FBX Importer/pluginmain.cpp:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | Copyright (C) 2012-2022 DAZ 3D, Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | **********************************************************************/
16 |
17 | /*****************************
18 | Include files
19 | *****************************/
20 | #include "dzplugin.h"
21 | #include "dzapp.h"
22 |
23 | #include "version.h"
24 | #include "dzfbximporter.h"
25 |
26 | /*****************************
27 | Plugin Definition
28 | *****************************/
29 |
30 | /**
31 | This macro creates the plugin definition, and the functions that are needed
32 | for Daz Studio to load the plugin.
33 | **/
34 | DZ_PLUGIN_DEFINITION( "FBX Importer" );
35 |
36 | /**
37 | This macro sets the author string for the plugin
38 | **/
39 | DZ_PLUGIN_AUTHOR( "Daz 3D, Inc" );
40 |
41 | /**
42 | This macro sets the version number for the plugin
43 | **/
44 | DZ_PLUGIN_VERSION( PLUGIN_MAJOR, PLUGIN_MINOR, PLUGIN_REV, PLUGIN_BUILD );
45 |
46 | /**
47 | This macro sets the description string for the plugin. This is a good place
48 | to provide specific information about the plugin, including an HTML link to
49 | any external documentation. Links are shown in the system default browser.
50 | **/
51 | DZ_PLUGIN_DESCRIPTION(
52 | "Imports the Autodesk FBX format. "
53 | "
Source code is available on Github.
"
54 | "This software contains Autodesk® FBX® code developed by Autodesk, Inc. "
55 | "Copyright 2013 Autodesk, Inc. All rights, reserved. Such code is provided \"as is\" "
56 | "and Autodesk, Inc. disclaims any and all warranties, whether express or implied, including "
57 | "without limitation the implied warranties of merchantability, fitness for a particular "
58 | "purpose or non-infringement of third party rights. In no event shall Autodesk, Inc. be liable "
59 | "for any direct, indirect, incidental, special, exemplary, or consequential damages (including, "
60 | "but not limited to, procurement of substitute goods or services; loss of use, data, or profits; "
61 | "or business interruption) however caused and on any theory of liability, whether in contract, "
62 | "strict liability, or tort (including negligence or otherwise) arising in any way out of such code.
"
63 | );
64 |
65 | /**
66 | This macro adds this plugin's classes to the objects exported by the plugin, and specifies the
67 | GUID (Globally Unique Identifier) that makes this class unique from any other class
68 | that is available from Daz Studio or one of it's plug-ins. DO NOT USE the GUID below
69 | in your plug-in. Make sure that you generate a new GUID for every class that you export
70 | from your plug-in. To avoid potential conflicts, DO NOT USE the same class name in your own
71 | plugin.
72 | **/
73 | DZ_PLUGIN_CLASS_GUID( DzFbxImporter, 4E0BDC3A-2B5C-4E21-A250-1327D5D6A92B );
74 |
--------------------------------------------------------------------------------
/cmake/DzMocFiles.cmake:
--------------------------------------------------------------------------------
1 | #######################################################################
2 | # Copyright (C) 2016-2022 DAZ 3D, Inc. All Rights Reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #######################################################################
16 |
17 | macro( dz_moc_headers is_qt5_moc addtional_options outputList )
18 | foreach(mocHeader ${ARGN})
19 | get_filename_component(bareMocHeaderName ${mocHeader} NAME)
20 | if( ${is_qt5_moc} )
21 | qt5_wrap_cpp( ${outputList} ${mocHeader}
22 | OPTIONS
23 | ${${addtional_options}}
24 | -f${bareMocHeaderName} )
25 | else()
26 | qt4_wrap_cpp( ${outputList} ${mocHeader}
27 | OPTIONS
28 | ${${addtional_options}}
29 | -f${bareMocHeaderName} )
30 | endif()
31 | list(APPEND ${outputList} ${sourceFile} ${mocHeader} )
32 | endforeach()
33 | endmacro( dz_moc_headers )
34 |
35 | macro( dz_uic_headers is_qt5 out_path addtional_options outputList )
36 | #Adapted from qt4_wrap_ui found in Qt4Macros.cmake
37 | #BSD License, see cmake modules
38 | foreach(uicFile ${ARGN})
39 | get_filename_component(outfile ${uicFile} NAME_WE)
40 | get_filename_component(infile ${uicFile} ABSOLUTE)
41 | set(outfile ${out_path}/ui_${outfile}.h)
42 | if( ${is_qt5} )
43 | set(UIC_COMMAND Qt5::uic )
44 | else()
45 | set(UIC_COMMAND Qt4::uic )
46 | endif()
47 | add_custom_command(OUTPUT ${outfile}
48 | COMMAND ${UIC_COMMAND}
49 | ARGS ${${addtional_options}} -o ${outfile} ${infile}
50 | MAIN_DEPENDENCY ${infile} VERBATIM)
51 | list(APPEND ${outputList} ${outfile} ${uicFile})
52 | endforeach()
53 | endmacro( dz_uic_headers )
54 |
55 |
56 | macro( dz_rcc is_qt5 addtional_options outputList )
57 | foreach(rccFile ${ARGN})
58 | get_filename_component(bareFilename ${rccFile} NAME_WE)
59 | if( ${is_qt5} )
60 | qt5_add_resources( ${outputList} ${rccFile}
61 | OPTIONS
62 | ${${addtional_options}} )
63 | else()
64 | qt4_add_resources( ${outputList} ${rccFile}
65 | OPTIONS
66 | ${${addtional_options}} )
67 | endif()
68 | list(APPEND ${outputList} ${sourceFile} ${rccFile} )
69 | endforeach()
70 | endmacro( dz_rcc )
71 |
72 | function(dz_source_subgroup name)
73 | string(REPLACE "/" "\\" folder_name ${name})
74 | source_group("Header Files\\${folder_name}" REGULAR_EXPRESSION ".*/${name}/.*\\.[hH]")
75 | source_group("Source Files\\${folder_name}" REGULAR_EXPRESSION ".*/${name}/.*\\.c(|pp)")
76 | endfunction()
77 |
78 | function(dz_optimize_target target)
79 | if (MSVC)
80 | get_property(dz_current_rel_flags TARGET ${target} PROPERTY LINK_FLAGS_RELWITHDEBINFO)
81 | set_target_properties(
82 | ${target}
83 | PROPERTIES
84 | LINK_FLAGS_RELWITHDEBINFO "${dz_current_rel_flags} /OPT:REF /OPT:ICF /INCREMENTAL:NO"
85 | )
86 | endif(MSVC)
87 | endfunction()
88 |
89 | function(dz_uac_linker_target target)
90 | if (MSVC)
91 | get_property(dz_linker_flags TARGET ${target} PROPERTY LINK_FLAGS)
92 | set_target_properties(
93 | ${target}
94 | PROPERTIES
95 | LINK_FLAGS "${dz_linker_flags} /MANIFESTUAC:\"level=asInvoker uiAccess=false\""
96 | )
97 | endif(MSVC)
98 | endfunction()
99 |
100 | function(dz_grow_stack_linker_target target)
101 | get_property(dz_linker_flags TARGET ${target} PROPERTY LINK_FLAGS)
102 | if (MSVC)
103 | set_target_properties(
104 | ${target}
105 | PROPERTIES
106 | LINK_FLAGS "${dz_linker_flags} /STACK:0x1000000"
107 | )
108 | elseif(APPLE)
109 | set_target_properties(
110 | ${target}
111 | PROPERTIES
112 | LINK_FLAGS "${dz_linker_flags} -Wl,-stack_size -Wl,0x1000000"
113 | )
114 | endif()
115 | endfunction()
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Daz Studio FBX Importer
2 | * Owner: [Daz 3D][OwnerURL] — [@Daz3d][TwitterURL]
3 | * License: [Apache License, Version 2.0][LicenseURL] - see ``LICENSE`` and ``NOTICE`` for more information.
4 | * Official Project: [github.com/daz3d/StudioFbxImporter][RepositoryURL]
5 |
6 | ## Prerequisites
7 | * **[Daz Studio][DazStudioURL]** application
8 | * 4.16.1.17 Public Build or newer
9 | * _Includes Qt 4.8.7 binaries_ (platform specific)
10 | * 4.20.0.17 General Release or newer
11 | * _Includes Qt 4.8.7 binaries_ (platform specific)
12 | * **Daz Studio SDK**
13 | * [Version 4.5+][DazStudioSDKURL] or newer
14 | * _Includes Qt 4.8.1 binaries_
15 | * _Includes Qt 4.8 headers_
16 | * **[FBX SDK][FBXSDKURL]**
17 | * Version [2016][FBXSDKArchiveURL] or newer
18 | * **[CMake][CMakeURL]**
19 | * Version 3.4.0 or newer
20 | * Operating System
21 | * Windows 7 or newer
22 |
23 | ## Build instructions
24 | * Download and install the **Daz Studio** application.
25 | * Note the installation path, it _may_ be needed in a later step.
26 | * Download and install the **Daz Studio SDK**.
27 | * Note the installation path, it _will_ be needed in a later step.
28 | * Download and install the **FBX SDK**.
29 | * Note the installation path _before the version number_, it _will_ be needed in a later step.
30 | * **CMake** is required to generate project files.
31 | * CMake can be used via the GUI tool, or the command line interface.
32 | * Using cmake-gui:
33 | * Launch the CMake GUI tool.
34 | * Click _Browse Source..._ to specify the path where this repository has been cloned locally.
35 | * Click _Browse Build..._ to specify the path where build files should be created - e.g., ``.../build/x64``.
36 | * Click _Configure_ to initialize the setup for this project.
37 | * Choose a generator from the list provided.
38 | * Optionally choose a platform (e.g., ``x64``) for the generator.
39 | * In the optional toolset field, enter ``v100`` to indicate use of the Visual Studio 2010 toolset.
40 | * _NOTE: Other compilers may face memory allocation/de-allocation issues._
41 | * Click _Finish_ - CMake will begin processing and ultimately throw an error indicating a need to provide a valid path to the Daz Studio SDK.
42 | * Set the ``DAZ_SDK_DIR`` variable to the **Daz Studio SDK** installation path (as noted above).
43 | * Set the ``FBX_SDK_INSTALL_DIR`` variable to the **FBX SDK** installation path (as noted above).
44 | * Set the ``FBX_SDK_VERSION`` and ``FBX_SDK_VSTUDIO_VERSION`` variables to the version of the FBX SDK and corresponding Visual Studio version respectively
45 | * These variables are used to generate paths to the library files of the specified FBX SDK.
46 | * These variables allow for easy switching between multiple installed FBX SDK versions.
47 | * Click _Configure_ - the remaining ``FBX_SDK_`` prefixed variables will be automatically populated based on the variables described above.
48 | * The values of these ``FBX_SDK_`` prefixed variables may need to be adjusted to reflect machine specific configurations if ``FBX_CUSTOM_LAYOUT`` is enabled.
49 | * Click _Generate_ once the configuration has successfully completed to generate the project.
50 | * Using cmake command line:
51 | * ``cmake`` can be run at the root level of the repository with specific options, as shown in the following command:
52 | * ``cmake -B -G "Visual Studio 16" -T v100 -D DAZ_SDK_DIR= -D FBX_SDK_INSTALL_DIR= -D FBX_SDK_VERSION= -D FBX_SDK_VSTUDIO_VERSION=``
53 | * ``-B`` will set the path to the generated files.
54 | * ``-G`` specifies the Visual Studio generator version.
55 | * ``-T`` will specify the compiler toolset.
56 | * ``-D`` is used for setting the cmake variables for the build.
57 | * Configuration and generation of project files are both performed using the above command.
58 | * Launch the project in Visual Studio and build the solution.
59 | * If the build is successful, copy ``dzfbximporter.dll`` from the project output directory. Paste the library to the ``plugins`` folder under Daz Studio install location.
60 | * This step will replace the existing FBX importer plugin file that is bundled with the application.
61 | * Installing the application again will replace this file to the version distributed with it.
62 | * Uninstalling the application will remove this file.
63 | * Alternatively, the previous step can be automated by setting the ``DAZ_STUDIO_EXE_DIR`` variable while generating the project. In this case, while building the solution, make sure to quit any active instances of Daz Studio.
64 | * _NOTE: Visual Studio may need to be run with admin privileges if the ``DAZ_STUDIO_EXE_DIR`` variable is pointing to a protected path like ``Program Files``._
65 | * This step will replace the existing FBX importer plugin file that is bundled with the application.
66 | * Installing the application again will replace this file to the version distributed with it.
67 | * Uninstalling the application will remove this file.
68 | * Daz Studio is now installed with the built version of the plugin.
69 |
70 | [OwnerURL]: https://www.daz3d.com
71 | [TwitterURL]: https://twitter.com/Daz3d
72 | [LicenseURL]: http://www.apache.org/licenses/LICENSE-2.0
73 | [RepositoryURL]: https://github.com/daz3d/StudioFbxImporter
74 | [DazStudioURL]: https://www.daz3d.com/get_studio
75 | [DazStudioSDKURL]: https://www.daz3d.com/daz-studio-4-5-sdk
76 | [FBXSDKURL]: https://www.autodesk.com/products/fbx/overview
77 | [FBXSDKArchiveURL]: https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-archives
78 | [CMakeURL]: https://cmake.org
79 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #######################################################################
2 | # Copyright (C) 2002-2022 DAZ 3D, Inc. All Rights Reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #######################################################################
16 |
17 | cmake_minimum_required( VERSION 3.4.0 )
18 |
19 | project( "DAZ Studio Fbx Importer" )
20 |
21 | set_property( GLOBAL PROPERTY USE_FOLDERS ON )
22 |
23 | set( DAZ_STUDIO_EXE_DIR "" CACHE PATH "Path to DAZ Studio, needs to be installed to a writeable location." )
24 |
25 | set( DAZ_SDK_DIR "" CACHE PATH "Path to root of the DAZ Studio SDK." )
26 | if( NOT EXISTS ${DAZ_SDK_DIR} )
27 | message( SEND_ERROR "Provide a valid path to the DAZ Studio SDK (DAZ_SDK_DIR)." )
28 | return()
29 | endif()
30 |
31 | list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" )
32 | include( DzMocFiles )
33 |
34 | # Define platform specific variables
35 | if( WIN32 )
36 | set( DZ_LIB_SUFFIX ".lib" )
37 | set( DZ_BIN_SUFFIX ".dll" )
38 | set( DZ_LIB_PREFIX "" )
39 | set( UTIL_EXT ".exe" )
40 | if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
41 | set( DZ_PLATFORM x86 )
42 | set( DZ_MIXED_PLATFORM Win32 )
43 | set( DZ_OS_PLATFORM Win32 )
44 | elseif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
45 | set( DZ_PLATFORM x64 )
46 | set( DZ_MIXED_PLATFORM x64 )
47 | set( DZ_OS_PLATFORM Win64 )
48 | else()
49 | message( FATAL_ERROR "Unknown architecture" )
50 | endif()
51 | elseif( APPLE )
52 | set( DZ_LIB_SUFFIX ".dylib" )
53 | set( DZ_BIN_SUFFIX ".dylib" )
54 | set( DZ_LIB_PREFIX "lib" )
55 | set( UTIL_EXT "" )
56 | if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
57 | set( DZ_PLATFORM x86 )
58 | set( DZ_MIXED_PLATFORM Mac32 )
59 | set( DZ_OS_PLATFORM Mac32 )
60 | elseif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
61 | set( DZ_PLATFORM x64 )
62 | set( DZ_MIXED_PLATFORM Mac64 )
63 | set( DZ_OS_PLATFORM Mac64 )
64 | else()
65 | message( FATAL_ERROR "Unknown architecture" )
66 | endif()
67 | set( CMAKE_MACOSX_RPATH TRUE )
68 | set( CMAKE_BUILD_WITH_INSTALL_RPATH TRUE )
69 | else()
70 | message( FATAL_ERROR "Unknown architecture" )
71 | endif( WIN32 )
72 |
73 | set( DAZ_SDK_INCLUDE_DIR "${DAZ_SDK_DIR}/include" CACHE FILEPATH "Path to daz sdk includes." )
74 | set( DAZ_SDK_CORE_RELATIVE_PATH "lib/${DZ_MIXED_PLATFORM}/${DZ_LIB_PREFIX}dzcore${DZ_LIB_SUFFIX}" )
75 | set( DAZ_SDK_LIB "${DAZ_SDK_DIR}/${DAZ_SDK_CORE_RELATIVE_PATH}" CACHE FILEPATH "Path to dzcore." )
76 |
77 | add_library( dzcore SHARED IMPORTED )
78 | if( WIN32 )
79 | set_property( TARGET dzcore APPEND PROPERTY IMPORTED_IMPLIB ${DAZ_SDK_LIB} )
80 | else()
81 | set_property( TARGET dzcore APPEND PROPERTY IMPORTED_LOCATION ${DAZ_SDK_LIB} )
82 | endif( WIN32 )
83 | set_property( TARGET dzcore APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${DAZ_SDK_INCLUDE_DIR}" )
84 |
85 | # Setup Qt from the DAZ Studio SDK
86 | if( WIN32 )
87 | set( DAZ_SDK_QTCORE_LIBRARY "${DAZ_SDK_DIR}/lib/${DZ_MIXED_PLATFORM}/QtCore4.lib" )
88 | elseif( APPLE )
89 | set( DAZ_SDK_QTCORE_LIBRARY "${DAZ_SDK_DIR}/lib/${DZ_MIXED_PLATFORM}/QtCore.framework" )
90 | endif()
91 |
92 | set( QT_QTCORE_LIBRARY_RELEASE ${DAZ_SDK_QTCORE_LIBRARY} )
93 | set( QT_QMAKE_EXECUTABLE "${DAZ_SDK_DIR}/bin/${DZ_MIXED_PLATFORM}/qmake${UTIL_EXT}" )
94 | set( QT_BINARY_DIR "${DAZ_SDK_DIR}/bin/${DZ_MIXED_PLATFORM}" )
95 | set( QT_HEADERS_DIR "${DAZ_SDK_DIR}/include" )
96 | set( QT_QTCORE_INCLUDE_DIR "${DAZ_SDK_DIR}/include/QtCore" )
97 |
98 | # The Qt find module needs this folder, but our build does not, so just fake it
99 | file( MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/DUMMY_MKSPECS/default" )
100 | set( QT_MKSPECS_DIR "${CMAKE_CURRENT_BINARY_DIR}/DUMMY_MKSPECS" )
101 |
102 | find_package( Qt4 4.8.1 REQUIRED QtCore QtGui QtScript QtOpenGL QtNetwork QtSql QtXml )
103 |
104 | set( DZSDK_QT_CORE_TARGET Qt4::QtCore )
105 | set( DZSDK_QT_GUI_TARGET Qt4::QtGui )
106 | set( DZSDK_QT_SCRIPT_TARGET Qt4::QtScript )
107 | set( DZSDK_QT_OPENGL_TARGET Qt4::QtOpenGL )
108 | set( DZSDK_QT_NETWORK_TARGET Qt4::QtNetwork )
109 | set( DZSDK_QT_SQL_TARGET Qt4::QtSql )
110 | set( DZSDK_QT_XML_TARGET Qt4::QtXml )
111 |
112 | set( PLUGIN_MOC_OPTIONS
113 | "-I${DAZ_SDK_INCLUDE_DIR}"
114 | )
115 |
116 | function( setup_standard_plugin_source_groups )
117 | source_group( "Resource Files" REGULAR_EXPRESSION ".*\\.(def|rc|ico|icns|rgs)" )
118 | source_group( "Source Files\\generated\\moc" REGULAR_EXPRESSION "/moc_.*\\.c(xx|pp)$" )
119 | source_group( "Header Files\\generated\\ui files" REGULAR_EXPRESSION "/ui_.*\\.h$" )
120 | source_group( "Source Files\\ui files" REGULAR_EXPRESSION ".*\\.ui$" )
121 | endfunction()
122 |
123 | # If DAZ_STUDIO_EXE_DIR is not defined, the compiled result will be placed in the default CMake binary folder
124 | # If DAZ_STUDIO_EXE_DIR is defined, the compiled result placed in the Daz Studio ./plugins directory
125 | if( DAZ_STUDIO_EXE_DIR )
126 | foreach( curConfig ${CMAKE_CONFIGURATION_TYPES} )
127 | string( TOUPPER ${curConfig} curConfig )
128 | set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${curConfig} ${DAZ_STUDIO_EXE_DIR}/plugins )
129 | set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${curConfig} ${DAZ_STUDIO_EXE_DIR}/plugins )
130 | endforeach()
131 | endif()
132 |
133 | add_subdirectory( "FBX Importer" )
134 |
--------------------------------------------------------------------------------
/FBX Importer/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #######################################################################
2 | # Copyright (C) 2016-2022 DAZ 3D, Inc. All Rights Reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #######################################################################
16 |
17 | set( CMAKE_AUTOMOC ON )
18 | set( CMAKE_INCLUDE_CURRENT_DIR ON )
19 |
20 | set( DZ_PLUGIN_TGT_NAME dzfbximporter )
21 | set( DZ_PLUGIN_PROJECT_NAME "FBX Importer" )
22 |
23 | if( WIN32 )
24 | set( OS_SOURCES
25 | DzFbxImporter.rc
26 | DzFbxImporter.def
27 | )
28 | elseif( APPLE )
29 | set( OS_SOURCES "" )
30 | endif()
31 |
32 | set( PLUGIN_MOC_SOURCES "" )
33 |
34 | dz_moc_headers( PLUGIN_MOC_OPTIONS PLUGIN_MOC_SOURCES
35 | dzfbximporter.h
36 | )
37 |
38 | option( FBX_CUSTOM_LAYOUT "If the FBX SDK directory has a custom layout." OFF )
39 |
40 | set( FBX_SDK_INSTALL_DIR "" CACHE PATH "Install directory of the FBX SDK." )
41 | set( FBX_SDK_VERSION "" CACHE STRING "FBX SDK version, used for locating the path to the FBX SDK libraries." )
42 | set( FBX_SDK_VSTUDIO_VERSION "" CACHE STRING "FBX SDK VS compiler version, used for locating the path to the FBX SDK libraries." )
43 |
44 | set( FBX_SDK_ROOT_DIR "${FBX_SDK_INSTALL_DIR}/${FBX_SDK_VERSION}" CACHE PATH "Root directory of the FBX SDK." FORCE)
45 | set( FBX_SDK_LIB_ROOT_DIR "${FBX_SDK_ROOT_DIR}/lib/${FBX_SDK_VSTUDIO_VERSION}" CACHE PATH "Root directory of the FBX SDK." FORCE)
46 |
47 | if( NOT FBX_CUSTOM_LAYOUT )
48 | set( FBX_SDK_DIR TRUE )
49 | if( NOT EXISTS ${FBX_SDK_INSTALL_DIR} )
50 | message( SEND_ERROR "Provide a valid path to the FBX SDK location (FBX_SDK_INSTALL_DIR)." )
51 | set( FBX_SDK_DIR FALSE )
52 | endif()
53 | if( NOT EXISTS ${FBX_SDK_ROOT_DIR} OR NOT FBX_SDK_DIR )
54 | message( SEND_ERROR "Provide a valid path to the FBX SDK location with correct SDK version (FBX_SDK_VERSION)." )
55 | set( FBX_SDK_DIR FALSE )
56 | endif()
57 | if( NOT EXISTS ${FBX_SDK_LIB_ROOT_DIR} )
58 | message( SEND_ERROR "Provide a valid path to the FBX SDK library directory with correct Visual Studio version (FBX_SDK_VSTUDIO_VERSION)." )
59 | set( FBX_SDK_DIR FALSE )
60 | endif()
61 | if( NOT FBX_SDK_DIR )
62 | return()
63 | endif()
64 | endif()
65 |
66 | set( FBX_SDK_INCLUDE "${FBX_SDK_ROOT_DIR}/include" CACHE PATH "Include directory of the FBX SDK." )
67 | if( WIN32 )
68 | set( FBX_SDK_LIB "${FBX_SDK_LIB_ROOT_DIR}/${DZ_PLATFORM}/release/libfbxsdk.lib" CACHE FILEPATH "" )
69 | set( FBX_SDK_SHARED "${FBX_SDK_LIB_ROOT_DIR}/${DZ_PLATFORM}/release/libfbxsdk.dll" CACHE FILEPATH "" )
70 | set( FBX_SDK_DEBUG_LIB "${FBX_SDK_LIB_ROOT_DIR}/${DZ_PLATFORM}/debug/libfbxsdk.lib" CACHE FILEPATH "" )
71 | set( FBX_SDK_DEBUG_SHARED "${FBX_SDK_LIB_ROOT_DIR}/${DZ_PLATFORM}/debug/libfbxsdk.dll" CACHE FILEPATH "" )
72 | else()
73 | set( FBX_SDK_LIB "${FBX_SDK_ROOT_DIR}/libmac/gcc4/ub/debug/shared/libfbxsdk.dylib" CACHE FILEPATH "" )
74 | set( FBX_SDK_SHARED "${FBX_SDK_LIB}" CACHE FILEPATH "" )
75 | set( FBX_SDK_DEBUG_LIB "${FBX_SDK_ROOT_DIR}/libmac/gcc4/ub/release/shared/libfbxsdk.dylib" CACHE FILEPATH "" )
76 | set( FBX_SDK_DEBUG_SHARED "${FBX_SDK_DEBUG_LIB}" CACHE FILEPATH "" )
77 | endif( WIN32 )
78 |
79 | set( FBX_LIB_EXISTS TRUE )
80 | if( NOT ( EXISTS ${FBX_SDK_INCLUDE} ) )
81 | message( SEND_ERROR "Invalid path to the FBX SDK include directory (FBX_SDK_INCLUDE)." )
82 | set( FBX_LIB_EXISTS FALSE )
83 | endif()
84 | if( NOT ( EXISTS ${FBX_SDK_LIB} ) )
85 | message( SEND_ERROR "Unable to find the file ${FBX_SDK_LIB} (FBX_SDK_LIB)." )
86 | set( FBX_LIB_EXISTS FALSE )
87 | endif()
88 | if( NOT ( EXISTS ${FBX_SDK_SHARED} ) )
89 | message( SEND_ERROR "Unable to find the file ${FBX_SDK_SHARED} (FBX_SDK_SHARED)." )
90 | set( FBX_LIB_EXISTS FALSE )
91 | endif()
92 | if( NOT ( EXISTS ${FBX_SDK_DEBUG_LIB} ) )
93 | message( SEND_ERROR "Unable to find the file ${FBX_SDK_DEBUG_LIB} (FBX_SDK_DEBUG_LIB)." )
94 | set( FBX_LIB_EXISTS FALSE )
95 | endif()
96 | if( NOT ( EXISTS ${FBX_SDK_DEBUG_SHARED} ) )
97 | message( SEND_ERROR "Unable to find the file ${FBX_SDK_DEBUG_SHARED} (FBX_SDK_DEBUG_SHARED)." )
98 | set( FBX_LIB_EXISTS FALSE )
99 | endif()
100 | if( NOT FBX_LIB_EXISTS )
101 | return()
102 | endif()
103 |
104 | add_library( DzFbx SHARED IMPORTED )
105 | set_property( TARGET DzFbx APPEND PROPERTY IMPORTED_LOCATION "${FBX_SDK_SHARED}" )
106 | set_property( TARGET DzFbx APPEND PROPERTY IMPORTED_LOCATION_DEBUG "${FBX_SDK_DEBUG_SHARED}" )
107 | if( WIN32 )
108 | set_property( TARGET DzFbx APPEND PROPERTY IMPORTED_IMPLIB "${FBX_SDK_LIB}" )
109 | set_property( TARGET DzFbx APPEND PROPERTY IMPORTED_IMPLIB_DEBUG "${FBX_SDK_DEBUG_LIB}" )
110 | endif( WIN32 )
111 | set_property( TARGET DzFbx APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${FBX_SDK_INCLUDE}" )
112 | # FBX requires this to be defined when linking dynamically.
113 | set_property( TARGET DzFbx APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS FBXSDK_SHARED )
114 |
115 | add_library( ${DZ_PLUGIN_TGT_NAME} SHARED
116 | dzfbximporter.cpp
117 | dzfbximporter.h
118 | pluginmain.cpp
119 | version.h
120 | ${OS_SOURCES}
121 | ${PLUGIN_MOC_SOURCES}
122 | )
123 |
124 | target_link_libraries( ${DZ_PLUGIN_TGT_NAME}
125 | PRIVATE
126 | dzcore
127 | DzFbx
128 | ${DZSDK_QT_CORE_TARGET}
129 | ${DZSDK_QT_GUI_TARGET}
130 | ${DZSDK_QT_SCRIPT_TARGET}
131 | )
132 |
133 | target_include_directories( ${DZ_PLUGIN_TGT_NAME}
134 | PRIVATE
135 | ${CMAKE_CURRENT_SOURCE_DIR}
136 | )
137 |
138 | set_target_properties( ${DZ_PLUGIN_TGT_NAME}
139 | PROPERTIES
140 | FOLDER "My Plugins/Importers"
141 | PROJECT_LABEL ${DZ_PLUGIN_PROJECT_NAME}
142 | )
143 |
144 | setup_standard_plugin_source_groups()
145 |
146 | if( WIN32 )
147 | target_compile_definitions( ${DZ_PLUGIN_TGT_NAME} PRIVATE -D_CRT_SECURE_NO_DEPRECATE )
148 | endif()
149 |
--------------------------------------------------------------------------------
/FBX Importer/DzFbxImporter.h:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | Copyright (C) 2012-2022 DAZ 3D, Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | **********************************************************************/
16 |
17 | #pragma once
18 |
19 | /****************************
20 | Include files
21 | ****************************/
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | #include "dzfileio.h"
28 | #include "dzimporter.h"
29 | #include "dzvec3.h"
30 | #include "dzweightmap.h"
31 |
32 | #include
33 |
34 | /****************************
35 | Forward declarations
36 | ****************************/
37 |
38 | class QComboBox;
39 |
40 | class DzFacetMesh;
41 | class DzFacetShape;
42 | class DzFigure;
43 | class DzFloatProperty;
44 | class DzMaterial;
45 | class DzNode;
46 | class DzObject;
47 | class DzSkeleton;
48 | class DzTexture;
49 |
50 | /****************************
51 | Class definitions
52 | ****************************/
53 |
54 | class DzFbxImporter : public DzImporter {
55 | Q_OBJECT
56 | public:
57 | DzFbxImporter();
58 | virtual ~DzFbxImporter();
59 |
60 | //
61 | // RE-IMPLEMENTATIONS
62 | //
63 |
64 | ////////////////////
65 | //from DzFileIO
66 | virtual void getDefaultOptions( DzFileIOSettings* options ) const;
67 |
68 | ////////////////////
69 | //from DzImporter
70 | virtual bool recognize( const QString &filename ) const;
71 | virtual int getNumExtensions() const;
72 | virtual QString getExtension( int i ) const;
73 | virtual QString getDescription() const;
74 |
75 | virtual DzError read( const QString &filename, const DzFileIOSettings* options );
76 |
77 | //
78 | // IMPLEMENTATIONS
79 | //
80 |
81 | QString getFileVersion() const;
82 | QString getFileCreator() const;
83 | QString getFileFormat() const;
84 |
85 | QString getSceneAuthor() const;
86 | QString getSceneTitle() const;
87 | QString getSceneSubject() const;
88 | QString getSceneKeywords() const;
89 | QString getSceneRevision() const;
90 | QString getSceneComment() const;
91 | QString getOriginalAppVendor() const;
92 | QString getOriginalAppName() const;
93 | QString getOriginalAppVersion() const;
94 |
95 | QStringList getAnimStackNames() const;
96 | QStringList getErrorList() const;
97 |
98 | public slots:
99 |
100 | void setRotationLimits( bool enable );
101 | void setIncludeAnimations( bool enable );
102 | void setTakeName( const QString &name );
103 |
104 | void setIncludePolygonSets( bool enable );
105 | void setIncludePolygonGroups( bool enable );
106 |
107 | void setStudioNodeNamesLabels( bool enable );
108 | void setStudioNodePresentation( bool enable );
109 | void setStudioNodeSelectionMap( bool enable );
110 | void setStudioSceneIDs( bool enable );
111 |
112 | protected:
113 |
114 | int getOptions( DzFileIOSettings* options, const DzFileIOSettings* impOptions, const QString &filename );
115 |
116 | private:
117 |
118 | class Node {
119 | public:
120 | Node() :
121 | parent( 0 ),
122 | dsParent( 0 ),
123 | dsNode( 0 ),
124 | fbxNode( 0 ),
125 | bindTranslation( 0, 0, 0 ),
126 | collapseTranslation( false )
127 | {}
128 |
129 | void setParent( Node* parent )
130 | {
131 | this->parent = parent;
132 | if ( this->parent )
133 | {
134 | this->parent->children.append( this );
135 | }
136 | }
137 |
138 | Node* find( DzNode* inDazNode )
139 | {
140 | if ( !inDazNode )
141 | {
142 | return NULL;
143 | }
144 |
145 | if ( dsNode == inDazNode )
146 | {
147 | return this;
148 | }
149 |
150 | for ( int i = 0; i < children.count(); i++ )
151 | {
152 | Node* child = children[i]->find( inDazNode );
153 | if ( child )
154 | {
155 | return child;
156 | }
157 | }
158 |
159 | return NULL;
160 | }
161 |
162 | Node* parent;
163 | QVector children;
164 | DzNode* dsParent;
165 | DzNode* dsNode;
166 | FbxNode* fbxNode;
167 | DzVec3 bindTranslation;
168 | bool collapseTranslation;
169 | };
170 |
171 | struct Skinning
172 | {
173 | Node* node;
174 | FbxSkin* fbxSkin;
175 | DzFigure* dsFigure;
176 | int numVertices;
177 | DzWeightMapPtr blendWeights;
178 | };
179 |
180 |
181 | void fbxPreImportAnimationStack();
182 | void fbxPreImportGraph( FbxNode* fbxNode );
183 | void fbxPreImport();
184 |
185 | DzTexture* toTexture( FbxProperty fbxProperty );
186 |
187 | void fbxImportVertices( int numVertices, FbxVector4* fbxVertices, DzFacetMesh* dsMesh, DzVec3 offset );
188 | void fbxImportUVs( FbxMesh* fbxMesh, DzFacetMesh* dsMesh );
189 | void fbxImportSubdVertexWeights( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, bool &enableSubd );
190 | void fbxImportMaterials( FbxNode* fbxNode, FbxMesh* fbxMesh, DzFacetMesh* dsMesh, DzFacetShape* dsShape, bool &matsAllSame );
191 | void fbxImportPolygonSets( DzNode* dsMeshNode, DzFacetMesh* dsMesh, DzFacetShape* dsShape );
192 | void fbxImportFaces( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, bool matsAllSame, QMap, int> &edgeMap );
193 | void fbxImportSubdEdgeWeights( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, QMap, int> edgeMap, bool &enableSubd );
194 | DzWeightMapPtr fbxImportSkinningBlendWeights( int numVertices, const FbxSkin* fbxSkin );
195 | void fbxImportMorph( FbxBlendShape* fbxBlendShape, DzObject* dsObject, int numVertices, FbxVector4* fbxVertices );
196 | void fbxImportMeshModifiers( Node* node, FbxMesh* fbxMesh, DzObject* dsObject, DzFigure* dsFigure, int numVertices, FbxVector4* fbxVertices );
197 | void fbxImportMesh( Node* node, FbxNode* fbxNode, DzNode* dsMeshNode );
198 | void setSubdEnabled( bool onOff, DzFacetMesh* dsMesh, DzFacetShape* dsShape );
199 |
200 | void applyFbxCurve( FbxAnimCurve* fbxCurve, DzFloatProperty* dsProperty, double scale = 1 );
201 |
202 | void fbxImportGraph( Node* node );
203 | void fbxImportAnimation( Node* node );
204 |
205 | void updateSelectionMap( Node* node );
206 |
207 | void replicateSkeleton( DzSkeleton* dsBaseSkeleton, const Skinning &skinning );
208 |
209 | void fbxRead( const QString &filename );
210 | void fbxPickAnimationTake( int idx );
211 | void fbxPickAnimation();
212 | void fbxImportSkinning();
213 | void fbxImport();
214 | void fbxCleanup();
215 |
216 |
217 | bool m_fbxRead;
218 | FbxManager* m_fbxManager;
219 | FbxScene* m_fbxScene;
220 |
221 | QStringList m_animStackNames;
222 | FbxAnimStack* m_fbxAnimStack;
223 | FbxAnimLayer* m_fbxAnimLayer;
224 |
225 | int m_fbxFileMajor;
226 | int m_fbxFileMinor;
227 | int m_fbxFileRevision;
228 | FbxString m_fbxFileCreator;
229 | int m_fbxFileBinary;
230 |
231 | FbxString m_fbxSceneAuthor;
232 | FbxString m_fbxSceneTitle;
233 | FbxString m_fbxSceneSubject;
234 | FbxString m_fbxSceneKeywords;
235 | FbxString m_fbxSceneRevision;
236 | FbxString m_fbxSceneComment;
237 | FbxString m_fbxOrigAppVendor;
238 | FbxString m_fbxOrigAppName;
239 | FbxString m_fbxOrigAppVersion;
240 |
241 | QVector m_skins;
242 | QMap m_nodeMap;
243 | QMap m_nodeFaceGroupMap;
244 | bool m_needConversion;
245 | DzTime m_dsEndTime;
246 |
247 | bool m_suppressRigErrors;
248 | QStringList m_errorList;
249 |
250 | QDir m_folder;
251 |
252 | QVector m_dsMaterials;
253 |
254 | bool m_includeRotationLimits;
255 | bool m_includeAnimations;
256 | QString m_takeName;
257 |
258 | bool m_includePolygonSets;
259 | bool m_includePolygonGroups;
260 |
261 | bool m_studioNodeNamesLabels;
262 | bool m_studioNodePresentation;
263 | bool m_studioNodeSelectionMap;
264 | bool m_studioSceneIDs;
265 |
266 | Node* m_root;
267 | };
268 |
269 |
270 | class DzFbxImportFrame : public DzFileIOFrame {
271 | Q_OBJECT
272 | public:
273 | DzFbxImportFrame( DzFbxImporter* importer );
274 | ~DzFbxImportFrame();
275 |
276 | //
277 | // RE-IMPLEMENTATIONS
278 | //
279 |
280 | ////////////////////
281 | //from DzFileIOFrame
282 | virtual void setOptions( const DzFileIOSettings* settings, const QString &filename );
283 | virtual void getOptions( DzFileIOSettings* settings ) const;
284 |
285 | protected:
286 |
287 | ////////////////////
288 | //from DzOptionsFrame
289 | virtual void applyChanges();
290 | virtual void resetOptions();
291 |
292 | private:
293 |
294 | struct Data;
295 | QScopedPointer m_data;
296 | };
297 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/FBX Importer/DzFbxImporter.cpp:
--------------------------------------------------------------------------------
1 | /**********************************************************************
2 | Copyright (C) 2012-2022 DAZ 3D, Inc. All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | **********************************************************************/
16 | #include "dzversion.h"
17 |
18 | #if ((DZ_SDK_VERSION_MAJOR >= 5) || ((DZ_SDK_VERSION_MAJOR == 4) && (DZ_SDK_VERSION_MINOR >= 12)))
19 | #define DZ_SDK_4_12_OR_GREATER 1
20 | #else
21 | #define DZ_SDK_4_12_OR_GREATER 0
22 | #endif
23 |
24 | /*****************************
25 | Include files
26 | *****************************/
27 | // Direct Relation
28 | #include "DzFbxImporter.h"
29 |
30 | // System
31 |
32 | // Standard Library
33 |
34 | // Qt
35 | #include
36 |
37 | // DS Public SDK
38 | #include "dzapp.h"
39 | #include "dzbone.h"
40 | #include "dzbonebinding.h"
41 | #if DZ_SDK_4_12_OR_GREATER
42 | #include "dzcollapsiblegroupbox.h"
43 | #endif //DZ_SDK_4_12_OR_GREATER
44 | #include "dzdefaultmaterial.h"
45 | #include "dzenumproperty.h"
46 | #include "dzfacegroup.h"
47 | #include "dzfacetmesh.h"
48 | #include "dzfacetshape.h"
49 | #include "dzfigure.h"
50 | #include "dzfileiosettings.h"
51 | #include "dzfloatproperty.h"
52 | #if DZ_SDK_4_12_OR_GREATER
53 | #include "dzgraftingfigureshape.h"
54 | #endif // DZ_SDK_4_12_OR_GREATER
55 | #include "dzdynamicdividerwgt.h"
56 | #include "dzimagemgr.h"
57 | #include "dzmorph.h"
58 | #include "dzmorphdeltas.h"
59 | #include "dznode.h"
60 | #include "dzobject.h"
61 | #include "dzpresentation.h"
62 | #include "dzprogress.h"
63 | #include "dzscene.h"
64 | #include "dzselectionmap.h"
65 | #include "dzsettings.h"
66 | #include "dzskinbinding.h"
67 | #include "dzstyle.h"
68 |
69 | // Project Specific
70 |
71 | /*****************************
72 | Local Definitions
73 | *****************************/
74 |
75 | #if FBXSDK_VERSION_MAJOR >= 2016
76 | #define DATA_FBX_USER_PROPERTIES "FbxUserProperties"
77 | #define DATA_LOD_INFO "LODInfo"
78 | #endif
79 |
80 | namespace
81 | {
82 |
83 | // settings keys
84 | const QString c_optTake( "Take" );
85 |
86 | const QString c_optIncRotationLimits( "IncludeRotationLimits" );
87 | const QString c_optIncAnimations( "IncludeAnimations" );
88 |
89 | const QString c_optIncPolygonSets( "IncludePolygonSets" );
90 | const QString c_optIncPolygonGroups( "IncludePolygonGroups" );
91 |
92 | const QString c_optStudioNodeNamesLabels( "IncludeNodeNamesLabels" );
93 | const QString c_optStudioPresentation( "IncludeNodePresentation" );
94 | const QString c_optStudioNodeSelectionMap( "IncludeNodeSelectionMap" );
95 | const QString c_optStudioSceneIDs( "IncludeSceneIDs" );
96 |
97 | const QString c_optRunSilent( "RunSilent" );
98 |
99 | // settings default values
100 | const bool c_defaultIncludeRotationLimits = true;
101 | const bool c_defaultIncludeAnimations = false;
102 |
103 | const bool c_defaultIncludePolygonSets = true;
104 | const bool c_defaultIncludePolygonGroups = false;
105 |
106 | const bool c_defaultStudioNodeNames = true;
107 | const bool c_defaultStudioNodePresentation = true;
108 | const bool c_defaultStudioNodeSelectionMap = true;
109 | const bool c_defaultStudioSceneIDs = true;
110 |
111 | // functions
112 | DzFigure* createFigure()
113 | {
114 | DzFigure* dsFigure = new DzFigure();
115 |
116 | DzEnumProperty* followModeControl = NULL;
117 | #if DZ_SDK_4_12_OR_GREATER
118 | followModeControl = dsFigure->getFollowModeControl();
119 | followModeControl->setValue( DzSkeleton::fmAutoFollow );
120 | #else
121 | // DzSkeleton::getFollowModeControl() is not in the 4.5 SDK, so we attempt
122 | // to use the meta-object to call the methods - since 4.8.0.23. If this fails,
123 | // we attempt to find the property by name and if found set its value.
124 |
125 | if ( !QMetaObject::invokeMethod( dsFigure,
126 | "getFollowModeControl", Q_RETURN_ARG( DzEnumProperty*, followModeControl ) )
127 | || !followModeControl )
128 | {
129 | followModeControl = qobject_cast( dsFigure->findProperty( "Fit to Mode" ) );
130 | if ( followModeControl )
131 | {
132 | followModeControl->setValue( 1 );
133 | }
134 | }
135 | #endif
136 |
137 | dsFigure->setDrawGLBones( true );
138 |
139 | return dsFigure;
140 | }
141 |
142 | } // namespace
143 |
144 | ///////////////////////////////////////////////////////////////////////
145 | // DzFbxImporter
146 | ///////////////////////////////////////////////////////////////////////
147 |
148 | #ifdef DAZ_SCRIPT_DOCS
149 |
150 | class DzFbxImporter : public DzImporter {
151 | public:
152 | // DAZScript Constructors
153 |
154 | DzFbxImporter();
155 | };
156 |
157 | #endif // DAZ_SCRIPT_DOCS
158 |
159 | /**
160 | @script
161 | @class DzFbxImporter
162 |
163 | @ingroup FileIO
164 | @nosubgrouping
165 | @brief Class for importing files in the Autodesk FBX (*.fbx) format.
166 |
167 | A specialization of DzImporter that implements an importer for the Autodesk
168 | FBX (.fbx) format. Through its use of the FBX SDK to accomplish this task,
169 | this importer also provides import capabilities for the Autodesk AutoCAD DXF
170 | (.dxf) format, the Autodesk 3ds Max (.3ds) format, and the Collada DAE (.dae)
171 | format, as supported by the FBX SDK.
172 |
173 | @attention The FBX SDK also provides import capabilities for the Alias
174 | Wavefront OBJ (.obj) format, but it has been intentionally
175 | excluded. Use DzObjImporter instead.
176 |
177 | @sa DzImportMgr::findImporterByClassName()
178 | @sa DzImportMgr::findImporter()
179 |
180 | @sa Sample: @dzscript{api_reference/samples/file_io/import_fbx_silent/start, Silent FBX Import}
181 | **/
182 |
183 |
184 | /**
185 | @script
186 | Default Constructor.
187 | **/
188 | DzFbxImporter::DzFbxImporter() :
189 | m_fbxRead( false ),
190 | m_fbxManager( NULL ),
191 | m_fbxScene( NULL ),
192 | m_fbxAnimStack( NULL ),
193 | m_fbxAnimLayer( NULL ),
194 | m_fbxFileMajor( 0 ),
195 | m_fbxFileMinor( 0 ),
196 | m_fbxFileRevision( 0 ),
197 | m_fbxFileBinary( -1 ),
198 | m_needConversion( false ),
199 | m_dsEndTime( 0 ),
200 | m_suppressRigErrors( false ),
201 | m_includeRotationLimits( c_defaultIncludeRotationLimits ),
202 | m_includeAnimations( c_defaultIncludeAnimations ),
203 | m_includePolygonSets( c_defaultIncludePolygonSets ),
204 | m_includePolygonGroups( c_defaultIncludePolygonGroups ),
205 | m_studioNodeNamesLabels( c_defaultStudioNodeNames ),
206 | m_studioNodePresentation( c_defaultStudioNodePresentation ),
207 | m_studioNodeSelectionMap( c_defaultStudioNodeSelectionMap ),
208 | m_studioSceneIDs( c_defaultStudioSceneIDs ),
209 | m_root( NULL )
210 | {}
211 |
212 | /**
213 | **/
214 | DzFbxImporter::~DzFbxImporter()
215 | {
216 | }
217 |
218 | /**
219 | **/
220 | bool DzFbxImporter::recognize( const QString &filename ) const
221 | {
222 | const QString ext = getFileExtension( filename ); //return value is lowercase
223 | for ( int i = 0, n = getNumExtensions(); i < n; i++ )
224 | {
225 | if ( ext == getExtension( i ) )
226 | {
227 | return true;
228 | }
229 | }
230 |
231 | return false;
232 | }
233 |
234 | /**
235 | **/
236 | int DzFbxImporter::getNumExtensions() const
237 | {
238 | return 4;
239 | }
240 |
241 | /**
242 | **/
243 | QString DzFbxImporter::getExtension( int i ) const
244 | {
245 | switch ( i )
246 | {
247 | case 0:
248 | return "fbx";
249 | case 1:
250 | return "dxf";
251 | case 2:
252 | return "3ds";
253 | case 3:
254 | // DzCOLLADAImporter depends on FCollada (discontinued)
255 | // DzCOLLADAImporter is deprecated
256 | return "dae";
257 | case 4:
258 | // DzObjImporter provides a more suitable result
259 | // This conflicts with DzObjImporter and recognize()
260 | //return "obj";
261 | default:
262 | return QString();
263 | }
264 | }
265 |
266 | /**
267 | **/
268 | QString DzFbxImporter::getDescription() const
269 | {
270 | return "Autodesk FBX SDK";
271 | }
272 |
273 | /**
274 | **/
275 | void DzFbxImporter::getDefaultOptions( DzFileIOSettings* options ) const
276 | {
277 | assert( options );
278 | if ( !options )
279 | {
280 | return;
281 | }
282 |
283 | // Properties
284 | options->setBoolValue( c_optIncRotationLimits, c_defaultIncludeRotationLimits );
285 | options->setBoolValue( c_optIncAnimations, c_defaultIncludeAnimations );
286 | options->setStringValue( c_optTake, QString() );
287 |
288 | // Geometry
289 | options->setBoolValue( c_optIncPolygonSets, c_defaultIncludePolygonSets );
290 | options->setBoolValue( c_optIncPolygonGroups, c_defaultIncludePolygonGroups );
291 |
292 | // Custom Data
293 | options->setBoolValue( c_optStudioNodeNamesLabels, c_defaultStudioNodeNames );
294 | options->setBoolValue( c_optStudioPresentation, c_defaultStudioNodePresentation );
295 | options->setBoolValue( c_optStudioNodeSelectionMap, c_defaultStudioNodeSelectionMap );
296 | options->setBoolValue( c_optStudioSceneIDs, c_defaultStudioSceneIDs );
297 |
298 | options->setIntValue( c_optRunSilent, 0 );
299 | }
300 |
301 |
302 | namespace
303 | {
304 |
305 | class MapConversion {
306 | public:
307 | QVector fbxWeights;
308 | unsigned short* dsWeights;
309 | };
310 |
311 | bool isChildNode( DzNode* child, DzNode* parent )
312 | {
313 | if ( !parent || !child || child == parent )
314 | {
315 | return false;
316 | }
317 |
318 | while ( child )
319 | {
320 | if ( child == parent )
321 | {
322 | return true;
323 | }
324 | child = child->getNodeParent();
325 | }
326 |
327 | return false;
328 | }
329 |
330 | } //namespace
331 |
332 | /**
333 | Manually get the options. If the "RunSilent" option is true, then the dialog
334 | will be skipped.
335 | **/
336 | int DzFbxImporter::getOptions( DzFileIOSettings* options, const DzFileIOSettings* impOptions, const QString &filename )
337 | {
338 | assert( options );
339 | assert( impOptions );
340 | if ( !options || !impOptions )
341 | {
342 | return false;
343 | }
344 |
345 | bool optionsShown = false;
346 | #if DZ_SDK_4_12_OR_GREATER
347 | optionsShown = getOptionsShown();
348 | #endif
349 |
350 | if ( optionsShown || impOptions->getIntValue( c_optRunSilent, 0 ) )
351 | {
352 | if ( optionsShown )
353 | {
354 | getSavedOptions( options ); // includes defaults
355 | }
356 | else
357 | {
358 | getDefaultOptions( options );
359 | }
360 |
361 | #if DZ_SDK_4_12_OR_GREATER
362 | copySettings( options, impOptions );
363 | #else
364 | // DzFileIO::copySettings() is not in the 4.5 SDK, and it is not exposed
365 | // to QMetaObject::invokedMethod() in later builds, so we copy manually.
366 | for ( int i = 0, n = options->getNumValues(); i < n; i++ )
367 | {
368 | const QString key = options->getKey( i );
369 | switch ( options->getValueType( i ) )
370 | {
371 | default:
372 | case DzSettings::StringValue:
373 | case DzSettings::IntValue:
374 | case DzSettings::BoolValue:
375 | case DzSettings::FloatValue:
376 | impOptions->copySetting( key, options );
377 | break;
378 | case DzSettings::SettingsValue:
379 | impOptions->copySetting( key, options->getSettingsValue( key ) );
380 | break;
381 | }
382 | }
383 | #endif
384 |
385 | return true;
386 | }
387 |
388 | fbxRead( filename );
389 | fbxPreImport();
390 |
391 | DzFbxImporter* self = const_cast( this );
392 | DzFbxImportFrame* frame = new DzFbxImportFrame( self );
393 | if ( !frame )
394 | {
395 | fbxCleanup();
396 | return true;
397 | }
398 |
399 | DzFileIODlg optionsDlg( frame );
400 | frame->setOptions( impOptions, filename );
401 | if ( optionsDlg.exec() != QDialog::Accepted )
402 | {
403 | fbxCleanup();
404 | return false; // user cancelled
405 | }
406 |
407 | #if DZ_SDK_4_12_OR_GREATER
408 | setOptionsShown( true );
409 | #endif
410 |
411 | frame->getOptions( options );
412 |
413 | // if handling the options dialog ourselves, we also need to save the state
414 | options->setIntValue( c_optRunSilent, 0 );
415 | saveOptions( options );
416 |
417 | return true;
418 | }
419 |
420 | /**
421 | **/
422 | void DzFbxImporter::fbxRead( const QString &filename )
423 | {
424 | if ( m_fbxRead )
425 | {
426 | return;
427 | }
428 |
429 | QString orgName;
430 | #if DZ_SDK_4_12_OR_GREATER
431 | orgName = dzApp->getOrgName();
432 | #else
433 | // DzApp::getOrgName() is not in the 4.5 SDK, so we attempt to use the
434 | // meta-object to access the DzApp::orgName property - since 4.6.4.30.
435 |
436 | orgName = dzApp->property( "orgName" ).toString();
437 | #endif
438 | if ( !orgName.isEmpty()
439 | && orgName != QString( "DAZ 3D" ) )
440 | {
441 | m_suppressRigErrors = true;
442 | }
443 |
444 | m_fbxManager = FbxManager::Create();
445 | FbxIOSettings* fbxIoSettings = FbxIOSettings::Create( m_fbxManager, IOSROOT );
446 | m_fbxManager->SetIOSettings( fbxIoSettings );
447 |
448 | m_fbxScene = FbxScene::Create( m_fbxManager, "" );
449 |
450 | m_fbxAnimStack = NULL;
451 | m_fbxAnimLayer = NULL;
452 | m_dsEndTime = dzScene->getAnimRange().getEnd();
453 |
454 | FbxImporter* fbxImporter = FbxImporter::Create( m_fbxManager, "" );
455 | if ( !fbxImporter->Initialize( filename.toUtf8().data(), -1, fbxIoSettings ) )
456 | {
457 | const FbxStatus status = fbxImporter->GetStatus();
458 | if ( status != FbxStatus::eSuccess )
459 | {
460 | dzApp->warning( QString( "FBX Importer: %1" ).arg( status.GetErrorString() ) );
461 | }
462 | }
463 |
464 | fbxImporter->GetFileVersion( m_fbxFileMajor, m_fbxFileMinor, m_fbxFileRevision );
465 |
466 | if ( fbxImporter->IsFBX() )
467 | {
468 | fbxIoSettings->SetBoolProp( IMP_FBX_MATERIAL, true );
469 | fbxIoSettings->SetBoolProp( IMP_FBX_TEXTURE, true );
470 | fbxIoSettings->SetBoolProp( IMP_FBX_LINK, true );
471 | fbxIoSettings->SetBoolProp( IMP_FBX_SHAPE, true );
472 | fbxIoSettings->SetBoolProp( IMP_FBX_GOBO, true );
473 | fbxIoSettings->SetBoolProp( IMP_FBX_ANIMATION, true );
474 | fbxIoSettings->SetBoolProp( IMP_FBX_GLOBAL_SETTINGS, true );
475 | }
476 |
477 | #if FBXSDK_VERSION_MAJOR >= 2020
478 | fbxImporter->GetStatus().KeepErrorStringHistory( true );
479 | #endif
480 |
481 | fbxImporter->Import( m_fbxScene );
482 |
483 | FbxStatus status = fbxImporter->GetStatus();
484 | if ( status != FbxStatus::eSuccess )
485 | {
486 | #if FBXSDK_VERSION_MAJOR >= 2020
487 | FbxArray history;
488 | status.GetErrorStringHistory( history );
489 | if ( history.GetCount() > 1 )
490 | {
491 | // error strings are in stack order (last error -> first element)
492 | for ( int i = history.GetCount() - 1; i >= 0 ; --i )
493 | {
494 | dzApp->warning( QString( "FBX Importer: %1" ).arg( history[i]->Buffer() ) );
495 | }
496 | }
497 | FbxArrayDelete( history );
498 | #else
499 | dzApp->warning( QString( "FBX Importer: %1" ).arg( status.GetErrorString() ) );
500 | #endif
501 | }
502 |
503 | const FbxIOFileHeaderInfo* fbxHeaderInfo = fbxImporter->GetFileHeaderInfo();
504 | m_fbxFileCreator = fbxHeaderInfo->mCreator;
505 | #if FBXSDK_VERSION_MAJOR > 2020 || (FBXSDK_VERSION_MAJOR == 2020 && FBXSDK_VERSION_MINOR >= 3)
506 | m_fbxFileBinary = fbxHeaderInfo->mBinary ? 1 : 0;
507 | #endif
508 |
509 | fbxImporter->Destroy();
510 |
511 | const FbxDocumentInfo* fbxSceneInfo = m_fbxScene->GetSceneInfo();
512 | m_fbxSceneAuthor = fbxSceneInfo->mAuthor;
513 | m_fbxSceneTitle = fbxSceneInfo->mTitle;
514 | m_fbxSceneSubject = fbxSceneInfo->mSubject;
515 | m_fbxSceneKeywords = fbxSceneInfo->mKeywords;
516 | m_fbxSceneRevision = fbxSceneInfo->mRevision;
517 | m_fbxSceneComment = fbxSceneInfo->mComment;
518 | m_fbxOrigAppVendor = fbxSceneInfo->Original_ApplicationVendor;
519 | m_fbxOrigAppName = fbxSceneInfo->Original_ApplicationName;
520 | m_fbxOrigAppVersion = fbxSceneInfo->Original_ApplicationVersion;
521 |
522 | m_fbxRead = true;
523 | }
524 |
525 | /**
526 | **/
527 | void DzFbxImporter::fbxPickAnimationTake( int idx )
528 | {
529 | m_fbxAnimStack = m_fbxScene->GetSrcObject( idx );
530 | if ( m_fbxAnimStack->GetMemberCount() <= 0 )
531 | {
532 | return;
533 | }
534 |
535 | m_fbxAnimLayer = m_fbxAnimStack->GetMember( 0 );
536 | }
537 |
538 | /**
539 | **/
540 | void DzFbxImporter::fbxPickAnimation()
541 | {
542 | if ( !m_includeAnimations
543 | || m_takeName.isEmpty() )
544 | {
545 | return;
546 | }
547 |
548 | const QString idxPrefix( "idx::" );
549 | if ( m_takeName.startsWith( idxPrefix ) )
550 | {
551 | bool isNum = false;
552 | const int takeIdx = m_takeName.mid( idxPrefix.length() ).toInt( &isNum );
553 | if ( isNum
554 | && takeIdx > -1
555 | && takeIdx < m_fbxScene->GetSrcObjectCount() )
556 | {
557 | fbxPickAnimationTake( takeIdx );
558 | }
559 | }
560 | else
561 | {
562 | for ( int i = 0, n = m_fbxScene->GetSrcObjectCount(); i < n; i++ )
563 | {
564 | const FbxAnimStack* animStack = m_fbxScene->GetSrcObject( i );
565 | if ( QString( animStack->GetName() ) != m_takeName )
566 | {
567 | continue;
568 | }
569 |
570 | fbxPickAnimationTake( i );
571 | }
572 | }
573 | }
574 |
575 | /**
576 | **/
577 | void DzFbxImporter::fbxImportSkinning()
578 | {
579 | QVector dsBones;
580 | for ( int i = 0; i < m_skins.size(); i++ )
581 | {
582 | Skinning skinning = m_skins[i];
583 |
584 | const Node* node = skinning.node;
585 | Q_UNUSED( node )
586 |
587 | FbxSkin* fbxSkin = skinning.fbxSkin;
588 | DzFigure* dsFigure = skinning.dsFigure;
589 | const int numVertices = skinning.numVertices;
590 |
591 | DzSkinBinding* dsSkin = dsFigure->getSkinBinding();
592 |
593 | #if DZ_SDK_4_12_OR_GREATER
594 | if ( dsSkin
595 | && dsSkin->getTargetVertexCount() < 1 )
596 | {
597 | dsSkin->setTargetVertexCount( numVertices );
598 | #else
599 | // DzSkinBinding::getTargetVertexCount() is not in the 4.5 SDK, so
600 | // we attempt to use the meta-object to call the method.
601 |
602 | int targetVertexCount = 0;
603 | if ( dsSkin
604 | && QMetaObject::invokeMethod( dsSkin, "getTargetVertexCount",
605 | Q_RETURN_ARG( int, targetVertexCount ) )
606 | && targetVertexCount < 1 )
607 | {
608 | // DzSkinBinding::setTargetVertexCount() is not in the 4.5 SDK,
609 | // so we attempt to use the meta-object to call the method.
610 |
611 | bool im = QMetaObject::invokeMethod( dsSkin, "setTargetVertexCount",
612 | Q_ARG( int, numVertices ) );
613 | assert( im );
614 | #endif
615 | }
616 | else if ( !dsSkin )
617 | {
618 | assert( !"Binding was not found" );
619 | continue;
620 | }
621 |
622 | const int numClusters = fbxSkin->GetClusterCount();
623 |
624 | DzSkeleton* dsBaseSkeleton = NULL;
625 |
626 | for ( int j = 0; j < numClusters; j++ )
627 | {
628 | FbxCluster* fbxCluster = fbxSkin->GetCluster( j );
629 | DzBone* dsBone = qobject_cast( m_nodeMap.value( fbxCluster->GetLink() ) );
630 | if ( !dsBone )
631 | {
632 | continue;
633 | }
634 |
635 | if ( !isChildNode( dsBone, dsFigure ) )
636 | {
637 | dsBaseSkeleton = dsBone->getSkeleton();
638 | }
639 | }
640 |
641 | if ( dsBaseSkeleton )
642 | {
643 | replicateSkeleton( dsBaseSkeleton, skinning );
644 | }
645 |
646 |
647 | DzWeightMapList maps;
648 | QVector mapConversions;
649 | for ( int j = 0; j < numClusters; j++ )
650 | {
651 | FbxCluster* fbxCluster = fbxSkin->GetCluster( j );
652 | DzBone* dsBone = qobject_cast( m_nodeMap.value( fbxCluster->GetLink() ) );
653 | if ( !dsBone )
654 | {
655 | continue;
656 | }
657 |
658 | DzBoneBinding* dsBinding = new DzBoneBinding();
659 | dsBinding->setBone( dsBone );
660 | dsSkin->addBoneBinding( dsBinding );
661 |
662 | DzWeightMap* dsWeightMap = new DzWeightMap( numVertices );
663 | int* fbxIndices = fbxCluster->GetControlPointIndices();
664 | double* fbxWeights = fbxCluster->GetControlPointWeights();
665 |
666 | MapConversion mapConv;
667 | mapConv.dsWeights = dsWeightMap->getWeights();
668 | mapConv.fbxWeights.resize( numVertices );
669 | for ( int k = 0; k < fbxCluster->GetControlPointIndicesCount(); k++ )
670 | {
671 | mapConv.fbxWeights[fbxIndices[k]] = fbxWeights[k];
672 | }
673 | mapConversions.append( mapConv );
674 |
675 | dsBinding->setWeights( dsWeightMap );
676 | FbxAMatrix fbxMatrix;
677 | fbxCluster->GetTransformLinkMatrix( fbxMatrix );
678 |
679 | DzMatrix3 dsMatrix;
680 | dsMatrix[0][0] = fbxMatrix[0][0];
681 | dsMatrix[0][1] = fbxMatrix[0][1];
682 | dsMatrix[0][2] = fbxMatrix[0][2];
683 | dsMatrix[1][0] = fbxMatrix[1][0];
684 | dsMatrix[1][1] = fbxMatrix[1][1];
685 | dsMatrix[1][2] = fbxMatrix[1][2];
686 | dsMatrix[2][0] = fbxMatrix[2][0];
687 | dsMatrix[2][1] = fbxMatrix[2][1];
688 | dsMatrix[2][2] = fbxMatrix[2][2];
689 | dsMatrix[3][0] = -fbxMatrix[3][0];
690 | dsMatrix[3][1] = -fbxMatrix[3][1];
691 | dsMatrix[3][2] = -fbxMatrix[3][2];
692 |
693 | DzVec3 skelOrigin = dsFigure->getOrigin();
694 | DzVec3 origin = dsBone->getOrigin();
695 | dsMatrix[3][0] += ( origin[0] - skelOrigin[0] );
696 | dsMatrix[3][1] += ( origin[1] - skelOrigin[1] );
697 | dsMatrix[3][2] += ( origin[2] - skelOrigin[2] );
698 | dsBinding->setBindingMatrix( dsMatrix );
699 | maps.append( dsWeightMap );
700 | }
701 |
702 | for ( int v = 0; v < numVertices; v++ )
703 | {
704 | double sum = 0.0;
705 | for ( int m = 0; m < mapConversions.count(); m++ )
706 | {
707 | sum += mapConversions[m].fbxWeights[v];
708 | }
709 |
710 | for ( int m = 0; m < mapConversions.count(); m++ )
711 | {
712 | mapConversions[m].dsWeights[v] = static_cast( mapConversions[m].fbxWeights[v] / sum * DZ_USHORT_MAX );
713 | }
714 | }
715 |
716 | DzWeightMap::normalizeMaps( maps );
717 |
718 | FbxSkin::EType fbxSkinningType = fbxSkin->GetSkinningType();
719 |
720 | #if DZ_SDK_4_12_OR_GREATER
721 | DzSkinBinding::BindingMode bindingMode = DzSkinBinding::General;
722 | DzSkinBinding::GeneralMapMode generalMapMode = DzSkinBinding::Linear;
723 | switch ( fbxSkinningType )
724 | {
725 | default:
726 | break;
727 | case FbxSkin::eDualQuaternion:
728 | generalMapMode = DzSkinBinding::DualQuat;
729 | break;
730 | case FbxSkin::eBlend:
731 | bindingMode = DzSkinBinding::Blended;
732 | generalMapMode = DzSkinBinding::DualQuat;
733 | break;
734 | }
735 |
736 | dsSkin->setBindingMode( bindingMode );
737 | dsSkin->setGeneralMapMode( generalMapMode );
738 | dsSkin->setScaleMode( DzSkinBinding::BindingMaps );
739 |
740 | #else
741 | // DzSkinBinding::BindingMode, and DzSkinBinding::GeneralMapMode are not
742 | // in the 4.5 SDK, so we use the int equivalents.
743 |
744 | int bindingMode = 0;
745 | int generalMapMode = 0;
746 | switch ( fbxSkinningType )
747 | {
748 | default:
749 | break;
750 | case FbxSkin::eDualQuaternion:
751 | generalMapMode = 1;
752 | break;
753 | case FbxSkin::eBlend:
754 | bindingMode = 2;
755 | generalMapMode = 1;
756 | break;
757 | }
758 |
759 | // DzSkinBinding::setBindingMode(), DzSkinBinding::setScaleMode(),
760 | // and DzSkinBinding::setGeneralMapMode() are not in the 4.5 SDK,
761 | // so we attempt to use the meta-object to call these methods.
762 |
763 | bool im = QMetaObject::invokeMethod( dsSkin, "setBindingMode",
764 | Q_ARG( int, bindingMode ) );
765 | assert( im );
766 |
767 | im = QMetaObject::invokeMethod( dsSkin, "setGeneralMapMode",
768 | Q_ARG( int, generalMapMode ) );
769 | assert( im );
770 |
771 | im = QMetaObject::invokeMethod( dsSkin, "setScaleMode",
772 | Q_ARG( int, 1 ) );
773 | assert( im );
774 | #endif
775 |
776 | if ( fbxSkinningType == FbxSkin::eBlend
777 | && skinning.blendWeights )
778 | {
779 | #if DZ_SDK_4_12_OR_GREATER
780 | dsSkin->setBlendMap( skinning.blendWeights );
781 | dsSkin->setBlendMode( DzSkinBinding::BlendLinearDualQuat );
782 | #else
783 | // DzSkinBinding::setBlendMap() and DzSkinBinding::setBlendMode()
784 | // are not in the 4.5 SDK, so we attempt to use the meta-object to
785 | // call these methods.
786 |
787 | im = QMetaObject::invokeMethod( dsSkin, "setBlendMap",
788 | Q_ARG( DzWeightMap*, skinning.blendWeights.operator->() ) );
789 | assert( im );
790 |
791 | im = QMetaObject::invokeMethod( dsSkin, "setBlendMode",
792 | Q_ARG( int, 1 ) );
793 | assert( im );
794 | #endif
795 | }
796 | }
797 | }
798 |
799 | /**
800 | **/
801 | void DzFbxImporter::fbxImport()
802 | {
803 | fbxPickAnimation();
804 |
805 | m_root = new Node();
806 | m_root->fbxNode = m_fbxScene->GetRootNode();
807 |
808 | fbxImportGraph( m_root );
809 |
810 | fbxImportSkinning();
811 |
812 | fbxImportAnimation( m_root );
813 |
814 | if ( m_includeAnimations )
815 | {
816 | dzScene->setAnimRange( DzTimeRange( dzScene->getAnimRange().getStart(), m_dsEndTime ) );
817 | dzScene->setPlayRange( DzTimeRange( dzScene->getAnimRange().getStart(), m_dsEndTime ) );
818 | }
819 |
820 | QMap::iterator nodeFaceGroupIt;
821 | for ( nodeFaceGroupIt = m_nodeFaceGroupMap.begin(); nodeFaceGroupIt != m_nodeFaceGroupMap.end(); ++nodeFaceGroupIt )
822 | {
823 | updateSelectionMap( nodeFaceGroupIt.key() );
824 | }
825 | }
826 |
827 | /**
828 | **/
829 | void DzFbxImporter::fbxCleanup()
830 | {
831 | if ( m_fbxManager )
832 | {
833 | m_fbxManager->Destroy();
834 | }
835 |
836 | m_fbxManager = NULL;
837 | }
838 |
839 | /**
840 | @param filename The full path of the file to import.
841 | @param impOptions The options to use while importing the file.
842 |
843 | @return DZ_NO_ERROR if the file was successfully imported.
844 | **/
845 | DzError DzFbxImporter::read( const QString &filename, const DzFileIOSettings* impOptions )
846 | {
847 | DzFileIOSettings options;
848 | const int isOK = getOptions( &options, impOptions, filename );
849 | if ( !isOK )
850 | {
851 | return DZ_USER_CANCELLED_OPERATION;
852 | }
853 |
854 | // Properties
855 | m_includeRotationLimits = options.getBoolValue( c_optIncRotationLimits, c_defaultIncludeRotationLimits );
856 | m_includeAnimations = options.getBoolValue( c_optIncAnimations, c_defaultIncludeAnimations );
857 | m_takeName = options.getStringValue( c_optTake, QString() );
858 |
859 | // Geometry
860 | m_includePolygonSets = options.getBoolValue( c_optIncPolygonSets, c_defaultIncludePolygonSets );
861 | m_includePolygonGroups = options.getBoolValue( c_optIncPolygonGroups, c_defaultIncludePolygonGroups );
862 |
863 | // Custom Data
864 | m_studioNodeNamesLabels = options.getBoolValue( c_optStudioNodeNamesLabels, c_defaultStudioNodeNames );
865 | m_studioNodePresentation = options.getBoolValue( c_optStudioPresentation, c_defaultStudioNodePresentation );
866 | m_studioNodeSelectionMap = options.getBoolValue( c_optStudioNodeSelectionMap, c_defaultStudioNodeSelectionMap );
867 | m_studioSceneIDs = options.getBoolValue( c_optStudioSceneIDs, c_defaultStudioSceneIDs );
868 |
869 | #if DZ_SDK_4_12_OR_GREATER
870 | clearImportedNodes();
871 | #endif
872 |
873 | m_folder = filename;
874 | m_folder.cdUp();
875 |
876 | fbxRead( filename );
877 | fbxImport();
878 | fbxCleanup();
879 |
880 | bool allTransparent = true;
881 | for ( int i = 0; i < m_dsMaterials.size() && allTransparent; i++ )
882 | {
883 | if ( m_dsMaterials[i]->getBaseOpacity() > 0.1 )
884 | {
885 | allTransparent = false;
886 | }
887 | }
888 |
889 | if ( allTransparent )
890 | {
891 | for ( int i = 0; i < m_dsMaterials.size() && allTransparent; i++ )
892 | {
893 | m_dsMaterials[i]->setBaseOpacity( 1 );
894 | }
895 | }
896 |
897 | return DZ_NO_ERROR;
898 | }
899 |
900 | /**
901 | **/
902 | QString DzFbxImporter::getFileVersion() const
903 | {
904 | QString sdkStr( "Unknown" );
905 | const QString versionStr( "%1 (%2.%3.%4)%5" );
906 | switch ( m_fbxFileMajor )
907 | {
908 | case 7:
909 | switch( m_fbxFileMinor )
910 | {
911 | case 7:
912 | sdkStr = "FBX 2019";
913 | break;
914 | case 5:
915 | sdkStr = "FBX 2016/2017";
916 | break;
917 | case 4:
918 | sdkStr = "FBX 2014/2015";
919 | break;
920 | case 3:
921 | sdkStr = "FBX 2013";
922 | break;
923 | case 2:
924 | sdkStr = "FBX 2012";
925 | break;
926 | case 1:
927 | sdkStr = "FBX 2011";
928 | break;
929 | default:
930 | break;
931 | }
932 | break;
933 | case 6:
934 | switch( m_fbxFileMinor )
935 | {
936 | case 1:
937 | sdkStr = "FBX 2006/2009/2010";
938 | break;
939 | default:
940 | break;
941 | }
942 | break;
943 | default:
944 | break;
945 | }
946 |
947 | return versionStr
948 | .arg( sdkStr )
949 | .arg( m_fbxFileMajor )
950 | .arg( m_fbxFileMinor )
951 | .arg( m_fbxFileRevision )
952 | .arg( getFileFormat() );
953 | }
954 |
955 | /**
956 | **/
957 | QString DzFbxImporter::getFileCreator() const
958 | {
959 | return QString( m_fbxFileCreator );
960 | }
961 |
962 | /**
963 | **/
964 | QString DzFbxImporter::getFileFormat() const
965 | {
966 | switch ( m_fbxFileBinary )
967 | {
968 | default:
969 | case -1:
970 | return QString();
971 | case 0:
972 | return " -- Ascii";
973 | case 1:
974 | return " -- Binary";
975 | }
976 | }
977 |
978 | /**
979 | **/
980 | QString DzFbxImporter::getSceneAuthor() const
981 | {
982 | return QString( m_fbxSceneAuthor );
983 | }
984 |
985 | /**
986 | **/
987 | QString DzFbxImporter::getSceneTitle() const
988 | {
989 | return QString( m_fbxSceneTitle );
990 | }
991 |
992 | /**
993 | **/
994 | QString DzFbxImporter::getSceneSubject() const
995 | {
996 | return QString( m_fbxSceneSubject );
997 | }
998 |
999 | /**
1000 | **/
1001 | QString DzFbxImporter::getSceneKeywords() const
1002 | {
1003 | return QString( m_fbxSceneKeywords );
1004 | }
1005 |
1006 | /**
1007 | **/
1008 | QString DzFbxImporter::getSceneRevision() const
1009 | {
1010 | return QString( m_fbxSceneRevision );
1011 | }
1012 |
1013 | /**
1014 | **/
1015 | QString DzFbxImporter::getSceneComment() const
1016 | {
1017 | return QString( m_fbxSceneComment );
1018 | }
1019 |
1020 | /**
1021 | **/
1022 | QString DzFbxImporter::getOriginalAppVendor() const
1023 | {
1024 | return QString( m_fbxOrigAppVendor );
1025 | }
1026 |
1027 | /**
1028 | **/
1029 | QString DzFbxImporter::getOriginalAppName() const
1030 | {
1031 | return QString( m_fbxOrigAppName );
1032 | }
1033 |
1034 | /**
1035 | **/
1036 | QString DzFbxImporter::getOriginalAppVersion() const
1037 | {
1038 | return QString( m_fbxOrigAppVersion );
1039 | }
1040 |
1041 | /**
1042 | **/
1043 | QStringList DzFbxImporter::getAnimStackNames() const
1044 | {
1045 | return m_animStackNames;
1046 | }
1047 |
1048 | /**
1049 | **/
1050 | void DzFbxImporter::setRotationLimits( bool enable )
1051 | {
1052 | m_includeRotationLimits = enable;
1053 | }
1054 |
1055 | /**
1056 | **/
1057 | void DzFbxImporter::setIncludeAnimations( bool enable )
1058 | {
1059 | m_includeAnimations = enable;
1060 | }
1061 |
1062 | /**
1063 | **/
1064 | void DzFbxImporter::setTakeName( const QString &name )
1065 | {
1066 | m_takeName = name;
1067 | }
1068 |
1069 | /**
1070 | **/
1071 | void DzFbxImporter::setIncludePolygonSets( bool enable )
1072 | {
1073 | m_includePolygonSets = enable;
1074 | }
1075 |
1076 | /**
1077 | **/
1078 | void DzFbxImporter::setIncludePolygonGroups( bool enable )
1079 | {
1080 | m_includePolygonGroups = enable;
1081 | }
1082 |
1083 | /**
1084 | **/
1085 | void DzFbxImporter::setStudioNodeNamesLabels( bool enable )
1086 | {
1087 | m_studioNodeNamesLabels = enable;
1088 | }
1089 |
1090 | /**
1091 | **/
1092 | void DzFbxImporter::setStudioNodePresentation( bool enable )
1093 | {
1094 | m_studioNodePresentation = enable;
1095 | }
1096 |
1097 | /**
1098 | **/
1099 | void DzFbxImporter::setStudioNodeSelectionMap( bool enable )
1100 | {
1101 | m_studioNodeSelectionMap = enable;
1102 | }
1103 |
1104 | /**
1105 | **/
1106 | void DzFbxImporter::setStudioSceneIDs( bool enable )
1107 | {
1108 | m_studioSceneIDs = enable;
1109 | }
1110 |
1111 | /**
1112 | **/
1113 | QStringList DzFbxImporter::getErrorList() const
1114 | {
1115 | return m_errorList;
1116 | }
1117 |
1118 | /**
1119 | **/
1120 | void DzFbxImporter::replicateSkeleton( DzSkeleton* dsBaseSkeleton, const Skinning &skinning )
1121 | {
1122 | Node* node = skinning.node;
1123 | DzSkeleton* dsSkeleton = qobject_cast( node->dsNode );
1124 | if ( !dsSkeleton )
1125 | {
1126 | return;
1127 | }
1128 |
1129 | const Node* baseNode = m_root->find( dsBaseSkeleton );
1130 |
1131 | for ( int i = 0, n = baseNode->children.count(); i < n; i++ )
1132 | {
1133 | const Node* baseChild = baseNode->children.at( i );
1134 | const FbxNodeAttribute* fbxBaseNodeAttr = baseChild->fbxNode->GetNodeAttribute();
1135 | if ( fbxBaseNodeAttr && fbxBaseNodeAttr->GetAttributeType() == FbxNodeAttribute::eMesh )
1136 | {
1137 | continue;
1138 | }
1139 |
1140 | Node* child = new Node();
1141 | child->setParent( node );
1142 | child->fbxNode = baseChild->fbxNode;
1143 | child->dsParent = node->dsNode;
1144 |
1145 | fbxImportGraph( child );
1146 | }
1147 |
1148 | dsSkeleton->setFollowTarget( dsBaseSkeleton );
1149 | }
1150 |
1151 | static DzVec3 toVec3( FbxVector4 v )
1152 | {
1153 | DzVec3 r;
1154 | r.m_x = v[0];
1155 | r.m_y = v[1];
1156 | r.m_z = v[2];
1157 | r.m_w = v[3];
1158 | return r;
1159 | }
1160 |
1161 | static FbxVector4 calcFbxRotationOffset( FbxNode* fbxNode )
1162 | {
1163 | FbxVector4 offset( 0, 0, 0 );
1164 | while ( fbxNode )
1165 | {
1166 | bool applyOffset = true;
1167 |
1168 | if ( fbxNode->GetNodeAttribute()
1169 | && fbxNode->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eMesh )
1170 | {
1171 | applyOffset = false;
1172 | }
1173 |
1174 | if ( applyOffset )
1175 | {
1176 | offset += fbxNode->GetRotationOffset( FbxNode::eSourcePivot );
1177 | }
1178 |
1179 | fbxNode = fbxNode->GetParent();
1180 | }
1181 | offset[3] = 1;
1182 | return offset;
1183 | }
1184 |
1185 | static void setNodeOrientation( DzNode* dsNode, FbxNode* fbxNode )
1186 | {
1187 | FbxVector4 fbxPre = fbxNode->GetPreRotation( FbxNode::eSourcePivot );
1188 | const DzQuat rot( DzRotationOrder::XYZ, DzVec3( fbxPre[0], fbxPre[1], fbxPre[2] ) * DZ_FLT_DEG_TO_RAD );
1189 |
1190 | dsNode->setOrientation( rot, true );
1191 | }
1192 |
1193 | static void setNodeRotationOrder( DzNode* dsNode, FbxNode* fbxNode )
1194 | {
1195 | DzRotationOrder dsRotationOrder( DzRotationOrder::XYZ );
1196 | EFbxRotationOrder fbxRotationOrder( eEulerXYZ );
1197 |
1198 | fbxNode->GetRotationOrder( FbxNode::eSourcePivot, fbxRotationOrder );
1199 | switch ( fbxRotationOrder )
1200 | {
1201 | case eEulerXYZ:
1202 | dsRotationOrder = DzRotationOrder::XYZ;
1203 | break;
1204 | case eEulerXZY:
1205 | dsRotationOrder = DzRotationOrder::XZY;
1206 | break;
1207 | case eEulerYXZ:
1208 | dsRotationOrder = DzRotationOrder::YXZ;
1209 | break;
1210 | case eEulerYZX:
1211 | dsRotationOrder = DzRotationOrder::YZX;
1212 | break;
1213 | case eEulerZXY:
1214 | dsRotationOrder = DzRotationOrder::ZXY;
1215 | break;
1216 | case eEulerZYX:
1217 | dsRotationOrder = DzRotationOrder::ZYX;
1218 | break;
1219 | default:
1220 | break;
1221 | }
1222 |
1223 | dsNode->setRotationOrder( dsRotationOrder );
1224 | }
1225 |
1226 | static void setNodeRotation( DzNode* dsNode, FbxNode* fbxNode )
1227 | {
1228 | const FbxDouble3 lclRotation = fbxNode->LclRotation.Get();
1229 |
1230 | //dsNode->getXRotControl()->setDefaultValue( lclRotation[0] );
1231 | //dsNode->getYRotControl()->setDefaultValue( lclRotation[1] );
1232 | //dsNode->getZRotControl()->setDefaultValue( lclRotation[2] );
1233 | dsNode->getXRotControl()->setValue( lclRotation[0] );
1234 | dsNode->getYRotControl()->setValue( lclRotation[1] );
1235 | dsNode->getZRotControl()->setValue( lclRotation[2] );
1236 | }
1237 |
1238 | static void setNodeRotationLimits( DzNode* dsNode, FbxNode* fbxNode )
1239 | {
1240 | const FbxLimits rotationLimits = fbxNode->GetRotationLimits();
1241 | if ( !rotationLimits.GetActive() )
1242 | {
1243 | return;
1244 | }
1245 |
1246 | const FbxDouble3 min = rotationLimits.GetMin();
1247 | const FbxDouble3 max = rotationLimits.GetMax();
1248 |
1249 | if ( rotationLimits.GetMaxXActive()
1250 | && rotationLimits.GetMinXActive() )
1251 | {
1252 | dsNode->getXRotControl()->setIsClamped( true );
1253 | dsNode->getXRotControl()->setMinMax( min[0], max[0] );
1254 | }
1255 |
1256 | if ( rotationLimits.GetMaxYActive()
1257 | && rotationLimits.GetMinYActive() )
1258 | {
1259 | dsNode->getYRotControl()->setIsClamped( true );
1260 | dsNode->getYRotControl()->setMinMax( min[1], max[1] );
1261 | }
1262 |
1263 | if ( rotationLimits.GetMaxZActive()
1264 | && rotationLimits.GetMinZActive() )
1265 | {
1266 | dsNode->getZRotControl()->setIsClamped( true );
1267 | dsNode->getZRotControl()->setMinMax( min[2], max[2] );
1268 | }
1269 | }
1270 |
1271 | static void setNodeTranslation( DzNode* dsNode, FbxNode* fbxNode, DzVec3 translationOffset )
1272 | {
1273 | const FbxDouble3 translation = fbxNode->LclTranslation.Get();
1274 |
1275 | const float posX = translation[0] - translationOffset[0];
1276 | const float posY = translation[1] - translationOffset[1];
1277 | const float posZ = translation[2] - translationOffset[2];
1278 |
1279 | //dsNode->getXPosControl()->setDefaultValue( posX );
1280 | //dsNode->getYPosControl()->setDefaultValue( posY );
1281 | //dsNode->getZPosControl()->setDefaultValue( posZ );
1282 | dsNode->getXPosControl()->setValue( posX );
1283 | dsNode->getYPosControl()->setValue( posY );
1284 | dsNode->getZPosControl()->setValue( posZ );
1285 | }
1286 |
1287 | static void setNodeInheritsScale( DzNode* dsNode, FbxNode* fbxNode )
1288 | {
1289 | FbxTransform::EInheritType inheritType;
1290 | fbxNode->GetTransformationInheritType( inheritType );
1291 | dsNode->setInheritScale( inheritType != FbxTransform::eInheritRrs );
1292 | }
1293 |
1294 | static void setNodeScaling( DzNode* dsNode, FbxNode* fbxNode )
1295 | {
1296 | const FbxDouble3 scaling = fbxNode->LclScaling.Get();
1297 |
1298 | //dsNode->getXScaleControl()->setDefaultValue( scaling[0] );
1299 | //dsNode->getYScaleControl()->setDefaultValue( scaling[1] );
1300 | //dsNode->getZScaleControl()->setDefaultValue( scaling[2] );
1301 | dsNode->getXScaleControl()->setValue( scaling[0] );
1302 | dsNode->getYScaleControl()->setValue( scaling[1] );
1303 | dsNode->getZScaleControl()->setValue( scaling[2] );
1304 | }
1305 |
1306 | static void setNodeSceneID( DzNode* dsNode, FbxNode* fbxNode )
1307 | {
1308 | QString dsSceneId;
1309 |
1310 | #if FBXSDK_VERSION_MAJOR >= 2016
1311 | const FbxProperty fbxSceneIdProperty = fbxNode->FindProperty( "StudioSceneID" );
1312 | if ( fbxSceneIdProperty.IsValid() )
1313 | {
1314 | dsSceneId = QString( fbxSceneIdProperty.Get() );
1315 | }
1316 | #endif
1317 |
1318 | if ( dsSceneId.isEmpty() )
1319 | {
1320 | return;
1321 | }
1322 |
1323 | const DzUri nodeUri( dsSceneId );
1324 | if ( nodeUri.getFilePath().isEmpty() )
1325 | {
1326 | return;
1327 | }
1328 |
1329 | dsNode->modifyAsset( nodeUri ); //cause assetUri to be set
1330 | dsNode->modifyAsset(); //cause assetUri to become the source and mark as modified
1331 | }
1332 |
1333 | static void setNodePresentation( DzNode* dsNode, FbxNode* fbxNode )
1334 | {
1335 | QString presentationType;
1336 | QString autoFitBase;
1337 | QString preferredBase;
1338 |
1339 | #if FBXSDK_VERSION_MAJOR >= 2016
1340 | const FbxProperty fbxPresentationTypeProperty = fbxNode->FindProperty( "StudioPresentationType" );
1341 | if ( fbxPresentationTypeProperty.IsValid() )
1342 | {
1343 | presentationType = QString( fbxPresentationTypeProperty.Get() );
1344 | }
1345 |
1346 | const FbxProperty fbxPresentationAutoFitBaseProperty = fbxNode->FindProperty( "StudioPresentationAutoFitBase" );
1347 | if ( fbxPresentationAutoFitBaseProperty.IsValid() )
1348 | {
1349 | autoFitBase = QString( fbxPresentationAutoFitBaseProperty.Get() );
1350 | }
1351 |
1352 | const FbxProperty fbxPresentationPreferredBaseProperty = fbxNode->FindProperty( "StudioPresentationPreferredBase" );
1353 | if ( fbxPresentationPreferredBaseProperty.IsValid() )
1354 | {
1355 | preferredBase = QString( fbxPresentationPreferredBaseProperty.Get() );
1356 | }
1357 | #endif
1358 |
1359 | if ( presentationType.isEmpty()
1360 | && autoFitBase.isEmpty()
1361 | && preferredBase.isEmpty() )
1362 | {
1363 | return;
1364 | }
1365 |
1366 | DzPresentation* presentation = dsNode->getPresentation();
1367 | if ( !presentation )
1368 | {
1369 | presentation = new DzPresentation();
1370 | dsNode->setPresentation( presentation );
1371 | }
1372 |
1373 | if ( !presentationType.isEmpty() )
1374 | {
1375 | presentation->setType( presentationType );
1376 | }
1377 |
1378 | if ( !autoFitBase.isEmpty() )
1379 | {
1380 | #if DZ_SDK_4_12_OR_GREATER
1381 | presentation->setAutoFitBase( autoFitBase );
1382 | #else
1383 | // DzPresentation::setAutoFitBase() is not in the 4.5 SDK, so we attempt
1384 | // to use the meta-object to access/set the DzPresentation::autoFitBase
1385 | // property - since 4.5.2.13.
1386 |
1387 | presentation->setProperty( "autoFitBase", autoFitBase );
1388 | #endif //DZ_SDK_4_12_OR_GREATER
1389 | }
1390 |
1391 | if ( !preferredBase.isEmpty() )
1392 | {
1393 | #if DZ_SDK_4_12_OR_GREATER
1394 | presentation->setPreferredBase( preferredBase );
1395 | #else
1396 | // DzPresentation::setPreferredBase() is not in the 4.5 SDK, so we attempt
1397 | // to use the meta-object to access/set the DzPresentation::preferredBase
1398 | // property - since 4.5.2.13.
1399 |
1400 | presentation->setProperty( "preferredBase", preferredBase );
1401 | #endif //DZ_SDK_4_12_OR_GREATER
1402 | }
1403 | }
1404 |
1405 | static bool isFuzzyClose( double a, double b, double c )
1406 | {
1407 | if ( qAbs( a - b ) > 0.0000000001f
1408 | || qAbs( a - c ) > 0.0000000001f )
1409 | {
1410 | return false;
1411 | }
1412 |
1413 | return true;
1414 | }
1415 |
1416 | /**
1417 | **/
1418 | void DzFbxImporter::fbxPreImportAnimationStack()
1419 | {
1420 | for ( int i = 0, n = m_fbxScene->GetSrcObjectCount(); i < n; i++ )
1421 | {
1422 | const FbxAnimStack* animStack = m_fbxScene->GetSrcObject( i );
1423 |
1424 | const QString stackName( animStack->GetName() );
1425 |
1426 | const int numLayers = animStack->GetMemberCount();
1427 | if ( numLayers == 0 )
1428 | {
1429 | m_errorList << "Animation: \"" % stackName % "\" has no layers.";
1430 | }
1431 | else if ( numLayers > 1 )
1432 | {
1433 | m_errorList << "Animation: \"" % stackName % "\" has multiple layers.";
1434 | }
1435 |
1436 | m_animStackNames.push_back( stackName );
1437 | }
1438 | }
1439 |
1440 | /**
1441 | **/
1442 | void DzFbxImporter::fbxPreImportGraph( FbxNode* fbxNode )
1443 | {
1444 | const QString nodeName( fbxNode->GetName() );
1445 |
1446 | if ( !m_suppressRigErrors )
1447 | {
1448 | // pre (Joint Orient)/post (Rotate Axis) rotation must match
1449 | if ( fbxNode->GetPreRotation( FbxNode::eSourcePivot ) != fbxNode->GetPostRotation( FbxNode::eSourcePivot ) )
1450 | {
1451 | m_errorList << "Rigging: Pre/Post rotation mismatch: " % nodeName;
1452 | }
1453 |
1454 | // scale must be uniform
1455 | FbxDouble3 fbxScaling = fbxNode->LclScaling.Get();
1456 | if ( !isFuzzyClose( fbxScaling[0], fbxScaling[1], fbxScaling[2] ) )
1457 | {
1458 | m_errorList << "Rigging: Non-uniform scale: " % nodeName;
1459 | }
1460 |
1461 | // mesh
1462 | if ( const FbxMesh* fbxMesh = fbxNode->GetMesh() )
1463 | {
1464 | // we are only concerned with skinning at the moment
1465 | const int numSkins = fbxMesh->GetDeformerCount( FbxDeformer::eSkin );
1466 | for ( int i = 0; i < numSkins; i++ )
1467 | {
1468 | // skinning weights must be linked to a bone
1469 |
1470 | FbxSkin* fbxSkin = FbxCast( fbxMesh->GetDeformer( i ) );
1471 | for ( int j = 0, m = fbxSkin->GetClusterCount(); j < m; j++ )
1472 | {
1473 | FbxNode* fbxClusterNode = fbxSkin->GetCluster( j )->GetLink();
1474 | if ( fbxClusterNode && fbxClusterNode->GetSkeleton() )
1475 | {
1476 | continue;
1477 | }
1478 |
1479 | m_errorList << "Rigging: Cluster linked to non-bone: " % QString( fbxClusterNode->GetName() );
1480 | }
1481 | }
1482 | }
1483 |
1484 | // "bone chains"
1485 | if ( const FbxSkeleton* fbxSkeleton = fbxNode->GetSkeleton() )
1486 | {
1487 | // a "bone chain" must ultimately start with a "root"; if the 'current'
1488 | // skeleton node is not the root, it should have a parent that is
1489 |
1490 | const char* skelTypes[] = { "Root", "Limb", "Limb Node", "Effector" };
1491 |
1492 | FbxSkeleton::EType skelType = fbxSkeleton->GetSkeletonType();
1493 | switch ( skelType )
1494 | {
1495 | default:
1496 | case FbxSkeleton::eRoot:
1497 | break;
1498 | case FbxSkeleton::eLimb:
1499 | case FbxSkeleton::eLimbNode:
1500 | case FbxSkeleton::eEffector:
1501 | {
1502 | FbxNode* fbxParentNode = fbxNode->GetParent();
1503 | if ( !fbxParentNode
1504 | || !fbxParentNode->GetSkeleton() )
1505 | {
1506 | m_errorList << "Rigging: Bone chain type incorrect - " % QString( skelTypes[skelType] ) % ": " % nodeName;
1507 | }
1508 | }
1509 | break;
1510 | }
1511 | }
1512 | }
1513 |
1514 | for ( int i = 0, n = fbxNode->GetChildCount(); i < n; i++ )
1515 | {
1516 | fbxPreImportGraph( fbxNode->GetChild( i ) );
1517 | }
1518 | }
1519 |
1520 | /**
1521 | **/
1522 | void DzFbxImporter::fbxPreImport()
1523 | {
1524 | fbxPreImportAnimationStack();
1525 |
1526 | FbxNode* fbxRootNode = m_fbxScene->GetRootNode();
1527 | for ( int i = 0, n = fbxRootNode->GetChildCount(); i < n; i++ )
1528 | {
1529 | fbxPreImportGraph( fbxRootNode->GetChild( i ) );
1530 | }
1531 | }
1532 |
1533 | /**
1534 | **/
1535 | void DzFbxImporter::fbxImportGraph( Node* node )
1536 | {
1537 | if ( node == m_root )
1538 | {
1539 | for ( int i = 0; i < node->fbxNode->GetChildCount(); i++ )
1540 | {
1541 | Node* child = new Node();
1542 | child->setParent( node );
1543 | child->fbxNode = node->fbxNode->GetChild( i );
1544 | }
1545 |
1546 | for ( int i = 0; i < node->children.count(); i++ )
1547 | {
1548 | fbxImportGraph( node->children[i] );
1549 | }
1550 |
1551 | return;
1552 | }
1553 |
1554 | DzNode* dsMeshNode = NULL;
1555 |
1556 | const FbxNull* fbxNull = node->fbxNode->GetNull();
1557 | if ( fbxNull || !node->fbxNode->GetNodeAttribute() )
1558 | {
1559 | node->dsNode = new DzNode();
1560 | }
1561 | else
1562 | {
1563 | switch ( node->fbxNode->GetNodeAttribute()->GetAttributeType() )
1564 | {
1565 | case FbxNodeAttribute::eMarker:
1566 | break;
1567 | case FbxNodeAttribute::eSkeleton:
1568 | {
1569 | const FbxSkeleton* fbxSkeleton = node->fbxNode->GetSkeleton();
1570 | switch ( fbxSkeleton->GetSkeletonType() )
1571 | {
1572 | case FbxSkeleton::eRoot:
1573 | node->dsNode = createFigure();
1574 | break;
1575 | case FbxSkeleton::eLimb: //intentional fall-through
1576 | case FbxSkeleton::eLimbNode:
1577 | {
1578 | node->dsNode = new DzBone();
1579 | node->dsNode->setInheritScale( true );
1580 |
1581 | #if FBXSDK_VERSION_MAJOR >= 2016
1582 | FbxProperty fbxPropertyFaceGroup;
1583 | if ( m_studioNodeSelectionMap )
1584 | {
1585 | fbxPropertyFaceGroup = node->fbxNode->FindProperty( "StudioNodeFaceGroup" );
1586 | }
1587 |
1588 | if ( fbxPropertyFaceGroup.IsValid() )
1589 | {
1590 | const QString selectionSetName( fbxPropertyFaceGroup.Get() );
1591 | m_nodeFaceGroupMap.insert( node, selectionSetName );
1592 | }
1593 | #endif
1594 | }
1595 | break;
1596 | case FbxSkeleton::eEffector:
1597 | break;
1598 | }
1599 | }
1600 | break;
1601 | case FbxNodeAttribute::eMesh:
1602 | {
1603 | const QString fbxNodeName( node->fbxNode->GetName() );
1604 | if ( node->dsParent &&
1605 | !node->dsParent->getObject() &&
1606 | ( node->dsParent->getName() + ".Shape" == fbxNodeName ||
1607 | node->dsParent->getName() + "_Shape" == fbxNodeName ) )
1608 | {
1609 | dsMeshNode = node->dsParent;
1610 | }
1611 | else
1612 | {
1613 | const FbxMesh* fbxMesh = node->fbxNode->GetMesh();
1614 | if ( fbxMesh->GetDeformerCount( FbxDeformer::eSkin ) > 0 )
1615 | {
1616 | node->dsNode = createFigure();
1617 | node->collapseTranslation = true;
1618 | }
1619 | else
1620 | {
1621 | node->dsNode = new DzNode();
1622 | }
1623 |
1624 | dsMeshNode = node->dsNode;
1625 | }
1626 |
1627 | fbxImportMesh( node, node->fbxNode, dsMeshNode );
1628 | }
1629 | break;
1630 | case FbxNodeAttribute::eNurbs:
1631 | break;
1632 | case FbxNodeAttribute::ePatch:
1633 | break;
1634 | case FbxNodeAttribute::eCamera:
1635 | break;
1636 | case FbxNodeAttribute::eLight:
1637 | break;
1638 | case FbxNodeAttribute::eLODGroup:
1639 | break;
1640 | default:
1641 | FbxNodeAttribute::EType type = node->fbxNode->GetNodeAttribute()->GetAttributeType();
1642 | break;
1643 | }
1644 | }
1645 |
1646 | if ( node->dsNode )
1647 | {
1648 | m_nodeMap[node->fbxNode] = node->dsNode;
1649 |
1650 | QString nodeName( node->fbxNode->GetName() );
1651 | #if FBXSDK_VERSION_MAJOR >= 2016
1652 | FbxProperty fbxPropertyNodeName;
1653 | if ( m_studioNodeNamesLabels )
1654 | {
1655 | fbxPropertyNodeName = node->fbxNode->FindProperty( "StudioNodeName" );
1656 | }
1657 |
1658 | if ( fbxPropertyNodeName.IsValid() )
1659 | {
1660 | nodeName = fbxPropertyNodeName.Get();
1661 | }
1662 | #endif
1663 | node->dsNode->setName( nodeName );
1664 |
1665 | if ( node->dsParent )
1666 | {
1667 | node->dsParent->addNodeChild( node->dsNode );
1668 | }
1669 |
1670 | #if FBXSDK_VERSION_MAJOR >= 2016
1671 | FbxProperty fbxPropertyNodeLabel;
1672 | if ( m_studioNodeNamesLabels )
1673 | {
1674 | fbxPropertyNodeLabel = node->fbxNode->FindProperty( "StudioNodeLabel" );
1675 | }
1676 |
1677 | if ( fbxPropertyNodeLabel.IsValid() )
1678 | {
1679 | const QString nodeLabel( fbxPropertyNodeLabel.Get());
1680 | node->dsNode->setLabel( dzScene->getUniqueTopLevelLabel( nodeLabel ) );
1681 | }
1682 | #endif
1683 |
1684 | if ( m_studioNodePresentation )
1685 | {
1686 | setNodePresentation( node->dsNode, node->fbxNode );
1687 | }
1688 |
1689 | setNodeInheritsScale( node->dsNode, node->fbxNode );
1690 |
1691 | const FbxVector4 rotationOffset = calcFbxRotationOffset( node->fbxNode );
1692 | node->dsNode->setOrigin( toVec3( rotationOffset ), true );
1693 | setNodeOrientation( node->dsNode, node->fbxNode );
1694 | setNodeRotationOrder( node->dsNode, node->fbxNode );
1695 |
1696 | if ( rotationOffset.SquareLength() == 0.0 )
1697 | {
1698 | bool found = false;
1699 | FbxMatrix fbxMatrix;
1700 |
1701 | for ( int i = 0; i < m_fbxScene->GetPoseCount(); i++ )
1702 | {
1703 | const FbxPose* pose = m_fbxScene->GetPose( i );
1704 | if ( pose->IsBindPose() )
1705 | {
1706 | for ( int j = 0; j < pose->GetCount(); j++ )
1707 | {
1708 | if ( pose->GetNode( j ) == node->fbxNode )
1709 | {
1710 | found = true;
1711 | fbxMatrix = pose->GetMatrix( j );
1712 | }
1713 | }
1714 | }
1715 | }
1716 |
1717 | if ( !found )
1718 | {
1719 | fbxMatrix = node->fbxNode->EvaluateGlobalTransform();
1720 | }
1721 |
1722 | node->bindTranslation[0] = fbxMatrix[3][0];
1723 | node->bindTranslation[1] = fbxMatrix[3][1];
1724 | node->bindTranslation[2] = fbxMatrix[3][2];
1725 | if ( !node->collapseTranslation )
1726 | {
1727 | node->dsNode->setOrigin( node->bindTranslation, true );
1728 | }
1729 | }
1730 |
1731 | if ( node->collapseTranslation && dsMeshNode )
1732 | {
1733 | DzFacetMesh* dsFacetMesh = qobject_cast( dsMeshNode->getObject()->getCurrentShape()->getGeometry() );
1734 | if ( dsFacetMesh )
1735 | {
1736 | DzPnt3* vertices = dsFacetMesh->getVerticesPtr();
1737 | for ( int i = 0; i < dsFacetMesh->getNumVertices(); i++ )
1738 | {
1739 | vertices[i][0] += node->bindTranslation[0];
1740 | vertices[i][1] += node->bindTranslation[1];
1741 | vertices[i][2] += node->bindTranslation[2];
1742 | }
1743 | }
1744 | }
1745 |
1746 | dzScene->addNode( node->dsNode );
1747 |
1748 | #if DZ_SDK_4_12_OR_GREATER
1749 | addImportedNode( node->dsNode );
1750 | #endif
1751 |
1752 | for ( int i = 0; i < node->fbxNode->GetChildCount(); i++ )
1753 | {
1754 | Node* child = new Node();
1755 | child->setParent( node );
1756 | child->dsParent = node->dsNode;
1757 | child->fbxNode = node->fbxNode->GetChild( i );
1758 | }
1759 |
1760 | for ( int i = 0; i < node->children.count(); i++ )
1761 | {
1762 | fbxImportGraph( node->children[i] );
1763 | }
1764 |
1765 | DzVec3 endPoint = node->dsNode->getOrigin();
1766 | if ( node->dsNode->getNumNodeChildren() )
1767 | {
1768 | endPoint = node->dsNode->getNodeChild( 0 )->getOrigin( true );
1769 | for ( int i = 1; i < node->dsNode->getNumNodeChildren(); i++ )
1770 | {
1771 | endPoint += node->dsNode->getNodeChild( i )->getOrigin( true );
1772 | }
1773 | endPoint.m_x /= node->dsNode->getNumNodeChildren();
1774 | endPoint.m_y /= node->dsNode->getNumNodeChildren();
1775 | endPoint.m_z /= node->dsNode->getNumNodeChildren();
1776 | node->dsNode->setEndPoint( endPoint, true );
1777 | }
1778 | else
1779 | {
1780 | DzVec3 toCenter = endPoint;
1781 | if ( node->dsNode->getNodeParent() )
1782 | {
1783 | toCenter -= node->dsNode->getNodeParent()->getOrigin();
1784 | toCenter = ( node->dsNode->getNodeParent()->getOrientation().inverse() * node->dsNode->getOrientation() ).multVec( toCenter );
1785 | if ( toCenter.length() > 1 )
1786 | {
1787 | toCenter /= 2.0;
1788 | }
1789 | }
1790 | node->dsNode->setEndPoint( endPoint + toCenter, true );
1791 | }
1792 |
1793 | // setup a decent guess so IK will work
1794 | if ( qobject_cast( node->dsNode ) &&
1795 | qobject_cast( node->dsParent ) &&
1796 | node->dsNode->getNumNodeChildren() != 0 )
1797 | {
1798 | node->dsNode->getXPosControl()->setHidden( true );
1799 | node->dsNode->getYPosControl()->setHidden( true );
1800 | node->dsNode->getZPosControl()->setHidden( true );
1801 | }
1802 |
1803 | if ( m_includeRotationLimits )
1804 | {
1805 | setNodeRotationLimits( node->dsNode, node->fbxNode );
1806 | }
1807 |
1808 | if ( m_studioSceneIDs )
1809 | {
1810 | setNodeSceneID( node->dsNode, node->fbxNode );
1811 | }
1812 | }
1813 | }
1814 |
1815 | /**
1816 | **/
1817 | void DzFbxImporter::fbxImportAnimation( Node* node )
1818 | {
1819 | if ( node->dsNode )
1820 | {
1821 | if ( !node->collapseTranslation )
1822 | {
1823 | DzVec3 translationOffset = node->bindTranslation;
1824 | if ( node->parent )
1825 | {
1826 | translationOffset -= node->parent->bindTranslation;
1827 | }
1828 |
1829 | setNodeTranslation( node->dsNode, node->fbxNode, translationOffset );
1830 | setNodeRotation( node->dsNode, node->fbxNode );
1831 |
1832 | setNodeScaling( node->dsNode, node->fbxNode );
1833 | }
1834 |
1835 | if ( m_fbxAnimLayer && !node->collapseTranslation )
1836 | {
1837 | applyFbxCurve( node->fbxNode->LclTranslation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_X ), node->dsNode->getXPosControl() );
1838 | applyFbxCurve( node->fbxNode->LclTranslation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y ), node->dsNode->getYPosControl() );
1839 | applyFbxCurve( node->fbxNode->LclTranslation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z ), node->dsNode->getZPosControl() );
1840 |
1841 | applyFbxCurve( node->fbxNode->LclRotation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_X ), node->dsNode->getXRotControl() );
1842 | applyFbxCurve( node->fbxNode->LclRotation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y ), node->dsNode->getYRotControl() );
1843 | applyFbxCurve( node->fbxNode->LclRotation.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z ), node->dsNode->getZRotControl() );
1844 |
1845 | applyFbxCurve( node->fbxNode->LclScaling.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_X ), node->dsNode->getXScaleControl() );
1846 | applyFbxCurve( node->fbxNode->LclScaling.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y ), node->dsNode->getYScaleControl() );
1847 | applyFbxCurve( node->fbxNode->LclScaling.GetCurve( m_fbxAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z ), node->dsNode->getZScaleControl() );
1848 | }
1849 |
1850 |
1851 | #if FBXSDK_VERSION_MAJOR >= 2016
1852 | for ( FbxProperty fbxProperty = node->fbxNode->GetFirstProperty(); fbxProperty.IsValid(); fbxProperty = node->fbxNode->GetNextProperty( fbxProperty ) )
1853 | {
1854 | if ( !fbxProperty.GetFlag( FbxPropertyFlags::eUserDefined ) )
1855 | {
1856 | continue;
1857 | }
1858 |
1859 | if ( node->dsNode->findDataItem( DATA_FBX_USER_PROPERTIES ) == NULL )
1860 | {
1861 | node->dsNode->addDataItem( new DzSimpleElementData( DATA_FBX_USER_PROPERTIES, true ) );
1862 | }
1863 |
1864 | const QString key( fbxProperty.GetName() );
1865 | DzSimpleElementData* userPropertyData = qobject_cast( node->dsNode->findDataItem( DATA_FBX_USER_PROPERTIES ) );
1866 | DzSettings* userSettings = userPropertyData->getSettings();
1867 |
1868 | FbxDataType fbxPropertyData = fbxProperty.GetPropertyDataType();
1869 | switch ( fbxPropertyData.GetType() )
1870 | {
1871 | case eFbxInt:
1872 | userSettings->setIntValue( key, fbxProperty.Get() );
1873 | break;
1874 | case eFbxBool:
1875 | userSettings->setBoolValue( key, fbxProperty.Get() );
1876 | break;
1877 | case eFbxFloat:
1878 | userSettings->setFloatValue( key, fbxProperty.Get() );
1879 | break;
1880 | case eFbxDouble:
1881 | userSettings->setFloatValue( key, fbxProperty.Get() );
1882 | break;
1883 | case eFbxString:
1884 | userSettings->setStringValue( key, QString( fbxProperty.Get() ) );
1885 | break;
1886 | default:
1887 | break;
1888 | }
1889 | }
1890 | #endif
1891 | }
1892 |
1893 | for ( int i = 0; i < node->children.count(); i++ )
1894 | {
1895 | fbxImportAnimation( node->children[i] );
1896 | }
1897 | }
1898 |
1899 |
1900 | static QColor toQColor( FbxPropertyT fbxValue )
1901 | {
1902 | QColor clr;
1903 |
1904 | clr.setRedF( fbxValue.Get()[0] );
1905 | clr.setGreenF( fbxValue.Get()[1] );
1906 | clr.setBlueF( fbxValue.Get()[2] );
1907 |
1908 | return clr;
1909 | }
1910 |
1911 | /**
1912 | **/
1913 | DzTexture* DzFbxImporter::toTexture( FbxProperty fbxProperty )
1914 | {
1915 | for ( int i = 0; i < fbxProperty.GetSrcObjectCount(); ++i )
1916 | {
1917 | const FbxFileTexture* fbxFileTexture = fbxProperty.GetSrcObject( i );
1918 | const DzImageMgr* imgMgr = dzApp->getImageMgr();
1919 | DzTexture* dsTexture = imgMgr->getImage( fbxFileTexture->GetFileName() );
1920 | if ( !dsTexture )
1921 | {
1922 | dsTexture = imgMgr->getImage( m_folder.filePath( fbxFileTexture->GetFileName() ) );
1923 | }
1924 |
1925 | return dsTexture;
1926 | }
1927 |
1928 | return 0;
1929 | }
1930 |
1931 | /**
1932 | **/
1933 | void DzFbxImporter::fbxImportVertices( int numVertices, FbxVector4* fbxVertices, DzFacetMesh* dsMesh, DzVec3 offset )
1934 | {
1935 | DzPnt3* dsVertices = dsMesh->setVertexArray( numVertices );
1936 | for ( int i = 0; i < numVertices; i++ )
1937 | {
1938 | dsVertices[i][0] = fbxVertices[i][0] + offset[0];
1939 | dsVertices[i][1] = fbxVertices[i][1] + offset[1];
1940 | dsVertices[i][2] = fbxVertices[i][2] + offset[2];
1941 | }
1942 | }
1943 |
1944 | /**
1945 | **/
1946 | void DzFbxImporter::fbxImportUVs( FbxMesh* fbxMesh, DzFacetMesh* dsMesh )
1947 | {
1948 | for ( int i = 0, n = fbxMesh->GetElementUVCount(); i < n; i++ )
1949 | {
1950 | const FbxGeometryElementUV* fbxGeomUv = fbxMesh->GetElementUV( i );
1951 | const int numUvs = fbxGeomUv->GetDirectArray().GetCount();
1952 |
1953 | DzMap* dsUvMap = dsMesh->getUVs();
1954 | dsUvMap->setNumValues( numUvs );
1955 | DzPnt2* dsUVs = dsUvMap->getPnt2ArrayPtr();
1956 |
1957 | for ( int j = 0; j < numUvs; j++ )
1958 | {
1959 | const FbxVector2 fbxUv = fbxGeomUv->GetDirectArray().GetAt( j );
1960 | dsUVs[j][0] = fbxUv[0];
1961 | dsUVs[j][1] = fbxUv[1];
1962 | }
1963 |
1964 | // only do the first
1965 | break;
1966 | }
1967 | }
1968 |
1969 | /**
1970 | **/
1971 | void DzFbxImporter::fbxImportSubdVertexWeights( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, bool &enableSubd )
1972 | {
1973 | for ( int i = 0, n = fbxMesh->GetElementVertexCreaseCount(); i < n; i++ )
1974 | {
1975 | const FbxGeometryElementCrease* fbxSubdVertexCrease = fbxMesh->GetElementVertexCrease( i );
1976 | for ( int j = 0, m = fbxSubdVertexCrease->GetDirectArray().GetCount(); j < m; j++ )
1977 | {
1978 | const double weight = fbxSubdVertexCrease->GetDirectArray().GetAt( j );
1979 | if ( weight > 0 )
1980 | {
1981 | enableSubd = true;
1982 |
1983 | #if DZ_SDK_4_12_OR_GREATER
1984 | dsMesh->setVertexWeight( j, weight );
1985 | #else
1986 | // DzFacetMesh::setVertexWeight() is not in the 4.5 SDK, so we
1987 | // attempt to use the meta-object to call the method.
1988 |
1989 | bool im = QMetaObject::invokeMethod( dsMesh, "setVertexWeight",
1990 | Q_ARG( int, j ), Q_ARG( int, weight ) );
1991 | assert( im );
1992 | #endif
1993 | }
1994 | }
1995 |
1996 | // only do the first
1997 | break;
1998 | }
1999 | }
2000 |
2001 | /**
2002 | **/
2003 | void DzFbxImporter::fbxImportMaterials( FbxNode* fbxNode, FbxMesh* fbxMesh, DzFacetMesh* dsMesh, DzFacetShape* dsShape, bool &matsAllSame )
2004 | {
2005 | for ( int i = 0, n = fbxNode->GetMaterialCount(); i < n; i++ )
2006 | {
2007 | QColor diffuseColor = Qt::white;
2008 | DzTexturePtr diffuseMap = NULL;
2009 |
2010 | float diffuseFactor = 1.0f;
2011 |
2012 | float opacityBase = 1.0f;
2013 | DzTexturePtr opacityMap = NULL;
2014 |
2015 | QColor ambientColor = Qt::black;
2016 | DzTexturePtr ambientMap = NULL;
2017 |
2018 | float ambientFactor = 1.0f;
2019 |
2020 | QColor specularColor = Qt::white;
2021 | DzTexturePtr specularMap = NULL;
2022 |
2023 | float specularFactor = 1.0f;
2024 |
2025 | float shininess = 1.0f;
2026 | DzTexturePtr shininessMap = NULL;
2027 |
2028 | float reflectionFactor = 1.0f;
2029 | DzTexturePtr reflectionMap = NULL;
2030 |
2031 | float roughness = 0.1f;
2032 | float metallicity = 1.0f;
2033 |
2034 | FbxSurfaceMaterial* fbxMaterial = fbxNode->GetMaterial( i );
2035 | DzMaterialPtr dsMaterial = NULL;
2036 |
2037 | const DzClassFactory* pbrMatFactory = dzApp->findClassFactory( "DzPbrMaterial" ); //or "DzUberIrayMaterial"
2038 | if ( QObject* pbrMatInstance = pbrMatFactory ? pbrMatFactory->createInstance() : NULL )
2039 | {
2040 | dsMaterial = qobject_cast( pbrMatInstance );
2041 | }
2042 | else
2043 | {
2044 | dsMaterial = new DzDefaultMaterial();
2045 | }
2046 |
2047 | DzDefaultMaterial* dsDefMaterial = qobject_cast( dsMaterial );
2048 |
2049 | FbxSurfacePhong* fbxPhong = FbxCast( fbxMaterial );
2050 | if ( fbxPhong )
2051 | {
2052 | diffuseColor = toQColor( fbxPhong->Diffuse );
2053 | diffuseMap = toTexture( fbxPhong->Diffuse );
2054 |
2055 | // Maya and Max want transparency in the color
2056 | opacityBase = 1 - (fbxPhong->TransparentColor.Get()[0] + fbxPhong->TransparentColor.Get()[1] + fbxPhong->TransparentColor.Get()[2]) / 3;
2057 | opacityMap = toTexture( fbxPhong->TransparentColor );
2058 |
2059 | if ( dsDefMaterial )
2060 | {
2061 | diffuseFactor = fbxPhong->DiffuseFactor.Get();
2062 |
2063 | ambientColor = toQColor( fbxPhong->Ambient );
2064 | ambientMap = toTexture( fbxPhong->Ambient );
2065 |
2066 | ambientFactor = fbxPhong->AmbientFactor.Get();
2067 |
2068 | specularColor = toQColor( fbxPhong->Specular );
2069 | specularMap = toTexture( fbxPhong->Specular );
2070 |
2071 | specularFactor = fbxPhong->SpecularFactor.Get();
2072 |
2073 | shininess = fbxPhong->Shininess.Get();
2074 | shininessMap = toTexture( fbxPhong->Shininess );
2075 |
2076 | reflectionFactor = fbxPhong->ReflectionFactor.Get();
2077 | reflectionMap = toTexture( fbxPhong->ReflectionFactor );
2078 | }
2079 | else //DzPbrMaterial or DzUberIrayMaterial
2080 | {
2081 | roughness = 1.0 - ((log( fbxPhong->Shininess.Get() ) / log( 2.0 )) - 2) / 10;
2082 |
2083 | FbxDouble3 spec = fbxPhong->Specular.Get();
2084 | float innerDistance = qAbs( spec[1] - spec[0] ) + qAbs( spec[2] - spec[0] ) + qAbs( spec[2] - spec[1] );
2085 | metallicity = qMin( 1.0f, innerDistance );
2086 | }
2087 | }
2088 | else if ( FbxSurfaceLambert* fbxLambert = FbxCast( fbxMaterial ) )
2089 | {
2090 | diffuseColor = toQColor( fbxLambert->Diffuse );
2091 | diffuseMap = toTexture( fbxLambert->Diffuse );
2092 |
2093 | // Maya and Max want transparency in the color
2094 | opacityBase = 1 - (fbxLambert->TransparentColor.Get()[0] + fbxLambert->TransparentColor.Get()[1] + fbxLambert->TransparentColor.Get()[2]) / 3;
2095 | opacityMap = toTexture( fbxLambert->TransparentColor );
2096 |
2097 | if ( dsDefMaterial )
2098 | {
2099 | ambientColor = toQColor( fbxLambert->Ambient );
2100 | ambientMap = toTexture( fbxLambert->Ambient );
2101 |
2102 | ambientFactor = fbxLambert->AmbientFactor.Get();
2103 | }
2104 | }
2105 |
2106 | dsMaterial->setName( fbxMaterial->GetName() );
2107 |
2108 | dsMaterial->setDiffuseColor( diffuseColor );
2109 | dsMaterial->setColorMap( diffuseMap );
2110 |
2111 | dsMaterial->setBaseOpacity( opacityBase );
2112 | dsMaterial->setOpacityMap( opacityMap );
2113 |
2114 | if ( dsDefMaterial )
2115 | {
2116 | dsDefMaterial->setAmbientColor( ambientColor );
2117 | dsDefMaterial->setAmbientColorMap( ambientMap );
2118 |
2119 | dsDefMaterial->setAmbientStrength( ambientFactor );
2120 |
2121 | if ( fbxPhong )
2122 | {
2123 | dsDefMaterial->setDiffuseStrength( diffuseFactor );
2124 |
2125 | dsDefMaterial->setSpecularColor( specularColor );
2126 | dsDefMaterial->setSpecularColorMap( specularMap );
2127 |
2128 | dsDefMaterial->setSpecularStrength( specularFactor );
2129 |
2130 | dsDefMaterial->setGlossinessStrength( shininess );
2131 | dsDefMaterial->setGlossinessValueMap( shininessMap );
2132 |
2133 | dsDefMaterial->setReflectionStrength( reflectionFactor );
2134 | dsDefMaterial->setReflectionMap( reflectionMap );
2135 | }
2136 | }
2137 | else if ( fbxPhong ) //DzPbrMaterial or DzUberIrayMaterial
2138 | {
2139 | // Because DzPbrMaterial is not in the public SDK, we attempt to use
2140 | // the meta-object to call the methods. If this fails, we attempt to
2141 | // find the properties by name and if found set their respective values.
2142 |
2143 | // use "setGlossyRoughness" double if using DzUberIrayMaterial
2144 | if ( !QMetaObject::invokeMethod( dsMaterial,
2145 | "setRoughness", Q_ARG( float, roughness ) ) )
2146 | {
2147 | if ( DzFloatProperty* fProp = qobject_cast( dsMaterial->findProperty( "Glossy Roughness" ) ) )
2148 | {
2149 | fProp->setValue( roughness );
2150 | }
2151 | }
2152 |
2153 | //use "setMetallicity" double if using DzUberIrayMaterial
2154 | if ( !QMetaObject::invokeMethod( dsMaterial,
2155 | "setMetallicity", Q_ARG( float, metallicity ) ) )
2156 | {
2157 | if ( DzFloatProperty* fProp = qobject_cast( dsMaterial->findProperty( "Metallic Weight" ) ) )
2158 | {
2159 | fProp->setValue( metallicity );
2160 | }
2161 | }
2162 | }
2163 |
2164 | m_dsMaterials.push_back( dsMaterial );
2165 |
2166 | dsShape->addMaterial( dsMaterial );
2167 | dsMesh->activateMaterial( dsMaterial->getName() );
2168 | }
2169 |
2170 | matsAllSame = true;
2171 | for ( int i = 0, n = fbxMesh->GetElementMaterialCount(); i < n; i++ )
2172 | {
2173 | const FbxGeometryElementMaterial* fbxMaterial = fbxMesh->GetElementMaterial( i );
2174 | if ( fbxMaterial->GetMappingMode() == FbxGeometryElement::eByPolygon )
2175 | {
2176 | matsAllSame = false;
2177 | break;
2178 | }
2179 | }
2180 |
2181 | if ( matsAllSame )
2182 | {
2183 | for ( int i = 0, n = fbxMesh->GetElementMaterialCount(); i < n; i++ )
2184 | {
2185 | const FbxGeometryElementMaterial* fbxMaterial = fbxMesh->GetElementMaterial( i );
2186 | if ( fbxMaterial->GetMappingMode() == FbxGeometryElement::eAllSame )
2187 | {
2188 | const int matIdx = fbxMaterial->GetIndexArray().GetAt( 0 );
2189 | if ( matIdx >= 0 )
2190 | {
2191 | dsMesh->activateMaterial( matIdx );
2192 | break;
2193 | }
2194 | }
2195 | }
2196 | }
2197 | }
2198 |
2199 | #if !DZ_SDK_4_12_OR_GREATER
2200 | static void selectFacetsByIndexList( DzFacetMesh* dsMesh, DzFaceGroup* dsFaceGroup )
2201 | {
2202 | const int nFacets = dsMesh->getNumFacets();
2203 | const int* faceGrpIndices = dsFaceGroup->getIndicesPtr();
2204 | unsigned char* facetFlags = dsMesh->getFacetFlagsPtr();
2205 | for ( int i = 0, n = dsFaceGroup->count(); i < n; ++i )
2206 | {
2207 | const int faceGrpIdx = faceGrpIndices[i];
2208 | if ( faceGrpIdx >= nFacets )
2209 | {
2210 | break;
2211 | }
2212 |
2213 | if ( facetFlags[faceGrpIdx] & DZ_HIDDEN_FACE_BIT )
2214 | {
2215 | continue;
2216 | }
2217 |
2218 | facetFlags[faceGrpIdx] |= DZ_SELECTED_FACE_BIT;
2219 | }
2220 | }
2221 | #endif
2222 |
2223 | /**
2224 | Builds face groups, or polygon selection sets, from polygon selection set
2225 | data in the FBX.
2226 |
2227 | @param dsMeshNode The node that provides the mesh with the polygons we are
2228 | interested in. Used to validate that a given selection
2229 | set is intended for 'this' object.
2230 | @param dsMesh The facet mesh that we will alter the face group(s) of.
2231 | @param dsShape The shape to create a facet selection group on; depending
2232 | on the active options.
2233 |
2234 | @sa fbxImportMesh()
2235 | **/
2236 | void DzFbxImporter::fbxImportPolygonSets( DzNode* dsMeshNode, DzFacetMesh* dsMesh, DzFacetShape* dsShape )
2237 | {
2238 | if ( !m_includePolygonSets )
2239 | {
2240 | return;
2241 | }
2242 |
2243 | const bool asFaceGroups = !m_includePolygonGroups;
2244 |
2245 | for ( int i = 0, n = m_fbxScene->GetMemberCount(); i < n; i++ )
2246 | {
2247 | FbxSelectionSet* fbxSelectionSet = m_fbxScene->GetMember( i );
2248 | if ( !fbxSelectionSet )
2249 | {
2250 | continue;
2251 | }
2252 |
2253 | const QString fbxSelSetName( fbxSelectionSet->GetName() );
2254 | QStringList fbxSelSetNameParts = fbxSelSetName.split( "__" );
2255 | const QString dsFaceGroupName( fbxSelSetNameParts.first() );
2256 | const QString dsMeshNodeName( fbxSelSetNameParts.last() );
2257 | if ( dsMeshNodeName == dsFaceGroupName
2258 | || dsMeshNodeName != dsMeshNode->getName() )
2259 | {
2260 | continue;
2261 | }
2262 |
2263 | FbxArray fbxSelectionNodeList;
2264 | FbxArray fbxDirectObjectList;
2265 | fbxSelectionSet->GetSelectionNodesAndDirectObjects( fbxSelectionNodeList, fbxDirectObjectList );
2266 |
2267 | // directly connected objects
2268 | for ( int j = 0, m = fbxDirectObjectList.GetCount(); j < m; j++ )
2269 | {
2270 | const FbxObject* fbxObject = fbxDirectObjectList[j];
2271 | const QString str( fbxObject->GetName() );
2272 | Q_UNUSED( str );
2273 | }
2274 |
2275 | // selection nodes
2276 | for ( int j = 0, m = fbxSelectionNodeList.GetCount(); j < m; j++ )
2277 | {
2278 | FbxSelectionNode* fbxSelectionNode = fbxSelectionNodeList[j];
2279 | if ( !fbxSelectionNode )
2280 | {
2281 | continue;
2282 | }
2283 |
2284 | FbxArray fbxFacetIndices;
2285 | fbxSelectionSet->GetFaceSelection( fbxSelectionNode, fbxFacetIndices );
2286 |
2287 | if ( fbxFacetIndices.GetCount() < 1 )
2288 | {
2289 | continue;
2290 | }
2291 |
2292 | if ( asFaceGroups )
2293 | {
2294 | const bool created = dsMesh->createFaceGroup( dsFaceGroupName );
2295 | Q_UNUSED( created )
2296 |
2297 | const int numFacetIndices = fbxFacetIndices.GetCount();
2298 |
2299 | // create a temporary list of facet indices to use for selection
2300 | DzTSharedPointer dsFaceGroup( new DzFaceGroup( dsFaceGroupName ) );
2301 | dsFaceGroup->preSizeArray( numFacetIndices );
2302 | for ( int k = 0; k < numFacetIndices; k++ )
2303 | {
2304 | dsFaceGroup->addIndex( fbxFacetIndices.GetAt( k ) );
2305 | }
2306 |
2307 | // use facet selection state to create face groups;
2308 | // doing it this way more easily handles exclusivity
2309 | #if DZ_SDK_4_12_OR_GREATER
2310 | dsMesh->beginFacetSelectionEdit();
2311 | #else
2312 | // DzFacetMesh::beginFacetSelectionEdit() is not in the 4.5 SDK,
2313 | // so we attempt to use the meta-object to call the method - since 4.6.3.39
2314 |
2315 | bool im = QMetaObject::invokeMethod( dsMesh, "beginFacetSelectionEdit" );
2316 | assert( im );
2317 | #endif
2318 |
2319 | dsMesh->deselectAllFacets();
2320 |
2321 | #if DZ_SDK_4_12_OR_GREATER
2322 | dsMesh->selectFacetsByIndexList( dsFaceGroup, true );
2323 | #else
2324 | // DzFacetMesh::selectFacetsByIndexList() is not in the 4.5 SDK,
2325 | // so we attempt to use the meta-object to call the method - since 4.6.3.39.
2326 | // If that fails we fall back to doing it ourselves
2327 |
2328 | if ( !QMetaObject::invokeMethod( dsMesh, "selectFacetsByIndexList",
2329 | Q_ARG( const DzIndexList*, dsFaceGroup ), Q_ARG( bool, true) ) )
2330 | {
2331 | selectFacetsByIndexList( dsMesh, dsFaceGroup );
2332 | }
2333 | #endif
2334 |
2335 | dsMesh->addSelectedFacetsToGroup( dsFaceGroupName );
2336 | dsMesh->deselectAllFacets();
2337 |
2338 | #if DZ_SDK_4_12_OR_GREATER
2339 | dsMesh->finishFacetSelectionEdit();
2340 | #else
2341 | // DzFacetMesh::beginFacetSelectionEdit() is not in the 4.5 SDK,
2342 | // so we attempt to use the meta-object to call the method - since 4.6.3.39
2343 |
2344 | im = QMetaObject::invokeMethod( dsMesh, "finishFacetSelectionEdit" );
2345 | assert( im );
2346 | #endif
2347 | }
2348 | else // as a selection group
2349 | {
2350 | #if DZ_SDK_4_12_OR_GREATER
2351 | DzSelectionGroup* dsSelectionGrp = dsShape->findFacetSelectionGroup( dsFaceGroupName, true );
2352 | for ( int k = 0; k < fbxFacetIndices.GetCount(); k++ )
2353 | {
2354 | dsSelectionGrp->addIndex( fbxFacetIndices.GetAt( k ) );
2355 | }
2356 | #else
2357 | // DzSelectionGroup is not in the 4.5 SDK, but its superclass
2358 | // DzIndexList is and it provides DzIndexList::addIndex()
2359 |
2360 | // DzFacetShape::findFacetSelectionGroup() is not in the 4.5 SDK,
2361 | // so we attempt to use the meta-object to call the method - since 4.6.3.39
2362 |
2363 | DzIndexList* dsSelectionGrp = NULL;
2364 | if ( QMetaObject::invokeMethod( dsShape, "findFacetSelectionGroup",
2365 | Q_RETURN_ARG( DzIndexList*, dsSelectionGrp ),
2366 | Q_ARG( const QString&, dsFaceGroupName ), Q_ARG( bool, true ) ) )
2367 | {
2368 | for ( int k = 0, p = fbxFacetIndices.GetCount(); k < p; k++ )
2369 | {
2370 | dsSelectionGrp->addIndex( fbxFacetIndices.GetAt( k ) );
2371 | }
2372 | }
2373 | #endif
2374 | }
2375 | }
2376 | }
2377 |
2378 | // clean up empty face groups
2379 | for ( int i = dsMesh->getNumFaceGroups() - 1; i >= 0; --i )
2380 | {
2381 | DzFaceGroup* dsFaceGroup = dsMesh->getFaceGroup( i );
2382 | if ( dsFaceGroup->count() > 0 )
2383 | {
2384 | continue;
2385 | }
2386 |
2387 | #if DZ_SDK_4_12_OR_GREATER
2388 | const bool removed = dsMesh->removeFaceGroup( dsFaceGroup->getName() );
2389 | Q_UNUSED( removed )
2390 | #else
2391 | bool removed = false;
2392 | // DzFacetMesh::removeFaceGroup() is not in the 4.5 SDK, so we attempt
2393 | // to use the meta-object to call the method. If this fails, we attempt to
2394 | // use the deprecated method.
2395 |
2396 | if ( !QMetaObject::invokeMethod( dsMesh, "removeFaceGroup",
2397 | Q_RETURN_ARG( bool, removed ), Q_ARG( QString, dsFaceGroup->getName() )) )
2398 | {
2399 | removed = dsMesh->removeFacetGroup( dsFaceGroup->getName() );
2400 | }
2401 | Q_UNUSED( removed )
2402 | #endif
2403 | }
2404 | }
2405 |
2406 | /**
2407 | **/
2408 | void DzFbxImporter::updateSelectionMap( Node* node )
2409 | {
2410 | const QString fbxSelSetName = m_nodeFaceGroupMap.value( node );
2411 | if ( fbxSelSetName.isEmpty() )
2412 | {
2413 | return;
2414 | }
2415 |
2416 | QStringList fbxSelSetNameParts = fbxSelSetName.split( "__" );
2417 | const QString dsFaceGroupName( fbxSelSetNameParts.first() );
2418 | const QString dsMeshNodeName( fbxSelSetNameParts.last() );
2419 |
2420 | DzBone* dsBone = qobject_cast( node->dsNode );
2421 | if ( !dsBone )
2422 | {
2423 | return;
2424 | }
2425 |
2426 | DzSkeleton* dsSkeleton = qobject_cast( dsBone->getSkeleton() );
2427 | if ( !dsSkeleton )
2428 | {
2429 | return;
2430 | }
2431 |
2432 | if ( dsSkeleton->getName() != dsMeshNodeName )
2433 | {
2434 | return;
2435 | }
2436 |
2437 | const DzObject* dsObject = dsSkeleton->getObject();
2438 | if ( !dsObject )
2439 | {
2440 | return;
2441 | }
2442 |
2443 | const DzShape* dsShape = dsObject->getCurrentShape();
2444 | if ( !dsShape )
2445 | {
2446 | return;
2447 | }
2448 |
2449 | const DzFacetMesh* dsMesh = qobject_cast( dsShape->getGeometry() );
2450 | if ( !dsMesh )
2451 | {
2452 | return;
2453 | }
2454 |
2455 | if ( !dsMesh->findFaceGroup( dsFaceGroupName ) )
2456 | {
2457 | return;
2458 | }
2459 |
2460 | DzSelectionMap* dsSelectionMap = dsSkeleton->getSelectionMap();
2461 | if ( !dsSelectionMap )
2462 | {
2463 | dsSelectionMap = new DzSelectionMap();
2464 | dsSkeleton->setSelectionMap( dsSelectionMap );
2465 | }
2466 |
2467 | dsSelectionMap->addPair( dsFaceGroupName, dsBone );
2468 |
2469 | dsSkeleton->setDrawGLBones( false );
2470 | }
2471 |
2472 | /**
2473 | **/
2474 | void DzFbxImporter::fbxImportFaces( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, bool matsAllSame, QMap, int> &edgeMap )
2475 | {
2476 | int numEdges = 0;
2477 |
2478 | const int numPolygons = fbxMesh->GetPolygonCount();
2479 |
2480 | const FbxGeometryElementPolygonGroup* fbxPolygonGroup = m_includePolygonGroups ?
2481 | fbxMesh->GetElementPolygonGroup( 0 ) : NULL;
2482 |
2483 | // check whether we have compatible polygon group info;
2484 | // count is 0 since FBX SDK 2020.0;
2485 | // count is as expected with FBX SDK 2019.5 and prior
2486 | const bool compatPolyGroup = fbxPolygonGroup && numPolygons == fbxPolygonGroup->GetIndexArray().GetCount();
2487 |
2488 | int curGroupIdx = -1;
2489 | for ( int polyIdx = 0; polyIdx < numPolygons; polyIdx++ )
2490 | {
2491 | // active material group
2492 | if ( !matsAllSame )
2493 | {
2494 | for ( int matElemIdx = 0, numMatElements = fbxMesh->GetElementMaterialCount();
2495 | matElemIdx < numMatElements; matElemIdx++ )
2496 | {
2497 | const FbxGeometryElementMaterial* fbxMaterial = fbxMesh->GetElementMaterial( matElemIdx );
2498 | const int polyMatIdx = fbxMaterial->GetIndexArray().GetAt( polyIdx );
2499 | if ( polyMatIdx >= 0 )
2500 | {
2501 | dsMesh->activateMaterial( polyMatIdx );
2502 | break;
2503 | }
2504 | }
2505 | }
2506 |
2507 | // active face group
2508 | if ( compatPolyGroup )
2509 | {
2510 | const int groupIdx = fbxPolygonGroup->GetIndexArray().GetAt( polyIdx );
2511 | if ( groupIdx != curGroupIdx )
2512 | {
2513 | curGroupIdx = groupIdx;
2514 | dsMesh->activateFaceGroup( "fbx_polygonGroup_" % QString::number( groupIdx ) );
2515 | }
2516 | }
2517 |
2518 | DzFacet face;
2519 |
2520 | // facet vertices
2521 | int triFanRoot = -1;
2522 | for ( int polyVertIdx = 0, numPolyVerts = fbxMesh->GetPolygonSize( polyIdx );
2523 | polyVertIdx < numPolyVerts; polyVertIdx++ )
2524 | {
2525 | // quads, tris, lines
2526 | if ( numPolyVerts <= 4 )
2527 | {
2528 | face.m_vertIdx[polyVertIdx] = fbxMesh->GetPolygonVertex( polyIdx, polyVertIdx );
2529 | face.m_normIdx[polyVertIdx] = face.m_vertIdx[polyVertIdx];
2530 |
2531 | // facet UVs
2532 | for ( int uvElemIdx = 0, numUvElems = fbxMesh->GetElementUVCount();
2533 | uvElemIdx < numUvElems; uvElemIdx++ )
2534 | {
2535 | const FbxGeometryElementUV* fbxGeomUv = fbxMesh->GetElementUV( uvElemIdx );
2536 | switch ( fbxGeomUv->GetMappingMode() )
2537 | {
2538 | case FbxGeometryElement::eByControlPoint:
2539 | switch ( fbxGeomUv->GetReferenceMode() )
2540 | {
2541 | case FbxGeometryElement::eDirect:
2542 | face.m_uvwIdx[polyVertIdx] = face.m_vertIdx[polyVertIdx];
2543 | break;
2544 | case FbxGeometryElement::eIndexToDirect:
2545 | face.m_uvwIdx[polyVertIdx] = fbxGeomUv->GetIndexArray().GetAt( face.m_vertIdx[polyVertIdx] );
2546 | break;
2547 | default:
2548 | break;
2549 | }
2550 | break;
2551 | case FbxGeometryElement::eByPolygonVertex:
2552 | face.m_uvwIdx[polyVertIdx] = fbxMesh->GetTextureUVIndex( polyIdx, polyVertIdx );
2553 | break;
2554 | default:
2555 | break;
2556 | }
2557 |
2558 | // only do the first UV set
2559 | break;
2560 | }
2561 |
2562 | if ( polyVertIdx == numPolyVerts - 1 )
2563 | {
2564 | dsMesh->addFacet( face.m_vertIdx, face.m_uvwIdx );
2565 | }
2566 | }
2567 | // n-gons
2568 | else if ( polyVertIdx >= 2 )
2569 | {
2570 | const bool isRoot = polyVertIdx == 2;
2571 |
2572 | face.m_vertIdx[0] = fbxMesh->GetPolygonVertex( polyIdx, 0 );
2573 | face.m_vertIdx[1] = fbxMesh->GetPolygonVertex( polyIdx, polyVertIdx - 1 );
2574 | face.m_vertIdx[2] = fbxMesh->GetPolygonVertex( polyIdx, polyVertIdx );
2575 | face.m_vertIdx[3] = -1;
2576 | face.m_normIdx[0] = face.m_vertIdx[0];
2577 | face.m_normIdx[1] = face.m_vertIdx[1];
2578 | face.m_normIdx[2] = face.m_vertIdx[2];
2579 | face.m_normIdx[3] = face.m_vertIdx[3];
2580 |
2581 | if ( isRoot )
2582 | {
2583 | triFanRoot = dsMesh->getNumFacets();
2584 | }
2585 |
2586 | #if DZ_SDK_4_12_OR_GREATER
2587 | face.setTriFanRoot( triFanRoot );
2588 | #else
2589 | // DzFacet::setTriFanRoot() is not in the 4.5 SDK, and DzFacet
2590 | // is not derived from QObject, so we must modify the member
2591 | // directly.
2592 |
2593 | face.m_vertIdx[3] = -(triFanRoot + 2);
2594 | #endif
2595 |
2596 | if ( isRoot )
2597 | {
2598 | #if DZ_SDK_4_12_OR_GREATER
2599 | face.setTriFanCount( numPolyVerts - 2 );
2600 | #else
2601 | // DzFacet::setTriFanCount() is not in the 4.5 SDK, and DzFacet
2602 | // is not derived from QObject, so we must modify the member
2603 | // directly.
2604 |
2605 | face.m_edges[3] = -numPolyVerts;
2606 | #endif
2607 | }
2608 | else
2609 | {
2610 | #if DZ_SDK_4_12_OR_GREATER
2611 | face.clearTriFanCount();
2612 | #else
2613 | // DzFacet::clearTriFanCount() is not in the 4.5 SDK, and DzFacet
2614 | // is not derived from QObject, so we must modify the member
2615 | // directly.
2616 |
2617 | face.m_edges[3] = -1;
2618 | #endif
2619 | }
2620 |
2621 | // facet UVs
2622 | for ( int uvElemIdx = 0, numUvElems = fbxMesh->GetElementUVCount();
2623 | uvElemIdx < numUvElems; uvElemIdx++ )
2624 | {
2625 | const FbxGeometryElementUV* fbxGeomUv = fbxMesh->GetElementUV( uvElemIdx );
2626 | switch ( fbxGeomUv->GetMappingMode() )
2627 | {
2628 | case FbxGeometryElement::eByControlPoint:
2629 | switch ( fbxGeomUv->GetReferenceMode() )
2630 | {
2631 | case FbxGeometryElement::eDirect:
2632 | face.m_uvwIdx[0] = face.m_vertIdx[0];
2633 | face.m_uvwIdx[1] = face.m_vertIdx[polyVertIdx - 1];
2634 | face.m_uvwIdx[2] = face.m_vertIdx[polyVertIdx];
2635 | face.m_uvwIdx[3] = -1;
2636 | break;
2637 | case FbxGeometryElement::eIndexToDirect:
2638 | face.m_uvwIdx[0] = fbxGeomUv->GetIndexArray().GetAt( face.m_vertIdx[0] );
2639 | face.m_uvwIdx[1] = fbxGeomUv->GetIndexArray().GetAt( face.m_vertIdx[polyVertIdx - 1] );
2640 | face.m_uvwIdx[2] = fbxGeomUv->GetIndexArray().GetAt( face.m_vertIdx[polyVertIdx] );
2641 | face.m_uvwIdx[3] = -1;
2642 | break;
2643 | default:
2644 | break;
2645 | }
2646 | break;
2647 | case FbxGeometryElement::eByPolygonVertex:
2648 | face.m_uvwIdx[0] = fbxMesh->GetTextureUVIndex( polyIdx, polyVertIdx );
2649 | face.m_uvwIdx[1] = fbxMesh->GetTextureUVIndex( polyIdx, polyVertIdx - 1 );
2650 | face.m_uvwIdx[2] = fbxMesh->GetTextureUVIndex( polyIdx, polyVertIdx );
2651 | face.m_uvwIdx[3] = -1;
2652 | break;
2653 | default:
2654 | break;
2655 | }
2656 |
2657 | // only do the first UV set
2658 | break;
2659 | }
2660 |
2661 | #if DZ_SDK_4_12_OR_GREATER
2662 | dsMesh->addFacet( face );
2663 | #else
2664 | // DzFacetMesh::addFacet() is not in the 4.5 SDK, so we attempt
2665 | // to use the meta-object to call the method.
2666 |
2667 | bool im = QMetaObject::invokeMethod( dsMesh, "addFacet",
2668 | Q_ARG( const DzFacet &, face ) );
2669 | assert( im );
2670 | #endif
2671 |
2672 | if ( isRoot )
2673 | {
2674 | #if DZ_SDK_4_12_OR_GREATER
2675 | dsMesh->incrementNgons();
2676 | #else
2677 | // DzFacetMesh::incrementNgons() is not in the 4.5 SDK, so
2678 | // we attempt to use the meta-object to call the method.
2679 |
2680 | bool im = QMetaObject::invokeMethod( dsMesh, "incrementNgons" );
2681 | assert( im );
2682 | #endif
2683 | }
2684 | }
2685 |
2686 |
2687 | {
2688 | const int polyVertNextIdx = (polyVertIdx + 1) % numPolyVerts;
2689 |
2690 | const int edgeVertA = fbxMesh->GetPolygonVertex( polyIdx, polyVertIdx );
2691 | const int edgeVertB = fbxMesh->GetPolygonVertex( polyIdx, polyVertNextIdx );
2692 | QPair edgeVertPair( qMin( edgeVertA, edgeVertB ), qMax( edgeVertA, edgeVertB ) );
2693 | if ( !edgeMap.contains( edgeVertPair ) )
2694 | {
2695 | edgeMap[edgeVertPair] = numEdges;
2696 | numEdges++;
2697 | }
2698 | }
2699 | }
2700 | }
2701 | }
2702 |
2703 | /**
2704 | **/
2705 | void DzFbxImporter::fbxImportSubdEdgeWeights( FbxMesh* fbxMesh, DzFacetMesh* dsMesh, QMap, int> edgeMap, bool &enableSubd )
2706 | {
2707 | for ( int i = 0, n = fbxMesh->GetElementEdgeCreaseCount(); i < n; i++ )
2708 | {
2709 | const FbxGeometryElementCrease* fbxSubdEdgeCrease = fbxMesh->GetElementEdgeCrease( i );
2710 | const int numCreases = fbxSubdEdgeCrease->GetDirectArray().GetCount();
2711 | Q_UNUSED( numCreases )
2712 |
2713 | QMap< QPair, int >::iterator edgeMapIt;
2714 | for ( edgeMapIt = edgeMap.begin(); edgeMapIt != edgeMap.end(); ++edgeMapIt )
2715 | {
2716 | const int edgeIdx = edgeMapIt.value();
2717 | const float weight = fbxSubdEdgeCrease->GetDirectArray().GetAt( edgeIdx );
2718 | const int edgeVertA = edgeMapIt.key().first;
2719 | const int edgeVertB = edgeMapIt.key().second;
2720 | if ( weight > 0 )
2721 | {
2722 | enableSubd = true;
2723 | #if DZ_SDK_4_12_OR_GREATER
2724 | dsMesh->setEdgeWeight( edgeVertA, edgeVertB, weight );
2725 | #else
2726 | // DzFacetMesh::setEdgeWeight() is not in the 4.5 SDK, so we
2727 | // attempt to use the meta-object to call the method.
2728 |
2729 | bool im = QMetaObject::invokeMethod( dsMesh, "setEdgeWeight",
2730 | Q_ARG( int, edgeVertA ), Q_ARG( int, edgeVertB ), Q_ARG( int, weight ) );
2731 | assert( im );
2732 | #endif
2733 | }
2734 | }
2735 |
2736 | // only do the first
2737 | break;
2738 | }
2739 | }
2740 |
2741 | /**
2742 | **/
2743 | DzWeightMapPtr DzFbxImporter::fbxImportSkinningBlendWeights( int numVertices, const FbxSkin* fbxSkin )
2744 | {
2745 | if ( numVertices < 1
2746 | || !fbxSkin
2747 | || fbxSkin->GetSkinningType() != FbxSkin::eBlend )
2748 | {
2749 | return NULL;
2750 | }
2751 |
2752 | const int numBlendIndices = fbxSkin->GetControlPointIndicesCount();
2753 | const int* fbxBlendIndices = fbxSkin->GetControlPointIndices();
2754 | if ( numBlendIndices <= 0 || !fbxBlendIndices )
2755 | {
2756 | return NULL;
2757 | }
2758 |
2759 | DzWeightMapPtr dsBlendWeights = new DzWeightMap( numVertices, "Blend Weights" );
2760 | unsigned short* dsWeightValues = dsBlendWeights->getWeights();
2761 | for ( int bwIdx = 0; bwIdx < numBlendIndices; ++bwIdx )
2762 | {
2763 | const int idx = fbxBlendIndices[bwIdx];
2764 | if ( idx > numVertices )
2765 | {
2766 | continue;
2767 | }
2768 |
2769 | const double fbxBlendWeight = fbxSkin->GetControlPointBlendWeights()[bwIdx];
2770 | dsWeightValues[idx] = DZ_USHORT_MAX * fbxBlendWeight;
2771 | }
2772 |
2773 | #if DZ_SDK_4_12_OR_GREATER
2774 | dsBlendWeights->reduceWeightMemory();
2775 | #endif
2776 |
2777 | return dsBlendWeights;
2778 | }
2779 |
2780 | /**
2781 | **/
2782 | void DzFbxImporter::fbxImportMorph( FbxBlendShape* fbxBlendShape, DzObject* dsObject, int numVertices, FbxVector4* fbxVertices )
2783 | {
2784 | if ( !fbxBlendShape
2785 | || !dsObject
2786 | || numVertices < 1 )
2787 | {
2788 | return;
2789 | }
2790 |
2791 | DzPnt3* values = new DzPnt3[numVertices];
2792 |
2793 | const int numBlendShapeChannels = fbxBlendShape->GetBlendShapeChannelCount();
2794 |
2795 | DzProgress progress( "Morphs", numBlendShapeChannels );
2796 | for ( int blendShapeChanIdx = 0; blendShapeChanIdx < numBlendShapeChannels; blendShapeChanIdx++ )
2797 | {
2798 | FbxBlendShapeChannel* fbxBlendChannel = fbxBlendShape->GetBlendShapeChannel( blendShapeChanIdx );
2799 |
2800 | DzMorph* dsMorph = new DzMorph;
2801 | dsMorph->setName( fbxBlendChannel->GetName() );
2802 | DzMorphDeltas* dsDeltas = dsMorph->getDeltas();
2803 |
2804 | DzFloatProperty* morphControl = NULL;
2805 | #if DZ_SDK_4_12_OR_GREATER
2806 | morphControl = dsMorph->getValueControl();
2807 | #else
2808 | // DzMorph::getValueControl() is not in the 4.5 SDK, but DzMorph::getValueChannel()
2809 | // was, so we use the previous name.
2810 |
2811 | morphControl = dsMorph->getValueChannel();
2812 | #endif
2813 |
2814 | applyFbxCurve( fbxBlendChannel->DeformPercent.GetCurve( m_fbxAnimLayer ), morphControl, 0.01 );
2815 |
2816 | for ( int vertIdx = 0; vertIdx < numVertices; vertIdx++ )
2817 | {
2818 | values[vertIdx][0] = 0;
2819 | values[vertIdx][1] = 0;
2820 | values[vertIdx][2] = 0;
2821 | }
2822 |
2823 | for ( int tgtShapeIdx = 0, numTgtShapes = fbxBlendChannel->GetTargetShapeCount();
2824 | tgtShapeIdx < numTgtShapes; tgtShapeIdx++ )
2825 | {
2826 | FbxShape* fbxTargetShape = fbxBlendChannel->GetTargetShape( tgtShapeIdx );
2827 | FbxVector4* fbxTargetShapeVerts = fbxTargetShape->GetControlPoints();
2828 | int* fbxTgtShapeVertIndices = fbxTargetShape->GetControlPointIndices();
2829 | //double weight = fbxBlendChannel->GetTargetShapeFullWeights()[k];
2830 |
2831 | if ( fbxTgtShapeVertIndices )
2832 | {
2833 | for ( int tgtShapeVertIndicesIdx = 0, numTgtShapeVertIndices = fbxTargetShape->GetControlPointIndicesCount();
2834 | tgtShapeVertIndicesIdx < numTgtShapeVertIndices; tgtShapeVertIndicesIdx++ )
2835 | {
2836 | const int vertIdx = fbxTgtShapeVertIndices[tgtShapeVertIndicesIdx];
2837 | values[vertIdx][0] = fbxTargetShapeVerts[vertIdx][0] - fbxVertices[vertIdx][0];
2838 | values[vertIdx][1] = fbxTargetShapeVerts[vertIdx][1] - fbxVertices[vertIdx][1];
2839 | values[vertIdx][2] = fbxTargetShapeVerts[vertIdx][2] - fbxVertices[vertIdx][2];
2840 | }
2841 | }
2842 | else
2843 | {
2844 | for ( int vertIdx = 0, numTgtShapeVerts = fbxTargetShape->GetControlPointsCount();
2845 | vertIdx < numTgtShapeVerts; vertIdx++ )
2846 | {
2847 | values[vertIdx][0] = fbxTargetShapeVerts[vertIdx][0] - fbxVertices[vertIdx][0];
2848 | values[vertIdx][1] = fbxTargetShapeVerts[vertIdx][1] - fbxVertices[vertIdx][1];
2849 | values[vertIdx][2] = fbxTargetShapeVerts[vertIdx][2] - fbxVertices[vertIdx][2];
2850 | }
2851 | }
2852 | }
2853 |
2854 | DzIntArray indexes;
2855 | DzTArray deltas;
2856 | for ( int vertIdx = 0; vertIdx < numVertices; vertIdx++ )
2857 | {
2858 | if ( values[vertIdx][0] != 0 || values[vertIdx][1] != 0 || values[vertIdx][2] != 0 )
2859 | {
2860 | indexes.append( vertIdx );
2861 | deltas.append( DzVec3( values[vertIdx][0], values[vertIdx][1], values[vertIdx][2] ) );
2862 | }
2863 | }
2864 | dsDeltas->addDeltas( indexes, deltas, false );
2865 | dsObject->addModifier( dsMorph );
2866 |
2867 | progress.step();
2868 | }
2869 |
2870 | delete[] values;
2871 | }
2872 |
2873 | /**
2874 | **/
2875 | void DzFbxImporter::fbxImportMeshModifiers( Node* node, FbxMesh* fbxMesh, DzObject* dsObject, DzFigure* dsFigure, int numVertices, FbxVector4* fbxVertices )
2876 | {
2877 | for ( int deformerIdx = 0, numDeformers = fbxMesh->GetDeformerCount(); deformerIdx < numDeformers; deformerIdx++ )
2878 | {
2879 | FbxDeformer* fbxDeformer = fbxMesh->GetDeformer( deformerIdx );
2880 |
2881 | // skin binding
2882 | if ( FbxSkin* fbxSkin = FbxCast( fbxDeformer ) )
2883 | {
2884 | if ( !dsFigure )
2885 | {
2886 | continue;
2887 | }
2888 |
2889 | Skinning skinning;
2890 | skinning.node = node;
2891 | skinning.fbxSkin = fbxSkin;
2892 | skinning.dsFigure = dsFigure;
2893 | skinning.numVertices = numVertices;
2894 | skinning.blendWeights = fbxImportSkinningBlendWeights( numVertices, fbxSkin );
2895 | m_skins.push_back( skinning );
2896 | }
2897 | // morphs
2898 | else if ( FbxBlendShape* fbxBlendShape = FbxCast( fbxDeformer ) )
2899 | {
2900 | fbxImportMorph( fbxBlendShape, dsObject, numVertices, fbxVertices );
2901 | }
2902 | }
2903 | }
2904 |
2905 | /**
2906 | **/
2907 | void DzFbxImporter::fbxImportMesh( Node* node, FbxNode* fbxNode, DzNode* dsMeshNode )
2908 | {
2909 | FbxMesh* fbxMesh = fbxNode->GetMesh();
2910 |
2911 | const QString dsName = dsMeshNode ? dsMeshNode->getName() : fbxNode->GetName();
2912 |
2913 | DzObject* dsObject = new DzObject();
2914 | dsObject->setName( !dsName.isEmpty() ? dsName : "object" );
2915 |
2916 | DzFacetMesh* dsMesh = new DzFacetMesh();
2917 | dsMesh->setName( !dsName.isEmpty() ? dsName : "geometry" );
2918 |
2919 | #if DZ_SDK_4_12_OR_GREATER
2920 | DzFacetShape* dsShape = new DzGraftingFigureShape();
2921 | #else
2922 | // DzGraftingFigureShape is not in the 4.5 SDK, but if the version of the
2923 | // application has the factory for the class we can use it to create an
2924 | // instance or fallback to the base class that is in the 4.5 SDK
2925 |
2926 | DzFacetShape* dsShape;
2927 | if ( const DzClassFactory* factory = dzApp->findClassFactory( "DzGraftingFigureShape" ) )
2928 | {
2929 | dsShape = qobject_cast( factory->createInstance() );
2930 | }
2931 | else
2932 | {
2933 | dsShape = new DzFacetShape();
2934 | }
2935 | #endif
2936 | dsShape->setName( !dsName.isEmpty() ? dsName : "shape" );
2937 |
2938 | DzFigure* dsFigure = qobject_cast( dsMeshNode );
2939 |
2940 | DzVec3 offset( 0, 0, 0 );
2941 | if ( dsFigure )
2942 | {
2943 | offset = dsFigure->getOrigin();
2944 | }
2945 |
2946 | // begin the edit
2947 | dsMesh->beginEdit();
2948 |
2949 | const int numVertices = fbxMesh->GetControlPointsCount();
2950 | FbxVector4* fbxVertices = fbxMesh->GetControlPoints();
2951 | fbxImportVertices( numVertices, fbxVertices, dsMesh, offset );
2952 |
2953 | fbxImportUVs( fbxMesh, dsMesh );
2954 |
2955 | bool enableSubd = false;
2956 | fbxImportSubdVertexWeights( fbxMesh, dsMesh, enableSubd );
2957 |
2958 | bool matsAllSame;
2959 | fbxImportMaterials( fbxNode, fbxMesh, dsMesh, dsShape, matsAllSame );
2960 |
2961 | QMap< QPair< int, int >, int > edgeMap;
2962 | fbxImportFaces( fbxMesh, dsMesh, matsAllSame, edgeMap );
2963 |
2964 | fbxImportSubdEdgeWeights( fbxMesh, dsMesh, edgeMap, enableSubd );
2965 |
2966 | // end the edit
2967 | dsMesh->finishEdit();
2968 |
2969 | dsShape->setFacetMesh( dsMesh );
2970 |
2971 | setSubdEnabled( enableSubd, dsMesh, dsShape );
2972 |
2973 | dsObject->addShape( dsShape );
2974 | dsMeshNode->setObject( dsObject );
2975 |
2976 | fbxImportPolygonSets( dsMeshNode, dsMesh, dsShape );
2977 |
2978 | fbxImportMeshModifiers( node, fbxMesh, dsObject, dsFigure, numVertices, fbxVertices );
2979 | }
2980 |
2981 | /**
2982 | **/
2983 | void DzFbxImporter::setSubdEnabled( bool onOff, DzFacetMesh* dsMesh, DzFacetShape* dsShape )
2984 | {
2985 | if ( !onOff )
2986 | {
2987 | return;
2988 | }
2989 |
2990 | dsMesh->enableSubDivision( true );
2991 |
2992 | if ( DzEnumProperty* lodControl = dsShape->getLODControl() )
2993 | {
2994 | lodControl->setValue( lodControl->getNumItems() - 1 ); //set to high res
2995 | lodControl->setDefaultValue( lodControl->getNumItems() - 1 ); //set to high res
2996 | }
2997 | }
2998 |
2999 | /**
3000 | **/
3001 | void DzFbxImporter::applyFbxCurve( FbxAnimCurve* fbxCurve, DzFloatProperty* dsProperty, double scale )
3002 | {
3003 | if ( !fbxCurve || !dsProperty )
3004 | {
3005 | return;
3006 | }
3007 |
3008 | dsProperty->deleteAllKeys();
3009 |
3010 | for ( int i = 0; i < fbxCurve->KeyGetCount(); i++ )
3011 | {
3012 | const double fbxTime = fbxCurve->KeyGetTime( i ).GetSecondDouble();
3013 | const double fbxValue = fbxCurve->KeyGetValue( i );
3014 | DzTime dsTime = static_cast< DzTime >((fbxTime * DZ_TICKS_PER_SECOND) + 0.5f); //round to nearest tick
3015 | m_dsEndTime = qMax( m_dsEndTime, dsTime );
3016 |
3017 | dsProperty->setValue( dsTime, fbxValue * scale );
3018 | }
3019 | }
3020 |
3021 | ///////////////////////////////////////////////////////////////////////
3022 | // DzFbxImportFrame
3023 | ///////////////////////////////////////////////////////////////////////
3024 |
3025 | struct DzFbxImportFrame::Data
3026 | {
3027 | Data( DzFbxImporter* importer ) :
3028 | m_importer( importer ),
3029 | m_includeRotationLimitsCbx( NULL ),
3030 | m_includeAnimationCbx( NULL ),
3031 | m_animationTakeCmb( NULL ),
3032 | m_includePolygonSetsCbx( NULL ),
3033 | m_includePolygonGroupsCbx( NULL ),
3034 | m_studioNodeNameLabelCbx( NULL ),
3035 | m_studioPresentationCbx( NULL ),
3036 | m_studioSelectionMapCbx( NULL ),
3037 | m_studioSceneIDsCbx( NULL )
3038 | {}
3039 |
3040 | DzFbxImporter* m_importer;
3041 |
3042 | QCheckBox* m_includeRotationLimitsCbx;
3043 | QCheckBox* m_includeAnimationCbx;
3044 | QComboBox* m_animationTakeCmb;
3045 |
3046 | QCheckBox* m_includePolygonSetsCbx;
3047 | QCheckBox* m_includePolygonGroupsCbx;
3048 |
3049 | QCheckBox* m_studioNodeNameLabelCbx;
3050 | QCheckBox* m_studioPresentationCbx;
3051 | QCheckBox* m_studioSelectionMapCbx;
3052 | QCheckBox* m_studioSceneIDsCbx;
3053 | };
3054 |
3055 | namespace
3056 | {
3057 |
3058 | QGroupBox* createCollapsibleGroupBox( const QString &title, const QString &basename, bool collapsed = false )
3059 | {
3060 | #if DZ_SDK_4_12_OR_GREATER
3061 | DzCollapsibleGroupBox* groupBox = new DzCollapsibleGroupBox( title );
3062 | groupBox->setObjectName( basename % "GBox" );
3063 | groupBox->setCollapsed( collapsed );
3064 | #else
3065 | QGroupBox* groupBox = NULL;
3066 | if ( const DzClassFactory* factory = dzApp->findClassFactory( "DzCollapsibleGroupBox" ) )
3067 | {
3068 | groupBox = qobject_cast( factory->createInstance() );
3069 | }
3070 |
3071 | if ( !groupBox )
3072 | {
3073 | groupBox = new QGroupBox();
3074 | }
3075 |
3076 | groupBox->setObjectName( basename % "GBox" );
3077 | groupBox->setTitle( title );
3078 | #endif //DZ_SDK_4_12_OR_GREATER
3079 |
3080 | return groupBox;
3081 | }
3082 |
3083 | QScrollArea* createScrollableWidget( QWidget* widgetToScroll, int margin, int spacing, const QString &nameBase )
3084 | {
3085 | QWidget* scrollableWgt = new QWidget();
3086 | scrollableWgt->setObjectName( nameBase % "ScrollWgt" );
3087 |
3088 | QVBoxLayout* scrollableLyt = new QVBoxLayout();
3089 | scrollableLyt->setMargin( margin );
3090 | scrollableLyt->setSpacing( spacing );
3091 |
3092 | scrollableLyt->addWidget( widgetToScroll );
3093 |
3094 | scrollableLyt->addStretch();
3095 |
3096 | scrollableWgt->setLayout( scrollableLyt );
3097 |
3098 | QScrollArea* scrollArea = new QScrollArea();
3099 | scrollArea->setObjectName( nameBase % "ScrollArea" );
3100 | scrollArea->setWidgetResizable( true );
3101 | scrollArea->setWidget( scrollableWgt );
3102 |
3103 | return scrollArea;
3104 | }
3105 |
3106 | const char* c_none = QT_TRANSLATE_NOOP( "DzFbxImportFrame", "" );
3107 |
3108 | } //namespace
3109 |
3110 | /**
3111 | **/
3112 | DzFbxImportFrame::DzFbxImportFrame( DzFbxImporter* importer ) :
3113 | DzFileIOFrame( tr( "FBX Import Options" ) ), m_data( new Data( importer ) )
3114 | {
3115 | const QString name( "FbxImport" );
3116 |
3117 | const int margin = style()->pixelMetric( DZ_PM_GeneralMargin );
3118 | const int btnHeight = style()->pixelMetric( DZ_PM_ButtonHeight );
3119 |
3120 | QVector leftLabels;
3121 | leftLabels.reserve( 10 );
3122 |
3123 | QVBoxLayout* mainLyt = new QVBoxLayout();
3124 | mainLyt->setSpacing( margin );
3125 | mainLyt->setMargin( margin );
3126 |
3127 | // Format
3128 | QGroupBox* formatGBox = new QGroupBox( tr( "Format :" ) );
3129 | formatGBox->setObjectName( name % "FormatGBox" );
3130 |
3131 | QGridLayout* formatLyt = new QGridLayout();
3132 | formatLyt->setSpacing( margin );
3133 | formatLyt->setMargin( margin );
3134 | formatLyt->setColumnStretch( 1, 1 );
3135 |
3136 | int row = 0;
3137 |
3138 | QLabel* lbl = new QLabel( tr( "Version:" ) );
3139 | lbl->setObjectName( name % "FileVersionLbl" );
3140 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3141 | formatLyt->addWidget( lbl, row, 0 );
3142 | leftLabels.push_back( lbl );
3143 |
3144 | lbl = new QLabel( importer->getFileVersion() );
3145 | lbl->setObjectName( name % "FileVersionValueLbl" );
3146 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3147 | formatLyt->addWidget( lbl, row++, 1 );
3148 |
3149 | lbl = new QLabel( tr( "Creator:" ) );
3150 | lbl->setObjectName( name % "FileCreatorLbl" );
3151 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3152 | formatLyt->addWidget( lbl, row, 0 );
3153 | leftLabels.push_back( lbl );
3154 |
3155 | lbl = new QLabel( importer->getFileCreator() );
3156 | lbl->setObjectName( name % "FileCreatorValueLbl" );
3157 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3158 | formatLyt->addWidget( lbl, row++, 1 );
3159 |
3160 | formatGBox->setLayout( formatLyt );
3161 |
3162 | mainLyt->addWidget( formatGBox );
3163 |
3164 |
3165 | // Scene Info
3166 | QGroupBox* sceneInfoGBox = createCollapsibleGroupBox( tr( "Scene :" ), name % "SceneInfo", true );
3167 |
3168 | QGridLayout* sceneInfoLyt = new QGridLayout();
3169 | sceneInfoLyt->setSpacing( margin );
3170 | sceneInfoLyt->setMargin( margin );
3171 | sceneInfoLyt->setColumnStretch( 1, 1 );
3172 |
3173 | row = 0;
3174 |
3175 | const QString sceneAuthor = importer->getSceneAuthor();
3176 | if ( !sceneAuthor.isEmpty() )
3177 | {
3178 | lbl = new QLabel( tr( "Author:" ) );
3179 | lbl->setObjectName( name % "SceneAuthorLbl" );
3180 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3181 | sceneInfoLyt->addWidget( lbl, row, 0 );
3182 | leftLabels.push_back( lbl );
3183 |
3184 | lbl = new QLabel( sceneAuthor );
3185 | lbl->setObjectName( name % "SceneAuthorValueLbl" );
3186 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3187 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3188 | }
3189 |
3190 | const QString sceneTitle = importer->getSceneTitle();
3191 | if ( !sceneTitle.isEmpty() )
3192 | {
3193 | lbl = new QLabel( tr( "Title:" ) );
3194 | lbl->setObjectName( name % "SceneTitleLbl" );
3195 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3196 | sceneInfoLyt->addWidget( lbl, row, 0 );
3197 | leftLabels.push_back( lbl );
3198 |
3199 | lbl = new QLabel( sceneTitle );
3200 | lbl->setObjectName( name % "SceneTitleValueLbl" );
3201 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3202 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3203 | }
3204 |
3205 | const QString sceneSubject = importer->getSceneSubject();
3206 | if ( !sceneSubject.isEmpty() )
3207 | {
3208 | lbl = new QLabel( tr( "Subject:" ) );
3209 | lbl->setObjectName( name % "SceneSubjectLbl" );
3210 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3211 | sceneInfoLyt->addWidget( lbl, row, 0 );
3212 | leftLabels.push_back( lbl );
3213 |
3214 | lbl = new QLabel( sceneSubject );
3215 | lbl->setObjectName( name % "SceneSubjectValueLbl" );
3216 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3217 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3218 | }
3219 |
3220 | const QString sceneKeywords = importer->getSceneKeywords();
3221 | if ( !sceneKeywords.isEmpty() )
3222 | {
3223 | lbl = new QLabel( tr( "Keywords:" ) );
3224 | lbl->setObjectName( name % "SceneKeywordsLbl" );
3225 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3226 | sceneInfoLyt->addWidget( lbl, row, 0 );
3227 | leftLabels.push_back( lbl );
3228 |
3229 | lbl = new QLabel( sceneKeywords );
3230 | lbl->setObjectName( name % "SceneKeywordsValueLbl" );
3231 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3232 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3233 | }
3234 |
3235 | const QString sceneRevision = importer->getSceneRevision();
3236 | if ( !sceneRevision.isEmpty() )
3237 | {
3238 | lbl = new QLabel( tr( "Revision:" ) );
3239 | lbl->setObjectName( name % "SceneRevisionLbl" );
3240 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3241 | sceneInfoLyt->addWidget( lbl, row, 0 );
3242 | leftLabels.push_back( lbl );
3243 |
3244 | lbl = new QLabel( sceneRevision );
3245 | lbl->setObjectName( name % "SceneRevisionValueLbl" );
3246 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3247 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3248 | }
3249 |
3250 | const QString sceneComment = importer->getSceneComment();
3251 | if ( !sceneComment.isEmpty() )
3252 | {
3253 | lbl = new QLabel( tr( "Comment:" ) );
3254 | lbl->setObjectName( name % "SceneCommentLbl" );
3255 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3256 | sceneInfoLyt->addWidget( lbl, row, 0 );
3257 | leftLabels.push_back( lbl );
3258 |
3259 | lbl = new QLabel( sceneComment );
3260 | lbl->setObjectName( name % "SceneCommentValueLbl" );
3261 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3262 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3263 | }
3264 |
3265 | const QString vendor = importer->getOriginalAppVendor();
3266 | if ( !vendor.simplified().isEmpty() )
3267 | {
3268 | lbl = new QLabel( tr( "Vendor:" ) );
3269 | lbl->setObjectName( name % "VendorLbl" );
3270 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3271 | sceneInfoLyt->addWidget( lbl, row, 0 );
3272 | leftLabels.push_back( lbl );
3273 |
3274 | lbl = new QLabel( vendor );
3275 | lbl->setObjectName( name % "VendorValueLbl" );
3276 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3277 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3278 | }
3279 |
3280 | const QString application = QString( "%1 %2" )
3281 | .arg( importer->getOriginalAppName() )
3282 | .arg( importer->getOriginalAppVersion() );
3283 | if ( !application.simplified().isEmpty() )
3284 | {
3285 | lbl = new QLabel( tr( "Application:" ) );
3286 | lbl->setObjectName( name % "ApplicationLbl" );
3287 | lbl->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
3288 | sceneInfoLyt->addWidget( lbl, row, 0 );
3289 | leftLabels.push_back( lbl );
3290 |
3291 | lbl = new QLabel( application );
3292 | lbl->setObjectName( name % "ApplicationValueLbl" );
3293 | lbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3294 | sceneInfoLyt->addWidget( lbl, row++, 1 );
3295 | }
3296 |
3297 | #if DZ_SDK_4_12_OR_GREATER
3298 | if ( DzCollapsibleGroupBox* sceneInfoCGBox = qobject_cast( sceneInfoGBox ) )
3299 | {
3300 | sceneInfoCGBox->addLayout( sceneInfoLyt );
3301 | }
3302 | else
3303 | {
3304 | sceneInfoGBox->setLayout( sceneInfoLyt );
3305 | }
3306 | #else
3307 | sceneInfoGBox->setLayout( sceneInfoLyt );
3308 | #endif //DZ_SDK_4_12_OR_GREATER
3309 |
3310 | mainLyt->addWidget( sceneInfoGBox );
3311 |
3312 | QWidget* scrollableOptionsWgt = new QWidget();
3313 | scrollableOptionsWgt->setObjectName( name % "ScrollableOptionsWgt" );
3314 |
3315 |
3316 | QVBoxLayout* scrollableOptionsLyt = new QVBoxLayout();
3317 | scrollableOptionsLyt->setSpacing( margin );
3318 | scrollableOptionsLyt->setMargin( 0 );
3319 |
3320 |
3321 | // Properties
3322 | QGroupBox* propertiesGBox = new QGroupBox( tr( "Properties :" ) );
3323 | propertiesGBox->setObjectName( name % "PropertiesGBox" );
3324 |
3325 | QVBoxLayout* propertiesLyt = new QVBoxLayout();
3326 | propertiesLyt->setSpacing( margin );
3327 | propertiesLyt->setMargin( margin );
3328 |
3329 | m_data->m_includeRotationLimitsCbx = new QCheckBox();
3330 | m_data->m_includeRotationLimitsCbx->setObjectName( name % "IncludeRotationLimitsCbx" );
3331 | m_data->m_includeRotationLimitsCbx->setText( tr( "Include Rotation Limits" ) );
3332 | propertiesLyt->addWidget( m_data->m_includeRotationLimitsCbx );
3333 | DzConnect( m_data->m_includeRotationLimitsCbx, SIGNAL(toggled(bool)),
3334 | importer, SLOT(setRotationLimits(bool)) );
3335 |
3336 | m_data->m_includeAnimationCbx = new QCheckBox();
3337 | m_data->m_includeAnimationCbx->setObjectName( name % "IncludeAnimationCbx" );
3338 | m_data->m_includeAnimationCbx->setText( tr( "Include Animation" ) );
3339 | propertiesLyt->addWidget( m_data->m_includeAnimationCbx );
3340 | DzConnect( m_data->m_includeAnimationCbx, SIGNAL(toggled(bool)),
3341 | importer, SLOT(setIncludeAnimations(bool)) );
3342 |
3343 | m_data->m_animationTakeCmb = new QComboBox();
3344 | m_data->m_animationTakeCmb->setObjectName( name % "TakeToImportCmb" );
3345 | m_data->m_animationTakeCmb->addItem( tr( c_none ) );
3346 | //m_data->m_animationTakeCmb->insertSeparator( m_data->m_animationTakeCmb->count() );
3347 | m_data->m_animationTakeCmb->addItems( importer->getAnimStackNames() );
3348 | m_data->m_animationTakeCmb->setCurrentIndex( 0 );
3349 | m_data->m_animationTakeCmb->setFixedHeight( btnHeight );
3350 | m_data->m_animationTakeCmb->setEnabled( false );
3351 | propertiesLyt->addWidget( m_data->m_animationTakeCmb );
3352 | DzConnect( m_data->m_animationTakeCmb, SIGNAL(activated(const QString&)),
3353 | importer, SLOT(setTakeName(const QString&)) );
3354 |
3355 | DzConnect( m_data->m_includeAnimationCbx, SIGNAL(toggled(bool)),
3356 | m_data->m_animationTakeCmb, SLOT(setEnabled(bool)) );
3357 |
3358 | propertiesGBox->setLayout( propertiesLyt );
3359 |
3360 | scrollableOptionsLyt->addWidget( propertiesGBox );
3361 |
3362 |
3363 | // Geometry
3364 | QGroupBox* geometryGBox = new QGroupBox( tr( "Geometry :" ) );
3365 | geometryGBox->setObjectName( name % "GeometryGBox" );
3366 |
3367 | QBoxLayout* geometryLyt = new QVBoxLayout();
3368 | geometryLyt->setSpacing( margin );
3369 | geometryLyt->setMargin( margin );
3370 |
3371 | m_data->m_includePolygonSetsCbx = new QCheckBox();
3372 | m_data->m_includePolygonSetsCbx->setObjectName( name % "IncludePolygonSetsCbx" );
3373 | m_data->m_includePolygonSetsCbx->setText( tr( "Include Polygon Sets" ) );
3374 | geometryLyt->addWidget( m_data->m_includePolygonSetsCbx );
3375 | DzConnect( m_data->m_includePolygonSetsCbx, SIGNAL(toggled(bool)),
3376 | importer, SLOT(setIncludePolygonSets(bool)) );
3377 |
3378 | m_data->m_includePolygonGroupsCbx = new QCheckBox();
3379 | m_data->m_includePolygonGroupsCbx->setObjectName( name % "IncludePolygonGroupsCbx" );
3380 | m_data->m_includePolygonGroupsCbx->setText( tr( "Include Polygon Groups" ) );
3381 | geometryLyt->addWidget( m_data->m_includePolygonGroupsCbx );
3382 | DzConnect( m_data->m_includePolygonGroupsCbx, SIGNAL(toggled(bool)),
3383 | importer, SLOT(setIncludePolygonGroups(bool)) );
3384 |
3385 | geometryGBox->setLayout( geometryLyt );
3386 |
3387 | scrollableOptionsLyt->addWidget( geometryGBox );
3388 |
3389 |
3390 | // Custom Data
3391 | QGroupBox* customDataGBox = new QGroupBox( tr( "Custom Data :" ) );
3392 | customDataGBox->setObjectName( name % "CustomDataGBox" );
3393 |
3394 | QVBoxLayout* customDataLyt = new QVBoxLayout();
3395 | customDataLyt->setSpacing( margin );
3396 | customDataLyt->setMargin( margin );
3397 |
3398 | m_data->m_studioNodeNameLabelCbx = new QCheckBox();
3399 | m_data->m_studioNodeNameLabelCbx->setObjectName( name % "IncludeNodeNameLabelCbx" );
3400 | m_data->m_studioNodeNameLabelCbx->setText( tr( "Include Node Names/Labels" ) );
3401 | customDataLyt->addWidget( m_data->m_studioNodeNameLabelCbx );
3402 | DzConnect( m_data->m_studioNodeNameLabelCbx, SIGNAL(toggled(bool)),
3403 | importer, SLOT(setStudioNodeNamesLabels(bool)) );
3404 |
3405 | m_data->m_studioPresentationCbx = new QCheckBox();
3406 | m_data->m_studioPresentationCbx->setObjectName( name % "IncludePresentationCbx" );
3407 | m_data->m_studioPresentationCbx->setText( tr( "Include Presentation" ) );
3408 | customDataLyt->addWidget( m_data->m_studioPresentationCbx );
3409 | DzConnect( m_data->m_studioPresentationCbx, SIGNAL(toggled(bool)),
3410 | importer, SLOT(setStudioNodePresentation(bool)) );
3411 |
3412 | m_data->m_studioSelectionMapCbx = new QCheckBox();
3413 | m_data->m_studioSelectionMapCbx->setObjectName( name % "IncludeSelectionMapCbx" );
3414 | m_data->m_studioSelectionMapCbx->setText( tr( "Include Node Selection Map" ) );
3415 | customDataLyt->addWidget( m_data->m_studioSelectionMapCbx );
3416 | DzConnect( m_data->m_studioSelectionMapCbx, SIGNAL(toggled(bool)),
3417 | importer, SLOT(setStudioNodeSelectionMap(bool)) );
3418 |
3419 | m_data->m_studioSceneIDsCbx = new QCheckBox();
3420 | m_data->m_studioSceneIDsCbx->setObjectName( name % "IncludeSceneIDssCbx" );
3421 | m_data->m_studioSceneIDsCbx->setText( tr( "Include Scene IDs" ) );
3422 | customDataLyt->addWidget( m_data->m_studioSceneIDsCbx );
3423 | DzConnect( m_data->m_studioSceneIDsCbx, SIGNAL(toggled(bool)),
3424 | importer, SLOT(setStudioSceneIDs(bool)) );
3425 |
3426 | customDataGBox->setLayout( customDataLyt );
3427 |
3428 | scrollableOptionsLyt->addWidget( customDataGBox );
3429 |
3430 | scrollableOptionsWgt->setLayout( scrollableOptionsLyt );
3431 |
3432 | QScrollArea* scrollableOptionsArea = createScrollableWidget( scrollableOptionsWgt, margin, margin, name % "Options" );
3433 |
3434 |
3435 | // Footer
3436 | const QString errorList = importer->getErrorList().join( "\n" );
3437 |
3438 | QGroupBox* reportGrp = new QGroupBox();
3439 | reportGrp->setObjectName( name % "PreImportReportGBox" );
3440 | reportGrp->setTitle( tr( "Pre-Import Report :" ) );
3441 |
3442 | QVBoxLayout* reportLyt = new QVBoxLayout();
3443 | reportLyt->setSpacing( margin );
3444 | reportLyt->setMargin( margin );
3445 |
3446 | QLabel* preImportLbl = new QLabel();
3447 | preImportLbl->setObjectName( name % "PreImportReportLbl" );
3448 | preImportLbl->setText( !errorList.isEmpty() ? errorList : tr( "Import Ready." ) );
3449 | preImportLbl->setTextInteractionFlags( Qt::TextBrowserInteraction );
3450 |
3451 | QScrollArea* preImportScroll = createScrollableWidget( preImportLbl, margin, margin, name % "PreImportReport" );
3452 |
3453 | reportLyt->addWidget( preImportScroll, 1 );
3454 |
3455 | reportGrp->setLayout( reportLyt );
3456 |
3457 |
3458 | DzDynamicDividerWgt* optionsStagingDvdr = new DzDynamicDividerWgt();
3459 | optionsStagingDvdr->setObjectName( name % "OptionsReportDvdr" );
3460 | optionsStagingDvdr->setDividerBar( Qt::Horizontal, DzDividerBar::BSThin );
3461 | optionsStagingDvdr->setMargin( margin );
3462 | optionsStagingDvdr->setFirstWidget( scrollableOptionsArea );
3463 | optionsStagingDvdr->setSecondWidget( reportGrp );
3464 | optionsStagingDvdr->setPreferredDividerPercent( 0.7 );
3465 | mainLyt->addWidget( optionsStagingDvdr, 10 );
3466 |
3467 | setLayout( mainLyt );
3468 |
3469 | // --------
3470 |
3471 | int leftWidth = 0;
3472 | for ( int i = 0, n = leftLabels.count(); i < n; ++i )
3473 | {
3474 | lbl = leftLabels.at( i );
3475 | const int minWidth = lbl->minimumSizeHint().width();
3476 | if ( minWidth > leftWidth )
3477 | {
3478 | leftWidth = minWidth;
3479 | }
3480 | }
3481 |
3482 | for ( int i = 0, n = leftLabels.count(); i < n; ++i )
3483 | {
3484 | lbl = leftLabels.at( i );
3485 | lbl->setFixedWidth( leftWidth );
3486 | }
3487 |
3488 | DzFbxImportFrame::resetOptions();
3489 | }
3490 |
3491 | /**
3492 | **/
3493 | DzFbxImportFrame::~DzFbxImportFrame()
3494 | {}
3495 |
3496 | /**
3497 | **/
3498 | void DzFbxImportFrame::setOptions( const DzFileIOSettings* settings, const QString &filename )
3499 | {
3500 | assert( settings );
3501 | if ( !settings )
3502 | {
3503 | return;
3504 | }
3505 |
3506 | // Properties
3507 | m_data->m_includeRotationLimitsCbx->setChecked( settings->getBoolValue( c_optIncRotationLimits, c_defaultIncludeRotationLimits ) );
3508 | m_data->m_includeAnimationCbx->setChecked( settings->getBoolValue( c_optIncAnimations, c_defaultIncludeAnimations ) );
3509 | const QString take = settings->getStringValue( c_optTake, QString() );
3510 | for ( int i = 0; i < m_data->m_animationTakeCmb->count(); i++ )
3511 | {
3512 | if ( m_data->m_animationTakeCmb->itemText( i ) == take )
3513 | {
3514 | m_data->m_animationTakeCmb->setCurrentIndex( i );
3515 | break;
3516 | }
3517 | }
3518 |
3519 | // Geometry
3520 | m_data->m_includePolygonSetsCbx->setChecked( settings->getBoolValue( c_optIncPolygonSets, c_defaultIncludePolygonSets ) );
3521 | m_data->m_includePolygonGroupsCbx->setChecked( settings->getBoolValue( c_optIncPolygonGroups, c_defaultIncludePolygonGroups ) );
3522 |
3523 | // Custom Data
3524 | m_data->m_studioNodeNameLabelCbx->setChecked( settings->getBoolValue( c_optStudioNodeNamesLabels, c_defaultStudioNodeNames ) );
3525 | m_data->m_studioPresentationCbx->setChecked( settings->getBoolValue( c_optStudioPresentation, c_defaultStudioNodePresentation ) );
3526 | m_data->m_studioSelectionMapCbx->setChecked( settings->getBoolValue( c_optStudioNodeSelectionMap, c_defaultStudioNodeSelectionMap ) );
3527 | m_data->m_studioSceneIDsCbx->setChecked( settings->getBoolValue( c_optStudioSceneIDs, c_defaultStudioSceneIDs ) );
3528 | }
3529 |
3530 | /**
3531 | **/
3532 | void DzFbxImportFrame::getOptions( DzFileIOSettings* settings ) const
3533 | {
3534 | assert( settings );
3535 | if ( !settings )
3536 | {
3537 | return;
3538 | }
3539 |
3540 | // Properties
3541 | settings->setBoolValue( c_optIncRotationLimits, m_data->m_includeRotationLimitsCbx->isChecked() );
3542 | settings->setBoolValue( c_optIncAnimations, m_data->m_includeAnimationCbx->isChecked() );
3543 | const QString animTake = m_data->m_animationTakeCmb->currentText();
3544 | settings->setStringValue( c_optTake, animTake != tr( c_none ) ? animTake : QString() );
3545 |
3546 | // Geometry
3547 | settings->setBoolValue( c_optIncPolygonSets, m_data->m_includePolygonSetsCbx->isChecked() );
3548 | settings->setBoolValue( c_optIncPolygonGroups, m_data->m_includePolygonGroupsCbx->isChecked() );
3549 |
3550 | // Custom Data
3551 | settings->setBoolValue( c_optStudioNodeNamesLabels, m_data->m_studioNodeNameLabelCbx->isChecked() );
3552 | settings->setBoolValue( c_optStudioPresentation, m_data->m_studioPresentationCbx->isChecked() );
3553 | settings->setBoolValue( c_optStudioNodeSelectionMap, m_data->m_studioSelectionMapCbx->isChecked() );
3554 | settings->setBoolValue( c_optStudioSceneIDs, m_data->m_studioSceneIDsCbx->isChecked() );
3555 | }
3556 |
3557 | /**
3558 | **/
3559 | void DzFbxImportFrame::applyChanges()
3560 | {
3561 | }
3562 |
3563 | /**
3564 | **/
3565 | void DzFbxImportFrame::resetOptions()
3566 | {
3567 | DzFileIOSettings* ioSettings = new DzFileIOSettings();
3568 | m_data->m_importer->getDefaultOptions( ioSettings );
3569 | setOptions( ioSettings, QString() );
3570 | }
3571 |
3572 | #include "moc_dzfbximporter.cpp"
--------------------------------------------------------------------------------