From d218c7e1885530c2a5800a3bc0381a5f7f052159 Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Mon, 28 May 2007 02:05:28 +0000 Subject: [PATCH] Update to latest revision of niflib. --- MaxNifTools.ini | 3 + NifCommon/AnimKey.cpp | 2 + NifCommon/AppSettings.cpp | 6 +- NifCommon/IniSection.h | 81 +- NifCommon/MAX_MemDirect.h | 4 +- NifCommon/niutils.cpp | 43 +- NifCommon/niutils.h | 8 +- NifExport/Animation.cpp | 23 +- NifExport/Coll.cpp | 20 +- NifExport/Config.cpp | 15 +- NifExport/Exporter.cpp | 6 +- NifExport/KfExport.cpp | 15 +- NifExport/Mesh.cpp | 8 +- NifExport/MtlTex.cpp | 53 +- NifExport/NifExport.cpp | 180 +- NifExport/NvTriStrip/NvTriStrip.cpp | 504 ++++++ NifExport/NvTriStrip/NvTriStrip.h | 147 ++ NifExport/NvTriStrip/NvTriStripObjects.cpp | 1771 +++++++++++++++++++ NifExport/NvTriStrip/NvTriStripObjects.h | 248 +++ NifExport/NvTriStrip/VertexCache.cpp | 87 + NifExport/NvTriStrip/VertexCache.h | 31 + NifExport/Strips.cpp | 4 +- NifExport/Util.cpp | 2 +- NifFurniture/NifFurniture.cpp | 7 +- NifImport/ImportAnimation.cpp | 8 +- NifImport/ImportCollision.cpp | 10 +- NifImport/ImportLights.cpp | 10 +- NifImport/ImportMeshAndSkin.cpp | 17 +- NifImport/ImportMtlAndTex.cpp | 36 +- NifImport/ImportSkeleton.cpp | 11 +- NifImport/MaxNifImport.cpp | 19 +- NifImport/NIFImport.cpp | 9 +- NifPlugins/DllEntry.cpp | 17 +- NifPlugins_VC80.sln | 110 +- NifPlugins_VC80.vcproj | 1708 +++++++++++++++++- NifProps/bhkBoxObj.cpp | 8 +- NifProps/bhkCapsuleObj.cpp | 8 +- NifProps/bhkRigidBodyModifer.cpp | 7 +- NifProps/bhkSphereObj.cpp | 8 +- NifProps/dds/ConvertColor.h | 349 ++++ NifProps/dds/dds.cpp | 774 ++++++++ NifProps/dds/dds.dep | 128 ++ NifProps/dds/dds.h | 159 ++ NifProps/dds/dds.rc | 156 ++ NifProps/dds/ddsTypes.h | 375 ++++ NifProps/dds/ddsres.h | 46 + NifProps/dds/dxtlib.h | 124 ++ NifProps/dds/nvDXTlib.lib | Bin 0 -> 90212 bytes NifProps/dds/nvErrorCodes.h | 112 ++ NifProps/dds/nvdxt_options.h | 779 +++++++++ NifProps/dds/tPixel.h | 1840 ++++++++++++++++++++ NifProps/dds/tVector.h | 778 +++++++++ NifProps/dds/veroverrides.h | 15 + 53 files changed, 10471 insertions(+), 418 deletions(-) create mode 100644 NifExport/NvTriStrip/NvTriStrip.cpp create mode 100644 NifExport/NvTriStrip/NvTriStrip.h create mode 100644 NifExport/NvTriStrip/NvTriStripObjects.cpp create mode 100644 NifExport/NvTriStrip/NvTriStripObjects.h create mode 100644 NifExport/NvTriStrip/VertexCache.cpp create mode 100644 NifExport/NvTriStrip/VertexCache.h create mode 100644 NifProps/dds/ConvertColor.h create mode 100644 NifProps/dds/dds.cpp create mode 100644 NifProps/dds/dds.dep create mode 100644 NifProps/dds/dds.h create mode 100644 NifProps/dds/dds.rc create mode 100644 NifProps/dds/ddsTypes.h create mode 100644 NifProps/dds/ddsres.h create mode 100644 NifProps/dds/dxtlib.h create mode 100644 NifProps/dds/nvDXTlib.lib create mode 100644 NifProps/dds/nvErrorCodes.h create mode 100644 NifProps/dds/nvdxt_options.h create mode 100644 NifProps/dds/tPixel.h create mode 100644 NifProps/dds/tVector.h create mode 100644 NifProps/dds/veroverrides.h diff --git a/MaxNifTools.ini b/MaxNifTools.ini index 7c11d9c..0b89594 100644 --- a/MaxNifTools.ini +++ b/MaxNifTools.ini @@ -15,6 +15,9 @@ Reparse=0 Website=http://www.niftools.org ; Wiki - Documentation website Wiki=http://www.niftools.org/wiki/index.php/3ds_Max +; Force Plugcfg directory (Default=1) dont use the "recommended directory by max" +ForcePlugcfg=1 + [MaxNifExport] ; Enable/Disable Exporter Class in max. Default: 1 diff --git a/NifCommon/AnimKey.cpp b/NifCommon/AnimKey.cpp index 30fdbb0..04342e9 100644 --- a/NifCommon/AnimKey.cpp +++ b/NifCommon/AnimKey.cpp @@ -50,8 +50,10 @@ T& InitBezKey(T& rKey, U& key, float time) { rKey.time = TimeToFrame(time + key.time); rKey.flags = 0; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ SetInTanType(rKey.flags,BEZKEY_FLAT); SetOutTanType(rKey.flags,BEZKEY_FLAT); +#endif return rKey; } diff --git a/NifCommon/AppSettings.cpp b/NifCommon/AppSettings.cpp index d469702..2e63281 100644 --- a/NifCommon/AppSettings.cpp +++ b/NifCommon/AppSettings.cpp @@ -9,8 +9,7 @@ AppSettingsMap TheAppSettings; void AppSettings::Initialize(Interface *gi) { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); if (-1 != _taccess(iniName, 0)) { bool reparse = GetIniValue<bool>("System", "Reparse", false, iniName); if (reparse || TheAppSettings.empty()){ @@ -72,8 +71,7 @@ void AppSettings::ReadSettings(string iniFile) void AppSettings::WriteSettings(Interface *gi) { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); if (-1 != _taccess(iniName, 0)) { SetIniValue(Name.c_str(), "NiVersion", NiVersion.c_str(), iniName); diff --git a/NifCommon/IniSection.h b/NifCommon/IniSection.h index e42f6a8..624bd02 100644 --- a/NifCommon/IniSection.h +++ b/NifCommon/IniSection.h @@ -2,22 +2,28 @@ #include <string> #include <list> -enum INIDEFTYPE + +enum VARIABLETYPE { - IDT_STRING, - IDT_INT, - IDT_FLOAT, - IDT_BOOL, - IDT_FILENAME, - IDT_UNKNOWN, + vtUnknown, + vtInteger, + vtFloat, + vtDouble, + vtBoolean, + vtText, + vtPointer, + vtHandle, + vtVector = 0x1000, + vtFixedVector = vtVector | 0x2000, + vtMatrix = 0x4000, }; -struct INIDEF +struct VARIABLE { - INIDEF() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) { + VARIABLE() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) { } - ~INIDEF() { + ~VARIABLE() { if (ValueSize && DefaultValue) { delete DefaultValue; DefaultValue = NULL; @@ -26,36 +32,43 @@ struct INIDEF } template<typename U> - INIDEF(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, INIDEFTYPE type) + VARIABLE(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, VARIABLETYPE type) : ShortName(sName), IniName(iName), MemberAddr(NULL), Description(NULL), MemberType(type) { SetDefault(default); } template<> - INIDEF(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, INIDEFTYPE type) + VARIABLE(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, VARIABLETYPE type) : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { - MemberType = type==IDT_UNKNOWN?IDT_STRING:type; + MemberType = type==vtUnknown?vtText:type; SetDefault(default); } template<> - INIDEF(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, INIDEFTYPE type) + VARIABLE(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, VARIABLETYPE type) : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { - MemberType = type==IDT_UNKNOWN?IDT_INT:type; + MemberType = type==vtUnknown?vtInteger:type; SetDefault(default); } template<> - INIDEF(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, INIDEFTYPE type) + VARIABLE(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, VARIABLETYPE type) : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { - MemberType = type==IDT_UNKNOWN?IDT_FLOAT:type; + MemberType = type==vtUnknown?vtFloat:type; SetDefault(default); } template<> - INIDEF(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, INIDEFTYPE type) + VARIABLE(LPCTSTR sName, LPCTSTR iName, const double& member, double default, LPCTSTR desc, VARIABLETYPE type) + : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { + MemberType = type==vtUnknown?vtDouble:type; + SetDefault(default); + } + + template<> + VARIABLE(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, VARIABLETYPE type) : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { - MemberType = type==IDT_UNKNOWN?IDT_BOOL:type; + MemberType = type==vtUnknown?vtBoolean:type; SetDefault(default); } @@ -73,42 +86,42 @@ struct INIDEF LPCTSTR ShortName; LPCTSTR IniName; DWORD MemberAddr; - INIDEFTYPE MemberType; + VARIABLETYPE MemberType; LPCTSTR Description; LPVOID DefaultValue; DWORD ValueSize; }; #define BEGIN_INI_MAP(name) \ - virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ - virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \ - static INIDEF* InternalGetInfDefmap() { \ + virtual void *GetMember(const VARIABLE* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ + virtual const VARIABLE* GetInfDefmap() const { return InternalGetInfDefmap(); } \ + static VARIABLE* InternalGetInfDefmap() { \ const name* pThis = 0; \ - static INIDEF map[] = { \ + static VARIABLE map[] = { \ #define BEGIN_INI_MAP_WITH_BASE(name, base) \ - virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ - virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \ - static INIDEF* InternalGetInfDefmap() { \ + virtual void *GetMember(const VARIABLE* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ + virtual const VARIABLE* GetInfDefmap() const { return InternalGetInfDefmap(); } \ + static VARIABLE* InternalGetInfDefmap() { \ const name* pThis = 0; \ - static INIDEF map[] = { \ + static VARIABLE map[] = { \ #define END_INI_MAP() \ - INIDEF() };\ + VARIABLE() };\ return map;\ } #define ADDITEM(sName, iName, member, desc) \ - INIDEF(sName, iName, pThis->member, desc, IDT_UNKNOWN), \ + VARIABLE(sName, iName, pThis->member, desc, vtUnknown), \ #define ADDITEMEX(sName, iName, member, type, desc) \ - INIDEF(sName, iName, pThis->member, desc, type), \ + VARIABLE(sName, iName, pThis->member, desc, type), \ struct IniFileSection { virtual LPCTSTR GetName() const = 0; - virtual const INIDEF* GetInfDefmap() const = 0; - virtual void *GetMember(const INIDEF* memptr) const = 0; + virtual const VARIABLE* GetInfDefmap() const = 0; + virtual void *GetMember(const VARIABLE* memptr) const = 0; }; typedef std::list<IniFileSection*> IniFileSectionList; @@ -116,7 +129,7 @@ typedef std::list<IniFileSection*> IniFileSectionList; inline int GetIniDefSectionSize(IniFileSection *section) { int len = 0; - for (const INIDEF *inidef = section->GetInfDefmap() + for (const VARIABLE *inidef = section->GetInfDefmap() ; inidef != NULL && inidef->ShortName ; ++inidef) ++len; diff --git a/NifCommon/MAX_MemDirect.h b/NifCommon/MAX_MemDirect.h index 47340a5..57af5ac 100644 --- a/NifCommon/MAX_MemDirect.h +++ b/NifCommon/MAX_MemDirect.h @@ -16,6 +16,8 @@ #ifndef __MAX_MEM_H #define __MAX_MEM_H +#if VERSION_3DSMAX < ((9000<<16)+(15<<8)+0) // Version 9 + #include <crtdbg.h> #include <malloc.h> #include <new.h> @@ -191,5 +193,5 @@ CoreExport int (__cdecl *MAX_CrtDumpMemoryLeaks)(void); #endif //IS_HYBRID #endif //_DEBUG - +#endif #endif //__MAX_MEM_H diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp index d50499b..9de0136 100644 --- a/NifCommon/niutils.cpp +++ b/NifCommon/niutils.cpp @@ -947,7 +947,6 @@ void CalcCenteredSphere(const vector<Vector3>& vertices, Vector3& center, float& static void TransformVector3(Matrix44& tm, vector<Vector3>& pts) { - Matrix44::IDENTITY; for (vector<Vector3>::iterator itr = pts.begin(); itr != pts.end(); ++itr) { Matrix44 m4(*itr, Matrix33::IDENTITY, 1.0f); @@ -1095,3 +1094,45 @@ Modifier *GetbhkCollisionModifier(INode *node) } return NULL; } + +void GetIniFileName(char *iniName) +{ +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + Interface *gi = GetCOREInterface(); +#else + Interface *gi = NULL; +#endif + if (gi) { + LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); + PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + + int forcePlugcfg = GetIniValue("System", "ForcePlugcfg", 0, iniName); + + if (forcePlugcfg == 1 || _access(iniName, 06) != 0) { + TCHAR iniPath[MAX_PATH]; + GetModuleFileName(NULL, iniPath, MAX_PATH); + if (LPTSTR fname = PathFindFileName(iniPath)) + *fname = 0; + PathAddBackslash(iniPath); + PathAppend(iniPath, "plugcfg"); + PathAppend(iniPath, "MaxNifTools.ini"); + + // Use plugcfg directory ini + if (_access(iniPath, 06) == 0) { + strcpy(iniName, iniPath); + } + } + } else { + GetModuleFileName(NULL, iniName, MAX_PATH); + if (LPTSTR fname = PathFindFileName(iniName)) + *fname = 0; + PathAddBackslash(iniName); + PathAppend(iniName, "plugcfg"); + PathAppend(iniName, "MaxNifTools.ini"); + } + + if (_access(iniName, 06) != 0) { + MessageBox(NULL, "MaxNifTools could not find a valid INI. The plugin may not work correctly.\nPlease check for proper installation.", + "MaxNifTools", MB_OK|MB_ICONWARNING); + } +} \ No newline at end of file diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h index 81c2153..59b541a 100644 --- a/NifCommon/niutils.h +++ b/NifCommon/niutils.h @@ -387,13 +387,9 @@ extern TriObject* GetTriObject(Object *o); extern TSTR GetFileVersion(const char *fileName); -inline Niflib::NiObjectRef CreateBlock(const char *name) { - return Niflib::CreateObject(name); -} - template<typename T> inline Niflib::Ref<T> CreateNiObject() { - return Niflib::StaticCast<T>(Niflib::CreateObject(T::TypeConst().GetTypeName())); + return Niflib::StaticCast<T>(T::Create()); } void CollapseGeomTransform(Niflib::NiTriBasedGeomRef shape); @@ -402,4 +398,6 @@ void FixNormals(std::vector<Niflib::Triangle>& tris, std::vector<Niflib::Vector3 Modifier *GetbhkCollisionModifier(INode *node); +void GetIniFileName(char *iniName); + #endif // _NIUTILS_H_ \ No newline at end of file diff --git a/NifExport/Animation.cpp b/NifExport/Animation.cpp index 07d943d..8154228 100644 --- a/NifExport/Animation.cpp +++ b/NifExport/Animation.cpp @@ -11,7 +11,7 @@ HISTORY: *> Copyright (c) 2006, All Rights Reserved. **********************************************************************/ #include "pch.h" -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7+ #include <IFrameTagManager.h> #endif #include <notetrck.h> @@ -74,7 +74,7 @@ bool GetTextKeys(INode *node, vector<StringKey>& textKeys, Interval range) { // Populate Text keys and Sequence information from note tracks if (Exporter::mUseTimeTags) { -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7+ if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) { int n = tagMgr->GetTagCount(); for (int i = 0; i<n; i++) { @@ -138,7 +138,7 @@ void Exporter::InitializeTimeController(NiTimeControllerRef ctrl, NiNodeRef pare ctrl->SetStopTime(FloatNegINF); ctrl->SetPhase(0.0f); ctrl->SetFlags(0x0C); - ctrl->SetTarget( parent ); + //ctrl->SetTarget( parent ); parent->AddController(DynamicCast<NiTimeController>(ctrl)); } @@ -328,7 +328,7 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq) // Populate Text keys and Sequence information from note tracks if (Exporter::mUseTimeTags) { -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) { int n = tagMgr->GetTagCount(); for (int i = 0; i<n; i++) { @@ -409,7 +409,7 @@ bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node) // Populate Text keys and Sequence information from note tracks if (Exporter::mUseTimeTags) { -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) { curSeq = new NiControllerSequence(); @@ -721,13 +721,14 @@ NiTimeControllerRef AnimationExport::exportController(INode *node, Interval rang Exporter::InitializeTimeController(control, ninode); NiTransformInterpolatorRef interp = new NiTransformInterpolator(); - data = new NiTransformData(); + NiTransformDataRef tdata = new NiTransformData(); + data = StaticCast<NiKeyframeData>(tdata); control->SetInterpolator(StaticCast<NiInterpolator>(interp)); interp->SetTranslation(trans); interp->SetScale(scale); interp->SetRotation(rot); - interp->SetData(data); + interp->SetData(tdata); timeControl = StaticCast<NiTimeController>(control); } @@ -740,7 +741,7 @@ NiTimeControllerRef AnimationExport::exportController(INode *node, Interval rang // interp->SetTranslation( TOVECTOR3(tm.GetTrans()) ); // interp->SetScale( Average(GetScale(tm)) ); // interp->SetRotation( TOQUAT( Quat(tm) ) ); - // seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control)); + // seq->AddInterpolator(StaticCast<NiSingleInterpController>(control)); //} //else { @@ -954,13 +955,13 @@ bool AnimationExport::exportController(INode *node, bool hasAccum) NiTimeControllerRef control = exportController( node, range, keepTM ); if (control != NULL) { - NiSingleInterpolatorControllerRef interpControl = DynamicCast<NiSingleInterpolatorController>(control); + NiSingleInterpControllerRef interpControl = DynamicCast<NiSingleInterpController>(control); if (interpControl) { // Get Priority from node float priority; npGetProp(node, NP_ANM_PRI, priority, Exporter::mDefaultPriority); - seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), priority); + seq->AddInterpolator(StaticCast<NiSingleInterpController>(control), priority); // Handle NonAccum if (Exporter::mAllowAccum && hasAccum) @@ -985,7 +986,7 @@ bool AnimationExport::exportController(INode *node, bool hasAccum) accinterp->SetData( interp->GetData() ); interp->SetData( NiTransformDataRef() ); } - seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(acccontrol), Exporter::mDefaultPriority); + seq->AddInterpolator(StaticCast<NiSingleInterpController>(acccontrol), Exporter::mDefaultPriority); accnode->RemoveController(acccontrol); } diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index 8281c68..0ccf098 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -281,7 +281,7 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) bhkCollisionObjectRef co = new bhkCollisionObject(); co->SetBody(DynamicCast<NiObject>(body)); - co->SetParent(newParent); + //co->SetTarget(newParent); // link newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co)); @@ -332,7 +332,7 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node) npGetProp(node, NP_HVK_CENTER, center); // setup body - bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBodyT")); + bhkRigidBodyRef body = CreateNiObject<bhkRigidBodyT>(); body->SetLayer(OblivionLayer(lyr)); body->SetLayerCopy(OblivionLayer(lyr)); @@ -424,7 +424,7 @@ bhkSphereRepShapeRef Exporter::makeCapsuleShape(Object *obj, const Matrix3& tm) params->GetValue(obj->GetParamBlockIndex(CAPSULE_RADIUS), 0, radius, FOREVER); params->GetValue(obj->GetParamBlockIndex(CAPSULE_HEIGHT), 0, height, FOREVER); - bhkCapsuleShapeRef capsule = DynamicCast<bhkCapsuleShape>(CreateBlock("bhkCapsuleShape")); + bhkCapsuleShapeRef capsule = CreateNiObject<bhkCapsuleShape>(); return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(capsule)); } @@ -476,14 +476,16 @@ bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node, const Matrix3& tm data->SetNormals(vnorms); // setup shape - bhkNiTriStripsShapeRef shape = DynamicCast<bhkNiTriStripsShape>(CreateBlock("bhkNiTriStripsShape")); - shape->SetNumStripsData(1); - shape->SetStripsData(0, data); + bhkNiTriStripsShapeRef shape = StaticCast<bhkNiTriStripsShape>(bhkNiTriStripsShape::Create()); - if (tri != os.obj) - tri->DeleteMe(); + //bhkNiTriStripsShapeRef shape = DynamicCast<bhkNiTriStripsShape>(CreateBlock("bhkNiTriStripsShape")); + //shape->SetNumStripsData(1); + //shape->SetStripsData(0, data); + + //if (tri != os.obj) + // tri->DeleteMe(); - return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(shape)); + return bhkSphereRepShapeRef(); } diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp index 39ab0ef..5f40d78 100755 --- a/NifExport/Config.cpp +++ b/NifExport/Config.cpp @@ -46,8 +46,7 @@ void Exporter::writeConfig(Interface *i) else { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); SetIniValue(NifExportSection, "GenerateStrips", mTriStrips, iniName); SetIniValue(NifExportSection, "IncludeHidden", mExportHidden, iniName); @@ -118,8 +117,7 @@ void Exporter::readConfig(Interface *i) else { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); //mVersion = GetIniValue<int>(NifExportSection, "Version", 013, iniName); mTriStrips = GetIniValue<bool>(NifExportSection, "GenerateStrips", true, iniName); @@ -165,8 +163,7 @@ void Exporter::readConfig(Interface *i) void Exporter::readKfConfig(Interface *i) { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); mExportHidden = GetIniValue(KfExportSection, "IncludeHidden", false, iniName); mExportLights = GetIniValue(KfExportSection, "Lights", false, iniName); @@ -192,8 +189,7 @@ void Exporter::writeKfConfig(Interface *i) AppSettings * Exporter::exportAppSettings() { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = GetCOREInterface()->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); // Update the current app version AppSettings * appSettings = FindAppSetting(Exporter::mGameName); @@ -218,8 +214,7 @@ AppSettings *Exporter::importAppSettings(string fname) { AppSettings *appSettings = NULL; TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = GetCOREInterface()->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); // Locate which application to use. If Auto, find first app where this file appears in the root path list string curapp = GetIniValue<string>(NifExportSection, "CurrentApp", "AUTO", iniName); diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp index e7fe0de..6e848f1 100755 --- a/NifExport/Exporter.cpp +++ b/NifExport/Exporter.cpp @@ -90,21 +90,21 @@ Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node) BSXFlagsRef bsx = CreateNiObject<BSXFlags>(); bsx->SetName("BSX"); - bsx->SetFlags( 0x00000007 ); + bsx->SetData( 0x00000007 ); root->AddExtraData(DynamicCast<NiExtraData>(bsx)); } else if (mExportType != NIF_WO_ANIM) { BSXFlagsRef bsx = CreateNiObject<BSXFlags>(); bsx->SetName("BSX"); - bsx->SetFlags( 0x00000003 ); + bsx->SetData( 0x00000003 ); root->AddExtraData(DynamicCast<NiExtraData>(bsx)); } else if (mExportCollision) { BSXFlagsRef bsx = CreateNiObject<BSXFlags>(); bsx->SetName("BSX"); - bsx->SetFlags( 0x00000002 ); + bsx->SetData( 0x00000002 ); root->AddExtraData(DynamicCast<NiExtraData>(bsx)); } } diff --git a/NifExport/KfExport.cpp b/NifExport/KfExport.cpp index 0d85c97..0bfcd70 100644 --- a/NifExport/KfExport.cpp +++ b/NifExport/KfExport.cpp @@ -188,17 +188,7 @@ KfExport::KfExport() { Interface *gi = GetCOREInterface(); TCHAR iniName[MAX_PATH]; - if (gi) { - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); - } else { - GetModuleFileName(NULL, iniName, _countof(iniName)); - if (LPTSTR fname = PathFindFileName(iniName)) - fname = NULL; - PathAddBackslash(iniName); - PathAppend(iniName, "plugcfg"); - PathAppend(iniName, "MaxNifTools.ini"); - } + GetIniFileName(iniName); iniFileName = iniName; shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName); fileVersion = GetFileVersion(NULL); @@ -275,8 +265,7 @@ int KfExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL s AppSettings::Initialize(i); TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); bool iniNameIsValid = (-1 != _taccess(iniName, 0)); // read config from registry diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp index 9fcc315..ddeac52 100755 --- a/NifExport/Mesh.cpp +++ b/NifExport/Mesh.cpp @@ -38,7 +38,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue mtx.NoTrans(); mesh = copymesh = new Mesh(*mesh); int n = mesh->getNumVerts(); - for ( uint i = 0; i < n; ++i ) { + for ( unsigned int i = 0; i < n; ++i ) { Point3& vert = mesh->getVert(i); vert = mtx * vert; } @@ -47,7 +47,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals (); if (NULL != specNorms) { specNorms->CheckNormals(); - for ( uint i = 0; i < specNorms->GetNumNormals(); ++i ) { + for ( unsigned int i = 0; i < specNorms->GetNumNormals(); ++i ) { Point3& norm = specNorms->Normal(i); norm = (mtx * norm).Normalize(); } @@ -141,7 +141,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue } if (node->IsHidden()) - shape->SetHidden(true); + shape->SetVisibility(false); shape->SetName(name); shape->SetLocalTransform(tm); @@ -423,7 +423,7 @@ bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, Ti Exporter::Result SkinInstance::execute() { shape->BindSkin(boneList); - uint bone = 0; + unsigned int bone = 0; for (BoneWeightList::iterator bitr = boneWeights.begin(); bitr != boneWeights.end(); ++bitr, ++bone) { shape->SetBoneWeights(bone, (*bitr)); } diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp index 8624b17..587ab65 100755 --- a/NifExport/MtlTex.cpp +++ b/NifExport/MtlTex.cpp @@ -79,9 +79,7 @@ bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td) if (mAppSettings) { string newPath = mAppSettings->GetRelativeTexPath(string(mapPath), mTexPrefix); - - NiObjectRef unk_link(NULL); - td.source->SetExternalTexture(newPath, unk_link); + td.source->SetExternalTexture(newPath); } else { @@ -93,8 +91,7 @@ bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td) else newPath = f; - NiObjectRef unk_link(NULL); - td.source->SetExternalTexture(newPath.data(), unk_link); + td.source->SetExternalTexture(newPath.data()); } return true; } @@ -107,7 +104,7 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl) return; string name; - NiMaterialPropertyRef mtlProp(DynamicCast<NiMaterialProperty>(CreateBlock("NiMaterialProperty"))); + NiMaterialPropertyRef mtlProp(CreateNiObject<NiMaterialProperty>()); if (mtl) { Color c; @@ -143,9 +140,9 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl) if (smtl->GetTwoSided()){ NiStencilPropertyRef stencil = new NiStencilProperty(); stencil->SetStencilFunction(TEST_GREATER); - stencil->SetStencilEnabled(false); + stencil->SetStencilState(false); stencil->SetPassAction(ACTION_INCREMENT); - stencil->SetDrawMode(DRAW_BOTH); + stencil->SetFaceDrawMode(DRAW_BOTH); parent->AddProperty(stencil); } if (smtl->IsFaceted()) { @@ -344,9 +341,9 @@ bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl) if (smtl->GetTwoSided()){ NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>(); stencil->SetStencilFunction(TEST_GREATER); - stencil->SetStencilEnabled(false); + stencil->SetStencilState(false); stencil->SetPassAction(ACTION_INCREMENT); - stencil->SetDrawMode(DRAW_BOTH); + stencil->SetFaceDrawMode(DRAW_BOTH); parent->AddProperty(stencil); } if (smtl->IsFaceted()) { @@ -378,31 +375,31 @@ bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl) if (alphaMode != 0 || AlphaTestEnable) { // always add alpha ??? NiAlphaPropertyRef alphaProp = CreateNiObject<NiAlphaProperty>(); - alphaProp->SetAlphaBlend(true); + alphaProp->SetBlendState(true); if (alphaMode == 0) { // automatic - alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend)); - alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend)); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BlendFunc(srcBlend)); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BlendFunc(destBlend)); } else if (alphaMode == 1) { // None - alphaProp->SetAlphaBlend(false); - alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA); - alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA); + alphaProp->SetBlendState(false); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_SRC_ALPHA); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA); } else if (alphaMode == 2) { // Standard - alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA); - alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_SRC_ALPHA); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA); } else if (alphaMode == 3) { // Additive - alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ONE); - alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_ONE); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE); } else if (alphaMode == 4) { // Multiplicative - alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ZERO); - alphaProp->SetDestBlendMode(NiAlphaProperty::BM_SRC_COLOR); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_ZERO); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_SRC_COLOR); } else { // Advanced - alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend)); - alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend)); + alphaProp->SetSourceBlendFunc(NiAlphaProperty::BlendFunc(srcBlend)); + alphaProp->SetDestBlendFunc(NiAlphaProperty::BlendFunc(destBlend)); } - alphaProp->SetTestMode(NiAlphaProperty::TestMode(TestMode)); - alphaProp->SetAlphaSort(!NoSorter); - alphaProp->SetAlphaTestThreshold(TestRef); - alphaProp->SetAlphaTest(AlphaTestEnable); + alphaProp->SetTestFunc(NiAlphaProperty::TestFunc(TestMode)); + alphaProp->SetTriangleSortMode(!NoSorter); + alphaProp->SetTestThreshold(TestRef); + alphaProp->SetBlendState(AlphaTestEnable); parent->AddProperty(alphaProp); } diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp index 22a8ad5..dfbaf9b 100755 --- a/NifExport/NifExport.cpp +++ b/NifExport/NifExport.cpp @@ -39,6 +39,13 @@ public: int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0); int DoExportInternal(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options); + SDK_RESERVED_METHOD(1); // russom 02/26/01 + SDK_RESERVED_METHOD(2); // russom 02/26/01 + SDK_RESERVED_METHOD(3); // russom 02/26/01 + SDK_RESERVED_METHOD(4); // russom 02/26/01 + SDK_RESERVED_METHOD(5); // russom 02/26/01 + SDK_RESERVED_METHOD(6); // russom 02/26/01 + NifExport(); ~NifExport(); }; @@ -167,12 +174,12 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH); if (tmp[0] != 0) { - int nifVersion = ParseVersionString(tmp); - if (!IsSupportedVersion(nifVersion)) - { - MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP); - return FALSE; - } + int nifVersion = ParseVersionString(tmp); + if (!IsSupportedVersion(nifVersion)) + { + MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP); + return FALSE; + } } Exporter::mTriStrips = IsDlgButtonChecked(hWnd, IDC_CHK_STRIPS); @@ -275,17 +282,7 @@ NifExport::NifExport() { Interface *gi = GetCOREInterface(); TCHAR iniName[MAX_PATH]; - if (gi) { - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); - } else { - GetModuleFileName(NULL, iniName, _countof(iniName)); - if (LPTSTR fname = PathFindFileName(iniName)) - fname = NULL; - PathAddBackslash(iniName); - PathAppend(iniName, "plugcfg"); - PathAppend(iniName, "MaxNifTools.ini"); - } + GetIniFileName(iniName); iniFileName = iniName; shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName); fileVersion = GetFileVersion(NULL); @@ -369,44 +366,43 @@ int NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL i->PushPrompt(title); if (!suppressPrompts) i->ProgressStart(title, TRUE, dummyProgress, NULL); - try - { - DoExportInternal(name, ei, i, suppressPrompts, options); - } - catch (Exporter::CancelExporterException&) - { - // Special user cancellation exception - } - catch (exception &e) - { - if (!suppressPrompts) - MessageBox(NULL, e.what(), "Export Error", MB_OK); + try + { + DoExportInternal(name, ei, i, suppressPrompts, options); + } + catch (Exporter::CancelExporterException&) + { + // Special user cancellation exception + } + catch (exception &e) + { + if (!suppressPrompts) + MessageBox(NULL, e.what(), "Export Error", MB_OK); } catch (...) { if (!suppressPrompts) - MessageBox(NULL, "Unknown error.", "Export Error", MB_OK); + MessageBox(NULL, "Unknown error.", "Export Error", MB_OK); } i->PopPrompt(); if (!suppressPrompts) i->ProgressEnd(); return true; -} - +} + int NifExport::DoExportInternal(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options) { - TCHAR path[MAX_PATH]; - GetFullPathName(name, MAX_PATH, path, NULL); - PathRenameExtension(path, ".nif"); - - Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0; - + TCHAR path[MAX_PATH]; + GetFullPathName(name, MAX_PATH, path, NULL); + PathRenameExtension(path, ".nif"); + + Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0; + // read application settings AppSettings::Initialize(i); TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); bool iniNameIsValid = (-1 != _taccess(iniName, 0)); // Set whether Config should use registry or not @@ -433,66 +429,66 @@ int NifExport::DoExportInternal(const TCHAR *name, ExpInterface *ei, Interface * appSettings = Exporter::exportAppSettings(); appSettings->WriteSettings(i); - } - - int nifVersion = VER_20_0_0_5; - int nifUserVer = Exporter::mNifUserVersion; - if (!Exporter::mNifVersion.empty()) - { - nifVersion = ParseVersionString(Exporter::mNifVersion); - if (!IsSupportedVersion(nifVersion)) - throw exception(FormatString("Version '%s' is not a supported version.").c_str()); - } - Exporter::mNifVersionInt = nifVersion; - - Exporter::ExportType exportType = Exporter::mExportType; - - // Hack so MW exports cleaner. Basically write tree without NiControllerManager - if ( nifVersion <= VER_10_0_1_0 - && (Exporter::mExportType != Exporter::NIF_WO_ANIM && Exporter::mExportType != Exporter::NIF_WITH_MGR) - ) - { - Exporter::mExportType = Exporter::NIF_WO_KF; - } - Niflib::NifInfo info(nifVersion, nifUserVer, nifUserVer); - info.endian = Niflib::NifInfo::INFO_LITTLE_ENDIAN; - info.creator = Exporter::mCreatorName; - info.exportInfo1 = FormatText("Niftools 3ds Max Plugins %s", fileVersion.data()); - - Exporter exp(i, appSettings); - - Ref<NiNode> root = new NiNode(); + } + + int nifVersion = VER_20_0_0_5; + int nifUserVer = Exporter::mNifUserVersion; + if (!Exporter::mNifVersion.empty()) + { + nifVersion = ParseVersionString(Exporter::mNifVersion); + if (!IsSupportedVersion(nifVersion)) + throw exception(FormatString("Version '%s' is not a supported version.").c_str()); + } + Exporter::mNifVersionInt = nifVersion; + + Exporter::ExportType exportType = Exporter::mExportType; + + // Hack so MW exports cleaner. Basically write tree without NiControllerManager + if ( nifVersion <= VER_10_0_1_0 + && (Exporter::mExportType != Exporter::NIF_WO_ANIM && Exporter::mExportType != Exporter::NIF_WITH_MGR) + ) + { + Exporter::mExportType = Exporter::NIF_WO_KF; + } + Niflib::NifInfo info(nifVersion, nifUserVer, nifUserVer); + info.endian = ENDIAN_LITTLE; + info.creator = Exporter::mCreatorName; + info.exportInfo1 = FormatText("Niftools 3ds Max Plugins %s", fileVersion.data()); + + Exporter exp(i, appSettings); + + Ref<NiNode> root = new NiNode(); Exporter::Result result = exp.doExport(root, i->GetRootNode()); if (result!=Exporter::Ok) throw exception("Unknown error."); - - if (exportType == Exporter::NIF_WO_ANIM || exportType == Exporter::NIF_WITH_MGR) - { - WriteNifTree(path, NiObjectRef(root), info); - } - else - { - Niflib::ExportOptions export_type = EXPORT_NIF; - switch (exportType) { + + if (exportType == Exporter::NIF_WO_ANIM || exportType == Exporter::NIF_WITH_MGR) + { + WriteNifTree(path, NiObjectRef(root), info); + } + else + { + Niflib::ExportOptions export_type = EXPORT_NIF; + switch (exportType) { case Exporter::SINGLE_KF_WITH_NIF: export_type = EXPORT_NIF_KF; break; case Exporter::SINGLE_KF_WO_NIF: export_type = EXPORT_KF; break; case Exporter::MULTI_KF_WITH_NIF: export_type = EXPORT_NIF_KF_MULTI; break; case Exporter::MULTI_KF_WO_NIF: export_type = EXPORT_KF_MULTI; break; - } - - Niflib::NifGame game = KF_MW; - if (nifVersion <= VER_4_0_0_2) { - game = KF_MW; - } else if (nifVersion <= VER_20_0_0_4) { - game = KF_DAOC; - } else { - game = KF_CIV4; - } - - WriteFileGroup(path, StaticCast<NiObject>(root), info, export_type, game); - } - return true; + } + + Niflib::NifGame game = KF_MW; + if (nifVersion <= VER_4_0_0_2) { + game = KF_MW; + } else if (nifVersion <= VER_20_0_0_4) { + game = KF_DAOC; + } else { + game = KF_CIV4; + } + + WriteFileGroup(path, StaticCast<NiObject>(root), info, export_type, game); + } + return true; } diff --git a/NifExport/NvTriStrip/NvTriStrip.cpp b/NifExport/NvTriStrip/NvTriStrip.cpp new file mode 100644 index 0000000..88e4c1e --- /dev/null +++ b/NifExport/NvTriStrip/NvTriStrip.cpp @@ -0,0 +1,504 @@ + +#include "NvTriStripObjects.h" +#include "NvTriStrip.h" + +using namespace NvTriStrip; + +namespace NvTriStrip { + +//////////////////////////////////////////////////////////////////////////////////////// +//private data +static unsigned int cacheSize = CACHESIZE_GEFORCE1_2; +static bool bStitchStrips = true; +static unsigned int minStripSize = 0; +static bool bListsOnly = false; +static unsigned int restartVal = 0; +static bool bRestart = false; + +void EnableRestart(const unsigned int _restartVal) +{ + bRestart = true; + restartVal = _restartVal; +} + +void DisableRestart() +{ + bRestart = false; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// SetListsOnly() +// +// If set to true, will return an optimized list, with no strips at all. +// +// Default value: false +// +void SetListsOnly(const bool _bListsOnly) +{ + bListsOnly = _bListsOnly; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// SetCacheSize() +// +// Sets the cache size which the stripfier uses to optimize the data. +// Controls the length of the generated individual strips. +// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2 +// You may want to play around with this number to tweak performance. +// +// Default value: 16 +// +void SetCacheSize(const unsigned int _cacheSize) +{ + cacheSize = _cacheSize; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetStitchStrips() +// +// bool to indicate whether to stitch together strips into one huge strip or not. +// If set to true, you'll get back one huge strip stitched together using degenerate +// triangles. +// If set to false, you'll get back a large number of separate strips. +// +// Default value: true +// +void SetStitchStrips(const bool _bStitchStrips) +{ + bStitchStrips = _bStitchStrips; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetMinStripSize() +// +// Sets the minimum acceptable size for a strip, in triangles. +// All strips generated which are shorter than this will be thrown into one big, separate list. +// +// Default value: 0 +// +void SetMinStripSize(const unsigned int _minStripSize) +{ + minStripSize = _minStripSize; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +//Cleanup strips / faces, used by generatestrips +void Cleanup(NvStripInfoVec& tempStrips, NvFaceInfoVec& tempFaces) +{ + //delete strips + for(size_t i = 0; i < tempStrips.size(); i++) + { + for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++) + { + delete tempStrips[i]->m_faces[j]; + tempStrips[i]->m_faces[j] = NULL; + } + tempStrips[i]->m_faces.resize(0); + delete tempStrips[i]; + tempStrips[i] = NULL; + } + + //delete faces + for(size_t i = 0; i < tempFaces.size(); i++) + { + delete tempFaces[i]; + tempFaces[i] = NULL; + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +//SameTriangle() +// +//Returns true if the two triangles defined by firstTri and secondTri are the same +// The "same" is defined in this case as having the same indices with the same winding order +// +bool SameTriangle(unsigned short firstTri0, unsigned short firstTri1, unsigned short firstTri2, + unsigned short secondTri0, unsigned short secondTri1, unsigned short secondTri2) +{ + bool isSame = false; + + if (firstTri0 == secondTri0) + { + if (firstTri1 == secondTri1) + { + if (firstTri2 == secondTri2) + isSame = true; + } + } + else if (firstTri0 == secondTri1) + { + if (firstTri1 == secondTri2) + { + if (firstTri2 == secondTri0) + isSame = true; + } + } + else if (firstTri0 == secondTri2) + { + if (firstTri1 == secondTri0) + { + if (firstTri2 == secondTri1) + isSame = true; + } + } + + return isSame; +} + + +bool TestTriangle(const unsigned short v0, const unsigned short v1, const unsigned short v2, const std::vector<NvFaceInfo>* in_bins, const int NUMBINS) +{ + //hash this triangle + bool isLegit = false; + int ctr = v0 % NUMBINS; + for (size_t k = 0; k < in_bins[ctr].size(); ++k) + { + //check triangles in this bin + if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, + v0, v1, v2)) + { + isLegit = true; + break; + } + } + if (!isLegit) + { + ctr = v1 % NUMBINS; + for (size_t k = 0; k < in_bins[ctr].size(); ++k) + { + //check triangles in this bin + if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, + v0, v1, v2)) + { + isLegit = true; + break; + } + } + + if (!isLegit) + { + ctr = v2 % NUMBINS; + for (size_t k = 0; k < in_bins[ctr].size(); ++k) + { + //check triangles in this bin + if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, + v0, v1, v2)) + { + isLegit = true; + break; + } + } + + } + } + + return isLegit; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// GenerateStrips() +// +// in_indices: input index list, the indices you would use to render +// in_numIndices: number of entries in in_indices +// primGroups: array of optimized/stripified PrimitiveGroups +// numGroups: number of groups returned +// +// Be sure to call delete[] on the returned primGroups to avoid leaking mem +// +bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices, + PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled) +{ + //put data in format that the stripifier likes + WordVec tempIndices; + tempIndices.resize(in_numIndices); + unsigned short maxIndex = 0; + unsigned short minIndex = 0xFFFF; + for(size_t i = 0; i < in_numIndices; i++) + { + tempIndices[i] = in_indices[i]; + if (in_indices[i] > maxIndex) + maxIndex = in_indices[i]; + if (in_indices[i] < minIndex) + minIndex = in_indices[i]; + } + NvStripInfoVec tempStrips; + NvFaceInfoVec tempFaces; + + NvStripifier stripifier; + + //do actual stripification + stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces); + + //stitch strips together + IntVec stripIndices; + unsigned int numSeparateStrips = 0; + + if(bListsOnly) + { + //if we're outputting only lists, we're done + *numGroups = 1; + (*primGroups) = new PrimitiveGroup[*numGroups]; + PrimitiveGroup* primGroupArray = *primGroups; + + //count the total number of indices + unsigned int numIndices = 0; + for(size_t i = 0; i < tempStrips.size(); i++) + { + numIndices += tempStrips[i]->m_faces.size() * 3; + } + + //add in the list + numIndices += tempFaces.size() * 3; + + primGroupArray[0].type = PT_LIST; + primGroupArray[0].numIndices = numIndices; + primGroupArray[0].indices = new unsigned short[numIndices]; + + //do strips + unsigned int indexCtr = 0; + for(size_t i = 0; i < tempStrips.size(); i++) + { + for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++) + { + //degenerates are of no use with lists + if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j])) + { + primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0; + primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1; + primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2; + } + else + { + //we've removed a tri, reduce the number of indices + primGroupArray[0].numIndices -= 3; + } + } + } + + //do lists + for(size_t i = 0; i < tempFaces.size(); i++) + { + primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0; + primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1; + primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2; + } + } + else + { + stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips, bRestart, restartVal); + + //if we're stitching strips together, we better get back only one strip from CreateStrips() + assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips); + + //convert to output format + *numGroups = numSeparateStrips; //for the strips + if(tempFaces.size() != 0) + (*numGroups)++; //we've got a list as well, increment + (*primGroups) = new PrimitiveGroup[*numGroups]; + + PrimitiveGroup* primGroupArray = *primGroups; + + //first, the strips + int startingLoc = 0; + for(size_t stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++) + { + int stripLength = 0; + + if(!bStitchStrips) + { + //if we've got multiple strips, we need to figure out the correct length + size_t i; + for(i = startingLoc; i < stripIndices.size(); i++) + { + if(stripIndices[i] == -1) + break; + } + + stripLength = i - startingLoc; + } + else + stripLength = stripIndices.size(); + + primGroupArray[stripCtr].type = PT_STRIP; + primGroupArray[stripCtr].indices = new unsigned short[stripLength]; + primGroupArray[stripCtr].numIndices = stripLength; + + int indexCtr = 0; + for(int i = startingLoc; i < stripLength + startingLoc; i++) + primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i]; + + //we add 1 to account for the -1 separating strips + //this doesn't break the stitched case since we'll exit the loop + startingLoc += stripLength + 1; + } + + //next, the list + if(tempFaces.size() != 0) + { + int faceGroupLoc = (*numGroups) - 1; //the face group is the last one + primGroupArray[faceGroupLoc].type = PT_LIST; + primGroupArray[faceGroupLoc].indices = new unsigned short[tempFaces.size() * 3]; + primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3; + int indexCtr = 0; + for(size_t i = 0; i < tempFaces.size(); i++) + { + primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0; + primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1; + primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2; + } + } + } + + //validate generated data against input + if (validateEnabled) + { + const int NUMBINS = 100; + + std::vector<NvFaceInfo> in_bins[NUMBINS]; + + //hash input indices on first index + for (size_t i = 0; i < in_numIndices; i += 3) + { + NvFaceInfo faceInfo(in_indices[i], in_indices[i + 1], in_indices[i + 2]); + in_bins[in_indices[i] % NUMBINS].push_back(faceInfo); + } + + for (int i = 0; i < *numGroups; ++i) + { + switch ((*primGroups)[i].type) + { + case PT_LIST: + { + for (size_t j = 0; j < (*primGroups)[i].numIndices; j += 3) + { + unsigned short v0 = (*primGroups)[i].indices[j]; + unsigned short v1 = (*primGroups)[i].indices[j + 1]; + unsigned short v2 = (*primGroups)[i].indices[j + 2]; + + //ignore degenerates + if (NvStripifier::IsDegenerate(v0, v1, v2)) + continue; + + if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS)) + { + Cleanup(tempStrips, tempFaces); + return false; + } + } + break; + } + + case PT_STRIP: + { + //int brokenCtr = 0; + bool flip = false; + for (size_t j = 2; j < (*primGroups)[i].numIndices; ++j) + { + unsigned short v0 = (*primGroups)[i].indices[j - 2]; + unsigned short v1 = (*primGroups)[i].indices[j - 1]; + unsigned short v2 = (*primGroups)[i].indices[j]; + + if (flip) + { + //swap v1 and v2 + unsigned short swap = v1; + v1 = v2; + v2 = swap; + } + + //ignore degenerates + if (NvStripifier::IsDegenerate(v0, v1, v2)) + { + flip = !flip; + continue; + } + + if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS)) + { + Cleanup(tempStrips, tempFaces); + return false; + } + + flip = !flip; + } + break; + } + + case PT_FAN: + default: + break; + } + } + + } + + //clean up everything + Cleanup(tempStrips, tempFaces); + + return true; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// RemapIndices() +// +// Function to remap your indices to improve spatial locality in your vertex buffer. +// +// in_primGroups: array of PrimitiveGroups you want remapped +// numGroups: number of entries in in_primGroups +// numVerts: number of vertices in your vertex buffer, also can be thought of as the range +// of acceptable values for indices in your primitive groups. +// remappedGroups: array of remapped PrimitiveGroups +// +// Note that, according to the remapping handed back to you, you must reorder your +// vertex buffer. +// +void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups, + const unsigned short numVerts, PrimitiveGroup** remappedGroups) +{ + (*remappedGroups) = new PrimitiveGroup[numGroups]; + + //caches oldIndex --> newIndex conversion + int *indexCache; + indexCache = new int[numVerts]; + memset(indexCache, -1, sizeof(int)*numVerts); + + //loop over primitive groups + unsigned int indexCtr = 0; + for(int i = 0; i < numGroups; i++) + { + unsigned int numIndices = in_primGroups[i].numIndices; + + //init remapped group + (*remappedGroups)[i].type = in_primGroups[i].type; + (*remappedGroups)[i].numIndices = numIndices; + (*remappedGroups)[i].indices = new unsigned short[numIndices]; + + for(size_t j = 0; j < numIndices; j++) + { + int cachedIndex = indexCache[in_primGroups[i].indices[j]]; + if(cachedIndex == -1) //we haven't seen this index before + { + //point to "last" vertex in VB + (*remappedGroups)[i].indices[j] = indexCtr; + + //add to index cache, increment + indexCache[in_primGroups[i].indices[j]] = indexCtr++; + } + else + { + //we've seen this index before + (*remappedGroups)[i].indices[j] = cachedIndex; + } + } + } + + delete[] indexCache; +} + +} //end namespace diff --git a/NifExport/NvTriStrip/NvTriStrip.h b/NifExport/NvTriStrip/NvTriStrip.h new file mode 100644 index 0000000..0e6c695 --- /dev/null +++ b/NifExport/NvTriStrip/NvTriStrip.h @@ -0,0 +1,147 @@ +#ifndef NVTRISTRIP_H +#define NVTRISTRIP_H + +#ifndef NULL +#define NULL 0 +#endif + +namespace NvTriStrip { + +//////////////////////////////////////////////////////////////////////////////////////// +// Public interface for stripifier +//////////////////////////////////////////////////////////////////////////////////////// + +//GeForce1 and 2 cache size +#define CACHESIZE_GEFORCE1_2 16 + +//GeForce3 cache size +#define CACHESIZE_GEFORCE3 24 + +enum PrimType +{ + PT_LIST, + PT_STRIP, + PT_FAN +}; + +struct PrimitiveGroup +{ + PrimType type; + unsigned int numIndices; + unsigned short* indices; + +//////////////////////////////////////////////////////////////////////////////////////// + + PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {} + ~PrimitiveGroup() + { + if(indices) + delete[] indices; + indices = NULL; + } +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +// EnableRestart() +// +// For GPUs that support primitive restart, this sets a value as the restart index +// +// Restart is meaningless if strips are not being stitched together, so enabling restart +// makes NvTriStrip forcing stitching. So, you'll get back one strip. +// +// Default value: disabled +// +void EnableRestart(const unsigned int restartVal); + +//////////////////////////////////////////////////////////////////////////////////////// +// DisableRestart() +// +// For GPUs that support primitive restart, this disables using primitive restart +// +void DisableRestart(); + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetCacheSize() +// +// Sets the cache size which the stripfier uses to optimize the data. +// Controls the length of the generated individual strips. +// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2 +// You may want to play around with this number to tweak performance. +// +// Default value: 16 +// +void SetCacheSize(const unsigned int cacheSize); + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetStitchStrips() +// +// bool to indicate whether to stitch together strips into one huge strip or not. +// If set to true, you'll get back one huge strip stitched together using degenerate +// triangles. +// If set to false, you'll get back a large number of separate strips. +// +// Default value: true +// +void SetStitchStrips(const bool bStitchStrips); + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetMinStripSize() +// +// Sets the minimum acceptable size for a strip, in triangles. +// All strips generated which are shorter than this will be thrown into one big, separate list. +// +// Default value: 0 +// +void SetMinStripSize(const unsigned int minSize); + + +//////////////////////////////////////////////////////////////////////////////////////// +// SetListsOnly() +// +// If set to true, will return an optimized list, with no strips at all. +// +// Default value: false +// +void SetListsOnly(const bool bListsOnly); + + +//////////////////////////////////////////////////////////////////////////////////////// +// GenerateStrips() +// +// in_indices: input index list, the indices you would use to render +// in_numIndices: number of entries in in_indices +// primGroups: array of optimized/stripified PrimitiveGroups +// numGroups: number of groups returned +// +// Be sure to call delete[] on the returned primGroups to avoid leaking mem +// +bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices, + PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled = false); + + +//////////////////////////////////////////////////////////////////////////////////////// +// RemapIndices() +// +// Function to remap your indices to improve spatial locality in your vertex buffer. +// +// in_primGroups: array of PrimitiveGroups you want remapped +// numGroups: number of entries in in_primGroups +// numVerts: number of vertices in your vertex buffer, also can be thought of as the range +// of acceptable values for indices in your primitive groups. +// remappedGroups: array of remapped PrimitiveGroups +// +// Note that, according to the remapping handed back to you, you must reorder your +// vertex buffer. +// +// Credit goes to the MS Xbox crew for the idea for this interface. +// +void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups, + const unsigned short numVerts, PrimitiveGroup** remappedGroups); + +} //End namespace + +#endif \ No newline at end of file diff --git a/NifExport/NvTriStrip/NvTriStripObjects.cpp b/NifExport/NvTriStrip/NvTriStripObjects.cpp new file mode 100644 index 0000000..4cf11d3 --- /dev/null +++ b/NifExport/NvTriStrip/NvTriStripObjects.cpp @@ -0,0 +1,1771 @@ + +//#pragma warning( disable : 4786 ) + +#include <assert.h> +#include <set> +#include "NvTriStripObjects.h" +#include "VertexCache.h" + +using namespace NvTriStrip; + +#define CACHE_INEFFICIENCY 6 + +NvStripifier::NvStripifier() +{ + +} + +NvStripifier::~NvStripifier() +{ + +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindEdgeInfo() +// +// find the edge info for these two indices +// +NvEdgeInfo * NvStripifier::FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1){ + + // we can get to it through either array + // because the edge infos have a v0 and v1 + // and there is no order except how it was + // first created. + NvEdgeInfo *infoIter = edgeInfos[v0]; + while (infoIter != NULL){ + if (infoIter->m_v0 == v0){ + if (infoIter->m_v1 == v1) + return infoIter; + else + infoIter = infoIter->m_nextV0; + } + else { + assert(infoIter->m_v1 == v0); + if (infoIter->m_v0 == v1) + return infoIter; + else + infoIter = infoIter->m_nextV1; + } + } + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindOtherFace +// +// find the other face sharing these vertices +// exactly like the edge info above +// +NvFaceInfo * NvStripifier::FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo){ + NvEdgeInfo *edgeInfo = FindEdgeInfo(edgeInfos, v0, v1); + + if( (edgeInfo == NULL) && (v0 == v1)) + { + //we've hit a degenerate + return NULL; + } + + assert(edgeInfo != NULL); + return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0); +} + + +bool NvStripifier::AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos) +{ + for(size_t i = 0; i < faceInfos.size(); ++i) + { + if( (faceInfos[i]->m_v0 == faceInfo->m_v0) && + (faceInfos[i]->m_v1 == faceInfo->m_v1) && + (faceInfos[i]->m_v2 == faceInfo->m_v2) ) + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// BuildStripifyInfo() +// +// Builds the list of all face and edge infos +// +void NvStripifier::BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, + const unsigned short maxIndex) +{ + // reserve space for the face infos, but do not resize them. + int numIndices = indices.size(); + faceInfos.reserve(numIndices / 3); + + // we actually resize the edge infos, so we must initialize to NULL + edgeInfos.resize(maxIndex + 1); + for (int i = 0; i < maxIndex + 1; i++) + edgeInfos[i] = NULL; + + // iterate through the triangles of the triangle list + int numTriangles = numIndices / 3; + int index = 0; + bool bFaceUpdated[3]; + + for (int i = 0; i < numTriangles; i++) + { + bool bMightAlreadyExist = true; + bFaceUpdated[0] = false; + bFaceUpdated[1] = false; + bFaceUpdated[2] = false; + + // grab the indices + int v0 = indices[index++]; + int v1 = indices[index++]; + int v2 = indices[index++]; + + //we disregard degenerates + if(IsDegenerate(v0, v1, v2)) + continue; + + // create the face info and add it to the list of faces, but only if this exact face doesn't already + // exist in the list + NvFaceInfo *faceInfo = new NvFaceInfo(v0, v1, v2); + + // grab the edge infos, creating them if they do not already exist + NvEdgeInfo *edgeInfo01 = FindEdgeInfo(edgeInfos, v0, v1); + if (edgeInfo01 == NULL) + { + //since one of it's edges isn't in the edge data structure, it can't already exist in the face structure + bMightAlreadyExist = false; + + // create the info + edgeInfo01 = new NvEdgeInfo(v0, v1); + + // update the linked list on both + edgeInfo01->m_nextV0 = edgeInfos[v0]; + edgeInfo01->m_nextV1 = edgeInfos[v1]; + edgeInfos[v0] = edgeInfo01; + edgeInfos[v1] = edgeInfo01; + + // set face 0 + edgeInfo01->m_face0 = faceInfo; + } + else + { + if (edgeInfo01->m_face1 != NULL) + { + //printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n"); + } + else + { + edgeInfo01->m_face1 = faceInfo; + bFaceUpdated[0] = true; + } + } + + // grab the edge infos, creating them if they do not already exist + NvEdgeInfo *edgeInfo12 = FindEdgeInfo(edgeInfos, v1, v2); + if (edgeInfo12 == NULL) + { + bMightAlreadyExist = false; + + // create the info + edgeInfo12 = new NvEdgeInfo(v1, v2); + + // update the linked list on both + edgeInfo12->m_nextV0 = edgeInfos[v1]; + edgeInfo12->m_nextV1 = edgeInfos[v2]; + edgeInfos[v1] = edgeInfo12; + edgeInfos[v2] = edgeInfo12; + + // set face 0 + edgeInfo12->m_face0 = faceInfo; + } + else + { + if (edgeInfo12->m_face1 != NULL) + { + //printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n"); + } + else + { + edgeInfo12->m_face1 = faceInfo; + bFaceUpdated[1] = true; + } + } + + // grab the edge infos, creating them if they do not already exist + NvEdgeInfo *edgeInfo20 = FindEdgeInfo(edgeInfos, v2, v0); + if (edgeInfo20 == NULL) + { + bMightAlreadyExist = false; + + // create the info + edgeInfo20 = new NvEdgeInfo(v2, v0); + + // update the linked list on both + edgeInfo20->m_nextV0 = edgeInfos[v2]; + edgeInfo20->m_nextV1 = edgeInfos[v0]; + edgeInfos[v2] = edgeInfo20; + edgeInfos[v0] = edgeInfo20; + + // set face 0 + edgeInfo20->m_face0 = faceInfo; + } + else + { + if (edgeInfo20->m_face1 != NULL) + { + //printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n"); + } + else + { + edgeInfo20->m_face1 = faceInfo; + bFaceUpdated[2] = true; + } + } + + if(bMightAlreadyExist) + { + if(!AlreadyExists(faceInfo, faceInfos)) + faceInfos.push_back(faceInfo); + else + { + delete faceInfo; + + //cleanup pointers that point to this deleted face + if(bFaceUpdated[0]) + edgeInfo01->m_face1 = NULL; + if(bFaceUpdated[1]) + edgeInfo12->m_face1 = NULL; + if(bFaceUpdated[2]) + edgeInfo20->m_face1 = NULL; + } + } + else + { + faceInfos.push_back(faceInfo); + } + + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindStartPoint() +// +// Finds a good starting point, namely one which has only one neighbor +// +int NvStripifier::FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos) +{ + int bestCtr = -1; + int bestIndex = -1; + + for(size_t i = 0; i < faceInfos.size(); i++) + { + int ctr = 0; + + if(FindOtherFace(edgeInfos, faceInfos[i]->m_v0, faceInfos[i]->m_v1, faceInfos[i]) == NULL) + ctr++; + if(FindOtherFace(edgeInfos, faceInfos[i]->m_v1, faceInfos[i]->m_v2, faceInfos[i]) == NULL) + ctr++; + if(FindOtherFace(edgeInfos, faceInfos[i]->m_v2, faceInfos[i]->m_v0, faceInfos[i]) == NULL) + ctr++; + if(ctr > bestCtr) + { + bestCtr = ctr; + bestIndex = i; + //return i; + } + } + //return -1; + + if(bestCtr == 0) + return -1; + else + return bestIndex; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindGoodResetPoint() +// +// A good reset point is one near other commited areas so that +// we know that when we've made the longest strips its because +// we're stripifying in the same general orientation. +// +NvFaceInfo* NvStripifier::FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos){ + // we hop into different areas of the mesh to try to get + // other large open spans done. Areas of small strips can + // just be left to triangle lists added at the end. + NvFaceInfo *result = NULL; + + if(result == NULL) + { + int numFaces = faceInfos.size(); + if (numFaces == 0) + return NULL; + + int startPoint; + if(bFirstTimeResetPoint) + { + //first time, find a face with few neighbors (look for an edge of the mesh) + startPoint = FindStartPoint(faceInfos, edgeInfos); + bFirstTimeResetPoint = false; + } + else + startPoint = (int)(((float) numFaces - 1) * meshJump); + + if(startPoint == -1) + { + startPoint = (int)(((float) numFaces - 1) * meshJump); + + //meshJump += 0.1f; + //if (meshJump > 1.0f) + // meshJump = .05f; + } + + int i = startPoint; + do { + + // if this guy isn't visited, try him + if (faceInfos[i]->m_stripId < 0){ + result = faceInfos[i]; + break; + } + + // update the index and clamp to 0-(numFaces-1) + if (++i >= numFaces) + i = 0; + + } while (i != startPoint); + + // update the meshJump + meshJump += 0.1f; + if (meshJump > 1.0f) + meshJump = .05f; + } + + // return the best face we found + return result; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// GetUniqueVertexInB() +// +// Returns the vertex unique to faceB +// +int NvStripifier::GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB){ + + int facev0 = faceB->m_v0; + if (facev0 != faceA->m_v0 && + facev0 != faceA->m_v1 && + facev0 != faceA->m_v2) + return facev0; + + int facev1 = faceB->m_v1; + if (facev1 != faceA->m_v0 && + facev1 != faceA->m_v1 && + facev1 != faceA->m_v2) + return facev1; + + int facev2 = faceB->m_v2; + if (facev2 != faceA->m_v0 && + facev2 != faceA->m_v1 && + facev2 != faceA->m_v2) + return facev2; + + // nothing is different + return -1; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// GetSharedVertices() +// +// Returns the (at most) two vertices shared between the two faces +// +void NvStripifier::GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1) +{ + *vertex0 = -1; + *vertex1 = -1; + + int facev0 = faceB->m_v0; + if (facev0 == faceA->m_v0 || + facev0 == faceA->m_v1 || + facev0 == faceA->m_v2) + { + if(*vertex0 == -1) + *vertex0 = facev0; + else + { + *vertex1 = facev0; + return; + } + } + + int facev1 = faceB->m_v1; + if (facev1 == faceA->m_v0 || + facev1 == faceA->m_v1 || + facev1 == faceA->m_v2) + { + if(*vertex0 == -1) + *vertex0 = facev1; + else + { + *vertex1 = facev1; + return; + } + } + + int facev2 = faceB->m_v2; + if (facev2 == faceA->m_v0 || + facev2 == faceA->m_v1 || + facev2 == faceA->m_v2) + { + if(*vertex0 == -1) + *vertex0 = facev2; + else + { + *vertex1 = facev2; + return; + } + } + +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// GetNextIndex() +// +// Returns vertex of the input face which is "next" in the input index list +// +inline int NvStripifier::GetNextIndex(const WordVec &indices, NvFaceInfo *face){ + + int numIndices = indices.size(); + assert(numIndices >= 2); + + int v0 = indices[numIndices-2]; + int v1 = indices[numIndices-1]; + + int fv0 = face->m_v0; + int fv1 = face->m_v1; + int fv2 = face->m_v2; + + if (fv0 != v0 && fv0 != v1){ + if ((fv1 != v0 && fv1 != v1) || (fv2 != v0 && fv2 != v1)){ + //printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); + //printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); + } + return fv0; + } + if (fv1 != v0 && fv1 != v1){ + if ((fv0 != v0 && fv0 != v1) || (fv2 != v0 && fv2 != v1)){ + //printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); + //printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); + } + return fv1; + } + if (fv2 != v0 && fv2 != v1){ + if ((fv0 != v0 && fv0 != v1) || (fv1 != v0 && fv1 != v1)){ + //printf("GetNextIndex: Triangle doesn't have all of its vertices\n"); + //printf("GetNextIndex: Duplicate triangle probably got us derailed\n"); + } + return fv2; + } + + // shouldn't get here, but let's try and fail gracefully + if( (fv0 == fv1) || (fv0 == fv2) ) + return fv0; + else if( (fv1 == fv0) || (fv1 == fv2) ) + return fv1; + else if( (fv2 == fv0) || (fv2 == fv1) ) + return fv2; + else + return -1; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// IsMarked() +// +// If either the faceInfo has a real strip index because it is +// already assign to a committed strip OR it is assigned in an +// experiment and the experiment index is the one we are building +// for, then it is marked and unavailable +inline bool NvStripInfo::IsMarked(NvFaceInfo *faceInfo){ + return (faceInfo->m_stripId >= 0) || (IsExperiment() && faceInfo->m_experimentId == m_experimentId); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// MarkTriangle() +// +// Marks the face with the current strip ID +// +inline void NvStripInfo::MarkTriangle(NvFaceInfo *faceInfo){ + assert(!IsMarked(faceInfo)); + if (IsExperiment()){ + faceInfo->m_experimentId = m_experimentId; + faceInfo->m_testStripId = m_stripId; + } + else{ + assert(faceInfo->m_stripId == -1); + faceInfo->m_experimentId = -1; + faceInfo->m_stripId = m_stripId; + } +} + + +bool NvStripInfo::Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face) +{ + bool bv0, bv1, bv2; //bools to indicate whether a vertex is in the faceVec or not + bv0 = bv1 = bv2 = false; + + for(size_t i = 0; i < faceVec.size(); i++) + { + if(!bv0) + { + if( (faceVec[i]->m_v0 == face->m_v0) || + (faceVec[i]->m_v1 == face->m_v0) || + (faceVec[i]->m_v2 == face->m_v0) ) + bv0 = true; + } + + if(!bv1) + { + if( (faceVec[i]->m_v0 == face->m_v1) || + (faceVec[i]->m_v1 == face->m_v1) || + (faceVec[i]->m_v2 == face->m_v1) ) + bv1 = true; + } + + if(!bv2) + { + if( (faceVec[i]->m_v0 == face->m_v2) || + (faceVec[i]->m_v1 == face->m_v2) || + (faceVec[i]->m_v2 == face->m_v2) ) + bv2 = true; + } + + //the face is not unique, all it's vertices exist in the face vector + if(bv0 && bv1 && bv2) + return false; + } + + //if we get out here, it's unique + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// Build() +// +// Builds a strip forward as far as we can go, then builds backwards, and joins the two lists +// +void NvStripInfo::Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos) +{ + // used in building the strips forward and backward + WordVec scratchIndices; + + // build forward... start with the initial face + NvFaceInfoVec forwardFaces, backwardFaces; + forwardFaces.push_back(m_startInfo.m_startFace); + + MarkTriangle(m_startInfo.m_startFace); + + int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v0 : m_startInfo.m_startEdge->m_v1); + int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v1 : m_startInfo.m_startEdge->m_v0); + + // easiest way to get v2 is to use this function which requires the + // other indices to already be in the list. + scratchIndices.push_back(v0); + scratchIndices.push_back(v1); + int v2 = NvStripifier::GetNextIndex(scratchIndices, m_startInfo.m_startFace); + scratchIndices.push_back(v2); + + // + // build the forward list + // + int nv0 = v1; + int nv1 = v2; + + NvFaceInfo *nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace); + while (nextFace != NULL && !IsMarked(nextFace)) + { + //check to see if this next face is going to cause us to die soon + int testnv0 = nv1; + int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); + + NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace); + + if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) ) + { + //uh, oh, we're following a dead end, try swapping + NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace); + + if( ((testNextFace != NULL) && !IsMarked(testNextFace)) ) + { + //we only swap if it buys us something + + //add a "fake" degenerate face + NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true); + + forwardFaces.push_back(tempFace); + MarkTriangle(tempFace); + + scratchIndices.push_back(nv0); + testnv0 = nv0; + + ++m_numDegenerates; + } + + } + + // add this to the strip + forwardFaces.push_back(nextFace); + + MarkTriangle(nextFace); + + // add the index + //nv0 = nv1; + //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); + scratchIndices.push_back(testnv1); + + // and get the next face + nv0 = testnv0; + nv1 = testnv1; + + nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace); + + } + + // tempAllFaces is going to be forwardFaces + backwardFaces + // it's used for Unique() + NvFaceInfoVec tempAllFaces; + for(size_t i = 0; i < forwardFaces.size(); i++) + tempAllFaces.push_back(forwardFaces[i]); + + // + // reset the indices for building the strip backwards and do so + // + scratchIndices.resize(0); + scratchIndices.push_back(v2); + scratchIndices.push_back(v1); + scratchIndices.push_back(v0); + nv0 = v1; + nv1 = v0; + nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace); + while (nextFace != NULL && !IsMarked(nextFace)) + { + //this tests to see if a face is "unique", meaning that its vertices aren't already in the list + // so, strips which "wrap-around" are not allowed + if(!Unique(tempAllFaces, nextFace)) + break; + + //check to see if this next face is going to cause us to die soon + int testnv0 = nv1; + int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); + + NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace); + + if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) ) + { + //uh, oh, we're following a dead end, try swapping + NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace); + if( ((testNextFace != NULL) && !IsMarked(testNextFace)) ) + { + //we only swap if it buys us something + + //add a "fake" degenerate face + NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true); + + backwardFaces.push_back(tempFace); + MarkTriangle(tempFace); + scratchIndices.push_back(nv0); + testnv0 = nv0; + + ++m_numDegenerates; + } + + } + + // add this to the strip + backwardFaces.push_back(nextFace); + + //this is just so Unique() will work + tempAllFaces.push_back(nextFace); + + MarkTriangle(nextFace); + + // add the index + //nv0 = nv1; + //nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace); + scratchIndices.push_back(testnv1); + + // and get the next face + nv0 = testnv0; + nv1 = testnv1; + nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace); + } + + // Combine the forward and backwards stripification lists and put into our own face vector + Combine(forwardFaces, backwardFaces); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// Combine() +// +// Combines the two input face vectors and puts the result into m_faces +// +void NvStripInfo::Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward){ + + // add backward faces + int numFaces = backward.size(); + for (int i = numFaces - 1; i >= 0; i--) + m_faces.push_back(backward[i]); + + // add forward faces + numFaces = forward.size(); + for (int i = 0; i < numFaces; i++) + m_faces.push_back(forward[i]); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// SharesEdge() +// +// Returns true if the input face and the current strip share an edge +// +bool NvStripInfo::SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos) +{ + //check v0->v1 edge + NvEdgeInfo* currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v0, faceInfo->m_v1); + + if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) + return true; + + //check v1->v2 edge + currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v1, faceInfo->m_v2); + + if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) + return true; + + //check v2->v0 edge + currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v2, faceInfo->m_v0); + + if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1)) + return true; + + return false; + +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// CommitStrips() +// +// "Commits" the input strips by setting their m_experimentId to -1 and adding to the allStrips +// vector +// +void NvStripifier::CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips) +{ + // Iterate through strips + int numStrips = strips.size(); + for (int i = 0; i < numStrips; i++){ + + // Tell the strip that it is now real + NvStripInfo *strip = strips[i]; + strip->m_experimentId = -1; + + // add to the list of real strips + allStrips.push_back(strip); + + // Iterate through the faces of the strip + // Tell the faces of the strip that they belong to a real strip now + const NvFaceInfoVec &faces = strips[i]->m_faces; + int numFaces = faces.size(); + + for (int j = 0; j < numFaces; j++) + { + strip->MarkTriangle(faces[j]); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindTraversal() +// +// Finds the next face to start the next strip on. +// +bool NvStripifier::FindTraversal(NvFaceInfoVec &faceInfos, + NvEdgeInfoVec &edgeInfos, + NvStripInfo *strip, + NvStripStartInfo &startInfo){ + + // if the strip was v0->v1 on the edge, then v1 will be a vertex in the next edge. + int v = (strip->m_startInfo.m_toV1 ? strip->m_startInfo.m_startEdge->m_v1 : strip->m_startInfo.m_startEdge->m_v0); + + NvFaceInfo *untouchedFace = NULL; + NvEdgeInfo *edgeIter = edgeInfos[v]; + while (edgeIter != NULL){ + NvFaceInfo *face0 = edgeIter->m_face0; + NvFaceInfo *face1 = edgeIter->m_face1; + if ((face0 != NULL && !strip->IsInStrip(face0)) && face1 != NULL && !strip->IsMarked(face1)) + { + untouchedFace = face1; + break; + } + if ((face1 != NULL && !strip->IsInStrip(face1)) && face0 != NULL && !strip->IsMarked(face0)){ + untouchedFace = face0; + break; + } + + // find the next edgeIter + edgeIter = (edgeIter->m_v0 == v ? edgeIter->m_nextV0 : edgeIter->m_nextV1); + } + + startInfo.m_startFace = untouchedFace; + startInfo.m_startEdge = edgeIter; + if (edgeIter != NULL) + { + if(strip->SharesEdge(startInfo.m_startFace, edgeInfos)) + startInfo.m_toV1 = (edgeIter->m_v0 == v); //note! used to be m_v1 + else + startInfo.m_toV1 = (edgeIter->m_v1 == v); + } + return (startInfo.m_startFace != NULL); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// RemoveSmallStrips() +// +// allStrips is the whole strip vector...all small strips will be deleted from this list, to avoid leaking mem +// allBigStrips is an out parameter which will contain all strips above minStripLength +// faceList is an out parameter which will contain all faces which were removed from the striplist +// +void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList) +{ + faceList.clear(); + allBigStrips.clear(); //make sure these are empty + NvFaceInfoVec tempFaceList; + + for(size_t i = 0; i < allStrips.size(); i++) + { + if(allStrips[i]->m_faces.size() < size_t(minStripLength)) + { + //strip is too small, add faces to faceList + for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++) + tempFaceList.push_back(allStrips[i]->m_faces[j]); + + //and free memory + delete allStrips[i]; + } + else + { + allBigStrips.push_back(allStrips[i]); + } + } + + if(tempFaceList.size()) + { + bool *bVisitedList = new bool[tempFaceList.size()]; + memset(bVisitedList, 0, tempFaceList.size()*sizeof(bool)); + + VertexCache* vcache = new VertexCache(cacheSize); + + int bestNumHits = -1; + int numHits; + int bestIndex = -1; + + while(1) + { + bestNumHits = -1; + + //find best face to add next, given the current cache + for(size_t i = 0; i < tempFaceList.size(); i++) + { + if(bVisitedList[i]) + continue; + + numHits = CalcNumHitsFace(vcache, tempFaceList[i]); + if(numHits > bestNumHits) + { + bestNumHits = numHits; + bestIndex = i; + } + } + + if(bestNumHits == -1.0f) + break; + bVisitedList[bestIndex] = true; + UpdateCacheFace(vcache, tempFaceList[bestIndex]); + faceList.push_back(tempFaceList[bestIndex]); + } + + delete vcache; + delete[] bVisitedList; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// NextIsCW() +// +// Returns true if the next face should be ordered in CW fashion +// +bool NvStripifier::NextIsCW(const int numIndices) +{ + return ((numIndices % 2) == 0); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// IsCW() +// +// Returns true if the face is ordered in CW fashion +// +bool NvStripifier::IsCW(NvFaceInfo *faceInfo, int v0, int v1) +{ + if (faceInfo->m_v0 == v0) + return (faceInfo->m_v1 == v1); + + else if (faceInfo->m_v1 == v0) + return (faceInfo->m_v2 == v1); + + else + return (faceInfo->m_v0 == v1); + + // shouldn't get here + assert(0); + return false; +} + +bool NvStripifier::FaceContainsIndex(const NvFaceInfo& face, const unsigned int index) +{ + return ( (size_t(face.m_v0) == index) || (size_t(face.m_v1) == index) || (size_t(face.m_v2) == index) ); +} + +bool NvStripifier::IsMoneyFace(const NvFaceInfo& face) +{ + if(FaceContainsIndex(face, 800) && + FaceContainsIndex(face, 812) && + FaceContainsIndex(face, 731)) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// CreateStrips() +// +// Generates actual strips from the list-in-strip-order. +// +void NvStripifier::CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, + const bool bStitchStrips, unsigned int& numSeparateStrips, + const bool bRestart, const unsigned int restartVal) +{ + assert(numSeparateStrips == 0); + + NvFaceInfo tLastFace(0, 0, 0); + NvFaceInfo tPrevStripLastFace(0, 0, 0); + int nStripCount = allStrips.size(); + assert(nStripCount > 0); + + //we infer the cw/ccw ordering depending on the number of indices + //this is screwed up by the fact that we insert -1s to denote changing strips + //this is to account for that + int accountForNegatives = 0; + + for (int i = 0; i < nStripCount; i++) + { + NvStripInfo *strip = allStrips[i]; + int nStripFaceCount = strip->m_faces.size(); + assert(nStripFaceCount > 0); + + // Handle the first face in the strip + { + NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); + + // If there is a second face, reorder vertices such that the + // unique vertex is first + if (nStripFaceCount > 1) + { + int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); + if (nUnique == tFirstFace.m_v1) + { + SWAP(tFirstFace.m_v0, tFirstFace.m_v1); + } + else if (nUnique == tFirstFace.m_v2) + { + SWAP(tFirstFace.m_v0, tFirstFace.m_v2); + } + + // If there is a third face, reorder vertices such that the + // shared vertex is last + if (nStripFaceCount > 2) + { + if(IsDegenerate(strip->m_faces[1])) + { + int pivot = strip->m_faces[1]->m_v1; + if(tFirstFace.m_v1 == pivot) + { + SWAP(tFirstFace.m_v1, tFirstFace.m_v2); + } + } + else + { + int nShared0, nShared1; + GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1); + if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) ) + { + SWAP(tFirstFace.m_v1, tFirstFace.m_v2); + } + } + } + } + + if( (i == 0) || !bStitchStrips || bRestart) + { + if(!IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) + stripIndices.push_back(tFirstFace.m_v0); + } + else + { + // Double tap the first in the new strip + stripIndices.push_back(tFirstFace.m_v0); + + // Check CW/CCW ordering + if (NextIsCW(stripIndices.size() - accountForNegatives) != IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) + { + stripIndices.push_back(tFirstFace.m_v0); + } + } + + stripIndices.push_back(tFirstFace.m_v0); + stripIndices.push_back(tFirstFace.m_v1); + stripIndices.push_back(tFirstFace.m_v2); + + // Update last face info + tLastFace = tFirstFace; + } + + for (int j = 1; j < nStripFaceCount; j++) + { + int nUnique = GetUniqueVertexInB(&tLastFace, strip->m_faces[j]); + if (nUnique != -1) + { + stripIndices.push_back(nUnique); + + // Update last face info + tLastFace.m_v0 = tLastFace.m_v1; + tLastFace.m_v1 = tLastFace.m_v2; + tLastFace.m_v2 = nUnique; + } + else + { + //we've hit a degenerate + stripIndices.push_back(strip->m_faces[j]->m_v2); + tLastFace.m_v0 = strip->m_faces[j]->m_v0;//tLastFace.m_v1; + tLastFace.m_v1 = strip->m_faces[j]->m_v1;//tLastFace.m_v2; + tLastFace.m_v2 = strip->m_faces[j]->m_v2;//tLastFace.m_v1; + + } + } + + // Double tap between strips. + if (bStitchStrips && !bRestart) + { + if (i != nStripCount - 1) + stripIndices.push_back(tLastFace.m_v2); + } + else if (bRestart) + { + stripIndices.push_back(restartVal); + } + else + { + //-1 index indicates next strip + stripIndices.push_back(-1); + accountForNegatives++; + numSeparateStrips++; + } + + // Update last face info + tLastFace.m_v0 = tLastFace.m_v1; + tLastFace.m_v1 = tLastFace.m_v2; + tLastFace.m_v2 = tLastFace.m_v2; + } + + if(bStitchStrips || bRestart) + numSeparateStrips = 1; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// Stripify() +// +// +// in_indices are the input indices of the mesh to stripify +// in_cacheSize is the target cache size +// +void NvStripifier::Stripify(const WordVec &in_indices, const int in_cacheSize, + const int in_minStripLength, const unsigned short maxIndex, + NvStripInfoVec &outStrips, NvFaceInfoVec& outFaceList) +{ + meshJump = 0.0f; + bFirstTimeResetPoint = true; //used in FindGoodResetPoint() + + //the number of times to run the experiments + int numSamples = 10; + + //the cache size, clamped to one + if ( in_cacheSize - CACHE_INEFFICIENCY < 1 ) cacheSize = 1; + else cacheSize = in_cacheSize - CACHE_INEFFICIENCY; + + minStripLength = in_minStripLength; //this is the strip size threshold below which we dump the strip into a list + + indices = in_indices; + + // build the stripification info + NvFaceInfoVec allFaceInfos; + NvEdgeInfoVec allEdgeInfos; + + BuildStripifyInfo(allFaceInfos, allEdgeInfos, maxIndex); + + NvStripInfoVec allStrips; + + // stripify + FindAllStrips(allStrips, allFaceInfos, allEdgeInfos, numSamples); + + //split up the strips into cache friendly pieces, optimize them, then dump these into outStrips + SplitUpStripsAndOptimize(allStrips, outStrips, allEdgeInfos, outFaceList); + + //clean up + for(size_t i = 0; i < allStrips.size(); i++) + { + delete allStrips[i]; + } + + for (size_t i = 0; i < allEdgeInfos.size(); i++) + { + NvEdgeInfo *info = allEdgeInfos[i]; + while (info != NULL) + { + NvEdgeInfo *next = (size_t(info->m_v0) == i ? info->m_nextV0 : info->m_nextV1); + info->Unref(); + info = next; + } + } + +} + + +bool NvStripifier::IsDegenerate(const NvFaceInfo* face) +{ + if(face->m_v0 == face->m_v1) + return true; + else if(face->m_v0 == face->m_v2) + return true; + else if(face->m_v1 == face->m_v2) + return true; + else + return false; +} + +bool NvStripifier::IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2) +{ + if(v0 == v1) + return true; + else if(v0 == v2) + return true; + else if(v1 == v2) + return true; + else + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// SplitUpStripsAndOptimize() +// +// Splits the input vector of strips (allBigStrips) into smaller, cache friendly pieces, then +// reorders these pieces to maximize cache hits +// The final strips are output through outStrips +// +void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, + NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList) +{ + int threshold = cacheSize; + NvStripInfoVec tempStrips; + + //split up strips into threshold-sized pieces + for(size_t i = 0; i < allStrips.size(); i++) + { + NvStripInfo* currentStrip; + NvStripStartInfo startInfo(NULL, NULL, false); + + int actualStripSize = 0; + for(size_t j = 0; j < allStrips[i]->m_faces.size(); ++j) + { + if( !IsDegenerate(allStrips[i]->m_faces[j]) ) + actualStripSize++; + } + + if(actualStripSize /*allStrips[i]->m_faces.size()*/ > threshold) + { + + int numTimes = actualStripSize /*allStrips[i]->m_faces.size()*/ / threshold; + int numLeftover = actualStripSize /*allStrips[i]->m_faces.size()*/ % threshold; + + int degenerateCount = 0; + int j; + for(j = 0; j < numTimes; j++) + { + currentStrip = new NvStripInfo(startInfo, 0, -1); + + int faceCtr = j*threshold + degenerateCount; + bool bFirstTime = true; + while(faceCtr < threshold+(j*threshold)+degenerateCount) + { + if(IsDegenerate(allStrips[i]->m_faces[faceCtr])) + { + degenerateCount++; + + //last time or first time through, no need for a degenerate + if( (((faceCtr + 1) != threshold+(j*threshold)+degenerateCount) || + ((j == numTimes - 1) && (numLeftover < 4) && (numLeftover > 0))) && + !bFirstTime) + { + currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); + } + else + { + //but, we do need to delete the degenerate, if it's marked fake, to avoid leaking + if(allStrips[i]->m_faces[faceCtr]->m_bIsFake) + { + delete allStrips[i]->m_faces[faceCtr], allStrips[i]->m_faces[faceCtr] = NULL; + } + ++faceCtr; + } + } + else + { + currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); + bFirstTime = false; + } + } + /* + for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++) + { + currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]); + } + */ + if(j == numTimes - 1) //last time through + { + if( (numLeftover < 4) && (numLeftover > 0) ) //way too small + { + //just add to last strip + int ctr = 0; + while(ctr < numLeftover) + { + IsDegenerate( allStrips[i]->m_faces[faceCtr] ) ? ++degenerateCount : ++ctr; + currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]); + } + numLeftover = 0; + } + } + tempStrips.push_back(currentStrip); + } + + int leftOff = j * threshold + degenerateCount; + + if(numLeftover != 0) + { + currentStrip = new NvStripInfo(startInfo, 0, -1); + + int ctr = 0; + bool bFirstTime = true; + while(ctr < numLeftover) + { + if( !IsDegenerate(allStrips[i]->m_faces[leftOff]) ) + { + ctr++; + bFirstTime = false; + currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); + } + else if(!bFirstTime) + currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); + else + { + //don't leak + if(allStrips[i]->m_faces[leftOff]->m_bIsFake) + { + delete allStrips[i]->m_faces[leftOff], allStrips[i]->m_faces[leftOff] = NULL; + } + + leftOff++; + } + } + /* + for(int k = 0; k < numLeftover; k++) + { + currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]); + } + */ + + tempStrips.push_back(currentStrip); + } + } + else + { + //we're not just doing a tempStrips.push_back(allBigStrips[i]) because + // this way we can delete allBigStrips later to free the memory + currentStrip = new NvStripInfo(startInfo, 0, -1); + + for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++) + currentStrip->m_faces.push_back(allStrips[i]->m_faces[j]); + + tempStrips.push_back(currentStrip); + } + } + + //add small strips to face list + NvStripInfoVec tempStrips2; + RemoveSmallStrips(tempStrips, tempStrips2, outFaceList); + + outStrips.clear(); + //screw optimization for now +// for(i = 0; i < tempStrips.size(); ++i) +// outStrips.push_back(tempStrips[i]); + + if(tempStrips2.size() != 0) + { + //Optimize for the vertex cache + VertexCache* vcache = new VertexCache(cacheSize); + + float bestNumHits = -1.0f; + float numHits; + int bestIndex = -1; + //bool done = false; + + int firstIndex = 0; + float minCost = 10000.0f; + + for(size_t i = 0; i < tempStrips2.size(); i++) + { + int numNeighbors = 0; + + //find strip with least number of neighbors per face + for(size_t j = 0; j < tempStrips2[i]->m_faces.size(); j++) + { + numNeighbors += NumNeighbors(tempStrips2[i]->m_faces[j], edgeInfos); + } + + float currCost = (float)numNeighbors / (float)tempStrips2[i]->m_faces.size(); + if(currCost < minCost) + { + minCost = currCost; + firstIndex = i; + } + } + + UpdateCacheStrip(vcache, tempStrips2[firstIndex]); + outStrips.push_back(tempStrips2[firstIndex]); + + tempStrips2[firstIndex]->visited = true; + + bool bWantsCW = (tempStrips2[firstIndex]->m_faces.size() % 2) == 0; + + //this n^2 algo is what slows down stripification so much.... + // needs to be improved + while(1) + { + bestNumHits = -1.0f; + + //find best strip to add next, given the current cache + for(size_t i = 0; i < tempStrips2.size(); i++) + { + if(tempStrips2[i]->visited) + continue; + + numHits = CalcNumHitsStrip(vcache, tempStrips2[i]); + if(numHits > bestNumHits) + { + bestNumHits = numHits; + bestIndex = i; + } + else if(numHits >= bestNumHits) + { + //check previous strip to see if this one requires it to switch polarity + NvStripInfo *strip = tempStrips2[i]; + int nStripFaceCount = strip->m_faces.size(); + + NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); + + // If there is a second face, reorder vertices such that the + // unique vertex is first + if (nStripFaceCount > 1) + { + int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); + if (nUnique == tFirstFace.m_v1) + { + SWAP(tFirstFace.m_v0, tFirstFace.m_v1); + } + else if (nUnique == tFirstFace.m_v2) + { + SWAP(tFirstFace.m_v0, tFirstFace.m_v2); + } + + // If there is a third face, reorder vertices such that the + // shared vertex is last + if (nStripFaceCount > 2) + { + int nShared0, nShared1; + GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1); + if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) ) + { + SWAP(tFirstFace.m_v1, tFirstFace.m_v2); + } + } + } + + // Check CW/CCW ordering + if (bWantsCW == IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1)) + { + //I like this one! + bestIndex = i; + } + } + } + + if(bestNumHits == -1.0f) + break; + tempStrips2[bestIndex]->visited = true; + UpdateCacheStrip(vcache, tempStrips2[bestIndex]); + outStrips.push_back(tempStrips2[bestIndex]); + bWantsCW = (tempStrips2[bestIndex]->m_faces.size() % 2 == 0) ? bWantsCW : !bWantsCW; + } + + delete vcache; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// UpdateCacheStrip() +// +// Updates the input vertex cache with this strip's vertices +// +void NvStripifier::UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip) +{ + for(size_t i = 0; i < strip->m_faces.size(); ++i) + { + if(!vcache->InCache(strip->m_faces[i]->m_v0)) + vcache->AddEntry(strip->m_faces[i]->m_v0); + + if(!vcache->InCache(strip->m_faces[i]->m_v1)) + vcache->AddEntry(strip->m_faces[i]->m_v1); + + if(!vcache->InCache(strip->m_faces[i]->m_v2)) + vcache->AddEntry(strip->m_faces[i]->m_v2); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// UpdateCacheFace() +// +// Updates the input vertex cache with this face's vertices +// +void NvStripifier::UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face) +{ + if(!vcache->InCache(face->m_v0)) + vcache->AddEntry(face->m_v0); + + if(!vcache->InCache(face->m_v1)) + vcache->AddEntry(face->m_v1); + + if(!vcache->InCache(face->m_v2)) + vcache->AddEntry(face->m_v2); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// CalcNumHitsStrip() +// +// returns the number of cache hits per face in the strip +// +float NvStripifier::CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip) +{ + int numHits = 0; + int numFaces = 0; + + for(size_t i = 0; i < strip->m_faces.size(); i++) + { + if(vcache->InCache(strip->m_faces[i]->m_v0)) + ++numHits; + + if(vcache->InCache(strip->m_faces[i]->m_v1)) + ++numHits; + + if(vcache->InCache(strip->m_faces[i]->m_v2)) + ++numHits; + + numFaces++; + } + + return ((float)numHits / (float)numFaces); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// CalcNumHitsFace() +// +// returns the number of cache hits in the face +// +int NvStripifier::CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face) +{ + int numHits = 0; + + if(vcache->InCache(face->m_v0)) + numHits++; + + if(vcache->InCache(face->m_v1)) + numHits++; + + if(vcache->InCache(face->m_v2)) + numHits++; + + return numHits; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// NumNeighbors() +// +// Returns the number of neighbors that this face has +// +int NvStripifier::NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec) +{ + int numNeighbors = 0; + + if(FindOtherFace(edgeInfoVec, face->m_v0, face->m_v1, face) != NULL) + { + numNeighbors++; + } + + if(FindOtherFace(edgeInfoVec, face->m_v1, face->m_v2, face) != NULL) + { + numNeighbors++; + } + + if(FindOtherFace(edgeInfoVec, face->m_v2, face->m_v0, face) != NULL) + { + numNeighbors++; + } + + return numNeighbors; +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// AvgStripSize() +// +// Finds the average strip size of the input vector of strips +// +float NvStripifier::AvgStripSize(const NvStripInfoVec &strips){ + int sizeAccum = 0; + int numStrips = strips.size(); + for (int i = 0; i < numStrips; i++){ + NvStripInfo *strip = strips[i]; + sizeAccum += strip->m_faces.size(); + sizeAccum -= strip->m_numDegenerates; + } + return ((float)sizeAccum) / ((float)numStrips); +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// FindAllStrips() +// +// Does the stripification, puts output strips into vector allStrips +// +// Works by setting runnning a number of experiments in different areas of the mesh, and +// accepting the one which results in the longest strips. It then accepts this, and moves +// on to a different area of the mesh. We try to jump around the mesh some, to ensure that +// large open spans of strips get generated. +// +void NvStripifier::FindAllStrips(NvStripInfoVec &allStrips, + NvFaceInfoVec &allFaceInfos, + NvEdgeInfoVec &allEdgeInfos, + int numSamples){ + // the experiments + int experimentId = 0; + int stripId = 0; + bool done = false; + + int loopCtr = 0; + + while (!done) + { + loopCtr++; + + // + // PHASE 1: Set up numSamples * numEdges experiments + // + NvStripInfoVec *experiments = new NvStripInfoVec [numSamples * 6]; + int experimentIndex = 0; + std::set <NvFaceInfo*> resetPoints; + for (int i = 0; i < numSamples; i++) + { + + // Try to find another good reset point. + // If there are none to be found, we are done + NvFaceInfo *nextFace = FindGoodResetPoint(allFaceInfos, allEdgeInfos); + if (nextFace == NULL){ + done = true; + break; + } + // If we have already evaluated starting at this face in this slew + // of experiments, then skip going any further + else if (resetPoints.find(nextFace) != resetPoints.end()){ + continue; + } + + // trying it now... + resetPoints.insert(nextFace); + + // otherwise, we shall now try experiments for starting on the 01,12, and 20 edges + assert(nextFace->m_stripId < 0); + + // build the strip off of this face's 0-1 edge + NvEdgeInfo *edge01 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1); + NvStripInfo *strip01 = new NvStripInfo(NvStripStartInfo(nextFace, edge01, true), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip01); + + // build the strip off of this face's 1-0 edge + NvEdgeInfo *edge10 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1); + NvStripInfo *strip10 = new NvStripInfo(NvStripStartInfo(nextFace, edge10, false), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip10); + + // build the strip off of this face's 1-2 edge + NvEdgeInfo *edge12 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2); + NvStripInfo *strip12 = new NvStripInfo(NvStripStartInfo(nextFace, edge12, true), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip12); + + // build the strip off of this face's 2-1 edge + NvEdgeInfo *edge21 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2); + NvStripInfo *strip21 = new NvStripInfo(NvStripStartInfo(nextFace, edge21, false), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip21); + + // build the strip off of this face's 2-0 edge + NvEdgeInfo *edge20 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0); + NvStripInfo *strip20 = new NvStripInfo(NvStripStartInfo(nextFace, edge20, true), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip20); + + // build the strip off of this face's 0-2 edge + NvEdgeInfo *edge02 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0); + NvStripInfo *strip02 = new NvStripInfo(NvStripStartInfo(nextFace, edge02, false), stripId++, experimentId++); + experiments[experimentIndex++].push_back(strip02); + } + + // + // PHASE 2: Iterate through that we setup in the last phase + // and really build each of the strips and strips that follow to see how + // far we get + // + int numExperiments = experimentIndex; + for (int i = 0; i < numExperiments; i++){ + + // get the strip set + + // build the first strip of the list + experiments[i][0]->Build(allEdgeInfos, allFaceInfos); + int experimentId = experiments[i][0]->m_experimentId; + + NvStripInfo *stripIter = experiments[i][0]; + NvStripStartInfo startInfo(NULL, NULL, false); + while (FindTraversal(allFaceInfos, allEdgeInfos, stripIter, startInfo)){ + + // create the new strip info + stripIter = new NvStripInfo(startInfo, stripId++, experimentId); + + // build the next strip + stripIter->Build(allEdgeInfos, allFaceInfos); + + // add it to the list + experiments[i].push_back(stripIter); + } + } + + // + // Phase 3: Find the experiment that has the most promise + // + int bestIndex = 0; + double bestValue = 0; + for (int i = 0; i < numExperiments; i++) + { + const float avgStripSizeWeight = 1.0f; + //const float numTrisWeight = 0.0f; + const float numStripsWeight = 0.0f; + float avgStripSize = AvgStripSize(experiments[i]); + float numStrips = (float) experiments[i].size(); + float value = avgStripSize * avgStripSizeWeight + (numStrips * numStripsWeight); + //float value = 1.f / numStrips; + //float value = numStrips * avgStripSize; + + if (value > bestValue) + { + bestValue = value; + bestIndex = i; + } + } + + // + // Phase 4: commit the best experiment of the bunch + // + CommitStrips(allStrips, experiments[bestIndex]); + + // and destroy all of the others + for (int i = 0; i < numExperiments; i++) + { + if (i != bestIndex) + { + int numStrips = experiments[i].size(); + for (int j = 0; j < numStrips; j++) + { + NvStripInfo* currStrip = experiments[i][j]; + //delete all bogus faces in the experiments + for (size_t k = 0; k < currStrip->m_faces.size(); ++k) + { + if(currStrip->m_faces[k]->m_bIsFake) + { + delete currStrip->m_faces[k], currStrip->m_faces[k] = NULL; + } + } + delete currStrip, currStrip = NULL, experiments[i][j] = NULL; + } + } + } + + // delete the array that we used for all experiments + delete [] experiments; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +// CountRemainingTris() +// +// This will count the number of triangles left in the +// strip list starting at iter and finishing up at end +// +int NvStripifier::CountRemainingTris(std::list<NvStripInfo*>::iterator iter, + std::list<NvStripInfo*>::iterator end){ + int count = 0; + while (iter != end){ + count += (*iter)->m_faces.size(); + iter++; + } + return count; +} + diff --git a/NifExport/NvTriStrip/NvTriStripObjects.h b/NifExport/NvTriStrip/NvTriStripObjects.h new file mode 100644 index 0000000..32d90f8 --- /dev/null +++ b/NifExport/NvTriStrip/NvTriStripObjects.h @@ -0,0 +1,248 @@ + +#ifndef NV_TRISTRIP_OBJECTS_H +#define NV_TRISTRIP_OBJECTS_H + +#include <assert.h> +#include <vector> +#include <list> +#include "VertexCache.h" + +//Wrap these types in a namespace +namespace NvTriStrip { + +///////////////////////////////////////////////////////////////////////////////// +// +// Types defined for stripification +// +///////////////////////////////////////////////////////////////////////////////// + +struct MyVertex { + float x, y, z; + float nx, ny, nz; +}; + +typedef MyVertex MyVector; + +struct MyFace { + int v1, v2, v3; + float nx, ny, nz; +}; + + +class NvFaceInfo { +public: + + // vertex indices + NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){ + m_v0 = v0; m_v1 = v1; m_v2 = v2; + m_stripId = -1; + m_testStripId = -1; + m_experimentId = -1; + m_bIsFake = bIsFake; + } + + // data members are left public + int m_v0, m_v1, m_v2; + int m_stripId; // real strip Id + int m_testStripId; // strip Id in an experiment + int m_experimentId; // in what experiment was it given an experiment Id? + bool m_bIsFake; //if true, will be deleted when the strip it's in is deleted +}; + +// nice and dumb edge class that points knows its +// indices, the two faces, and the next edge using +// the lesser of the indices +class NvEdgeInfo { +public: + + // constructor puts 1 ref on us + NvEdgeInfo (int v0, int v1){ + m_v0 = v0; + m_v1 = v1; + m_face0 = NULL; + m_face1 = NULL; + m_nextV0 = NULL; + m_nextV1 = NULL; + + // we will appear in 2 lists. this is a good + // way to make sure we delete it the second time + // we hit it in the edge infos + m_refCount = 2; + + } + + // ref and unref + void Unref () { if (--m_refCount == 0) delete this; } + + // data members are left public + unsigned int m_refCount; + NvFaceInfo *m_face0, *m_face1; + int m_v0, m_v1; + NvEdgeInfo *m_nextV0, *m_nextV1; +}; + + +// This class is a quick summary of parameters used +// to begin a triangle strip. Some operations may +// want to create lists of such items, so they were +// pulled out into a class +class NvStripStartInfo { +public: + NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){ + m_startFace = startFace; + m_startEdge = startEdge; + m_toV1 = toV1; + } + NvFaceInfo *m_startFace; + NvEdgeInfo *m_startEdge; + bool m_toV1; +}; + + +typedef std::vector<NvFaceInfo*> NvFaceInfoVec; +typedef std::list <NvFaceInfo*> NvFaceInfoList; +typedef std::list <NvFaceInfoVec*> NvStripList; +typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec; + +typedef std::vector<short> WordVec; +typedef std::vector<int> IntVec; +typedef std::vector<MyVertex> MyVertexVec; +typedef std::vector<MyFace> MyFaceVec; + +template<class T> +inline void SWAP(T& first, T& second) +{ + T temp = first; + first = second; + second = temp; +} + +// This is a summary of a strip that has been built +class NvStripInfo { +public: + + // A little information about the creation of the triangle strips + NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) : + m_startInfo(startInfo) + { + m_stripId = stripId; + m_experimentId = experimentId; + visited = false; + m_numDegenerates = 0; + } + + // This is an experiment if the experiment id is >= 0 + inline bool IsExperiment () const { return m_experimentId >= 0; } + + inline bool IsInStrip (const NvFaceInfo *faceInfo) const + { + if(faceInfo == NULL) + return false; + + return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId); + } + + bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos); + + // take the given forward and backward strips and combine them together + void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward); + + //returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec + bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face); + + // mark the triangle as taken by this strip + bool IsMarked (NvFaceInfo *faceInfo); + void MarkTriangle(NvFaceInfo *faceInfo); + + // build the strip + void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos); + + // public data members + NvStripStartInfo m_startInfo; + NvFaceInfoVec m_faces; + int m_stripId; + int m_experimentId; + + bool visited; + + int m_numDegenerates; +}; + +typedef std::vector<NvStripInfo*> NvStripInfoVec; + + +//The actual stripifier +class NvStripifier { +public: + + // Constructor + NvStripifier(); + ~NvStripifier(); + + //the target vertex cache size, the structure to place the strips in, and the input indices + void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength, + const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces); + void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips, const bool bRestart, const unsigned int restartVal); + + static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB); + //static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB); + static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1); + + static bool IsDegenerate(const NvFaceInfo* face); + static bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2); + +protected: + + WordVec indices; + int cacheSize; + int minStripLength; + float meshJump; + bool bFirstTimeResetPoint; + + ///////////////////////////////////////////////////////////////////////////////// + // + // Big mess of functions called during stripification + // + ///////////////////////////////////////////////////////////////////////////////// + + //******************** + bool IsMoneyFace(const NvFaceInfo& face); + bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index); + + bool IsCW(NvFaceInfo *faceInfo, int v0, int v1); + bool NextIsCW(const int numIndices); + + static int GetNextIndex(const WordVec &indices, NvFaceInfo *face); + static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1); + static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo); + NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos); + + void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples); + void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList); + void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList); + + bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo); + int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end); + + void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips); + + float AvgStripSize(const NvStripInfoVec &strips); + int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos); + + void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip); + void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face); + float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip); + int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face); + int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec); + + void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex); + bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos); + + // let our strip info classes and the other classes get + // to these protected stripificaton methods if they want + friend class NvStripInfo; +}; + +} //End namespace + +#endif \ No newline at end of file diff --git a/NifExport/NvTriStrip/VertexCache.cpp b/NifExport/NvTriStrip/VertexCache.cpp new file mode 100644 index 0000000..a5f0bad --- /dev/null +++ b/NifExport/NvTriStrip/VertexCache.cpp @@ -0,0 +1,87 @@ + + +#include "VertexCache.h" +using namespace NvTriStrip; + +VertexCache::VertexCache() +{ + VertexCache(16); +} + + +VertexCache::VertexCache(int size) +{ + numEntries = size; + + entries = new int[numEntries]; + + for(int i = 0; i < numEntries; i++) + entries[i] = -1; +} + + +VertexCache::~VertexCache() +{ + delete[] entries; +} + + +int VertexCache::At(int index) +{ + return entries[index]; +} + + +void VertexCache::Set(int index, int value) +{ + entries[index] = value; +} + + +void VertexCache::Clear() +{ + for(int i = 0; i < numEntries; i++) + entries[i] = -1; +} + +void VertexCache::Copy(VertexCache* inVcache) +{ + for(int i = 0; i < numEntries; i++) + { + inVcache->Set(i, entries[i]); + } +} + +bool VertexCache::InCache(int entry) +{ + bool returnVal = false; + + for(int i = 0; i < numEntries; i++) + { + if(entries[i] == entry) + { + returnVal = true; + break; + } + } + + return returnVal; +} + + +int VertexCache::AddEntry(int entry) +{ + int removed; + + removed = entries[numEntries - 1]; + + //push everything right one + for(int i = numEntries - 2; i >= 0; i--) + { + entries[i + 1] = entries[i]; + } + + entries[0] = entry; + + return removed; +} diff --git a/NifExport/NvTriStrip/VertexCache.h b/NifExport/NvTriStrip/VertexCache.h new file mode 100644 index 0000000..dcb075a --- /dev/null +++ b/NifExport/NvTriStrip/VertexCache.h @@ -0,0 +1,31 @@ + +#ifndef VERTEX_CACHE_H + +#define VERTEX_CACHE_H + +namespace NvTriStrip { + +class VertexCache +{ + +public: + VertexCache(int size); + VertexCache(); + ~VertexCache(); + bool InCache(int entry); + int AddEntry(int entry); + void Clear(); + void Copy(VertexCache* inVcache) ; + int At(int index); + void Set(int index, int value); + +private: + + int *entries; + int numEntries; + +}; + +} //End namespace + +#endif diff --git a/NifExport/Strips.cpp b/NifExport/Strips.cpp index 019af36..b418cda 100755 --- a/NifExport/Strips.cpp +++ b/NifExport/Strips.cpp @@ -1,5 +1,7 @@ #include "pch.h" +#include "NvTriStrip/NvTriStrip.h" +using namespace NvTriStrip; /* using namespace triangle_stripper; @@ -85,7 +87,7 @@ void Exporter::strippify(FaceGroup &grp) data[i * 3 + 2] = grp.faces[i][2]; } - PrimitiveGroup * groups = 0; + PrimitiveGroup * groups = 0; unsigned short numGroups = 0; // GF 3+ diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index 6f98c6f..2a356c0 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -228,7 +228,7 @@ bool Exporter::removeUnreferencedBones(NiNodeRef node) { NiAVObjectRef& child = (*itr); bool childRemove = false; - if (child->IsDerivedType(NiNode::TypeConst())) + if (child->IsDerivedType(NiNode::TYPE)) { childRemove = removeUnreferencedBones(StaticCast<NiNode>(child)); } diff --git a/NifFurniture/NifFurniture.cpp b/NifFurniture/NifFurniture.cpp index d80d111..d4f3d5c 100755 --- a/NifFurniture/NifFurniture.cpp +++ b/NifFurniture/NifFurniture.cpp @@ -252,7 +252,12 @@ int NifFurnitureMarker::Display(TimeValue t, INode* inode, ViewExp *vpt, int fla Material *mtl = gw->getMaterial(); DWORD rlim = gw->getRndLimits(); - gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|GW_BACKCULL); + + DWORD newrlim = GW_WIREFRAME|GW_BACKCULL; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + newrlim |= GW_EDGES_ONLY; +#endif + gw->setRndLimits(newrlim); GetMat(t, inode, vpt, m); m.Scale(mFlip); diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp index adb3da6..6e0e27a 100644 --- a/NifImport/ImportAnimation.cpp +++ b/NifImport/ImportAnimation.cpp @@ -11,7 +11,7 @@ HISTORY: *> Copyright (c) 2006, All Rights Reserved. **********************************************************************/ #include "stdafx.h" -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+ +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 # include <IFrameTagManager.h> #endif #include <notetrck.h> @@ -181,7 +181,7 @@ void NifImporter::ClearAnimation() { if (clearAnimation) { -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) { int n = tagMgr->GetTagCount(); @@ -430,7 +430,7 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe } if (addTimeTags) { -#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 +#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) { for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) { tagMgr->CreateNewTag(const_cast<TCHAR*>((*itr).data.c_str()), TimeToFrame(time + (*itr).time), 0, FALSE); @@ -539,7 +539,7 @@ bool AnimationImport::GetTransformData(ControllerLink& lnk, string name, NiKeyfr if (npoints > 3) { - NiKeyframeDataRef data = CreateBlock("NiKeyframeData"); + NiKeyframeDataRef data = CreateNiObject<NiKeyframeData>(); data->SetRotateType(QUADRATIC_KEY); data->SetTranslateType(QUADRATIC_KEY); data->SetScaleType(QUADRATIC_KEY); diff --git a/NifImport/ImportCollision.cpp b/NifImport/ImportCollision.cpp index 53d6aed..22f17b3 100644 --- a/NifImport/ImportCollision.cpp +++ b/NifImport/ImportCollision.cpp @@ -56,10 +56,10 @@ bool NifImporter::ImportCollision(NiNodeRef node) if (collObj) { CollisionImport ci(*this); - if (INode *inode = FindINode(gi, collObj->GetParent())) + if (INode *inode = FindINode(gi, collObj->GetTarget())) { NiObjectRef body = collObj->GetBody(); - if (body->IsDerivedType(bhkRigidBody::TypeConst())) + if (body->IsDerivedType(bhkRigidBody::TYPE)) { ci.ImportRigidBody(bhkRigidBodyRef(body), inode); } @@ -113,15 +113,15 @@ bool CollisionImport::ImportRigidBody(bhkRigidBodyRef body, INode* node) bool CollisionImport::ImportShape(bhkRigidBodyRef body, bhkShapeRef shape, INode* parent) { INode *shapeNode = NULL; - if (shape->IsDerivedType(bhkCapsuleShape::TypeConst())) + if (shape->IsDerivedType(bhkCapsuleShape::TYPE)) { shapeNode = ImportCapsule(body, bhkCapsuleShapeRef(shape), parent); } - else if (shape->IsDerivedType(bhkSphereShape::TypeConst())) + else if (shape->IsDerivedType(bhkSphereShape::TYPE)) { shapeNode = ImportSphere(body, bhkSphereShapeRef(shape), parent); } - else if (shape->IsDerivedType(bhkConvexVerticesShape::TypeConst())) + else if (shape->IsDerivedType(bhkConvexVerticesShape::TYPE)) { shapeNode = ImportConvexVertices(body, bhkConvexVerticesShapeRef(shape), parent); } diff --git a/NifImport/ImportLights.cpp b/NifImport/ImportLights.cpp index a48feb3..ed67650 100644 --- a/NifImport/ImportLights.cpp +++ b/NifImport/ImportLights.cpp @@ -72,7 +72,7 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights) GenLight *ob = NULL; NiLightRef& light = (*itr); - if (light->IsSameType(NiPointLight::TypeConst())){ + if (light->IsSameType(NiPointLight::TYPE)){ ob = CreateLight(gi, light, OMNI_LIGHT); NiPointLightRef ptLight = light; float c = ptLight->GetConstantAttenuation(); @@ -88,12 +88,12 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights) ob->SetDecayType(2); ob->SetAtten(0, ATTEN_START, 4.0f/(l*l)); } - } else if (light->IsSameType(NiDirectionalLight::TypeConst())){ + } else if (light->IsSameType(NiDirectionalLight::TYPE)){ ob = CreateLight(gi, light, DIR_LIGHT); - } else if (light->IsSameType(NiAmbientLight::TypeConst())){ + } else if (light->IsSameType(NiAmbientLight::TYPE)){ ob = CreateLight(gi, light, OMNI_LIGHT); ob->SetAmbientOnly(TRUE); - } else if (light->IsSameType(NiSpotLight::TypeConst())){ + } else if (light->IsSameType(NiSpotLight::TYPE)){ ob = CreateLight(gi, light, FSPOT_LIGHT); } if (INode *n = gi->CreateObjectNode(ob)) { @@ -108,7 +108,7 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights) Quat q = TOQUAT(rot.AsQuaternion()); PosRotScaleNode(n, p, q, scale, prsDefault); - n->Hide(light->GetHidden() ? TRUE : FALSE); + n->Hide(light->GetVisibility() ? FALSE : TRUE ); } ok = true; } diff --git a/NifImport/ImportMeshAndSkin.cpp b/NifImport/ImportMeshAndSkin.cpp index 5a90945..552a76f 100644 --- a/NifImport/ImportMeshAndSkin.cpp +++ b/NifImport/ImportMeshAndSkin.cpp @@ -173,7 +173,7 @@ bool NifImporter::ImportMesh(ImpNode *node, TriObject *o, NiTriBasedGeomRef triG if (INode *parent = GetNode(triGeom->GetParent())) parent->AttachChild(inode, 1); - inode->Hide(triGeom->GetHidden() ? TRUE : FALSE); + inode->Hide(triGeom->GetVisibility() ? FALSE : TRUE); if (enableAutoSmooth){ mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE); @@ -278,7 +278,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom Matrix44 transform = (*itr)->GetLocalTransform(); //Apply the transformations if (transform != Matrix44::IDENTITY) { - for ( uint i = 0; i < subverts.size(); ++i ) + for ( unsigned int i = 0; i < subverts.size(); ++i ) subverts[i] = transform * subverts[i]; } vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) ); @@ -334,7 +334,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom vector<Vector3> subnorms = triGeomData->GetNormals(); Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation(); if (rotation != Matrix44::IDENTITY) { - for ( uint i = 0; i < subnorms.size(); ++i ) + for ( unsigned int i = 0; i < subnorms.size(); ++i ) subnorms[i] = rotation * subnorms[i]; } if (!subnorms.empty()) @@ -410,7 +410,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom // attach child if (INode *parent = GetNode((*itr)->GetParent())) parent->AttachChild(inode, 1); - inode->Hide((*itr)->GetHidden() ? TRUE : FALSE); + inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE); } if (removeDegenerateFaces) mesh.RemoveDegenerateFaces(); @@ -600,8 +600,10 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_sta // and the value always seems to be 4 anyway. I'd also this be more dynamic than hard coded numbers // but I cant figure out the correct values to pass the scripting engine from here so I'm giving up. int numWeightsPerVertex = 4; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ IParamBlock2 *params = skinMod->GetParamBlockByID(2/*advanced*/); params->SetValue(0x7/*bone_Limit*/, 0, numWeightsPerVertex); +#endif // Can get some truly bizarre animations without this in MAX with Civ4 Leaderheads #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+ @@ -655,6 +657,13 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_sta } } + tnode->EvalWorldState(0); + skinMod->DisableModInViews(); + skinMod->EnableModInViews(); +#if VERSION_3DSMAX < ((5000<<16)+(15<<8)+0) // Version 4 + gi->SetCommandPanelTaskMode(TASK_MODE_MODIFY); + gi->SelectNode(tnode); +#endif // Assign the weights for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){ VertexHolder& h = (*itr); diff --git a/NifImport/ImportMtlAndTex.cpp b/NifImport/ImportMtlAndTex.cpp index 2a7e698..7664618 100644 --- a/NifImport/ImportMtlAndTex.cpp +++ b/NifImport/ImportMtlAndTex.cpp @@ -27,7 +27,7 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc) { BitmapManager *bmpMgr = TheManager; if (NiSourceTextureRef texSrc = desc.source){ - string filename = texSrc->GetExternalFileName(); + string filename = texSrc->GetTextureFileName(); if (bmpMgr->CanImport(filename.c_str())){ BitmapTex *bmpTex = NewDefaultBitmapTex(); string name = texSrc->GetName(); @@ -83,13 +83,13 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc) StdMat2 *NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObject) { // Texture - NiMaterialPropertyRef matRef = avObject->GetPropertyByType(NiMaterialProperty::TypeConst()); + NiMaterialPropertyRef matRef = avObject->GetPropertyByType(NiMaterialProperty::TYPE); if (matRef != NULL){ - NiTexturingPropertyRef texRef = avObject->GetPropertyByType(NiTexturingProperty::TypeConst()); - NiWireframePropertyRef wireRef = avObject->GetPropertyByType(NiWireframeProperty::TypeConst()); - NiAlphaPropertyRef alphaRef = avObject->GetPropertyByType(NiAlphaProperty::TypeConst()); - NiStencilPropertyRef stencilRef = avObject->GetPropertyByType(NiStencilProperty::TypeConst()); - NiShadePropertyRef shadeRef = avObject->GetPropertyByType(NiShadeProperty::TypeConst()); + NiTexturingPropertyRef texRef = avObject->GetPropertyByType(NiTexturingProperty::TYPE); + NiWireframePropertyRef wireRef = avObject->GetPropertyByType(NiWireframeProperty::TYPE); + NiAlphaPropertyRef alphaRef = avObject->GetPropertyByType(NiAlphaProperty::TYPE); + NiStencilPropertyRef stencilRef = avObject->GetPropertyByType(NiStencilProperty::TYPE); + NiShadePropertyRef shadeRef = avObject->GetPropertyByType(NiShadeProperty::TYPE); StdMat2 *m = NewDefaultStdMat(); m->SetName(matRef->GetName().c_str()); @@ -120,7 +120,7 @@ StdMat2 *NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avO m->SetWire(value); } if (stencilRef != NULL) { - if (stencilRef->GetDrawMode() == 3 /*DRAW_BOTH*/) { + if (stencilRef->GetFaceDrawMode() == DRAW_BOTH) { BOOL value = TRUE; m->SetTwoSided(value); } @@ -267,22 +267,22 @@ bool NifImporter::ImportCiv4Shader(ImpNode *node, NiAVObjectRef avObject, StdMat setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable); } if (NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props)) { - int TestRef = alphaRef->GetAlphaTestThreshold(); - int srcBlend = alphaRef->GetSourceBlendMode(); - int destBlend = alphaRef->GetDestBlendMode(); - int TestMode = alphaRef->GetTestMode(); - bool AlphaTestEnable = alphaRef->GetAlphaTest(); - bool NoSorter = !alphaRef->GetAlphaSort(); - bool alphaBlend = alphaRef->GetAlphaBlend(); + int TestRef = alphaRef->GetTestThreshold(); + int srcBlend = alphaRef->GetSourceBlendFunc(); + int destBlend = alphaRef->GetSourceBlendFunc (); + int TestMode = alphaRef->GetTestFunc(); + bool AlphaTestEnable = alphaRef->GetTestState(); + bool NoSorter = !alphaRef->GetTriangleSortMode(); + bool alphaBlend = alphaRef->GetBlendState(); int alphaMode = 1; if (!alphaBlend) { alphaMode = 1; // none - } else if (srcBlend == NiAlphaProperty::BM_SRC_ALPHA && destBlend == NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA) { + } else if (srcBlend == NiAlphaProperty::BF_SRC_ALPHA && destBlend == NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA) { alphaMode = 0; // standard or automatic? - } else if (srcBlend == NiAlphaProperty::BM_ONE && destBlend == NiAlphaProperty::BM_ONE) { + } else if (srcBlend == NiAlphaProperty::BF_ONE && destBlend == NiAlphaProperty::BF_ONE) { alphaMode = 3; - } else if (srcBlend == NiAlphaProperty::BM_ZERO && destBlend == NiAlphaProperty::BM_SRC_COLOR) { + } else if (srcBlend == NiAlphaProperty::BF_ZERO && destBlend == NiAlphaProperty::BF_SRC_COLOR) { alphaMode = 4; } else { alphaMode = 5; diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp index e5f5b60..9605290 100644 --- a/NifImport/ImportSkeleton.cpp +++ b/NifImport/ImportSkeleton.cpp @@ -36,7 +36,7 @@ struct NiNodeNameEquivalence : public NumericStringEquivalence void GoToSkeletonBindPosition(vector<NiNodeRef>& blocks) { //Send all skeleton roots to bind position - for (uint i = 0; i < blocks.size(); ++i) { + for (unsigned int i = 0; i < blocks.size(); ++i) { NiNodeRef node = blocks[i]; if ( node != NULL && node->IsSkeletonRoot() ) { node->GoToSkeletonBindPosition(); @@ -481,6 +481,7 @@ INode *NifImporter::CreateBone(const string& name, Point3 startPos, Point3 endPo if (INode *n = result.n) { n->SetName(const_cast<TCHAR*>(name.c_str())); + float len = Length(endPos-startPos); float width = max(minBoneWidth, min(maxBoneWidth, len * boneWidthToLengthRatio)); if (Object* o = n->GetObjectRef()) @@ -573,7 +574,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse) vector<NiAVObjectRef> children = node->GetChildren(); vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children); - NiAVObject::CollisionType cType = node->GetCollision(); + NiAVObject::CollisionType cType = node->GetCollisionMode(); if (children.empty() && name=="Bounding Box") return; @@ -654,13 +655,13 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse) { bool isDummy = ( (uncontrolledDummies && !HasControllerRef(ctrlCount, name)) || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name)) - || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TypeConst())) + || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TYPE)) ); if (wildmatch("Camera*", name)) { if (enableCameras) { if (bone = CreateCamera(name)) { PosRotScaleNode(bone, p, q, scale, prs); - bone->Hide(node->GetHidden() ? TRUE : FALSE); + bone->Hide(node->GetVisibility() ? FALSE : TRUE); } } }else if (isDummy && createNubsForBones) @@ -668,7 +669,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse) else if (bone = CreateBone(name, p, pp, zAxis)) { PosRotScaleNode(bone, p, q, scale, prs); - bone->Hide(node->GetHidden() ? TRUE : FALSE); + bone->Hide(node->GetVisibility() ? FALSE : TRUE); } if (bone) { diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp index b1903c7..3202ae7 100644 --- a/NifImport/MaxNifImport.cpp +++ b/NifImport/MaxNifImport.cpp @@ -38,6 +38,13 @@ class MaxNifImport : public SceneImport { unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301) void ShowAbout(HWND hWnd); // Show DLL's "About..." box int DoImport(const TCHAR *name,ImpInterface *i,Interface *gi, BOOL suppressPrompts=FALSE); // Import file + + SDK_RESERVED_METHOD(1); // russom 02/26/01 + SDK_RESERVED_METHOD(2); // russom 02/26/01 + SDK_RESERVED_METHOD(3); // russom 02/26/01 + SDK_RESERVED_METHOD(4); // russom 02/26/01 + SDK_RESERVED_METHOD(5); // russom 02/26/01 + SDK_RESERVED_METHOD(6); // russom 02/26/01 //Constructor/Destructor MaxNifImport(); @@ -72,17 +79,7 @@ MaxNifImport::MaxNifImport() { Interface *gi = GetCOREInterface(); TCHAR iniName[MAX_PATH]; - if (gi) { - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); - } else { - GetModuleFileName(NULL, iniName, _countof(iniName)); - if (LPTSTR fname = PathFindFileName(iniName)) - fname = NULL; - PathAddBackslash(iniName); - PathAppend(iniName, "plugcfg"); - PathAppend(iniName, "MaxNifTools.ini"); - } + GetIniFileName(iniName); iniFileName = iniName; shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName.c_str()); webSite = GetIniValue<TSTR>("System", "Website", "http://www.niftools.org", iniFileName.c_str()); diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index a49134c..628e43c 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -108,8 +108,7 @@ string NifImporter::GetSkeleton(AppSettings *appSettings) void NifImporter::LoadIniSettings() { TCHAR iniName[MAX_PATH]; - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + GetIniFileName(iniName); this->iniFileName = iniName; iniFileValid = (-1 != _access(iniName, 0)); @@ -283,7 +282,7 @@ bool NifImporter::DoImport() if (isValid()) { - if (root->IsDerivedType(NiNode::TypeConst())) + if (root->IsDerivedType(NiNode::TYPE)) { NiNodeRef rootNode = root; @@ -317,11 +316,11 @@ bool NifImporter::DoImport() } } } - else if (root->IsDerivedType(NiTriShape::TypeConst())) + else if (root->IsDerivedType(NiTriShape::TYPE)) { ok |= ImportMesh(NiTriShapeRef(root)); } - else if (root->IsDerivedType(NiTriStrips::TypeConst())) + else if (root->IsDerivedType(NiTriStrips::TYPE)) { ok |= ImportMesh(NiTriStripsRef(root)); } diff --git a/NifPlugins/DllEntry.cpp b/NifPlugins/DllEntry.cpp index 3beef10..90bc9d0 100644 --- a/NifPlugins/DllEntry.cpp +++ b/NifPlugins/DllEntry.cpp @@ -20,6 +20,7 @@ extern ClassDesc2* GetbhkSphereDesc(); extern ClassDesc2* GetbhkCapsuleDesc(); extern ClassDesc2* GetbhkRigidBodyModifierDesc(); extern ClassDesc2* GetbhkBoxDesc(); +extern ClassDesc* GetDDSLibClassDesc(); enum ClassDescType { @@ -66,19 +67,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) void InitializeLibSettings() { - Interface *gi = GetCOREInterface(); TCHAR iniName[MAX_PATH]; - if (gi) { - LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); - PathCombine(iniName, pluginDir, "MaxNifTools.ini"); - } else { - GetModuleFileName(NULL, iniName, _countof(iniName)); - if (LPTSTR fname = PathFindFileName(iniName)) - *fname = 0; - PathAddBackslash(iniName); - PathAppend(iniName, "plugcfg"); - PathAppend(iniName, "MaxNifTools.ini"); - } + GetIniFileName(iniName); libVersion = GetIniValue("System", "MaxSDKVersion", libVersion, iniName); if (libVersion == 0) libVersion = VERSION_3DSMAX; @@ -110,6 +100,9 @@ void InitializeLibSettings() classDescEnabled[CD_KFExport] = true; classDescriptions[nClasses++] = GetKfExportDesc(); } +#ifdef GAME_VER + classDescriptions[nClasses++] = (ClassDesc2 *)GetDDSLibClassDesc(); +#endif } // This function returns a string that describes the DLL and where the user diff --git a/NifPlugins_VC80.sln b/NifPlugins_VC80.sln index edd1334..edda373 100644 --- a/NifPlugins_VC80.sln +++ b/NifPlugins_VC80.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NIFlib", "..\niflib\niflib.vcproj", "{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Niflib", "..\niflib\niflib.vcproj", "{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{50B67748-0DFB-45B0-BF1F-E80135EE3823}" ProjectSection(SolutionItems) = preProject @@ -17,6 +17,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NifPlugins", "NifPlugins_VC EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug - gmax|Win32 = Debug - gmax|Win32 + Debug - gmax|x64 = Debug - gmax|x64 + Debug - Max 4.2|Win32 = Debug - Max 4.2|Win32 + Debug - Max 4.2|x64 = Debug - Max 4.2|x64 + Debug - Max 4|Win32 = Debug - Max 4|Win32 + Debug - Max 4|x64 = Debug - Max 4|x64 Debug - Max 5|Win32 = Debug - Max 5|Win32 Debug - Max 5|x64 = Debug - Max 5|x64 Debug - Max 6|Win32 = Debug - Max 6|Win32 @@ -27,6 +33,12 @@ Global Debug - Max 8|x64 = Debug - Max 8|x64 Debug - Max 9|Win32 = Debug - Max 9|Win32 Debug - Max 9|x64 = Debug - Max 9|x64 + Release - gmax|Win32 = Release - gmax|Win32 + Release - gmax|x64 = Release - gmax|x64 + Release - Max 4.2|Win32 = Release - Max 4.2|Win32 + Release - Max 4.2|x64 = Release - Max 4.2|x64 + Release - Max 4|Win32 = Release - Max 4|Win32 + Release - Max 4|x64 = Release - Max 4|x64 Release - Max 5|Win32 = Release - Max 5|Win32 Release - Max 5|x64 = Release - Max 5|x64 Release - Max 6|Win32 = Release - Max 6|Win32 @@ -39,36 +51,63 @@ Global Release - Max 9|x64 = Release - Max 9|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.Build.0 = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|x64.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.Build.0 = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|x64.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.Build.0 = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|x64.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.Build.0 = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|x64.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.Build.0 = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|x64.ActiveCfg = Debug - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.Build.0 = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|x64.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.Build.0 = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|x64.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.Build.0 = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|x64.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.Build.0 = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|x64.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.ActiveCfg = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.Build.0 = Release - PCH|Win32 - {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|x64.ActiveCfg = Release - PCH|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.ActiveCfg = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.Build.0 = Debug - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|x64.ActiveCfg = Debug - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|x64.ActiveCfg = Release - DLL|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.ActiveCfg = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.Build.0 = Release - Static|Win32 + {19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|x64.ActiveCfg = Release - DLL|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|Win32.ActiveCfg = Debug - gmax|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|Win32.Build.0 = Debug - gmax|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|x64.ActiveCfg = Debug - Max 5|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|Win32.ActiveCfg = Debug - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|Win32.Build.0 = Debug - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|x64.ActiveCfg = Debug - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|Win32.ActiveCfg = Debug - Max 4|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|Win32.Build.0 = Debug - Max 4|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|x64.ActiveCfg = Debug - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|Win32.ActiveCfg = Debug - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|Win32.Build.0 = Debug - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|x64.ActiveCfg = Debug - Max 5|Win32 @@ -84,6 +123,15 @@ Global {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|Win32.ActiveCfg = Debug - Max 9|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|Win32.Build.0 = Debug - Max 9|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|x64.ActiveCfg = Debug - Max 9|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|Win32.ActiveCfg = Release - gmax|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|Win32.Build.0 = Release - gmax|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|x64.ActiveCfg = Release - Max 5|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|Win32.ActiveCfg = Release - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|Win32.Build.0 = Release - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|x64.ActiveCfg = Release - Max 4.2|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|Win32.ActiveCfg = Release - Max 4|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|Win32.Build.0 = Release - Max 4|Win32 + {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|x64.ActiveCfg = Release - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|Win32.ActiveCfg = Release - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|Win32.Build.0 = Release - Max 5|Win32 {466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|x64.ActiveCfg = Release - Max 5|Win32 diff --git a/NifPlugins_VC80.vcproj b/NifPlugins_VC80.vcproj index 0de9f6b..9716378 100644 --- a/NifPlugins_VC80.vcproj +++ b/NifPlugins_VC80.vcproj @@ -50,7 +50,7 @@ AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" InlineFunctionExpansion="2" AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - 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;NIFLIB_STATIC_LINK" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" @@ -78,18 +78,638 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu" + LinkIncremental="1" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + SetChecksum="true" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" + /> + </Configuration> + <Configuration + Name="Debug - Max 6|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + Optimization="0" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK" + GeneratePreprocessedFile="0" + MinimalRebuild="true" + ExceptionHandling="2" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu" + LinkIncremental="2" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="" + /> + </Configuration> + <Configuration + Name="Release - Max 7|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="0" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + CommandLine="" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK" + StringPooling="true" + ExceptionHandling="2" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu" LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib" + AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + SetChecksum="true" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" + /> + </Configuration> + <Configuration + Name="Debug - Max 7|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + Optimization="0" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + 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;NIFLIB_STATIC_LINK" + GeneratePreprocessedFile="0" + MinimalRebuild="true" + ExceptionHandling="2" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu" + LinkIncremental="2" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="" + /> + </Configuration> + <Configuration + Name="Release - Max 8|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="0" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + CommandLine="" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK" + StringPooling="true" + ExceptionHandling="2" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu" + LinkIncremental="1" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + SetChecksum="true" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" + /> + </Configuration> + <Configuration + Name="Debug - Max 8|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + Optimization="0" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + 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;NIFLIB_STATIC_LINK" + GeneratePreprocessedFile="0" + MinimalRebuild="true" + ExceptionHandling="2" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu" + LinkIncremental="2" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" + ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" + SubSystem="2" + BaseAddress="0x16860000" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + CommandLine="" + /> + </Configuration> + <Configuration + Name="Debug - Max 5|Win32" + OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" + IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" + ConfigurationType="2" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + UseOfMFC="0" + ATLMinimizesCRunTimeLibraryUsage="false" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="true" + SuppressStartupBanner="true" + TargetEnvironment="1" + TypeLibraryName="$(OutDir)NifPlugins.tlb" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + Optimization="0" + InlineFunctionExpansion="2" + AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK" + GeneratePreprocessedFile="0" + MinimalRebuild="true" + ExceptionHandling="2" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + ForceConformanceInForLoopScope="false" + UsePrecompiledHeader="2" + PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" + WarningLevel="3" + SuppressStartupBanner="true" + DebugInformationFormat="3" + CompileAs="0" + DisableSpecificWarnings="4244;4018" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + Culture="1033" + AdditionalIncludeDirectories=".\NifCommon" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/MACHINE:I386" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu" + LinkIncremental="2" + SuppressStartupBanner="true" + AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" SubSystem="2" - OptimizeReferences="2" - EnableCOMDATFolding="2" - SetChecksum="true" BaseAddress="0x16860000" /> <Tool @@ -115,23 +735,25 @@ /> <Tool Name="VCPostBuildEventTool" - CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" + CommandLine="" /> </Configuration> <Configuration - Name="Debug - Max 6|Win32" + Name="Release - Max 5|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="0" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" + CommandLine="" /> <Tool Name="VCXMLDataGeneratorTool" @@ -141,7 +763,7 @@ /> <Tool Name="VCMIDLTool" - PreprocessorDefinitions="_DEBUG" + PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" @@ -150,15 +772,13 @@ <Tool Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" - Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - 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" - MinimalRebuild="true" + AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK" + StringPooling="true" ExceptionHandling="2" - BasicRuntimeChecks="3" - RuntimeLibrary="1" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" ForceConformanceInForLoopScope="false" UsePrecompiledHeader="2" PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" @@ -172,7 +792,7 @@ /> <Tool Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + PreprocessorDefinitions="NDEBUG;NIFPLUGINS" Culture="1033" AdditionalIncludeDirectories=".\NifCommon" /> @@ -182,16 +802,19 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflibd.lib" - OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu" - LinkIncremental="2" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu" + LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib" - IgnoreDefaultLibraryNames="msvcrtd.lib" + AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + SetChecksum="true" BaseAddress="0x16860000" /> <Tool @@ -217,25 +840,24 @@ /> <Tool Name="VCPostBuildEventTool" - CommandLine="" + CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" /> </Configuration> <Configuration - Name="Release - Max 7|Win32" + Name="Debug - Max 9|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" - WholeProgramOptimization="0" + CharacterSet="2" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" - CommandLine="" /> <Tool Name="VCXMLDataGeneratorTool" @@ -245,7 +867,7 @@ /> <Tool Name="VCMIDLTool" - PreprocessorDefinitions="NDEBUG" + PreprocessorDefinitions="_DEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" @@ -254,13 +876,15 @@ <Tool Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" + Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED" - StringPooling="true" - ExceptionHandling="2" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" + AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + 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;NIFLIB_STATIC_LINK" + GeneratePreprocessedFile="0" + MinimalRebuild="true" + ExceptionHandling="1" + BasicRuntimeChecks="3" + RuntimeLibrary="1" ForceConformanceInForLoopScope="false" UsePrecompiledHeader="2" PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" @@ -274,7 +898,7 @@ /> <Tool Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG;NIFPLUGINS" + PreprocessorDefinitions="_DEBUG;NIFPLUGINS" Culture="1033" AdditionalIncludeDirectories=".\NifCommon" /> @@ -284,18 +908,16 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib" - OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu" - LinkIncremental="1" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu" + LinkIncremental="2" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib" + AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" SubSystem="2" - OptimizeReferences="2" - EnableCOMDATFolding="2" - SetChecksum="true" BaseAddress="0x16860000" /> <Tool @@ -321,23 +943,25 @@ /> <Tool Name="VCPostBuildEventTool" - CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" + CommandLine="" /> </Configuration> <Configuration - Name="Debug - Max 7|Win32" + Name="Release - Max 9|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="0" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" + CommandLine="" /> <Tool Name="VCXMLDataGeneratorTool" @@ -347,7 +971,7 @@ /> <Tool Name="VCMIDLTool" - PreprocessorDefinitions="_DEBUG" + PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" @@ -356,15 +980,13 @@ <Tool Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" - Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - 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" - MinimalRebuild="true" + AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK" + StringPooling="true" ExceptionHandling="2" - BasicRuntimeChecks="3" - RuntimeLibrary="1" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" ForceConformanceInForLoopScope="false" UsePrecompiledHeader="2" PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" @@ -378,7 +1000,7 @@ /> <Tool Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG;NIFPLUGINS" + PreprocessorDefinitions="NDEBUG;NIFPLUGINS" Culture="1033" AdditionalIncludeDirectories=".\NifCommon" /> @@ -389,15 +1011,18 @@ Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" - OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu" - LinkIncremental="2" + OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu" + LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib" - IgnoreDefaultLibraryNames="msvcrtd.lib" + AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + SetChecksum="true" BaseAddress="0x16860000" /> <Tool @@ -423,11 +1048,11 @@ /> <Tool Name="VCPostBuildEventTool" - CommandLine="" + CommandLine="set MaxRootDir=$(TargetDir)\..
if exist "%MaxRootDir%\plugcfg" (
if not exist "%MaxRootDir%\plugcfg\MaxNifTools.ini" (
copy "$(ProjectDir)MaxNifTools.ini" "%MaxRootDir%\plugcfg\MaxNifTools.ini"
)
)
xcopy /D /Y /I "$(ProjectDir)MaxNifPlugins_Readme.txt" "$(OutDir)"
xcopy /D /Y /I "$(ProjectDir)MaxNifTools.ini" "$(OutDir)"
xcopy /D /Y /I "$(TargetPath)" "$(OutDir)"
" /> </Configuration> <Configuration - Name="Release - Max 8|Win32" + Name="Release - Max 4|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -461,8 +1086,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED" + AdditionalIncludeDirectories="C:\3dsmax4\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" @@ -490,11 +1115,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib" - OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax4\plugins\NifPlugins.dlu" LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib" + AdditionalLibraryDirectories="C:\3dsmax4\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -531,7 +1157,7 @@ /> </Configuration> <Configuration - Name="Debug - Max 8|Win32" + Name="Debug - Max 4|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -564,8 +1190,8 @@ AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - 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" + AdditionalIncludeDirectories="C:\3dsmax4\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK" GeneratePreprocessedFile="0" MinimalRebuild="true" ExceptionHandling="2" @@ -578,6 +1204,7 @@ SuppressStartupBanner="true" DebugInformationFormat="3" CompileAs="0" + DisableSpecificWarnings="4244;4018" /> <Tool Name="VCManagedResourceCompilerTool" @@ -595,11 +1222,11 @@ Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" - OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu" + OutputFile="C:\3dsmax4\plugins\NifPlugins.dlu" LinkIncremental="2" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib" - IgnoreDefaultLibraryNames="msvcrtd.lib" + AdditionalLibraryDirectories="C:\3dsmax4\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -633,7 +1260,7 @@ /> </Configuration> <Configuration - Name="Debug - Max 5|Win32" + Name="Debug - gmax|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -666,8 +1293,8 @@ AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE" + AdditionalIncludeDirectories="C:\gmax12\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;GAME_VER;NIFLIB_STATIC_LINK" GeneratePreprocessedFile="0" MinimalRebuild="true" ExceptionHandling="2" @@ -698,11 +1325,11 @@ Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" - OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu" + OutputFile="C:\gmax12\plugins\NifPlugins.dlu" LinkIncremental="2" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib" - IgnoreDefaultLibraryNames="msvcrtd.lib" + AdditionalLibraryDirectories="C:\gmax12\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -736,7 +1363,7 @@ /> </Configuration> <Configuration - Name="Release - Max 5|Win32" + Name="Release - gmax|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -770,12 +1397,12 @@ Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES" + AdditionalIncludeDirectories="C:\gmax12\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;GAME_VER;NIFLIB_STATIC_LINK" StringPooling="true" - ExceptionHandling="2" + ExceptionHandling="1" RuntimeLibrary="0" - EnableFunctionLevelLinking="true" + EnableFunctionLevelLinking="false" ForceConformanceInForLoopScope="false" UsePrecompiledHeader="2" PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h" @@ -799,11 +1426,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib" - OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\gmax12\plugins\NifPlugins.dlu" LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib" + AdditionalLibraryDirectories="C:\gmax12\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -840,7 +1468,7 @@ /> </Configuration> <Configuration - Name="Debug - Max 9|Win32" + Name="Debug - Max 4.2|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -873,8 +1501,8 @@ AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" Optimization="0" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - 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" + AdditionalIncludeDirectories="C:\3dsmax42\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK" GeneratePreprocessedFile="0" MinimalRebuild="true" ExceptionHandling="2" @@ -887,6 +1515,7 @@ SuppressStartupBanner="true" DebugInformationFormat="3" CompileAs="0" + DisableSpecificWarnings="4244;4018" /> <Tool Name="VCManagedResourceCompilerTool" @@ -903,12 +1532,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib_debug.lib" - OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax42\plugins\NifPlugins.dlu" LinkIncremental="2" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib" - IgnoreDefaultLibraryNames="msvcrtd.lib" + AdditionalLibraryDirectories="C:\3dsmax42\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -942,7 +1571,7 @@ /> </Configuration> <Configuration - Name="Release - Max 9|Win32" + Name="Release - Max 4.2|Win32" OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\" IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\" ConfigurationType="2" @@ -976,8 +1605,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/LD /Zm200 /FI"$(ProjectDir)NifPlugins\pch.h"" InlineFunctionExpansion="2" - AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED" + AdditionalIncludeDirectories="C:\3dsmax42\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK" StringPooling="true" ExceptionHandling="2" RuntimeLibrary="0" @@ -1005,11 +1634,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib" - OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu" + AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib" + OutputFile="C:\3dsmax42\plugins\NifPlugins.dlu" LinkIncremental="1" SuppressStartupBanner="true" - AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib" + AdditionalLibraryDirectories="C:\3dsmax42\maxsdk\lib;..\niflib\lib" + IgnoreDefaultLibraryNames="" ModuleDefinitionFile=".\NifPlugins\NifPlugins.def" GenerateDebugInformation="true" ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb" @@ -1104,6 +1734,762 @@ > </File> </Filter> + <Filter + Name="dds" + > + <File + RelativePath=".\NifProps\dds\dds.cpp" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\NifProps\dds\dds.h" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\NifProps\dds\dds.rc" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCResourceCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\NifProps\dds\ddsres.h" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\NifProps\dds\dxtlib.h" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\NifProps\dds\veroverrides.h" + > + <FileConfiguration + Name="Release - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 6|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 7|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 8|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 5|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 9|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + </File> + </Filter> </Filter> <Filter Name="NifFurniture" @@ -1216,6 +2602,34 @@ > </File> </Filter> + <Filter + Name="NvTriStrip" + > + <File + RelativePath=".\NifExport\NvTriStrip\NvTriStrip.cpp" + > + </File> + <File + RelativePath=".\NifExport\NvTriStrip\NvTriStrip.h" + > + </File> + <File + RelativePath=".\NifExport\NvTriStrip\NvTriStripObjects.cpp" + > + </File> + <File + RelativePath=".\NifExport\NvTriStrip\NvTriStripObjects.h" + > + </File> + <File + RelativePath=".\NifExport\NvTriStrip\VertexCache.cpp" + > + </File> + <File + RelativePath=".\NifExport\NvTriStrip\VertexCache.h" + > + </File> + </Filter> </Filter> <Filter Name="NifCommon" @@ -1401,6 +2815,60 @@ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" /> </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> </File> <File RelativePath=".\NifPlugins\NifPlugins.rc" @@ -1489,6 +2957,54 @@ UsePrecompiledHeader="1" /> </FileConfiguration> + <FileConfiguration + Name="Release - Max 4|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - gmax|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - gmax|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug - Max 4.2|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> + <FileConfiguration + Name="Release - Max 4.2|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="1" + /> + </FileConfiguration> </File> <File RelativePath=".\NifPlugins\pch.h" diff --git a/NifProps/bhkBoxObj.cpp b/NifProps/bhkBoxObj.cpp index 9079331..0415051 100644 --- a/NifProps/bhkBoxObj.cpp +++ b/NifProps/bhkBoxObj.cpp @@ -798,7 +798,13 @@ int bhkBoxObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags) m = inode->GetObjectTM(t); gw->setTransform(m); DWORD rlim = gw->getRndLimits(); - gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|GW_Z_BUFFER); + + DWORD newrlim = GW_WIREFRAME|GW_Z_BUFFER; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + newrlim |= GW_EDGES_ONLY; +#endif + gw->setRndLimits(newrlim); + if (inode->Selected()) gw->setColor( LINE_COLOR, GetSelColor()); else if(!inode->IsFrozen() && !inode->Dependent()) diff --git a/NifProps/bhkCapsuleObj.cpp b/NifProps/bhkCapsuleObj.cpp index 4e98bcd..6fa759a 100644 --- a/NifProps/bhkCapsuleObj.cpp +++ b/NifProps/bhkCapsuleObj.cpp @@ -680,7 +680,13 @@ int bhkCapsuleObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags m = inode->GetObjectTM(t); gw->setTransform(m); DWORD rlim = gw->getRndLimits(); - gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/); + + DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + newrlim |= GW_EDGES_ONLY; +#endif + gw->setRndLimits(newrlim); + if (inode->Selected()) gw->setColor( LINE_COLOR, GetSelColor()); else if(!inode->IsFrozen() && !inode->Dependent()) diff --git a/NifProps/bhkRigidBodyModifer.cpp b/NifProps/bhkRigidBodyModifer.cpp index 48c50f3..9dd47f8 100644 --- a/NifProps/bhkRigidBodyModifer.cpp +++ b/NifProps/bhkRigidBodyModifer.cpp @@ -748,7 +748,12 @@ int bhkRigidBodyModifier::Display(TimeValue t, INode* inode, ViewExp *vpt, int f m = inode->GetObjectTM(t); gw->setTransform(m); DWORD rlim = gw->getRndLimits(); - gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/); + + DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + newrlim |= GW_EDGES_ONLY; +#endif + gw->setRndLimits(newrlim); //UpdateMesh(t); gw->setMaterial(swMtl); diff --git a/NifProps/bhkSphereObj.cpp b/NifProps/bhkSphereObj.cpp index f0ac610..89ecd25 100644 --- a/NifProps/bhkSphereObj.cpp +++ b/NifProps/bhkSphereObj.cpp @@ -591,7 +591,13 @@ int bhkSphereObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags) m = inode->GetObjectTM(t); gw->setTransform(m); DWORD rlim = gw->getRndLimits(); - gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/); + + DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/; +#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ + newrlim |= GW_EDGES_ONLY; +#endif + gw->setRndLimits(newrlim); + if (inode->Selected()) gw->setColor( LINE_COLOR, GetSelColor()); else if(!inode->IsFrozen() && !inode->Dependent()) diff --git a/NifProps/dds/ConvertColor.h b/NifProps/dds/ConvertColor.h new file mode 100644 index 0000000..c334b4c --- /dev/null +++ b/NifProps/dds/ConvertColor.h @@ -0,0 +1,349 @@ +#pragma once +#include "tPixel.h" + +namespace nv +{ + +template < class T > inline T Min(const T &x, const T &y) +{ + if (x < y) + return x; + else + return y; +} +template < class T > inline T Max(const T &x, const T &y) +{ + if (x < y) + return y; + else + return x; +} + + + +} + + +typedef unsigned short nvhalf; + +union nv_half_data +{ + unsigned short bits; + struct + { + unsigned long m : 10; + unsigned long e : 5; + unsigned long s : 1; + } ieee; +}; + +union nv_ieee_single +{ + float f; + struct { + unsigned long m : 23; + unsigned long e : 8; + unsigned long s : 1; + } ieee; +}; + + +class nvColorConvert +{ +public: + + void RGBAToFloat(const RGBAImage & srcImage, + fpImage & dstImage); + + void RGBAToFloat(const RGBAMipMappedImage & srcMIPImage, + fpMipMappedImage & dstMIPImage); + + + void FloatToRGBA(const fpImage & srcImage, + RGBAImage & dstImage); + + void FloatToRGBA(const fpMipMappedImage & srcMIPImage, + RGBAMipMappedImage & dstMIPImage); + + fpPixel RGBEtoFloat(int r, int g, int b, int e); + + + // photoshop import export + float PSSignedToFloat(int pixel, int depth, int plane); + float PSUnsignedToFloat(int pixel, int depth); + + int FloatToUnsignedPS(float pixel, int depth); + int FloatToSignedPS(float pixel, int depth, int plane); + + // format to float + static float UnsignedToFloat(int channel); // unsigned, 8 bits + static float UnsignedToFloat(int channel, int nBits); // unsigned + static float SignedToFloat(int channel); // 8 bits + static float SignedToFloat(int channel, int nBits); + + + static void RGBAToFloat(int r, int g, int b, int a, fpPixel & fp) + { + fp.r = UnsignedToFloat(r); + fp.g = UnsignedToFloat(g); + fp.b = UnsignedToFloat(b); + fp.a = UnsignedToFloat(a); + } + + + static void RGBAToFloat( const rgba_t & inColor, fpPixel & fp) + { + + fp.r = UnsignedToFloat(inColor.r); + fp.g = UnsignedToFloat(inColor.g); + fp.b = UnsignedToFloat(inColor.b); + fp.a = UnsignedToFloat(inColor.a); + } + + + static void RGBEToFloat(fpPixel & fp, const rgba_t & rgbe); + static void RGBEToFloat(float &r, float & g, float & b, const rgba_t & rgbe); + + + + + static float HalfToFloat(nvhalf val) + { + nv_half_data h; + //h.bits = val.value_bits; + h.bits = val; + nv_ieee_single sng; + sng.ieee.s = h.ieee.s; + + // handle special cases + if ( (h.ieee.e==0) && (h.ieee.m==0) ) + { // zero + sng.ieee.m=0; + sng.ieee.e=0; + } + else if ( (h.ieee.e==0) && (h.ieee.m!=0) ) + { + // denorm -- denorm half will fit in non-denorm single + const float half_denorm = (1.0f/16384.0f); // 2^-14 + float mantissa = ((float)(h.ieee.m)) / 1024.0f; + float sgn = (h.ieee.s)? -1.0f :1.0f; + sng.f = sgn*mantissa*half_denorm; + } + else if ( (h.ieee.e==31) && (h.ieee.m==0) ) + { // infinity + sng.ieee.e = 0xff; + sng.ieee.m = 0; + } + else if ( (h.ieee.e==31) && (h.ieee.m!=0) ) + { // NaN + sng.ieee.e = 0xff; + sng.ieee.m = 1; + } + else + { + sng.ieee.e = h.ieee.e+112; + sng.ieee.m = (h.ieee.m << 13); + } + + return sng.f; + } + + + + /// float to format + static unsigned long FloatToUnsigned(float channel); // 8 bits + static unsigned long FloatToUnsigned(float channel, int nBits); + + static long FloatToSigned(float channel); // 8 bits + static long FloatToSigned(float channel, int nBits); + + + + + static unsigned long NormalToUnsigned(float inColor ) + { + return FloatToUnsigned(inColor * 0.5f + 0.5f); + } + + static unsigned long NormalToUnsigned(float inColor, int nBits ) + { + return FloatToUnsigned(inColor * 0.5f + 0.5f, nBits); + } + + static void NormalToRGBA(const fpPixel & inColor, rgba_t & outColor ) + { + outColor.r = (unsigned char)NormalToUnsigned(inColor.r); + outColor.g = (unsigned char)NormalToUnsigned(inColor.g); + outColor.b = (unsigned char)NormalToUnsigned(inColor.b); + outColor.a = (unsigned char)NormalToUnsigned(inColor.a); + + } + + static void FloatToRGBA(const fpPixel & inColor, rgba_t & p ) + { + p.r = (unsigned char)FloatToUnsigned(inColor.r); + p.g = (unsigned char)FloatToUnsigned(inColor.g); + p.b = (unsigned char)FloatToUnsigned(inColor.b); + p.a = (unsigned char)FloatToUnsigned(inColor.a); + + } + + static void FloatToBGRA(const fpPixel & inColor, unsigned long & outColor ) + { + unsigned int r = FloatToUnsigned(inColor.r); + unsigned int g = FloatToUnsigned(inColor.g); + unsigned int b = FloatToUnsigned(inColor.b); + unsigned int a = FloatToUnsigned(inColor.a); + + outColor = (a << 24) | (r << 16) | (g << 8) | b; + + } + + + + static void FloatToBGRA(float r, float g, float b, float a, unsigned long & outColor ) + { + unsigned int ri = FloatToUnsigned(r); + unsigned int gi = FloatToUnsigned(g); + unsigned int bi = FloatToUnsigned(b); + unsigned int ai = FloatToUnsigned(a); + + outColor = (ai << 24) | (ri << 16) | (gi << 8) | bi; + } + + static void FloatToQ8W8V8U8(const fpPixel & inColor, q8w8v8u8_t & outColor ) + { + outColor.q = (char)FloatToSigned(inColor.r); + outColor.v = (char)FloatToSigned(inColor.g); + outColor.w = (char)FloatToSigned(inColor.b); + outColor.u = (char)FloatToSigned(inColor.a); + + } + + + static void FloatToU16V16(float u, float v, v16u16_t & outColor ) + { + outColor.u = (short)FloatToSigned(u, 16); + outColor.v = (short)FloatToSigned(v, 16); + } + + + static void FloatToR12G12B8(const fpPixel & inColor, r12g12b8_t & outColor ) + { + outColor.r = FloatToUnsigned(inColor.r, 12); + outColor.g = FloatToUnsigned(inColor.g, 12); + outColor.b = FloatToUnsigned(inColor.b, 8); + } + + static void NormalToR12G12B8(const fpPixel & inColor, r12g12b8_t & outColor ) + { + outColor.r = FloatToUnsigned(inColor.r * 0.5f + 0.5f, 12); + outColor.g = FloatToUnsigned(inColor.g * 0.5f + 0.5f, 12); + outColor.b = FloatToUnsigned(inColor.b * 0.5f + 0.5f, 8); + } + + + + + static float FloatToRGBE_Alpha(const fpPixel & fp); + + static void FloatToRGBE(rgba_t & rgbe, const float &r, const float & g, const float & b ); + static void FloatToRGBE(rgba_t * rgbe, const float &r, const float & g, const float & b ); + + static void FloatToRGBE(fpPixel & rgbe, const fpPixel & fp); + static void FloatToRGBE(rgba_t & rgbe, const fpPixel & fp); + + static unsigned char FloatToRGBE_DXT3Alpha(const fpPixel & fp); + + + + static nvhalf FloatToHalf(float val) + { + nv_ieee_single f; + f.f = val; + nv_half_data h; + + h.ieee.s = f.ieee.s; + + // handle special cases + + //const float half_denorm = (1.0f/16384.0f); + + if ( (f.ieee.e==0) && (f.ieee.m==0) ) + { // zero + h.ieee.m = 0; + h.ieee.e = 0; + } + else if ( (f.ieee.e==0) && (f.ieee.m!=0) ) + { // denorm -- denorm float maps to 0 half + h.ieee.m = 0; + h.ieee.e = 0; + } + else if ( (f.ieee.e==0xff) && (f.ieee.m==0) ) + { + // infinity + h.ieee.m = 0; + h.ieee.e = 31; + } + else if ( (f.ieee.e==0xff) && (f.ieee.m!=0) ) + { + // NaN + h.ieee.m = 1; + h.ieee.e = 31; + } + else + { + // regular number + int new_exp = f.ieee.e-127; + + if (new_exp<-24) + { // this maps to 0 + h.ieee.m = 0; + h.ieee.e = 0; + } + + if (new_exp<-14) + { + // this maps to a denorm + h.ieee.e = 0; + unsigned int exp_val = (unsigned int) (-14 - new_exp); // 2^-exp_val + switch (exp_val) + { + case 0: + //fprintf(stderr, "ftoh: logical error in denorm creation!\n"); + h.ieee.m = 0; + break; + case 1: h.ieee.m = 512 + (f.ieee.m>>14); break; + case 2: h.ieee.m = 256 + (f.ieee.m>>15); break; + case 3: h.ieee.m = 128 + (f.ieee.m>>16); break; + case 4: h.ieee.m = 64 + (f.ieee.m>>17); break; + case 5: h.ieee.m = 32 + (f.ieee.m>>18); break; + case 6: h.ieee.m = 16 + (f.ieee.m>>19); break; + case 7: h.ieee.m = 8 + (f.ieee.m>>20); break; + case 8: h.ieee.m = 4 + (f.ieee.m>>21); break; + case 9: h.ieee.m = 2 + (f.ieee.m>>22); break; + case 10: h.ieee.m = 1; break; + } + } + else if (new_exp>15) + { // map this value to infinity + h.ieee.m = 0; + h.ieee.e = 31; + } + else + { + h.ieee.e = new_exp+15; + h.ieee.m = (f.ieee.m >> 13); + } + } + + return (*(nvhalf*)(&h.bits)); + } + + + +}; + + + + diff --git a/NifProps/dds/dds.cpp b/NifProps/dds/dds.cpp new file mode 100644 index 0000000..85fbc37 --- /dev/null +++ b/NifProps/dds/dds.cpp @@ -0,0 +1,774 @@ +// File ....: dds.cpp +// ------------------ +// Author...: Sean Palmer +// Date ....: April 2001 +// Descr....: DDS File I/O Module + +//-- Include files + +#include <max.h> +#include <bmmlib.h> +#include <pixelbuf.h> +#include "dds.h" +#include "ddsres.h" + +#include <stdio.h> + +#include "dxtlib.h" + +//extern "C" FILE _iob[3] = {NULL, NULL, NULL}; + +extern HINSTANCE hInstance; + +static FILE* ghFile=NULL; + +void WriteDTXnFile(DWORD count, void *buffer) +{ + fwrite(buffer, count, 1, ghFile); +} + +void ReadDTXnFile(DWORD count, void *buffer) +{ + fread(buffer, count, 1, ghFile); +} + +//----------------------------------------------------------------------------- +//-- File Class + +class File +{ +public: + FILE *stream; + File (const TCHAR *name, const TCHAR *mode) { stream = _tfopen(name,mode); } + ~File () { Close(); } + void Close() { if(stream) fclose(stream); stream = NULL; } +}; + +//----------------------------------------------------------------------------- +// DDS Class Description + +class DDSClassDesc : public ClassDesc +{ +public: + int IsPublic () { return 1; } + void *Create (BOOL loading=FALSE) { return new BitmapIO_DDS; } + const TCHAR *ClassName () { return GetString(IDS_DDS); } + SClass_ID SuperClassID () { return BMM_IO_CLASS_ID; } + Class_ID ClassID () { return DDS_CLASS_ID; } + const TCHAR *Category () { return GetString(IDS_BITMAP_IO); } +}; + +static DDSClassDesc DDSDesc; + +//----------------------------------------------------------------------------- +// *> AboutCtrlDlgProc() +// + +BOOL CALLBACK AboutCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + CenterWindow(hWnd,GetParent(hWnd)); + return 1; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + EndDialog(hWnd,1); + break; + + case IDCANCEL: + EndDialog(hWnd,0); + break; + + } + return 1; + } + return 0; +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::BitmapIO_DDS() + +BitmapIO_DDS::BitmapIO_DDS() +{ + mParams.outFormat = TF_DXT3 | TF_MIPMAPS; +} + +BitmapIO_DDS::~BitmapIO_DDS () {} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::LongDesc() + +const TCHAR *BitmapIO_DDS::LongDesc() +{ + return GetString(IDS_DDS_FILE); +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::ShortDesc() + +const TCHAR *BitmapIO_DDS::ShortDesc() +{ + return GetString(IDS_DDS); +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::LoadConfigure() + +BOOL BitmapIO_DDS::LoadConfigure (void *ptr) +{ + DDSParams *buf = (DDSParams*) ptr; + memcpy(&mParams, ptr, sizeof(DDSParams)); + return TRUE; +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::SaveConfigure() + +BOOL BitmapIO_DDS::SaveConfigure (void *ptr) +{ + if (ptr) + { + memcpy(ptr, &mParams, sizeof(DDSParams)); + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::ShowAbout() + +void BitmapIO_DDS::ShowAbout(HWND hWnd) +{ + DialogBoxParam( + hInstance, + MAKEINTRESOURCE(IDD_DDS_ABOUT), + hWnd, + (DLGPROC)AboutCtrlDlgProc, + (LPARAM)0); +} + + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::ConfigCtrlDlgProc + +BOOL BitmapIO_DDS::ConfigCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) +{ + + switch (message) + { + case WM_INITDIALOG: + switch (mParams.outFormat & TF_FMTMASK) + { + case TF_DXT1: CheckDlgButton(hWnd, IDC_DDS_DXT1, TRUE); break; + case TF_DXT1_1BitAlpha: CheckDlgButton(hWnd, IDC_DDS_DXT1ALPHA, TRUE); break; + case TF_DXT3: CheckDlgButton(hWnd, IDC_DDS_DXT3, TRUE); break; + case TF_DXT5: CheckDlgButton(hWnd, IDC_DDS_DXT5, TRUE); break; + case TF_RGB4444: CheckDlgButton(hWnd, IDC_DDS_ARGB4444, TRUE); break; + case TF_RGB1555: CheckDlgButton(hWnd, IDC_DDS_ARGB1555, TRUE); break; + case TF_RGB565: CheckDlgButton(hWnd, IDC_DDS_RGB565, TRUE); break; + case TF_RGB8888: CheckDlgButton(hWnd, IDC_DDS_ARGB8888, TRUE); break; + } + CheckDlgButton(hWnd, IDC_DDS_DITHER, (mParams.outFormat & TF_DITHER)!=0); + CheckDlgButton(hWnd, IDC_DDS_MIPMAPS, (mParams.outFormat & TF_MIPMAPS)!=0); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + EndDialog(hWnd,1); + break; + case IDCANCEL: + EndDialog(hWnd,0); + break; + + case IDC_DDS_DXT1: mParams.outFormat = TF_DXT1 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_DXT1ALPHA: mParams.outFormat = TF_DXT1_1BitAlpha | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_DXT3: mParams.outFormat = TF_DXT3 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_DXT5: mParams.outFormat = TF_DXT5 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_ARGB4444: mParams.outFormat = TF_RGB4444 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_ARGB1555: mParams.outFormat = TF_RGB1555 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_RGB565: mParams.outFormat = TF_RGB565 | (mParams.outFormat&~TF_FMTMASK); break; + case IDC_DDS_ARGB8888: mParams.outFormat = TF_RGB8888 | (mParams.outFormat&~TF_FMTMASK); break; + + case IDC_DDS_DITHER: + if (IsDlgButtonChecked(hWnd, IDC_DDS_DITHER)) + mParams.outFormat |= TF_DITHER; + else + mParams.outFormat &= ~TF_DITHER; + break; + + case IDC_DDS_MIPMAPS: + if (IsDlgButtonChecked(hWnd, IDC_DDS_MIPMAPS)) + mParams.outFormat |= TF_MIPMAPS; + else + mParams.outFormat &= ~TF_MIPMAPS; + break; + } + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------------------------- +// #> StaticDialogProc + +BOOL CALLBACK StaticDialogProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l) +{ + BitmapIO_DDS* p; + + if (msg==WM_INITDIALOG) + { + p = (BitmapIO_DDS*)l; + SetWindowLong(hwnd, GWL_USERDATA,l); + } + else + { + if ((p = (BitmapIO_DDS*)GetWindowLong(hwnd, GWL_USERDATA)) == NULL) + return FALSE; + } + return p->ConfigCtrlDlgProc(hwnd,msg,w,l); +} + + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::ShowControl() + +BOOL BitmapIO_DDS::ShowControl(HWND hWnd, DWORD flag) +{ + return DialogBoxParam( + hInstance, + MAKEINTRESOURCE (IDD_DDS_CONFIG), + hWnd, + (DLGPROC) StaticDialogProc, + (LPARAM) this); +} + + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::GetImageInfo() + +BMMRES BitmapIO_DDS::GetImageInfo (BitmapInfo *fbi) +{ + //-- Open DDS File ----------------------------------- + + File file(fbi->Name(), _T("rb")); + + if (!file.stream) + return (ProcessImageIOError(fbi)); + + //-- Read File Header -------------------------------- + + if (!ReadDDSHeader(file.stream)) + return (ProcessImageIOError(fbi,BMMRES_BADFILEHEADER)); + + //-- Update Bitmap Info ------------------------------ + + fbi->SetWidth((WORD)hdr.dwWidth); + fbi->SetHeight((WORD)hdr.dwHeight); + + switch (hdr.dwFourCC) + { + case 0: + switch (hdr.dwRGBBitCount) + { + //case 1: fbi->SetType(BMM_LINE_ART); break; + //case 4: fbi->SetType(BMM_BMP_4); break; + //case 8: fbi->SetType(BMM_PALETTED); break; + case 16: + if (hdr.dwRGBAlphaBitMask) + fbi->SetType(BMM_TRUE_32); + else + fbi->SetType(BMM_TRUE_24); + break; + case 24: fbi->SetType(BMM_TRUE_24); break; + case 32: fbi->SetType(BMM_TRUE_32); break; + default: fbi->SetType(BMM_NO_TYPE); break; + } + break; + case 'D'|('X'<<8)|('T'<<16)|('1'<<24): + case 'D'|('X'<<8)|('T'<<16)|('2'<<24): + case 'D'|('X'<<8)|('T'<<16)|('3'<<24): + case 'D'|('X'<<8)|('T'<<16)|('4'<<24): + case 'D'|('X'<<8)|('T'<<16)|('5'<<24): + fbi->SetType(BMM_TRUE_32); + break; + } + +// fbi->SetGamma(1.0f); + fbi->SetAspect(1.0f); + fbi->SetFirstFrame(0); + fbi->SetLastFrame(0); + + return BMMRES_SUCCESS; +} + +inline WORD Conv4To16(int d) { return (d<<12) | (d<<8) | (d<<4) | d; } +inline WORD Conv5To16(int d) { return (d<<11) | (d<<6) | (d<<1); } +inline WORD Conv6To16(int d) { return (d<<10) | (d<<4) | (d>>2); } +inline WORD Conv8To16(int d) { return (d<<8) | d; } + +//----------------------------------------------------------------------------- +//-- BitmapIO_DDS::Load() + +BitmapStorage *BitmapIO_DDS::Load(BitmapInfo *fbi, Bitmap *map, BMMRES *status) +{ + RGBQUAD *rgb = NULL; + BMM_Color_48 *pal = NULL; + BitmapStorage *s = NULL; + BMM_Color_64 *b = NULL; + BYTE *p = NULL; + + + int pixels = 0; + int rows = 0; + int w = 0; + int wb = 0; + int h = 0; + + //-- Initialize Status Optimistically + + *status = BMMRES_SUCCESS; + + //-- Make sure nothing weird is going on + + if(openMode != BMM_NOT_OPEN) + { + *status = ProcessImageIOError(fbi,BMMRES_INTERNALERROR); + return NULL; + } + + //-- Open DDS File ----------------------------------- + + File file(fbi->Name(), _T("rb")); + + if (!file.stream) + { + *status = ProcessImageIOError(fbi); + return(NULL); + } + + ghFile = file.stream; + + int width; + int height; + int planes; + int lTotalWidth; + int rowBytes; + + //-- Read File Header -------------------------------- + + unsigned char* data = nvDXTdecompress(width, height, planes, lTotalWidth, rowBytes); + + if (!data) + { + *status = ProcessImageIOError(fbi,BMMRES_BADFILEHEADER); + return (NULL); + } + + ghFile = NULL; + + + //-- Update Bitmap Info ------------------------------ + + fbi->SetWidth(width); + fbi->SetHeight(height); + + //fbi->SetGamma(1.0f); + fbi->SetAspect(1.0f); + + switch(planes) + { + case 3: + fbi->SetType(BMM_TRUE_24); + break; + + case 4: + fbi->SetType(BMM_TRUE_32); + break; + } + + fbi->SetFirstFrame(0); + fbi->SetLastFrame(0); + + //-- Create Image Storage ---------------------------- + + switch(planes) + { + case 3: + case 4: + s = BMMCreateStorage(map->Manager(),BMM_TRUE_32); + break; + } + + if(!s) + { + *status = ProcessImageIOError(fbi,BMMRES_CANTSTORAGE); + return NULL; + } + + //-- Allocate Image Storage -------------------------- + + if (s->Allocate(fbi,map->Manager(),BMM_OPEN_R)==0) + { + + memory_error_out: + *status = ProcessImageIOError(fbi,BMMRES_MEMORYERROR); + goto bail_out; + + io_error_out: + *status = ProcessImageIOError(fbi); + bail_out: + + if (s) delete s; + if (b) free(b); + if (p) free(p); + if (rgb) free(rgb); + if (pal) free(pal); + + return NULL; + + } + + switch (planes) + { + case 3: + { + //-- Read Image (24 Bits) ---------------------------- + + w = width; + wb = lTotalWidth*planes; //rowBytes; + h = height; + + b = (BMM_Color_64 *)malloc(width*sizeof(BMM_Color_64)); + p = (BYTE *)data; + + if(!b || !p) + goto memory_error_out; + + BYTE *ptr; + + do + { + ptr = p; + p += wb; + for (int x = 0; x < w; x++) + { + b[x].b = Conv8To16(*ptr++); + b[x].g = Conv8To16(*ptr++); + b[x].r = Conv8To16(*ptr++); + } + if (s->PutPixels(0,rows,w,b)!=1) + goto io_error_out; + rows++; + if (rows>=h) break; + + //-- Progress Report + + if (fbi->GetUpdateWindow()) + SendMessage(fbi->GetUpdateWindow(),BMM_PROGRESS,rows,h); + + } while (true); + break; + } + case 4: + { + //-- Read Image (32 Bits) ---------------------------- + + w = width; + wb = lTotalWidth*planes; //rowBytes; + h = height; + + b = (BMM_Color_64 *)malloc(width*sizeof(BMM_Color_64)); + p = (BYTE *)data; + + if(!b || !p) + goto memory_error_out; + + BYTE *ptr; + + bool foundalpha = false; + + do + { + ptr = p; + p += wb; + for (int x = 0; x < w; x++) + { + b[x].b = Conv8To16(*ptr++); + b[x].g = Conv8To16(*ptr++); + b[x].r = Conv8To16(*ptr++); + if (*ptr != 0xFF) foundalpha=true; + b[x].a = Conv8To16(*ptr++); + } + if (s->PutPixels(0,rows,w,b)!=1) + goto io_error_out; + rows++; + if (rows>=h) break; + + //-- Progress Report + + if (fbi->GetUpdateWindow()) + SendMessage(fbi->GetUpdateWindow(),BMM_PROGRESS,rows,h); + + } while (true); + if (foundalpha) + fbi->SetFlags(MAP_HAS_ALPHA); + else + fbi->SetType(BMM_TRUE_24); + break; + } + } + + //-- Clean Up ---------------------------------------- + + free(data); + + if (b) free(b); + + //-- Set the storage's BitmapInfo + + s->bi.CopyImageInfo(fbi); + + return s; + +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::OpenOutput() +// + +BMMRES BitmapIO_DDS::OpenOutput(BitmapInfo *fbi, Bitmap *map) +{ + + if (openMode != BMM_NOT_OPEN) + return (ProcessImageIOError(&bi,BMMRES_INTERNALERROR)); + + if (!map) + return (ProcessImageIOError(&bi,BMMRES_INTERNALERROR)); + + //-- Save Image Info Data + + bi.CopyImageInfo(fbi); + bi.SetUpdateWindow(fbi->GetUpdateWindow()); + + this->map = map; + openMode = BMM_OPEN_W; + + return (BMMRES_SUCCESS); + +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::Write() +// +// + +BMMRES BitmapIO_DDS::Write(int frame) +{ + + BMMRES result = BMMRES_SUCCESS; + + //-- If we haven't gone through an OpenOutput(), leave + + if (openMode != BMM_OPEN_W) + return ProcessImageIOError(&bi,BMMRES_INTERNALERROR); + + //-- Resolve Filename -------------------------------- + + TCHAR filename[MAX_PATH]; + + if (frame == BMM_SINGLEFRAME) + { + _tcscpy(filename,bi.Name()); + } + else + { + if (!BMMCreateNumberedFilename(bi.Name(),frame,filename)) + return ProcessImageIOError(&bi,BMMRES_NUMBEREDFILENAMEERROR); + } + + //-- Create Image File ------------------------------- + + PBITMAPINFO pbmi = GetDitheredOutputDib(32); + if (!pbmi) + return ProcessImageIOError(&bi,GetString(IDS_CONVERT_ERROR)); + int w=map->Width(); + int h=map->Height(); + int wb=w*4; + unsigned char* data = new unsigned char[wb*h]; + const unsigned char* psrc = (const unsigned char*)pbmi->bmiColors; + unsigned char* pdst = data + wb*h; + for (int j=h; --j>=0; ) + { + pdst -= wb; + memcpy(pdst,psrc,wb); + psrc += wb; + } + + //-- Write Image File -------------------------------- + + if (bi.GetUpdateWindow()) + SendMessage(bi.GetUpdateWindow(),BMM_PROGRESS,50,100); + + File file(filename, _T("wb")); + + if (!file.stream) + { + LocalFree(pbmi); + return ProcessImageIOError(&bi); + } + + ghFile = file.stream; + +/* + Compresses an image with a user supplied callback with the data for each MIP level created + Only supports input of RGB 24 or ARGB 32 bpp + if callback is == 0 (or not specified), then WriteDTXnFile is called with all file info +*/ + HRESULT res = nvDXTcompress(data, // pointer to data (24 or 32 bit) + w, // width in texels + h, // height in texels + mParams.outFormat&TF_FMTMASK, + (mParams.outFormat&TF_MIPMAPS)!=0, // auto gen MIP maps + (mParams.outFormat&TF_DITHER)!=0, // dither + 4, // 3 or 4 bytes per pixel + 0); // callback for generated levels + + delete[] data; + + LocalFree(pbmi); + ghFile = NULL; + + if (res != 0) + { + switch (res) + { + default: + case DXTERR_INPUT_POINTER_ZERO: + return ProcessImageIOError(&bi,GetString(IDS_CONVERT_ERROR)); + case DXTERR_DEPTH_IS_NOT_3_OR_4: + return ProcessImageIOError(&bi,GetString(IDS_UNSUPPORTEDFORMAT_ERROR)); + case DXTERR_NON_POWER_2: + return ProcessImageIOError(&bi,GetString(IDS_NONPOWEROF2_ERROR)); + } + } + + if (bi.GetUpdateWindow()) + SendMessage(bi.GetUpdateWindow(),BMM_PROGRESS,100,100); + + return result; +} + +//----------------------------------------------------------------------------- +// BitmapIO_DDS::Close() +// + +int BitmapIO_DDS::Close(int flag) +{ + return 1; +} + +//----------------------------------------------------------------------------- +// #> BitmapIO_DDS::ReadDDSHeader() +// + +int BitmapIO_DDS::ReadDDSHeader(FILE *stream) +{ + //-- Read File Header -------------------------------- + + int res = fread(&hdr,1,sizeof(DDSFILEHEADER),stream); + + if (res != sizeof(DDSFILEHEADER)) + return 0; + + //-- Validate ---------------------------------------- + + if (hdr.dwMagic != 0x20534444) + return 0; + + //-- Done + return 1; +} + + +//----------------------------------------------------------------------------- +// Interface + +extern ClassDesc *GetDDSLibClassDesc() +{ + return &DDSDesc; +} + +#if 0 +//-- Globals ------------------------------------------------------------------ + +TCHAR *GetString(int id) +{ + static TCHAR buf[256]; + if (hInstance) + return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL; + return NULL; +} + + +DLLEXPORT const TCHAR * LibDescription () +{ + return GetString(IDS_DDS_DESC); +} + +DLLEXPORT int LibNumberClasses () +{ + return 1; +} + +DLLEXPORT ClassDesc *LibClassDesc(int i) +{ + switch(i) + { + case 0: return &DDSDesc; break; + default: return 0; break; + } +} + +DLLEXPORT ULONG LibVersion () +{ + return (VERSION_3DSMAX); +} + +// Let the plug-in register itself for deferred loading +__declspec(dllexport) ULONG CanAutoDefer() +{ + return 1; +} + +//----------------------------------------------------------------------------- +//-- DLL Declaration + +BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + if (hInstance) + return(FALSE); + hInstance = hDLLInst; + break; + case DLL_PROCESS_DETACH: + hInstance = NULL; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} + +#endif \ No newline at end of file diff --git a/NifProps/dds/dds.dep b/NifProps/dds/dds.dep new file mode 100644 index 0000000..076baa3 --- /dev/null +++ b/NifProps/dds/dds.dep @@ -0,0 +1,128 @@ +# Microsoft Developer Studio Generated Dependency File, included by dds.mak + +.\dds.cpp : \ + "..\..\..\include\acolor.h"\ + "..\..\..\include\ActionTable.h"\ + "..\..\..\include\animtbl.h"\ + "..\..\..\include\appio.h"\ + "..\..\..\include\assert1.h"\ + "..\..\..\include\baseinterface.h"\ + "..\..\..\include\bitarray.h"\ + "..\..\..\include\bitmap.h"\ + "..\..\..\include\bmmlib.h"\ + "..\..\..\include\box2.h"\ + "..\..\..\include\box3.h"\ + "..\..\..\include\buildver.h"\ + "..\..\..\include\captypes.h"\ + "..\..\..\include\channels.h"\ + "..\..\..\include\cmdmode.h"\ + "..\..\..\include\color.h"\ + "..\..\..\include\coreexp.h"\ + "..\..\..\include\custcont.h"\ + "..\..\..\include\dbgprint.h"\ + "..\..\..\include\dpoint3.h"\ + "..\..\..\include\euler.h"\ + "..\..\..\include\evuser.h"\ + "..\..\..\include\excllist.h"\ + "..\..\..\include\export.h"\ + "..\..\..\include\gbuf.h"\ + "..\..\..\include\gencam.h"\ + "..\..\..\include\genhier.h"\ + "..\..\..\include\genlight.h"\ + "..\..\..\include\genshape.h"\ + "..\..\..\include\geom.h"\ + "..\..\..\include\geomlib.h"\ + "..\..\..\include\gfloat.h"\ + "..\..\..\include\gfx.h"\ + "..\..\..\include\gfxlib.h"\ + "..\..\..\include\gutil.h"\ + "..\..\..\include\hitdata.h"\ + "..\..\..\include\hold.h"\ + "..\..\..\include\iColorMan.h"\ + "..\..\..\include\iFnPub.h"\ + "..\..\..\include\impapi.h"\ + "..\..\..\include\impexp.h"\ + "..\..\..\include\impexpintf.h"\ + "..\..\..\include\imtl.h"\ + "..\..\..\include\inode.h"\ + "..\..\..\include\INodeGIProperties.h"\ + "..\..\..\include\interval.h"\ + "..\..\..\include\ioapi.h"\ + "..\..\..\include\iparamb.h"\ + "..\..\..\include\ipipelineclient.h"\ + "..\..\..\include\ipoint2.h"\ + "..\..\..\include\ipoint3.h"\ + "..\..\..\include\istdplug.h"\ + "..\..\..\include\iTreeVw.h"\ + "..\..\..\include\linklist.h"\ + "..\..\..\include\lockid.h"\ + "..\..\..\include\log.h"\ + "..\..\..\include\matrix2.h"\ + "..\..\..\include\matrix3.h"\ + "..\..\..\include\max.h"\ + "..\..\..\include\maxapi.h"\ + "..\..\..\include\maxcom.h"\ + "..\..\..\include\maxtess.h"\ + "..\..\..\include\maxtypes.h"\ + "..\..\..\include\mesh.h"\ + "..\..\..\include\meshlib.h"\ + "..\..\..\include\MNBigMat.h"\ + "..\..\..\include\MNCommon.h"\ + "..\..\..\include\mnmath.h"\ + "..\..\..\include\MNMesh.h"\ + "..\..\..\include\MNNormalSpec.h"\ + "..\..\..\include\mouseman.h"\ + "..\..\..\include\mtl.h"\ + "..\..\..\include\namesel.h"\ + "..\..\..\include\nametab.h"\ + "..\..\..\include\object.h"\ + "..\..\..\include\objmode.h"\ + "..\..\..\include\palutil.h"\ + "..\..\..\include\paramtype.h"\ + "..\..\..\include\patch.h"\ + "..\..\..\include\patchlib.h"\ + "..\..\..\include\patchobj.h"\ + "..\..\..\include\pixelbuf.h"\ + "..\..\..\include\plugapi.h"\ + "..\..\..\include\plugin.h"\ + "..\..\..\include\point2.h"\ + "..\..\..\include\point3.h"\ + "..\..\..\include\point4.h"\ + "..\..\..\include\polyobj.h"\ + "..\..\..\include\polyshp.h"\ + "..\..\..\include\ptrvec.h"\ + "..\..\..\include\quat.h"\ + "..\..\..\include\random.h"\ + "..\..\..\include\ref.h"\ + "..\..\..\include\render.h"\ + "..\..\..\include\RenderElements.h"\ + "..\..\..\include\rtclick.h"\ + "..\..\..\include\sbmtlapi.h"\ + "..\..\..\include\sceneapi.h"\ + "..\..\..\include\sfx.h"\ + "..\..\..\include\shape.h"\ + "..\..\..\include\shphier.h"\ + "..\..\..\include\shpsels.h"\ + "..\..\..\include\snap.h"\ + "..\..\..\include\soundobj.h"\ + "..\..\..\include\spline3d.h"\ + "..\..\..\include\stack.h"\ + "..\..\..\include\stack3.h"\ + "..\..\..\include\strbasic.h"\ + "..\..\..\include\strclass.h"\ + "..\..\..\include\SvCore.h"\ + "..\..\..\include\SystemUtilities.h"\ + "..\..\..\include\tab.h"\ + "..\..\..\include\templt.h"\ + "..\..\..\include\trig.h"\ + "..\..\..\include\triobj.h"\ + "..\..\..\include\udmIA64.h"\ + "..\..\..\include\units.h"\ + "..\..\..\include\utilexp.h"\ + "..\..\..\include\utilintf.h"\ + "..\..\..\include\utillib.h"\ + "..\..\..\include\vedge.h"\ + "..\..\..\include\winutil.h"\ + ".\DDS.H"\ + ".\dxtlib.h"\ + diff --git a/NifProps/dds/dds.h b/NifProps/dds/dds.h new file mode 100644 index 0000000..6af084c --- /dev/null +++ b/NifProps/dds/dds.h @@ -0,0 +1,159 @@ +// File ....: dds.h +// ---------------- +// Author...: Sean Palmer +// Date ....: April 2001 +// Descr....: DDS File I/O Module + +#ifndef _DDSCLASS_ +#define _DDSCLASS_ + +#define DLLEXPORT __declspec(dllexport) + +#define DDS_CLASS_ID Class_ID(0xe3061ca, 0xd2120de) + +#pragma pack(push,1) + +struct DDSCOLORKEY +{ + DWORD dwColorSpaceLowValue; // low boundary of color space that is to + // be treated as Color Key, inclusive + DWORD dwColorSpaceHighValue; // high boundary of color space that is +}; + +struct DDSFILEHEADER +{ + DWORD dwMagic; // (0x20534444, or "DDS ") + + // the following matches DDSURFACEDESC2 + DWORD dwSize; // size of the DDSURFACEDESC structure + DWORD dwFlags; // determines what fields are valid + DWORD dwHeight; // height of surface to be created + DWORD dwWidth; // width of input surface + long lPitch; // distance to start of next line (return value only) + DWORD dwDepth; // the depth if this is a volume texture + DWORD dwMipMapCount; // number of mip-map levels requested + DWORD dwAlphaBitDepth; // depth of alpha buffer requested + DWORD dwReserved; // reserved + void* lpSurface; // pointer to the associated surface memory + DDSCOLORKEY ddckCKDestOverlay; // color key for destination overlay use + DDSCOLORKEY ddckCKDestBlt; // color key for destination blt use + DDSCOLORKEY ddckCKSrcOverlay; // color key for source overlay use + DDSCOLORKEY ddckCKSrcBlt; // color key for source blt use + + // from DDPIXELFORMAT structure + DWORD dwPFSize; // size of DDPIXELFORMAT structure + DWORD dwPFFlags; // pixel format flags + DWORD dwFourCC; // (FOURCC code) + DWORD dwRGBBitCount; // how many bits per pixel + DWORD dwRBitMask; // mask for red bit + DWORD dwGBitMask; // mask for green bits + DWORD dwBBitMask; // mask for blue bits + DWORD dwRGBAlphaBitMask; // mask for alpha channel + + // from DDSCAPS2 structure + DWORD dwCaps; // capabilities of surface wanted + DWORD dwCaps2; + DWORD dwCaps3; + DWORD dwVolumeDepth; + + DWORD dwTextureStage; // stage in multitexture cascade +//BYTE bData1[]; // Data for the main surface +//[BYTE bData2[]]; // Data for attached surfaces, if any, follows. +}; + +#pragma pack(pop) + +enum +{ + TF_DITHER = 0x40000000, + TF_MIPMAPS = 0x80000000, + TF_FMTMASK = 0x0000FFFF, +}; + +struct DDSParams +{ + int outFormat; // Output format +}; + +class BitmapIO_DDS : public BitmapIO +{ + +private: + + DDSFILEHEADER hdr; + DDSParams mParams; + +public: + + //-- Constructors/Destructors + + BitmapIO_DDS (); + ~BitmapIO_DDS (); + + //-- Number of extemsions supported + + int ExtCount () { return 1; } + + //-- Extension #n (i.e. "3DS") + + const TCHAR *Ext (int n) { return _T("dds"); } + + //-- Descriptions + + const TCHAR *LongDesc (); + const TCHAR *ShortDesc (); + + //-- Miscelaneous Messages + + const TCHAR *AuthorName () { return _T("Sean Palmer");} + const TCHAR *CopyrightMessage () { return _T("Copyright 2001 Treyarch LLC");} + const TCHAR *OtherMessage1 () { return _T("");} + const TCHAR *OtherMessage2 () { return _T("");} + + unsigned int Version () { return (100);} + + //-- Driver capabilities + + int Capability () { return BMMIO_READER | +// BMMIO_WRITER | + BMMIO_EXTENSION | + BMMIO_CONTROLWRITE;} + + //-- Driver Configuration + + BOOL LoadConfigure (void *ptr); + BOOL SaveConfigure (void *ptr); + DWORD EvaluateConfigure () { return sizeof(DDSParams); } + + //-- Show DLL's "About..." box + + void ShowAbout (HWND hWnd); + + //-- Show Image's control Dlg Box + BOOL ShowControl (HWND hWnd, DWORD flag); + + //-- Return info about image + + BMMRES GetImageInfo (BitmapInfo *fbi); + + //-- Image Input + + BitmapStorage *Load (BitmapInfo *fbi, Bitmap *map, BMMRES *status); + + //-- Image Output + + BMMRES OpenOutput (BitmapInfo *fbi, Bitmap *map); + BMMRES Write (int frame); + int Close (int flag); + + //-- This handler's specialized functions + + int ReadDDSHeader (FILE *stream); + + //-- Dialog Proc for the Image control Dlg box + + BOOL ConfigCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); +}; + +#endif _DDSCLASS_ + diff --git a/NifProps/dds/dds.rc b/NifProps/dds/dds.rc new file mode 100644 index 0000000..2d6329b --- /dev/null +++ b/NifProps/dds/dds.rc @@ -0,0 +1,156 @@ +//Microsoft Developer Studio generated resource script. +// +#include "ddsres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include <windows.h> +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "ddsres.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include <windows.h>\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""veroverrides.h""\r\n" + "#include ""maxversion.r""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DDS_ABOUT DIALOG DISCARDABLE 0, 0, 166, 97 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About DDS Image File I/O" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,108,77,50,14 + RTEXT "DDS File I/O Module",IDC_STATIC,37,9,118,9 + RTEXT "Version 1.0",IDC_STATIC,37,19,118,9 + GROUPBOX "",IDC_STATIC,8,2,151,29 + RTEXT "Author: Sean L. Palmer",IDC_STATIC,9,38,148,8 + RTEXT "Copyright 2001 Treyarch LLC",IDC_STATIC,9,50,148,8 + RTEXT "Using NVIDIA nvDXTlib DDS converter",IDC_STATIC,9,62, + 148,8 +END + +IDD_DDS_CONFIG DIALOG DISCARDABLE 0, 0, 177, 185 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "DDS Configuration" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Colors",-1,6,2,164,127,WS_GROUP + CONTROL "DXT1 Compression",IDC_DDS_DXT1,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,29,15,128,10 + CONTROL "DXT1 with 1 bit alpha",IDC_DDS_DXT1ALPHA,"Button", + BS_AUTORADIOBUTTON,29,29,125,10 + CONTROL "DXT3 Compressed with alpha",IDC_DDS_DXT3,"Button", + BS_AUTORADIOBUTTON,29,43,125,10 + CONTROL "DXT5 Compressed with alpha",IDC_DDS_DXT5,"Button", + BS_AUTORADIOBUTTON,29,57,125,10 + CONTROL "ARGB 4444",IDC_DDS_ARGB4444,"Button",BS_AUTORADIOBUTTON, + 29,71,125,10 + CONTROL "ARGB 1555",IDC_DDS_ARGB1555,"Button",BS_AUTORADIOBUTTON, + 29,85,125,10 + CONTROL "RGB 565",IDC_DDS_RGB565,"Button",BS_AUTORADIOBUTTON,29, + 99,125,10 + CONTROL "ARGB 8888",IDC_DDS_ARGB8888,"Button",BS_AUTORADIOBUTTON, + 29,113,125,10 + DEFPUSHBUTTON "OK",IDOK,38,165,50,14 + PUSHBUTTON "Cancel",IDCANCEL,94,165,50,14 + CONTROL "Dither",IDC_DDS_DITHER,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,30,135,95,9 + CONTROL "Generate Mipmaps",IDC_DDS_MIPMAPS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,30,148,96,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DDS_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 179 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_DDS "DDS" + IDS_BITMAP_IO "Bitmap I/O" + IDS_DDS_FILE "DDS Image File" + IDS_UNSUPPORTED "Unsupported DDS Image File" + IDS_CONVERT_ERROR "Error converting bitmap" + IDS_DDS_DESC "DDS file I/O" + IDS_NONPOWEROF2_ERROR "Dimensions not power of 2" + IDS_UNSUPPORTEDFORMAT_ERROR "Unsupported format" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "veroverrides.h" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/NifProps/dds/ddsTypes.h b/NifProps/dds/ddsTypes.h new file mode 100644 index 0000000..576b75c --- /dev/null +++ b/NifProps/dds/ddsTypes.h @@ -0,0 +1,375 @@ +#pragma once +#include <windows.h> +#include <memory.h> + +#if defined(WIN32_LEAN_AND_MEAN) + #include <mmsystem.h> // MAKEFOURCC +#endif + +#include "tPixel.h" +#include "nvErrorCodes.h" + + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + + + + +typedef enum nvD3DFORMAT +{ + nvD3DFMT_UNKNOWN = 0, + + nvD3DFMT_R8G8B8 = 20, + nvD3DFMT_A8R8G8B8 = 21, + nvD3DFMT_X8R8G8B8 = 22, + nvD3DFMT_R5G6B5 = 23, + nvD3DFMT_X1R5G5B5 = 24, + nvD3DFMT_A1R5G5B5 = 25, + nvD3DFMT_A4R4G4B4 = 26, + nvD3DFMT_R3G3B2 = 27, + nvD3DFMT_A8 = 28, + nvD3DFMT_A8R3G3B2 = 29, + nvD3DFMT_X4R4G4B4 = 30, + nvD3DFMT_A2B10G10R10 = 31, + nvD3DFMT_A8B8G8R8 = 32, + nvD3DFMT_X8B8G8R8 = 33, + nvD3DFMT_G16R16 = 34, + nvD3DFMT_A2R10G10B10 = 35, + nvD3DFMT_A16B16G16R16 = 36, + + nvD3DFMT_A8P8 = 40, + nvD3DFMT_P8 = 41, + + nvD3DFMT_L8 = 50, + nvD3DFMT_A8L8 = 51, + nvD3DFMT_A4L4 = 52, + + nvD3DFMT_V8U8 = 60, + nvD3DFMT_L6V5U5 = 61, + nvD3DFMT_X8L8V8U8 = 62, + nvD3DFMT_Q8W8V8U8 = 63, + nvD3DFMT_V16U16 = 64, + nvD3DFMT_A2W10V10U10 = 67, + + nvD3DFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'), + nvD3DFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'), + nvD3DFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'), + nvD3DFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'), + nvD3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'), + nvD3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'), + nvD3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'), + nvD3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'), + nvD3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'), + nvD3DFMT_3Dc = MAKEFOURCC('A', 'T', 'I', '2'), + + nvD3DFMT_D16_LOCKABLE = 70, + nvD3DFMT_D32 = 71, + nvD3DFMT_D15S1 = 73, + nvD3DFMT_D24S8 = 75, + nvD3DFMT_D24X8 = 77, + nvD3DFMT_D24X4S4 = 79, + nvD3DFMT_D16 = 80, + + nvD3DFMT_D32F_LOCKABLE = 82, + nvD3DFMT_D24FS8 = 83, + + + nvD3DFMT_L16 = 81, + + nvD3DFMT_VERTEXDATA =100, + nvD3DFMT_INDEX16 =101, + nvD3DFMT_INDEX32 =102, + + nvD3DFMT_Q16W16V16U16 =110, + + nvD3DFMT_MULTI2_ARGB8 = MAKEFOURCC('M','E','T','1'), + + // Floating point surface formats + + // s10e5 formats (16-bits per channel) + nvD3DFMT_R16F = 111, + nvD3DFMT_G16R16F = 112, + nvD3DFMT_A16B16G16R16F = 113, + + // IEEE s23e8 formats (32-bits per channel) + nvD3DFMT_R32F = 114, + nvD3DFMT_G32R32F = 115, + nvD3DFMT_A32B32G32R32F = 116, + + nvD3DFMT_CxV8U8 = 117, + + + nvD3DFMT_FORCE_DWORD =0x7fffffff +} nvD3DFORMAT; + +typedef enum nvRescaleTypes +{ + kRescaleNone, // no rescale + kRescaleNearestPower2, // rescale to nearest power of two + kRescaleBiggestPower2, // rescale to next bigger power of 2 + kRescaleSmallestPower2, // rescale to smaller power of 2 + kRescaleNextSmallestPower2, // rescale to next smaller power of 2 + kRescalePreScale, // rescale to this size + kRescaleRelScale, // relative rescale + +} RescaleTypes; + + +typedef enum nvSharpenFilterTypes +{ + kSharpenFilterNone, + kSharpenFilterNegative, + kSharpenFilterLighter, + kSharpenFilterDarker, + kSharpenFilterContrastMore, + kSharpenFilterContrastLess, + kSharpenFilterSmoothen, + kSharpenFilterSharpenSoft, + kSharpenFilterSharpenMedium, + kSharpenFilterSharpenStrong, + kSharpenFilterFindEdges, + kSharpenFilterContour, + kSharpenFilterEdgeDetect, + kSharpenFilterEdgeDetectSoft, + kSharpenFilterEmboss, + kSharpenFilterMeanRemoval, + kSharpenFilterUnSharp, + kSharpenFilterXSharpen, + kSharpenFilterWarpSharp, + kSharpenFilterCustom, +}; + + +typedef enum nvMipMapGeneration +{ + kGenerateMipMaps = 30, + kUseExistingMipMaps = 31, + kNoMipMaps = 32, + kCompleteMipMapChain = 33, // fill in missing MIP maps + +}; + + +typedef enum nvMipFilterTypes +{ + kMipFilterPoint , + kMipFilterBox , + kMipFilterTriangle , + kMipFilterQuadratic , + kMipFilterCubic , + + kMipFilterCatrom , + kMipFilterMitchell , + + kMipFilterGaussian , + kMipFilterSinc , + kMipFilterBessel , + + kMipFilterHanning , + kMipFilterHamming , + kMipFilterBlackman , + kMipFilterKaiser, +}; + + +enum nvTextureFormats +{ + kDXT1 , + kDXT1a , // DXT1 with one bit alpha + kDXT3 , // explicit alpha + kDXT5 , // interpolated alpha + k4444 , // a4 r4 g4 b4 + k1555 , // a1 r5 g5 b5 + k565 , // a0 r5 g6 b5 + k8888 , // a8 r8 g8 b8 + k888 , // a0 r8 g8 b8 + k555 , // a0 r5 g5 b5 + kP8c , // paletted color only + kV8U8 , // DuDv + kCxV8U8 , // normal map + kA8 , // alpha only + kP4c , // 16 bit color palette + kQ8W8V8U8, + kA8L8, + kR32F, + kA32B32G32R32F, + kA16B16G16R16F, + kL8, // luminance + kP8a , // paletted with alpha + kP4a , // 16 bit color palette with alpha + kR16F, // single component fp16 + kDXT5_NM , // normal map compression. G = Y, A = X + kX888 , // aX r8 g8 b8 + kV16U16, + kG16R16, + kG16R16F, + k3Dc, + kL16, + + kUnknownTextureFormat = 0xFFFFFFFF, + +}; + + +enum nvTextureTypes +{ + kTextureTypeTexture2D, + kTextureTypeCubeMap, + kTextureTypeVolumeMap, +}; + + +enum nvCompressionWeighting +{ + kLuminanceWeighting, + kGreyScaleWeighting, + kTangentSpaceNormalMapWeighting, + kObjectSpaceNormalMapWeighting, + kUserDefinedWeighting, // used values stored in 'weight' +}; + +enum nvNormalMapFilters +{ + kFilter4x = 1040, + kFilter3x3 = 1041, + kFilter5x5 = 1042, + kFilter7x7 = 1043, + kFilter9x9 = 1044, + kFilterDuDv = 1045, +}; + + +enum nvHeightConversionMethods +{ + kAlphaChannel = 1009, + kAverageRGB = 1010, + kBiasedRGB = 1011, + kRed = 1012, + kGreen = 1013, + kBlue = 1014, + kMaxRGB = 1015, + kColorSpace = 1016, + kNormalize = 1017, + kNormalMapToHeightMap = 1018, +}; + +enum nvAlphaResult +{ + kAlphaUnchanged = 1033, + kAlphaHeight = 1034, + kAlphaSetToZero = 1035, + kAlphaSetToOne = 1036, +}; + + +enum nvQualitySetting +{ + kQualityFastest = 68, + kQualityNormal = 69, + kQualityProduction = 71, // typical value + kQualityHighest = 72, +}; + + +enum nvPixelFormat +{ + PF_RGBA, + PF_FP32, +}; + + + +// filled in by reading a dds file +struct DDS_PIXELFORMAT +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwFourCC; + DWORD dwRGBBitCount; + DWORD dwRBitMask; + DWORD dwGBitMask; + DWORD dwBBitMask; + DWORD dwRGBAlphaBitMask; +}; + + +class nvImageContainer +{ + +public: + // loaded directly from the .dds header + DDS_PIXELFORMAT m_ddpfPixelFormat; + + + nvImageContainer() + { + + bits_per_component = 0; //image's resolution in bits per pixel per plane + paletteSize = 0; + + + + bFoundAlphaInRead = false; + bCompressed = false; + fmt = 0; // nvD3DFMT_UNKNOWN + + dwCubeMapFlags = 0; + + actualMipMapCount = 1; + //maxPossibleMipMapCount = 1; + nMIPMapsToLoad = 1; + depth = 0; + + + } + + + + // in file read + size_t width; // of MIP 0 + size_t height; // of MIP 0 + size_t depth; // for volume maps + + size_t actualMipMapCount; + size_t nMIPMapsToLoad; + + + bool bFoundAlphaInRead; // is alpha field present and non-zero + + // in the input file + + DWORD dwCubeMapFlags; + size_t bits_per_component; + size_t nPlanes; // number of planes in the file format + bool bCompressed; // is file a compressed format + size_t paletteSize; // 16 or 256 entries + rgba_t palette[256]; + + DWORD fmt; // D3DFORMAT specified in .dds file + + nvTextureFormats textureFormat; + + nvTextureTypes textureType; + + + + + + fpMipMappedImage fpMIPImage; + fpMipMappedCubeMap fpMIPCubeMap; + fpMipMappedVolumeMap fpMIPVolumeMap; + + RGBAMipMappedImage rgbaMIPImage; + RGBAMipMappedCubeMap rgbaMIPCubeMap; + RGBAMipMappedVolumeMap rgbaMIPVolumeMap; + + + ~nvImageContainer() + { + } +}; + + + diff --git a/NifProps/dds/ddsres.h b/NifProps/dds/ddsres.h new file mode 100644 index 0000000..17688d0 --- /dev/null +++ b/NifProps/dds/ddsres.h @@ -0,0 +1,46 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dds.rc +// +#define IDS_DDS 1 +#define IDS_BITMAP_IO 2 +#define IDS_DDS_FILE 3 +#define IDS_UNSUPPORTED 4 +#define IDS_CONVERT_ERROR 5 +#define IDS_DDS_DESC 6 +#define IDS_NONPOWEROF2_ERROR 7 +#define IDS_UNSUPPORTEDFORMAT_ERROR 8 +#define IDD_DDS_ABOUT 101 +#define IDD_DDS_CONTROL 102 +#define IDD_DDS_CONFIG 102 +#define IDC_DDS_PALETTE 1000 +#define IDC_DDS_DXT1 1000 +#define IDC_RAD_NTSC 1001 +#define IDC_RAD_24 1001 +#define IDC_DDS_RGB24 1001 +#define IDC_DDS_ARGB8888 1001 +#define IDC_RAD_PAL 1002 +#define IDC_RAD_8 1002 +#define IDC_DDS_DXT3 1002 +#define IDC_EDIT_X 1003 +#define IDC_DDS_DXT1ALPHA 1003 +#define IDC_EDIT_Y 1004 +#define IDC_DDS_DXT5 1004 +#define IDC_RAD_CUSTOM 1005 +#define IDC_DDS_ARGB1555 1005 +#define IDC_DDS_ARGB4444 1006 +#define IDC_DDS_RGB565 1007 +#define IDC_DDS_DITHER 1008 +#define IDC_DDS_MIPMAPS 1009 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1010 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/NifProps/dds/dxtlib.h b/NifProps/dds/dxtlib.h new file mode 100644 index 0000000..84f6852 --- /dev/null +++ b/NifProps/dds/dxtlib.h @@ -0,0 +1,124 @@ +/*********************************************************************NVMH2**** +Path: C:\Dev\devrel\Nv_sdk_4\Dx8_private\PhotoShop\dxtlib +File: dxtlib.h + +Copyright (C) 1999, 2000 NVIDIA Corporation +This file is provided without support, instruction, or implied warranty of any +kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is +not liable under any circumstances for any damages or loss whatsoever arising +from the use or inability to use this file or items derived from it. + +Comments: + + +******************************************************************************/ + + + + +#pragma comment(lib, "C:\\Development\\Projects\\NifLib\\niftools\\trunk\\max\\NifProps\\dds\\nvDXTlib.lib") +//#pragma comment(lib, "C:\\Development\\Projects\\NifLib\\niftools\\trunk\\max\\NifProps\\dds\\nvDXTlib.vc7.lib") + + + + + + + + +typedef HRESULT (*MIPcallback)(void * data, int miplevel, DWORD size); +// call back +// pointer to data +// mip level +// size of chunk + + +/* + Compresses an image with a user supplied callback with the data for each MIP level created + Only supports input of RGB 24 or ARGB 32 bpp +*/ +HRESULT nvDXTcompress(unsigned char * raw_data, // pointer to data (24 or 32 bit) + unsigned long w, // width in texels + unsigned long h, // height in texels + DWORD TextureFormat, // list below + bool bGenMipMaps, // auto gen MIP maps + bool bDither, + DWORD depth, // 3 or 4 + MIPcallback callback = 0); // callback for generated levels +// if callback is == 0 (or not specified), then WriteDTXnFile is called with all file info +// +// You must write the routines (or provide stubs) +// void WriteDTXnFile(count, buffer); +// void ReadDTXnFile(count, buffer); +// +// +/* returns + w width + h height + depth ( 3 or 4) + total_width + rowBytes - pitch + +*/ +unsigned char * nvDXTdecompress(int & w, int & h, int & depth, int & total_width, int & rowBytes); + + +// see examples + + +void WriteDTXnFile(DWORD count, void * buffer); +void ReadDTXnFile(DWORD count, void * buffer); + + +// TextureFormat +#define TF_DXT1 10 +#define TF_DXT1_1BitAlpha 11 +#define TF_DXT3 12 +#define TF_DXT5 13 +#define TF_RGB4444 14 +#define TF_RGB1555 15 +#define TF_RGB565 16 +#define TF_RGB8888 17 + + +#define DXTERR_INPUT_POINTER_ZERO -1 +#define DXTERR_DEPTH_IS_NOT_3_OR_4 -2 +#define DXTERR_NON_POWER_2 -3 + +/* example + +LPDIRECT3DTEXTURE8 pCurrentTexture = 0; + +HRESULT LoadAllMipSurfaces(void * data, int iLevel) +{ + HRESULT hr; + LPDIRECT3DSURFACE8 psurf; + D3DSURFACE_DESC sd; + D3DLOCKED_RECT lr; + + hr = pCurrentTexture->GetSurfaceLevel(iLevel, &psurf); + + if (FAILED(hr)) + return hr; + psurf->GetDesc(&sd); + + + hr = pCurrentTexture->LockRect(iLevel, &lr, NULL, 0); + if (FAILED(hr)) + return hr; + + memcpy(lr.pBits, data, sd.Size); + + hr = pCurrentTexture->UnlockRect(iLevel); + + ReleasePpo(&psurf); + + return 0; +} + + + hr = D3DXCreateTexture(m_pd3dDevice, Width, Height, nMips, 0, D3DFMT_DXT3, D3DPOOL_MANAGED, &pCurrentTexture); + nvDXTcompress(raw_data, Width, Height, DXT3, true, 4, LoadAllMipSurfaces); + +*/ + diff --git a/NifProps/dds/nvDXTlib.lib b/NifProps/dds/nvDXTlib.lib new file mode 100644 index 0000000000000000000000000000000000000000..8675cab326a4d86972a04a50c0ff88c9151c930c GIT binary patch literal 90212 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�e4XAS>&OiM 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 UJer;RiyMdlVXB-H-zymM-%w6uRsaA1 literal 0 HcmV?d00001 diff --git a/NifProps/dds/nvErrorCodes.h b/NifProps/dds/nvErrorCodes.h new file mode 100644 index 0000000..e6fa48b --- /dev/null +++ b/NifProps/dds/nvErrorCodes.h @@ -0,0 +1,112 @@ +#pragma once + +typedef enum NV_ERROR_CODE +{ + NV_OK = 0, + NV_FAIL = -1, // generic + NV_CANT_OPEN_INPUT_FILE = -2, + NV_CANT_OPEN_OUTPUT_FILE = -3, + NV_BAD_OPTION = -4, + NV_BAD_OUTPUT_DIRECTORY = -5, + NV_CANT_DECOMPRESS_IMAGE = -6, + NV_BAD_LIST_FILE = -7, + NV_CANT_OPEN_LIST_FILE = -8, + NV_BAD_LIST_FILE_CONTENTS = -9, + NV_IMAGE_NOT_SQUARE = -10, + NV_IMAGES_NOT_SAME_SIZE = -11, + NV_UNKNOWN_CONVERSION = -12, // for normal map generation + NV_CANT_OPEN_PROFILE = -13, + NV_IMAGE_NOT_MULT4 = -14, + NV_OUTPUT_FILE_IS_READ_ONLY= -15, + NV_INPUT_POINTER_ZERO = -16, + NV_DEPTH_IS_NOT_3_OR_4 = -17, + NV_IMAGE_NOT_POWER_2 = -18, + NV_CANT_MAKE_MATRIX = -19, + NV_CANT_NORMALIZE = -20, + NV_CANT_INVERT_MATRIX = -21, + NV_CANT_MAKE_VECTOR = -22, + NV_CANT_INITIALIZE_CONVOLVER = -23, + NV_EMPTY_IMAGE = -24, + NV_BAD_FLAGS = -25, + NV_GBM_IO_ERR = -26, + NV_TGA_IO_ERR = -27, + NV_TGA_RLE_ERR = -28, + NV_PNG_IO_ERR = -29, + NV_CANT_CREATE_INDEX_BUFFER= -30, + NV_CANT_CREATE_CUBE_MAP = -31, + NV_BAD_FORMAT = -32, + NV_CANT_CREATE_TEXTURE = -33, + NV_UNKNOWN_FORMAT = -34, + NV_CANT_CREATE_VERTEX_BUFFER = -35, + NV_CANT_CREATE_PIXEL_SHADER= -36, + NV_CANT_CREATE_VERTEX_DECL = -37, + NV_NEED_4_PLANES_FOR_RGBE = -38, + NV_PSD_IO_ERR = -39, + NV_NO_FILENAME = -40, + + NV_CANT_DECOMPOSE_MATRIX = -41, + NV_HDR_IO_ERR = -42, + NV_RGBA_IO_ERR = -43, + NV_READ_FAILED = -44, + NV_WRITE_FAILED = -45, + NV_BAD_ARG = -46, + NV_CANT_LOCK = -47, + NV_FAILED_UNLOCK = -48, + NV_NOT_RING_LOOP = -49, + + NV_CHART_FOLDED = -50, + NV_CHART_CANNOT_INVERT = -51, + NV_CHART_BAD_PERIMETER = -52, + NV_CHART_NO_DATA = -53, + NV_CHART_CANT_OPTIMIZE = -54, + NV_CHART_NO_POINTS_FOUND = -55, + NV_CHART_ZERO_SIZE = -56, + NV_CHART_NO_UNPINNED = -57, + NV_CHART_OVERLAP = -58, + NV_CHART_NO_FACES = -59, + NV_CHART_MAX_DISTORTION_EXCEEDED = -60, + NV_CHART_AVE_DISTORTION_EXCEEDED = -61, + + NV_CANT_CREATE_PRECONDITIONER = -70, + NV_NO_CONVERGENCE = -71, + NV_ZERO_DIAGONAL = -72, + NV_ZERO_TRIANGLE_AREA = -73, + NV_LINE_ON_PLANE = -74, + NV_LINE_AND_PLANE_PARALLEL = -75, + NV_CANT_COMPILE_EFFECT_FILE = -76, + // open + NV_CANT_UNLOCK_INDEX_BUFFER = -78, + NV_CANT_CLONE_MESH = -79, + NV_CANT_FIND_FILE = -80, + NV_INVALID_FILENAME = -81, + NV_CANT_SET_MATRIX = -82, + NV_NEED_PIXEL_SHADER2 = -83, + NV_CANT_UNLOCK_TEXTURE = -84, + NV_OUT_OF_MEMORY = -85, + NV_TIFF_IO_ERR = -86, + + + NV_FILE_BAD_INDEX = -90, + NV_FILE_NOT_ENOUGH_INDICES = -91, + NV_FILE_FORMAT_NOT_SUPPORTED= -92, + NV_CANT_CREATE_EFFECT = -93, + NV_NAN = -94, + + NV_SURFACE_IS_CUBE_MAP = -95, + NV_SURFACE_IS_VOLUME_MAP = -96, + NV_UNSUPPORTED_FORMAT = -97, + NV_MEMORY_ALLOCATION_FAILED = -98, + NV_CUBE_MAP_NEEDS_SIX_FACES = -99, + NV_IMAGE_EXCEEDS_INTERNAL_SIZE = -100, + NV_CUBE_MAP_WIDTH_IS_NOT_SIX_TIMES_HEIGHT = -101, + NV_VOLUME_MAP_IS_NOT_POWER2 = -102, + + + + +}; + + const char *getErrorString(NV_ERROR_CODE hr); + + + diff --git a/NifProps/dds/nvdxt_options.h b/NifProps/dds/nvdxt_options.h new file mode 100644 index 0000000..3c82516 --- /dev/null +++ b/NifProps/dds/nvdxt_options.h @@ -0,0 +1,779 @@ +/**************************************************************************************** + + Copyright (C) NVIDIA Corporation 2003 + + TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED + *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS + BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES + WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, + BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) + ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS + BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +*****************************************************************************************/ +#pragma once + +#include <windows.h> +#include "tPixel.h" +#include "ddsTypes.h" + +inline char * GetDXTCVersion() { return "Version 8.30";} + +// max mip maps +#define MAX_MIP_MAPS 17 + + +typedef unsigned char nvBoolean; // for photoshop scripting + + + + +typedef struct nvNormalMap +{ +public: + + + nvNormalMap() + { + bEnableNormalMapConversion = false; + + minz = 0; + scale = 1; + filterKernel = kFilter3x3; + + heightConversionMethod = kAverageRGB; + alphaResult = kAlphaUnchanged; + + bWrap = false; + bInvertX = false; + bInvertY = false; + bInvertZ = false; + bAddHeightMap = false; + bNormalMapSwapRGB = false; + + + } + nvBoolean bEnableNormalMapConversion; // do not convert to a normal map + int minz; // minimum value the z value can attain in the x y z normal + // keeps normal point "upwards" + float scale; // height multiplier + + + + nvNormalMapFilters filterKernel; // kernel used to create normal maps. Done this way to be compatible with plugins + nvHeightConversionMethods heightConversionMethod; // method to convert color to height + nvAlphaResult alphaResult; // what to do with the alpha channel when done + + nvBoolean bWrap; + nvBoolean bInvertX; // flip the x direction + nvBoolean bInvertY; // flip the y direction + nvBoolean bInvertZ; // flip the z direction + + nvBoolean bAddHeightMap; + nvBoolean bNormalMapSwapRGB; // swap color channels +} nvNormalMap; + +class nvCompressionOptions +{ +public: + + nvCompressionOptions() + { + SetDefaultOptions(); + } + + + void SetDefaultOptions() + { + quality = kQualityProduction; + rmsErrorSearchThreshold = 400; // in kQualityHighest mode, rms error above which will cause a long search for a better answer + + rescaleImageType = kRescaleNone; + rescaleImageFilter = kMipFilterCubic; + scaleX = 1; + scaleY = 1; + bClamp = false; + clampX = 4096; + clampY = 4096; + + bClampScale = false; + clampScaleX = 4096; + clampScaleY = 4096; + + mipMapGeneration = kGenerateMipMaps; // dNoMipMaps, dUseExistingMipMaps, dGenerateMipMaps + numMipMapsToWrite = 0; // (number of mipmaps to write out) + + mipFilterType = kMipFilterTriangle; // for MIP maps + + bBinaryAlpha = false; // zero or one alpha channel + + bRGBE = false; + + bAlphaBorder = false; // make an alpha border + bAlphaBorderLeft = false; + bAlphaBorderRight = false; + + bAlphaBorderTop = false; + bAlphaBorderBottom = false; + + + bBorder = false; // make a color border + borderColor32F.r = 0.0f; // color of border + borderColor32F.g = 0.0f; // color of border + borderColor32F.b = 0.0f; // color of border + borderColor32F.a = 0.0f; // alpha of border + + bFadeColor = false; // fade color over MIP maps + bFadeAlpha = false; // fade alpha over MIP maps + + fadeToColor32F.r = 0.0f; // color to fade to + fadeToColor32F.g = 0.0f; // color to fade to + fadeToColor32F.b = 0.0f; // color to fade to + fadeToColor32F.a = 0.0f; // alpha to fade to + + fadeToDelay = 0; // start fading after 'n' MIP maps + + fadeAmount32F = 0.15f; // percentage of color to fade in %15 + + alphaThreshold32F = 0.5; // When Binary Alpha is selected, below this value, alpha is zero + + + bDitherColor = false; // enable dithering during 16 bit conversion + bDitherMip0 = false;// enable dithering during 16 bit conversion for each MIP level (after filtering) + + bForceDXT1FourColors = false; // do not let DXT1 use 3 color representation + + + sharpenFilterType = kSharpenFilterNone; + bErrorDiffusion = false; + errorDiffusionWidth = 1; + + weightType = kLuminanceWeighting; + bNormalizeTexels = false; + + weight[0] = 0.3086f; // luminance conversion values + weight[1] = 0.6094f; + weight[2] = 0.0820f; + + // gamma value for all filters + bEnableFilterGamma = false; + filterGamma = 2.2f; + + // alpha value for + filterBlur = 1.0f; + // width of filter + filterWidth = 10.0f; + bOverrideFilterWidth = false; + + textureType = kTextureTypeTexture2D; // regular decal, cube or volume + textureFormat = kDXT1; // + + bSwapRG = false; // swap color positions R and G + bSwapRB = false; // swap color positions R and G + user_data = NULL; // user supplied point passed down to write functions + + int i,j; + + float default_filter[5][5] = + { + 0, 0, 0, 0, 0, + 0, 0, -2, 0, 0, + 0,-2, 11,-2, 0, + 0, 0, -2, 0, 0, + 0, 0, 0, 0, 0, + }; + + + for(i = 0; i<5; i++) + { + for(j = 0; j<5; j++) + { + custom_filter_data.filter[i][j] = default_filter[i][j]; + } + } + + custom_filter_data.div = 3; // div + custom_filter_data.bias = 0; // bias + + unsharp_data.radius32F = 5.0; // radius + unsharp_data.amount32F = 0.5; // amount + unsharp_data.threshold32F = 0; // threshold + + xsharp_data.strength32F = 1.0f; // xsharp strength + xsharp_data.threshold32F = 1.0f; // xsharp threshold + + + sharpening_passes_per_mip_level[0] = 0; + + for(i = 1; i<MAX_MIP_MAPS; i++) + sharpening_passes_per_mip_level[i] = 1; + + bAlphaFilterModulate = false; + bPreModulateColorWithAlpha = false; + + + bUserSpecifiedFadingAmounts = false; + + + for(i = 0; i<256; i++) + { + color_palette[i].r = 0; + color_palette[i].g = 0; + color_palette[i].b = 0; + color_palette[i].a = 0; + } + + paletteSize = 0; // this will be set by the format read or write + autoGeneratePalette = false; + + + outputScale.r = 1.0f; // scale and bias when writing output values + outputScale.g = 1.0f; // scale and bias when writing output values + outputScale.b = 1.0f; // scale and bias when writing output values + outputScale.a = 1.0f; // scale and bias when writing output values + + outputBias.r = 0.0f; + outputBias.g = 0.0f; + outputBias.b = 0.0f; + outputBias.a = 0.0f; + + inputScale.r = 1.0f; // scale and bias after loading data + inputScale.g = 1.0f; // scale and bias + inputScale.b = 1.0f; // scale and bias + inputScale.a = 1.0f; // scale and bias + + inputBias.r = 0.0f; + inputBias.g = 0.0f; + inputBias.b = 0.0f; + inputBias.a = 0.0f; + + + + bConvertToGreyScale = false; + greyScaleWeight.r = 0.3086f; // scale and bias after loading data + greyScaleWeight.g = 0.6094f; // scale and bias + greyScaleWeight.b = 0.0820f; // scale and bias + greyScaleWeight.a = 0.0f; // scale and bias + + + brightness.r = 0.0; // adjust brightness = 0 none + brightness.g = 0.0; // + brightness.b = 0.0; // + brightness.a = 0.0; // + + contrast.r = 1; // contrast 1 == none + contrast.g = 1; + contrast.b = 1; + contrast.a = 1; + + bCalcLuminance = false; // do not convert to luminance by default + + bOutputWrap = false; // wrap the values when outputting to the desired format + // + + bCreateOnePalette = false; + + } + + /////////////////////////// COMPRESSION QUALITY ////////////////////////////////// + + nvQualitySetting quality; + float rmsErrorSearchThreshold; + + + void SetQuality(nvQualitySetting setting, float threshold) + { + quality = setting; + // if setting == kQualityHighest, if the RMS error for a 4x4 block is bigger than + // this, an extended search is performed. In practice this has been equivalent to and + // exhaustive search in the entire domain. aka it doesn't get any better than this. + + rmsErrorSearchThreshold = threshold; + + + } + + /////////////////////////////// COMPRESSION WEIGHTING ////////////////////////////// + nvCompressionWeighting weightType; // weighting type for DXT compressop + float weight[3]; // weights used for compress + + void SetCompressionWeighting(nvCompressionWeighting type, float new_weight[3]) + { + weightType = type; + + // if type == kUserDefinedWeighting, then use these weights + weight[0] = new_weight[0]; + weight[1] = new_weight[1]; + weight[2] = new_weight[2]; + + } + + + ///////////////////////////////////////////////////////////// + + nvNormalMap normalMap; // filled when processing normal maps + + nvBoolean bNormalizeTexels; // normalize the texels + + + + + /////////////////////////// SCALING IMAGE ///////////////////////////////// + + nvRescaleTypes rescaleImageType; // rescaling type before image before compression + nvMipFilterTypes rescaleImageFilter; // rescaling filter + + float scaleX; // scale to this if we are prescaling images before compressing + float scaleY; + + + // scale the image to this size first + void PreScaleImage(float x, float y, nvMipFilterTypes filter) + { + rescaleImageType = kRescalePreScale; + scaleX = x; + scaleY = y; + rescaleImageFilter = filter; + } + // relative scaling. 0.5 is half the image size + void RelativeScaling(float x, float y, nvMipFilterTypes filter) + { + rescaleImageType = kRescaleRelScale; + scaleX = x; + scaleY = y; + rescaleImageFilter = filter; + + } + + void RescaleToNearestPOW2(nvMipFilterTypes filter) + { + rescaleImageType = kRescaleNearestPower2; + rescaleImageFilter = filter; + + } + void RescaleToNearestBiggestPOW2(nvMipFilterTypes filter) + { + rescaleImageType = kRescaleBiggestPower2; + rescaleImageFilter = filter; + + } + void RescaleToNearestSmallestPOW2(nvMipFilterTypes filter) + { + rescaleImageFilter = filter; + rescaleImageType = kRescaleSmallestPower2; + + } + void RescaleToNearestNextSmallestPOW2(nvMipFilterTypes filter) + { + rescaleImageType = kRescaleNextSmallestPower2; + rescaleImageFilter = filter; + + } + + /////////////////// CLAMPING IMAGE SIZE /////////////////////////////////// + nvBoolean bClamp; // Clamp to max size + float clampX; // clamping values + float clampY; + + // image no bigger than... + void ClampMaxImageSize(float maxX, float maxY) + { + bClamp = true; + clampX = maxX; + clampY = maxY; + } + + + nvBoolean bClampScale; // maximum value of h or w (retain scale) + float clampScaleX; // clamping values + float clampScaleY; + + // clamp max image size and maintain image proportions. + // Evenly scale down in both directions so that the given image size is not exceeded + void ClampMaxImageSizeContrained(float maxX, float maxY) + { + bClampScale = true; + clampScaleX = maxX; + clampScaleY = maxY; + } + + ///////////////////////////// MIP MAPS /////////////////////////////////// + + nvMipMapGeneration mipMapGeneration; // changed MIPMaptype to an enum + + long numMipMapsToWrite; // max number of Mip maps to generate + + // 0 = all + void GenerateMIPMaps(int n) + { + mipMapGeneration = kGenerateMipMaps; + numMipMapsToWrite = n; + + } + void DoNotGenerateMIPMaps() + { + mipMapGeneration = kNoMipMaps; + + } + void UseExisitingMIPMaps() + { + // what ever is in the image + mipMapGeneration = kUseExistingMipMaps; + //numMipMapsToWrite is ignored + } + void CompleteMIPMapChain(int n) + { + mipMapGeneration = kCompleteMipMapChain; + numMipMapsToWrite = n; + } + + nvMipFilterTypes mipFilterType; // for MIP map, select from MIPFilterTypes + + + /////////////////// ALPHA ////////////////////////////////////////// + nvBoolean bBinaryAlpha; // zero or one alpha channel + + // [0,1] + float alphaThreshold32F; // threshold for alpha transparency DXT1 + // or wen Binary Alpha is selected, below this value, alpha is zero + + void SetBinaryAlpha(float threshold) + { + bBinaryAlpha = true; + alphaThreshold32F = threshold; + + } + + + + + ////////////////////////// BORDERS ///////////////////////////////////////// + + // set any of these to generate an alpha border + nvBoolean bAlphaBorder; // make an alpha border + nvBoolean bAlphaBorderLeft; // make an alpha border on just the left + nvBoolean bAlphaBorderRight; // make an alpha border on just the right + + nvBoolean bAlphaBorderTop; // make an alpha border on just the top + nvBoolean bAlphaBorderBottom; // make an alpha + + nvBoolean bBorder; // make a color border + fpPixel borderColor32F; // color of border [0,1] + + void SetBorderColor(fpPixel & color) + { + bBorder = true; + borderColor32F = color; + + } + void NoBorderColor() + { + bBorder = false; + + } + + /////////////////////// FADING MIP LEVELS //////////////////////////// + + nvBoolean bFadeColor; // fade color over MIP maps + nvBoolean bFadeAlpha; // fade alpha over MIP maps + + fpPixel fadeToColor32F; // color and alpha to fade to + + long fadeToDelay; // start fading after 'n' MIP maps + + float fadeAmount32F; // percentage of color to fade in + + nvBoolean bUserSpecifiedFadingAmounts; + float userFadingAmounts[MAX_MIP_MAPS]; + + + // [0,1] + void FadeAlphaInMIPMaps(float alpha) + { + bFadeAlpha = true; + fadeToColor32F.a = alpha; + + + } + // 0 - 255 + void FadeColorInMIPMaps(float r, float g, float b) + { + fadeToColor32F.r = r; + fadeToColor32F.g = g; + fadeToColor32F.b = b; + + + bFadeColor = true; + } + void SetFadingAsPercentage(float percentPerMIP, int mipLevelToStartFading) + { + bUserSpecifiedFadingAmounts = false; + + fadeAmount32F = percentPerMIP; + fadeToDelay = mipLevelToStartFading; + } + // or + void SpecifyFadingPerMIPLevel(float fadeAmounts[MAX_MIP_MAPS]) + { + bUserSpecifiedFadingAmounts = true; + + for(int i = 0; i < MAX_MIP_MAPS; i++) + { + userFadingAmounts[i] = fadeAmounts[i]; + } + } + + + + /////////////////////////// SHARPENING ///////////////////////////////////// + + // sharpening after creating each MIP map level + + // used when custom sharping filter is used + // 5x5 filter + struct + { + float filter[5][5]; + float div; + float bias; + + } custom_filter_data; + + + + // used when unsharpen sharping filter is used + struct + { + float radius32F; // radius + float amount32F; // amount + float threshold32F; // threshold [0,1] + + } unsharp_data; + + // used when xsharpen sharping filter is used + struct + { + // 0 - 1 + float strength32F; + float threshold32F; + } xsharp_data; + + + int sharpening_passes_per_mip_level[MAX_MIP_MAPS]; + + nvSharpenFilterTypes sharpenFilterType; // post filtering image sharpening + + + void SetNumberOfSharpeningPassesPerMIPLevel( int passes[MAX_MIP_MAPS]) + { + for (int i = 0; i < MAX_MIP_MAPS; i++) + { + sharpening_passes_per_mip_level[i] = passes[i]; + } + } + + // [0,1] + void XSharpenImage(float strength, float threshold) + { + sharpenFilterType = kSharpenFilterXSharpen; + xsharp_data.strength32F = strength; + xsharp_data.threshold32F = threshold; + } + + void UnSharpenImage(float radius, float amount, float threshold) + { + sharpenFilterType = kSharpenFilterUnSharp; + unsharp_data.radius32F = radius; + unsharp_data.amount32F = amount; + unsharp_data.threshold32F = threshold; + } + + // roll your own post filter sharpen + void SetCustomFilter(float filter[5][5], float div, float bias) + { + sharpenFilterType = kSharpenFilterCustom; + custom_filter_data.div = div; + custom_filter_data.bias = bias; + + for(int i = 0; i<5; i++) + for(int j = 0; j<5; j++) + custom_filter_data.filter[i][j] = filter[i][j]; + + } + + ///////////////////////////////////////////////////// + + + + + + nvBoolean bErrorDiffusion; // diffuse error, used for helping gradient images + int errorDiffusionWidth; // number of texel to include + + void EnableErrorDiffusion(int width) + { + bErrorDiffusion = true; + errorDiffusionWidth = width; + } + ///////////////////// FILTERING //////////////////////////////////////// + // convert to gamma space before filtering + nvBoolean bEnableFilterGamma; + float filterGamma; // gamma value for filtering (MIP map generation) + + + float filterBlur; // sharpness or blurriness of filtering + nvBoolean bOverrideFilterWidth; // use the specified width in FilterWidth,instead of the default + float filterWidth; // override fiter width with this value + + + // 0 is no gamma correction + void EnableGammaFiltering(float gamma) + { + bEnableFilterGamma = true; + + filterGamma = gamma; + } + + void OverrideFilterWidth(float w) + { + bOverrideFilterWidth = true; + filterWidth = w; + + + } + void SetFilterSharpness(float sharp) + { + filterBlur = sharp; + } + + ///////////////////////////////////////////////////// + + + + + nvTextureTypes textureType; // what type of texture is this? + + + nvTextureFormats textureFormat; // format to convert to + + void SetTextureFormat(nvTextureTypes type, nvTextureFormats format ) + { + textureType = type; + textureFormat = format; + } + + + size_t paletteSize; + rgba_t color_palette[256]; + + nvBoolean autoGeneratePalette; // generate palette for p8 and p4 formats + + + // for P4 and P8 formats + // set 16 for P4 format and 256 for P8 format + + void SetPalette(int n, rgba_t user_palette[256]) + { + paletteSize = n; + for(int i = 0; i < n; i++) + color_palette[i] = user_palette[i]; + + autoGeneratePalette = false; + + } + + + + + ////////////////// DATA SCALING + + + fpPixel outputScale; // scale and bias when writing output values + fpPixel outputBias; + + void ScaleBiasOutput(fpPixel & scale, fpPixel & bias) + { + outputScale = scale; + outputBias = bias; + + } + + + fpPixel inputScale; // scale and bias on input to compressor + fpPixel inputBias; + + void ScaleBiasInput(fpPixel & scale, fpPixel & bias) + { + inputScale = scale; + inputBias = bias; + + } + + /////////////////////////////////////////////////////////////////////////////////// + + bool bConvertToGreyScale; + fpPixel greyScaleWeight; + + void SetGreyScale(fpPixel & w) + { + bConvertToGreyScale = true; + greyScaleWeight = w; + + } + + + + + ///////////////////////////////////////////////////////////////////////////// + fpPixel brightness; + fpPixel contrast; + + + void SetBrightnessAndContrast(fpPixel & _brightness, fpPixel & _contrast) + { + brightness = _brightness; + contrast = _contrast; + } + + + + /////////// general enables + ///////////////////////////////////////////////////////////////////////////// + nvBoolean bOutputWrap; // wrap the values (before clamping to the format range) + // when outputting to the desired format + + nvBoolean bCalcLuminance; // convert color to luminance for 'L' formats + + nvBoolean bSwapRB; // swap color positions R and G + nvBoolean bSwapRG; // swap color positions R and G + + + nvBoolean bForceDXT1FourColors; // do not let DXT1 use 3 color representation + + + nvBoolean bRGBE; // rgba_t is in RGBE format + + nvBoolean bCreateOnePalette; // All 4x4 compression blocks share the same palette + + + + + /////////////////// DISABLED + + nvBoolean bDitherColor; // enable dithering during 16 bit conversion + nvBoolean bDitherMip0; // enable dithering during 16 bit conversion for each MIP level (after filtering) + + + nvBoolean bPreModulateColorWithAlpha; // modulate color by alpha + nvBoolean bAlphaFilterModulate; // modulate color by alpha for filtering only + + + + ///////////////////////// USER DATA + + void * user_data; // user supplied values passed down to write functions + +} ; + diff --git a/NifProps/dds/tPixel.h b/NifProps/dds/tPixel.h new file mode 100644 index 0000000..d34f9e8 --- /dev/null +++ b/NifProps/dds/tPixel.h @@ -0,0 +1,1840 @@ +#pragma once + +#include <math.h> +#include <memory.h> +#include "tVector.h" +#include "nvErrorCodes.h" + +#pragma warning(disable : 4201) + +namespace nv +{ +// modulo value x between [lo,hi] +// allows value 'hi' +template < class _Type > +inline _Type Clamp(const _Type &x, + const _Type &lo, + const _Type &hi) +{ + if (x < lo) + return lo; + else if (x > hi) + return hi; + else + return x; +} + + +inline int iClamp(int x, int lo, int hi) +{ + if (x < lo) + return lo; + if (x > hi) + return hi; + return x; +} + +inline float fClamp(float x, float lo, float hi) +{ + if (x < lo) + return lo; + if (x > hi) + return hi; + return x; +} + + +inline int fmod(int x, int size) +{ + return x % size; +} + +inline __int64 fmod(__int64 x, __int64 size) +{ + return x % size; +} +inline unsigned __int64 fmod(unsigned __int64 x, unsigned __int64 size) +{ + return x % size; +} + + +inline float __cdecl fmod(float _X, float _Y) +{ + return ( fmodf(_X, _Y) ); +} + +// calcMaxMipmap +// calculates max # of mipmap levels for given texture size +inline size_t calcMaxMipmap(size_t w, size_t h) +{ + size_t n = 0; + size_t count = 0; + + assert(w >= 0); + assert(h >= 0); + + if (w < h) + count = h; + else + count = w; + + while (count) + { + n++; + count >>= 1; + } + return n; +} + + +inline size_t calcMaxMipmap(size_t w, size_t h, size_t d) +{ + size_t n = 0; + size_t count = 0; + + assert(w >= 0); + assert(h >= 0); + assert(d >= 0); + + if (w < h) + count = h; + else + count = w; + + if (d > count) + count = d; + + + while (count) + { + n++; + count >>= 1; + } + return n; +} + + +// get next mip level size +inline size_t NextMip(size_t m) +{ + size_t next = m / 2; // round down + if (next == 0) + return 1; + else + return next; +} + + + +// lo = 0; +// allow hi value +template < class _Type > +inline _Type Modulo(const _Type &x, const _Type &hi) +{ + if (x >= 0 && x <= hi) + return x; + + _Type f = fmod(x, hi); + + if (f < 0) + f += hi; + + return f; +} +// does not allow x == size +inline int iModulo(int x, int size) +{ + if (x < 0) + { + int n = x / size; + x += size * (n + 1); + } + + return x % size; +} + + + +template < class _Type > +inline _Type Modulo(const _Type &x, const _Type &lo, const _Type &hi) +{ + if (x >= lo && x <= hi) + return x; + + _Type dw = hi - lo; + _Type t = x - lo; + + _Type f = fmod(t, dw); + + + if (f < 0) + f += dw; + + f += lo; + + return f; +} + +} + + + + +#pragma pack(push,4) + +// red and green +class v16u16_t +{ +public: + + union + { + short uv[4]; + struct + { + short u; + short v; + }; + }; + v16u16_t & operator += ( const v16u16_t & v ); // incrementation by a Vec4f + + + void set(unsigned short _u, unsigned short _v) + { + u = _u; + v = _v; + } +}; + +class r12g12b8_t +{ +public: + + union + { + + struct + { + unsigned long r:12; + unsigned long g:12; + unsigned long b:8; + }; + }; + r12g12b8_t & operator += ( const r12g12b8_t& v ); // incrementation by a Vec4f + + + void set(unsigned long _r, unsigned long _g, unsigned long _b) + { + r = _r; + g = _g; + b = _b; + } +}; + + + +class rgba_t +{ +public: + + union + { + unsigned long u; + unsigned char p[4]; + struct + { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + }; + }; + + rgba_t() + { + } + + // + + unsigned long bgra() + { + + return ((unsigned long)a << 24) | ((unsigned long)r << 16) | ((unsigned long)g << 8) | ((unsigned long)b); + } + rgba_t(unsigned char _r, unsigned char _g, unsigned char _b,unsigned char _a) + { + a = _a; + r = _r; + g = _g; + b = _b; + } + + rgba_t & operator += ( const rgba_t& v ) // incrementation by a rgba_t + { + r = (unsigned char)nv::Clamp((int)((int)r + (int)v.r), 0, 255); + g = (unsigned char)nv::Clamp((int)g + (int)v.g, 0, 255); + b = (unsigned char)nv::Clamp((int)b + (int)v.b, 0, 255); + a = (unsigned char)nv::Clamp((int)a + (int)v.a, 0, 255); + + return *this; + } + + rgba_t & operator -= ( const rgba_t& v ); // decrementation by a rgba_t + rgba_t & operator *= ( const float d ); // multiplication by a constant + rgba_t & operator /= ( const float d ); // division by a constant + + + rgba_t& operator = (const rgba_t& v) + { + r = v.r; + g = v.g; + b = v.b; + a = v.a; + return *this; + } + + friend rgba_t operator + (const rgba_t & v1, const rgba_t& v2) + { + + int r,g,b,a; + r = nv::Clamp((int)v1.r + (int)v2.r, 0, 255); + g = nv::Clamp((int)v1.g + (int)v2.g, 0, 255); + b = nv::Clamp((int)v1.b + (int)v2.b, 0, 255); + a = nv::Clamp((int)v1.a + (int)v2.a, 0, 255); + + return rgba_t((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); + } + + friend rgba_t operator / (const rgba_t& v, float s) + { + return rgba_t( + (unsigned char)(v.r/s), + (unsigned char)(v.g/s), + (unsigned char)(v.b/s), + (unsigned char)(v.a/s)); + } + + friend rgba_t operator / (const rgba_t& v, int s) + { + return rgba_t( + (unsigned char)(v.r/s), + (unsigned char)(v.g/s), + (unsigned char)(v.b/s), + (unsigned char)(v.a/s)); + } + + void set(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } + + void SetToZero() + { + r = g = b = a = 0; + } +}; + +class rgba16_t +{ +public: + + union + { + //unsigned __int64 u; + unsigned short rgba[4]; + struct + { + unsigned short r; + unsigned short g; + unsigned short b; + unsigned short a; + }; + }; + + rgba16_t() + { + } + rgba16_t(unsigned short _r, unsigned short _g, unsigned short _b,unsigned short _a) + { + a = _a; + r = _r; + g = _g; + b = _b; + } + + rgba16_t & operator += ( const rgba16_t& v ) // incrementation by a rgba_t + { + r = (unsigned char)nv::Clamp((int)r + (int)v.r, 0, 65535); + g = (unsigned char)nv::Clamp((int)g + (int)v.g, 0, 65535); + b = (unsigned char)nv::Clamp((int)b + (int)v.b, 0, 65535); + a = (unsigned char)nv::Clamp((int)a + (int)v.a, 0, 65535); + + return *this; + } + + rgba16_t & operator -= ( const rgba16_t& v ); // decrementation by a rgba_t + rgba16_t & operator *= ( const float d ); // multiplication by a constant + rgba16_t & operator /= ( const float d ); // division by a constant + + + rgba16_t& operator = (const rgba16_t& v) + { + r = v.r; + g = v.g; + b = v.b; + a = v.a; + return *this; + } + + friend rgba16_t operator + (const rgba16_t & v1, const rgba16_t& v2) + { + + int r,g,b,a; + r = nv::Clamp((int)v1.r + (int)v2.r, 0, 65535); + g = nv::Clamp((int)v1.g + (int)v2.g, 0, 65535); + b = nv::Clamp((int)v1.b + (int)v2.b, 0, 65535); + a = nv::Clamp((int)v1.a + (int)v2.a, 0, 65535); + + return rgba16_t((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); + } + + friend rgba16_t operator / (const rgba16_t& v, float s) + { + return rgba16_t((unsigned short)(v.r/s), + (unsigned short)(v.g/s), + (unsigned short)(v.b/s), + (unsigned short)(v.a/s)); + } + + friend rgba16_t operator / (const rgba16_t& v, int s) + { + return rgba16_t( + (unsigned short)(v.r/s), + (unsigned short)(v.g/s), + (unsigned short)(v.b/s), + (unsigned short)(v.a/s)); + } + + void set(unsigned short _r, unsigned short _g, unsigned short _b, unsigned short _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } +}; + + +class urgba_t +{ +public: + + union + { + unsigned long u; + char rgba[4]; + struct + { + char r; + char g; + char b; + char a; + }; + }; + urgba_t & operator += ( const urgba_t& v ); // incrementation by a Vec4f + + + void set(char _r, char _g, char _b, char _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } +}; + + + + +class q8w8v8u8_t +{ +public: + + union + { + char qwvu[4]; + struct + { + char q; + char w; + char v; + char u; + }; + }; + q8w8v8u8_t & operator += ( const q8w8v8u8_t& v ); // incrementation by a Vec4f + + + void set(char _r, char _g, char _b, char _a) + { + q = _r; + w = _g; + v = _b; + u = _a; + } +}; + + + + + + + +#define _R 0 +#define _G 1 +#define _B 2 +#define _A 3 + + + + +class fpPixel +{ +public: + union + { + float p[4]; + struct + { + float r; + float g; + float b; + float a; + }; + struct + { + float x; + float y; + float z; + float w; + }; + + }; + + void SetToZero() + { + r = 0; + g = 0; + b = 0; + a = 0; + + } + + + void Clamp(fpPixel & lo, fpPixel & hi) + { + + r = nv::Clamp(r, lo.r, hi.r); + g = nv::Clamp(g, lo.g, hi.g); + b = nv::Clamp(b, lo.b, hi.b); + a = nv::Clamp(a, lo.a, hi.a); + } + + void Wrap(fpPixel & lo, fpPixel & hi) + { + + r = nv::Modulo(r, lo.r, hi.r); + g = nv::Modulo(g, lo.g, hi.g); + b = nv::Modulo(b, lo.b, hi.b); + a = nv::Modulo(a, lo.a, hi.a); + + + + + } + + + void dot(fpPixel & w) + { + float grey = r * w.r + + g * w.g + + b * w.b + + a * w.a; + r = grey; + g = grey; + b = grey; + + } + + + + //float& operator () ( int i) { return p[i]; }; // indexing + //const float& operator()(int i) const { return p[i];} + + + + fpPixel() {} + fpPixel(const float _r, const float _g, const float _b, const float _a) + { + a = _a; + r = _r; + g = _g; + b = _b; + } + + + fpPixel(const fpPixel& v) + { + a = v.a; + r = v.r; + g = v.g; + b = v.b; + } // copy constructor + + void set(const float _r, const float _g, const float _b, const float _a) + { + a = _a; + r = _r; + g = _g; + b = _b; + } + + void set(const fpPixel& v) + { + a = v.a; + r = v.r; + g = v.g; + b = v.b; + } + + + fpPixel & operator += ( const fpPixel& v ) // incrementation by a rgba_t + { + r += v.r; + g += v.g; + b += v.b; + a += v.a; + + return *this; + } + + + fpPixel & operator -= ( const fpPixel& v ) // incrementation by a rgba_t + { + r -= v.r; + g -= v.g; + b -= v.b; + a -= v.a; + + return *this; + } + + + fpPixel & operator *= ( const fpPixel& v ) // incrementation by a rgba_t + { + r *= v.r; + g *= v.g; + b *= v.b; + a *= v.a; + + return *this; + } + + fpPixel & operator /= ( const fpPixel& v ) // incrementation by a rgba_t + { + r /= v.r; + g /= v.g; + b /= v.b; + a /= v.a; + + return *this; + } + + fpPixel & operator /= ( const float& s ) // incrementation by a rgba_t + { + r /= s; + g /= s; + b /= s; + a /= s; + + return *this; + } + + fpPixel & operator = ( const fpPixel& v ); // assignment of a Vec3f + + + + friend fpPixel operator + (const fpPixel& v1, const fpPixel& v2) + { + return fpPixel(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a); + } + + friend fpPixel operator / (const fpPixel& v, float s) + { + return fpPixel(v.r/s, v.g/s, v.b/s, v.a/s); + + } + friend int operator == (const fpPixel& v1, const fpPixel& v2); // v1 == v2 ? + + NV_ERROR_CODE normalize() + { + double u; + u = x * x + y * y + z * z; + + if ( fabs(u - 1.0) < 1e-12) + return NV_OK; // already normalized + + if ( fabs((double)u) < 1e-12) + { + x = y = z = 0.0f; + return NV_CANT_NORMALIZE; + } + + + u = 1.0 / sqrt(u); + + + x = (float)(x*u); + y = (float)(y*u); + z = (float)(z*u); + + return NV_OK; + } + + +}; + + + +class fpPixel3 +{ +public: + union + { + float p[3]; + struct + { + float r; + float g; + float b; + }; + struct + { + float x; + float y; + float z; + }; + + }; + + + void SetToZero() + { + r = 0; + g = 0; + b = 0; + } + + //float& operator () ( int i) { return p[i]; }; // indexing + //const float& operator()(int i) const { return p[i];} + + + + fpPixel3() {} + fpPixel3(const float _r, const float _g, const float _b) + { + r = _r; + g = _g; + b = _b; + } + + + fpPixel3(const fpPixel3& v) + { + r = v.r; + g = v.g; + b = v.b; + } // copy constructor + + void set(const float _r, const float _g, const float _b) + { + r = _r; + g = _g; + b = _b; + } + + void set(const fpPixel3& v) + { + r = v.r; + g = v.g; + b = v.b; + } + + fpPixel3 & operator += ( const fpPixel3& v ); // incrementation by a Vec4f + + fpPixel3 & operator = ( const fpPixel3& v ); // assignment of a Vec3f + fpPixel3 & operator -= ( const fpPixel3& v ); // decrementation by a Vec3f + fpPixel3 & operator *= ( const float d ); // multiplication by a constant + fpPixel3 & operator /= ( const float d ); // division by a constant + + + + friend fpPixel3 operator + (const fpPixel3& v1, const fpPixel3& v2) + { + return fpPixel3(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); + } + + friend fpPixel3 operator / (const fpPixel3& v, float s) + { + return fpPixel3(v.r/s, v.g/s, v.b/s); + + } + friend int operator == (const fpPixel3& v1, const fpPixel3& v2); // v1 == v2 ? + + NV_ERROR_CODE normalize() + { + double u; + u = x * x + y * y + z * z; + + if ( fabs(u - 1.0) < 1e-12) + return NV_OK; // already normalized + + if ( fabs((double)u) < 1e-12) + { + x = y = z = 0.0f; + return NV_CANT_NORMALIZE; + } + + + u = 1.0 / sqrt(u); + + + x = (float)(x*u); + y = (float)(y*u); + z = (float)(z*u); + + return NV_OK; + } + + +}; + + +typedef fpPixel * fp_i; + + +inline int operator == (const fpPixel& v1, const fpPixel& v2) +{ + return + v1.a == v2.a && + v1.r == v2.r && + v1.b == v2.g && + v1.g == v2.b; +} + +inline fpPixel& fpPixel::operator = (const fpPixel& v) +{ + a = v.a; + r = v.r; + g = v.g; + b = v.b; + return *this; +} + + + + + + + +template <class _Type> +class nvImage +{ + size_t m_width; + size_t m_height; + nvVector<_Type> m_pixels; + + bool m_RGBE; + + +public: + void SetRGBE(bool b) + { + m_RGBE = b; + } + + bool isRGBE() const + { + return m_RGBE; + } + + + + size_t size() + { + return m_width * m_height; + } + + + nvImage < _Type > & operator = ( const nvImage < _Type >& v ) + { + + // resize and copy over + resize(v.width(), v.height()); + + m_pixels = v.m_pixels; + m_RGBE = v.m_RGBE; + + return *this; + } + + + _Type& operator [] ( size_t i) + { +#ifdef _DEBUG + assert(i < m_width * m_height); +#endif + return m_pixels[i]; + }; + + const _Type& operator[](size_t i) const + { +#ifdef _DEBUG + assert(i < m_width * m_height); +#endif + return m_pixels[i]; + } + + _Type & operator () (const size_t &y, const size_t &x) + { +#if _DEBUG + assert(y < m_height); + assert(x < m_width); +#endif + return m_pixels[y * m_width + x]; + + } + const _Type & operator () (const size_t &y, const size_t &x) const + { +#if _DEBUG + assert(y < m_height); + assert(x < m_width); +#endif + return m_pixels[y * m_width + x]; + + } + + + size_t width() const + { + return m_width; + + } + + size_t height() const + { + return m_height; + + } + + + + _Type * pixels(size_t n = 0) + { + + return &m_pixels[n]; + } + _Type * pixelsXY(size_t x, size_t y) + { + return &m_pixels[y * width() + x]; + } + _Type * pixelsXY_Safe(size_t x, size_t y) + { + if (m_pixels.size() == 0) + return 0; + else + return &m_pixels[y * width() + x]; + } + + _Type * pixelsYX(size_t y, size_t x) + { + return &m_pixels[y * width() + x]; + + } + // row / column + _Type * pixelsRC(size_t y, size_t x) + { + return &m_pixels[y * width() + x]; + + } + + + _Type & pixel_ref(size_t n = 0) + { + return m_pixels[n]; + } + _Type & pixelsXY_ref(size_t x, size_t y) + { + return m_pixels[y * width() + x]; + } + + _Type & pixelsYX_ref(size_t y, size_t x) + { + return m_pixels[y * width() + x]; + + } + // row / column + _Type & pixelsRC_ref(size_t y, size_t x) + { + return m_pixels[y * width() + x]; + + } + + _Type * pixelsXY_wrapped(int x, int y) + { + y = mod(y, m_height); + x = mod(x, m_width); + + return &m_pixels[y * m_width + x]; + } + + + + nvImage( const nvImage < _Type > & other) + { + m_width = other.m_width; + m_height = other.m_height; + + m_pixels = other.m_pixels; + m_RGBE = other.m_RGBE; + + + } + + nvImage() + { + m_width = 0; + + m_height = 0; + m_RGBE = false; + + m_pixels.clear(); + + }; + ~nvImage() + { + + } + void clear() + { + m_width = 0; + m_height = 0; + m_pixels.clear(); + } + + void resize(size_t width, size_t height) + { + m_pixels.resize(width * height); + m_width = width; + m_height = height; + + } + void realloc(size_t width, size_t height) + { + m_pixels.realloc(width * height); + m_width = width; + m_height = height; + + } + + nvImage<_Type>(size_t width, size_t height) + { + m_pixels.resize(width * height); + m_width = width; + m_height = height; + m_RGBE = false; + + }; + + + void SwapRB() + { + + _Type * p = &m_pixels[0]; + _Type tmp; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + + tmp.r = p->r; + p->r = p->b; + p->b = tmp.r; + + p++; + } + } + + + + void Scale(_Type s) + { + + _Type * p = &m_pixels[0]; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + *p++ *= s; + } + + } + + void Bias(_Type b) + { + + _Type * p = &m_pixels[0]; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + *p++ += b; + } + + } + + + void dot(_Type w) + { + + + _Type * p = &m_pixels[0]; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + p->dot(w); + p++; + } + } + + + + void Clamp(_Type low, _Type hi) + { + + _Type * p = &m_pixels[0]; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + p->Clamp(low, hi); + p++; + } + + } + + void Wrap(_Type low, _Type hi) + { + _Type * p = &m_pixels[0]; + for(size_t i=0; i < m_width * m_height; i++ ); + { + + p->Wrap(low, hi); + p++; + } + + } + + + + void FlipTopToBottom() + { + + _Type * swap = new _Type[ m_width]; + + size_t row; + + _Type * end_row; + _Type * start_row; + + size_t len = sizeof(_Type) * m_width; + + for( row = 0; row < m_height / 2; row ++ ) + { + end_row = &m_pixels[ m_width * ( m_height - row - 1) ]; + start_row = &m_pixels[ m_width * row ]; + + // copy row toward end of image into temporary swap buffer + memcpy( swap, end_row, len ); + + // copy row at beginning to row at end + memcpy( end_row, start_row, len ); + + // copy old bytes from row at end (in swap) to row at beginning + memcpy( start_row, swap, len ); + } + + delete [] swap; + } + + void SetToZero() + { + + for(size_t i=0; i< m_width * m_height; i++) + { + pixel_ref(i).SetToZero(); + + } + } + void SetToZeroDirect() + { + for(size_t i=0; i< m_width * m_height; i++) + { + m_pixels[i] = 0; + + } + } + + + +}; + + + + + +typedef nvImage<rgba_t> RGBAImage; +typedef nvVector<RGBAImage> RGBAImageArray; + + +class RGBAMipMappedImage +{ + RGBAImageArray mipArray; // array of images, one for each MIP map RGBA + + +public: + + + void resize(size_t width, size_t height, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height); + + mipArray.resize(nMIPMaps); + + for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++) + { + RGBAImage & mip = mipArray[mipLevel]; + + mip.resize(width, height); + + width = nv::NextMip(width); + height = nv::NextMip(height); + + } + + + } + + + RGBAMipMappedImage(int width, int height, int nMIPMaps) + { + resize(width, height, nMIPMaps); + + + + } + RGBAMipMappedImage() + { + + + + } + + + + RGBAImage & operator [] ( size_t i) { return mipArray[i]; }; // indexing + const RGBAImage& operator[](size_t i) const { return mipArray[i];} + + size_t numMIPMaps() const + { + return mipArray.size(); + } + + + void resize(size_t size) + { + mipArray.resize(size); + } + void realloc(size_t size) + { + mipArray.realloc(size); + } + + size_t width() const + { + if (mipArray.size() == 0) + return 0; + return mipArray[0].width(); + + } + size_t height() const + { + if (mipArray.size() == 0) + return 0; + return mipArray[0].height(); + + } + + void clear() + { + mipArray.clear(); + } + + +}; + + +class RGBAMipMappedCubeMap +{ + RGBAMipMappedImage cubeFaces[6]; // array of images, one for each MIP map RGBA + +public: + + void resize(size_t width, size_t height, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height); + + for(int f = 0; f < 6; f++) + { + RGBAMipMappedImage & mipFace = cubeFaces[f]; + mipFace.resize(width, height, nMIPMaps); + } + + + } + + RGBAMipMappedCubeMap(size_t width, size_t height, size_t nMIPMaps) + { + resize(width, height, nMIPMaps); + + } + + RGBAMipMappedCubeMap() + { + } + + RGBAMipMappedImage & operator [] ( size_t i) { return cubeFaces[i]; }; // indexing + const RGBAMipMappedImage& operator[](size_t i) const { return cubeFaces[i];} + + + size_t numMIPMaps() const + { + return cubeFaces[0].numMIPMaps(); + } + + size_t height() const + { + return cubeFaces[0].height(); + } + + size_t width() const + { + return cubeFaces[0].height(); + } + + void clear() + { + for(size_t f = 0; f < 6; f++) + { + RGBAMipMappedImage & mipFace = cubeFaces[f]; + mipFace.clear(); + } + + } + + + + +}; + + + +typedef nvVector< RGBAImageArray > RGBAVolume; + +class RGBAMipMappedVolumeMap +{ + // array of MIP mapped images + RGBAVolume volumeArray; + +public: + + void resize(size_t width, size_t height, size_t depth, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height, depth); + + volumeArray.resize(nMIPMaps); + + size_t w = width; + size_t h = height; + size_t d = depth; + + for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++) + { + + RGBAImageArray & volImage = volumeArray[mipLevel]; + + volImage.resize(d); + + + for(size_t slice = 0; slice < d; slice++) + { + RGBAImage & mipFace = volImage[slice]; + + mipFace.resize(w, h); + } + w = nv::NextMip(w); + h = nv::NextMip(h); + d = nv::NextMip(d); + + + } + } + + + RGBAMipMappedVolumeMap(size_t width, size_t height, size_t depth, size_t nMIPMaps) + { + resize(width, height, depth, nMIPMaps); + } + + + // mip level + RGBAImageArray & operator [] ( size_t i) { return volumeArray[i]; }; // indexing + const RGBAImageArray& operator[](size_t i) const { return volumeArray[i];} + + RGBAMipMappedVolumeMap() + { + } + size_t numMIPMaps() const + { + return volumeArray.size(); + } + + + + + const RGBAImageArray * vol0() const + { + if (numMIPMaps() == 0) + return 0; + + return &volumeArray[0]; + } + + + const RGBAImage * slice0() const + { + const RGBAImageArray * v0 = vol0(); + + if (v0 == 0) + return 0; + + if (v0->size() == 0) + return 0; + + const RGBAImageArray &array = *v0; + + return &array[0]; + } + + size_t width() const + { + const RGBAImage * image0 = slice0(); + + if (image0 == 0) + return 0; + + else + return image0->width(); + + } + size_t height() const + { + const RGBAImage * image0 = slice0(); + + if (image0 == 0) + return 0; + + else + return image0->height(); + } + + size_t depth() const + { + const RGBAImageArray * v0 = vol0(); + + if (v0 == 0) + return 0; + + return v0->size(); + + } + + + + +}; + + +typedef nvMatrix<float> floatImage; +typedef nvMatrix<fpPixel> fpImage; +typedef nvMatrix<fpPixel3> fpImage3; + + +//typedef nvImage<fpPixel> fpImage; +//typedef nvImage<float> floatImage; +//typedef nvImage<fpPixel3> fpImage3; + + + +typedef nvVector<fpImage> fpImageArray; + + + + +class fpMipMappedImage +{ + fpImageArray mipArray; // array of images, one for each MIP map RGBA + +public: + + fpMipMappedImage() + { + } + + fpMipMappedImage(size_t width, size_t height, size_t nMIPMaps) + { + resize(width, height, nMIPMaps); + } + + // copy constructor + fpMipMappedImage(const fpMipMappedImage& v) + { + // copy the images over + mipArray.resize(v.mipArray.size() ); + for(size_t mipLevel = 0; mipLevel < numMIPMaps(); mipLevel++) + { + fpImage & dst = mipArray[mipLevel]; + const fpImage & src = v.mipArray[mipLevel]; + dst = src; + } + } + + + void resize(size_t width, size_t height, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height); + + mipArray.resize(nMIPMaps); + + for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++) + { + fpImage & mip = mipArray[mipLevel]; + + mip.resize(width, height); + + width = nv::NextMip(width); + height = nv::NextMip(height); + } + } + + void FlipTopToBottom() + { + // copy the images over + for(size_t mipLevel = 0; mipLevel < numMIPMaps(); mipLevel++) + { + fpImage & mip = mipArray[mipLevel]; + mip.FlipTopToBottom(); + } + } + + fpImage & operator [] ( size_t i) { return mipArray[i]; }; // indexing + const fpImage& operator[](size_t i) const { return mipArray[i];} + + void SetToZero() + { + for(size_t mipLevel = 0; mipLevel < numMIPMaps(); mipLevel++) + { + fpImage & mip = mipArray[mipLevel]; + mip.SetToZero(); + } + } + + void clear() + { + mipArray.clear(); + } + void realloc(size_t size) + { + mipArray.realloc(size); + } + void resize(size_t nMIPLevels) + { + mipArray.resize(nMIPLevels); + } + + size_t numMIPMaps() const + { + return mipArray.size(); + } + + size_t width() const + { + return mipArray[0].width(); + + } + size_t height() const + { + return mipArray[0].height(); + } + +}; + + +class fpMipMappedCubeMap +{ + fpMipMappedImage cubeFaces[6]; // array of images, one for each MIP map RGBA + +public: + + void resize(size_t width, size_t height, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height); + + for(size_t f = 0; f < 6; f++) + { + fpMipMappedImage & mipFace = cubeFaces[f]; + mipFace.resize(width, height, nMIPMaps); + } + + + } + + fpMipMappedCubeMap(int width, int height, int nMIPMaps) + { + resize(width, height, nMIPMaps); + + } + + fpMipMappedCubeMap() + { + } + + fpMipMappedImage & operator [] ( size_t i) { return cubeFaces[i]; }; // indexing + const fpMipMappedImage& operator[](size_t i) const { return cubeFaces[i];} + + + size_t numMIPMaps() const + { + return cubeFaces[0].numMIPMaps(); + } + + size_t height() const + { + return cubeFaces[0].height(); + } + + size_t width() const + { + return cubeFaces[0].height(); + } + + void clear() + { + for(size_t f = 0; f < 6; f++) + { + fpMipMappedImage & mipFace = cubeFaces[f]; + mipFace.clear(); + } + + } + + + void FlipTopToBottom() + { + for(size_t f = 0; f < 6; f++) + { + fpMipMappedImage & mipFace = cubeFaces[f]; + mipFace.FlipTopToBottom(); + } + + } + + +}; + + +// mip level, array +typedef nvVector< fpImageArray > fpVolume; + +class fpMipMappedVolumeMap +{ + // array of MIP mapped images + fpVolume volumeArray; + +public: + + void resize(size_t width, size_t height, size_t depth, size_t nMIPMaps) + { + if (nMIPMaps == 0) + nMIPMaps = nv::calcMaxMipmap(width, height, depth); + volumeArray.resize(nMIPMaps); + + size_t w = width; + size_t h = height; + size_t d = depth; + + for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++) + { + + fpImageArray & volImage = volumeArray[mipLevel]; + + volImage.resize(d); + + + for(size_t slice = 0; slice < d; slice++) + { + fpImage & mipFace = volImage[slice]; + + mipFace.resize(w, h); + } + + w = nv::NextMip(w); + h = nv::NextMip(h); + d = nv::NextMip(d); + + } + } + + void FlipTopToBottom() + { + for(size_t mipLevel = 0; mipLevel < numMIPMaps(); mipLevel++) + { + + fpImageArray & volImage = volumeArray[mipLevel]; + + + for(size_t slice = 0; slice < volImage.size(); slice++) + { + fpImage & mipFace = volImage[slice]; + mipFace.FlipTopToBottom(); + } + } + } + + + + void realloc(size_t size) + { + volumeArray.realloc(size); + } + + + fpMipMappedVolumeMap(size_t width, size_t height, size_t depth, size_t nMIPMaps) + { + resize(width, height, depth, nMIPMaps); + } + + + // mip level + fpImageArray & operator [] ( size_t i) { return volumeArray[i]; }; // indexing + const fpImageArray& operator[](size_t i) const { return volumeArray[i];} + + fpMipMappedVolumeMap() + { + } + size_t numMIPMaps() const + { + return volumeArray.size(); + } + + + + + const fpImageArray * vol0() const + { + if (numMIPMaps() == 0) + return 0; + + return &volumeArray[0]; + } + + + const fpImage * slice0() const + { + const fpImageArray * v0 = vol0(); + + if (v0 == 0) + return 0; + + if (v0->size() == 0) + return 0; + + const fpImageArray &array = *v0; + + return &array[0]; + } + + size_t width() const + { + const fpImage * image0 = slice0(); + + if (image0 == 0) + return 0; + + else + return image0->width(); + + } + size_t height() const + { + const fpImage * image0 = slice0(); + + if (image0 == 0) + return 0; + + else + return image0->height(); + } + + size_t depth() const + { + const fpImageArray * v0 = vol0(); + + if (v0 == 0) + return 0; + + return v0->size(); + + } + + void clear() + { + volumeArray.clear(); + + } + + + + +}; +#pragma pack(pop) + + + + +#include "ConvertColor.h" + diff --git a/NifProps/dds/tVector.h b/NifProps/dds/tVector.h new file mode 100644 index 0000000..22bbfad --- /dev/null +++ b/NifProps/dds/tVector.h @@ -0,0 +1,778 @@ +#pragma once +#include <assert.h> + + + + +template <class _Type> +class nvMatrix +{ + _Type **m; + + size_t rows, cols; + +public: + + nvMatrix() + { + rows = 0; + cols = 0; + m = 0; + } + + // copy constructor + nvMatrix(const nvMatrix & v) + { + rows = 0; + cols = 0; + m = 0; + + resize(v.width(), v.height()); + + for(size_t i = 0; i < v.rows; i++) + { + for(size_t j = 0; j<v.cols; j++) + m[i][j] = v.m[i][j]; + } + } + + nvMatrix(size_t width, size_t height) + { + m = 0; + rows = 0; + cols = 0; + resize(width, height); + } + ~nvMatrix() + { + tvfree(); + } + + _Type& operator [] ( size_t i) + { + size_t r = i / cols; + size_t c = i % cols; + +#if _DEBUG + assert(r < rows); + assert(c < cols); +#endif + return m[r][c]; + }; + + + _Type * pixels( size_t i = 0) + { + + size_t r = i / cols; + size_t c = i % cols; + +#if _DEBUG + assert(r < rows); + assert(c < cols); +#endif + return &m[r][c]; + }; + + + _Type & operator () (const size_t &r, const size_t &c) const + { +#if _DEBUG + assert(r < rows); + assert(c < cols); +#endif + return m[r][c]; + } + + _Type & operator () (const size_t &r, const size_t &c) + { +#if _DEBUG + assert(r < rows); + assert(c < cols); +#endif + return m[r][c]; + } + + _Type * pixelsRC( size_t r, size_t c) + { +#if _DEBUG + assert(r < rows); + assert(c < cols); +#endif + return &m[r][c]; + }; + + _Type * pixelsXY( size_t x, size_t y) + { +#if _DEBUG + assert(y < rows); + assert(x < cols); +#endif + return &m[y][x]; + }; + + + _Type * pixelsYX( size_t y, size_t x) + { +#if _DEBUG + assert(y < rows); + assert(x < cols); +#endif + return &m[y][x]; + }; + + + _Type * pixelsXY_wrapped(int x, int y) + { + y = iModulo(y, (int)rows); + x = iModulo(x, (int)cols); + + return &m[y][x]; + } + + size_t width() const + { + return cols; + } + size_t height() const + { + return rows; + } + + + void tvfree() + { + if (m) + { + for(size_t i = 0; i < rows; i++) + delete [] m[i]; + + delete [] m; + m = 0; + rows = 0; + cols = 0; + } + } + + void tvallocate(size_t r, size_t c) + { + assert(m == NULL); + + rows = r; + cols = c; + if (r == 0 || c == 0) + return; + + m = new _Type *[r]; + + + for(size_t i = 0; i < r; i++) + { + m[i] = new _Type [c]; + } + } + + nvMatrix & operator = ( const nvMatrix& v ) + { + resize(v.width(), v.height()); + + for(size_t i = 0; i < v.rows; i++) + { + for(size_t j = 0; j<v.cols; j++) + m[i][j] = v.m[i][j]; + } + return *this; + } + + + void SetToZero() + { + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + m[i][j].SetToZero(); + } + } + + + + + // destructive + void resize(size_t width, size_t height) + { + if (height != rows || width != cols) + { + tvfree (); + + tvallocate(height, width); + } + } + + + void Release() + { + tvfree (); + } + void clear() + { + tvfree(); + } + + size_t size() const + { + return rows * cols; + } + + + + void FlipTopToBottom() + { + _Type * swap = new _Type[ cols]; + + size_t row; + + //_Type * end_row; + //_Type * start_row; + int end_row; + int start_row; + + size_t len = sizeof(_Type) * cols; + + for( row = 0; row < rows / 2; row ++ ) + { + /*end_row = &m[( rows - row - 1) ][0]; + start_row = &m[ row ][0]; + + // copy row toward end of image into temporary swap buffer + memcpy( swap, end_row, len ); + + // copy row at beginning to row at end + memcpy( end_row, start_row, len ); + + // copy old bytes from row at end (in swap) to row at beginning + memcpy( start_row, swap, len );*/ + + end_row = rows - row - 1; + start_row = row ; + + // copy row toward end of image into temporary swap buffer + //memcpy( swap, end_row, len ); + for(size_t i = 0; i < cols; i++) + swap[i] = m[end_row][i]; + + // copy row at beginning to row at end + //memcpy( end_row, start_row, len ); + for(size_t i = 0; i < cols; i++) + m[end_row][i] = m[start_row][i]; + + // copy old bytes from row at end (in swap) to row at beginning + //memcpy( start_row, swap, len ); + for(size_t i = 0; i < cols; i++) + m[start_row][i] = swap[i]; + + } + + delete [] swap; + } + + + void Scale(_Type s) + { + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + m[i][j] *= s; + } + } + + void Bias(_Type s) + { + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + m[i][j] += s; + } + } + + void dot(_Type w) + { + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + m[i][j].dot(w); + } + } + + + + void Clamp(_Type low, _Type hi) + { + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + { + m[i][j].Clamp(low, hi); + } + } + } + + void Wrap(_Type low, _Type hi) + { + // to do + for(size_t i = 0; i < rows; i++) + { + for(size_t j = 0; j<cols; j++) + { + + m[i][j].Wrap(low, hi); + } + } + } + +}; + +/* +#include <vector> + +template <class T> +class nvVector : public std::vector<T> +{ +public: + + void resize(size_t newSize) + { + // Hack to emulate nvVector behaviour. + nvVector tmp; + ((std::vector<T> &)tmp).resize(newSize); + std::swap(*this, tmp); + } + + void realloc(size_t newSize) + { + std::vector<T>::resize(newSize); + } +}; + + +template <class _Type> +class nvVector +{ + _Type *m_data; + + size_t allocated_size; + size_t current_size; + +public: + + nvVector() + { + m_data = 0; + current_size = 0; + allocated_size = 0; + } + + nvVector(const nvVector<_Type> & other) + { + resize(other.size()); + + for(size_t i = 0; i < other.size(); i++) + { + m_data[i] = other.m_data[i]; + } + } + + ~nvVector() + { + Release(); + } + + static void tvfree(_Type * & ptr) + { + if (ptr) + { + delete [] ptr; + ptr = 0; + } + } + + static _Type * tvallocate(size_t elements) + { + return new _Type[elements]; + } + + nvVector & operator = ( const nvVector& v ) + { + resize(v.size()); + + for(size_t i = 0; i < v.size(); i++) + { + m_data[i] = v.m_data[i]; + } + return *this; + } + + + void FirstAllocation() + { + // start with 256 entries + + tvfree (m_data); + + allocated_size = 256; + current_size = 0; + m_data = tvallocate(allocated_size); + } + + + + void resize(size_t newSize) + { + if (newSize != allocated_size) + { + allocated_size = newSize; + + tvfree (m_data); + + m_data = tvallocate(allocated_size); + } + + current_size = newSize; + } + + // keep old contents + void realloc(size_t newSize) + { + if (newSize != allocated_size) + { + _Type * oldData = new _Type[current_size]; + size_t oldSize = current_size; + + for(size_t i = 0; i < current_size; i++) + { + oldData[i] = m_data[i]; + } + + + allocated_size = newSize; + + tvfree (m_data); + + m_data = tvallocate(allocated_size); + + size_t minSize; + if (oldSize < newSize) + minSize = oldSize; + else + minSize = newSize; + + for(size_t i = 0; i < minSize; i++) + { + m_data[i] = oldData[i]; + } + } + + current_size = newSize; + } + + void push_back(_Type item) + { + if (allocated_size == 0) + { + FirstAllocation(); + } + else if (current_size >= allocated_size) + { + allocated_size = allocated_size * 2; + + _Type *temp = tvallocate(allocated_size); + + // copy old data to new area + for(size_t i = 0; i< current_size; i++) + temp[i] = m_data[i]; + + tvfree (m_data); + + m_data = temp; + } + + + m_data[current_size] = item; + current_size++; + } + + // indexing + + _Type& operator [] ( size_t i) + { +#ifdef _DEBUG + assert(i < current_size); + assert(current_size <= allocated_size); +#endif + return m_data[i]; + }; + + const _Type& operator[](size_t i) const + { +#ifdef _DEBUG + assert(i < current_size); + assert(current_size <= allocated_size); +#endif + return m_data[i]; + } + + void Release() + { + tvfree (m_data); + + current_size = 0; + allocated_size = 0; + } + void clear() + { + Release(); + } + + size_t size() const + { + return current_size; + } + +}; +*/ + +#include <new> + +template<typename T> +class nvVector { +public: + + /** Ctor. */ + nvVector() : m_buffer(NULL), m_size(0), m_buffer_size(0) { + } + + /** Copy ctor. */ + nvVector( const nvVector & a ) : m_buffer(NULL), m_size(0), m_buffer_size(0) { + copy( a.m_buffer, a.m_size); + } + + + /** Ctor that initializes the array with the given elements. */ + nvVector( const T * ptr, size_t num ) : m_buffer(NULL), m_size(0), m_buffer_size(0) { + copy( ptr, num); + } + + + /** Dtor. */ + ~nvVector() { + clear(); + allocate(0); + } + + + /** Const and save array access. */ + const T & operator[]( size_t index ) const { + assert( index < m_size ); + return m_buffer[index]; + } + + /** Safe array access. */ + T & operator[] ( size_t index ) { + assert( index < m_size ); + return m_buffer[index]; + } + + + /** Get array size. */ + size_t size() const { return m_size; } + + + /** Push an element at the end of the array. */ + void push_back( const T & val ) { + // DO NOT pass elements of your own vector into + // push_back()! Since we're using references, + // resize() may munge the element storage! + assert( &val < &m_buffer[0] || &val > &m_buffer[m_size] ); + + int new_size = m_size + 1; + resize( new_size ); + m_buffer[new_size-1] = val; + } + + /** Pop and return element at the end of the array. */ + void pop_back() { + assert( m_size > 0 ); + resize( m_size-1 ); + } + + /** Get back element. */ + const T & back() const { + assert( m_size > 0 ); + return m_buffer[m_size-1]; + } + + /** Get back element. */ + T & back() { + assert( m_size > 0 ); + return m_buffer[m_size-1]; + } + + /** Get back element. */ + const T & front() const { + assert( m_size > 0 ); + return m_buffer[0]; + } + + /** Get back element. */ + T & front() { + assert( m_size > 0 ); + return m_buffer[0]; + } + + + // nvVector semantics: realloc preserves contents, resize does not. + void realloc( size_t new_size ) { + resize(new_size); + } + + + /** Resize the array preserving existing elements. */ + void resize( size_t new_size ) { + size_t i; + size_t old_size = m_size; + m_size = new_size; + + // Destruct old elements (if we're shrinking). + for( i = new_size; i < old_size; i++ ) { + (m_buffer+i)->~T(); // Explicit call to the destructor + } + + if( m_size == 0 ) { + //allocate(0); // Don't shrink automatically. + } + else if( m_size <= m_buffer_size && m_size > m_buffer_size >> 1) { + // don't compact yet. + assert(m_buffer != NULL); + } + else { + size_t new_buffer_size; + if( m_buffer_size == 0 ) { + // first allocation + new_buffer_size = m_size; + } + else { + // growing + new_buffer_size = m_size + (m_size >> 2); + } + allocate( new_buffer_size ); + } + + // Call default constructors + for( i = old_size; i < new_size; i++ ) { + new(m_buffer+i) T(); // placement new + } + } + + + /** + * Resize the array preserving existing elements and initializing the + * new ones with the given value. + */ + void resize( size_t new_size, const T &elem ) { + size_t i; + size_t old_size = m_size; + m_size = new_size; + + // Destruct old elements (if we're shrinking). + for( i = new_size; i < old_size; i++ ) { + (m_buffer+i)->~T(); // Explicit call to the destructor + } + + if( m_size == 0 ) { + //allocate(0); // Don't shrink automatically. + } + else if( m_size <= m_buffer_size && m_size > m_buffer_size >> 1 ) { + // don't compact yet. + assert(m_buffer != NULL); + } + else { + size_t new_buffer_size; + if( m_buffer_size == 0 ) { + // first allocation + new_buffer_size = m_size; + } + else { + // growing + new_buffer_size = m_size + (m_size >> 2); + } + allocate( new_buffer_size ); + } + + // Call copy constructors + for( i = old_size; i < new_size; i++ ) { + new(m_buffer+i) T( elem ); // placement new + } + } + + /** Clear the buffer. */ + void clear() { + resize(0); + } + + /** Shrink the allocated array. */ + void shrink() { + if( m_size < m_buffer_size) { + allocate(m_size); + } + } + + /** Preallocate space. */ + void reserve( size_t desired_size ) { + if( desired_size > m_buffer_size ) { + allocate( desired_size ); + } + } + + + /** Assignment operator. */ + void operator=( const nvVector & a ) { + copy( a.m_buffer, a.m_size ); + } + + +private: + + /** Change buffer size. */ + void allocate( size_t rsize ) { + + m_buffer_size = rsize; + + // free the buffer. + if( m_buffer_size == 0 ) { + if( m_buffer ) { + free( m_buffer ); + m_buffer = NULL; + } + } + + // realloc the buffer + else { + if( m_buffer ) m_buffer = (T *) ::realloc( m_buffer, sizeof(T) * m_buffer_size ); + else m_buffer = (T *) malloc( sizeof(T) * m_buffer_size ); + } + } + + /** Copy memory to our array. Resizes the array if needed. */ + void copy( const T * ptr, size_t num ) { + resize( num ); + for( size_t i = 0; i < m_size; i++ ) { + m_buffer[i] = ptr[i]; + } + } + +private: + + T * m_buffer; + size_t m_size; + size_t m_buffer_size; + +}; diff --git a/NifProps/dds/veroverrides.h b/NifProps/dds/veroverrides.h new file mode 100644 index 0000000..744b070 --- /dev/null +++ b/NifProps/dds/veroverrides.h @@ -0,0 +1,15 @@ +// The to be #defined in a .h file included by a .rc file before maxversion.r + + +#define MAXVER_INTERNALNAME "dds\0"//should be overidden on a per-dll level +#define MAXVER_ORIGINALFILENAME "dds.bmi\0"//should be overidden on a per-dll level +#define MAXVER_FILEDESCRIPTION "A DDS image IO plugin\0"//should be overidden on a per-dll level +#define MAXVER_COMMENTS "TECH: neil.hazzard\0"//should be overidden on a per-dll level + +// #define MAXVER_PRODUCTNAME //generally not overridden at the maxversion.r level +// #define MAXVER_COPYRIGHT //only in exceptions should this be overridden +// #define MAXVER_LEGALTRADEMARKS //only in exceptions should this be overridden +// #define MAXVER_COMPANYNAME //only in exceptions should this be overridden +// #define MAX_VERSION_MAJOR //only in exceptions should this be overridden +// #define MAX_VERSION_MINOR //only in exceptions should this be overridden +// #define MAX_VERSION_POINT //only in exceptions should this be overridden -- GitLab