2012-03-23 02:28:46 +00:00
//
// KRResource+fbx.cpp
// KREngine
//
// Created by Kearwood Gilbert on 12-03-22.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
2013-01-11 03:21:19 +00:00
# include "KREngine-common.h"
2013-04-04 12:50:53 -07:00
# include <boost/tokenizer.hpp>
# include <boost/lexical_cast.hpp>
2013-12-05 19:44:58 -08:00
# include <boost/variant.hpp>
2012-03-23 02:28:46 +00:00
# include <fbxsdk.h>
# include "KRResource.h"
2013-01-09 22:37:23 +00:00
# include "KRMesh.h"
2012-03-28 21:58:55 +00:00
# include "KRMaterial.h"
2012-04-05 23:09:41 +00:00
# include "KRLight.h"
# include "KRPointLight.h"
# include "KRDirectionalLight.h"
# include "KRSpotLight.h"
2012-04-12 00:43:53 +00:00
# include "KRNode.h"
# include "KRScene.h"
2012-12-07 08:22:20 +00:00
# include "KRBone.h"
2013-10-06 18:56:23 -07:00
# include "KRLocator.h"
2012-12-20 01:23:57 +00:00
# include "KRBundle.h"
2013-01-09 22:37:23 +00:00
# include "KRModel.h"
2013-04-04 12:50:53 -07:00
# include "KRLODGroup.h"
2014-03-10 22:32:49 -07:00
# include "KRLODSet.h"
2012-12-20 01:53:09 +00:00
# include "KRCollider.h"
2012-03-23 02:28:46 +00:00
# ifdef IOS_REF
# undef IOS_REF
# define IOS_REF (*(pSdkManager->GetIOSettings()))
# endif
2013-12-14 16:37:14 -08:00
# define warning(e,s) if(!(e))KRContext::Log(KRContext::LOG_LEVEL_WARNING, "%s\n",s)
2013-12-14 14:20:30 -08:00
2013-11-23 12:16:31 -08:00
void InitializeSdkObjects ( FbxManager * & pSdkManager , FbxScene * & pScene ) ;
void DestroySdkObjects ( FbxManager * pSdkManager ) ;
bool LoadScene ( FbxManager * pSdkManager , FbxDocument * pScene , const char * pFilename ) ;
2012-12-01 02:03:18 +00:00
KRAnimation * LoadAnimation ( KRContext & context , FbxAnimStack * pAnimStack ) ;
2012-12-07 00:20:06 +00:00
KRAnimationCurve * LoadAnimationCurve ( KRContext & context , FbxAnimCurve * pAnimCurve ) ;
2012-12-01 02:03:18 +00:00
KRAnimationLayer * LoadAnimationLayer ( KRContext & context , FbxAnimLayer * pAnimLayer ) ;
2013-11-23 12:16:31 -08:00
void LoadNode ( FbxScene * pFbxScene , KRNode * parent_node , FbxGeometryConverter * pGeometryConverter , FbxNode * pNode ) ;
2012-12-01 02:03:18 +00:00
//void BakeNode(KFbxNode* pNode);
2013-05-06 14:06:29 -07:00
void LoadMaterial ( KRContext & context , FbxSurfaceMaterial * pMaterial ) ;
2016-08-07 20:28:15 -07:00
void LoadMesh ( KRContext & context , FbxScene * pFbxScene , FbxGeometryConverter * pGeometryConverter , FbxMesh * pMesh ) ;
2013-11-23 12:16:31 -08:00
KRNode * LoadMesh ( KRNode * parent_node , FbxScene * pFbxScene , FbxGeometryConverter * pGeometryConverter , FbxNode * pNode ) ;
KRNode * LoadLight ( KRNode * parent_node , FbxNode * pNode ) ;
KRNode * LoadSkeleton ( KRNode * parent_node , FbxScene * pScene , FbxNode * pNode ) ;
KRNode * LoadLocator ( KRNode * parent_node , FbxScene * pScene , FbxNode * pNode ) ;
KRNode * LoadCamera ( KRNode * parent_node , FbxNode * pNode ) ;
2012-12-07 08:22:20 +00:00
std : : string GetFbxObjectName ( FbxObject * obj ) ;
2012-03-23 02:28:46 +00:00
2012-11-29 21:28:49 +00:00
const float KRAKEN_FBX_ANIMATION_FRAMERATE = 30.0f ; // FINDME - This should be configurable
2012-12-07 00:20:06 +00:00
2012-12-07 08:22:20 +00:00
std : : string GetFbxObjectName ( FbxObject * obj )
2012-12-07 00:20:06 +00:00
{
2013-10-06 18:56:23 -07:00
bool is_locator = false ;
2013-11-23 12:16:31 -08:00
FbxNode * node = FbxCast < FbxNode > ( obj ) ;
2013-10-06 18:56:23 -07:00
if ( node ) {
2013-11-23 12:16:31 -08:00
FbxNodeAttribute : : EType attribute_type = ( node - > GetNodeAttribute ( ) - > GetAttributeType ( ) ) ;
if ( attribute_type = = FbxNodeAttribute : : eNull ) {
FbxNull * pSourceNull = ( FbxNull * ) node - > GetNodeAttribute ( ) ;
if ( pSourceNull - > Look . Get ( ) = = FbxNull : : eCross ) {
2013-10-06 18:56:23 -07:00
is_locator = true ;
}
}
}
2012-12-07 08:22:55 +00:00
// Object names from FBX files are now concatenated with the FBX numerical ID to ensure that they are unique
// TODO - This should be updated to only add a prefix or suffix if needed to make the name unique
2013-10-06 18:56:23 -07:00
if ( is_locator ) {
// We do not rename locators
return std : : string ( obj - > GetName ( ) ) ;
2013-11-23 12:16:31 -08:00
} else if ( strncmp ( obj - > GetName ( ) , " so_ " , 3 ) = = 0 ) {
// An so_ prefix indicates that this is a "Scriptable Object" that should not have the name decorated;
return obj - > GetName ( ) ;
2013-10-06 18:56:23 -07:00
} else if ( strcmp ( obj - > GetName ( ) , " default_camera " ) = = 0 ) {
2013-05-24 12:20:47 -07:00
// There is currently support for rendering from only one camera, "default_camera". We don't translate this node's name, so that animations can drive the camera
return " default_camera " ;
} else {
std : : stringstream st ;
st < < " fbx_ " ;
st < < obj - > GetUniqueID ( ) ;
if ( strlen ( obj - > GetName ( ) ) ! = 0 ) {
st < < " _ " ;
st < < obj - > GetName ( ) ;
}
return st . str ( ) ;
2012-12-07 00:20:06 +00:00
}
}
2013-05-06 14:06:29 -07:00
void KRResource : : LoadFbx ( KRContext & context , const std : : string & path )
2012-03-23 02:28:46 +00:00
{
2012-09-05 18:14:08 +00:00
KRScene * pScene = new KRScene ( context , KRResource : : GetFileBase ( path ) ) ;
2013-05-06 14:06:29 -07:00
context . getSceneManager ( ) - > add ( pScene ) ;
2012-04-12 00:43:53 +00:00
2013-11-23 12:16:31 -08:00
FbxManager * lSdkManager = NULL ;
FbxScene * pFbxScene = NULL ;
2012-03-23 02:28:46 +00:00
bool lResult ;
2012-11-30 00:32:03 +00:00
FbxGeometryConverter * pGeometryConverter = NULL ;
2012-03-23 02:28:46 +00:00
// Prepare the FBX SDK.
2012-04-12 00:43:53 +00:00
InitializeSdkObjects ( lSdkManager , pFbxScene ) ;
2012-03-23 02:28:46 +00:00
// Initialize Geometry Converter
2012-11-30 00:32:03 +00:00
pGeometryConverter = new FbxGeometryConverter ( lSdkManager ) ;
2012-03-23 02:28:46 +00:00
// Load the scene.
2012-04-12 00:43:53 +00:00
lResult = LoadScene ( lSdkManager , pFbxScene , path . c_str ( ) ) ;
2016-08-07 20:28:15 -07:00
// Triangulate the scene.
lResult = pGeometryConverter - > Triangulate ( pFbxScene , true ) ;
2012-03-23 02:28:46 +00:00
2013-11-23 12:16:31 -08:00
FbxNode * pNode = pFbxScene - > GetRootNode ( ) ;
2012-03-23 02:28:46 +00:00
2013-05-13 13:16:25 -07:00
// ----====---- Bake pivots into transforms, as Kraken doesn't support them directly ----====----
/*
2012-12-01 02:03:18 +00:00
printf ( " Baking pivots... \n " ) ;
2013-05-13 13:16:25 -07:00
2012-12-01 02:03:18 +00:00
if ( pNode ) {
pNode - > ResetPivotSetAndConvertAnimation ( ) ;
}
2013-05-13 13:16:25 -07:00
*/
2013-04-04 16:09:29 -07:00
2012-12-20 01:23:57 +00:00
// ----====---- Import Animation Layers ----====----
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " \n Loading animations... " ) ;
2012-12-07 00:20:06 +00:00
int animation_count = pFbxScene - > GetSrcObjectCount < FbxAnimStack > ( ) ;
2012-12-02 09:31:01 +00:00
for ( int i = 0 ; i < animation_count ; i + + ) {
2012-12-20 01:23:57 +00:00
FbxAnimStack * animation = pFbxScene - > GetSrcObject < FbxAnimStack > ( i ) ;
2013-12-14 18:03:51 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Animation %i of %i: %s " , i + 1 , animation_count , animation - > GetName ( ) ) ;
2012-12-20 01:23:57 +00:00
KRAnimation * new_animation = LoadAnimation ( context , animation ) ;
2013-01-11 03:21:19 +00:00
if ( new_animation ) {
context . getAnimationManager ( ) - > addAnimation ( new_animation ) ;
}
2012-12-07 00:20:06 +00:00
}
// ----====---- Import Animation Curves ----====----
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " \n Loading animation curves... " ) ;
2012-12-07 00:20:06 +00:00
int curve_count = pFbxScene - > GetSrcObjectCount < FbxAnimCurve > ( ) ;
for ( int i = 0 ; i < curve_count ; i + + ) {
2012-12-20 01:23:57 +00:00
FbxAnimCurve * curve = pFbxScene - > GetSrcObject < FbxAnimCurve > ( i ) ;
2013-12-14 18:03:51 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Animation Curve %i of %i: %s " , i + 1 , curve_count , curve - > GetName ( ) ) ;
2012-12-20 01:23:57 +00:00
KRAnimationCurve * new_curve = LoadAnimationCurve ( context , curve ) ;
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
2013-01-11 03:21:19 +00:00
if ( new_curve ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Adding a curve " ) ;
2013-01-11 03:21:19 +00:00
context . getAnimationCurveManager ( ) - > addAnimationCurve ( new_curve ) ;
}
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
}
2012-12-02 09:31:01 +00:00
2013-05-06 12:58:57 -07:00
// ----====---- Import Materials ----====----
int material_count = pFbxScene - > GetSrcObjectCount < FbxSurfaceMaterial > ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " \n Loading materials... " ) ;
2013-05-06 12:58:57 -07:00
for ( int i = 0 ; i < material_count ; i + + ) {
FbxSurfaceMaterial * material = pFbxScene - > GetSrcObject < FbxSurfaceMaterial > ( i ) ;
2013-12-14 18:03:51 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Material %i of %i: %s " , i + 1 , material_count , material - > GetName ( ) ) ;
2013-05-06 14:06:29 -07:00
LoadMaterial ( context , material ) ;
2013-05-06 12:58:57 -07:00
}
2012-12-20 01:23:57 +00:00
// ----====---- Import Meshes ----====----
int mesh_count = pFbxScene - > GetSrcObjectCount < FbxMesh > ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Loading meshes... " ) ;
2012-12-20 01:23:57 +00:00
for ( int i = 0 ; i < mesh_count ; i + + ) {
FbxMesh * mesh = pFbxScene - > GetSrcObject < FbxMesh > ( i ) ;
2013-12-14 18:03:51 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Mesh %i of %i: %s " , i + 1 , mesh_count , mesh - > GetNode ( ) - > GetName ( ) ) ;
2013-05-24 12:20:47 -07:00
LoadMesh ( context , pFbxScene , pGeometryConverter , mesh ) ;
2012-03-23 02:28:46 +00:00
}
2012-12-20 01:23:57 +00:00
// ----====---- Import Textures ----====----
int texture_count = pFbxScene - > GetSrcObjectCount < FbxFileTexture > ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Loading textures... " ) ;
2012-12-20 01:23:57 +00:00
for ( int i = 0 ; i < texture_count ; i + + ) {
FbxFileTexture * texture = pFbxScene - > GetSrcObject < FbxFileTexture > ( i ) ;
const char * file_name = texture - > GetFileName ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Texture %i of %i: %s " , i + 1 , texture_count , ( KRResource : : GetFileBase ( file_name ) + " . " + KRResource : : GetFileExtension ( file_name ) ) . c_str ( ) ) ;
2012-12-20 01:23:57 +00:00
context . loadResource ( file_name ) ;
}
2013-04-04 16:09:29 -07:00
// ----====---- Import Scene Graph Nodes ----====----
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Loading scene graph... " ) ;
2013-04-04 16:09:29 -07:00
if ( pNode )
{
for ( int i = 0 ; i < pNode - > GetChildCount ( ) ; i + + )
{
2013-05-06 14:06:29 -07:00
LoadNode ( pFbxScene , pScene - > getRootNode ( ) , pGeometryConverter , pNode - > GetChild ( i ) ) ;
2013-04-04 16:09:29 -07:00
}
}
2012-12-07 00:20:06 +00:00
2013-01-24 13:52:26 -08:00
2012-12-20 01:23:57 +00:00
2013-05-06 14:06:29 -07:00
DestroySdkObjects ( lSdkManager ) ;
2012-03-23 02:28:46 +00:00
}
2013-11-23 12:16:31 -08:00
void InitializeSdkObjects ( FbxManager * & pSdkManager , FbxScene * & pScene )
2012-03-23 02:28:46 +00:00
{
// The first thing to do is to create the FBX SDK manager which is the
// object allocator for almost all the classes in the SDK.
2013-11-23 12:16:31 -08:00
pSdkManager = FbxManager : : Create ( ) ;
2012-03-23 02:28:46 +00:00
if ( ! pSdkManager )
{
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_ERROR , " Unable to create the FBX SDK manager " ) ;
2012-03-23 02:28:46 +00:00
exit ( 0 ) ;
}
// create an IOSettings object
2013-11-23 12:16:31 -08:00
FbxIOSettings * ios = FbxIOSettings : : Create ( pSdkManager , IOSROOT ) ;
2012-03-23 02:28:46 +00:00
pSdkManager - > SetIOSettings ( ios ) ;
// Load plugins from the executable directory
2013-11-23 12:16:31 -08:00
FbxString lPath = FbxGetApplicationDirectory ( ) ;
2016-08-07 20:28:15 -07:00
# if defined(_WIN32) || defined(_WIN64)
2013-11-23 12:16:31 -08:00
FbxString lExtension = " dll " ;
# elif TARGET_OS_MAC
FbxString lExtension = " dylib " ;
# elif TARGET_OS_UNIX
FbxString lExtension = " so " ;
# elif
# error Unsupported Platform
2012-03-23 02:28:46 +00:00
# endif
pSdkManager - > LoadPluginsDirectory ( lPath . Buffer ( ) , lExtension . Buffer ( ) ) ;
// Create the entity that will hold the scene.
2013-11-23 12:16:31 -08:00
pScene = FbxScene : : Create ( pSdkManager , " " ) ;
2012-03-23 02:28:46 +00:00
}
2013-11-23 12:16:31 -08:00
void DestroySdkObjects ( FbxManager * pSdkManager )
2012-03-23 02:28:46 +00:00
{
// Delete the FBX SDK manager. All the objects that have been allocated
// using the FBX SDK manager and that haven't been explicitly destroyed
// are automatically destroyed at the same time.
if ( pSdkManager ) pSdkManager - > Destroy ( ) ;
pSdkManager = NULL ;
}
2013-11-23 12:16:31 -08:00
bool LoadScene ( FbxManager * pSdkManager , FbxDocument * pScene , const char * pFilename )
2012-03-23 02:28:46 +00:00
{
int lFileMajor , lFileMinor , lFileRevision ;
int lSDKMajor , lSDKMinor , lSDKRevision ;
//int lFileFormat = -1;
2012-12-01 02:03:18 +00:00
int lAnimStackCount ;
2012-03-23 02:28:46 +00:00
bool lStatus ;
char lPassword [ 1024 ] ;
// Get the file version number generate by the FBX SDK.
2013-11-23 12:16:31 -08:00
FbxManager : : GetFileFormatVersion ( lSDKMajor , lSDKMinor , lSDKRevision ) ;
2012-03-23 02:28:46 +00:00
// Create an importer.
2013-11-23 12:16:31 -08:00
FbxImporter * lImporter = FbxImporter : : Create ( pSdkManager , " " ) ;
2012-03-23 02:28:46 +00:00
// Initialize the importer by providing a filename.
const bool lImportStatus = lImporter - > Initialize ( pFilename , - 1 , pSdkManager - > GetIOSettings ( ) ) ;
lImporter - > GetFileVersion ( lFileMajor , lFileMinor , lFileRevision ) ;
if ( ! lImportStatus )
{
2013-11-23 12:16:31 -08:00
FbxStatus & status = lImporter - > GetStatus ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_ERROR , " Call to KFbxImporter::Initialize() failed. \n Error returned: %s " , status . GetErrorString ( ) ) ;
2013-11-23 12:16:31 -08:00
2012-03-23 02:28:46 +00:00
2013-11-23 12:16:31 -08:00
if ( status . GetCode ( ) = = FbxStatus : : EStatusCode : : eInvalidFileVersion )
2012-03-23 02:28:46 +00:00
{
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " FBX version number for this FBX SDK is %d.%d.%d " , lSDKMajor , lSDKMinor , lSDKRevision ) ;
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " FBX version number for file %s is %d.%d.%d " , pFilename , lFileMajor , lFileMinor , lFileRevision ) ;
2012-03-23 02:28:46 +00:00
}
return false ;
}
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " FBX version number for this FBX SDK is %d.%d.%d " , lSDKMajor , lSDKMinor , lSDKRevision ) ;
2012-03-23 02:28:46 +00:00
2012-11-29 21:28:49 +00:00
if ( ! lImporter - > IsFBX ( ) ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_ERROR , " ERROR Unrecognized FBX File " ) ;
2012-11-29 21:28:49 +00:00
return false ;
}
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " FBX version number for file %s is %d.%d.%d \n " , pFilename , lFileMajor , lFileMinor , lFileRevision ) ;
2012-11-29 21:28:49 +00:00
// From this point, it is possible to access animation stack information without
// the expense of loading the entire file.
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Animation Stack Information " ) ;
2012-11-29 21:28:49 +00:00
lAnimStackCount = lImporter - > GetAnimStackCount ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Number of Animation Stacks: %d " , lAnimStackCount ) ;
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Current Animation Stack: \" %s \" " , lImporter - > GetActiveAnimStackName ( ) . Buffer ( ) ) ;
2012-11-29 21:28:49 +00:00
2012-03-23 02:28:46 +00:00
2012-11-29 21:28:49 +00:00
// Set the import states. By default, the import states are always set to
// true. The code below shows how to change these states.
IOS_REF . SetBoolProp ( IMP_FBX_MATERIAL , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_TEXTURE , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_LINK , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_SHAPE , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_GOBO , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_ANIMATION , true ) ;
IOS_REF . SetBoolProp ( IMP_FBX_GLOBAL_SETTINGS , true ) ;
2012-03-23 02:28:46 +00:00
// Import the scene.
lStatus = lImporter - > Import ( pScene ) ;
2013-11-23 12:16:31 -08:00
if ( lStatus = = false & & lImporter - > GetStatus ( ) . GetCode ( ) = = FbxStatus : : EStatusCode : : ePasswordError )
2012-03-23 02:28:46 +00:00
{
printf ( " Please enter password: " ) ;
lPassword [ 0 ] = ' \0 ' ;
scanf ( " %s " , lPassword ) ;
2013-11-23 12:16:31 -08:00
FbxString lString ( lPassword ) ;
2012-03-23 02:28:46 +00:00
IOS_REF . SetStringProp ( IMP_FBX_PASSWORD , lString ) ;
IOS_REF . SetBoolProp ( IMP_FBX_PASSWORD_ENABLE , true ) ;
lStatus = lImporter - > Import ( pScene ) ;
2013-11-23 12:16:31 -08:00
if ( lStatus = = false & & lImporter - > GetStatus ( ) . GetCode ( ) = = FbxStatus : : EStatusCode : : ePasswordError )
2012-03-23 02:28:46 +00:00
{
printf ( " \n Password is wrong, import aborted. \n " ) ;
}
}
2012-12-01 02:03:18 +00:00
// // ----====---- Start: Bake pivots into transforms, as Kraken doesn't support them directly ----====----
//
// printf("Baking pivots...\n");
// KFbxNode* pNode = ((KFbxScene*)pScene)->GetRootNode();
//// BakeNode(pNode);
//
// for(i = 0; i < lAnimStackCount; i++)
// {
// KFbxTakeInfo* lTakeInfo = lImporter->GetTakeInfo(i);
//
// printf(" Animation: \"%s\"\n", lTakeInfo->mName.Buffer());
//
// //pNode->ConvertPivotAnimationRecursive(lTakeInfo->mName.Buffer(), KFbxNode::eDestinationPivot, KRAKEN_FBX_ANIMATION_FRAMERATE);
// pNode->ResetPivotSetAndConvertAnimation();
//
// }
//// pNode->ConvertPivotAnimationRecursive(NULL, KFbxNode::eDestinationPivot, KRAKEN_FBX_ANIMATION_FRAMERATE);
//// pNode->UpdatePropertiesFromPivotsAndLimits();
//
// // ----====---- End: Bake pivots into transforms, as Kraken doesn't support them directly ----====----
// // ----====---- Bake pivots into transforms, as Kraken doesn't support them directly ----====----
//
// printf("Baking pivots...\n");
// KFbxNode* pNode = ((KFbxScene*)pScene)->GetRootNode();
// if(pNode) {
// pNode->ResetPivotSetAndConvertAnimation();
// }
2012-11-29 21:28:49 +00:00
2012-03-23 02:28:46 +00:00
// Destroy the importer.
lImporter - > Destroy ( ) ;
return lStatus ;
}
2012-12-01 02:03:18 +00:00
KRAnimation * LoadAnimation ( KRContext & context , FbxAnimStack * pAnimStack )
{
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Loading animation: \" %s \" " , pAnimStack - > GetName ( ) ) ;
2012-12-01 02:03:18 +00:00
KRAnimation * new_animation = new KRAnimation ( context , pAnimStack - > GetName ( ) ) ;
int cLayers = pAnimStack - > GetMemberCount < FbxAnimLayer > ( ) ;
2012-12-07 01:49:17 +00:00
new_animation - > setDuration ( pAnimStack - > LocalStop . Get ( ) . GetSecondDouble ( ) ) ;
2012-12-01 02:03:18 +00:00
for ( int iLayer = 0 ; iLayer < cLayers ; iLayer + + ) {
new_animation - > addLayer ( LoadAnimationLayer ( context , pAnimStack - > GetMember < FbxAnimLayer > ( iLayer ) ) ) ;
2012-11-29 21:28:49 +00:00
}
2012-12-01 02:03:18 +00:00
return new_animation ;
2012-11-29 21:28:49 +00:00
}
2012-12-07 00:20:06 +00:00
KRAnimationCurve * LoadAnimationCurve ( KRContext & context , FbxAnimCurve * pAnimCurve )
{
2012-12-07 08:22:20 +00:00
std : : string name = GetFbxObjectName ( pAnimCurve ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Loading animation curve: \" %s \" " , name . c_str ( ) ) ;
2012-12-07 00:20:06 +00:00
FbxTimeSpan time_span ;
if ( ! pAnimCurve - > GetTimeInterval ( time_span ) ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_ERROR , " Failed to get time interval. " ) ;
2012-12-07 00:20:06 +00:00
return NULL ;
}
2013-08-31 19:22:37 -07:00
float dest_frame_rate = 30.0f ; // FINDME, TODO - This needs to be dynamic
int frame_start = time_span . GetStart ( ) . GetSecondDouble ( ) * dest_frame_rate ;
int frame_count = ( time_span . GetStop ( ) . GetSecondDouble ( ) * dest_frame_rate ) - frame_start ;
2012-12-07 00:20:06 +00:00
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " animation start %d and frame count %d " , frame_start , frame_count ) ;
2013-12-02 17:44:55 -08:00
2012-12-07 00:20:06 +00:00
KRAnimationCurve * new_curve = new KRAnimationCurve ( context , name ) ;
2013-08-31 19:22:37 -07:00
new_curve - > setFrameRate ( dest_frame_rate ) ;
2012-12-07 00:20:06 +00:00
new_curve - > setFrameStart ( frame_start ) ;
new_curve - > setFrameCount ( frame_count ) ;
// Resample animation curve
int last_frame = 0 ; // Used by FBX sdk for faster keyframe searches
for ( int frame_number = 0 ; frame_number < frame_count ; frame_number + + ) {
2013-08-31 19:22:37 -07:00
float frame_seconds = ( frame_start + frame_number ) / dest_frame_rate ;
2012-12-07 00:20:06 +00:00
FbxTime frame_time ;
frame_time . SetSecondDouble ( frame_seconds ) ;
float frame_value = pAnimCurve - > Evaluate ( frame_time , & last_frame ) ;
2013-12-02 17:44:55 -08:00
// printf(" Frame %i / %i: %.6f\n", frame_number, frame_count, frame_value);
2013-12-14 16:37:14 -08:00
if ( 0 = = frame_number ) KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Value at starting key frame = %3.3f " , frame_value ) ;
2013-12-02 17:44:55 -08:00
new_curve - > setValue ( frame_number + frame_start , frame_value ) ;
// BUG FIX Dec 2, 2013 .. changed frame_number to frame_number+frame_start
// setValue(frame_number, frame_value) clamps the frame_number range between frame_start : frame_start+frame_count
2012-12-07 00:20:06 +00:00
}
return new_curve ;
}
2012-12-01 02:03:18 +00:00
KRAnimationLayer * LoadAnimationLayer ( KRContext & context , FbxAnimLayer * pAnimLayer )
{
KRAnimationLayer * new_layer = new KRAnimationLayer ( context ) ;
new_layer - > setName ( pAnimLayer - > GetName ( ) ) ;
2012-12-02 09:31:01 +00:00
new_layer - > setWeight ( pAnimLayer - > Weight . Get ( ) / 100.0f ) ;
2012-12-01 02:03:18 +00:00
switch ( pAnimLayer - > BlendMode . Get ( ) ) {
case FbxAnimLayer : : eBlendAdditive :
new_layer - > setBlendMode ( KRAnimationLayer : : KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE ) ;
break ;
case FbxAnimLayer : : eBlendOverride :
new_layer - > setBlendMode ( KRAnimationLayer : : KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE ) ;
break ;
case FbxAnimLayer : : eBlendOverridePassthrough :
new_layer - > setBlendMode ( KRAnimationLayer : : KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH ) ;
break ;
}
switch ( pAnimLayer - > RotationAccumulationMode . Get ( ) ) {
case FbxAnimLayer : : eRotationByLayer :
new_layer - > setRotationAccumulationMode ( KRAnimationLayer : : KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER ) ;
break ;
case FbxAnimLayer : : eRotationByChannel :
new_layer - > setRotationAccumulationMode ( KRAnimationLayer : : KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL ) ;
break ;
}
switch ( pAnimLayer - > ScaleAccumulationMode . Get ( ) ) {
case FbxAnimLayer : : eScaleAdditive :
new_layer - > setScaleAccumulationMode ( KRAnimationLayer : : KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE ) ;
break ;
case FbxAnimLayer : : eScaleMultiply :
new_layer - > setScaleAccumulationMode ( KRAnimationLayer : : KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY ) ;
break ;
}
2012-12-02 09:31:01 +00:00
2012-12-01 02:03:18 +00:00
return new_layer ;
}
//
//void BakeNode(KFbxNode *pNode) {
//
// pNode->SetPivotState(KFbxNode::eSourcePivot, KFbxNode::ePivotActive);
// pNode->SetPivotState(KFbxNode::eDestinationPivot, KFbxNode::ePivotActive);
2012-12-12 09:32:53 +00:00
//
2012-12-01 02:03:18 +00:00
// // Pass the current value to the source pivot.
//// * - Rotation offset (Roff)
//// * - Rotation pivot (Rp)
//// * - Pre-rotation (Rpre)
//// * - Post-rotation (Rpost)
//// * - Scaling offset (Soff)
//// * - Scaling pivot (Sp)
//// * - Geometric translation (Gt)
//// * - Geometric rotation (Gr)
//// * - Geometric scaling (Gs)
// /*
// pNode->SetPostRotation(KFbxNode::eSourcePivot, pNode->PostRotation.Get());
// pNode->SetPreRotation(KFbxNode::eSourcePivot, pNode->PreRotation.Get());
// pNode->SetRotationOffset(KFbxNode::eSourcePivot, pNode->RotationOffset.Get());
// pNode->SetScalingOffset(KFbxNode::eSourcePivot, pNode->ScalingOffset.Get());
// pNode->SetRotationPivot(KFbxNode::eSourcePivot, pNode->RotationPivot.Get());
// pNode->SetScalingPivot(KFbxNode::eSourcePivot, pNode->ScalingPivot.Get());
// pNode->SetGeometricRotation(KFbxNode::eSourcePivot, pNode->GeometricRotation.Get());
// pNode->SetGeometricTranslation(KFbxNode::eSourcePivot, pNode->GeometricTranslation.Get());
// pNode->SetGeometricScaling(KFbxNode::eSourcePivot, pNode->GeometricScaling.Get());
// pNode->SetRotationOrder(KFbxNode::eSourcePivot, pNode->RotationOrder.Get());
// */
//
// // We want to set all these to 0 and bake them into the transforms.
// KFbxVector4 lZero(0.0, 0.0, 0.0);
// KFbxVector4 lOne(1.0, 1.0, 1.0);
// pNode->SetPostRotation(KFbxNode::eDestinationPivot, lZero);
// pNode->SetPreRotation(KFbxNode::eDestinationPivot, lZero);
// pNode->SetRotationOffset(KFbxNode::eDestinationPivot, lZero);
// pNode->SetScalingOffset(KFbxNode::eDestinationPivot, lZero);
// pNode->SetRotationPivot(KFbxNode::eDestinationPivot, lZero);
// pNode->SetScalingPivot(KFbxNode::eDestinationPivot, lZero);
// pNode->SetGeometricRotation(KFbxNode::eDestinationPivot, lZero);
// pNode->SetGeometricTranslation(KFbxNode::eDestinationPivot, lZero);
// pNode->SetGeometricScaling(KFbxNode::eDestinationPivot, lOne);
// pNode->SetRotationOrder(KFbxNode::eDestinationPivot, eEULER_XYZ);
//
//
// /*
// FbxVector4 lZero(0,0,0);
// FbxVector4 lOne(1,1,1);
// pNode->SetPivotState(FbxNode::eSourcePivot, FbxNode::ePivotActive);
// pNode->SetPivotState(FbxNode::eDestinationPivot, FbxNode::ePivotActive);
//
// EFbxRotationOrder lRotationOrder;
// pNode->GetRotationOrder(FbxNode::eSourcePivot , lRotationOrder);
// pNode->SetRotationOrder(FbxNode::eDestinationPivot , lRotationOrder);
//
// //For cameras and lights (without targets) let's compensate the postrotation.
// if( pNode->GetCamera() || pNode->GetLight() )
// {
// if( !pNode->GetTarget() )
// {
// FbxVector4 lRV(90, 0, 0);
// if( pNode->GetCamera() )
// lRV.Set(0, 90, 0);
//
// FbxVector4 prV = pNode->GetPostRotation(FbxNode::eSourcePivot);
// FbxAMatrix lSourceR;
// FbxAMatrix lR(lZero, lRV, lOne);
// FbxVector4 res = prV;
//
// // Rotation order don't affect post rotation, so just use the default XYZ order
// FbxRotationOrder rOrder;
// rOrder.V2M(lSourceR, res);
//
// lR = lSourceR * lR;
// rOrder.M2V(res, lR);
// prV = res;
// pNode->SetPostRotation(FbxNode::eSourcePivot, prV);
// pNode->SetRotationActive(true);
// }
//
// // Point light do not need to be adjusted (since they radiate in all the directions).
// if( pNode->GetLight() && pNode->GetLight()->LightType.Get() == FbxLight::ePoint )
// {
// pNode->SetPostRotation(FbxNode::eSourcePivot, FbxVector4(0,0,0,0));
// }
// }
// // apply Pre rotations only on bones / end of chains
// if( pNode->GetNodeAttribute() && pNode->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton
// || (pNode->GetMarker() && pNode->GetMarker()->GetType() == FbxMarker::eEffectorFK)
// || (pNode->GetMarker() && pNode->GetMarker()->GetType() == FbxMarker::eEffectorIK) )
// {
// if( pNode->GetRotationActive() )
// {
// pNode->SetPreRotation(FbxNode::eDestinationPivot, pNode->GetPreRotation(FbxNode::eSourcePivot));
// }
//
// // No pivots on bones
// pNode->SetRotationPivot(FbxNode::eDestinationPivot, lZero);
// pNode->SetScalingPivot(FbxNode::eDestinationPivot, lZero);
// pNode->SetRotationOffset(FbxNode::eDestinationPivot,lZero);
// pNode->SetScalingOffset(FbxNode::eDestinationPivot, lZero);
// }
// else
// {
// // any other type: no pre-rotation support but...
// pNode->SetPreRotation(FbxNode::eDestinationPivot, lZero);
//
// // support for rotation and scaling pivots.
// pNode->SetRotationPivot(FbxNode::eDestinationPivot, pNode->GetRotationPivot(FbxNode::eSourcePivot));
// pNode->SetScalingPivot(FbxNode::eDestinationPivot, pNode->GetScalingPivot(FbxNode::eSourcePivot));
// // Rotation and scaling offset are supported
// pNode->SetRotationOffset(FbxNode::eDestinationPivot, pNode->GetRotationOffset(FbxNode::eSourcePivot));
// pNode->SetScalingOffset(FbxNode::eDestinationPivot, pNode->GetScalingOffset(FbxNode::eSourcePivot));
// //
// // If we don't "support" scaling pivots, we can simply do:
// // pNode->SetRotationPivot(FbxNode::eDestinationPivot, lZero);
// // pNode->SetScalingPivot(FbxNode::eDestinationPivot, lZero);
// }
// */
//
// // Bake child nodes
// for(int i = 0; i < pNode->GetChildCount(); i++)
// {
// BakeNode(pNode->GetChild(i));
// }
//}
2013-11-23 12:16:31 -08:00
void LoadNode ( FbxScene * pFbxScene , KRNode * parent_node , FbxGeometryConverter * pGeometryConverter , FbxNode * pNode ) {
FbxVector4 lTmpVector ;
2012-11-29 21:28:49 +00:00
pNode - > UpdatePropertiesFromPivotsAndLimits ( ) ;
2012-12-07 08:22:20 +00:00
2013-04-04 17:53:39 -07:00
FbxSystemUnit system_unit = pFbxScene - > GetGlobalSettings ( ) . GetSystemUnit ( ) ;
2012-11-29 21:28:49 +00:00
// Transform = T * Roff * Rp * Rpre * R * Rpost * inverse(Rp) * Soff * Sp * S * inverse(Sp)
2012-12-02 09:31:01 +00:00
2013-12-03 16:04:15 -08:00
int node_has_n_points = 0 ; // this will be 3 if the node_frame_key_position is complete after the import animated properties loop
KRVector3 node_key_frame_position = KRVector3 ( 0.0 , 0.0 , 0.0 ) ;
// ADDED 3, 2013 by Peter to store the key frame (start location) of an animation
// the x, y, z translation position of the animation will be extracted from the curves
// as they are added to the animation layer in the loop below ..
2012-12-02 10:58:59 +00:00
// Import animated properties
int animation_count = pFbxScene - > GetSrcObjectCount < FbxAnimStack > ( ) ;
for ( int i = 0 ; i < animation_count ; i + + ) {
// FbxAnimStack* pAnimStack = FbxCast<FbxAnimStack>(pFbxScene->GetSrcObject(FBX_TYPE(FbxAnimStack), i));
FbxAnimStack * pAnimStack = pFbxScene - > GetSrcObject < FbxAnimStack > ( i ) ;
KRAnimation * pAnimation = parent_node - > getContext ( ) . getAnimationManager ( ) - > getAnimation ( pAnimStack - > GetName ( ) ) ;
2013-01-09 22:59:33 +00:00
if ( pAnimation ) {
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
int cLayers = pAnimStack - > GetMemberCount < FbxAnimLayer > ( ) ;
2013-01-09 22:59:33 +00:00
for ( int iLayer = 0 ; iLayer < cLayers ; iLayer + + ) {
FbxAnimLayer * pFbxAnimLayer = pAnimStack - > GetMember < FbxAnimLayer > ( iLayer ) ;
// float weight = pFbxAnimLayer->Weight.Get();
KRAnimationLayer * pAnimationLayer = pAnimation - > getLayer ( pFbxAnimLayer - > GetName ( ) ) ;
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
2013-01-09 22:59:33 +00:00
FbxAnimCurve * pAnimCurve = pNode - > LclRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclTranslation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X ) ;
2013-12-03 16:04:15 -08:00
KRAnimationCurve * curve = new_attribute - > getCurve ( ) ;
node_key_frame_position . x = curve - > getValue ( curve - > getFrameStart ( ) ) ;
node_has_n_points + + ;
// ADDED Dec 3, 2013 by Peter to extract start location key frame
pAnimationLayer - > addAttribute ( new_attribute ) ;
2013-01-09 22:59:33 +00:00
}
pAnimCurve = pNode - > LclTranslation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y ) ;
2013-12-03 16:04:15 -08:00
KRAnimationCurve * curve = new_attribute - > getCurve ( ) ;
node_key_frame_position . y = curve - > getValue ( curve - > getFrameStart ( ) ) ;
node_has_n_points + + ;
// ADDED Dec 3, 2013 by Peter to extract start location key frame
2013-01-09 22:59:33 +00:00
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclTranslation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z ) ;
2013-12-03 16:04:15 -08:00
KRAnimationCurve * curve = new_attribute - > getCurve ( ) ;
node_key_frame_position . z = curve - > getValue ( curve - > getFrameStart ( ) ) ;
node_has_n_points + + ;
// ADDED Dec 3, 2013 by Peter to extract start location key frame
2013-01-09 22:59:33 +00:00
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclScaling . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclScaling . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > LclScaling . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
2013-05-24 12:20:47 -07:00
pAnimCurve = pNode - > PreRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > PreRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > PreRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > PostRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > PostRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > PostRotation . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingPivot . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > RotationOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_X ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_SCALE_OFFSET_X ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Y ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_SCALE_OFFSET_Y ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
pAnimCurve = pNode - > ScalingOffset . GetCurve ( pFbxAnimLayer , FBXSDK_CURVENODE_COMPONENT_Z ) ;
if ( pAnimCurve ) {
KRAnimationAttribute * new_attribute = new KRAnimationAttribute ( parent_node - > getContext ( ) ) ;
new_attribute - > setCurveName ( GetFbxObjectName ( pAnimCurve ) ) ;
new_attribute - > setTargetName ( GetFbxObjectName ( pNode ) ) ;
new_attribute - > setTargetAttribute ( KRNode : : KRENGINE_NODE_SCALE_OFFSET_Z ) ;
pAnimationLayer - > addAttribute ( new_attribute ) ;
}
2012-12-02 10:58:59 +00:00
}
}
}
2013-12-03 16:04:15 -08:00
2013-11-23 12:16:31 -08:00
FbxDouble3 local_rotation = pNode - > LclRotation . Get ( ) ; // pNode->GetGeometricRotation(KFbxNode::eSourcePivot);
FbxDouble3 local_translation = pNode - > LclTranslation . Get ( ) ; // pNode->GetGeometricTranslation(KFbxNode::eSourcePivot);
FbxDouble3 local_scale = pNode - > LclScaling . Get ( ) ; // pNode->GetGeometricScaling(KFbxNode::eSourcePivot);
2012-09-13 20:09:19 +00:00
2013-05-24 12:20:47 -07:00
bool rotation_active = pNode - > RotationActive . Get ( ) ;
2013-11-23 12:16:31 -08:00
FbxDouble3 post_rotation = pNode - > PostRotation . Get ( ) ;
FbxDouble3 pre_rotation = pNode - > PreRotation . Get ( ) ;
FbxDouble3 rotation_offset = pNode - > RotationOffset . Get ( ) ;
FbxDouble3 scaling_offset = pNode - > ScalingOffset . Get ( ) ;
FbxDouble3 rotation_pivot = pNode - > RotationPivot . Get ( ) ;
FbxDouble3 scaling_pivot = pNode - > ScalingPivot . Get ( ) ;
FbxDouble3 geometric_rotation = pNode - > GeometricRotation . Get ( ) ;
FbxDouble3 geometric_translation = pNode - > GeometricTranslation . Get ( ) ;
FbxDouble3 geometric_scaling = pNode - > GeometricScaling . Get ( ) ;
EFbxRotationOrder rotation_order = pNode - > RotationOrder . Get ( ) ;
2012-12-01 02:03:18 +00:00
2013-11-23 12:16:31 -08:00
FbxVector4 lZero ( 0.0 , 0.0 , 0.0 ) ;
FbxVector4 lOne ( 1.0 , 1.0 , 1.0 ) ;
2012-12-01 02:03:18 +00:00
2013-12-14 14:20:30 -08:00
warning ( ( geometric_rotation = = lZero ) , " Geometric Rotation not supported .. 3DSMax file?? " ) ;
warning ( ( geometric_translation = = lZero ) , " Geometric Rotation not supported .. 3DSMax file?? " ) ;
warning ( ( geometric_scaling = = lOne ) , " Geometric Rotation not supported .. 3DSMax file?? " ) ;
warning ( ( rotation_order = = eEulerXYZ ) , " Geometric Rotation not supported .. 3DSMax file?? " ) ;
2013-12-03 16:04:15 -08:00
// FINDME - node_key_frame_position contains the key frame (start location) for an animation node
// node_has_n_points
// node_key_frame_position
if ( 3 = = node_has_n_points )
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " key frame at %2.3f, %2.3f, %2.3f " ,
2013-12-03 16:04:15 -08:00
node_key_frame_position . x ,
node_key_frame_position . y ,
node_key_frame_position . z ) ;
//
// The animation curve data is output to the KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_ X, Y, Z attribute targets
// The actor scripts 'move' command modifies the node's world translations using setWorldTranslation()
//
// QUESTION - where should we store the key frame within the node to make sure it is output into the KRBundle ??
// do we store it as node_local or store it as the world translation? or somewhere else ??
//
2012-12-02 10:58:59 +00:00
2012-11-29 21:28:49 +00:00
KRVector3 node_translation = KRVector3 ( local_translation [ 0 ] , local_translation [ 1 ] , local_translation [ 2 ] ) ; // T * Roff * Rp
2012-12-01 02:03:18 +00:00
KRVector3 node_rotation = KRVector3 ( local_rotation [ 0 ] , local_rotation [ 1 ] , local_rotation [ 2 ] ) / 180.0 * M_PI ;
2012-11-29 21:28:49 +00:00
KRVector3 node_scale = KRVector3 ( local_scale [ 0 ] , local_scale [ 1 ] , local_scale [ 2 ] ) ;
2013-05-13 13:16:25 -07:00
KRVector3 node_rotation_offset = KRVector3 ( rotation_offset [ 0 ] , rotation_offset [ 1 ] , rotation_offset [ 2 ] ) ;
KRVector3 node_scaling_offset = KRVector3 ( scaling_offset [ 0 ] , scaling_offset [ 1 ] , scaling_offset [ 2 ] ) ;
KRVector3 node_rotation_pivot = KRVector3 ( rotation_pivot [ 0 ] , rotation_pivot [ 1 ] , rotation_pivot [ 2 ] ) ;
KRVector3 node_scaling_pivot = KRVector3 ( scaling_pivot [ 0 ] , scaling_pivot [ 1 ] , scaling_pivot [ 2 ] ) ;
2013-05-24 12:20:47 -07:00
KRVector3 node_pre_rotation , node_post_rotation ;
if ( rotation_active ) {
node_pre_rotation = KRVector3 ( pre_rotation [ 0 ] , pre_rotation [ 1 ] , pre_rotation [ 2 ] ) / 180.0 * M_PI ;
2014-04-10 19:12:19 -07:00
node_post_rotation = KRVector3 ( post_rotation [ 0 ] , post_rotation [ 1 ] , post_rotation [ 2 ] ) / 180.0 * M_PI ;
2014-04-04 00:46:36 -07:00
//&KRF HACK removing this line (above) to prevent the post rotation from corrupting the default light values; the FBX is importing a post rotation and setting it to -90 degrees
2013-05-24 12:20:47 -07:00
} else {
node_pre_rotation = KRVector3 : : Zero ( ) ;
node_post_rotation = KRVector3 : : Zero ( ) ;
}
2013-05-13 13:16:25 -07:00
2012-12-01 02:03:18 +00:00
// printf(" Local Translation: %f %f %f\n", local_translation[0], local_translation[1], local_translation[2]);
// printf(" Local Rotation: %f %f %f\n", local_rotation[0], local_rotation[1], local_rotation[2]);
// printf(" Local Scaling: %f %f %f\n", local_scale[0], local_scale[1], local_scale[2]);
2012-11-03 02:57:35 +00:00
2013-11-23 12:16:31 -08:00
FbxNodeAttribute : : EType attribute_type = ( pNode - > GetNodeAttribute ( ) - > GetAttributeType ( ) ) ;
if ( attribute_type = = FbxNodeAttribute : : eLODGroup ) {
2013-04-04 12:50:53 -07:00
std : : string name = GetFbxObjectName ( pNode ) ;
FbxLODGroup * fbx_lod_group = ( FbxLODGroup * ) pNode - > GetNodeAttribute ( ) ; // FbxCast<FbxLODGroup>(pNode);
2013-04-08 21:40:53 -07:00
bool use_world_space_units = fbx_lod_group - > WorldSpace . Get ( ) ;
2013-04-04 12:50:53 -07:00
float group_min_distance = 0.0f ;
float group_max_distance = 0.0f ;
if ( fbx_lod_group - > MinMaxDistance . Get ( ) ) {
group_min_distance = fbx_lod_group - > MinDistance . Get ( ) ;
2014-04-01 11:50:45 -07:00
group_max_distance = fbx_lod_group - > MaxDistance . Get ( ) ;
2013-04-04 12:50:53 -07:00
}
2013-04-04 16:09:29 -07:00
2014-03-10 22:32:49 -07:00
KRLODSet * lod_set = new KRLODSet ( parent_node - > getScene ( ) , name ) ;
parent_node - > addChild ( lod_set ) ;
2013-04-08 21:40:53 -07:00
KRAABB reference_bounds ;
2013-04-04 12:50:53 -07:00
// Create a lod_group node for each fbx child node
int child_count = pNode - > GetChildCount ( ) ;
for ( int i = 0 ; i < child_count ; i + + )
{
float min_distance = 0 ;
float max_distance = 0 ; // 0 for max_distance means infinity
FbxLODGroup : : EDisplayLevel display_level ;
fbx_lod_group - > GetDisplayLevel ( i , display_level ) ;
switch ( display_level ) {
case FbxLODGroup : : eUseLOD :
if ( i > 0 ) {
FbxDistance d ;
fbx_lod_group - > GetThreshold ( i - 1 , d ) ;
2013-04-04 17:53:39 -07:00
min_distance = d . valueAs ( system_unit ) ;
2013-04-04 12:50:53 -07:00
}
if ( i < child_count - 1 ) {
FbxDistance d ;
fbx_lod_group - > GetThreshold ( i , d ) ;
2013-04-04 17:53:39 -07:00
max_distance = d . valueAs ( system_unit ) ;
2013-04-04 12:50:53 -07:00
}
break ;
case FbxLODGroup : : eShow :
// We leave min_distance and max_distance as 0's, which effectively makes the LOD group always visible
break ;
case FbxLODGroup : : eHide :
min_distance = - 1 ;
max_distance = - 1 ;
// LOD Groups with -1 for both min_distance and max_distance will never be displayed; import in case that the distance values are to be modified by scripting at runtime
break ;
}
if ( group_min_distance ! = 0.0f & & min_distance ! = - 1 ) {
if ( min_distance < group_min_distance ) min_distance = group_min_distance ;
}
if ( group_max_distance ! = 0.0f & & max_distance ! = - 1 ) {
if ( max_distance = = 0.0f ) {
max_distance = group_max_distance ;
} else if ( max_distance > group_max_distance ) {
max_distance = group_max_distance ;
2012-11-03 02:57:35 +00:00
}
}
2013-04-04 12:50:53 -07:00
KRLODGroup * new_node = new KRLODGroup ( parent_node - > getScene ( ) , name + " _lodlevel " + boost : : lexical_cast < string > ( i + 1 ) ) ;
new_node - > setMinDistance ( min_distance ) ;
new_node - > setMaxDistance ( max_distance ) ;
new_node - > setLocalRotation ( node_rotation ) ;
new_node - > setLocalTranslation ( node_translation ) ;
new_node - > setLocalScale ( node_scale ) ;
2013-05-13 13:16:25 -07:00
new_node - > setRotationOffset ( node_rotation_offset ) ;
new_node - > setScalingOffset ( node_scaling_offset ) ;
new_node - > setRotationPivot ( node_rotation_pivot ) ;
new_node - > setScalingPivot ( node_scaling_pivot ) ;
new_node - > setPreRotation ( node_pre_rotation ) ;
new_node - > setPostRotation ( node_post_rotation ) ;
2013-04-08 21:40:53 -07:00
new_node - > setUseWorldUnits ( use_world_space_units ) ;
2014-03-10 22:32:49 -07:00
lod_set - > addChild ( new_node ) ;
2013-04-04 12:50:53 -07:00
2013-05-06 14:06:29 -07:00
LoadNode ( pFbxScene , new_node , pGeometryConverter , pNode - > GetChild ( i ) ) ;
2013-04-04 16:09:29 -07:00
if ( i = = 0 ) {
// Calculate reference point using the bounding box center from the highest quality LOD level
2013-04-08 21:40:53 -07:00
reference_bounds = new_node - > getBounds ( ) ;
2013-04-04 16:09:29 -07:00
}
2013-04-08 21:40:53 -07:00
new_node - > setReference ( KRAABB ( reference_bounds . min , reference_bounds . max , new_node - > getInverseModelMatrix ( ) ) ) ;
2012-11-03 02:57:35 +00:00
}
2013-04-04 12:50:53 -07:00
} else {
KRNode * new_node = NULL ;
switch ( attribute_type ) {
2013-11-23 12:16:31 -08:00
case FbxNodeAttribute : : eMesh :
2013-05-24 12:20:47 -07:00
new_node = LoadMesh ( parent_node , pFbxScene , pGeometryConverter , pNode ) ;
2013-04-04 12:50:53 -07:00
break ;
2013-11-23 12:16:31 -08:00
case FbxNodeAttribute : : eLight :
2013-05-06 14:06:29 -07:00
new_node = LoadLight ( parent_node , pNode ) ;
2013-04-04 12:50:53 -07:00
break ;
2013-11-23 12:16:31 -08:00
case FbxNodeAttribute : : eSkeleton :
2013-05-24 12:20:47 -07:00
new_node = LoadSkeleton ( parent_node , pFbxScene , pNode ) ;
2013-04-04 12:50:53 -07:00
break ;
2013-10-06 18:56:23 -07:00
2013-11-23 12:16:31 -08:00
case FbxNodeAttribute : : eCamera :
2013-05-06 14:06:29 -07:00
new_node = LoadCamera ( parent_node , pNode ) ;
2013-04-04 12:50:53 -07:00
break ;
default :
{
2013-10-06 18:56:23 -07:00
bool is_locator = false ;
2013-11-23 12:16:31 -08:00
if ( attribute_type = = FbxNodeAttribute : : eNull ) {
FbxNull * pSourceNull = ( FbxNull * ) pNode - > GetNodeAttribute ( ) ;
if ( pSourceNull - > Look . Get ( ) = = FbxNull : : eCross ) {
2013-10-06 18:56:23 -07:00
is_locator = true ;
2013-04-04 12:50:53 -07:00
}
2013-10-06 18:56:23 -07:00
}
if ( is_locator ) {
new_node = LoadLocator ( parent_node , pFbxScene , pNode ) ;
} else {
if ( pNode - > GetChildCount ( ) > 0 ) {
// Create an empty node, for inheritence of transforms
std : : string name = GetFbxObjectName ( pNode ) ;
2014-03-10 22:32:49 -07:00
new_node = new KRNode ( parent_node - > getScene ( ) , name ) ;
2013-04-04 12:50:53 -07:00
}
}
}
break ;
}
2013-12-03 16:04:15 -08:00
// this is a KRNode
2013-04-04 12:50:53 -07:00
if ( new_node ! = NULL ) {
new_node - > setLocalRotation ( node_rotation ) ;
new_node - > setLocalTranslation ( node_translation ) ;
new_node - > setLocalScale ( node_scale ) ;
2013-05-13 13:16:25 -07:00
new_node - > setRotationOffset ( node_rotation_offset ) ;
new_node - > setScalingOffset ( node_scaling_offset ) ;
new_node - > setRotationPivot ( node_rotation_pivot ) ;
new_node - > setScalingPivot ( node_scaling_pivot ) ;
new_node - > setPreRotation ( node_pre_rotation ) ;
new_node - > setPostRotation ( node_post_rotation ) ;
2013-04-04 12:50:53 -07:00
parent_node - > addChild ( new_node ) ;
2013-12-03 16:04:15 -08:00
2013-04-04 12:50:53 -07:00
// Load child nodes
for ( int i = 0 ; i < pNode - > GetChildCount ( ) ; i + + )
{
2013-05-06 14:06:29 -07:00
LoadNode ( pFbxScene , new_node , pGeometryConverter , pNode - > GetChild ( i ) ) ;
2013-04-04 12:50:53 -07:00
}
}
2012-03-23 02:28:46 +00:00
}
}
2013-05-06 14:06:29 -07:00
void LoadMaterial ( KRContext & context , FbxSurfaceMaterial * pMaterial ) {
2012-12-20 01:23:57 +00:00
//printf(" %s: %i - %i\n", pMaterial->GetName(), mat_vertex_start, mat_vertex_count + mat_vertex_start - 1);
// ----====---- Output Material File ----====----
KRMaterial * new_material = new KRMaterial ( context , pMaterial - > GetName ( ) ) ;
2013-01-23 12:43:43 -08:00
std : : string name = pMaterial - > GetName ( ) ;
2013-01-24 13:52:26 -08:00
if ( boost : : starts_with ( name , " ab_reflect_ " ) ) {
2013-01-23 12:43:43 -08:00
new_material - > setAlphaMode ( KRMaterial : : KRMATERIAL_ALPHA_MODE_BLENDONESIDE ) ;
2013-01-24 13:52:26 -08:00
size_t underscore_pos = name . find ( ' _ ' , 11 ) ;
2013-01-23 12:43:43 -08:00
new_material - > setReflectionCube ( name . substr ( 11 , underscore_pos - 11 ) ) ;
} else if ( boost : : starts_with ( name , " reflect_ " ) ) {
2013-01-24 13:52:26 -08:00
size_t underscore_pos = name . find ( ' _ ' , 8 ) ;
2013-01-23 12:43:43 -08:00
new_material - > setReflectionCube ( name . substr ( 8 , underscore_pos - 8 ) ) ;
} else if ( boost : : starts_with ( name , " at_ " ) ) {
new_material - > setAlphaMode ( KRMaterial : : KRMATERIAL_ALPHA_MODE_TEST ) ;
} else if ( boost : : starts_with ( name , " ab_ " ) ) {
new_material - > setAlphaMode ( KRMaterial : : KRMATERIAL_ALPHA_MODE_BLENDONESIDE ) ;
} else if ( boost : : starts_with ( name , " ab2_ " ) ) {
2013-01-24 13:52:26 -08:00
new_material - > setAlphaMode ( KRMaterial : : KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE ) ;
2013-01-23 12:43:43 -08:00
}
2012-12-20 01:23:57 +00:00
FbxPropertyT < FbxDouble3 > lKFbxDouble3 ;
FbxPropertyT < FbxDouble > lKFbxDouble1 ;
2013-11-23 12:16:31 -08:00
if ( pMaterial - > GetClassId ( ) . Is ( FbxSurfacePhong : : ClassId ) ) {
2012-12-20 01:23:57 +00:00
// We found a Phong material.
// Ambient Color
lKFbxDouble3 = ( ( FbxSurfacePhong * ) pMaterial ) - > Ambient ;
new_material - > setAmbient ( KRVector3 ( lKFbxDouble3 . Get ( ) [ 0 ] , lKFbxDouble3 . Get ( ) [ 1 ] , lKFbxDouble3 . Get ( ) [ 2 ] ) ) ;
// Diffuse Color
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfacePhong * ) pMaterial ) - > Diffuse ;
2012-12-20 01:23:57 +00:00
new_material - > setDiffuse ( KRVector3 ( lKFbxDouble3 . Get ( ) [ 0 ] , lKFbxDouble3 . Get ( ) [ 1 ] , lKFbxDouble3 . Get ( ) [ 2 ] ) ) ;
// Specular Color (unique to Phong materials)
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfacePhong * ) pMaterial ) - > Specular ;
2012-12-20 01:23:57 +00:00
new_material - > setSpecular ( KRVector3 ( lKFbxDouble3 . Get ( ) [ 0 ] , lKFbxDouble3 . Get ( ) [ 1 ] , lKFbxDouble3 . Get ( ) [ 2 ] ) ) ;
// Emissive Color
//lKFbxDouble3 =((KFbxSurfacePhong *) pMaterial)->Emissive;
2013-05-06 19:33:51 -07:00
/*
2012-12-20 01:23:57 +00:00
// Transparency
lKFbxDouble1 = ( ( KFbxSurfacePhong * ) pMaterial ) - > TransparencyFactor ;
2013-05-01 17:54:48 -07:00
new_material - > setTransparency ( 1.0f - lKFbxDouble1 . Get ( ) ) ;
2013-05-06 19:33:51 -07:00
*/
2012-12-20 01:23:57 +00:00
// Shininess
2013-11-23 12:16:31 -08:00
lKFbxDouble1 = ( ( FbxSurfacePhong * ) pMaterial ) - > Shininess ;
2012-12-20 01:23:57 +00:00
new_material - > setShininess ( lKFbxDouble1 . Get ( ) ) ;
2013-05-06 19:33:51 -07:00
/*
2012-12-20 01:23:57 +00:00
// Specular Factor
lKFbxDouble1 = ( ( KFbxSurfacePhong * ) pMaterial ) - > SpecularFactor ;
double specular_factor = lKFbxDouble1 . Get ( ) ;
2013-05-06 19:33:51 -07:00
*/
// Transparency Color
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfacePhong * ) pMaterial ) - > TransparentColor ;
2013-05-06 19:33:51 -07:00
new_material - > setTransparency ( 1.0f - ( lKFbxDouble3 . Get ( ) [ 0 ] + lKFbxDouble3 . Get ( ) [ 1 ] + lKFbxDouble3 . Get ( ) [ 2 ] ) / 3.0f ) ;
2012-12-20 01:23:57 +00:00
// Reflection factor
2013-11-23 12:16:31 -08:00
lKFbxDouble1 = ( ( FbxSurfacePhong * ) pMaterial ) - > ReflectionFactor ;
2012-12-20 01:23:57 +00:00
// Reflection color
2014-04-12 23:42:26 -07:00
//lKFbxDouble3 =((FbxSurfacePhong *) pMaterial)->Reflection;
2012-12-20 01:23:57 +00:00
// We modulate Relection color by reflection factor, as we only have one "reflection color" variable in Kraken
2014-04-12 23:42:26 -07:00
new_material - > setReflection ( KRVector3 ( /*lKFbxDouble3.Get()[0] * */ lKFbxDouble1 . Get ( ) , /*lKFbxDouble3.Get()[1] * */ lKFbxDouble1 . Get ( ) , /*lKFbxDouble3.Get()[2] * */ lKFbxDouble1 . Get ( ) ) ) ;
2012-12-20 01:23:57 +00:00
2013-11-23 12:16:31 -08:00
} else if ( pMaterial - > GetClassId ( ) . Is ( FbxSurfaceLambert : : ClassId ) ) {
2012-12-20 01:23:57 +00:00
// We found a Lambert material.
// Ambient Color
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfaceLambert * ) pMaterial ) - > Ambient ;
2012-12-20 01:23:57 +00:00
new_material - > setAmbient ( KRVector3 ( lKFbxDouble3 . Get ( ) [ 0 ] , lKFbxDouble3 . Get ( ) [ 1 ] , lKFbxDouble3 . Get ( ) [ 2 ] ) ) ;
// Diffuse Color
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfaceLambert * ) pMaterial ) - > Diffuse ;
2012-12-20 01:23:57 +00:00
new_material - > setDiffuse ( KRVector3 ( lKFbxDouble3 . Get ( ) [ 0 ] , lKFbxDouble3 . Get ( ) [ 1 ] , lKFbxDouble3 . Get ( ) [ 2 ] ) ) ;
// Emissive
//lKFbxDouble3 =((KFbxSurfaceLambert *)pMaterial)->Emissive;
2013-05-06 19:33:51 -07:00
/*
2012-12-20 01:23:57 +00:00
// Opacity
lKFbxDouble1 = ( ( KFbxSurfaceLambert * ) pMaterial ) - > TransparencyFactor ;
2013-05-01 17:54:48 -07:00
new_material - > setTransparency ( 1.0f - lKFbxDouble1 . Get ( ) ) ;
2013-05-06 19:33:51 -07:00
*/
// Transparency Color
2013-11-23 12:16:31 -08:00
lKFbxDouble3 = ( ( FbxSurfaceLambert * ) pMaterial ) - > TransparentColor ;
2013-05-06 19:33:51 -07:00
new_material - > setTransparency ( 1.0f - ( lKFbxDouble3 . Get ( ) [ 0 ] + lKFbxDouble3 . Get ( ) [ 1 ] + lKFbxDouble3 . Get ( ) [ 2 ] ) / 3.0f ) ;
2012-12-20 01:23:57 +00:00
} else {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_WARNING , " Unable to convert material: %s " , pMaterial - > GetName ( ) ) ;
2012-12-20 01:23:57 +00:00
}
2013-11-23 12:16:31 -08:00
FbxProperty pProperty ;
2012-12-20 01:23:57 +00:00
// Diffuse Map Texture
2013-11-23 12:16:31 -08:00
pProperty = pMaterial - > FindProperty ( FbxSurfaceMaterial : : sDiffuse ) ;
2016-08-07 20:28:15 -07:00
if ( pProperty . GetSrcObjectCount ( FbxCriteria : : ObjectType ( FbxLayeredTexture : : ClassId ) ) > 0 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_WARNING , " Layered textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
}
2016-08-07 20:28:15 -07:00
int texture_count = pProperty . GetSrcObjectCount ( FbxCriteria : : ObjectType ( FbxTexture : : ClassId ) ) ;
2012-12-20 01:23:57 +00:00
if ( texture_count > 1 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_WARNING , " Multiple diffuse textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
} else if ( texture_count = = 1 ) {
2016-08-07 20:28:15 -07:00
FbxTexture * pTexture = FbxCast < FbxTexture > ( pProperty . GetSrcObject ( FbxCriteria : : ObjectType ( FbxTexture : : ClassId ) , 0 ) ) ;
2012-12-20 01:23:57 +00:00
assert ( ! pTexture - > GetSwapUV ( ) ) ;
assert ( pTexture - > GetCroppingTop ( ) = = 0 ) ;
assert ( pTexture - > GetCroppingLeft ( ) = = 0 ) ;
assert ( pTexture - > GetCroppingRight ( ) = = 0 ) ;
assert ( pTexture - > GetCroppingBottom ( ) = = 0 ) ;
2013-11-23 12:16:31 -08:00
assert ( pTexture - > GetWrapModeU ( ) = = FbxTexture : : eRepeat ) ;
assert ( pTexture - > GetWrapModeV ( ) = = FbxTexture : : eRepeat ) ;
2012-12-20 01:23:57 +00:00
assert ( pTexture - > GetRotationU ( ) = = 0.0f ) ;
assert ( pTexture - > GetRotationV ( ) = = 0.0f ) ;
assert ( pTexture - > GetRotationW ( ) = = 0.0f ) ;
2013-11-23 12:16:31 -08:00
FbxFileTexture * pFileTexture = FbxCast < FbxFileTexture > ( pTexture ) ;
2012-12-20 01:23:57 +00:00
if ( pFileTexture ) {
new_material - > setDiffuseMap ( KRResource : : GetFileBase ( pFileTexture - > GetFileName ( ) ) , KRVector2 ( pTexture - > GetScaleU ( ) , pTexture - > GetScaleV ( ) ) , KRVector2 ( pTexture - > GetTranslationU ( ) , pTexture - > GetTranslationV ( ) ) ) ;
}
}
// Specular Map Texture
2013-11-23 12:16:31 -08:00
pProperty = pMaterial - > FindProperty ( FbxSurfaceMaterial : : sSpecular ) ;
2016-08-07 20:28:15 -07:00
if ( pProperty . GetSrcObjectCount ( FbxCriteria : : ObjectType ( FbxLayeredTexture : : ClassId ) ) > 0 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Layered textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
}
2016-08-07 20:28:15 -07:00
texture_count = pProperty . GetSrcObjectCount ( FbxCriteria : : ObjectType ( FbxTexture : : ClassId ) ) ;
2012-12-20 01:23:57 +00:00
if ( texture_count > 1 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Multiple specular textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
} else if ( texture_count = = 1 ) {
2016-08-07 20:28:15 -07:00
FbxTexture * pTexture = FbxCast < FbxTexture > ( pProperty . GetSrcObject ( FbxCriteria : : ObjectType ( FbxTexture : : ClassId ) , 0 ) ) ;
2013-11-23 12:16:31 -08:00
FbxFileTexture * pFileTexture = FbxCast < FbxFileTexture > ( pTexture ) ;
2012-12-20 01:23:57 +00:00
if ( pFileTexture ) {
new_material - > setSpecularMap ( KRResource : : GetFileBase ( pFileTexture - > GetFileName ( ) ) , KRVector2 ( pTexture - > GetScaleU ( ) , pTexture - > GetScaleV ( ) ) , KRVector2 ( pTexture - > GetTranslationU ( ) , pTexture - > GetTranslationV ( ) ) ) ;
}
}
// Normal Map Texture
2013-11-23 12:16:31 -08:00
pProperty = pMaterial - > FindProperty ( FbxSurfaceMaterial : : sNormalMap ) ;
2016-08-07 20:28:15 -07:00
if ( pProperty . GetSrcObjectCount ( FbxCriteria : : ObjectType ( FbxLayeredTexture : : ClassId ) ) > 0 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Layered textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
}
texture_count = pProperty . GetSrcObjectCount < FbxTexture > ( ) ;
if ( texture_count > 1 ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Multiple normal map textures not supported. " ) ;
2012-12-20 01:23:57 +00:00
} else if ( texture_count = = 1 ) {
2013-11-23 12:16:31 -08:00
FbxTexture * pTexture = pProperty . GetSrcObject < FbxTexture > ( 0 ) ;
FbxFileTexture * pFileTexture = FbxCast < FbxFileTexture > ( pTexture ) ;
2012-12-20 01:23:57 +00:00
if ( pFileTexture ) {
new_material - > setNormalMap ( KRResource : : GetFileBase ( pFileTexture - > GetFileName ( ) ) , KRVector2 ( pTexture - > GetScaleU ( ) , pTexture - > GetScaleV ( ) ) , KRVector2 ( pTexture - > GetTranslationU ( ) , pTexture - > GetTranslationV ( ) ) ) ;
}
}
2013-05-06 12:58:57 -07:00
// Only save unique materials
KRMaterial * found_material = context . getMaterialManager ( ) - > getMaterial ( new_material - > getName ( ) ) ;
if ( found_material = = NULL ) {
context . getMaterialManager ( ) - > add ( new_material ) ;
} else {
delete new_material ;
}
2012-12-20 01:23:57 +00:00
}
2013-05-24 12:20:47 -07:00
2016-08-07 20:28:15 -07:00
void LoadMesh ( KRContext & context , FbxScene * pFbxScene , FbxGeometryConverter * pGeometryConverter , FbxMesh * pMesh ) {
2013-05-24 12:20:47 -07:00
KRMesh : : mesh_info mi ;
mi . format = KRMesh : : KRENGINE_MODEL_FORMAT_TRIANGLES ;
2012-12-12 09:32:53 +00:00
2013-05-24 12:20:47 -07:00
typedef struct {
2012-12-12 22:15:09 +00:00
float weights [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ] ;
int bone_indexes [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ] ;
2013-05-24 12:20:47 -07:00
} control_point_weight_info_t ;
int control_point_count = pMesh - > GetControlPointsCount ( ) ;
2013-11-23 12:16:31 -08:00
FbxVector4 * control_points = pMesh - > GetControlPoints ( ) ;
2012-12-12 09:32:53 +00:00
2013-05-24 12:20:47 -07:00
control_point_weight_info_t * control_point_weights = new control_point_weight_info_t [ control_point_count ] ;
2012-12-12 09:32:53 +00:00
for ( int control_point = 0 ; control_point < control_point_count ; control_point + + ) {
2012-12-12 22:15:09 +00:00
for ( int i = 0 ; i < KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ; i + + ) {
2012-12-12 09:32:53 +00:00
control_point_weights [ control_point ] . weights [ i ] = 0.0f ;
control_point_weights [ control_point ] . bone_indexes [ i ] = 0 ;
}
2012-12-20 01:23:57 +00:00
2012-12-12 09:32:53 +00:00
}
bool too_many_bone_weights = false ;
// Collect the top 4 bone weights per vertex ...
2012-12-10 21:09:14 +00:00
int skin_count = pMesh - > GetDeformerCount ( FbxDeformer : : eSkin ) ;
2012-12-12 09:32:53 +00:00
int target_bone_index = 0 ;
2012-12-10 21:09:14 +00:00
for ( int skin_index = 0 ; skin_index < skin_count ; skin_index + + ) {
FbxSkin * skin = ( FbxSkin * ) pMesh - > GetDeformer ( skin_index , FbxDeformer : : eSkin ) ;
2012-12-12 09:32:53 +00:00
int cluster_count = skin - > GetClusterCount ( ) ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Found skin with %i clusters. \n " , cluster_count ) ;
2012-12-12 09:32:53 +00:00
for ( int cluster_index = 0 ; cluster_index < cluster_count ; cluster_index + + ) {
FbxCluster * cluster = skin - > GetCluster ( cluster_index ) ;
if ( cluster - > GetLinkMode ( ) ! = FbxCluster : : eNormalize ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_WARNING , " Warning! link mode not supported. " ) ;
2012-12-12 09:32:53 +00:00
}
std : : string bone_name = GetFbxObjectName ( cluster - > GetLink ( ) ) ;
2013-05-24 12:20:47 -07:00
mi . bone_names . push_back ( bone_name ) ;
/*
FbxMatrix fbx_bind_pose_matrix ;
KRMat4 bind_pose ;
PoseList pose_list ;
FbxArray < int > pose_indices ;
if ( FbxPose : : GetBindPoseContaining ( pFbxScene , cluster - > GetLink ( ) , pose_list , pose_indices ) ) {
fbx_bind_pose_matrix = ( * pose_list ) [ 0 ] . GetMatrix ( pose_indices [ 0 ] ) ;
bind_pose = KRMat4 (
KRVector3 ( fbx_bind_pose_matrix . GetColumn ( 0 ) . mData ) ,
KRVector3 ( fbx_bind_pose_matrix . GetColumn ( 1 ) . mData ) ,
KRVector3 ( fbx_bind_pose_matrix . GetColumn ( 2 ) . mData ) ,
KRVector3 ( fbx_bind_pose_matrix . GetColumn ( 3 ) . mData )
) ;
fprintf ( stderr , " Found bind pose(s)! \n " ) ;
}
*/
FbxAMatrix link_matrix ;
cluster - > GetTransformLinkMatrix ( link_matrix ) ;
mi . bone_bind_poses . push_back ( KRMat4 (
KRVector3 ( link_matrix . GetColumn ( 0 ) . mData ) ,
KRVector3 ( link_matrix . GetColumn ( 1 ) . mData ) ,
KRVector3 ( link_matrix . GetColumn ( 2 ) . mData ) ,
KRVector3 ( link_matrix . GetColumn ( 3 ) . mData )
) ) ;
2012-12-12 09:32:53 +00:00
int cluster_control_point_count = cluster - > GetControlPointIndicesCount ( ) ;
2013-05-24 12:20:47 -07:00
for ( int cluster_control_point = 0 ; cluster_control_point < cluster_control_point_count ; cluster_control_point + + ) {
int control_point = cluster - > GetControlPointIndices ( ) [ cluster_control_point ] ;
control_point_weight_info_t & weight_info = control_point_weights [ control_point ] ;
float bone_weight = cluster - > GetControlPointWeights ( ) [ cluster_control_point ] ;
2012-12-12 22:15:09 +00:00
if ( bone_weight > weight_info . weights [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX - 1 ] ) {
if ( weight_info . weights [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX - 1 ] ! = 0.0f ) {
2012-12-12 09:32:53 +00:00
too_many_bone_weights = true ;
}
2012-12-12 22:15:09 +00:00
weight_info . weights [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX - 1 ] = bone_weight ;
weight_info . bone_indexes [ KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX - 1 ] = target_bone_index ;
2013-05-13 13:16:25 -07:00
for ( int bone_index = KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX - 2 ; bone_index > = 0 ; bone_index - - ) {
2012-12-12 09:32:53 +00:00
if ( bone_weight > weight_info . weights [ bone_index ] ) {
weight_info . weights [ bone_index + 1 ] = weight_info . weights [ bone_index ] ;
weight_info . bone_indexes [ bone_index + 1 ] = weight_info . bone_indexes [ bone_index ] ;
weight_info . weights [ bone_index ] = bone_weight ;
weight_info . bone_indexes [ bone_index ] = target_bone_index ;
}
}
} else {
too_many_bone_weights = true ;
}
}
target_bone_index + + ;
}
2012-12-10 21:09:14 +00:00
}
2012-12-12 09:32:53 +00:00
if ( too_many_bone_weights ) {
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_WARNING , " Clipped bone weights to limit of %i per vertex (selecting largest weights and re-normalizing). " , KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ) ;
2012-12-12 09:32:53 +00:00
}
// Normalize bone weights
2013-05-24 12:20:47 -07:00
if ( mi . bone_names . size ( ) > 0 ) {
2012-12-12 09:32:53 +00:00
for ( int control_point_index = 0 ; control_point_index < control_point_count ; control_point_index + + ) {
2013-05-24 12:20:47 -07:00
control_point_weight_info_t & weight_info = control_point_weights [ control_point_index ] ;
2012-12-12 09:32:53 +00:00
float total_weights = 0.0f ;
2012-12-12 22:15:09 +00:00
for ( int i = 0 ; i < KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ; i + + ) {
2012-12-12 09:32:53 +00:00
total_weights + = weight_info . weights [ i ] ;
}
if ( total_weights = = 0.0f ) total_weights = 1.0f ; // Prevent any divisions by zero
2012-12-12 22:15:09 +00:00
for ( int i = 0 ; i < KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ; i + + ) {
2012-12-12 09:32:53 +00:00
weight_info . weights [ i ] = weight_info . weights [ i ] / total_weights ;
}
}
}
2012-03-23 02:28:46 +00:00
2014-04-12 23:42:26 -07:00
pMesh - > GenerateTangentsDataForAllUVSets ( true ) ;
2012-03-23 02:28:46 +00:00
int polygon_count = pMesh - > GetPolygonCount ( ) ;
2012-03-28 19:06:23 +00:00
int uv_count = pMesh - > GetElementUVCount ( ) ;
int normal_count = pMesh - > GetElementNormalCount ( ) ;
int tangent_count = pMesh - > GetElementTangentCount ( ) ;
2012-03-28 19:34:52 +00:00
int elementmaterial_count = pMesh - > GetElementMaterialCount ( ) ;
2016-08-07 20:28:15 -07:00
int material_count = pMesh - > GetNode ( ) - > GetMaterialCount ( ) ; // FINDME, TODO - To support instancing, material names should be stored in the instance rather than the mesh
2012-03-23 02:28:46 +00:00
2013-05-24 12:20:47 -07:00
// std::vector<std::vector<float> > bone_weights;
// std::vector<std::vector<int> > bone_indexes;
//
// std::vector<KRVector3> vertices;
// std::vector<KRVector2> uva;
// std::vector<KRVector2> uvb;
// std::vector<KRVector3> normals;
// std::vector<KRVector3> tangents;
// std::vector<int> submesh_lengths;
// std::vector<int> submesh_starts;
// std::vector<std::string> material_names;
2012-03-23 02:28:46 +00:00
2012-03-28 19:06:23 +00:00
int dest_vertex_id = 0 ;
2012-12-20 01:23:57 +00:00
2013-05-06 12:58:57 -07:00
bool need_tangents = false ;
2012-03-28 19:34:52 +00:00
for ( int iMaterial = 0 ; iMaterial < material_count ; iMaterial + + ) {
2016-08-07 20:28:15 -07:00
FbxSurfaceMaterial * pMaterial = pMesh - > GetNode ( ) - > GetMaterial ( iMaterial ) ;
2013-05-06 12:58:57 -07:00
KRMaterial * material = context . getMaterialManager ( ) - > getMaterial ( pMaterial - > GetName ( ) ) ;
if ( material ) {
if ( material - > needsVertexTangents ( ) ) {
need_tangents = true ;
}
}
2012-03-28 19:34:52 +00:00
int source_vertex_id = 0 ;
int mat_vertex_count = 0 ;
int mat_vertex_start = dest_vertex_id ;
for ( int iPolygon = 0 ; iPolygon < polygon_count ; iPolygon + + ) {
int lPolygonSize = pMesh - > GetPolygonSize ( iPolygon ) ;
if ( lPolygonSize ! = 3 ) {
source_vertex_id + = lPolygonSize ;
2013-12-14 16:37:14 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Poly with %i vertices found. Expecting only triangles. " , lPolygonSize ) ;
2012-03-28 19:34:52 +00:00
} else {
// ----====---- Read SubMesh / Material Mapping ----====----
int iNewMaterial = - 1 ;
for ( int l = 0 ; l < elementmaterial_count ; l + + )
{
2012-11-30 00:32:03 +00:00
FbxGeometryElementMaterial * leMat = pMesh - > GetElementMaterial ( l ) ;
2012-03-28 19:34:52 +00:00
if ( leMat ) {
2012-11-30 00:32:03 +00:00
if ( leMat - > GetReferenceMode ( ) = = FbxGeometryElement : : eIndex | | leMat - > GetReferenceMode ( ) = = FbxGeometryElement : : eIndexToDirect ) {
2012-03-28 19:34:52 +00:00
int new_id = leMat - > GetIndexArray ( ) . GetAt ( iPolygon ) ;
if ( new_id > = 0 ) {
iNewMaterial = new_id ;
}
2012-03-28 19:06:23 +00:00
}
}
}
2012-03-28 19:34:52 +00:00
if ( iMaterial = = iNewMaterial ) {
// ----====---- Read Vertex-level Attributes ----====----
for ( int iVertex = 0 ; iVertex < 3 ; iVertex + + ) {
// ----====---- Read Vertex Position ----====----
int lControlPointIndex = pMesh - > GetPolygonVertex ( iPolygon , iVertex ) ;
2013-11-23 12:16:31 -08:00
FbxVector4 v = control_points [ lControlPointIndex ] ;
2013-05-24 12:20:47 -07:00
mi . vertices . push_back ( KRVector3 ( v [ 0 ] , v [ 1 ] , v [ 2 ] ) ) ;
2012-03-28 19:34:52 +00:00
2013-05-24 12:20:47 -07:00
if ( mi . bone_names . size ( ) > 0 ) {
control_point_weight_info_t & weight_info = control_point_weights [ lControlPointIndex ] ;
2012-12-12 09:32:53 +00:00
std : : vector < int > vertex_bone_indexes ;
std : : vector < float > vertex_bone_weights ;
2012-12-12 22:15:09 +00:00
for ( int i = 0 ; i < KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX ; i + + ) {
2012-12-12 09:32:53 +00:00
vertex_bone_indexes . push_back ( weight_info . bone_indexes [ i ] ) ;
vertex_bone_weights . push_back ( weight_info . weights [ i ] ) ;
}
2013-05-24 12:20:47 -07:00
mi . bone_indexes . push_back ( vertex_bone_indexes ) ;
mi . bone_weights . push_back ( vertex_bone_weights ) ;
2012-12-12 09:32:53 +00:00
}
2012-04-05 20:12:39 +00:00
KRVector2 new_uva = KRVector2 ( 0.0 , 0.0 ) ;
KRVector2 new_uvb = KRVector2 ( 0.0 , 0.0 ) ;
2012-03-28 19:34:52 +00:00
// ----====---- Read UVs ----====----
2012-04-05 20:12:39 +00:00
2013-11-23 12:16:31 -08:00
FbxStringList uvNames ;
2012-04-05 20:12:39 +00:00
pMesh - > GetUVSetNames ( uvNames ) ;
if ( uv_count > = 1 ) {
const char * setName = uvNames [ 0 ] . Buffer ( ) ;
2013-11-23 12:16:31 -08:00
FbxVector2 uv ;
bool unmapped = false ;
if ( pMesh - > GetPolygonVertexUV ( iPolygon , iVertex , setName , uv , unmapped ) ) {
2013-11-27 00:10:29 -08:00
if ( ! unmapped ) {
new_uva = KRVector2 ( uv [ 0 ] , uv [ 1 ] ) ;
}
2012-04-05 20:12:39 +00:00
}
2013-05-24 12:20:47 -07:00
mi . uva . push_back ( new_uva ) ;
2012-04-05 20:12:39 +00:00
}
if ( uv_count > = 2 ) {
const char * setName = uvNames [ 1 ] . Buffer ( ) ;
2013-11-23 12:16:31 -08:00
FbxVector2 uv ;
bool unmapped = false ;
if ( pMesh - > GetPolygonVertexUV ( iPolygon , iVertex , setName , uv , unmapped ) ) {
2013-11-27 00:10:29 -08:00
if ( ! unmapped ) {
new_uvb = KRVector2 ( uv [ 0 ] , uv [ 1 ] ) ;
}
2012-04-05 20:12:39 +00:00
}
2013-05-24 12:20:47 -07:00
mi . uvb . push_back ( new_uvb ) ;
2012-12-20 01:23:57 +00:00
}
2012-03-28 23:34:39 +00:00
2012-03-28 19:34:52 +00:00
// ----====---- Read Normals ----====----
2012-03-28 23:34:39 +00:00
2013-11-23 12:16:31 -08:00
FbxVector4 new_normal ;
2012-03-28 23:34:39 +00:00
if ( pMesh - > GetPolygonVertexNormal ( iPolygon , iVertex , new_normal ) ) {
2013-05-24 12:20:47 -07:00
mi . normals . push_back ( KRVector3 ( new_normal [ 0 ] , new_normal [ 1 ] , new_normal [ 2 ] ) ) ;
2012-03-28 19:06:23 +00:00
}
2012-03-28 19:34:52 +00:00
2014-04-12 23:42:26 -07:00
/*
TODO - Tangent vectors imported from maya appear incorrectly . . . Only calculating them in Kraken for now
2012-03-28 19:34:52 +00:00
// ----====---- Read Tangents ----====----
2014-04-12 23:42:26 -07:00
if ( need_tangents ) {
for ( int l = 0 ; l < tangent_count ; + + l )
{
FbxVector4 new_tangent ;
FbxGeometryElementTangent * leTangent = pMesh - > GetElementTangent ( l ) ;
if ( leTangent - > GetMappingMode ( ) = = FbxGeometryElement : : eByPolygonVertex ) {
switch ( leTangent - > GetReferenceMode ( ) ) {
case FbxGeometryElement : : eDirect :
new_tangent = leTangent - > GetDirectArray ( ) . GetAt ( lControlPointIndex ) ;
break ;
case FbxGeometryElement : : eIndexToDirect :
{
int id = leTangent - > GetIndexArray ( ) . GetAt ( lControlPointIndex ) ;
new_tangent = leTangent - > GetDirectArray ( ) . GetAt ( id ) ;
}
break ;
default :
break ; // other reference modes not shown here!
2012-03-28 19:34:52 +00:00
}
}
2014-04-12 23:42:26 -07:00
if ( l = = 0 ) {
mi . tangents . push_back ( KRVector3 ( new_tangent [ 0 ] , new_tangent [ 1 ] , new_tangent [ 2 ] ) ) ;
}
2012-03-28 19:06:23 +00:00
}
}
2014-04-12 23:42:26 -07:00
*/
2012-03-28 19:34:52 +00:00
source_vertex_id + + ;
dest_vertex_id + + ;
mat_vertex_count + + ;
2012-03-28 19:06:23 +00:00
}
}
}
2012-03-23 02:28:46 +00:00
}
2012-03-28 19:34:52 +00:00
2012-03-28 21:58:55 +00:00
2012-03-28 19:34:52 +00:00
if ( mat_vertex_count ) {
2012-03-28 21:58:55 +00:00
// ----====---- Output last material / submesh details ----====----
2013-05-24 12:20:47 -07:00
mi . submesh_starts . push_back ( mat_vertex_start ) ;
mi . submesh_lengths . push_back ( mat_vertex_count ) ;
mi . material_names . push_back ( pMaterial - > GetName ( ) ) ;
2012-03-28 19:34:52 +00:00
}
2012-03-23 02:28:46 +00:00
}
2012-03-28 19:06:23 +00:00
2012-12-20 01:23:57 +00:00
delete control_point_weights ;
2012-03-28 19:06:23 +00:00
2016-08-07 20:28:15 -07:00
KRMesh * new_mesh = new KRMesh ( context , pMesh - > GetNode ( ) - > GetName ( ) ) ;
2013-05-24 12:20:47 -07:00
new_mesh - > LoadData ( mi , true , need_tangents ) ;
2013-04-04 16:09:29 -07:00
2014-05-13 21:56:06 -07:00
context . getMeshManager ( ) - > addModel ( new_mesh ) ;
2012-12-20 01:23:57 +00:00
}
2013-11-23 12:16:31 -08:00
KRNode * LoadMesh ( KRNode * parent_node , FbxScene * pFbxScene , FbxGeometryConverter * pGeometryConverter , FbxNode * pNode ) {
2012-12-20 01:23:57 +00:00
std : : string name = GetFbxObjectName ( pNode ) ;
2012-11-02 20:50:45 +00:00
2013-11-23 12:16:31 -08:00
FbxMesh * pSourceMesh = ( FbxMesh * ) pNode - > GetNodeAttribute ( ) ;
2012-12-20 01:23:57 +00:00
2013-01-09 22:37:23 +00:00
if ( KRMesh : : GetLODCoverage ( pNode - > GetName ( ) ) = = 100 ) {
2012-11-02 20:50:45 +00:00
// If this is the full detail model, add an instance of it to the scene file
std : : string light_map = pNode - > GetName ( ) ;
light_map . append ( " _lightmap " ) ;
2013-01-09 22:37:23 +00:00
// FINDME, HACK - Until we have a GUI, we're using prefixes to select correct object type
2012-12-20 01:53:09 +00:00
const char * node_name = pNode - > GetName ( ) ;
2013-01-09 22:37:23 +00:00
if ( strncmp ( node_name , " physics_collider_ " , strlen ( " physics_collider_ " ) ) = = 0 ) {
return new KRCollider ( parent_node - > getScene ( ) , GetFbxObjectName ( pNode ) , pSourceMesh - > GetNode ( ) - > GetName ( ) , KRAKEN_COLLIDER_PHYSICS , 0.0f ) ;
} else if ( strncmp ( node_name , " audio_collider_ " , strlen ( " audio_collider_ " ) ) = = 0 ) {
return new KRCollider ( parent_node - > getScene ( ) , GetFbxObjectName ( pNode ) , pSourceMesh - > GetNode ( ) - > GetName ( ) , KRAKEN_COLLIDER_AUDIO , 1.0f ) ;
2013-12-09 22:29:13 -08:00
} else if ( strncmp ( node_name , " collider " , 8 ) = = 0 ) { // 8 == strlen("collider")
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
// Colliders can have a prefix of collider_##_, where ## indicates the layer mask
// Colliders with a prefix of only collider_ will have a default layer mask of KRAKEN_COLLIDER_PHYSICS | KRAKEN_COLLIDER_AUDIO
2013-01-09 22:37:23 +00:00
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
// Scan through the characters of the name until we no longer see digit characters (or see a '\0' indicating the end of the string)
unsigned int layer = 0 ;
2013-12-09 22:29:13 -08:00
const char * szNodeName = node_name + 8 ; // 8 == strlen("collider")
2013-12-05 18:46:48 -08:00
const char * source_char = szNodeName ;
- I have replaced the lines inserted in to KRResource+Fbx that look for “collider_so_” with logic to look for “collider_##_”. This means that Jonny will need to name the flare height colliders with a prefix of “collider_16_” in the Circa 1948 project.
- The code block starting with “INTERRUPT THE NODE STUFF IN HERE” has been moved to KRImport where it should occur. I have added an example in there on
- Removed the comments, “***** curves 1, 2, and 3 are x, y, z translation .. the first point holds the key frame in centimeters. POSSIBLE UPGRADE .. grab the key frame and output it as the start location to the kranimation file”, as this is incorrect and misleading. You must never depend on the order of the curves in the FBX file. The exporting of the first point in the animation curve should be done in KRImport, after Kraken has already resolved the animation layers and attribute assignments using proper metadata in the fbx file. You can do this using the existing Kraken API rather than modifying Kraken itself. In addition, we can’t make any assumptions based on the first keyframe time matching the animation start time. The actual animation start time is imported by Kraken using the FBX fields that explicitly specify it. The reason we read animation start and end times from a text file is to split the animation into multiple animations from a single fbx file. KRImport can already export a single animation from an fbx file automatically simply by not specifying an animation split file.
- Removed comment, “// **** this is where the assert used to happen”. This comment adds no value and is confusing to other Kraken users, as the assert does not happen any more ;-)
- Removed comment, “// KRNode *LoadMesh parses the "collider names" and then alters the attributes (NFB HACK)”. I have refactored this code so this is no longer a hack.
--HG--
branch : nfb
2013-12-05 18:34:20 -08:00
while ( * source_char > = ' 0 ' & & * source_char < = ' 9 ' ) {
layer = layer * 10 + ( * source_char + + - ' 0 ' ) ;
}
if ( layer = = 0 ) {
// No layer mask number was found, use the default
layer = KRAKEN_COLLIDER_PHYSICS | KRAKEN_COLLIDER_AUDIO ;
}
2013-12-09 22:29:13 -08:00
if ( * source_char = = ' _ ' ) {
// Pattern has matched
return new KRCollider ( parent_node - > getScene ( ) , GetFbxObjectName ( pNode ) , pSourceMesh - > GetNode ( ) - > GetName ( ) , layer , 1.0f ) ;
} else {
// This is just a normal node, which happened to be prefixed with "collider" but didn't have a number and underscore
return new KRModel ( parent_node - > getScene ( ) , GetFbxObjectName ( pNode ) , pSourceMesh - > GetNode ( ) - > GetName ( ) , light_map , 0.0f , true , false ) ;
}
2012-12-20 01:53:09 +00:00
} else {
2013-01-09 22:37:23 +00:00
return new KRModel ( parent_node - > getScene ( ) , GetFbxObjectName ( pNode ) , pSourceMesh - > GetNode ( ) - > GetName ( ) , light_map , 0.0f , true , false ) ;
2012-12-20 01:53:09 +00:00
}
2012-11-03 02:57:35 +00:00
} else {
return NULL ;
2012-11-02 20:50:45 +00:00
}
2012-11-03 02:57:35 +00:00
2012-03-23 02:28:46 +00:00
}
2013-11-23 12:16:31 -08:00
KRNode * LoadSkeleton ( KRNode * parent_node , FbxScene * pFbxScene , FbxNode * pNode ) {
2012-12-07 08:22:20 +00:00
std : : string name = GetFbxObjectName ( pNode ) ;
KRBone * new_bone = new KRBone ( parent_node - > getScene ( ) , name . c_str ( ) ) ;
2013-05-24 12:20:47 -07:00
//static bool GetBindPoseContaining(FbxScene* pScene, FbxNode* pNode, PoseList& pPoseList, FbxArray<int>& pIndex);
// PoseList pose_list;
// FbxArray<int> pose_indices;
// if(FbxPose::GetBindPoseContaining(pFbxScene, pNode, pose_list, pose_indices)) {
// fprintf(stderr, "Found bind pose(s)!\n");
// }
2012-12-07 08:22:20 +00:00
return new_bone ;
}
2013-11-23 12:16:31 -08:00
KRNode * LoadLocator ( KRNode * parent_node , FbxScene * pFbxScene , FbxNode * pNode ) {
2013-10-06 18:56:23 -07:00
std : : string name = GetFbxObjectName ( pNode ) ;
KRLocator * new_locator = new KRLocator ( parent_node - > getScene ( ) , name . c_str ( ) ) ;
2013-12-05 19:44:58 -08:00
// Enumerate fbx properties so client code can convert locators into application-specific objects
FbxProperty fbx_property = pNode - > GetFirstProperty ( ) ;
while ( fbx_property . IsValid ( ) ) {
std : : string property_name = fbx_property . GetNameAsCStr ( ) ;
2013-12-05 20:15:32 -08:00
std : : transform ( property_name . begin ( ) , property_name . end ( ) , property_name . begin ( ) , : : tolower ) ;
2013-12-05 19:44:58 -08:00
boost : : variant < int , double , bool , std : : string > property_value = " " ;
switch ( fbx_property . GetPropertyDataType ( ) . GetType ( ) ) {
case eFbxInt :
2013-12-05 20:15:32 -08:00
new_locator - > getUserAttributes ( ) [ property_name ] = fbx_property . Get < FbxInt > ( ) ;
2013-12-05 19:44:58 -08:00
break ;
case eFbxDouble :
2013-12-05 20:15:32 -08:00
new_locator - > getUserAttributes ( ) [ property_name ] = fbx_property . Get < FbxDouble > ( ) ;
2013-12-05 19:44:58 -08:00
break ;
case eFbxBool :
2013-12-05 20:15:32 -08:00
new_locator - > getUserAttributes ( ) [ property_name ] = fbx_property . Get < FbxBool > ( ) ;
2013-12-05 19:44:58 -08:00
break ;
case eFbxFloat :
2013-12-05 20:15:32 -08:00
new_locator - > getUserAttributes ( ) [ property_name ] = fbx_property . Get < FbxDouble > ( ) ;
2013-12-05 19:44:58 -08:00
break ;
case eFbxString :
2013-12-05 20:15:32 -08:00
new_locator - > getUserAttributes ( ) [ property_name ] = std : : string ( fbx_property . Get < FbxString > ( ) . Buffer ( ) ) ;
2013-12-05 19:44:58 -08:00
break ;
default :
{
2013-12-09 15:35:07 -08:00
// fprintf(stderr, "FBX property not imported due to unsupported data type: %s.%s\n", name.c_str(), property_name.c_str());
2013-12-05 19:44:58 -08:00
}
break ;
}
2013-12-05 20:15:32 -08:00
fbx_property = pNode - > GetNextProperty ( fbx_property ) ;
2013-12-05 19:44:58 -08:00
}
2013-10-06 18:56:23 -07:00
//static bool GetBindPoseContaining(FbxScene* pScene, FbxNode* pNode, PoseList& pPoseList, FbxArray<int>& pIndex);
// PoseList pose_list;
// FbxArray<int> pose_indices;
// if(FbxPose::GetBindPoseContaining(pFbxScene, pNode, pose_list, pose_indices)) {
// fprintf(stderr, "Found bind pose(s)!\n");
// }
return new_locator ;
}
2013-11-23 12:16:31 -08:00
KRNode * LoadCamera ( KRNode * parent_node , FbxNode * pNode ) {
2012-12-20 22:08:41 +00:00
FbxCamera * camera = ( FbxCamera * ) pNode - > GetNodeAttribute ( ) ;
const char * szName = pNode - > GetName ( ) ;
KRCamera * new_camera = new KRCamera ( parent_node - > getScene ( ) , szName ) ;
return new_camera ;
}
2013-11-23 12:16:31 -08:00
KRNode * LoadLight ( KRNode * parent_node , FbxNode * pNode ) {
2012-04-12 00:43:53 +00:00
const GLfloat PI = 3.14159265 ;
const GLfloat d2r = PI * 2 / 360 ;
2012-11-30 00:32:03 +00:00
FbxLight * pLight = ( FbxLight * ) pNode - > GetNodeAttribute ( ) ;
2012-04-05 23:09:41 +00:00
const char * szName = pNode - > GetName ( ) ;
2012-04-06 01:07:23 +00:00
2012-11-30 00:32:03 +00:00
FbxDouble3 light_color = pLight - > Color . Get ( ) ;
FbxDouble light_intensity = pLight - > Intensity . Get ( ) ;
FbxDouble light_hotspot = pLight - > InnerAngle . Get ( ) ; // light inner cone angle (in degrees). Also know as the HotSpot
FbxDouble light_coneangle = pLight - > OuterAngle . Get ( ) ; // light outer cone angle (in degrees). Also known as the Falloff
2013-11-23 12:16:31 -08:00
FbxLight : : EDecayType light_decaytype = pLight - > DecayType . Get ( ) ; // decay type
2012-11-30 00:32:03 +00:00
FbxDouble light_decaystart = pLight - > DecayStart . Get ( ) ; // decay start distance
2012-04-06 01:07:23 +00:00
// KFbxLight::eNONE - does not attenuate with distance
// KFbxLight::eLINEAR - attenuation of 1/d
// KFbxLight::eQUADRATIC - attenuation of 1/d^2
2012-11-29 21:28:49 +00:00
// KFbxLight::eCUBIC - attenuation of
2012-04-12 00:43:53 +00:00
KRLight * new_light = NULL ;
2012-04-05 23:09:41 +00:00
switch ( pLight - > LightType . Get ( ) ) {
2013-11-23 12:16:31 -08:00
case FbxLight : : ePoint :
2012-04-12 00:43:53 +00:00
{
2012-09-05 18:14:08 +00:00
KRPointLight * l = new KRPointLight ( parent_node - > getScene ( ) , szName ) ;
2012-04-12 00:43:53 +00:00
new_light = l ;
}
2012-04-05 23:09:41 +00:00
break ;
2013-11-23 12:16:31 -08:00
case FbxLight : : eDirectional :
2012-04-12 00:43:53 +00:00
{
2012-09-05 18:14:08 +00:00
KRDirectionalLight * l = new KRDirectionalLight ( parent_node - > getScene ( ) , szName ) ;
2012-04-12 00:43:53 +00:00
new_light = l ;
}
2012-04-05 23:09:41 +00:00
break ;
2013-11-23 12:16:31 -08:00
case FbxLight : : eSpot :
2012-04-12 00:43:53 +00:00
{
2012-09-05 18:14:08 +00:00
KRSpotLight * l = new KRSpotLight ( parent_node - > getScene ( ) , szName ) ;
2012-04-12 00:43:53 +00:00
l - > setInnerAngle ( light_hotspot * d2r ) ;
l - > setOuterAngle ( light_coneangle * d2r ) ;
new_light = l ;
}
2012-04-05 23:09:41 +00:00
break ;
2013-11-23 12:16:31 -08:00
case FbxLight : : eVolume :
case FbxLight : : eArea :
2012-04-05 23:09:41 +00:00
// Not supported yet
break ;
}
2012-04-12 00:43:53 +00:00
if ( new_light ) {
new_light - > setColor ( KRVector3 ( light_color [ 0 ] , light_color [ 1 ] , light_color [ 2 ] ) ) ;
new_light - > setIntensity ( light_intensity ) ;
new_light - > setDecayStart ( light_decaystart ) ;
}
2012-11-03 02:57:35 +00:00
return new_light ;
2012-04-12 00:43:53 +00:00
2012-04-05 23:09:41 +00:00
}