diff --git a/tools/maya-plugin/Animation/Animation.vcxproj b/tools/maya-plugin/Animation/Animation.vcxproj new file mode 100644 index 000000000..3d1461510 --- /dev/null +++ b/tools/maya-plugin/Animation/Animation.vcxproj @@ -0,0 +1,529 @@ + + + + + Maya2020 Debug + Win32 + + + Maya2020 Debug + x64 + + + Maya2020 Release + Win32 + + + Maya2020 Release + x64 + + + Maya5.0 Debug + Win32 + + + Maya5.0 Debug + x64 + + + Maya5.0 Release + Win32 + + + Maya5.0 Release + x64 + + + Maya8.5 Debug + Win32 + + + Maya8.5 Debug + x64 + + + Maya8.5 Release + Win32 + + + Maya8.5 Release + x64 + + + + + + + + + + + + + 16.0 + Win32Proj + {8620b892-de9c-40c0-9200-6f64b45c599e} + Animation + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya50x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya50x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya2020x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya2020x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya50x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya50x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya2020x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) + $(DXSDK)\Lib\x86;$(Maya2020x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + SD2AniExport + .mll + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya50x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya50x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya2020x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya2020x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya50x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya50x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(DXSDK)\Include;$(Maya2020x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(DXSDK)\Lib\x64;$(Maya2020x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + SD2AniExport + .mll + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;ANIMATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;d3dx9.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/tools/maya-plugin/Animation/Animation.vcxproj.filters b/tools/maya-plugin/Animation/Animation.vcxproj.filters new file mode 100644 index 000000000..69fddc846 --- /dev/null +++ b/tools/maya-plugin/Animation/Animation.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/tools/maya-plugin/Animation/AnimationExport.cpp b/tools/maya-plugin/Animation/AnimationExport.cpp new file mode 100644 index 000000000..2e7dda535 --- /dev/null +++ b/tools/maya-plugin/Animation/AnimationExport.cpp @@ -0,0 +1,283 @@ +/****************************************************************************** +File: AnimationExport.cpp + +Author: Nick Chirkov +Copyright (C) 2001 Akella corp. + +Comments: +Maya export +******************************************************************************/ +#include +#include "AnimationExport.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "anim_file.h" +#include +#include "cvector.h" +#include "matrix.h" +#include + +#define CM2M_SCALE 0.01f + +FILE *LogFile=0; +void Log(const char *fmt,...) +{ + va_list args; + va_start(args,fmt); + vfprintf(LogFile, fmt, args); + va_end(args); +} + +bool GetDoubleValue(MObject &obj, const char *name, double &d) +{ + MFnDependencyNode NodeFnDn; + NodeFnDn.setObject(obj); + MStatus status; +#if MAYA_API_VERSION <= 500 + MPlug rpuv = NodeFnDn.findPlug(name, &status); +#else + MPlug rpuv = NodeFnDn.findPlug(name, false, &status); +#endif + if(!status) return false; + MObject val; + rpuv.getValue(d); + return true; +} + +FILE *anifile; +MStatus status; + +AniExport::AniExport() +{ +} + +AniExport::~AniExport() +{ +} + +MStatus AniExport::writer(const MFileObject &file, const MString &optionsString, FileAccessMode mode) +{ +#if MAYA_API_VERSION <= 500 + MString fname = file.fullName(); +#else + MString fname = file.expandedFullName(); +#endif + ExportAll(fname.asChar()); + return (MS::kSuccess); +} +bool AniExport::haveWriteMethod () const +{ + return (true); +} +MString AniExport::defaultExtension () const +{ + return MString("an"); +} + +MPxFileTranslator::MFileKind AniExport::identifyFile( const MFileObject &file, const char *buffer,short size) const +{ + //const char *name = file.resolvedName().asChar(); + //int nameLength = strlen(name); + return (kIsMyFileType); +} + +void *AniExport::creator() +{ + return new AniExport(); +} + +//**************************************************************** +__declspec(dllexport) MStatus initializePlugin (MObject obj) +{ + using namespace std::string_literals; + MStatus status; + MFnPlugin plugin (obj, "Nick Chirkov (C) 2001", "1.0"); + auto pixmap_name = ""s; + auto options_script_name = "SD2AniExportMel"s; + status = plugin.registerFileTranslator("SD2AniExport", &pixmap_name[0], AniExport::creator,&options_script_name[0]); + return status; +} + +__declspec(dllexport) MStatus uninitializePlugin (MObject obj) +{ + MFnPlugin plugin (obj); + plugin.deregisterFileTranslator ("SD2AniExport"); + return (MS::kSuccess); +} + +//------------------------------------------------------------------------ +//find root +//------------------------------------------------------------------------ +void AniExport::ExportAll(const char *fname) +{ + MGlobal::executeCommand("window -tlc 300 300 -w 300 -h 200 -title \"ani Export\" StatusWin",true); + MGlobal::executeCommand("columnLayout -adjustableColumn true",true); + MGlobal::executeCommand("text -label \"Default\" MyLable",true); + MGlobal::executeCommand("showWindow StatusWin",true); + MGlobal::executeCommand("text -edit -label \"Search root\" MyLable",true); + MGlobal::executeCommand("showWindow StatusWin",true); + + char newname[256]; + sprintf(newname, "%s.ant", fname); + LogFile = fopen(newname,"w+"); + char aniname[256]; + strcpy(aniname, newname); + aniname[strlen(aniname)-4] = 0; + anifile = fopen(aniname,"w+b"); + + //get selected locator + MSelectionList slist; + MGlobal::getActiveSelectionList(slist); + MItSelectionList iter(slist); + if(iter.isDone()) return; + MDagPath locator; + iter.getDagPath(locator); + if(!locator.hasFn(MFn::kLocator)) return; + + //------------------------------------------------------------------------------ + //EXPORT FRAMES + //------------------------------------------------------------------------------ + MTime startFrame( MAnimControl::minTime().value(), MTime::uiUnit() ); + float startTime = (float)startFrame.value(); + + MTime endFrame( MAnimControl::maxTime().value(), MTime::uiUnit() ); + float endTime = (float)endFrame.value(); + + ANIFILE::HEADER ah; + fwrite(&ah, sizeof ah, 1, anifile); + ah.nJoints = 0; + ah.nFrames = 0; + ah.framesPerSec = 15.0f; + + //-------------------------------------------------------- + //all joints + //-------------------------------------------------------- + //find all joints + MDagPathArray mJointsList; + MItDag dagIterator( MItDag::kBreadthFirst, MFn::kJoint, &status); + if(!status) return; + for ( ; !dagIterator.isDone(); dagIterator.next() ) + { + MDagPath dagPath; + status = dagIterator.getPath(dagPath); // Get DagPath + if(!status) continue; + + status = mJointsList.append(dagPath); + ah.nJoints++; + } + + //------------------------------------------------------------- + //parent index to handle hierarchy + //------------------------------------------------------------- + long *parIdx = new long[ah.nJoints]; + long j; + for(j=0; j begPos; + std::vector rootPos; + std::vector jointAngle; + + for(float time = startTime; time + +class AniExport : public MPxFileTranslator +{ +public: + AniExport(); + ~AniExport(); + + MStatus writer(const MFileObject &file, const MString &optionsString, FileAccessMode mode); + bool haveWriteMethod() const; + MString defaultExtension() const; + MFileKind identifyFile (const MFileObject &, const char *buffer, short size) const; + static void *creator(); +protected: + void ExportAll(const char *fname); + +}; + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Animation/anim_file.h b/tools/maya-plugin/Animation/anim_file.h new file mode 100644 index 000000000..ef81399d4 --- /dev/null +++ b/tools/maya-plugin/Animation/anim_file.h @@ -0,0 +1,20 @@ +#pragma once + +//ANIMATION_HEADER +//long parentIndex[nJoints] +//CVECTOR jointPos[nJoints] + +//Frames: +//CVECTOR rootPos[nFrames] +//CVECTOR jointAngle[nJoints][nFrames] + +namespace ANIFILE +{ + struct HEADER + { + long nFrames; + long nJoints; + float framesPerSec; + }; + +}; \ No newline at end of file diff --git a/tools/maya-plugin/Common/chunk.h b/tools/maya-plugin/Common/chunk.h new file mode 100644 index 000000000..4498b112b --- /dev/null +++ b/tools/maya-plugin/Common/chunk.h @@ -0,0 +1,16 @@ +#ifndef _CHUNK_H_ +#define _CHUNK_H_ + +#pragma pack(push,1) + +#define CHUNK_RDF_GEOMETRY 0 + +struct CHUNK +{ + unsigned long id; + unsigned long size; +}; + +#pragma pack(pop) + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Common/cvector.h b/tools/maya-plugin/Common/cvector.h new file mode 100644 index 000000000..160bbe1f5 --- /dev/null +++ b/tools/maya-plugin/Common/cvector.h @@ -0,0 +1,212 @@ +#ifndef __CVECTOR_H__ +#define __CVECTOR_H__ + +#include + +struct CVECTOR +{ +public: + float x; + float y; + float z; + CVECTOR(){}; + CVECTOR(float a) { x = a; y = a; z = a; }; + CVECTOR(double a) { x = float(a); y = float(a); z = float(a); }; + CVECTOR(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }; + CVECTOR(double _x, double _y, double _z) { x = float(_x); y = float(_y); z = float(_z); }; + CVECTOR(float a[3]) { x = a[0]; y = a[1]; z = a[2]; }; + CVECTOR(double a[3]) { x = float(a[0]); y = float(a[1]); z = float(a[2]); }; + //CVECTOR(const DVECTOR &d) : x((float)d.x), y((float)d.y), z((float)d.z){}; + + inline CVECTOR& operator += (const CVECTOR& v) + { + x += v.x; y += v.y; z += v.z; + return *this; + }; + inline CVECTOR& operator -= (const CVECTOR& v) + { + x -= v.x; y -= v.y; z -= v.z; + return *this; + }; + inline CVECTOR& operator *= (const CVECTOR& v) + { + x *= v.x; y *= v.y; z *= v.z; + return *this; + }; + inline CVECTOR& operator /= (const CVECTOR& v) + { + x /= v.x; y /= v.y; z /= v.z; + return *this; + }; + + //square magnitude + friend inline float operator ~ (const CVECTOR& v) + { + return v.x*v.x + v.y*v.y + v.z*v.z; + }; + + //normalize + friend inline CVECTOR operator ! (const CVECTOR& v) + { + double len = 1.0/sqrt(v.x*v.x + v.y*v.y + v.z*v.z); + return CVECTOR(v.x*len, v.y*len, v.z*len); + }; + + //none + friend inline CVECTOR operator + (const CVECTOR& v) + { + return v; + }; + //add + friend inline CVECTOR operator + (const CVECTOR& v1, const CVECTOR& v2) + { + return CVECTOR(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); + }; + //negative + friend inline CVECTOR operator - (const CVECTOR& v) + { + return CVECTOR(-v.x, -v.y, -v.z); + }; + //sub + friend inline CVECTOR operator - (const CVECTOR& v1, const CVECTOR& v2) + { + return CVECTOR(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z); + }; + //multiply each element by each + friend inline CVECTOR operator * (const CVECTOR& v1, const CVECTOR& v2) + { + return CVECTOR(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z); + }; + //multiply each element by float + friend inline CVECTOR operator * (const CVECTOR& v1, float f) + { + return CVECTOR(v1.x*f, v1.y*f, v1.z*f); + }; + //divide each element by each + friend inline CVECTOR operator / (const CVECTOR& v1, const CVECTOR& v2) + { + return CVECTOR(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z); + }; + //divide each element by float + friend inline CVECTOR operator / (const CVECTOR& v1, float f) + { + double _f = 1.0/f; return CVECTOR(v1.x*_f, v1.y*_f, v1.z*_f); + }; + //cross product + friend inline CVECTOR operator ^ (const CVECTOR& v1, const CVECTOR& v2) + { + return CVECTOR(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); + } + //dot product + friend inline float operator | (const CVECTOR& v1, const CVECTOR& v2) + { + return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; + } + + //== + inline bool operator==(const CVECTOR& v) + { + return (v.x==x && v.y==y && v.z==z); + } + +} ; + +struct DVECTOR +{ +public: + double x; + double y; + double z; + DVECTOR(){}; + DVECTOR(double a) { x = a; y = a; z = a; }; + DVECTOR(double _x, double _y, double _z) { x = _x; y = _y; z = _z; }; + DVECTOR(double a[3]) { x = a[0]; y = a[1]; z = a[2]; }; + DVECTOR(const CVECTOR &d) { x = d.x; y = d.y; z = d.z; }; + + inline DVECTOR& operator += (const DVECTOR& v) + { + x += v.x; y += v.y; z += v.z; + return *this; + }; + inline DVECTOR& operator -= (const DVECTOR& v) + { + x -= v.x; y -= v.y; z -= v.z; + return *this; + }; + inline DVECTOR& operator *= (const DVECTOR& v) + { + x *= v.x; y *= v.y; z *= v.z; + return *this; + }; + inline DVECTOR& operator /= (const DVECTOR& v) + { + x /= v.x; y /= v.y; z /= v.z; + return *this; + }; + + //square magnitude + friend inline double operator ~ (const DVECTOR& v) + { + return v.x*v.x + v.y*v.y + v.z*v.z; + }; + + //normalize + friend inline DVECTOR operator ! (const DVECTOR& v) + { + double len = 1.0/sqrt(v.x*v.x + v.y*v.y + v.z*v.z); + return DVECTOR(v.x*len, v.y*len, v.z*len); + }; + + //none + friend inline DVECTOR operator + (const DVECTOR& v) + { + return v; + }; + //add + friend inline DVECTOR operator + (const DVECTOR& v1, const DVECTOR& v2) + { + return DVECTOR(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); + }; + //negative + friend inline DVECTOR operator - (const DVECTOR& v) + { + return DVECTOR(-v.x, -v.y, -v.z); + }; + //sub + friend inline DVECTOR operator - (const DVECTOR& v1, const DVECTOR& v2) + { + return DVECTOR(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z); + }; + //multiply each element by each + friend inline DVECTOR operator * (const DVECTOR& v1, const DVECTOR& v2) + { + return DVECTOR(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z); + }; + //multiply each element by double + friend inline DVECTOR operator * (const DVECTOR& v1, double f) + { + return DVECTOR(v1.x*f, v1.y*f, v1.z*f); + }; + //divide each element by each + friend inline DVECTOR operator / (const DVECTOR& v1, const DVECTOR& v2) + { + return DVECTOR(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z); + }; + //divide each element by double + friend inline DVECTOR operator / (const DVECTOR& v1, double f) + { + double _f = 1.0/f; return DVECTOR(v1.x*_f, v1.y*_f, v1.z*_f); + }; + //cross product + friend inline DVECTOR operator ^ (const DVECTOR& v1, const DVECTOR& v2) + { + return DVECTOR(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); + } + //dot product + friend inline double operator | (const DVECTOR& v1, const DVECTOR& v2) + { + return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; + } +} ; + +#endif diff --git a/tools/maya-plugin/Common/matrix.h b/tools/maya-plugin/Common/matrix.h new file mode 100644 index 000000000..3a9bc5940 --- /dev/null +++ b/tools/maya-plugin/Common/matrix.h @@ -0,0 +1,684 @@ +#ifndef _MATRIX_H_ +#define _MATRIX_H_ + + +#include "cvector.h" + + +//============================================================================================ + +/* + 0 4 8 12 [0][0] [1][0] [2][0] [3][0] + 1 5 9 13 [0][1] [1][1] [2][1] [3][1] + 2 6 10 14 [0][2] [1][2] [2][2] [3][2] + 3 7 11 15 [0][3] [1][3] [2][3] [3][3] +*/ + +//============================================================================================ + +struct MTX_PRJ_VECTOR +{ + float x, y, z; + float rhw; +}; + +struct D3DXMATRIX; + +//============================================================================================ + +class CMatrix +{ +public: + union + { + float matrix[16]; + float m[4][4]; + }; + +//----------------------------------------------------------- +//Constructors +//----------------------------------------------------------- + CMatrix();//Identity matrix + CMatrix(float angX, float angY, float angZ, float x, float y, float z); + CMatrix(float angX, float angY, float angZ); + CMatrix(CVECTOR & ang, CVECTOR & pos); + CMatrix(CVECTOR & ang); + CMatrix(const CMatrix & matrix); + CMatrix(CMatrix * matrix); + //this = m1*m2 + CMatrix(CMatrix & m1, CMatrix & m2); + + +//----------------------------------------------------------- +//Main +//----------------------------------------------------------- + //Create identity matrix + void SetIdentity(); + + //Build matrix + //M = rotZ*rotX*rotY*Pos + void BuildMatrix(float angX, float angY, float angZ, float x, float y, float z); + void BuildMatrix(float angX, float angY, float angZ); + void BuildMatrix(CVECTOR & ang, CVECTOR & pos); + void BuildMatrix(CVECTOR & ang); + //M = rotX*rotY*rotZ*Pos + void BuildMatrixXYZ(float angX, float angY, float angZ, float x, float y, float z); + + //Build rotate matrix + void BuildRotateX(float ang); + void BuildRotateY(float ang); + void BuildRotateZ(float ang); + //Build position matrix + void BuildPosition(float x, float y, float z); + + //Equal + void operator = (const CMatrix & matrix); + + //Multiply + void operator *= (CMatrix & matrix); + void operator *= (float k); + CMatrix operator * (CMatrix & matrix); + CVECTOR operator * (CVECTOR & vector); + + + //this = m1*m2, (m1 != this, m2 != this) + void EqMultiply(CMatrix & m1, CMatrix & m2); + //Transform vertex to local coordinate system + void MulToInv(const CVECTOR & srcVrt, CVECTOR & resVrt); + //Transform normal to local coordinate system + void MulToInvNorm(CVECTOR & srcNorm, CVECTOR & resNorm); + + //Transposition + void Transposition(); + void Transposition3X3(); + + //Rotate + void RotateX(float ang); + void RotateY(float ang); + void RotateZ(float ang); + //Move + void Move(float dX, float dY, float dZ); + //Move(-(pos * this)) + void MoveInversePosition(float x, float y, float z); + //Set new position + void SetPosition(float x, float y, float z); + void SetPosition(CVECTOR & pos); + //SetPosition(-(pos * this)) + void SetInversePosition(float x, float y, float z); + +//----------------------------------------------------------- +//Utils +//----------------------------------------------------------- + + //Access to axis vectors + CVECTOR & Vx() const; // X () + CVECTOR & Vy() const; // Y () + CVECTOR & Vz() const; // Z () + CVECTOR & Pos() const; // () + + //Access to matrix element + float & operator () (long i, long j); + + + //Create only rotate matrix + void Get3X3(CMatrix & mtr); + void Get3X3(CMatrix * mtr); + + //Projection + void BuildProjectionMatrix(float viewAngle, float vpWidth, float vpHeight, float zNear, float zFar); + void Projection(CVECTOR * srcArray, MTX_PRJ_VECTOR * dstArray, long num, float vphWidth05, float vphHeight05, long srcStrcSize, long dstStrcSize); + + //View + bool BuildViewMatrix(CVECTOR lookFrom, CVECTOR lookTo, CVECTOR upVector); + + //Mirror + void BuildMirrorMatrix(float Nx, float Ny, float Nz, float D); + + //D3D extends (return (D3DXMATRIX *)pointer) + operator D3DXMATRIX * (); + +}; + +//============================================================================================ +//Constructors +//============================================================================================ + +inline CMatrix::CMatrix() +{ + SetIdentity(); +} + +inline CMatrix::CMatrix(float angX, float angY, float angZ) +{ + BuildMatrix(angX, angY, angZ, 0.0f, 0.0f, 0.0f); +} + +inline CMatrix::CMatrix(float angX, float angY, float angZ, float x, float y, float z) +{ + BuildMatrix(angX, angY, angZ, x, y, z); +} + +inline CMatrix::CMatrix(CVECTOR & ang, CVECTOR & pos) +{ + BuildMatrix(ang.x, ang.y, ang.z, pos.x, pos.y, pos.z); +} + +inline CMatrix::CMatrix(CVECTOR & ang) +{ + BuildMatrix(ang.x, ang.y, ang.z, 0.0f, 0.0f, 0.0f); +} + +inline CMatrix::CMatrix(const CMatrix & matrix) +{ + *this = matrix; +} + +inline CMatrix::CMatrix(CMatrix * matrix) +{ + *this = *matrix; +} + +//this = m1*m2 +inline CMatrix::CMatrix(CMatrix & m1, CMatrix & m2) +{ + EqMultiply(m1, m2); +} + +//============================================================================================ +//Main +//============================================================================================ + +//Create identity matrix +inline void CMatrix::SetIdentity() +{ + matrix[0] = 1.f; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 1.f; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 1.f; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1.f; +} + +//Build matrix +inline void CMatrix::BuildMatrix(float angX, float angY, float angZ, float x, float y, float z) +{ + register float sinAx = sinf(angX); + register float cosAx = cosf(angX); + register float sinAy = sinf(angY); + register float cosAy = cosf(angY); + register float sinAz = sinf(angZ); + register float cosAz = cosf(angZ); + + // rz*rx*ry + m[0][0] = cosAz*cosAy + sinAz*sinAx*sinAy; + m[1][0] = -sinAz*cosAy + cosAz*sinAx*sinAy; + m[2][0] = cosAx*sinAy; + m[3][0] = x; + + m[0][1] = sinAz*cosAx; + m[1][1] = cosAz*cosAx; + m[2][1] = -sinAx; + m[3][1] = y; + + m[0][2] = cosAz*-sinAy + sinAz*sinAx*cosAy; + m[1][2] = -sinAz*-sinAy + cosAz*sinAx*cosAy; + m[2][2] = cosAx*cosAy; + m[3][2] = z; + + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; +} + +inline void CMatrix::BuildMatrixXYZ(float angX, float angY, float angZ, float x, float y, float z) +{ + register float sinAx = sinf(angX); + register float cosAx = cosf(angX); + register float sinAy = sinf(angY); + register float cosAy = cosf(angY); + register float sinAz = sinf(angZ); + register float cosAz = cosf(angZ); + + m[0][0] = cosAy*cosAz; + m[1][0] = sinAx*sinAy*cosAz-cosAx*sinAz; + m[2][0] = cosAx*sinAy*cosAz+sinAx*sinAz; + m[3][0] = x; + + m[0][1] = cosAy*sinAz; + m[1][1] = sinAx*sinAy*sinAz+cosAx*cosAz; + m[2][1] = cosAx*sinAy*sinAz-sinAx*cosAz; + m[3][1] = y; + + m[0][2] = -sinAy; + m[1][2] = sinAx*cosAy; + m[2][2] = cosAx*cosAy; + m[3][2] = z; + + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; +} + + +inline void CMatrix::BuildMatrix(float angX, float angY, float angZ) +{ + BuildMatrix(angX, angY, angZ, 0.0f, 0.0f, 0.0f); +} + +inline void CMatrix::BuildMatrix(CVECTOR & ang, CVECTOR & pos) +{ + BuildMatrix(ang.x, ang.y, ang.z, pos.x, pos.y, pos.z); +} + +inline void CMatrix::BuildMatrix(CVECTOR & ang) +{ + BuildMatrix(ang.x, ang.y, ang.z, 0.0f, 0.0f, 0.0f); +} + +//Build rotate matrix +inline void CMatrix::BuildRotateX(float ang) +{ + SetIdentity(); + m[1][1] = cosf(ang); + m[2][1] = -sinf(ang); + m[1][2] = sinf(ang); + m[2][2] = cosf(ang); +} + +inline void CMatrix::BuildRotateY(float ang) +{ + SetIdentity(); + m[0][0] = cosf(ang); + m[2][0] = sinf(ang); + m[0][2] = -sinf(ang); + m[2][2] = cosf(ang); +} + +inline void CMatrix::BuildRotateZ(float ang) +{ + SetIdentity(); + m[0][0] = cosf(ang); + m[1][0] = -sinf(ang); + m[0][1] = sinf(ang); + m[1][1] = cosf(ang); +} + +//Build position matrix +inline void CMatrix::BuildPosition(float x, float y, float z) +{ + SetIdentity(); + matrix[12] = x; + matrix[13] = y; + matrix[14] = z; +} + +//Equal +inline void CMatrix::operator = (const CMatrix & matrix) +{ + this->matrix[0] = matrix.matrix[0]; + this->matrix[1] = matrix.matrix[1]; + this->matrix[2] = matrix.matrix[2]; + this->matrix[3] = matrix.matrix[3]; + this->matrix[4] = matrix.matrix[4]; + this->matrix[5] = matrix.matrix[5]; + this->matrix[6] = matrix.matrix[6]; + this->matrix[7] = matrix.matrix[7]; + this->matrix[8] = matrix.matrix[8]; + this->matrix[9] = matrix.matrix[9]; + this->matrix[10] = matrix.matrix[10]; + this->matrix[11] = matrix.matrix[11]; + this->matrix[12] = matrix.matrix[12]; + this->matrix[13] = matrix.matrix[13]; + this->matrix[14] = matrix.matrix[14]; + this->matrix[15] = matrix.matrix[15]; +} + +//Multiply +inline void CMatrix::operator *= (CMatrix & matrix) +{ + CMatrix tmp; + tmp.EqMultiply(*this, matrix); + *this = tmp; +} + + +inline void CMatrix::operator *= (float k) +{ + m[0][0] *= k; m[1][0] *= k; m[2][0] *= k; m[3][0] *= k; + m[0][1] *= k; m[1][1] *= k; m[2][1] *= k; m[3][1] *= k; + m[0][2] *= k; m[1][2] *= k; m[2][2] *= k; m[3][2] *= k; + m[0][3] *= k; m[1][3] *= k; m[2][3] *= k; m[3][3] *= k; +} + +inline CMatrix CMatrix::operator * (CMatrix & matrix) +{ + CMatrix tmp; + tmp.EqMultiply(*this, matrix); + return tmp; +} + +inline CVECTOR CMatrix::operator * (CVECTOR & vector) +{ + CVECTOR tmp; + tmp.x = matrix[0]*vector.x + matrix[4]*vector.y + matrix[8]*vector.z + matrix[12]; + tmp.y = matrix[1]*vector.x + matrix[5]*vector.y + matrix[9]*vector.z + matrix[13]; + tmp.z = matrix[2]*vector.x + matrix[6]*vector.y + matrix[10]*vector.z + matrix[14]; + return tmp; +} + +//this = m1*m2, (m1 != this, m2 != this) +inline void CMatrix::EqMultiply(CMatrix & m1, CMatrix & m2) +{ + matrix[0] = m2.matrix[0]*m1.matrix[0] + m2.matrix[4]*m1.matrix[1] + m2.matrix[8]*m1.matrix[2] + m2.matrix[12]*m1.matrix[3]; + matrix[1] = m2.matrix[1]*m1.matrix[0] + m2.matrix[5]*m1.matrix[1] + m2.matrix[9]*m1.matrix[2] + m2.matrix[13]*m1.matrix[3]; + matrix[2] = m2.matrix[2]*m1.matrix[0] + m2.matrix[6]*m1.matrix[1] + m2.matrix[10]*m1.matrix[2] + m2.matrix[14]*m1.matrix[3]; + matrix[3] = m2.matrix[3]*m1.matrix[0] + m2.matrix[7]*m1.matrix[1] + m2.matrix[11]*m1.matrix[2] + m2.matrix[15]*m1.matrix[3]; + + matrix[4] = m2.matrix[0]*m1.matrix[4] + m2.matrix[4]*m1.matrix[5] + m2.matrix[8]*m1.matrix[6] + m2.matrix[12]*m1.matrix[7]; + matrix[5] = m2.matrix[1]*m1.matrix[4] + m2.matrix[5]*m1.matrix[5] + m2.matrix[9]*m1.matrix[6] + m2.matrix[13]*m1.matrix[7]; + matrix[6] = m2.matrix[2]*m1.matrix[4] + m2.matrix[6]*m1.matrix[5] + m2.matrix[10]*m1.matrix[6] + m2.matrix[14]*m1.matrix[7]; + matrix[7] = m2.matrix[3]*m1.matrix[4] + m2.matrix[7]*m1.matrix[5] + m2.matrix[11]*m1.matrix[6] + m2.matrix[15]*m1.matrix[7]; + + matrix[8] = m2.matrix[0]*m1.matrix[8] + m2.matrix[4]*m1.matrix[9] + m2.matrix[8]*m1.matrix[10] + m2.matrix[12]*m1.matrix[11]; + matrix[9] = m2.matrix[1]*m1.matrix[8] + m2.matrix[5]*m1.matrix[9] + m2.matrix[9]*m1.matrix[10] + m2.matrix[13]*m1.matrix[11]; + matrix[10] = m2.matrix[2]*m1.matrix[8] + m2.matrix[6]*m1.matrix[9] + m2.matrix[10]*m1.matrix[10] + m2.matrix[14]*m1.matrix[11]; + matrix[11] = m2.matrix[3]*m1.matrix[8] + m2.matrix[7]*m1.matrix[9] + m2.matrix[11]*m1.matrix[10] + m2.matrix[15]*m1.matrix[11]; + + matrix[12] = m2.matrix[0]*m1.matrix[12] + m2.matrix[4]*m1.matrix[13] + m2.matrix[8]*m1.matrix[14] + m2.matrix[12]*m1.matrix[15]; + matrix[13] = m2.matrix[1]*m1.matrix[12] + m2.matrix[5]*m1.matrix[13] + m2.matrix[9]*m1.matrix[14] + m2.matrix[13]*m1.matrix[15]; + matrix[14] = m2.matrix[2]*m1.matrix[12] + m2.matrix[6]*m1.matrix[13] + m2.matrix[10]*m1.matrix[14] + m2.matrix[14]*m1.matrix[15]; + matrix[15] = m2.matrix[3]*m1.matrix[12] + m2.matrix[7]*m1.matrix[13] + m2.matrix[11]*m1.matrix[14] + m2.matrix[15]*m1.matrix[15]; +} + +//Transform vertex to local coordinate system +inline void CMatrix::MulToInv(const CVECTOR & src, CVECTOR & res) +{ + res.x = (src.x - matrix[12])*matrix[0] + (src.y - matrix[13])*matrix[1] + (src.z - matrix[14])*matrix[2]; + res.y = (src.x - matrix[12])*matrix[4] + (src.y - matrix[13])*matrix[5] + (src.z - matrix[14])*matrix[6]; + res.z = (src.x - matrix[12])*matrix[8] + (src.y - matrix[13])*matrix[9] + (src.z - matrix[14])*matrix[10]; +} + +//Transform normal to local coordinate system +inline void CMatrix::MulToInvNorm(CVECTOR & src, CVECTOR & res) +{ + res.x = src.x*matrix[0] + src.y*matrix[1] + src.z*matrix[2]; + res.y = src.x*matrix[4] + src.y*matrix[5] + src.z*matrix[6]; + res.z = src.x*matrix[8] + src.y*matrix[9] + src.z*matrix[10]; +} + +//Transposition +inline void CMatrix::Transposition() +{ + float x = Pos()|Vx(); + float y = Pos()|Vy(); + float z = Pos()|Vz(); + Pos().x = -x; + Pos().y = -y; + Pos().z = -z; + Transposition3X3(); +} + +inline void CMatrix::Transposition3X3() +{ + float tmp; + tmp = matrix[1]; + matrix[1] = matrix[4]; + matrix[4] = tmp; + tmp = matrix[2]; + matrix[2] = matrix[8]; + matrix[8] = tmp; + tmp = matrix[6]; + matrix[6] = matrix[9]; + matrix[9] = tmp; +} + +//Rotate +inline void CMatrix::RotateX(float ang) +{ + CMatrix mtr; + mtr.BuildRotateX(ang); + *this *= mtr; +} + +inline void CMatrix::RotateY(float ang) +{ + CMatrix mtr; + mtr.BuildRotateY(ang); + *this *= mtr; +} + +inline void CMatrix::RotateZ(float ang) +{ + CMatrix mtr; + mtr.BuildRotateZ(ang); + *this *= mtr; +} + +//Move +inline void CMatrix::Move(float dX, float dY, float dZ) +{ + matrix[12] += dX; matrix[13] += dY; matrix[14] += dZ; +} + +//Move(-(pos * this)) +inline void CMatrix::MoveInversePosition(float x, float y, float z) +{ + m[3][0] -= m[0][0]*x + m[1][0]*y + m[2][0]*z; + m[3][1] -= m[0][1]*x + m[1][1]*y + m[2][1]*z; + m[3][2] -= m[0][2]*x + m[1][2]*y + m[2][2]*z; +} + +//Set new position +inline void CMatrix::SetPosition(float x, float y, float z) +{ + matrix[12] = x; matrix[13] = y; matrix[14] = z; +} + +inline void CMatrix::SetPosition(CVECTOR & pos) +{ + matrix[12] = pos.x; matrix[13] = pos.y; matrix[14] = pos.z; +} + +//SetPosition(-(pos * this)) +inline void CMatrix::SetInversePosition(float x, float y, float z) +{ + m[3][0] = -(m[0][0]*x + m[1][0]*y + m[2][0]*z); + m[3][1] = -(m[0][1]*x + m[1][1]*y + m[2][1]*z); + m[3][2] = -(m[0][2]*x + m[1][2]*y + m[2][2]*z); +} + +//============================================================================================ +//Utils +//============================================================================================ + +//Access to axis vectors +inline CVECTOR & CMatrix::Vx() const +{ + return *(CVECTOR *)(matrix); +} + +inline CVECTOR & CMatrix::Vy() const +{ + return *(CVECTOR *)(matrix + 4); +} + +inline CVECTOR & CMatrix::Vz() const +{ + return *(CVECTOR *)(matrix + 8); +} + +inline CVECTOR & CMatrix::Pos() const +{ + return *(CVECTOR *)(matrix + 12); +} + +//Access to matrix element +inline float & CMatrix::operator () (long i, long j) +{ + return m[i][j]; +} + +//Create only rotate matrix +inline void CMatrix::Get3X3(CMatrix & mtr) +{ + mtr.matrix[0] = matrix[0]; + mtr.matrix[1] = matrix[1]; + mtr.matrix[2] = matrix[2]; + mtr.matrix[4] = matrix[4]; + mtr.matrix[5] = matrix[5]; + mtr.matrix[6] = matrix[6]; + mtr.matrix[8] = matrix[8]; + mtr.matrix[9] = matrix[9]; + mtr.matrix[10] = matrix[10]; +} + +inline void CMatrix::Get3X3(CMatrix * mtr) +{ + Get3X3(*mtr); +} + +//Projection +inline void CMatrix::BuildProjectionMatrix(float viewAngle, float vpWidth, float vpHeight, float zNear, float zFar) +{ + matrix[0] = 0; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 0; + matrix[4] = 0; + matrix[5] = 0; + matrix[6] = 0; + matrix[7] = 0; + matrix[8] = 0; + matrix[9] = 0; + matrix[10] = 0; + matrix[11] = 0; + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 0; + + const auto Q = static_cast(zFar) / static_cast(zFar - zNear); + + matrix[0] = 1.0f / tanf(viewAngle * 0.5f); + matrix[5] = 1.0f / tanf((vpHeight / vpWidth) * viewAngle * 0.5f); + matrix[10] = static_cast(Q); + matrix[11] = 1.0f; + matrix[14] = -static_cast(Q) * zNear; +} + +inline void CMatrix::Projection(CVECTOR * srcArray, MTX_PRJ_VECTOR * dstArray, long num, float vphWidth05, float vphHeight05, long srcStrcSize, long dstStrcSize) +{ + float k; + for (; num > 0; num--) + { + dstArray->x = matrix[0] * srcArray->x + matrix[4] * srcArray->y + matrix[8] * srcArray->z + matrix[12]; + dstArray->y = matrix[1] * srcArray->x + matrix[5] * srcArray->y + matrix[9] * srcArray->z + matrix[13]; + dstArray->z = matrix[2] * srcArray->x + matrix[6] * srcArray->y + matrix[10] * srcArray->z + matrix[14]; + dstArray->rhw = matrix[3] * srcArray->x + matrix[7] * srcArray->y + matrix[11] * srcArray->z + matrix[15]; + + k = 1.0f / dstArray->rhw; + + dstArray->x = (1.0f + dstArray->x * k) * vphWidth05; + dstArray->y = (1.0f - dstArray->y * k) * vphHeight05; + dstArray->z *= k; + + dstArray->rhw = k; + + srcArray = (CVECTOR*)((char*)(srcArray)+srcStrcSize); + dstArray = (MTX_PRJ_VECTOR*)((char*)(dstArray)+dstStrcSize); + } +} + +//View +inline bool CMatrix::BuildViewMatrix(CVECTOR lookFrom, CVECTOR lookTo, CVECTOR upVector) +{ + SetIdentity(); + // + lookTo -= lookFrom; + float l = ~lookTo; + if(l == 0.0f) + { + // + Pos() = -lookFrom; + return false; + } + lookTo *= 1.0f/sqrtf(l); + // + upVector -= lookTo*(lookTo | upVector); + // + l = ~upVector; + if(l == 0.0f) upVector.y = 1.0f; + else upVector *= 1.0f/sqrtf(l); + // + CVECTOR v = upVector ^ lookTo; + l = ~v; + if(l != 0.0f) + { + v *= (1.0f/sqrtf(l)); + // + Vx() = upVector; + Vy() = lookTo; + Vz() = v; + + m[0][0] = v.x; + m[1][0] = v.y; + m[2][0] = v.z; + m[0][1] = upVector.x; + m[1][1] = upVector.y; + m[2][1] = upVector.z; + m[0][2] = lookTo.x; + m[1][2] = lookTo.y; + m[2][2] = lookTo.z; + + } + // + SetInversePosition(lookFrom.x, lookFrom.y, lookFrom.z); + return true; +} + +//Mirror +// +inline void CMatrix::BuildMirrorMatrix(float Nx, float Ny, float Nz, float D) +{ + m[0][0] = -Nx*2.0f*Nx + 1.0f; + m[1][0] = -Nx*2.0f*Ny; + m[2][0] = -Nx*2.0f*Nz; + m[3][0] = -Nx*2.0f*-D; + + m[0][1] = -Ny*2.0f*Nx; + m[1][1] = -Ny*2.0f*Ny + 1.0f; + m[2][1] = -Ny*2.0f*Nz; + m[3][1] = -Ny*2.0f*-D; + + m[0][2] = -Nz*2.0f*Nx; + m[1][2] = -Nz*2.0f*Ny; + m[2][2] = -Nz*2.0f*Nz + 1.0f; + m[3][2] = -Nz*2.0f*-D; + + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; +} + +//D3D extends (return (D3DXMATRIX *)pointer) +inline CMatrix::operator D3DXMATRIX * () +{ + return ((D3DXMATRIX*)matrix); +}; + +//============================================================================================ + +#endif diff --git a/tools/maya-plugin/Common/rdf.h b/tools/maya-plugin/Common/rdf.h new file mode 100644 index 000000000..7b56ca698 --- /dev/null +++ b/tools/maya-plugin/Common/rdf.h @@ -0,0 +1,284 @@ +/****************************************************************************** +File: rdf.h + +Author: Nick Chirkov +Copyright (C) 2000, 2001 Nick Chirkov + +Comments: +geometry file format +******************************************************************************/ + +#ifndef __RDF_H__ +#define __RDF_H__ + +#include +#include + +#pragma pack(push,1) + +#include "cvector.h" + +/* + +RDF_HEAD; +NAMES; +textures; +materials; +lights; +labels; +objects; +triangles; +vertex_buffers; +vertices; + +BSP_HEAD +BSP_NODE - bsp nodes +BSP_VERTEX - bsp vertices +BSP_TRIANGLE - bsp triangles + +*/ + +//------------------------------------------------------------ +//header +//------------------------------------------------------------ + +#define RDF_VERSION '1.05' + +enum RDF_FLAGS +{ + FLAGS_VISIBLE_PRESENT = 1, + FLAGS_BSP_PRESENT = 2, + RDFFLAGS_FORCEDWORD = 0x7FFFFFFF +}; + +struct RDF_HEAD +{ + long version; //RDF_VERSION + long flags; //combination of RDF_FLAGS + long name_size; + long names; + long ntextures; + long nmaterials; + long nlights; + long nlabels; + long nobjects; + long ntriangles; + long nvrtbuffs; + + CVECTOR bbox_size, bbox_center; + float radius; +}; + +//------------------------------------------------------------ +//strings +//------------------------------------------------------------ +//char NAMES[name_size]; + +//------------------------------------------------------------ +//names of textures used +//------------------------------------------------------------ +struct RDF_TEXTURE +{ + long name; +}; + +//------------------------------------------------------------ +//material +//------------------------------------------------------------ +enum RDF_TEXTURE_TYPE +{ + TEXTURE_NONE = 0, + TEXTURE_BASE, + TEXTURE_NORMAL, + TEXTURE_FORCE_DWORD = 0x7FFFFFFF +}; +struct RDF_MATERIAL +{ + long group_name; + long name; + float diffuse; //0 - no diffuse material + float specular, gloss; //spec=0 - no specular, gloss is a power of cosine + float selfIllum; //for area light sources + RDF_TEXTURE_TYPE texture_type[4]; + long texture[4]; +}; + +//------------------------------------------------------------ +//dynamic light +//------------------------------------------------------------ +enum RDF_LIGHT_TYPE +{ + LIGHT_POINT = 0, + LIGHT_SPOT, + LIGHT_DIRECTIONAL, + LIGHT_FORCE_DWORD = 0x7FFFFFFF +}; +enum RDF_LIGHT_FLAGS +{ + LIGHT_SHADOW = 1, + LIGHT_FORCEDWORD = 0x7FFFFFFF +}; +struct RDF_LIGHT +{ + long flags; + RDF_LIGHT_TYPE type; + long group_name; + long name; + float r,g,b; + float range; + CVECTOR pos; + float atten[3]; + float inner, outer, falloff; + CVECTOR dir; +}; + +//------------------------------------------------------------ +//label +//------------------------------------------------------------ +enum RDF_LABEL_FLAGS +{ + LABEL_FORCEDWORD = 0x7FFFFFFF +}; +struct RDF_LABEL +{ + long group_name; + long name; + long flags; //combination of LABEL_FLAGS + float m[4][4]; + long bones[4]; + float weight[4]; +}; + +//------------------------------------------------------------ +//object +//------------------------------------------------------------ +enum RDF_OBJECT_FLAGS +{ + VISIBLE = (1<<0), + STATIC_LIGHT_ENABLE = (1<<1), //if no - object will not be lited + DINAMIC_LIGHT_ENABLE = (1<<2), //if no - no dynamic lighting perfomed + CAST_SHADOWS_ENABLE = (1<<3), //if material makes shadows + COLLISION_ENABLE = (1<<4), //if yes - object will be stored to BSP + VERTEX_WEIGHT = (1<<5), //animation + MERGE = (1<<6), //object is "merged"-type + CULLENABLE = (1<<7), //single-sided object + OBJECT_FORCEDWORD = 0x7FFFFFFF +}; +struct RDF_OBJECT +{ + long group_name; + long name; + long flags; + CVECTOR center; + float radius; + long vertex_buff; + long ntriangles, striangle, nvertices, svertex; + long material; + long lights[8]; + long bones[4]; + long atriangles; +}; + +//------------------------------------------------------------ +//triangle 16bit indices +//------------------------------------------------------------ +struct RDF_TRIANGLE +{ + unsigned short vindex[3]; +}; + +//------------------------------------------------------------ +//vertex buffer descriptor +//------------------------------------------------------------ +struct RDF_VERTEXBUFF +{ + long type; + long size; +}; + +//------------------------------------------------------------ +//vertex type +//------------------------------------------------------------ +struct RDF_VERTEX0 +{ + CVECTOR pos; + CVECTOR norm; + long color; + float tu0, tv0; +}; + +struct RDF_VERTEX1 +{ + CVECTOR pos; + CVECTOR norm; + long color; + float tu0, tv0; + float tu1, tv1; +}; + +struct RDF_VERTEX2 +{ + CVECTOR pos; + CVECTOR norm; + long color; + float tu0, tv0; + float tu1, tv1; + float tu2, tv2; +}; + +struct RDF_VERTEX3 +{ + CVECTOR pos; + CVECTOR norm; + long color; + float tu0, tv0; + float tu1, tv1; + float tu2, tv2; + float tu3, tv3; +}; + +//-------------------animated vertex--------------- +struct RDF_AVERTEX0 +{ + CVECTOR pos; + float weight; + unsigned long boneid; + CVECTOR norm; + long color; + float tu0, tv0; +}; + +//------------------------------------------------------------ +//bsp +//------------------------------------------------------------ +struct RDF_BSPHEAD +{ + long nnodes; + long nvertices; + long ntriangles; +}; + +struct RDF_BSPTRIANGLE +{ + unsigned char vindex[3][3]; +}; + +#define RDF_BSPVERTEX CVECTOR + +struct BSP_NODE +{ + CVECTOR norm; + float pd; + unsigned long + node:22, + sign:1, + left:1, + nfaces:4, + right:2, + type:2; + + long face; +}; + +#pragma pack(pop) +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Common/texture.h b/tools/maya-plugin/Common/texture.h new file mode 100644 index 000000000..a453b573f --- /dev/null +++ b/tools/maya-plugin/Common/texture.h @@ -0,0 +1,29 @@ +/****************************************************************************** +File: texture.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef __TEXTURE_H__ +#define __TEXTURE_H__ + +#pragma pack(push) +#pragma pack(1) + + +struct RDF_TEXTURE +{ + long flags; + long width, height; + long nmips; + long format; + long texel_size; + //palette; + //data; +}; + +#pragma pack(pop) + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Export/Export.vcxproj b/tools/maya-plugin/Export/Export.vcxproj new file mode 100644 index 000000000..f39fa0c14 --- /dev/null +++ b/tools/maya-plugin/Export/Export.vcxproj @@ -0,0 +1,185 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + 16.0 + Win32Proj + {b2a3b561-1b1c-4025-8a77-522fcb52e08a} + Export + 10.0 + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ../Common;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + false + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ../Common;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + true + ../Common;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + + + false + ../Common;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + + + true + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + + + true + true + true + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + + + true + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + + + true + true + true + + + + + + \ No newline at end of file diff --git a/tools/maya-plugin/Export/Export.vcxproj.filters b/tools/maya-plugin/Export/Export.vcxproj.filters new file mode 100644 index 000000000..af3e3807a --- /dev/null +++ b/tools/maya-plugin/Export/Export.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + \ No newline at end of file diff --git a/tools/maya-plugin/Export/bsp.cpp b/tools/maya-plugin/Export/bsp.cpp new file mode 100644 index 000000000..448a9c6c1 --- /dev/null +++ b/tools/maya-plugin/Export/bsp.cpp @@ -0,0 +1,409 @@ +/****************************************************************************** +File: bsp.cpp + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#include "bsp.h" + +extern CVECTOR *vrt; +extern BTRG *trg; +extern DVECTOR bbox; +extern long ssize, max_depth, ndepth[MAX_TREE_DEPTH]; +extern BSP_NODE *sroot; +extern long cur_node; +extern long cur_depth; +extern long cdepth; +extern long tnode; + +#define LIE_PREC 0.0001 + +BUILD_BSP_NODE::~BUILD_BSP_NODE() +{ + delete _face; + if(right!=NULL) delete right; + if(left!=NULL) delete left; +} + +double TOT_FACES, CUR_FACE; +long min_l, min_r, min_c, min_m; + +#include "rdf_exp.h" +extern RESULT_FUNC resultfn; +//----------------------------------------------------------------------------------- +//fill node +//----------------------------------------------------------------------------------- +BSP_NODE *BUILD_BSP_NODE::FillNode(BUILD_BSP_FACE **list, long nfaces) +{ + static long time = 0; + if(GetTickCount()-time>1000) + { + double prc = 100.0*CUR_FACE/TOT_FACES; + char ee[256]; + sprintf(ee, "Building BSP: %.2f %%", float(prc)); + if(resultfn(std::string(ee))==false) throw "Building BSP process was terminated"; + time = GetTickCount(); + } + + long best_plane = BestPlane(list, nfaces); +//######################################__SORT__###################################### + norm = list[best_plane]->normal; + pld = norm | vrt[trg[list[best_plane]->trg].vindex[0]]; + + if(min_m>MAX_PLANE_FACES) + { + BestEmptyPlane(list, nfaces, &norm, &pld); + best_plane = -1; + } + + BUILD_BSP_FACE **rlist = new BUILD_BSP_FACE*[min_r + min_c]; + BUILD_BSP_FACE **llist = new BUILD_BSP_FACE*[min_l + min_c]; + + CUR_FACE += min_m; TOT_FACES += min_c; + + cur_node++; + cur_depth++; if(cur_depth>max_depth) max_depth = cur_depth; + if(cur_depth>1000) + __debugbreak(); + + tot_faces=0; + _face = new long[min_m]; + + // sort all faces + long l=0,r=0; + for(long i=0; itrg].vindex[0]]) - pld; + res[1] = (norm | vrt[trg[list[i]->trg].vindex[1]]) - pld; + res[2] = (norm | vrt[trg[list[i]->trg].vindex[2]]) - pld; + if(fabs(res[0])trg) break; + //add new trg + if(tf==tot_faces) _face[tot_faces++] = list[i]->trg; + + delete list[i]->vertices; + delete list[i]; + continue; + } + + double vdist[256]; + long min_did, max_did; + double min_dist=1e300, max_dist=-1e300; + for(long v=0; vnvertices; v++) + { + vdist[v] = (norm | list[i]->vertices[v]) - pld; + if(vdist[v]>max_dist) + { + max_dist = vdist[v]; + max_did = v; + } + if(vdist[v]=-PRECISION && max_dist>=-PRECISION) + { + rlist[r++] = list[i]; + continue; + } + if(min_dist<=PRECISION && max_dist<=PRECISION) + { + llist[l++] = list[i]; + continue; + } + + //face is on the both sides + BUILD_BSP_FACE *right_face = new BUILD_BSP_FACE; + *right_face = *list[i]; + while(vdist[max_did]>-PRECISION) //search for a first vertex + { + max_did--; + if(max_did==-1) max_did=list[i]->nvertices-1; + } //max_did - first + + right_face->nvertices=0; + right_face->vertices=NULL; + do + { + right_face->nvertices++; + right_face->vertices = (DVECTOR*)realloc(right_face->vertices, right_face->nvertices*sizeof(DVECTOR)); + + if(vdist[max_did]<=-PRECISION) //split edge + { + long v = max_did+1; if(v==list[i]->nvertices) v=0; + + double d = vdist[max_did]/(vdist[max_did]-vdist[v]); + right_face->vertices[right_face->nvertices-1] = list[i]->vertices[max_did] + d*(list[i]->vertices[v] - list[i]->vertices[max_did]); + } + else right_face->vertices[right_face->nvertices-1] = list[i]->vertices[max_did]; //copy vertex + + max_did++; if(max_did==list[i]->nvertices) max_did=0; + }while(vdist[max_did]>-PRECISION); + + right_face->nvertices++; + right_face->vertices = (DVECTOR*)realloc(right_face->vertices, right_face->nvertices*sizeof(DVECTOR)); + //split the last edge + long v = max_did-1; if(v==-1) v=list[i]->nvertices-1; + double d = vdist[max_did]/(vdist[max_did]-vdist[v]); + right_face->vertices[right_face->nvertices-1] = list[i]->vertices[max_did] + d*(list[i]->vertices[v] - list[i]->vertices[max_did]); + // add to the right list + rlist[r++] = right_face; + + //------------------------------------LEFT----------------------------------------- + right_face = new BUILD_BSP_FACE; + *right_face = *list[i]; + while(vdist[min_did]nvertices-1; + } //min_did - first + + right_face->nvertices=0; + right_face->vertices=NULL; + do + { + right_face->nvertices++; + right_face->vertices = (DVECTOR*)realloc(right_face->vertices, right_face->nvertices*sizeof(DVECTOR)); + + if(vdist[min_did]>=PRECISION) //split edge + { + long v = min_did+1; if(v==list[i]->nvertices) v=0; + + double d = vdist[min_did]/(vdist[min_did]-vdist[v]); + right_face->vertices[right_face->nvertices-1] = list[i]->vertices[min_did] + d*(list[i]->vertices[v] - list[i]->vertices[min_did]); + } + else right_face->vertices[right_face->nvertices-1] = list[i]->vertices[min_did]; //copy vertex + + min_did++; if(min_did==list[i]->nvertices) min_did=0; + }while(vdist[min_did]nvertices++; + right_face->vertices = (DVECTOR*)realloc(right_face->vertices, right_face->nvertices*sizeof(DVECTOR)); + //split the last edge + v = min_did-1; if(v==-1) v=list[i]->nvertices-1; + d = vdist[min_did]/(vdist[min_did]-vdist[v]); + right_face->vertices[right_face->nvertices-1] = list[i]->vertices[min_did] + d*(list[i]->vertices[v] - list[i]->vertices[min_did]); + // add to the right list + llist[l++] = right_face; + + delete list[i]->vertices; + delete list[i]; + } + + delete list; + + //calculate size of BSP + ssize += NODESIZE(tot_faces); + ndepth[cur_depth] += NODESIZE(tot_faces); + + if(r>0) + { + right = new BUILD_BSP_NODE(); + right->FillNode(rlist,r); + } + else right = NULL; + + if(l>0) + { + left = new BUILD_BSP_NODE(); + left->FillNode(llist,l); + } + else left = NULL; + + cur_depth--; + + return 0; +} + + +//----------------------------------------------------------------------------------- +//best blane +//----------------------------------------------------------------------------------- +long BUILD_BSP_NODE::BestPlane(BUILD_BSP_FACE **list, long nfaces) +{ + double res0, res1, res2; + long best_plane; + + double gd = 1e20; + for(long f=0; fnormal | vrt[trg[list[i]->trg].vindex[0]]) - list[f]->plane_distance; + res1 = (list[f]->normal | vrt[trg[list[i]->trg].vindex[1]]) - list[f]->plane_distance; + res2 = (list[f]->normal | vrt[trg[list[i]->trg].vindex[2]]) - list[f]->plane_distance; + if(fabs(res0)nvertices; v++) + { + double dist = (list[f]->normal | list[i]->vertices[v]) - list[f]->plane_distance; + if(dist>max_dist) max_dist = dist; + if(dist=-PRECISION && max_dist>=-PRECISION) + { + r++; + continue; + } + if(min_dist<=PRECISION && max_dist<=PRECISION) + { + l++; + continue; + } + c++; //triangle is on the both sides + } + + double dist = 3.0*c + 1.0*fabs(r-l); + if(distvertices[e1] - list[f]->vertices[e]; + DVECTOR bnormal = !(((list[f]->normal*sqrt(~edge)) ^ edge)); + double bplane_distance = bnormal | list[f]->vertices[e]; + + long l=0, r=0, c=0, m=0; + long i; + for(i=0; itrg].vindex[0]]) - bplane_distance; + res1 = (bnormal | vrt[trg[list[i]->trg].vindex[1]]) - bplane_distance; + res2 = (bnormal | vrt[trg[list[i]->trg].vindex[2]]) - bplane_distance; + if(fabs(res0)nvertices; v++) + { + double dist = (bnormal | list[i]->vertices[v]) - bplane_distance; + if(dist>max_dist) max_dist = dist; + if(dist=-PRECISION && max_dist>=-PRECISION) + { + r++; + continue; + } + if(min_dist<=PRECISION && max_dist<=PRECISION) + { + l++; + continue; + } + c++; //triangle is on the both sides + } + + if(i0 && l>0 && distsign = 0; + node->type = 0; + node->norm.x = float(norm.x); + node->norm.y = float(norm.y); + node->norm.z = float(norm.z); + node->pd = float(pld); + + //store all faces + unsigned char *a = (unsigned char*)&node->face; + for(long f=0; fnfaces = tot_faces; + if(node->nfaces>MAX_PLANE_FACES) throw "Internal error: too many faces on the BSP node"; + + + ndepth[cdepth] += NODESIZE(node->nfaces); + + cdepth++; + + node->left = 0; + node->node = 0; + if(left!=NULL) + { + node->node = left->Store(); + //left is present + node->left = 1; + } + + if(right!=NULL) //right is present + if(left==NULL) + { + //left is not present + node->node = right->Store() - 1; + node->right = 1; + } + else + { + //node's size 1..3 blocks of 24 byte + node->right = right->Store() - node->node; + } + + cdepth--; + return long(node-sroot); +} diff --git a/tools/maya-plugin/Export/bsp.h b/tools/maya-plugin/Export/bsp.h new file mode 100644 index 000000000..3ba6982c2 --- /dev/null +++ b/tools/maya-plugin/Export/bsp.h @@ -0,0 +1,68 @@ +/****************************************************************************** +File: bsp.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef __BSP_H__ +#define __BSP_H__ + +#include "cvector.h" +#include "rdf.h" +#include + +#define MAX_TREE_DEPTH 1024 +#define MAX_PLANES_CALCULATED 256 +//#define PRECISION 5e-7 +#define PRECISION 0.00001 +#define KDISTANCE 0.0 +#define KBALANCE 1.0 +#define KCLIP 30.0 +//calculate size of node in blocks +#define NODESIZE(a) (1+(a*3+sizeof(BSP_NODE)-sizeof(long))/sizeof(BSP_NODE)) +//max faces on node +#define MAX_PLANE_FACES min(15, (sizeof(BSP_NODE)*2+sizeof(long))/3) + +#pragma pack(push) +#pragma pack(1) + +struct BTRG +{ + long vindex[3]; +}; + +//-----------BSP_FACE----------- +typedef struct +{ + long trg; + DVECTOR *vertices; + long nvertices; + DVECTOR normal; //temporary + double plane_distance; //temporary +}BUILD_BSP_FACE; + +// builder +class BUILD_BSP_NODE; +class BUILD_BSP_NODE +{ +public: + BUILD_BSP_NODE *right,*left; + + long current; + DVECTOR norm; + double pld; + long tot_faces; + long *_face; + + BUILD_BSP_NODE(){}; + ~BUILD_BSP_NODE(); + BSP_NODE *FillNode(BUILD_BSP_FACE **list, long nfaces); + long BestPlane(BUILD_BSP_FACE **list, long nfaces); + void BestEmptyPlane(BUILD_BSP_FACE **list, long nfaces, DVECTOR *epnorm, double *epdist); + long Store(); +}; +#pragma pack(pop) + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Export/collide.cpp b/tools/maya-plugin/Export/collide.cpp new file mode 100644 index 000000000..470335a77 --- /dev/null +++ b/tools/maya-plugin/Export/collide.cpp @@ -0,0 +1,222 @@ +/****************************************************************************** +File: collide.cpp + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#include "collide.h" + + +long nvrts, ntrgs, _ntrgs; +long cur_node, cur_depth; +BTRG *trg, *_trg; CVECTOR *vrt; +long cdepth, tnode; + +DVECTOR bbox; +BSP_NODE *sroot; +long max_depth, ssize, ndepth[MAX_TREE_DEPTH]; + +std::vector lvert; +std::vector geolink; +RESULT_FUNC resultfn; +extern double TOT_FACES, CUR_FACE; + +COLLIDE::COLLIDE(RESULT_FUNC _rfn) +{ + resultfn = _rfn; + rfn = _rfn; + nvrts=0; + ntrgs = _ntrgs = 0; + cur_node=-1; + cur_depth=0; + cdepth=0; + tnode=0; + max_depth = 0; + + iterations = 0; + triangles=0; + trg = _trg = 0; vrt = 0; +} + +COLLIDE::~COLLIDE() +{ + delete vrt; vrt = nullptr; + delete trg; trg = nullptr; + delete _trg; _trg = nullptr; + delete sroot; sroot = nullptr; + lvert.clear(); + geolink.clear(); +} + +void COLLIDE::AddCollideVertices(long obj, std::vector &av, long nav, RDF_TRIANGLE *at, long nat) +{ + for(long v0=0; v0pos==vrt[v1]) + break; + + //add new vertex + if(v1==nvrts) + { + nvrts++; + vrt = (CVECTOR*)realloc(vrt, sizeof(CVECTOR)*nvrts); + vrt[nvrts-1] = av[v0]->pos; + } + } +} + +void COLLIDE::AddCollideTriangles(long obj, std::vector &av, long nav, RDF_TRIANGLE *at, long nat) +{ + long t; + for(t=0; t0) + { + long v1; + for(v1=0; v1pos==vrt[v1]) + break; + + //add new vertex + if(v1==nvrts) + { + nvrts++; + vrt = (CVECTOR*)realloc(vrt, sizeof(CVECTOR)*nvrts); + vrt[nvrts-1] = av[v0]->pos; + } + ref[v0] = v1; + } + + //add triangles and relink vrtindex + _trg = (BTRG*)realloc(_trg, sizeof(BTRG)*(_ntrgs+nat)); + for(t=0; t &av, long nav, RDF_TRIANGLE *at, long nat) +{ + long t; + for(t=0; t0) + { + long v1; + for(v1=0; v1pos==vrt[v1]) + break; + + //add new vertex + if(v1==nvrts) + { + nvrts++; + vrt = (CVECTOR*)realloc(vrt, sizeof(CVECTOR)*nvrts); + vrt[nvrts-1] = av[v0]->pos; + } + ref[v0] = v1; + } + + //add triangles and relink vrtindex + trg = (BTRG*)realloc(trg, sizeof(BTRG)*(ntrgs+nat)); + for(t=0; tvertices = (DVECTOR*)realloc(NULL, sizeof(DVECTOR)*3); + face->nvertices = 3; + for(long v=0; v<3; v++) face->vertices[v] = vrt[trg[t].vindex[v]]; + + face->normal = !( face->vertices[1]-face->vertices[0] ^ face->vertices[2]-face->vertices[0]); + face->plane_distance = face->vertices[0] | face->normal; + face->trg = t; + } + + DVECTOR bmin = 1e20f; + DVECTOR bmax = -1e20f; + for(long bv=0; bv0 in all axis + float minb = 0.001*sqrt(~bbox); + bbox.x = max(bbox.x, minb); + bbox.y = max(bbox.y, minb); + bbox.z = max(bbox.z, minb); + + //fill nodes + ZeroMemory(ndepth, sizeof(long)*MAX_TREE_DEPTH); + ssize = 0; + + TOT_FACES = ntrgs; CUR_FACE=0; + DWORD curti = GetTickCount(); + BUILD_BSP_NODE *root = new BUILD_BSP_NODE(); + root->FillNode(faces, ntrgs); + + long prv=0; + for(long d=0; dStore(); + + + FILE *fl = fopen("stat.txt", "a"); + fprintf(fl, "trg: %d, nodes: %d, depth: %d, byte/trg: %d, time: %d\n", + ntrgs, tnode, max_depth, ssize*sizeof(BSP_NODE)/ntrgs, (GetTickCount()-curti)/1000); + fclose(fl); + +} diff --git a/tools/maya-plugin/Export/collide.h b/tools/maya-plugin/Export/collide.h new file mode 100644 index 000000000..f3331e10f --- /dev/null +++ b/tools/maya-plugin/Export/collide.h @@ -0,0 +1,65 @@ +/****************************************************************************** +File: collide.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef _COLLIDE_H_ +#define _COLLIDE_H_ + +#include "bsp.h" +#include "rdf.h" +#include "cvector.h" +#include "rdf_exp.h" +#include "export.h" + +class COLLIDE +{ + + //strip section + struct STRIP_EDGE + { + long vertex[2]; + std::vector trg; + }; + + std::vector sedge; + + struct STRIP_TRIANGLE + { + long edge[3]; + }; + STRIP_TRIANGLE *striangle; + + long depth, maxdepth; + long *direction; + __int64 iterations; + long triangles; + long edge_iterations, max_iter; + DWORD ticks; + + CVECTOR *rvertex; + + long RecStrip(long cur_edge, long cur_vrt); + void MakeStrip(CVECTOR *_cvec, long nvrt, long *trg, long ntrgs); + long FillStrip(long cur_edge, long cur_vrt, long nnodes); + //------end strip section------ + + std::vector objStrg; + RESULT_FUNC rfn; + + bool production; +public: + + COLLIDE(RESULT_FUNC rfn); + ~COLLIDE(); + void AddMesh(long obj, std::vector &av, long nav, RDF_TRIANGLE *at, long nat); + void AddCollideVertices(long obj, std::vector &av, long nav, RDF_TRIANGLE *at, long nat); + void AddCollideTriangles(long obj, std::vector &av, long nav, RDF_TRIANGLE *at, long nat); + void BuildBSP(bool pr); + +}; + +#endif diff --git a/tools/maya-plugin/Export/export.h b/tools/maya-plugin/Export/export.h new file mode 100644 index 000000000..c4bcb73ee --- /dev/null +++ b/tools/maya-plugin/Export/export.h @@ -0,0 +1,111 @@ +/****************************************************************************** +File: export.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef _RDFEXP_H_ +#define _RDFEXP_H_ + +#pragma warning ( disable : 4786) + +#include +#include +#include +#include "cvector.h" +#include "rdf_exp.h" +#include "rdf.h" +#include "vertex.h" + +template T SQR(T a) { return a*a; }; + +struct GEOMLINK +{ + long obj; + long trg; +}; + +class SEARCH_NODE +{ +public: + long vertex; + float value; + long left, right; +}; + +//---------------------------------------------------------------------- +//object support class +//---------------------------------------------------------------------- +class EOBJECT +{ +public: + + enum FLAGS { MERGED = 1 }; + long flags; + long group_name; + long name; + long mtl; + std::vector trg; + std::vector vertex; + + //used for fast vertex search + long tot_nodes; + SEARCH_NODE *root; + long Insert(long n, float v); + + DVECTOR boxmin, boxmax, center; + double radius; + + EOBJECT(); + EOBJECT(const EOBJECT &o); + ~EOBJECT(); + void AddTriangle(VERTEX0 **vrt); + void CalculateBoxRadius(); + void Optimize(); +}; + +//---------------------------------------------------------------------- +//main export class +//---------------------------------------------------------------------- +class GEOM_STATIC : public EXPORT_STATIC +{ + + long trgaddby2side, tot_triangles, tot_vertices; + bool build_bsp, production, animation, geoaccess; + + TEXTURE_FUNC tfn; + RESULT_FUNC fnresult; + RESULT_FUNC fnerror; + FILE *fl; + float max_elength, merge_size; + long flags; + + + std::vector globname; + + std::vector texture; + std::vector texid; + std::vector material; + std::vector light; + std::vector object; + std::vector label; + + long FindGlobalName(const std::string &s); + long AddTexture(const TEXTURE &tex); + void SplitObject(long o); +public: + + GEOM_STATIC(const std::string &fname, + TEXTURE_FUNC Textures, RESULT_FUNC fnr, RESULT_FUNC fne, + float maxedge, float merge_size, long flags); + + virtual ~GEOM_STATIC(); + virtual void AddObject(const OBJECT &obj); + virtual void AddLight(const LIGHT &l); + virtual void AddLabel(const LABEL &l); + virtual void WriteFile(); +}; + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Export/object.cpp b/tools/maya-plugin/Export/object.cpp new file mode 100644 index 000000000..b42c7d425 --- /dev/null +++ b/tools/maya-plugin/Export/object.cpp @@ -0,0 +1,203 @@ +/****************************************************************************** +File: object.cpp + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#include "export.h" + +//--------------------------------------------------------------- +//create new object +//--------------------------------------------------------------- +EOBJECT::EOBJECT() +{ + boxmin = 1e20; + boxmax = -1e20; + radius = 0.0; + flags=0; + tot_nodes = 0; + root = 0; +} + +//--------------------------------------------------------------- +//copy constructor needed for template +//--------------------------------------------------------------- +EOBJECT::EOBJECT(const EOBJECT &o) +{ + boxmin = o.boxmin; + boxmax = o.boxmax; + center = o.center; + radius = o.radius; + + flags = o.flags; + group_name = o.group_name; + name = o.name; + trg = o.trg; + mtl = o.mtl; + vertex = o.vertex; + + tot_nodes = o.tot_nodes; + root = (SEARCH_NODE*)realloc(0, sizeof(SEARCH_NODE)*1024*(tot_nodes/1024+1)); + memcpy(root, o.root, sizeof(SEARCH_NODE)*tot_nodes); + +} + +//--------------------------------------------------------------- +//delete +//--------------------------------------------------------------- +EOBJECT::~EOBJECT() +{ + if(tot_nodes>0) + realloc(root, sizeof(SEARCH_NODE)*0); +} + + +//---------------------------------------------------------------------- +//vertex types hierarchy +//---------------------------------------------------------------------- +long sdepth = -1, smax_depth = 0; +double straverse; +VERTEX0 *sver; + +long EOBJECT::Insert(long n, float v) +{ + sdepth++; smax_depth = max(sdepth, smax_depth); + + SEARCH_NODE *node = &root[n]; + + //init this node + if(node->vertex<0) + { + node->value = v; + node->left = node->right = -1; + node->vertex = vertex.size(); + sdepth--; + return node->vertex; + } + + straverse += 1.0; + + //if found the same vertex + if(fabs(v-node->value)<2.0*VERTEX_DELTA*VERTEX_DELTA) + if(*sver==*vertex[node->vertex]) + { + sdepth--; + return node->vertex; + } + + //if value less or equal + if(v<=node->value) + if(node->left>=0) + { + long ret = Insert(node->left, v); + sdepth--; + return ret; + } + else + { + node->left = tot_nodes++; + if((tot_nodes%1024)==0) root = (SEARCH_NODE*)realloc(root, sizeof(SEARCH_NODE)*1024*(tot_nodes/1024+1)); + + root[root[n].left].vertex = -1; + long ret = Insert(root[n].left, v); + sdepth--; + return ret; + } + else + //if value greater + if(node->right>=0) + { + long ret = Insert(node->right, v); + sdepth--; + return ret; + } + else + { + node->right = tot_nodes++; + if((tot_nodes%1024)==0) root = (SEARCH_NODE*)realloc(root, sizeof(SEARCH_NODE)*1024*(tot_nodes/1024+1)); + + root[root[n].right].vertex = -1; + long ret = Insert(root[n].right, v); + sdepth--; + return ret; + } +} + +//--------------------------------------------------------------- +//add triangle +//--------------------------------------------------------------- +void EOBJECT::AddTriangle(VERTEX0 **ver) +{ + RDF_TRIANGLE rdft; + for(long v=0; v<3; v++) + { + sver = ver[v]; + float val = ~sver->pos; + + if(tot_nodes==0) + { + tot_nodes++; + root = (SEARCH_NODE*)realloc(root, sizeof(SEARCH_NODE)*((tot_nodes/1024+1)*1024)); + + root->value = val; + root->vertex = -1; + } + + rdft.vindex[v] = Insert(0, val); + + if(rdft.vindex[v]==vertex.size()) + vertex.push_back(ver[v]); + } + trg.push_back(rdft);//*/ + + /*RDF_TRIANGLE rdft; + for(long v=0; v<3; v++) + { + for(long ve = vertex.size()-1; ve>-1; ve--) + if(*ver[v]==*vertex[ve]) break; + //add new vertex + if(ve==-1) + { + rdft.vindex[v] = vertex.size(); + vertex.push_back(ver[v]); + } + else rdft.vindex[v] = ve; + + } + trg.push_back(rdft);//*/ +} + +//--------------------------------------------------------------- +//add triangle +//--------------------------------------------------------------- +void EOBJECT::CalculateBoxRadius() +{ + long v; + for(v=0; vpos.x); + boxmax.y = max(boxmax.y, vertex[v]->pos.y); + boxmax.z = max(boxmax.z, vertex[v]->pos.z); + boxmin.x = min(boxmin.x, vertex[v]->pos.x); + boxmin.y = min(boxmin.y, vertex[v]->pos.y); + boxmin.z = min(boxmin.z, vertex[v]->pos.z); + } + + center = 0.5*(boxmax + boxmin); + + //calculate radius + for(v=0; vpos)); + if(rad>radius) radius = rad; + } +} +//--------------------------------------------------------------- +//add triangle +//--------------------------------------------------------------- +void EOBJECT::Optimize() +{ +} \ No newline at end of file diff --git a/tools/maya-plugin/Export/rdf_exp.cpp b/tools/maya-plugin/Export/rdf_exp.cpp new file mode 100644 index 000000000..75c9f78dc --- /dev/null +++ b/tools/maya-plugin/Export/rdf_exp.cpp @@ -0,0 +1,779 @@ +/****************************************************************************** +File: rdf_exp.cpp + +Author: Nick Chirkov +Copyright (C) 2000, 2001 Nick Chirkov + +Comments: +geometry file format exporter +******************************************************************************/ +#include "export.h" +#include "collide.h" + +extern long nvrts, ntrgs; +extern BTRG *trg; +extern CVECTOR *vrt; +extern long ssize; +extern std::vector lvert; +extern std::vector geolink; +extern BSP_NODE *sroot; +//--------------------------------------------------------------------------------- +//create exporter +//--------------------------------------------------------------------------------- + +extern double straverse; +extern long smax_depth; +//--------------------------------------------------------------------------------- +//init exporter +//--------------------------------------------------------------------------------- +GEOM_STATIC::GEOM_STATIC(const std::string &fname, + TEXTURE_FUNC _tfn, RESULT_FUNC fnr, RESULT_FUNC fne, + float maxedge, float msize, long _flags) + : tfn(_tfn), fnresult(fnr), fnerror(fne), flags(_flags), max_elength(maxedge), merge_size(msize) +{ + if(_flags&ANIMATION) animation=true; + else + { + animation=false; + (_flags&BUILD_BSP)!=0 ? build_bsp=true : build_bsp=false; + } + + //(_flags&PRODUCTION)!=0 ? production=true : production=false; + production=false; + + //(_flags&GEOACCESS)!=0 ? geoaccess=true : geoaccess=false; + + FILE *fll = fopen("stat.txt", "a"); + fprintf(fll, "\n\n\n\n%s\n", fname.c_str()); + fclose(fll); + + fl = fopen(fname.c_str(), "w+b"); + if(fl==0) + { + fnerror(std::string("can't open file for writing")); + return; + } + + trgaddby2side=0; + tot_triangles=0; + tot_vertices=0; + straverse = 0.0; + + merge_size = 1.1f; +} + + +//--------------------------------------------------------------------------------- +//add triangle to current object +//--------------------------------------------------------------------------------- +void GEOM_STATIC::AddObject(const OBJECT &obj) +{ + //invalid material + if(obj.mtl.size()==0) + { + + char er[1024]; + sprintf(er, "no materials in %s, %s", obj.group_name.c_str(), obj.name.c_str()); + fnerror(std::string(er)); + return; + } + + //link materials + long *mtlref = new long[obj.mtl.size()]; + for(long m=0; m0) + if(obj.mtl[m].texture[tx].name!=globname[texture[material[g].texture[tx]]]) break; + } + if(tx==4) break; + } + //add new material + if(g==material.size()) + { + //-----------------fill material properties--------------- + RDF_MATERIAL mt; + mt.group_name = FindGlobalName(obj.mtl[m].group_name); + mt.name = FindGlobalName(obj.mtl[m].name); + mt.diffuse = obj.mtl[m].diffuse; + mt.specular = obj.mtl[m].specular; + mt.gloss = obj.mtl[m].gloss; + mt.selfIllum = obj.mtl[m].selfIllum; + + for(long tm=0; tm<4; tm++) + { + mt.texture_type[tm] = (RDF_TEXTURE_TYPE)obj.mtl[m].texture[tm].type; + if(mt.texture_type[tm]!=TEXTURE_NONE) mt.texture[tm] = AddTexture(obj.mtl[m].texture[tm]); + else mt.texture[tm] = -1; + } + //-------------------------------------------------------- + material.push_back(mt); + } + mtlref[m] = g; + } + + //link objects by material + long *objref = new long[obj.mtl.size()]; + for(long o=0; o= obj.mtl.size()) + { + + char er[1024]; + sprintf(er, "mtl in triangle #:%lu, %s, %s is %d", t, obj.group_name.c_str(), obj.name.c_str(), obj.trg[t].material); + fnerror(std::string(er)); + continue; + } + + EOBJECT *eo = &object[objref[obj.trg[t].material]]; + VERTEX0 *ver[3]; + long vb; + if(material[eo->mtl].texture_type[3]!=TEXTURE_NONE) vb=3; + else + if(material[eo->mtl].texture_type[2]!=TEXTURE_NONE) vb=2; + else + if(material[eo->mtl].texture_type[1]!=TEXTURE_NONE) vb=1; + else if(material[eo->mtl].texture_type[0]!=TEXTURE_NONE) vb=0; + else continue; //if incorrect material + if(animation) vb += 4; + + for(long v=0; v<3; v++) + { + switch(vb) + { + case 0: ver[v] = new VERTEX0(obj.trg[t].vrt[v]); break; + case 1: ver[v] = new VERTEX1(obj.trg[t].vrt[v]); break; + case 2: ver[v] = new VERTEX2(obj.trg[t].vrt[v]); break; + case 3: ver[v] = new VERTEX3(obj.trg[t].vrt[v]); break; + //animation + case 4: ver[v] = new VERTEXA0(obj.trg[t].vrt[v]); break; + } + } + + + //add new object if vertex count is 65536 or more + if(eo->vertex.size()+3>65536) + { + //replace all references to this object by last object + EOBJECT newo; + newo.flags = eo->flags; + newo.group_name = eo->group_name; + newo.name = eo->name; + newo.mtl = eo->mtl; + object.push_back(newo); + + objref[obj.trg[t].material] = object.size()-1; + eo = &object[objref[obj.trg[t].material]]; + } + eo->AddTriangle(ver); + + //dublicate triangle + if((obj.flags&CULLENABLE)==0) + { + trgaddby2side++; + + for(long v=0; v<3; v++) + { + switch(vb) + { + case 0: ver[v] = new VERTEX0(obj.trg[t].vrt[v]); break; + case 1: ver[v] = new VERTEX1(obj.trg[t].vrt[v]); break; + case 2: ver[v] = new VERTEX2(obj.trg[t].vrt[v]); break; + case 3: ver[v] = new VERTEX3(obj.trg[t].vrt[v]); break; + //animation + case 4: ver[v] = new VERTEXA0(obj.trg[t].vrt[v]); break; + } + ver[v]->norm = -ver[v]->norm; + ver[v]->pos += 1e-2f*ver[v]->norm; + } + + + //cull mode + VERTEX0 *dvr = ver[0]; + ver[0] = ver[1]; + ver[1] = dvr; + + //add new object if vertex count is 65536 or more + if(eo->vertex.size()+3>65536) + { + //replace all references to this object by last object + EOBJECT newo; + newo.flags = eo->flags; + newo.group_name = eo->group_name; + newo.name = eo->name; + newo.mtl = eo->mtl; + object.push_back(newo); + + objref[obj.trg[t].material] = object.size()-1; + eo = &object[objref[obj.trg[t].material]]; + } + //move this triangle by norm to avoid coplanar + eo->AddTriangle(ver); + } + + } + + delete objref; +} + +//--------------------------------------------------------------------------------- +//add light source +//--------------------------------------------------------------------------------- +void GEOM_STATIC::AddLight(const LIGHT &l) +{ + RDF_LIGHT lt; + lt.pos = CVECTOR(l.x, l.y, l.z); + lt.dir = CVECTOR(l.nx, l.ny, l.nz); + lt.atten[0] = l.atten[0]; lt.atten[1] = l.atten[1]; lt.atten[2] = l.atten[2]; + lt.r = l.r; lt.g = l.g; lt.b = l.b; + lt.falloff = l.falloff; + lt.inner = l.inner; + lt.outer = l.outer; + lt.type = (RDF_LIGHT_TYPE)l.type; + lt.range = l.range; + lt.flags = l.flags; + lt.name = FindGlobalName(l.name); + lt.group_name = FindGlobalName(l.group_name); + + light.push_back(lt); +} + +GEOM_STATIC::~GEOM_STATIC() +{ +} +//--------------------------------------------------------------------------------- +//export procedure +//--------------------------------------------------------------------------------- +void GEOM_STATIC::WriteFile() +{ + ssize = 0; + + RDF_HEAD rh; + fseek(fl, sizeof RDF_HEAD, SEEK_SET); + rh.version = RDF_VERSION; + rh.flags = 0; + rh.name_size = 0; + rh.ntextures = texture.size(); + rh.nmaterials = material.size(); + rh.nlights = light.size(); + rh.nobjects = 0; + rh.ntriangles = 0; + rh.nvrtbuffs = 0; + rh.nlabels = label.size(); + rh.names = globname.size(); + rh.bbox_size = rh.bbox_center = rh.radius = 0.0f; + CVECTOR bmin = 1e20; + CVECTOR bmax = -1e20; + + + //write NAMES and build a lookup table + std::vector lookup; + for(long n=0; n=lookup.size()) + { + fnerror(std::string("Texture name is invalid")); + return; + } + fwrite((char*)&lookup[texture[t]], sizeof(long), 1, fl); + } + + //write materials + for(long m=0; m=lookup.size()) + { + fnerror(std::string("Material name is invalid")); + return; + } + if(material[m].group_name<0 || material[m].group_name>=lookup.size()) + { + fnerror(std::string("Material group_name is invalid")); + return; + } + material[m].name = lookup[material[m].name]; + material[m].group_name = lookup[material[m].group_name]; + fwrite((char*)&material[m], sizeof RDF_MATERIAL, 1, fl); + } + + //write lights + for(long l=0; l=lookup.size()) + { + fnerror(std::string("Light name is invalid")); + return; + } + if(light[l].group_name<0 || light[l].group_name>=lookup.size()) + { + fnerror(std::string("Light group_name is invalid")); + return; + } + light[l].name = lookup[light[l].name]; + light[l].group_name = lookup[light[l].group_name]; + fwrite((char*)&light[l], sizeof RDF_LIGHT, 1, fl); + } + + //write labels + for(long lb=0; lb=lookup.size()) + { + fnerror(std::string("Label name is invalid")); + return; + } + if(label[lb].group_name<0 || label[lb].group_name>=lookup.size()) + { + fnerror(std::string("Label group_name is invalid")); + return; + } + label[lb].group_name = lookup[label[lb].group_name]; + label[lb].name = lookup[label[lb].name]; + fwrite((char*)&label[lb], sizeof RDF_LABEL, 1, fl); + } + + COLLIDE col(fnresult); + + //------------------------------------------------------------------- + //calculate boxsize + long o; + for(o=0; opos.x); + bmin.y = min(bmin.y, object[o].vertex[v]->pos.y); + bmin.z = min(bmin.z, object[o].vertex[v]->pos.z); + bmax.x = max(bmax.x, object[o].vertex[v]->pos.x); + bmax.y = max(bmax.y, object[o].vertex[v]->pos.y); + bmax.z = max(bmax.z, object[o].vertex[v]->pos.z); + } + + /*if(merge_size<1.0f) + { + merge_size *= 0.5f*sqrtf(~(bmax-bmin)); + //split objects + for(o=0; o65536) + vertex_buff += 8; + start_vrt[vertex_buff] += object[o].vertex.size(); + obj2vb[o] = vertex_buff; + } + + rh.bbox_size = bmax-bmin; + rh.bbox_center = 0.5f*(bmax+bmin); + + //write objects + long xlat_vbr[8*8]; + long combuf=0; + for(long vb=0; vb<8*8; vb++) + if(start_vrt[vb]>0) + xlat_vbr[vb] = combuf++; + + //------------------------------------------------- + //write objects and add geometry to BSP + long bsp_trg_offset = 0; + bool bsp_compiled = false; + memset(start_vrt, 0, sizeof(start_vrt)); + for(o=0; o=lookup.size()) + { + fnerror(std::string("Group name is invalid")); + return; + } + if(object[o].name<0 || object[o].name>=lookup.size()) + { + fnerror(std::string("Object name is invalid")); + return; + } + ro.group_name = lookup[object[o].group_name]; + ro.name = lookup[object[o].name]; + ro.flags = object[o].flags; + ro.material = object[o].mtl; + ro.ntriangles = object[o].trg.size(); + ro.striangle = rh.ntriangles; + rh.ntriangles += ro.ntriangles; + object[o].CalculateBoxRadius(); + ro.center = CVECTOR(object[o].center.x, object[o].center.y, object[o].center.z); + ro.radius = object[o].radius; + + ro.vertex_buff = xlat_vbr[obj2vb[o]]; + ro.nvertices = object[o].vertex.size(); + ro.svertex = start_vrt[obj2vb[o]]; + start_vrt[obj2vb[o]] += ro.nvertices; + + //collision enable + if(build_bsp==true && (object[o].flags&COLLISION_ENABLE)) + { + bsp_trg_offset += object[o].trg.size(); + col.AddMesh(o, object[o].vertex, object[o].vertex.size(), &object[o].trg[0], object[o].trg.size()); + bsp_compiled = true; + + } + ro.atriangles = bsp_trg_offset; + + fwrite((char*)&ro, sizeof RDF_OBJECT, 1, fl); + } + build_bsp = bsp_compiled; + + //write triangles + for(o=0; o0) + { + RDF_VERTEXBUFF vb; + vb.type = vrb&7; + long stride = sizeof(RDF_VERTEX0) + (vrb&3)*8 + ((vrb>>2)&1)*8; + vb.size = start_vrt[vrb]*stride; + fwrite((char*)&vb, sizeof RDF_VERTEXBUFF, 1, fl); + rh.nvrtbuffs++; + } + + //write vertices + for(vrb=0; vrb<8*8; vrb++) + for(o=0; ostore(&buf[0]); + fwrite(&buf[0], 1, size, fl); + rh.radius = max(rh.radius, sqrtf(~(object[o].vertex[v]->pos - rh.bbox_center))); + } + tot_vertices += object[o].vertex.size(); + } + delete[] obj2vb; + + FILE *fll = fopen("stat.txt", "a"); + fprintf(fll, "objects: %d, textures: %d, materials: %d\n", rh.nobjects, rh.ntextures, rh.nmaterials); + fprintf(fll, "triangles: %d, vertices: %d\n", tot_triangles, tot_vertices); + fprintf(fll, "2-sided triangles: %d\n", trgaddby2side); + fprintf(fll, "-----------------------------------\n"); + fprintf(fll, "bbox_size: %f,%f,%f, radius: %f\n", rh.bbox_size.x, rh.bbox_size.y, rh.bbox_size.z, rh.radius); + fprintf(fll, "-----------------------------------\n"); + fprintf(fll, "traverses/vertex: %f, max depth: %d\n", float(straverse/(tot_triangles*3.0)), smax_depth); + + fclose(fll); + + if(build_bsp==true) + { + rh.flags |= FLAGS_BSP_PRESENT; + //build BSP + col.BuildBSP(production); + //write bsp header + RDF_BSPHEAD bhead; + bhead.nnodes = ssize; + bhead.nvertices = nvrts; + bhead.ntriangles = ntrgs; + fwrite((char*)&bhead, sizeof RDF_BSPHEAD, 1, fl); + fwrite(sroot, sizeof BSP_NODE, bhead.nnodes, fl); + } + //write vertices and triangles for BSP and geoaccess + fwrite(&vrt[0], sizeof RDF_BSPVERTEX, nvrts, fl); + for(t=0; t>0)&0xFF; + btr.vindex[v][1] = (trg[t].vindex[v]>>8)&0xFF; + btr.vindex[v][2] = (trg[t].vindex[v]>>16)&0xFF; + } + fwrite(&btr, sizeof RDF_BSPTRIANGLE, 1, fl); + } + + + //write header + fseek(fl, 0, SEEK_SET); + fwrite((char*)&rh, sizeof RDF_HEAD, 1, fl); + + fclose(fl); +} + + +long GEOM_STATIC::FindGlobalName(const std::string &str) +{ + //find existing string + long s; + for(s=0; spos.x); + bmin.y = min(bmin.y, object[o].vertex[object[o].trg[t].vindex[v]]->pos.y); + bmin.z = min(bmin.z, object[o].vertex[object[o].trg[t].vindex[v]]->pos.z); + bmax.x = max(bmax.x, object[o].vertex[object[o].trg[t].vindex[v]]->pos.x); + bmax.y = max(bmax.y, object[o].vertex[object[o].trg[t].vindex[v]]->pos.y); + bmax.z = max(bmax.z, object[o].vertex[object[o].trg[t].vindex[v]]->pos.z); + } + CVECTOR cn = 0.5f*(bmax + bmin); + + //temporary calculate radius of object + float rd = 0.0f; + for(v=0; v<3; v++) + { + float rad = sqrtf(~(cn - object[o].vertex[object[o].trg[t].vindex[v]]->pos)); + if(rad>rd) rd = rad; + } + + if(rd>merge_size) reftrg[t]=-1; + else reftrg[t]=1; + } + + long removedtrg=0; + long added_objs=0; + for(;;) + { + EOBJECT eo; + eo.flags = object[o].flags; + eo.group_name = object[o].group_name; + eo.name = object[o].name; + eo.mtl = object[o].mtl; + //add triangles to be in sphere with merge_size + float radius = 0.0f; + CVECTOR bn = 1e10f; + CVECTOR bx = -1e10f; + for(long t=0; tpos.x); + bmin.y = min(bmin.y, object[o].vertex[object[o].trg[t].vindex[v]]->pos.y); + bmin.z = min(bmin.z, object[o].vertex[object[o].trg[t].vindex[v]]->pos.z); + bmax.x = max(bmax.x, object[o].vertex[object[o].trg[t].vindex[v]]->pos.x); + bmax.y = max(bmax.y, object[o].vertex[object[o].trg[t].vindex[v]]->pos.y); + bmax.z = max(bmax.z, object[o].vertex[object[o].trg[t].vindex[v]]->pos.z); + } + CVECTOR cn = 0.5f*(bmax + bmin); + + //temporary calculate radius of object + float rd = radius; + for(v=0; v<3; v++) + { + float rad = sqrtf(~(cn - object[o].vertex[object[o].trg[t].vindex[v]]->pos)); + if(rad>rd) rd = rad; + } + + //if new size less than merge_size + if(rd<=merge_size) + { + VERTEX0 *av[3]; + av[0] = object[o].vertex[object[o].trg[t].vindex[0]]; + av[1] = object[o].vertex[object[o].trg[t].vindex[1]]; + av[2] = object[o].vertex[object[o].trg[t].vindex[2]]; + eo.AddTriangle(av); + radius = rd; + bn = bmin; + bx = bmax; + reftrg[t] = 0; + removedtrg++; + } + } + if(removedtrg==object[o].trg.size()) + { + object[o] = eo; + break; + } + else + object.push_back(eo); + added_objs++; + } + + delete reftrg; +} diff --git a/tools/maya-plugin/Export/rdf_exp.h b/tools/maya-plugin/Export/rdf_exp.h new file mode 100644 index 000000000..373a44293 --- /dev/null +++ b/tools/maya-plugin/Export/rdf_exp.h @@ -0,0 +1,201 @@ +/****************************************************************************** +File: rdf_exp.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef _RDFLIB_I_H_ +#define _RDFLIB_I_H_ + +#include +#include +#include + +//texture callback +typedef void (*TEXTURE_FUNC)(long id); +//result callback +typedef bool (*RESULT_FUNC)(const std::string &s); + +class EXPORT_STATIC +{ +public: + + //-------------------------------------------------------------- + //texture + //-------------------------------------------------------------- + enum TEXTURE_TYPE + { + NONE = 0, + BASE, + NORMAL, + LIGHTMAP, + TEXTURE_FORCEDWORD = 0x7FFFFFFF + }; + struct TEXTURE + { + std::string name; + TEXTURE_TYPE type; + long id; //will be returned + }; + + //-------------------------------------------------------------- + //material + //-------------------------------------------------------------- + enum BRDF_TYPE + { + PHONG = 0, + BLINN, + METALL, + BRDF_FORCEDWORD = 0x7FFFFFFF + }; + struct MATERIAL + { + std::string group_name; + std::string name; + BRDF_TYPE brdf; + float diffuse; //0 - no diffuse material + float specular, gloss; //spec=0 - no specular, gloss is a power of cosine + float selfIllum; //for area light sources + float transparency, refraction_id; + float reflection; //0 for non-mirrors + TEXTURE texture[4]; + }; + + //-------------------------------------------------------------- + //vertex + //-------------------------------------------------------------- + struct VERTEX + { + float x,y,z; + float nx,ny,nz; + float tu[4], tv[4]; + //skinned animation + float weight[4]; + long boneid[4]; + long color; + }; + + //-------------------------------------------------------------- + //triangle + //-------------------------------------------------------------- + struct TRIANGLE + { + long material; + VERTEX vrt[3]; + }; + + //-------------------------------------------------------------- + //object + //-------------------------------------------------------------- + enum OBJECT_FLAGS + { + VISIBLE = (1<<0), + STATIC_LIGHT_ENABLE = (1<<1), //if no - object will not be lited + DINAMIC_LIGHT_ENABLE = (1<<2), //if no - no dynamic lighting perfomed + CAST_SHADOWS_ENABLE = (1<<3), //if material makes shadows + COLLISION_ENABLE = (1<<4), //if yes - object will be stored to BSP + + //geometry access flags + GEO_VERTEX = (1<<5), //vertices will be stored to geoaccess + GEO_VERTEX_TRIANGLE = (1<<6), //triangles and vertices will be stored to geoaccess + GEO_EDGE = (1<<7), //edges and vertices will be stored to geoaccess + GEO_EDGE_TRIANGLE = (1<<8), //triangles, edges and vertices will be stored to geoaccess + + VERTEX_WEIGHT = (1<<9), //animation + MERGE = (1<<10), //object is "merged"-type + CULLENABLE = (1<<11), //single-sided object + ZSORTED = (1<<12), //insert triangles into BSP for z-sorting during render + OBJECT_FORCEDWORD = 0x7FFFFFFF + + }; + struct OBJECT + { + long flags; //combination of OBJECT_FLAGS + std::string group_name; + std::string name; + + std::vector mtl; + std::vector trg; + float disp; + }; + //add a triangle by the vertex's index to the current sub-object + virtual void AddObject(const OBJECT &obj) = 0; + + //-------------------------------------------------------------- + //light source + //-------------------------------------------------------------- + enum LIGHT_TYPE + { + POINT = 0, + SPOT, + DIRECTIONAL, + LIGHT_FORCEDWORD = 0x7FFFFFFF + }; + enum LIGHT_FLAGS + { + SHADOW = 1, + LIGHT_FORCED_WORD = 0x7FFFFFFF + }; + struct LIGHT + { + std::string group_name; + std::string name; + long flags; + LIGHT_TYPE type; + float r,g,b; + float range; + float x,y,z; + float atten[3]; + float nx,ny,nz; + float inner, outer, falloff; + }; + //add a light sources + virtual void AddLight(const LIGHT &l) = 0; + + //-------------------------------------------------------------- + //label + //-------------------------------------------------------------- + enum LABEL_FLAGS + { + LABEL_FORCEDWORD = 0x7FFFFFFF + }; + struct LABEL + { + std::string group_name; + std::string name; + + long flags; //combination of LABEL_FLAGS + float vector[4][4]; + long bones[4]; + float weight[4]; + }; + //add a label + virtual void AddLabel(const LABEL &l) = 0; + + //-------------------------------------------------------------- + // + //-------------------------------------------------------------- + virtual ~EXPORT_STATIC(){}; + + //write file function + virtual void WriteFile() = 0; + +}; + +enum EXP_FLAGS +{ + BUILD_BSP=1, + PRODUCTION=2, + ANIMATION=4, + GEOACCESS=8, + EXP_FORCE_DWORD = 0x7FFFFFFF +}; + +typedef EXPORT_STATIC * (__cdecl *CREATE_EXPORT_FUNC)(const std::string &fname, + TEXTURE_FUNC Textures, + RESULT_FUNC statistic, RESULT_FUNC errors, + float maxedge, float merge_size, long flags); + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Export/vertex.h b/tools/maya-plugin/Export/vertex.h new file mode 100644 index 000000000..140c7812e --- /dev/null +++ b/tools/maya-plugin/Export/vertex.h @@ -0,0 +1,269 @@ +/****************************************************************************** +File: vertex.h + +Author: Nick Chirkov +Copyright (C) 2000-2002 Nick Chirkov + +Comments: +******************************************************************************/ +#ifndef __VERTEX_H__ +#define __VERTEX_H__ + +#include +#include "export.h" + +#define MIN_SQUARE 1e-20f +#define VERTEX_DELTA 1e-10f +#define TEXTURE_DELTA 1e-4f +#define NORMAL_DELTA 0.99f +#define WEIGHT_DELTA 1e-3f + +//---------------------------------------------------------------------- +//vertex types hierarchy +//---------------------------------------------------------------------- +class VERTEX0 +{ +public: + CVECTOR pos; + CVECTOR norm; + long color; + float tu0, tv0; + + VERTEX0(const EXPORT_STATIC::VERTEX &v) + { + pos = CVECTOR(v.x, v.y, v.z); + norm = CVECTOR(v.nx, v.ny, v.nz); + color = v.color; + tu0 = v.tu[0]; tv0 = v.tv[0]; + } + + virtual bool operator==(const VERTEX0 &rv) + { + return( + fabs(rv.tu0 - tu0) < TEXTURE_DELTA && + fabs(rv.tv0 - tv0) < TEXTURE_DELTA && + ~(rv.pos - pos) < VERTEX_DELTA*VERTEX_DELTA && + rv.color==color && + (rv.norm|norm) > NORMAL_DELTA + ); + } + + virtual long size() + { + return sizeof(RDF_VERTEX0); + } + virtual long store(char *buf) + { + RDF_VERTEX0 *v = (RDF_VERTEX0*)buf; + v->pos = pos; + v->norm = norm; + v->color = color; + v->tu0 = tu0; + v->tv0 = tv0; + return size(); + } + virtual long load(char *buf) + { + RDF_VERTEX0 *v = (RDF_VERTEX0*)buf; + pos = v->pos; + norm = v->norm; + color = v->color; + tu0 = v->tu0; + tv0 = v->tv0; + return size(); + } + +}; + + +//---------------------------------------------------------------------- +// 2 texture sets +//---------------------------------------------------------------------- +class VERTEX1 : public VERTEX0 +{ +public: + float tu1, tv1; + + VERTEX1(const EXPORT_STATIC::VERTEX &v) : VERTEX0(v) + { + tu1 = v.tu[1]; tv1 = v.tv[1]; + } + + virtual bool operator==(const VERTEX0 &_rv) + { + VERTEX1 &rv = *(VERTEX1*)&_rv; + return( + fabs(rv.tu1 - tu1) < TEXTURE_DELTA && fabs(rv.tv1 - tv1) < TEXTURE_DELTA && + VERTEX0::operator==(rv) + ); + } + + virtual long size() + { + return sizeof(RDF_VERTEX1); + } + virtual long store(char *buf) + { + RDF_VERTEX1 *v = (RDF_VERTEX1*)buf; + VERTEX0::store(buf); + v->tu1 = tu1; v->tv1 = tv1; + return size(); + } + virtual long load(char *buf) + { + RDF_VERTEX1 *v = (RDF_VERTEX1*)buf; + VERTEX0::load(buf); + tu1 = v->tu1; + tv1 = v->tv1; + return size(); + } + +}; + + +//---------------------------------------------------------------------- +// 3 texture sets +//---------------------------------------------------------------------- +class VERTEX2 : public VERTEX1 +{ +public: + float tu2, tv2; + + VERTEX2(const EXPORT_STATIC::VERTEX &v) : VERTEX1(v) + { + tu2 = v.tu[2]; tv2 = v.tv[2]; + } + + virtual bool operator==(const VERTEX0 &_rv) + { + VERTEX2 &rv = *(VERTEX2*)&_rv; + return( + fabs(rv.tu2 - tu2) < TEXTURE_DELTA && fabs(rv.tv2 - tv2) < TEXTURE_DELTA && + VERTEX1::operator==(rv) + ); + } + + virtual long size() + { + return sizeof(RDF_VERTEX2); + } + virtual long store(char *buf) + { + RDF_VERTEX2 *v = (RDF_VERTEX2*)buf; + VERTEX1::store(buf); + v->tu2 = tu2; v->tv2 = tv2; + return size(); + } + virtual long load(char *buf) + { + RDF_VERTEX2 *v = (RDF_VERTEX2*)buf; + VERTEX1::load(buf); + tu2 = v->tu2; + tv2 = v->tv2; + return size(); + } + +}; + + +//---------------------------------------------------------------------- +// 3 texture sets +//---------------------------------------------------------------------- +class VERTEX3 : public VERTEX2 +{ +public: + float tu3, tv3; + + VERTEX3(const EXPORT_STATIC::VERTEX &v) : VERTEX2(v) + { + tu3 = v.tu[3]; tv3 = v.tv[3]; + } + + virtual bool operator==(const VERTEX0 &_rv) + { + VERTEX3 &rv = *(VERTEX3*)&_rv; + return( + fabs(rv.tu3 - tu3) < TEXTURE_DELTA && fabs(rv.tv3 - tv3) < TEXTURE_DELTA && + VERTEX2::operator==(rv) + ); + } + + virtual long size() + { + return sizeof(RDF_VERTEX3); + } + virtual long store(char *buf) + { + RDF_VERTEX3 *v = (RDF_VERTEX3*)buf; + VERTEX2::store(buf); + v->tu3 = tu3; v->tv3 = tv3; + return size(); + } + virtual long load(char *buf) + { + RDF_VERTEX3 *v = (RDF_VERTEX3*)buf; + VERTEX2::load(buf); + tu3 = v->tu3; + tv3 = v->tv3; + return size(); + } + +}; + + +//---------------------------------------------------------------------- +// 1 texture sets with animation +//---------------------------------------------------------------------- +class VERTEXA0 : public VERTEX0 +{ +public: + float weight; + unsigned long boneid; + + VERTEXA0(const EXPORT_STATIC::VERTEX &v) : VERTEX0(v) + { + weight = v.weight[0]; + boneid = (v.boneid[1]<<8)|(v.boneid[0]<<0); + } + + virtual bool operator==(const VERTEXA0 &_rv) + { + VERTEXA0 &rv = *(VERTEXA0*)&_rv; + return( + fabs(rv.weight - weight) < WEIGHT_DELTA && rv.boneid==boneid && + VERTEX0::operator==(rv) + ); + } + + virtual long size() + { + return sizeof(RDF_AVERTEX0); + } + virtual long store(char *buf) + { + RDF_AVERTEX0 *v = (RDF_AVERTEX0*)buf; + v->pos = pos; + v->weight = weight; + v->boneid = boneid; + v->norm = norm; + v->color = color; + v->tu0 = tu0; + v->tv0 = tv0; + return size(); + } + virtual long load(char *buf) + { + RDF_AVERTEX0 *v = (RDF_AVERTEX0*)buf; + pos = v->pos; + weight = v->weight; + boneid = v->boneid; + norm = v->norm; + color = v->color; + tu0 = v->tu0; + tv0 = v->tv0; + return size(); + } +}; + + +#endif \ No newline at end of file diff --git a/tools/maya-plugin/Geometry/AtlaExport.cpp b/tools/maya-plugin/Geometry/AtlaExport.cpp new file mode 100644 index 000000000..e875953d6 --- /dev/null +++ b/tools/maya-plugin/Geometry/AtlaExport.cpp @@ -0,0 +1,1616 @@ +#define LOG + +#define CM2M_SCALE 0.01f + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include"AtlaExport.h" + +constexpr auto R2Y = 0.299f; +constexpr auto G2Y = 0.587f; +constexpr auto B2Y = 0.114f; + +#include + +#include +#include +#include +#include + + +bool MakePathForTraceMaker(char* buf) +{ + const char* cl = ::GetCommandLineA(); + if (cl[0] != '"') return false; + long i; + for (i = 1; cl[i] && cl[i] != '"'; i++) buf[i - 1] = cl[i]; + if (cl[i] != '"') return false; + for (i--; buf[i] != '\\' && i >= 0; i--); + i++; + const char* fileName = "TraceMaker.exe"; + for (long j = 0; fileName[j]; i++, j++) buf[i] = fileName[j]; + buf[i] = 0; + return true; +} + + +EXPORT_STATIC* rexp; +FILE* LogFile = 0; + +void Log(const char* fmt, ...) +{ +#ifdef LOG + va_list args; + va_start(args, fmt); + vfprintf(LogFile, fmt, args); + va_end(args); +#endif +} + +MStatus status; +#include +#include + +bool Result(const std::string& s) +{ + MString command = "text -edit -label \""; + command += s.c_str(); + command += "\" MyLable"; + MGlobal::executeCommand(command, true); + //MGlobal::executeCommand("showWindow StatusWin",true); + return true; +} + +bool Error(const std::string& s) +{ + MString command = "text -edit -label \""; + command += s.c_str(); + command += "\" MyLable"; + MGlobal::executeCommand(command, true); + FILE* errfl = fopen("error.txt", "w+a"); + fprintf(errfl, "%s\n", s.c_str()); + fclose(errfl); + return true; +} + +#include +#include + +struct BONEWEIGHT +{ + long idBone[4]; + float weight[4]; +}; + +MDagPathArray mJointsList{}; + +void FillJoints(MDagPath& path) +{ + MItDag dagIterator(MItDag::kBreadthFirst, MFn::kJoint, &status); + if (!status) return; + + for (; !dagIterator.isDone(); dagIterator.next()) + { + MDagPath dagPath; + status = dagIterator.getPath(dagPath); // Get DagPath + if (!status) return; + + //MObject object = dagIterator.currentItem(&status); // Get MObject + //if (!status) return; + + status = mJointsList.append(dagPath); + //status = mJointsList.add(dagPath, object, false); + //Log( "JOINT_ADDED: %s\n", dagPath.fullPathName().asChar()); + } +} + +void SaveAnimation(BONEWEIGHT* ani, MDagPath& path, long nverts) +{ + memset(ani, 0, sizeof(BONEWEIGHT) * nverts); + + MStatus status; + auto name = path.fullPathName(); + Log("\n\n\nobject: %s\n", name.asChar()); + FillJoints(path); + + MItDependencyNodes iter(MFn::kSkinClusterFilter); // Create SkinClusters iterator + if (iter.isDone()) return; // No SkinClusters + + for (; !iter.isDone(); iter.next()) + { +#if MAYA_API_VERSION <= 500 + MObject object = iter.item(); +#else + MObject object = iter.thisNode(); +#endif + MFnSkinCluster fnSkinCluster; + status = fnSkinCluster.setObject(object); // Get MFnSkinCluster interface + if (!status) continue; + + int numConnections = fnSkinCluster.numOutputConnections(&status); + if (numConnections == 0) continue; + + for (int con = 0; con < numConnections; con++) // Check Output connections + { + int PlugIndex = fnSkinCluster.indexForOutputConnection(con, &status); + if (!status) continue; + + MDagPath SkinDagPath; + status = fnSkinCluster.getPathAtIndex(PlugIndex, SkinDagPath); // Check connectoin to current shape + SkinDagPath.pop(); + if (!(SkinDagPath == path)) continue; + + MDagPathArray InfsObjectsArray; + fnSkinCluster.influenceObjects(InfsObjectsArray, &status); + if (!status) return; + + MItGeometry gIter(SkinDagPath); + for (; !gIter.isDone(); gIter.next()) // cycle for all vertexes in geometry -- + { +#if MAYA_API_VERSION <= 500 + MObject component = gIter.component(&status); +#else + MObject component = gIter.currentItem(&status); +#endif + if (!status) return; + + MFloatArray WeightArray; + unsigned int numInfl; + status = fnSkinCluster.getWeights(SkinDagPath, component, WeightArray, numInfl); + if (!status) return; + + int idxVrt = gIter.index(); + int count = 0; + for (long i = 0; i < numInfl; i++) + { + if (WeightArray[i] == 0.0f) continue; + + long J_Index = -1; + for (long joint = 0; joint < mJointsList.length(); joint++) + { + MDagPath dagPath = mJointsList[joint]; + if (!(InfsObjectsArray[i] == dagPath)) continue; + J_Index = joint; + break; + } + if (J_Index < 0) return; + + if (count >= 2) // More then 4 objects + { + long j = 0; + if (ani[idxVrt].weight[1] < ani[idxVrt].weight[0]) j = 1; + + if (WeightArray[i] > std::max(ani[idxVrt].weight[0], ani[idxVrt].weight[1])) + { + ani[idxVrt].weight[j] = WeightArray[i]; + ani[idxVrt].idBone[j] = J_Index; + } + } + else // Less then 4 objects + { + ani[idxVrt].weight[count] = WeightArray[i]; + ani[idxVrt].idBone[count] = J_Index; + } + count++; + } + + + //normalize value + float normw = 1.0f / (ani[idxVrt].weight[0] + ani[idxVrt].weight[1]); + ani[idxVrt].weight[0] *= normw; + ani[idxVrt].weight[1] *= normw; + + for (long w = 0; w < 4; w++) + Log("%f, %d, ", ani[idxVrt].weight[w], ani[idxVrt].idBone[w]); + Log("\n"); + } //all geometry + } //connections + } +}; + + +AtlaExport::AtlaExport() +{ +} + +AtlaExport::~AtlaExport() +{ +} + +void MulMtx(float* matrix, float* m1, float* m2) +{ + matrix[0] = m2[0] * m1[0] + m2[4] * m1[1] + m2[8] * m1[2] + m2[12] * m1[3]; + matrix[1] = m2[1] * m1[0] + m2[5] * m1[1] + m2[9] * m1[2] + m2[13] * m1[3]; + matrix[2] = m2[2] * m1[0] + m2[6] * m1[1] + m2[10] * m1[2] + m2[14] * m1[3]; + matrix[3] = m2[3] * m1[0] + m2[7] * m1[1] + m2[11] * m1[2] + m2[15] * m1[3]; + + matrix[4] = m2[0] * m1[4] + m2[4] * m1[5] + m2[8] * m1[6] + m2[12] * m1[7]; + matrix[5] = m2[1] * m1[4] + m2[5] * m1[5] + m2[9] * m1[6] + m2[13] * m1[7]; + matrix[6] = m2[2] * m1[4] + m2[6] * m1[5] + m2[10] * m1[6] + m2[14] * m1[7]; + matrix[7] = m2[3] * m1[4] + m2[7] * m1[5] + m2[11] * m1[6] + m2[15] * m1[7]; + + matrix[8] = m2[0] * m1[8] + m2[4] * m1[9] + m2[8] * m1[10] + m2[12] * m1[11]; + matrix[9] = m2[1] * m1[8] + m2[5] * m1[9] + m2[9] * m1[10] + m2[13] * m1[11]; + matrix[10] = m2[2] * m1[8] + m2[6] * m1[9] + m2[10] * m1[10] + m2[14] * m1[11]; + matrix[11] = m2[3] * m1[8] + m2[7] * m1[9] + m2[11] * m1[10] + m2[15] * m1[11]; + + matrix[12] = m2[0] * m1[12] + m2[4] * m1[13] + m2[8] * m1[14] + m2[12] * m1[15]; + matrix[13] = m2[1] * m1[12] + m2[5] * m1[13] + m2[9] * m1[14] + m2[13] * m1[15]; + matrix[14] = m2[2] * m1[12] + m2[6] * m1[13] + m2[10] * m1[14] + m2[14] * m1[15]; + matrix[15] = m2[3] * m1[12] + m2[7] * m1[13] + m2[11] * m1[14] + m2[15] * m1[15]; +} + +bool GetFloatValues(MObject& obj, const char* name, float& f0, float& f1) +{ + MFnDependencyNode NodeFnDn; + NodeFnDn.setObject(obj); + MStatus status; +#if MAYA_API_VERSION <= 500 + MPlug rpuv = NodeFnDn.findPlug(name, &status); +#else + MPlug rpuv = NodeFnDn.findPlug(name, false, &status); +#endif + if (!status) return false; + MObject val; + rpuv.getValue(val); + MFnNumericData numFn(val); + numFn.getData(f0, f1); + //Log( "%s, %f, %f\n", name, f0, f1); + return true; +} + +bool GetDoubleValue(MObject& obj, const char* name, double& d) +{ + MFnDependencyNode NodeFnDn; + NodeFnDn.setObject(obj); + MStatus status; +#if MAYA_API_VERSION <= 500 + MPlug rpuv = NodeFnDn.findPlug(name, &status); +#else + MPlug rpuv = NodeFnDn.findPlug(name, false, &status); +#endif + if (!status) return false; + MObject val; + rpuv.getValue(d); + return true; +} + +MMatrix GetLocator(MDagPath& path, MMatrix& localRotation) +{ + //adjust local position + double dbvx, dbvy, dbvz; + MDagPath shape = path; + shape.push(path.child(0)); + auto obj = shape.node(); + GetDoubleValue(obj, "localPositionX", dbvx); + GetDoubleValue(obj, "localPositionY", dbvy); + GetDoubleValue(obj, "localPositionZ", dbvz); + MVector translate; + translate.x = dbvx; + translate.y = dbvy; + translate.z = dbvz; + MTransformationMatrix mtrs; + mtrs.setTranslation(translate, MSpace::kWorld); + + //rotation component will be stored + obj = path.node(); + GetDoubleValue(obj, "rotateX", dbvx); + GetDoubleValue(obj, "rotateY", dbvy); + GetDoubleValue(obj, "rotateZ", dbvz); + MEulerRotation rt; + rt.x = dbvx; + rt.y = dbvy; + rt.z = dbvz; + MTransformationMatrix mtrr; + mtrr.rotateTo(rt); + localRotation = mtrr.asMatrix(); + + MMatrix mtx = mtrs.asMatrix() * path.inclusiveMatrix(); + return mtx; +} + +bool ExportCharacterPatch; + +MStatus AtlaExport::writer(const MFileObject& file, const MString& optionsString, FileAccessMode mode) +{ + MStringArray optionList; + MStringArray theOption; + optionsString.split(';', optionList); + + is_scaled_ = false; + bool bsp = false; + bool animation = false; + bool product = false; + ExportCharacterPatch = false; + + for (DWORD i = 0; i < optionList.length(); ++i) + { + theOption.clear(); + optionList[i].split('=', theOption); + if (theOption.length() <= 1) continue; + + if (theOption[0] == MString("Check1")) + { + if (theOption[1].asInt()) is_scaled_ = true; + } + if (theOption[0] == MString("Check2")) + { + if (theOption[1].asInt()) bsp = true; + } + if (theOption[0] == MString("Check3")) + { + if (theOption[1].asInt()) animation = true; + } + if (theOption[0] == MString("ExportCharacterPatch")) + { + if (theOption[1].asInt()) ExportCharacterPatch = true; + } + /*if(theOption[0] == MString("radioGrp1")) + { + if( theOption[1].asInt()==2 ) product = true; + else product = false; + }*/ + + //----------------------------------// + } // next i(element list) + + if (ExportCharacterPatch) bsp = true; + GlobAnimation = animation; + if (GlobAnimation) bsp = false; + +#if MAYA_API_VERSION <= 500 + MString fname = file.fullName(); +#else + MString fname = file.expandedFullName(); +#endif + ExportAll(fname.asChar(), bsp); + return (MS::kSuccess); +} + +bool AtlaExport::haveWriteMethod() const +{ + return (true); +} + +MString AtlaExport::defaultExtension() const +{ + return MString("gm"); +} + +MPxFileTranslator::MFileKind AtlaExport::identifyFile(const MFileObject& file, const char* buffer, short size) const +{ +#if MAYA_API_VERSION <= 500 + const char* name = file.name().asChar(); +#else + const char* name = file.resolvedName().asChar(); +#endif + int nameLength = strlen(name); + + return (kIsMyFileType); + //return (kNotMyFileType); +} + +void* AtlaExport::creator() +{ + return new AtlaExport(); +} + +// command for adding extra parameters +class ExtraCommand : public MPxCommand +{ +public: + MStatus doIt(const MArgList&) + { + MItDag itDag; + MDagPath dagPath; + + while (!itDag.isDone()) + { + itDag.getPath(dagPath); + itDag.next(); + if (!dagPath.hasFn(MFn::kMesh)) continue; + + MFnDependencyNode fnDep(dagPath.node()); + + if (dagPath.hasFn(MFn::kTransform)) + { + MFnNumericAttribute attr; + + MObject rdfattrib = attr.create("visible", "visible", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + rdfattrib = attr.create("static_light", "static_light", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + rdfattrib = attr.create("dynamic_light", "dynamic_light", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + rdfattrib = attr.create("merge", "merge", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + rdfattrib = attr.create("collision", "collision", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + rdfattrib = attr.create("cast_shadows", "cast_shadows", MFnNumericData::kBoolean, 1); + fnDep.addAttribute(rdfattrib); + } + /*else + { + MObject att; + att = fnDep.attribute("visible", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("static_light", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("dynamic_light", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("merge", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("collision", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("geometry_access", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + att = fnDep.attribute("cast_shadows", &status); if(status==MS::kSuccess) fnDep.removeAttribute(att); + }//*/ + } + return MS::kSuccess; + } + + static void* creator() + { + return new ExtraCommand(); + } +}; + +//**************************************************************** +__declspec(dllexport) MStatus initializePlugin(MObject obj) +{ + using namespace std::string_literals; + MStatus status; + MFnPlugin plugin(obj, "Nick Chirkov (C) 2001", "1.0"); + auto pixmapName = ""s; + auto pluginName = "SD2GeoExportMel"s; + status = plugin.registerFileTranslator("SD2GeoExport", &pixmapName[0], AtlaExport::creator, &pluginName[0]); + plugin.registerCommand("addsex", ExtraCommand::creator); + return (status); +} + +__declspec(dllexport) MStatus uninitializePlugin(MObject obj) +{ + MFnPlugin plugin(obj); + plugin.deregisterFileTranslator("SD2GeoExport"); + plugin.deregisterCommand("addsex"); + return (MS::kSuccess); +} + +size_t AtlaExport::CountObjects(const MDagPath& path) +{ + auto object_count = 0ull; + //geometry object + if (path.hasFn(MFn::kMesh) && path.hasFn(MFn::kTransform)) + { + object_count++; + } + + //recurse all children + const auto children_count = path.childCount(&status); + for (auto i = 0u; i < children_count; i++) + { + auto child = path.child(i, &status); + auto new_path = path; + new_path.push(child); + + //export locator + object_count += CountObjects(new_path); + } + + return object_count; +} + + +float locator_mtx[4][4]; +static long depth = -1; + +void AtlaExport::ExportLocator(MDagPath& cl) +{ + //search if selected + MSelectionList slist; + MGlobal::getActiveSelectionList(slist); + MItSelectionList iter(slist); + MItDag dagIterator(MItDag::kDepthFirst, MFn::kInvalid, &status); + for (; !iter.isDone(); iter.next()) + { + MDagPath objectPath; + status = iter.getDagPath(objectPath); + if (objectPath == cl) + break; + } + //if locator is not selected do not export + if (iter.isDone() == true) return; + + MDagPath gpath(cl); + MMatrix localRotation; + MMatrix locator_m = GetLocator(gpath, localRotation); + + gpath.pop(); + MFnDagNode fdagnodeg(gpath); + MFnDagNode fdagnode(cl); + + EXPORT_STATIC::LABEL loc; + loc.group_name = std::string(fdagnodeg.name().asChar()); + loc.name = std::string(fdagnode.name().asChar()); + loc.flags = 0; + memset(&loc.bones[0], 0, sizeof(loc.bones)); + memset(&loc.weight[0], 0, sizeof(loc.weight)); + + long joint; + for (joint = 0; joint < mJointsList.length(); joint++) + { + MDagPath dagPath = mJointsList[joint]; + if (gpath == dagPath) break; + } + //----------------------------------------------- + //get matrix for locator + float mtx[4][4]; + MMatrix glob_parent(locator_mtx); + MMatrix local_loc; + //joint is correct + if (joint < mJointsList.length()) + { + loc.bones[0] = joint; + Log("locator_bone: %d\n", joint); + /* MDagPath jointPath; + mJointsList.getDagPath(joint, jointPath); + MMatrix jm = jointPath.inclusiveMatrix().transpose(); + local_loc = locator_m * jm; + Log( "bone Matrix: \n"); + for(long ry=0; ry<4; ry++) + { + for(long rx=0; rx<4; rx++) + Log( "%f, ", jm[ry][rx]); + Log( "\n\n"); + }*/ + } //else + local_loc = locator_m * glob_parent; + + if (GlobAnimation) + { + local_loc[3][0] *= 0.01f; + local_loc[3][1] *= 0.01f; + local_loc[3][2] *= 0.01f; + } + else + { + local_loc[0][0] = local_loc[1][1] = local_loc[2][2] = local_loc[3][3] = 1.0f; + local_loc[0][1] = local_loc[0][2] = local_loc[0][3] = 0.0f; + local_loc[1][0] = local_loc[1][2] = local_loc[1][3] = 0.0f; + local_loc[2][0] = local_loc[2][1] = local_loc[2][3] = 0.0f; + local_loc[3][0] *= -0.01f; + local_loc[3][1] *= 0.01f; + local_loc[3][2] *= 0.01f; + local_loc = localRotation.transpose() * local_loc; + } + + //store to locator + local_loc.get(mtx); + memcpy(&loc.vector[0][0], &mtx[0][0], sizeof(loc.vector)); + + //memset(loc.vector, 0, sizeof loc.vector); loc.vector[0][0] = loc.vector[1][1] = loc.vector[2][2] = loc.vector[3][3] = 1.0f; + + Log("LOCATOR ADDED TO HIERARCHY: %s\n", loc.name.c_str()); + for (long ry = 0; ry < 4; ry++) + { + for (long rx = 0; rx < 4; rx++) + Log("%f, ", loc.vector[ry][rx]); + Log("\n"); + } + for (long l = 0; l < locators_.size(); l++) + if (locators_[l] == loc.name) + { + loc.group_name = std::string("geometry"); + break; + } + + Log("group_name: %s\n", loc.group_name.c_str()); + Log("name: %s\n\n", loc.name.c_str()); + + //------------------------------------------------------------------------ + //add locator + //------------------------------------------------------------------------ + try + { + rexp->AddLabel(loc); + } + catch (char* errmsg) + { + MString command = "text -edit -label \""; + command += errmsg; + command += "\" MyLable"; + MGlobal::executeCommand(command, true); + MGlobal::executeCommand("showWindow StatusWin", true); + Sleep(2000); + } +} + +void AtlaExport::Traverse(MDagPath& path) +{ + depth++; + //-------------------------------------------------------- + //geometry object + //-------------------------------------------------------- + if (path.hasFn(MFn::kMesh) && path.hasFn(MFn::kTransform)) + { + MString command = "text -edit -label \"Export object "; + char ee[256]; + sprintf(ee, "%d / %d", curobject + 1, total_objects); + command += ee; + command += "\" MyLable"; + MGlobal::executeCommand(command, true); + MGlobal::executeCommand("showWindow StatusWin", true); + curobject++; + + EXPORT_STATIC::OBJECT exp_obj; + EXPORT_STATIC::MATERIAL exp_mtl; + EXPORT_STATIC::TRIANGLE exp_trg; + //------------------------------------------------------------------------ + //object + MFnMesh fnMesh(path, &status); + if (!status) goto SkipObj; //throw "error fnMesh"; + + //group & object name + MDagPath gpath(path); + gpath.pop(); + MFnDagNode fdagnodeg(gpath); + MFnDagNode fdagnode(path); + exp_obj.group_name = std::string(fdagnodeg.name(&status).asChar()); + exp_obj.name = std::string(fdagnode.name(&status).asChar()); + + //------------------------------------------------------------------------ + //extra attributes + exp_obj.flags = 0; + + bool vis, stlt, dnlt, mg, col, cs; +#if MAYA_API_VERSION <= 500 + fdagnode.findPlug("visible", &status).getValue(vis); +#else + fdagnode.findPlug("visible", false, &status).getValue(vis); +#endif + if (!status) + { + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::VISIBLE; + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::STATIC_LIGHT_ENABLE; + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::DINAMIC_LIGHT_ENABLE; + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::MERGE; + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::COLLISION_ENABLE; + exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::CAST_SHADOWS_ENABLE; + } + else + { +#if MAYA_API_VERSION <= 500 + fdagnode.findPlug("static_light", nullptr).getValue(stlt); + fdagnode.findPlug("dynamic_light", nullptr).getValue(dnlt); + fdagnode.findPlug("merge", nullptr).getValue(mg); + fdagnode.findPlug("collision", nullptr).getValue(col); + fdagnode.findPlug("cast_shadows", nullptr).getValue(cs); +#else + fdagnode.findPlug("static_light", false, nullptr).getValue(stlt); + fdagnode.findPlug("dynamic_light", false, nullptr).getValue(dnlt); + fdagnode.findPlug("merge", false, nullptr).getValue(mg); + fdagnode.findPlug("collision", false, nullptr).getValue(col); + fdagnode.findPlug("cast_shadows", false, nullptr).getValue(cs); +#endif + + if (vis) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::VISIBLE; + if (stlt) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::STATIC_LIGHT_ENABLE; + if (dnlt) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::DINAMIC_LIGHT_ENABLE; + if (mg) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::MERGE; + if (col) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::COLLISION_ENABLE; + if (cs) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::CAST_SHADOWS_ENABLE; + } + + //------------------------------------------------------------------------ + //double side + bool doublesided = false; +#if MAYA_API_VERSION <= 500 + MPlug pdside = fnMesh.findPlug("doubleSided", &status); +#else + MPlug pdside = fnMesh.findPlug("doubleSided", false, &status); +#endif + if (status) pdside.getValue(doublesided); + if (!doublesided) exp_obj.flags |= EXPORT_STATIC::OBJECT_FLAGS::CULLENABLE; + + //------------------------------------------------------------------------ + //opposite + bool opposite = false; +#if MAYA_API_VERSION <= 500 + MPlug poppos = fnMesh.findPlug("opposite", &status); +#else + MPlug poppos = fnMesh.findPlug("opposite", false, &status); +#endif + if (status) poppos.getValue(opposite); + + //------------------------------------------------------------------------ + //object info + + //get uvset names + long uvsets = fnMesh.numUVSets(); + MStringArray msArray; + fnMesh.getUVSetNames(msArray); + long uvsettype[8]; + //calculate UVsets + bool color_present = false; + long s; + for (s = 0; s < uvsets; s++) + if (msArray[s] == "color") + color_present = true; + + for (s = 0; s < uvsets; s++) + { + uvsettype[s] = -1; + + //base texture + if (msArray[s] == "bump") uvsettype[s] = 1; + else if (msArray[s] == "color") uvsettype[s] = 0; + else + if (!color_present && msArray[s] == "map1") uvsettype[s] = 0; + } + + long InstaceNumber = path.instanceNumber(&status); + if (!status) + { + goto SkipObj; //throw "error instanceNumber"; + } + + MObjectArray ArrayOfSharers; + MIntArray ArrayOfIndex; + status = fnMesh.getConnectedShaders(InstaceNumber, ArrayOfSharers, ArrayOfIndex); + if (!status) + { + Error(std::string("error getConnectedShaders")); + goto SkipObj; //throw "error getConnectedShaders"; + } + + //------------------------------------------------------------------------ + //material + //------------------------------------------------------------------------ + //reference + for (unsigned long i = 0; i < ArrayOfSharers.length(); i++) + { + long m; + for (m = 0; m < nummat; m++) + //if(ArrayOfSharers[i]==material[m].MO) break;// && uvsets==material[m].ntex) break; + if (ArrayOfSharers[i] == *material[m].MO) break; + + if (m == nummat) + { + //optical params + MFnDependencyNode fnNode; + fnNode.setObject(ArrayOfSharers[i]); +#if MAYA_API_VERSION <= 500 + MPlug shaderPlug = fnNode.findPlug("surfaceShader", &status); +#else + MPlug shaderPlug = fnNode.findPlug("surfaceShader", false, &status); +#endif + if (status) + { + MPlugArray connectedPlugs; + shaderPlug.connectedTo(connectedPlugs, true, false); + if (connectedPlugs.length() == 1) + { + MObject ShaderObject = connectedPlugs[0].node(); + switch (ShaderObject.apiType()) + { + case MFn::kPhong: + { + MFnPhongShader fnShader(ShaderObject); + material[m].gloss = fnShader.cosPower(); + material[m].specular = fnShader.reflectivity(); + MColor sp_color = fnShader.specularColor(&status); + if (status) material[m].specular = sp_color.r * R2Y + sp_color.g * G2Y + sp_color.b * + B2Y; + material[m].brdf = EXPORT_STATIC::PHONG; //brdf + material[m].diffuse = fnShader.diffuseCoeff(); //diffuse + MColor si_color = fnShader.incandescence(&status); //selfillumination + if (status) material[m].selfIllum = R2Y * si_color.r + G2Y * si_color.g + B2Y * si_color + .b; + MColor tr_color = fnShader.transparency(&status); //transparency + if (status) material[m].transparency = R2Y * tr_color.r + G2Y * tr_color.g + B2Y * + tr_color.b; + material[m].refraction_id = fnShader.refractiveIndex(&status); //refraction +#if MAYA_API_VERSION <= 500 + MPlug reflectPlug = fnShader.findPlug("reflectionSpecularity", &status); +#else + MPlug reflectPlug = fnShader.findPlug("reflectionSpecularity", false, &status); +#endif + //reflection + if (status) reflectPlug.getValue(material[m].reflection); + } + break; + case MFn::kLambert: + { + MFnLambertShader fnShader(ShaderObject); + material[m].brdf = EXPORT_STATIC::PHONG; //brdf + material[m].diffuse = fnShader.diffuseCoeff(); //diffuse + MColor si_color = fnShader.incandescence(&status); //selfillumination + if (status) material[m].selfIllum = R2Y * si_color.r + G2Y * si_color.g + B2Y * si_color + .b; + MColor tr_color = fnShader.transparency(&status); //transparency + if (status) material[m].transparency = R2Y * tr_color.r + G2Y * tr_color.g + B2Y * + tr_color.b; + material[m].refraction_id = fnShader.refractiveIndex(&status); //refraction +#if MAYA_API_VERSION <= 500 + MPlug reflectPlug = fnShader.findPlug("reflectionSpecularity", &status); +#else + MPlug reflectPlug = fnShader.findPlug("reflectionSpecularity", false, &status); +#endif + //reflection + if (status) reflectPlug.getValue(material[m].reflection); + material[m].gloss = 2.0f; + material[m].specular = 0.0f; + material[m].specular = 0.0f; + } + break; + } + } + } + + + material[m].MO = new MObject(ArrayOfSharers[i]); + material[m].ntex = 0; + //shader's name + MFnDependencyNode fndn(ArrayOfSharers[i]); + sprintf(material[m].matname, "%s", fndn.name().asChar()); + //material[m].texname[0][0] = 0; + sprintf(material[m].texname[0], "%s", "checker.tga"); + material[m].texname[1][0] = 0; + material[m].texname[2][0] = 0; + material[m].texname[3][0] = 0; + + //------------------------------------------------------------------------ + //find lambert + MItDependencyGraph DpGraph(ArrayOfSharers[i], + MFn::kLambert, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel, &status); + DpGraph.disablePruningOnFilter(); +#if MAYA_API_VERSION <= 500 + MObject LambertNode = DpGraph.thisNode(); +#else + MObject LambertNode = DpGraph.currentItem(); +#endif + + //------------------------------------------------------------------------ + status = DpGraph.resetTo(LambertNode, MFn::kLayeredTexture, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel); + DpGraph.enablePruningOnFilter(); + + //if layered texture found + if (!DpGraph.isDone()) + { +#if MAYA_API_VERSION <= 500 + auto obj = DpGraph.thisNode(); +#else + auto obj = DpGraph.currentItem(); +#endif + status = DpGraph.resetTo(obj, MFn::kFileTexture, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel); + //all layers + if (status) + { + while (!DpGraph.isDone()) + { + long curlayer = -1; + + //search associated textures + for (long s = 0; s < uvsets; s++) + { + MObjectArray texArr; + fnMesh.getAssociatedUVSetTextures(msArray[s], texArr); + + //curlayer = -1 if no textures for this set + //if(texArr.length()==0) break; + + //if map1 uvset and 2 textures associated so + if (uvsets == 1 && texArr.length() == 2) DpGraph.next(); + + //for all textures in this uvset + long t; + for (t = 0; t < texArr.length(); t++) +#if MAYA_API_VERSION <= 500 + if (DpGraph.thisNode() == texArr[t]) break; +#else + if (DpGraph.currentItem() == texArr[t]) break; +#endif + + if (t < texArr.length()) + { + curlayer = uvsettype[s]; + break; + } + } + + //if color or bump + if (curlayer >= 0) + { + MFnDependencyNode NodeFnDn; +#if MAYA_API_VERSION <= 500 + NodeFnDn.setObject(DpGraph.thisNode()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", &status); +#else + NodeFnDn.setObject(DpGraph.currentItem()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", false, &status); +#endif + MObject fnameValue; + plugToFile.getValue(fnameValue); + MFnStringData stringFn(fnameValue); + MString nm = stringFn.string(); + + strcpy(material[m].texname[curlayer], stringFn.string().asChar()); +#if MAYA_API_VERSION <= 500 + obj = DpGraph.thisNode(); +#else + obj = DpGraph.currentItem(); +#endif + GetFloatValues(obj, "repeatUV", material[m].repeat[curlayer][0], + material[m].repeat[curlayer][1]); + GetFloatValues(obj, "offset", material[m].offset[curlayer][0], + material[m].offset[curlayer][1]); + GetDoubleValue(obj, "rotateFrame", material[m].rotate[curlayer]); + + material[m].ntex++; + } + + DpGraph.next(); + } + } + } + else //try to find file texture + { + //base texture--------------------------------------- + status = DpGraph.resetTo(LambertNode, MFn::kFileTexture, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel); + DpGraph.enablePruningOnFilter(); + if (status && !DpGraph.isDone()) + { + MFnDependencyNode NodeFnDn; +#if MAYA_API_VERSION <= 500 + NodeFnDn.setObject(DpGraph.thisNode()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", &status); +#else + NodeFnDn.setObject(DpGraph.currentItem()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", false, &status); +#endif + MObject fnameValue; + plugToFile.getValue(fnameValue); + MFnStringData stringFn(fnameValue); + MString nm = stringFn.string(); + + strcpy(material[m].texname[0], stringFn.string().asChar()); +#if MAYA_API_VERSION <= 500 + auto obj = DpGraph.thisNode(); +#else + auto obj = DpGraph.currentItem(); +#endif + GetFloatValues(obj, "repeatUV", material[m].repeat[0][0], material[m].repeat[0][1]); + GetFloatValues(obj, "offset", material[m].offset[0][0], material[m].offset[0][1]); + GetDoubleValue(obj, "rotateFrame", material[m].rotate[0]); + + material[m].ntex++; + } + + //bump texture--------------------------------------- + status = DpGraph.resetTo(LambertNode, MFn::kBump, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel); + + DpGraph.disablePruningOnFilter(); + if (status && !DpGraph.isDone()) + { +#if MAYA_API_VERSION <= 500 + auto obj = DpGraph.thisNode(); +#else + auto obj = DpGraph.currentItem(); +#endif + status = DpGraph.resetTo(obj, MFn::kFileTexture, + MItDependencyGraph::kUpstream, + MItDependencyGraph::kBreadthFirst, + MItDependencyGraph::kNodeLevel); + //texture file + DpGraph.enablePruningOnFilter(); + if (status && !DpGraph.isDone()) + { + MFnDependencyNode NodeFnDn; +#if MAYA_API_VERSION <= 500 + NodeFnDn.setObject(DpGraph.thisNode()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", &status); +#else + NodeFnDn.setObject(DpGraph.currentItem()); + MPlug plugToFile = NodeFnDn.findPlug("fileTextureName", false, &status); +#endif + MObject fnameValue; + plugToFile.getValue(fnameValue); + MFnStringData stringFn(fnameValue); + MString nm = stringFn.string(); + strcpy(material[m].texname[1], stringFn.string().asChar()); +#if MAYA_API_VERSION <= 500 + obj = DpGraph.thisNode(); +#else + obj = DpGraph.currentItem(); +#endif + GetFloatValues(obj, "repeatUV", material[m].repeat[1][0], material[m].repeat[1][1]); + GetFloatValues(obj, "offset", material[m].offset[1][0], material[m].offset[1][1]); + GetDoubleValue(obj, "rotateFrame", material[m].rotate[1]); + + material[m].ntex++; + } + } + } + if (material[m].ntex > 0) + { + nummat++; + if (nummat == 1024) + { + Error(std::string("Internal error: too much materials")); + depth--; + return; + } + } + + Log("%s\n", material[m].matname); + Log("%f\n", material[m].selfIllum); + Log("%f\n", material[m].diffuse); + Log("%f\n", material[m].gloss); + Log("%f\n", material[m].specular); + Log("%d\n", material[m].brdf); + Log("%f\n", material[m].reflection); + Log("%f\n", material[m].refraction_id); + Log("%f\n", material[m].transparency); + for (long ti = 0; ti < 4; ti++) + { + if (material[m].texname[ti][0] == 0) continue; + Log("%s\n", material[m].texname[ti]); + } + Log("\n\n"); //*/ + } + + exp_mtl.brdf = material[m].brdf; + exp_mtl.diffuse = material[m].diffuse; + exp_mtl.specular = material[m].specular; + exp_mtl.gloss = material[m].gloss; + exp_mtl.selfIllum = material[m].selfIllum; + exp_mtl.transparency = material[m].transparency; + exp_mtl.refraction_id = material[m].refraction_id; + exp_mtl.reflection = material[m].reflection; + exp_mtl.group_name = std::string("unknown material group"); + exp_mtl.name = std::string(material[m].matname); + + //fill material + for (long ti = 0; ti < 4; ti++) + { + exp_mtl.texture[ti].id = 0; + exp_mtl.texture[ti].type = EXPORT_STATIC::NONE; + if (material[m].texname[ti][0] == 0) continue; + + switch (ti) + { + case 0: + exp_mtl.texture[0].type = EXPORT_STATIC::BASE; + break; + case 1: + exp_mtl.texture[1].type = EXPORT_STATIC::NORMAL; + break; + case 2: + exp_mtl.texture[2].type = EXPORT_STATIC::BASE; + break; + case 3: + exp_mtl.texture[3].type = EXPORT_STATIC::BASE; + break; + } + + char* ctemp = strrchr(material[m].texname[ti], '\\'); + if (ctemp == 0) ctemp = strrchr(material[m].texname[ti], '/'); + if (ctemp == 0) ctemp = material[m].texname[ti]; + else ctemp++; + + exp_mtl.texture[ti].name = std::string(ctemp); + } + + //add material + //if(material[m].ntex>0)//NOTE_IT + { + exp_obj.mtl.push_back(exp_mtl); + matref[i] = m; + } + } + + //------------------------------------------------------------------------ + //transformation + //------------------------------------------------------------------------ + //mtx * path_mtx * INVERSE(locator_mtx) + //vrt = v*mtx -> vertex is reletive to locator + MMatrix locator_pos(locator_mtx); + MMatrix m = path.inclusiveMatrix() * locator_pos; + float mtx[4][4]; + status = m.get(mtx); + + + MTransformationMatrix mtrans = MTransformationMatrix(m); + double scale[3]; + mtrans.getScale(scale, MSpace::kWorld); + if (scale[0] * scale[1] * scale[2] < 0.0f) opposite = !opposite; + /*Log( "OBJECT_TRANSFORM: %s::%s\n", fdagnodeg.name(&status).asChar(), fdagnode.name(&status).asChar()); + for(long ry=0; ry<4; ry++) + { + for(long rx=0; rx<4; rx++) + Log( "%f, ", mtx[ry][rx]); + Log( "\n"); + } + Log( "\n");//*/ + + //------------------------------------------------------------------------ + //polygon + //------------------------------------------------------------------------ + //get vertex coord + MPointArray mesh_vrt; + fnMesh.getPoints(mesh_vrt); + + MFloatVectorArray meshNorm; + fnMesh.getNormals(meshNorm, MSpace::kWorld); + + BONEWEIGHT* ani = new BONEWEIGHT[fnMesh.numVertices()]; + if (GlobAnimation) SaveAnimation(ani, path, fnMesh.numVertices()); + //get colors + MColorArray mesh_col; + fnMesh.getFaceVertexColors(mesh_col); + + //get points + MFloatPointArray vertexArray; + fnMesh.getPoints(vertexArray); + + //polygon iterator + MItMeshPolygon itPoly(path); + + for (long p = 0; p < fnMesh.numPolygons(); p++) + { + //get triangles + if (itPoly.hasValidTriangulation() == false) + { + itPoly.next(); + continue; + } + exp_trg.material = ArrayOfIndex[p]; + long mmt = matref[exp_trg.material]; + + MIntArray vrtId; + itPoly.getVertices(vrtId); + + MPointArray points; + MIntArray vertexList; + int nTrgs; + itPoly.numTriangles(nTrgs); + for (int nt = 0; nt < nTrgs; nt++) + { + itPoly.getTriangle(nt, points, vertexList); + for (long v = 0; v < 3; v++) + { + int faceRelIndex; + for (faceRelIndex = 0; faceRelIndex < vrtId.length(); faceRelIndex++) + if (vrtId[faceRelIndex] == vertexList[v]) + break; + + //color-per-vertex + int colidx; + fnMesh.getFaceVertexColorIndex(p, v, colidx); + if (colidx < 0 || colidx >= mesh_col.length() || mesh_col[colidx].a < 0.0f) + //no colors here + exp_trg.vrt[v].color = 0xFF7F7F7F; + else + { + long a = long(255.0f * mesh_col[colidx].a); + long r = std::min(127l, long(127.0f * mesh_col[colidx].r)); + long g = std::min(127l, long(127.0f * mesh_col[colidx].g)); + long b = std::min(127l, long(127.0f * mesh_col[colidx].b)); + exp_trg.vrt[v].color = (a << 24) | (r << 16) | (g << 8) | b; + //Log( "%lu\n", exp_trg.vrt[v].color); + } + + //bones and weights + exp_trg.vrt[v].boneid[0] = ani[vertexList[v]].idBone[0]; + exp_trg.vrt[v].boneid[1] = ani[vertexList[v]].idBone[1]; + exp_trg.vrt[v].boneid[2] = ani[vertexList[v]].idBone[2]; + exp_trg.vrt[v].boneid[3] = ani[vertexList[v]].idBone[3]; + exp_trg.vrt[v].weight[0] = ani[vertexList[v]].weight[0]; + exp_trg.vrt[v].weight[1] = ani[vertexList[v]].weight[1]; + exp_trg.vrt[v].weight[2] = ani[vertexList[v]].weight[2]; + exp_trg.vrt[v].weight[3] = ani[vertexList[v]].weight[3]; + //Log( "%f, %f, %f, %f\n", exp_trg.vrt[v].weight[0], exp_trg.vrt[v].weight[1], exp_trg.vrt[v].weight[2], exp_trg.vrt[v].weight[3]); + + //position + float dx = mesh_vrt[vertexList[v]].x; + float dy = mesh_vrt[vertexList[v]].y; + float dz = mesh_vrt[vertexList[v]].z; + exp_trg.vrt[v].x = dx * mtx[0][0] + dy * mtx[1][0] + dz * mtx[2][0] + mtx[3][0]; + exp_trg.vrt[v].y = dx * mtx[0][1] + dy * mtx[1][1] + dz * mtx[2][1] + mtx[3][1]; + exp_trg.vrt[v].z = dx * mtx[0][2] + dy * mtx[1][2] + dz * mtx[2][2] + mtx[3][2]; + + if (is_scaled_) + { + exp_trg.vrt[v].x *= CM2M_SCALE; + exp_trg.vrt[v].y *= CM2M_SCALE; + exp_trg.vrt[v].z *= CM2M_SCALE; + } + + //normal + MVector norm; + itPoly.getNormal(faceRelIndex, norm, MSpace::kWorld); + exp_trg.vrt[v].nx = norm.x; + exp_trg.vrt[v].ny = norm.y; + exp_trg.vrt[v].nz = norm.z; + + if (!GlobAnimation) + { + exp_trg.vrt[v].x *= -1.0f; + exp_trg.vrt[v].nx *= -1.0f; + } + + /*if(opposite) //reverce normal + { + exp_trg.vrt[v].nx *= -1.0f; + exp_trg.vrt[v].ny *= -1.0f; + exp_trg.vrt[v].nz *= -1.0f; + }//*/ + + // UV set + for (long s = 0; s < uvsets; s++) + if (uvsettype[s] != -1) + { + float U, V; + float uvp[2]; + status = itPoly.getUV(faceRelIndex, uvp, &msArray[s]); + if (!status) + { + Log("can't get UV[%d] for uvSet: %d\n", uvsettype[s], s); + exp_trg.vrt[v].tu[uvsettype[s]] = 0.62109375f; + exp_trg.vrt[v].tv[uvsettype[s]] = 0.62109375f; + continue; + } + U = uvp[0]; + V = uvp[1]; + + float ang = -material[mmt].rotate[uvsettype[s]]; + float tU, tV; + tU = (U - 0.5f) * cosf(ang) + (V - 0.5f) * sinf(ang) + 0.5f; + tV = (V - 0.5f) * cosf(ang) - (U - 0.5f) * sinf(ang) + 0.5f; + tU *= material[mmt].repeat[uvsettype[s]][0]; + tV *= material[mmt].repeat[uvsettype[s]][1]; + tU += material[mmt].offset[uvsettype[s]][0]; + tV += material[mmt].offset[uvsettype[s]][1]; + + switch (uvsettype[s]) + { + case 0: + exp_trg.vrt[v].tu[0] = tU; + exp_trg.vrt[v].tv[0] = -tV; + break; + case 1: + exp_trg.vrt[v].tu[1] = tU; + exp_trg.vrt[v].tv[1] = -tV; + break; + } + + if (uvsets == 1) + for (long nt = 1; nt < material[mmt].ntex; nt++) + { + float ang = material[mmt].rotate[nt]; + tU = (U - 0.5f) * cosf(ang) + (V - 0.5f) * sinf(ang) + 0.5f; + tV = (V - 0.5f) * cosf(ang) - (U - 0.5f) * sinf(ang) + 0.5f; + tU *= material[mmt].repeat[nt][0]; + tV *= material[mmt].repeat[nt][1]; + tU += material[mmt].offset[nt][0]; + tV += material[mmt].offset[nt][1]; + + exp_trg.vrt[v].tu[nt] = tU; + exp_trg.vrt[v].tv[nt] = -tV; + } + } //*/ + } + //we use CCW, Maya uses CW back-face culling + if (!opposite) + { + EXPORT_STATIC::VERTEX tvrt = exp_trg.vrt[0]; + exp_trg.vrt[0] = exp_trg.vrt[1]; + exp_trg.vrt[1] = tvrt; + } + exp_obj.trg.push_back(exp_trg); + } + + itPoly.next(); + } + delete ani; + //------------------------------------------------------------------------ + //add object + //------------------------------------------------------------------------ + try + { + rexp->AddObject(exp_obj); + } + catch (char* errmsg) + { + MString command = "text -edit -label \""; + command += errmsg; + command += "\" MyLable"; + MGlobal::executeCommand(command, true); + MGlobal::executeCommand("showWindow StatusWin", true); + Sleep(2000); + } + } +SkipObj:; + //-------------------------------------------------------- + //recurse all children + //-------------------------------------------------------- + long nc = path.childCount(&status); + for (long c = 0; c < nc; c++) + { + MObject chlo = path.child(c, &status); + MDagPath cl = path; + cl.push(chlo); + + //export locator + if (cl.hasFn(MFn::kLocator) && cl.hasFn(MFn::kTransform)) + { + ExportLocator(cl); + } + else Traverse(cl); + } + + //if animation export we needs to link all other locators to the root + if (GlobAnimation && path.hasFn(MFn::kLocator) && path.hasFn(MFn::kTransform)) + { + MDagPath gpath(path); + gpath.pop(); + + //if parent of this locator is a joint - skip this + //if(!gpath.hasFn(MFn::kJoint)) + MFnDagNode fdagnodeg(gpath); + if (_strcmpi(fdagnodeg.name().asChar(), "world") == 0) + { + Log("#######: %s\n", fdagnodeg.name().asChar()); + + MSelectionList slist; + MGlobal::getActiveSelectionList(slist); + MItSelectionList iter(slist); + + for (; !iter.isDone(); iter.next()) + { + MDagPath exLoc; + status = iter.getDagPath(exLoc); + + //if the node is a root + if (path == exLoc) continue; + + //only locators + if (exLoc.hasFn(MFn::kLocator) && exLoc.hasFn(MFn::kTransform)) + { + ExportLocator(exLoc); + } + } + } + } + depth--; +} + +void SaveRTXtexture(long id) +{ + //printf(" SaveRTXtexture(%d) \n",id); +} + +void AtlaExport::ExportAll(const std::string& file_name, bool bsp) +{ + curobject = total_objects = 0; + + auto path = file_name; + if (auto extension_offset = path.find(".gm"); extension_offset != std::string::npos) + { + path.erase(extension_offset); + } + + auto selection_list = MSelectionList(); + MGlobal::getActiveSelectionList(selection_list); + + auto dag_iterator = MItDag(MItDag::kDepthFirst, MFn::kInvalid, &status); + + MGlobal::executeCommand("window -tlc 300 300 -w 300 -h 200 -title \"RDF Export\" StatusWin", true); + MGlobal::executeCommand("columnLayout -adjustableColumn true", true); + MGlobal::executeCommand("text -label \"Default\" MyLable", true); + MGlobal::executeCommand("showWindow StatusWin", true); + + MGlobal::executeCommand("text -edit -label \"Search root\" MyLable", true); + MGlobal::executeCommand("showWindow StatusWin", true); + + auto start_frame = MTime(MAnimControl::minTime().value(), MTime::uiUnit()); + auto time = MTime(start_frame.value(), MTime::uiUnit()); + MAnimControl::setCurrentTime(time); + + //search for many roots + auto roots = std::vector(); + for (auto it = MItSelectionList(selection_list); !it.isDone(); it.next()) + { + auto object_path = MDagPath(); + status = it.getDagPath(object_path); + + //only locators + if (object_path.hasFn(MFn::kLocator) && object_path.hasFn(MFn::kTransform)) + { + auto name = std::string(object_path.fullPathName().asChar()); + //search for parent or child and remove children + size_t root_index; + for (root_index = 0; root_index < roots.size(); ++root_index) + { + auto& other_name = roots[root_index]; + if (name.starts_with(other_name)) + { + break; + } + + if (other_name.starts_with(name)) + { + roots.erase(roots.begin() + root_index); + } + } + + //add new entry + if (root_index == roots.size()) + { + roots.emplace_back(std::move(name)); + } + + //only one root for animated model + //if(GlobAnimation) break; + } + } + + //------------------------------------------------------------------- + //calculate number of objects + locators_.clear(); + for (auto it = MItSelectionList(selection_list); !it.isDone(); it.next()) + { + auto object_path = MDagPath(); + status = it.getDagPath(object_path); + + //only locators + if (object_path.hasFn(MFn::kLocator) && object_path.hasFn(MFn::kTransform)) + { + //this locator has geometry data and must be marked under "geometry" group + if (auto objects_num = CountObjects(object_path); objects_num > 0) + { + auto node = MFnDagNode(object_path); + locators_.emplace_back(node.name().asChar()); + total_objects += objects_num; + } + } + } + + //------------------------------------------------------------------- + //export all selected locators + for (auto it = MItSelectionList(selection_list); !it.isDone(); it.next()) + { + auto object_path = MDagPath(); + status = it.getDagPath(object_path); + + //only locators + if (object_path.hasFn(MFn::kLocator) && object_path.hasFn(MFn::kTransform)) + { + auto node = MFnDagNode(object_path); + auto node_name = std::string(node.name().asChar()); + + //skip locators without any objects attached + if (std::ranges::find(locators_, node_name) == locators_.end()) + { + continue; + } + + auto new_path = std::format("{}_{}", path, node_name); + //auto new_name = std::format("{}_{}.atg", partial_name, pname); + + //find root + auto object_name = std::string(object_path.fullPathName().asChar()); + if (GlobAnimation || roots.size() == 1 && roots[0] == object_name) + { + new_path = path; + } + +#ifdef LOG + LogFile = fopen((new_path + ".atg").c_str(), "w"); +#endif + nummat = 0; + + //------------------------------------------------------------------------------ + auto gm_path = new_path + ".gm"; + + long flags = 0; + if (bsp) flags |= BUILD_BSP; + //if(product) flags |= PRODUCTION; + if (GlobAnimation) flags |= ANIMATION; + rexp = new GEOM_STATIC(gm_path, SaveRTXtexture, Result, Error, 1e10f, 1.0f, flags); + //------------------------------------------------------------------------------ + //unsigned long time = GetTickCount(); + + //create locator matrix + auto local_rotation = MMatrix(); + auto locator_m = GetLocator(object_path, local_rotation); + + locator_m.inverse(); + + locator_m[0][0] = locator_m[1][1] = locator_m[2][2] = locator_m[3][3] = 1.0f; + locator_m[0][1] = locator_m[0][2] = locator_m[0][3] = 0.0f; + locator_m[1][0] = locator_m[1][2] = locator_m[1][3] = 0.0f; + locator_m[2][0] = locator_m[2][1] = locator_m[2][3] = 0.0f; + locator_m[3][0] *= -1.0f; + locator_m[3][1] *= -1.0f; + locator_m[3][2] *= -1.0f; + + locator_m = local_rotation.transpose() * locator_m; + //rotation component will be stored + locator_m.get(locator_mtx); + + //set only position + + Log("LOCATOR\n"); + for (long ry = 0; ry < 4; ry++) + { + for (long rx = 0; rx < 4; rx++) + Log("%f, ", locator_mtx[ry][rx]); + Log("\n"); + } + Log("\n"); + + + for (; nummat > 0; nummat--) + material[nummat - 1].MO = 0; + + mJointsList.clear(); + Traverse(object_path); + + //------------------------------------------------------------------------------ + rexp->WriteFile(); + + STARTUPINFOA si; + memset(&si, 0, sizeof si); + si.cb = sizeof si; + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof pi); + + + BOOL created = false; + DWORD err; + if (ExportCharacterPatch) + { + char cd[_MAX_PATH]; + MakePathForTraceMaker(cd); + + auto arg = std::string(cd) + " " + gm_path; + created = CreateProcessA(cd, arg.data(), 0, 0, FALSE, /*CREATE_NEW_CONSOLE*/ + DETACHED_PROCESS | NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi); + err = GetLastError(); + } + delete rexp; + //------------------------------------------------------------------------------ + +#ifdef LOG + fclose(LogFile); +#endif + } + } + //fclose(trace); + MGlobal::executeCommand("deleteUI -window StatusWin;"); +} diff --git a/tools/maya-plugin/Geometry/AtlaExport.h b/tools/maya-plugin/Geometry/AtlaExport.h new file mode 100644 index 000000000..5725b3058 --- /dev/null +++ b/tools/maya-plugin/Geometry/AtlaExport.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../Export/rdf_exp.h" +#include "../Export/export.h" + +struct MATERIAL +{ + long ntex; + MObject* MO; + char matname[256]; + char texname[4][256]; + float offset[4][2], repeat[4][2]; + double rotate[4]; + + EXPORT_STATIC::BRDF_TYPE brdf; + float diffuse, specular, gloss, selfIllum, transparency, refraction_id, reflection; +}; + +class AtlaExport : public MPxFileTranslator +{ +public: + AtlaExport(); + ~AtlaExport(); + + MStatus writer(const MFileObject& file, const MString& optionsString, FileAccessMode mode) override; + bool haveWriteMethod() const override; + MString defaultExtension() const override; + MFileKind identifyFile(const MFileObject&, const char* buffer, short size) const override; + static void* creator(); +private: + void ExportAll(const std::string& file_name, bool bsp); + void Traverse(MDagPath& path); + void ExportLocator(MDagPath& cl); + size_t CountObjects(const MDagPath& path); + + std::vector locators_; + bool GlobAnimation; + long nummat; + MATERIAL material[1024]; + long matref[1024]; + + long curobject, total_objects; + + bool is_scaled_; +}; diff --git a/tools/maya-plugin/Geometry/Geometry.vcxproj b/tools/maya-plugin/Geometry/Geometry.vcxproj new file mode 100644 index 000000000..e319162d0 --- /dev/null +++ b/tools/maya-plugin/Geometry/Geometry.vcxproj @@ -0,0 +1,531 @@ + + + + + Maya2020 Debug + Win32 + + + Maya2020 Debug + x64 + + + Maya2020 Release + Win32 + + + Maya2020 Release + x64 + + + Maya5.0 Debug + Win32 + + + Maya5.0 Debug + x64 + + + Maya5.0 Release + Win32 + + + Maya5.0 Release + x64 + + + Maya8.5 Debug + Win32 + + + Maya8.5 Debug + x64 + + + Maya8.5 Release + Win32 + + + Maya8.5 Release + x64 + + + + + + + + + + + {b2a3b561-1b1c-4025-8a77-522fcb52e08a} + + + + 16.0 + Win32Proj + {49bd758c-e622-4b62-9de0-c26881d5fdb5} + Geometry + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya50x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya50x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + true + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + true + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + false + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya50x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya50x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + false + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + false + .mll + SD2GeoExport + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(PlatformShortName)\$(Configuration)\ + ..\Common;$(Maya85x86)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(Maya85x86)\lib;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) + + + true + .mll + SD2GeoExport + ..\Common;$(Maya50x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya50x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + true + .mll + SD2GeoExport + ..\Common;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + true + .mll + SD2GeoExport + ..\Common;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + false + .mll + SD2GeoExport + ..\Common;$(Maya50x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya50x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + false + .mll + SD2GeoExport + ..\Common;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + false + .mll + SD2GeoExport + ..\Common;$(Maya85x64)\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); + $(SolutionDir)$(PlatformShortName)\$(Configuration)\ + $(Maya85x64)\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) + $(PlatformShortName)\$(Configuration)\ + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;_DEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NOMINMAX;_BOOL;REQUIRE_IOSTREAM;_CRT_SECURE_NO_WARNINGS;NDEBUG;GEOMETRY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpplatest + + + Windows + true + true + true + false + OpenMaya.lib;OpenMayaAnim.lib;Image.lib;Foundation.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/tools/maya-plugin/Geometry/Geometry.vcxproj.filters b/tools/maya-plugin/Geometry/Geometry.vcxproj.filters new file mode 100644 index 000000000..2ae009375 --- /dev/null +++ b/tools/maya-plugin/Geometry/Geometry.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + + + Файлы заголовков + + + \ No newline at end of file diff --git a/tools/maya-plugin/MayaPlug.sln b/tools/maya-plugin/MayaPlug.sln new file mode 100644 index 000000000..937bca086 --- /dev/null +++ b/tools/maya-plugin/MayaPlug.sln @@ -0,0 +1,107 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31702.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Export", "Export\Export.vcxproj", "{B2A3B561-1B1C-4025-8A77-522FCB52E08A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Geometry", "Geometry\Geometry.vcxproj", "{49BD758C-E622-4B62-9DE0-C26881D5FDB5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Animation", "Animation\Animation.vcxproj", "{8620B892-DE9C-40C0-9200-6F64B45C599E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Maya2020 Debug|x64 = Maya2020 Debug|x64 + Maya2020 Debug|x86 = Maya2020 Debug|x86 + Maya2020 Release|x64 = Maya2020 Release|x64 + Maya2020 Release|x86 = Maya2020 Release|x86 + Maya5.0 Debug|x64 = Maya5.0 Debug|x64 + Maya5.0 Debug|x86 = Maya5.0 Debug|x86 + Maya5.0 Release|x64 = Maya5.0 Release|x64 + Maya5.0 Release|x86 = Maya5.0 Release|x86 + Maya8.5 Debug|x64 = Maya8.5 Debug|x64 + Maya8.5 Debug|x86 = Maya8.5 Debug|x86 + Maya8.5 Release|x64 = Maya8.5 Release|x64 + Maya8.5 Release|x86 = Maya8.5 Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Debug|x64.ActiveCfg = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Debug|x64.Build.0 = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Debug|x86.ActiveCfg = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Debug|x86.Build.0 = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Release|x64.ActiveCfg = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Release|x64.Build.0 = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Release|x86.ActiveCfg = Release|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya2020 Release|x86.Build.0 = Release|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Debug|x64.ActiveCfg = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Debug|x64.Build.0 = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Debug|x86.ActiveCfg = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Debug|x86.Build.0 = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Release|x64.ActiveCfg = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Release|x64.Build.0 = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Release|x86.ActiveCfg = Release|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya5.0 Release|x86.Build.0 = Release|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Debug|x64.ActiveCfg = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Debug|x64.Build.0 = Debug|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Debug|x86.ActiveCfg = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Debug|x86.Build.0 = Debug|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Release|x64.ActiveCfg = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Release|x64.Build.0 = Release|x64 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Release|x86.ActiveCfg = Release|Win32 + {B2A3B561-1B1C-4025-8A77-522FCB52E08A}.Maya8.5 Release|x86.Build.0 = Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Debug|x64.ActiveCfg = Maya2020 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Debug|x64.Build.0 = Maya2020 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Debug|x86.ActiveCfg = Maya2020 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Debug|x86.Build.0 = Maya2020 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Release|x64.ActiveCfg = Maya2020 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Release|x64.Build.0 = Maya2020 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Release|x86.ActiveCfg = Maya2020 Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya2020 Release|x86.Build.0 = Maya2020 Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Debug|x64.ActiveCfg = Maya5.0 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Debug|x64.Build.0 = Maya5.0 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Debug|x86.ActiveCfg = Maya5.0 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Debug|x86.Build.0 = Maya5.0 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Release|x64.ActiveCfg = Maya5.0 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Release|x64.Build.0 = Maya5.0 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Release|x86.ActiveCfg = Maya5.0 Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya5.0 Release|x86.Build.0 = Maya5.0 Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Debug|x64.ActiveCfg = Maya8.5 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Debug|x64.Build.0 = Maya8.5 Debug|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Debug|x86.ActiveCfg = Maya8.5 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Debug|x86.Build.0 = Maya8.5 Debug|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Release|x64.ActiveCfg = Maya8.5 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Release|x64.Build.0 = Maya8.5 Release|x64 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Release|x86.ActiveCfg = Maya8.5 Release|Win32 + {49BD758C-E622-4B62-9DE0-C26881D5FDB5}.Maya8.5 Release|x86.Build.0 = Maya8.5 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Debug|x64.ActiveCfg = Maya2020 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Debug|x64.Build.0 = Maya2020 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Debug|x86.ActiveCfg = Maya2020 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Debug|x86.Build.0 = Maya2020 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Release|x64.ActiveCfg = Maya2020 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Release|x64.Build.0 = Maya2020 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Release|x86.ActiveCfg = Maya2020 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya2020 Release|x86.Build.0 = Maya2020 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Debug|x64.ActiveCfg = Maya5.0 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Debug|x64.Build.0 = Maya5.0 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Debug|x86.ActiveCfg = Maya5.0 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Debug|x86.Build.0 = Maya5.0 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Release|x64.ActiveCfg = Maya5.0 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Release|x64.Build.0 = Maya5.0 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Release|x86.ActiveCfg = Maya5.0 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya5.0 Release|x86.Build.0 = Maya5.0 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Debug|x64.ActiveCfg = Maya8.5 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Debug|x64.Build.0 = Maya8.5 Debug|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Debug|x86.ActiveCfg = Maya8.5 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Debug|x86.Build.0 = Maya8.5 Debug|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Release|x64.ActiveCfg = Maya8.5 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Release|x64.Build.0 = Maya8.5 Release|x64 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Release|x86.ActiveCfg = Maya8.5 Release|Win32 + {8620B892-DE9C-40C0-9200-6F64B45C599E}.Maya8.5 Release|x86.Build.0 = Maya8.5 Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B87FEFFB-91E2-4AF7-9CA2-1679895B65D2} + EndGlobalSection +EndGlobal diff --git a/tools/maya-plugin/README.md b/tools/maya-plugin/README.md new file mode 100644 index 000000000..eb1387a4b --- /dev/null +++ b/tools/maya-plugin/README.md @@ -0,0 +1,17 @@ +# Build instructions +1. Get Maya 5.0, 8.5 or 2020. This is required because the installation contains necessary library and include files. You can probably get them somewhere else, but building was tested only on live Maya installations. +2. Set an environment variable depending on your Maya installation. Variable name is the concatenation of Maya version (Maya50, Maya85, Maya2020) and target platform (x86, x64), e.g. Maya85x64. Variable value is the path to the Maya installation (or a folder that contains include and lib folders with Maya SDK). +3. Select the appropriate configuration and target platform that match your Maya installation. +4. Build the solution. + +# Usage +1. Copy the two resulting .mll files to your ``Maya installation/bin/plug-ins`` folder. +2. Copy the .mel files to ``Maya installation/scripts/others`` folder. +3. Enable the plugins from Maya. + +# Acknowledgements +1. Nick Chirkov, the author of the plugin. + +# Changes to original plugin +1. Adapted for newer Maya versions. +2. 0.01 scale checkbox for geometry export made functional. \ No newline at end of file diff --git a/tools/maya-plugin/mel/SD2AniExportMel.mel b/tools/maya-plugin/mel/SD2AniExportMel.mel new file mode 100644 index 000000000..9dead3b30 --- /dev/null +++ b/tools/maya-plugin/mel/SD2AniExportMel.mel @@ -0,0 +1,67 @@ +global proc int SD2AniExportMel ( string $parent, string $action, string $initialSettings, string $resultCallback ) +{ + int $intVal; + float $floatVal; + int $bResult; + string $currentOptions; + string $optionList[]; + string $optionBreakDown[]; + string $strVal; + + int $index; + + if ($action == "post") + { + setParent $parent; + setUITemplate -pushTemplate DefaultTemplate; + + //---------- FORM -------------// + formLayout optionsBoxForm; + columnLayout -adj true; + columnLayout -adj true ; + checkBox -v true -l "0.01 Scale (cm->m)" -al "left" Check1; + + checkBox -l "animation" -al "left" Check3; + checkBox -l "Build BSP" -al "left" Check2; + radioButtonGrp -l "Method:" -nrb 2 -la2 "Draft" "Product" + -cw3 80 50 80 radioGrp1; + radioButtonGrp -e -sl 1 radioGrp1; + + setParent ..; // columnLayout + setParent ..; // columnLayout + + // --------------------------------------------------- + // Set to current settings. + // --------------------------------------------------- + + $currentOptions = $initialSettings; + if (size($currentOptions) > 0) + { + + } + $result = 1; + + + formLayout -e -vis true optionsBoxForm; + setUITemplate -popTemplate; + } + // --------------------------------------------------- + // Set option string + // --------------------------------------------------- + else if ($action == "query") + { + if(`checkBox -q -v Check1`==1) $currentOptions =$currentOptions +"Check1=1;"; + if(`checkBox -q -v Check2`==1) $currentOptions =$currentOptions +"Check2=1;"; + if(`checkBox -q -v Check3`==1) $currentOptions =$currentOptions +"Check3=1;"; + + $intVal = `radioButtonGrp -q -sl radioGrp1`; + if($intVal==1) $currentOptions =$currentOptions +"radioGrp1=1;"; + if($intVal==2) $currentOptions =$currentOptions +"radioGrp1=2;"; + } + + //-------------------------------------------// + eval($resultCallback+" \""+$currentOptions+"\""); + $result = 1; + + return $bResult; +} diff --git a/tools/maya-plugin/mel/SD2GeoExportMel.mel b/tools/maya-plugin/mel/SD2GeoExportMel.mel new file mode 100644 index 000000000..c9f3b7d16 --- /dev/null +++ b/tools/maya-plugin/mel/SD2GeoExportMel.mel @@ -0,0 +1,69 @@ +global proc int SD2GeoExportMel ( string $parent, string $action, string $initialSettings, string $resultCallback ) +{ + int $intVal; + float $floatVal; + int $bResult; + string $currentOptions; + string $optionList[]; + string $optionBreakDown[]; + string $strVal; + + int $index; + + if ($action == "post") + { + setParent $parent; + setUITemplate -pushTemplate DefaultTemplate; + + //---------- FORM -------------// + formLayout optionsBoxForm; + columnLayout -adj true; + columnLayout -adj true ; + checkBox -v true -l "0.01 Scale (cm->m)" -al "left" Check1; + + checkBox -l "ExportCharacterPatch" -al "left" ExportCharacterPatch; + checkBox -l "animation" -al "left" Check3; + checkBox -l "Build BSP" -al "left" Check2; + radioButtonGrp -l "Method:" -nrb 2 -la2 "Draft" "Product" + -cw3 80 50 80 radioGrp1; + radioButtonGrp -e -sl 1 radioGrp1; + + setParent ..; // columnLayout + setParent ..; // columnLayout + + // --------------------------------------------------- + // Set to current settings. + // --------------------------------------------------- + + $currentOptions = $initialSettings; + if (size($currentOptions) > 0) + { + + } + $result = 1; + + + formLayout -e -vis true optionsBoxForm; + setUITemplate -popTemplate; + } + // --------------------------------------------------- + // Set option string + // --------------------------------------------------- + else if ($action == "query") + { + if(`checkBox -q -v Check1`==1) $currentOptions =$currentOptions +"Check1=1;"; + if(`checkBox -q -v Check2`==1) $currentOptions =$currentOptions +"Check2=1;"; + if(`checkBox -q -v Check3`==1) $currentOptions =$currentOptions +"Check3=1;"; + if(`checkBox -q -v ExportCharacterPatch`==1) $currentOptions =$currentOptions +"ExportCharacterPatch=1;"; + + $intVal = `radioButtonGrp -q -sl radioGrp1`; + if($intVal==1) $currentOptions =$currentOptions +"radioGrp1=1;"; + if($intVal==2) $currentOptions =$currentOptions +"radioGrp1=2;"; + } + + //-------------------------------------------// + eval($resultCallback+" \""+$currentOptions+"\""); + $result = 1; + + return $bResult; +}