diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt index be0812cbfa365dbb597ce0b1b30fe428e01e9b17..9b799a492dfccf3ccdf13d46eb3f4587aedeab4d 100644 --- a/MaxNifPlugins_Readme.txt +++ b/MaxNifPlugins_Readme.txt @@ -1,4 +1,4 @@ - MaxPlugins 0.1.3 + MaxPlugins 0.1.4 ================ @@ -28,12 +28,20 @@ Change log ---------- + 0.1.4 + ----- + + o Importer + - Fixed UV values when flipping so they align properly in UVW window + - Fixed issues with DAoC mesh import (in NifLib) + - Fixed rotation issue with animation import + 0.1.3 ----- o Importer - - Fixed alignment issues when importing Morrowind Armor nifs - - Added initial animation support (only for animations internal to nif, no kf file support yet) + - Fixed alignment issues when importing Morrowind Armor nifs + - Added initial animation support (only for animations internal to nif, no kf file support yet) - Fixed numerous issues with bone system (biped is still broken) - Fixed issues with skin and doac nifs diff --git a/NifImport/BaseImporter.h b/NifImport/BaseImporter.h index abedf9fe8571dd63e0554319e5237a6f15120319..d6c3b7d287cedcac8d02690b432876299a845c18 100644 --- a/NifImport/BaseImporter.h +++ b/NifImport/BaseImporter.h @@ -16,6 +16,7 @@ HISTORY: class IBipMaster; extern IBipMaster * (_cdecl * Max8CreateNewBiped)(float,float,class Point3 const &,int,int,int,int,int,int,int,int,int,int,int,int,float,int,int,int,int,int,int,int,int); +extern IBipMaster * (_cdecl * Max7CreateNewBiped)(float,float,class Point3 const &,int,int,int,int,int,int,int,int,int,int,int,int,float,int,int,int,int); // Importer Base class BaseImporter @@ -47,11 +48,18 @@ public: path = buffer; iniFileValid = false; - LPCTSTR Max8CreateNewBipedName = TEXT("?CreateNewBiped@@YAPAVIBipMaster@@MMABVPoint3@@HHHHHHHHHHHHMHHHHHHHH@Z"); HMODULE hBiped = GetModuleHandle("biped.dlc"); - if (NULL != hBiped && 0 == Max8CreateNewBiped) - *(FARPROC*)&Max8CreateNewBiped = GetProcAddress(hBiped, Max8CreateNewBipedName); - + if (NULL != hBiped) + { + if (0 == Max8CreateNewBiped && 0 == Max7CreateNewBiped){ + LPCTSTR Max8CreateNewBipedName = TEXT("?CreateNewBiped@@YAPAVIBipMaster@@MMABVPoint3@@HHHHHHHHHHHHMHHHHHHHH@Z"); + *(FARPROC*)&Max8CreateNewBiped = GetProcAddress(hBiped, Max8CreateNewBipedName); + } + if (0 == Max8CreateNewBiped && 0 == Max7CreateNewBiped) { + LPCTSTR Max7CreateNewBipedName = TEXT("?CreateNewBiped@@YAPAVIBipMaster@@MMABVPoint3@@HHHHHHHHHHHHMHHHH@Z"); + *(FARPROC*)&Max7CreateNewBiped = GetProcAddress(hBiped, Max7CreateNewBipedName); + } + } // Load ini settings iniFileValid = false; LoadIniSettings(); diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp index 80cf8403c826221ad1c45e89fae45a4ba3760cf2..c126177aae030b3551ac3a03b6712db9ab690ca7 100644 --- a/NifImport/ImportAnimation.cpp +++ b/NifImport/ImportAnimation.cpp @@ -307,6 +307,13 @@ bool KFMImporter::ImportAnimation() float total = (stop - start); if ((*lnk).interpolator){ if (NiTransformInterpolatorRef interp = (*lnk).interpolator) { + + // Set initial conditions + Point3 p = TOPOINT3(interp->GetTranslation()); + Quat q = TOQUAT(interp->GetRotation()); + float s = interp->GetScale(); + PosRotScaleNode(c, p, q, s, prsDefault, 0); + if (NiTransformDataRef data = interp->GetData()){ if (ai.AddValues(c, data, time)) { minTime = min(minTime, start); @@ -317,6 +324,12 @@ bool KFMImporter::ImportAnimation() } else if (NiBSplineCompTransformInterpolatorRef interp = (*lnk).interpolator) { int npoints = total * 60.0f; + // Set initial conditions + Point3 p = TOPOINT3(interp->GetTranslation()); + Quat q = TOQUAT(interp->GetRotation()); + float s = interp->GetScale(); + PosRotScaleNode(c, p, q, s, prsDefault, 0); + NiKeyframeDataRef data = CreateBlock("NiKeyframeData"); data->SetRotateType(QUADRATIC_KEY); data->SetTranslateType(QUADRATIC_KEY); @@ -334,6 +347,12 @@ bool KFMImporter::ImportAnimation() } else if ((*lnk).controller) { if (NiTransformControllerRef tc = DynamicCast<NiTransformController>((*lnk).controller)) { if (NiTransformInterpolatorRef interp = tc->GetInterpolator()) { + // Set initial conditions + Point3 p = TOPOINT3(interp->GetTranslation()); + Quat q = TOQUAT(interp->GetRotation()); + float s = interp->GetScale(); + PosRotScaleNode(c, p, q, s, prsDefault, 0); + if (NiTransformDataRef data = interp->GetData()){ if (ai.AddValues(c, data, time)) { minTime = min(minTime, start); diff --git a/NifImport/ImportMeshAndSkin.cpp b/NifImport/ImportMeshAndSkin.cpp index 0b311ecc7c14dc380cac7cd5774e344a59907817..ef7e4351088dc199eadb1fe49b4df0ac7fd93aaa 100644 --- a/NifImport/ImportMeshAndSkin.cpp +++ b/NifImport/ImportMeshAndSkin.cpp @@ -128,7 +128,7 @@ bool NifImporter::ImportMesh(ImpNode *node, TriObject *o, NiTriBasedGeomRef triG mesh.setNumTVerts(n, FALSE); for (int i=0; i<n; ++i) { TexCoord& texCoord = texCoords[i]; - mesh.tVerts[i].Set(texCoord.u, (flipUVTextures) ? -texCoord.v : texCoord.v, 0); + mesh.tVerts[i].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } } diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp index 9cc6b8cd13b30fdbb5db3c32de9024c31a18862f..799771b124d7586eb8109b7b32e72d75b2952996 100644 --- a/NifImport/ImportSkeleton.cpp +++ b/NifImport/ImportSkeleton.cpp @@ -12,7 +12,7 @@ HISTORY: **********************************************************************/ #include "stdafx.h" #include "MaxNifImport.h" -//#include <cs/Biped8Api.h> +#include <cs/BipedApi.h> #include <obj/NiTriBasedGeom.h> #include <obj/NiTriBasedGeomData.h> #include <obj/NiTimeController.h> @@ -152,11 +152,20 @@ void NifImporter::ImportBipeds(vector<NiNodeRef>& nodes) int horseTwistLinks = CountNodesByName(bipedNodes, FormatText("%s L Horse*Twist*", bipname.c_str())); NiNodeRef root = nodes[0]; - IBipMaster* master = Max8CreateNewBiped(height, angle, wpos, arms, triPelvis, - nnecklinks, nspinelinks, nleglinks, ntaillinks, npony1links, npony2links, - numfingers, nfinglinks, numtoes, ntoelinks, bipedAnkleAttach, prop1exists, - prop2exists, prop3exists, forearmTwistLinks, upperarmTwistLinks, thighTwistLinks, - calfTwistLinks, horseTwistLinks); + IBipMaster* master = NULL; + if (Max8CreateNewBiped) { + master = Max8CreateNewBiped(height, angle, wpos, arms, triPelvis, + nnecklinks, nspinelinks, nleglinks, ntaillinks, npony1links, npony2links, + numfingers, nfinglinks, numtoes, ntoelinks, bipedAnkleAttach, prop1exists, + prop2exists, prop3exists, forearmTwistLinks, upperarmTwistLinks, thighTwistLinks, + calfTwistLinks, horseTwistLinks); + } else if (Max7CreateNewBiped) { + master = Max7CreateNewBiped(height, angle, wpos, arms, triPelvis, + nnecklinks, nspinelinks, nleglinks, ntaillinks, npony1links, npony2links, + numfingers, nfinglinks, numtoes, ntoelinks, bipedAnkleAttach, prop1exists, + prop2exists, prop3exists, forearmTwistLinks); + } + if (master) { master->SetRootName(const_cast<TCHAR*>(bipname.c_str())); @@ -328,15 +337,15 @@ Matrix3 GenerateRotMatrix(AngAxis a) float w = a.axis.z; float rcos = cos(a.angle); float rsin = sin(a.angle); - m[0][0] = rcos + u*u*(1-rcos); - m[1][0] = w * rsin + v*u*(1-rcos); - m[2][0] = -v * rsin + w*u*(1-rcos); - m[0][1] = -w * rsin + u*v*(1-rcos); - m[1][1] = rcos + v*v*(1-rcos); - m[2][1] = u * rsin + w*v*(1-rcos); - m[0][2] = v * rsin + u*w*(1-rcos); - m[1][2] = -u * rsin + v*w*(1-rcos); - m[2][2] = rcos + w*w*(1-rcos); + m.GetRow(0)[0] = rcos + u*u*(1-rcos); + m.GetRow(1)[0] = w * rsin + v*u*(1-rcos); + m.GetRow(2)[0] = -v * rsin + w*u*(1-rcos); + m.GetRow(0)[1] = -w * rsin + u*v*(1-rcos); + m.GetRow(1)[1] = rcos + v*v*(1-rcos); + m.GetRow(2)[1] = u * rsin + w*v*(1-rcos); + m.GetRow(0)[2] = v * rsin + u*w*(1-rcos); + m.GetRow(1)[2] = -u * rsin + v*w*(1-rcos); + m.GetRow(2)[2] = rcos + w*w*(1-rcos); return m; } @@ -560,7 +569,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse) Quat q(im); //q.Normalize(); Vector3 ppos; - Point3 zAxis(0,1,0); + Point3 zAxis(0,0,0); bool hasChildren = !children.empty(); if (hasChildren) { float len = 0.0f; diff --git a/NifImport/MaxNifImport.h b/NifImport/MaxNifImport.h index 19ff556f03aa7a703a51f1b2556ba88ebc817b16..30ff9e2ac3fad10698610d7bcd82288b58335930 100644 --- a/NifImport/MaxNifImport.h +++ b/NifImport/MaxNifImport.h @@ -24,7 +24,7 @@ #include <iparamb2.h> #include <iparamm2.h> #ifdef USE_BIPED -# include <cs/Biped8Api.h> +# include <cs/BipedApi.h> #endif #include <scenetraversal.h> #include <plugapi.h> diff --git a/NifImport/MaxNifImport.rc b/NifImport/MaxNifImport.rc index 51d812147d960129d4087b7d58cbb7d8ba323aa3..d343520627b5dc708226e02ad93f12e29dccf4ce 100644 --- a/NifImport/MaxNifImport.rc +++ b/NifImport/MaxNifImport.rc @@ -88,8 +88,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,1,3,4 - PRODUCTVERSION 0,1,3,0 + FILEVERSION 0,1,4,6 + PRODUCTVERSION 0,1,4,0 FILEFLAGSMASK 0x37L #ifdef _DEBUG FILEFLAGS 0x21L @@ -105,12 +105,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "3ds Max Nif Importer" - VALUE "FileVersion", "0, 1, 3, 4" + VALUE "FileVersion", "0, 1, 4, 6" VALUE "InternalName", "MaxNifImport.dli" VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved." VALUE "OriginalFilename", "MaxNifImport.dli" VALUE "ProductName", "3ds Max Nif Importer" - VALUE "ProductVersion", "0, 1, 3, 0" + VALUE "ProductVersion", "0, 1, 4, 0" VALUE "SpecialBuild", "Alpha" END END diff --git a/NifImport/MaxNifImport.vcproj b/NifImport/MaxNifImport.vcproj index 3c93bcd53bca8871a9559cf64701542e05ee285f..cbd0c7babdb3fa7975bf00ee9e75d3f78e44e95a 100644 --- a/NifImport/MaxNifImport.vcproj +++ b/NifImport/MaxNifImport.vcproj @@ -50,7 +50,7 @@ AdditionalOptions="/LD " InlineFunctionExpansion="1" AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" @@ -154,7 +154,7 @@ AdditionalOptions="/LD " Optimization="0" AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED" GeneratePreprocessedFile="0" ExceptionHandling="2" RuntimeLibrary="1" diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index 16b1047cb59d0284bf4e5ce2e98343151d09436e..c59900b7c6776221bb7ad057c4cd04b08a11ee4d 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -23,6 +23,7 @@ LPCTSTR AnimImportSection = TEXT("AnimationImport"); class IBipMaster; IBipMaster * (_cdecl * Max8CreateNewBiped)(float,float,class Point3 const &,int,int,int,int,int,int,int,int,int,int,int,int,float,int,int,int,int,int,int,int,int) = 0; +IBipMaster * (_cdecl * Max7CreateNewBiped)(float,float,class Point3 const &,int,int,int,int,int,int,int,int,int,int,int,int,float,int,int,int,int) = 0; NifImporter::NifImporter(const TCHAR *Name,ImpInterface *I,Interface *GI, BOOL SuppressPrompts) : BaseImporter() @@ -66,7 +67,7 @@ void NifImporter::Initialize() GoToSkeletonBindPosition(nodes); // Only support biped if CreateNewBiped can be found. - useBiped &= (Max8CreateNewBiped != NULL); + useBiped &= (Max8CreateNewBiped != NULL || Max7CreateNewBiped != NULL); hasSkeleton = HasSkeleton(); isBiped = IsBiped(); diff --git a/NifImport/niutils.cpp b/NifImport/niutils.cpp index b49bc0c3b0d7a3d147d32afc6dead286c88fd282..449e4450789e4f40c54fcb68250be4ce89169487 100644 --- a/NifImport/niutils.cpp +++ b/NifImport/niutils.cpp @@ -20,7 +20,7 @@ HISTORY: #include <modstack.h> #include <iskin.h> #ifdef USE_BIPED -# include <cs/Biped8Api.h> +# include <cs/BipedApi.h> # include <cs/OurExp.h> #endif using namespace std; @@ -334,13 +334,13 @@ void PosRotScaleNode(INode *n, Matrix3& m3, PosRotScale prs, TimeValue t) void PosRotScaleNode(INode *n, Point3 p, Quat& q, float s, PosRotScale prs, TimeValue t) { if (Control *c = n->GetTMController()) { - ScaleValue sv(Point3(s,s,s)); #ifdef USE_BIPED // Bipeds are special. And will crash if you dont treat them with care if ( (c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||(c->ClassID() == FOOTPRINT_CLASS_ID)) { + ScaleValue sv(Point3(s,s,s)); // Get the Biped Export Interface from the controller //IBipedExport *BipIface = (IBipedExport *) c->GetInterface(I_BIPINTERFACE); IOurBipExport *BipIface = (IOurBipExport *) c->GetInterface(I_OURINTERFACE); @@ -354,19 +354,31 @@ void PosRotScaleNode(INode *n, Point3 p, Quat& q, float s, PosRotScale prs, Time else #endif { - if (prs & prsScale) - if (Control *sclCtrl = c->GetScaleController()) - sclCtrl->SetValue(t, &sv, 1, CTRL_ABSOLUTE); - if (prs & prsRot) - if (Control *rotCtrl = c->GetRotationController()) - rotCtrl->SetValue(t, &q, 1, CTRL_ABSOLUTE); - if (prs & prsPos) - if (Control *posCtrl = c->GetPositionController()) - posCtrl->SetValue(t, &p, 1, CTRL_ABSOLUTE); + PosRotScaleNode(c, p, q, s, prs, t); } } } +void PosRotScaleNode(Control *c, Point3 p, Quat& q, float s, PosRotScale prs, TimeValue t) +{ + if (c) { + if (prs & prsRot && q.w == FloatNegINF) prs = PosRotScale(prs & ~prsRot); + if (prs & prsPos && p.x == FloatNegINF) prs = PosRotScale(prs & ~prsPos); + if (prs & prsScale && s == FloatNegINF) prs = PosRotScale(prs & ~prsScale); + + ScaleValue sv(Point3(s,s,s)); + if (prs & prsScale) + if (Control *sclCtrl = c->GetScaleController()) + sclCtrl->SetValue(t, &sv, 1, CTRL_ABSOLUTE); + if (prs & prsRot) + if (Control *rotCtrl = c->GetRotationController()) + rotCtrl->SetValue(t, &q, 1, CTRL_ABSOLUTE); + if (prs & prsPos) + if (Control *posCtrl = c->GetPositionController()) + posCtrl->SetValue(t, &p, 1, CTRL_ABSOLUTE); + } +} + // Search NiNode collection for a specific name NiNodeRef FindNodeByName( const vector<NiNodeRef>& blocks, const string& name ) { diff --git a/NifImport/niutils.h b/NifImport/niutils.h index 56685f368553feaa74a0d9145c29f0fb887c37c3..fd8f5cbdc6939bbcfc1df377527a2b39ae9476a7 100644 --- a/NifImport/niutils.h +++ b/NifImport/niutils.h @@ -41,6 +41,11 @@ INFO: See Implementation for minimalist comments #define _countof(x) (sizeof(x)/sizeof((x)[0])) #endif +const unsigned int IntegerInf = 0x7f7fffff; +const unsigned int IntegerNegInf = 0xff7fffff; +const float FloatINF = *(float*)&IntegerInf; +const float FloatNegINF = *(float*)&IntegerNegInf; + // Trim whitespace before and after a string inline TCHAR *Trim(TCHAR*&p) { while(_istspace(*p)) *p++ = 0; @@ -220,6 +225,7 @@ enum PosRotScale prsDefault = prsPos | prsRot | prsScale, }; extern void PosRotScaleNode(INode *n, Point3 p, Quat& q, float s, PosRotScale prs = prsDefault, TimeValue t = 0); +extern void PosRotScaleNode(Control *c, Point3 p, Quat& q, float s, PosRotScale prs = prsDefault, TimeValue t = 0); extern void PosRotScaleNode(INode *n, Matrix3& m3, PosRotScale prs = prsDefault, TimeValue t = 0); extern Niflib::NiNodeRef FindNodeByName( const vector<Niflib::NiNodeRef>& blocks, const string& name );