From 6d5169cf33d59643d38095ba4d37613441973199 Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Sat, 8 Jul 2006 14:27:13 +0000 Subject: [PATCH] Fix Animation support and add bsplines and kf files. --- NifImport/ImportAnimation.cpp | 93 +++++++++++++++++++++++++---------- NifImport/KFImporter.cpp | 35 +++++++++++++ NifImport/KFImporter.h | 34 +++++++++++++ NifImport/KFMImporter.cpp | 25 +++++++++- NifImport/KFMImporter.h | 1 + NifImport/MaxNifImport.cpp | 24 +++++---- NifImport/MaxNifImport.vcproj | 10 +++- NifImport/MaxNifTools.ini | 4 +- 8 files changed, 187 insertions(+), 39 deletions(-) create mode 100644 NifImport/KFImporter.cpp create mode 100644 NifImport/KFImporter.h diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp index c239048..1afe253 100644 --- a/NifImport/ImportAnimation.cpp +++ b/NifImport/ImportAnimation.cpp @@ -14,6 +14,7 @@ HISTORY: #include "MaxNifImport.h" #include "NIFImporter.h" #include "KFMImporter.h" +#include "KFImporter.h" #include <obj/NiInterpolator.h> #include <obj/NiTransformInterpolator.h> #include <obj/NiTransformData.h> @@ -23,7 +24,7 @@ HISTORY: #include <obj/NiKeyframeController.h> #include <obj/NiKeyframeData.h> #include <obj/NiStringPalette.h> - +#include <obj/NiBSplineCompTransformInterpolator.h> using namespace Niflib; const Class_ID IPOS_CONTROL_CLASS_ID = Class_ID(0x118f7e02,0xffee238a); @@ -71,7 +72,7 @@ template<> inline ILinRotKey MapKey<ILinRotKey, QuatKey>(QuatKey& key, float time) { ILinRotKey rKey; - rKey.val = TOQUAT(key.data); + rKey.val = TOQUAT(key.data, true); return InitLinKey(rKey, key, time); } @@ -127,7 +128,7 @@ template<> inline IBezQuatKey MapKey<IBezQuatKey, QuatKey>(QuatKey& key, float time) { IBezQuatKey rKey; - rKey.val = TOQUAT(key.data); + rKey.val = TOQUAT(key.data, true); return InitBezKey(rKey, key, time); } @@ -164,7 +165,7 @@ template<> inline ITCBRotKey MapKey<ITCBRotKey, QuatKey>(QuatKey& key, float time) { ITCBRotKey rKey; - rKey.val = TOQUAT(key.data); + rKey.val = TOQUAT(key.data, true); InitTCBKey(rKey, key, time); rKey.flags = TCBKEY_QUATVALID; return rKey; @@ -250,6 +251,7 @@ struct AnimationImport bool AddValues(Control *c, NiKeyframeDataRef data, float time); + Control* MakePosition(Control *tmCont, Class_ID clsid); Control* MakePositionXYZ(Control *tmCont, Class_ID clsid); Control* MakeRotation(Control *tmCont, Class_ID rotClsid, Class_ID rollClsid); Control* MakeScale(Control *tmCont, Class_ID clsid); @@ -265,8 +267,9 @@ bool NifImporter::ImportAnimation() if (nodes.empty()) return false; + NiNodeRef rootNode = root; AnimationImport ai(*this); - return ai.AddValues(DynamicCast<NiObjectNET>(nodes[0]->GetChildren())); + return ai.AddValues(DynamicCast<NiObjectNET>(rootNode->GetChildren())); } bool KFMImporter::ImportAnimation() @@ -274,12 +277,15 @@ bool KFMImporter::ImportAnimation() bool ok = false; int curFrame = 0; // Read Kf files -#ifdef USE_UNSUPPORTED_CODE + AnimationImport ai(*this); - float time = 0.0f; + float time = FramesIncrement; for(vector<NiControllerSequenceRef>::iterator itr = kf.begin(); itr != kf.end(); ++itr){ + float minTime = 1e+35f; + float maxTime = 0.0f; + NiControllerSequenceRef cntr = (*itr); vector<ControllerLink> links = cntr->GetControllerData(); for (vector<ControllerLink>::iterator lnk=links.begin(); lnk != links.end(); ++lnk){ @@ -298,31 +304,58 @@ bool KFMImporter::ImportAnimation() float start = cntr->GetStartTime(); float stop = cntr->GetStopTime(); + float total = (stop - start); if ((*lnk).interpolator){ if (NiTransformInterpolatorRef interp = (*lnk).interpolator) { if (NiTransformDataRef data = interp->GetData()){ - ok |= ai.AddValues(c, data, time); - time += (stop-start) + FramesIncrement; // round to nearest 10f ? + if (ai.AddValues(c, data, time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; + } + } + } else if (NiBSplineCompTransformInterpolatorRef interp = (*lnk).interpolator) { + int npoints = total * 60.0f; + + NiKeyframeDataRef data = CreateBlock("NiKeyframeData"); + data->SetRotateType(QUADRATIC_KEY); + data->SetTranslateType(QUADRATIC_KEY); + data->SetScaleType(QUADRATIC_KEY); + data->SetTranslateKeys( interp->SampleTranslateKeys(npoints, 4) ); + data->SetQuatRotateKeys( interp->SampleQuatRotateKeys(npoints, 4) ); + data->SetScaleKeys( interp->SampleScaleKeys(npoints, 4) ); + + if (ai.AddValues(c, data, time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; } } } else if ((*lnk).controller) { if (NiTransformControllerRef tc = DynamicCast<NiTransformController>((*lnk).controller)) { if (NiTransformInterpolatorRef interp = tc->GetInterpolator()) { if (NiTransformDataRef data = interp->GetData()){ - ok |= ai.AddValues(c, data, time); - time += (stop-start) + FramesIncrement; // round to nearest 10f ? + if (ai.AddValues(c, data, time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; + } } } } else if (NiKeyframeControllerRef kfc = DynamicCast<NiKeyframeController>((*lnk).controller)) { - if (NiKeyframeDataRef kfData = kfc->GetData()) { - ok |= ai.AddValues(c, kfData, time); - time += (stop-start) + FramesIncrement; // round to nearest 10f ? + if (NiKeyframeDataRef data = kfc->GetData()) { + if (ai.AddValues(c, data, time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; + } } } } } + if (maxTime > minTime && maxTime > 0.0f) + time += (maxTime-minTime) + FramesIncrement; } -#endif return ok; } @@ -371,7 +404,7 @@ bool AnimationImport::AddValues(NiObjectNETRef nref) if (NULL == c) return false; - float time = 0.0f; + float time = FramesIncrement; list< NiTimeControllerRef > clist = nref->GetControllers(); if (NiTransformControllerRef tc = SelectFirstObjectOfType<NiTransformController>(clist)) { if (NiTransformInterpolatorRef interp = tc->GetInterpolator()) { @@ -544,20 +577,28 @@ Control* AnimationImport::MakeScale(Control *tmCont, Class_ID clsid) return NULL; } -Control* AnimationImport::MakePositionXYZ(Control *tmCont, Class_ID clsid) +Control* AnimationImport::MakePosition(Control *tmCont, Class_ID clsid) { Interface *ip = ni.gi; - if (Control *c = tmCont->GetPositionController()){ - // First make the controller and XYZ Independent position controller, then fix individuals - if (c->ClassID()!= IPOS_CONTROL_CLASS_ID) { - if (Control *tmp = (Control*)ip->CreateInstance(CTRL_POSITION_CLASS_ID, IPOS_CONTROL_CLASS_ID)) { - if (!tmCont->SetPositionController(tmp)) { - tmp->DeleteThis(); - } else { - c = tmp; - } + if (Control *c = tmCont->GetPositionController()) { + if (c->ClassID()!=clsid) { + if (Control *tmpCtrl = (Control*)ip->CreateInstance(CTRL_POSITION_CLASS_ID, clsid)){ + if (!tmCont->SetPositionController(tmpCtrl)) + tmpCtrl->DeleteThis(); + else + c = tmpCtrl; } } + return c; + } + return NULL; +} + +Control* AnimationImport::MakePositionXYZ(Control *tmCont, Class_ID clsid) +{ + Interface *ip = ni.gi; + // First make the controller and XYZ Independent position controller, then fix individuals + if (Control *c = MakePosition(tmCont, IPOS_CONTROL_CLASS_ID)){ if (Control *x = c->GetXController()){ if (x->ClassID()!= clsid) { if (Control *tmp = (Control*)ip->CreateInstance(CTRL_FLOAT_CLASS_ID, clsid)) diff --git a/NifImport/KFImporter.cpp b/NifImport/KFImporter.cpp new file mode 100644 index 0000000..a27f131 --- /dev/null +++ b/NifImport/KFImporter.cpp @@ -0,0 +1,35 @@ +#include "StdAfx.h" +#include "KFImporter.h" +#include <kfm.h> +#include "gen/ControllerLink.h" +using namespace Niflib; + +KFImporter::KFImporter(const TCHAR *Name,ImpInterface *I,Interface *GI, BOOL SuppressPrompts) + : BaseClass() +{ + BaseInit(Name, I, GI, SuppressPrompts); +} + +KFImporter::~KFImporter(void) +{ +} + +void KFImporter::ReadBlocks() +{ + try + { + kf = DynamicCast<NiControllerSequence>(ReadNifList(name.c_str())); + BuildNodes(); + } + catch (std::exception&) + { + } + catch (...) + { + } +} + +bool KFImporter::DoImport() +{ + return ImportAnimation(); +} diff --git a/NifImport/KFImporter.h b/NifImport/KFImporter.h new file mode 100644 index 0000000..4022ea1 --- /dev/null +++ b/NifImport/KFImporter.h @@ -0,0 +1,34 @@ +/********************************************************************** +*< +FILE: KFImporter.h + +DESCRIPTION: KF Importer helper class + +CREATED BY: tazpn (Theo) + +HISTORY: + +*> Copyright (c) 2006, All Rights Reserved. +**********************************************************************/ +#ifndef _KFIMPORTER_H_ +#define _KFIMPORTER_H_ + +#pragma once +#include "NIFImporter.h" +#include "KFMImporter.h" +#include "niutils.h" +#include "obj/NiControllerSequence.h" + +class KFImporter : public KFMImporter +{ + typedef KFMImporter BaseClass; +public: + KFImporter(const TCHAR *Name,ImpInterface *I,Interface *GI, BOOL SuppressPrompts); + ~KFImporter(void); + + void ReadBlocks(); + virtual bool DoImport(); +}; + + +#endif \ No newline at end of file diff --git a/NifImport/KFMImporter.cpp b/NifImport/KFMImporter.cpp index dcdc4ef..bc801be 100644 --- a/NifImport/KFMImporter.cpp +++ b/NifImport/KFMImporter.cpp @@ -10,6 +10,10 @@ KFMImporter::KFMImporter(const TCHAR *Name,ImpInterface *I,Interface *GI, BOOL S BaseInit(Name, I, GI, SuppressPrompts); } +KFMImporter::KFMImporter() +{ +} + KFMImporter::~KFMImporter(void) { } @@ -26,6 +30,10 @@ void KFMImporter::ReadBlocks() GetFullPathName(name.c_str(), MAX_PATH, buffer, NULL); PathRemoveFileSpec(buffer); #ifdef USE_UNSUPPORTED_CODE + string nif_filename = path + '\\' + kfm.nif_filename; + if (_taccess(nif_filename.c_str(), 0) != -1) + root = ReadNifTree(nif_filename); + //root = kfm.MergeActions(string(buffer)); BuildNodes(); @@ -38,9 +46,12 @@ void KFMImporter::ReadBlocks() if (action_filename != last_file) { ctrllist = DynamicCast<NiControllerSequence>(ReadNifList(action_filename)); } - if ((*it).unk_int2 && (*it).unk_int2 <= ctrllist.size()) { + if (((*it).unk_int2 && (*it).unk_int2 <= ctrllist.size())) { if (NiControllerSequenceRef ctrlSeq = ctrllist[(*it).unk_int2-1]) kf.push_back(ctrlSeq); + } else if (!(*it).unk_int2 && ctrllist.size() == 1) { + if (NiControllerSequenceRef ctrlSeq = ctrllist[0]) + kf.push_back(ctrlSeq); } } } @@ -58,6 +69,18 @@ void KFMImporter::ReadBlocks() bool KFMImporter::DoImport() { // might check if blocks exist and if not go ahead and import nif. + if (root) + { + int n = nodes.size(); + int m = 0; + for (vector<NiNodeRef>::iterator itr = nodes.begin(), end = nodes.end(); itr != end; ++itr) { + if (INode *p = gi->GetINodeByName((*itr)->GetName().c_str())) + m++; + } + if (m != n) { + BaseClass::DoImport(); + } + } return ImportAnimation(); //return BaseClass::DoImport(); } diff --git a/NifImport/KFMImporter.h b/NifImport/KFMImporter.h index 241f706..f07aa80 100644 --- a/NifImport/KFMImporter.h +++ b/NifImport/KFMImporter.h @@ -23,6 +23,7 @@ class KFMImporter : public NifImporter typedef NifImporter BaseClass; public: KFMImporter(const TCHAR *Name,ImpInterface *I,Interface *GI, BOOL SuppressPrompts); + KFMImporter(); ~KFMImporter(void); void ReadBlocks(); diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp index aa456df..40f861f 100644 --- a/NifImport/MaxNifImport.cpp +++ b/NifImport/MaxNifImport.cpp @@ -13,6 +13,7 @@ #include "stdafx.h" #include "MaxNifImport.h" #include "KFMImporter.h" +#include "KFImporter.h" using namespace Niflib; #define MaxNifImport_CLASS_ID Class_ID(0x794ac1c1, 0x8b4c64c7) @@ -130,9 +131,9 @@ MaxNifImport::~MaxNifImport() int MaxNifImport::ExtCount() { #ifdef USE_UNSUPPORTED_CODE - return 2; + return 3; #else - return 1; + return 2; #endif } @@ -141,7 +142,8 @@ const TCHAR *MaxNifImport::Ext(int n) switch (n) { case 0: return _T("NIF"); - case 1: return _T("KFM"); + case 1: return _T("KF"); + case 2: return _T("KFM"); } return _T(""); } @@ -222,21 +224,25 @@ int MaxNifImport::DoImport(const TCHAR *filename,ImpInterface *i, Interface *gi, LPCTSTR ext = PathFindExtension(filename); - if (_tcsicmp(ext, ".KFM") == 0) + if (_tcsicmp(ext, ".NIF") == 0) + { + NifImporter importer(filename, i, gi, suppressPrompts); + if (!importer.isValid()) + return FALSE; + ok = importer.DoImport(); + } + else if (_tcsicmp(ext, ".KFM") == 0) { KFMImporter importer(filename, i, gi, suppressPrompts); if (!importer.isValid()) return FALSE; - ok = importer.DoImport(); - } - else + else if (_tcsicmp(ext, ".KF") == 0) { - NifImporter importer(filename, i, gi, suppressPrompts); + KFImporter importer(filename, i, gi, suppressPrompts); if (!importer.isValid()) return FALSE; - ok = importer.DoImport(); } } diff --git a/NifImport/MaxNifImport.vcproj b/NifImport/MaxNifImport.vcproj index 561006e..ace67d6 100644 --- a/NifImport/MaxNifImport.vcproj +++ b/NifImport/MaxNifImport.vcproj @@ -154,7 +154,7 @@ AdditionalOptions="/LD " Optimization="0" AdditionalIncludeDirectories="" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE" GeneratePreprocessedFile="0" ExceptionHandling="2" RuntimeLibrary="1" @@ -234,6 +234,10 @@ RelativePath=".\DllEntry.cpp" > </File> + <File + RelativePath=".\KFImporter.cpp" + > + </File> <File RelativePath=".\MaxNifImport.def" > @@ -263,6 +267,10 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl" > + <File + RelativePath=".\KFImporter.h" + > + </File> <File RelativePath=".\niutils.h" > diff --git a/NifImport/MaxNifTools.ini b/NifImport/MaxNifTools.ini index 0259437..4ec1a55 100644 --- a/NifImport/MaxNifTools.ini +++ b/NifImport/MaxNifTools.ini @@ -43,8 +43,8 @@ BipedAngle=90.0 BipedAnkleAttach=0.2 ; Use Triangle Pelvis. Default: 0 BipedTrianglePelvis=0 -; Remove unused bones from the biped on import of a mesh. Default: 1 -RemoveUnusedImportedBones=1 +; Remove unused bones from the biped on import of a mesh. Default: 0 +RemoveUnusedImportedBones=0 ; Minimum Bone Width / Maximum Bone Width / Ratio of Width to Length MinBoneWidth=0.001 MaxBoneWidth=0.1 -- GitLab