diff options
Diffstat (limited to 'groupexplode')
| -rw-r--r-- | groupexplode/config.cpp | 7 | ||||
| -rw-r--r-- | groupexplode/config.h | 4 | ||||
| -rw-r--r-- | groupexplode/dialog.cpp | 5 | ||||
| -rw-r--r-- | groupexplode/dialog.h | 1 | ||||
| -rw-r--r-- | groupexplode/main.cpp | 230 | ||||
| -rw-r--r-- | groupexplode/resource.h | 1 | ||||
| -rw-r--r-- | groupexplode/resource.rc | 9 | 
7 files changed, 249 insertions, 8 deletions
| diff --git a/groupexplode/config.cpp b/groupexplode/config.cpp index 59f87f0..740fd9d 100644 --- a/groupexplode/config.cpp +++ b/groupexplode/config.cpp @@ -27,6 +27,7 @@  bool		Config::m_init=false;  bool		Config::m_rmOrig=false; +bool		Config::m_collate=false;  void Config::Load()  { @@ -35,12 +36,14 @@ void Config::Load()      	m_init=true;  	m_rmOrig=false; +	m_collate=true;  #if REGISTRY_USAGE!=0  	W32DLib::Registry r(HKEY_CURRENT_USER,KEY);  	r.Read("RemoveOriginal",m_rmOrig); +	r.Read("Collate",m_collate);  #endif @@ -54,9 +57,13 @@ void Config::Save()      W32DLib::Registry r(HKEY_CURRENT_USER,KEY,REGISTRY_USAGE==2);      r.Write("RemoveOriginal",m_rmOrig); +    r.Write("Collate",m_collate);  #endif  }  bool Config::RemoveOriginal()			{return m_rmOrig;}  void Config::RemoveOriginal(bool flag)		{m_rmOrig=flag;} + +bool Config::Collate()				{return m_collate;} +void Config::Collate(bool flag)			{m_collate=flag;} diff --git a/groupexplode/config.h b/groupexplode/config.h index 8d00356..302e2fb 100644 --- a/groupexplode/config.h +++ b/groupexplode/config.h @@ -36,12 +36,16 @@ public:  	static bool		RemoveOriginal();  	static void		RemoveOriginal(bool flag); +	static bool		Collate(); +	static void		Collate(bool flag); +  private:  	Config();  	static bool		m_init;  	static bool		m_rmOrig; +	static bool		m_collate;  };  #endif // CONFIG_H diff --git a/groupexplode/dialog.cpp b/groupexplode/dialog.cpp index 6816de9..c8d30f7 100644 --- a/groupexplode/dialog.cpp +++ b/groupexplode/dialog.cpp @@ -33,6 +33,7 @@ Dialog::Dialog(const StringList& groups)  			    : m_ok(this,IDC_OKBUT,0)  			    , m_cancel(this,IDC_CANCELBUT,0)  			    , m_rmOrig(this,IDC_RMORIG,0) +			    , m_collate(this,IDC_COLLATE,0)  			    , m_groups(this,IDC_GROUP,0)  			    , m_sel(-1)  			    , m_groupList(groups) @@ -67,6 +68,7 @@ void Dialog::OnInit()      m_groups.SelectedIndex(0); +    m_collate.SetState(Config::Collate());      m_rmOrig.SetState(Config::RemoveOriginal());  } @@ -82,7 +84,10 @@ int Dialog::GetSelectedGroup()  BOOL Dialog::OnOK(UINT msg, WPARAM wp, LPARAM lp)   { +    Config::Collate(m_collate.GetState());      Config::RemoveOriginal(m_rmOrig.GetState()); +    Config::Save(); +      m_sel=m_groups.SelectedIndex();      Close(IDOK); diff --git a/groupexplode/dialog.h b/groupexplode/dialog.h index f68efa5..4620eec 100644 --- a/groupexplode/dialog.h +++ b/groupexplode/dialog.h @@ -43,6 +43,7 @@ private:      W32DLib::Button	m_ok;      W32DLib::Button	m_cancel;      W32DLib::AutoCheck	m_rmOrig; +    W32DLib::AutoCheck	m_collate;      W32DLib::ComboBox	m_groups;      int			m_sel;      const StringList&	m_groupList; diff --git a/groupexplode/main.cpp b/groupexplode/main.cpp index dbee433..2979b7b 100644 --- a/groupexplode/main.cpp +++ b/groupexplode/main.cpp @@ -20,10 +20,229 @@  //  static const char rcs_id[]="$Id$"; +#include <algorithm> +#include <cstdio> +#include <cstring> +#include <stdarg.h> +  #include "mingwms.h"  #include "msLib.h"  #include "dialog.h" +#include "config.h" + + +// ---------------------------------------------------------------------- +// TYPES +// +typedef std::vector<int>	IntList; +typedef std::vector<IntList>	TriangleList; + +class IndexMap : public std::map<int,int> +{ +public: +	IndexMap() : std::map<int,int> () {} + +	bool Has(int key) +	{ +	    return find(key)!=end(); +	} +}; + + +// ---------------------------------------------------------------------- +// UTILS +// +static bool VecMatch(const msVec3 v1, const msVec3 v2) +{ +    for(int f=0;f<3;f++) +    { +    	if (v1[f]!=v2[f]) +	{ +	    return false; +	} +    } + +    return true; +} + + +static void CopyVec3(msVec3 to, const msVec3 from) +{ +    for(int f=0;f<3;f++) +    { +    	to[f]=from[f]; +    } +} + + +static bool VertexNormalsMatch(msMesh *m, int t1, int t2) +{ +    msVec3 v1; +    msVec3 v2; + +    for(int f=0;f<3;f++) +    { +	msMesh_GetVertexNormalAt(m,(m->pTriangles+t1)->nNormalIndices[f],v1); +	msMesh_GetVertexNormalAt(m,(m->pTriangles+t2)->nNormalIndices[f],v2); + +	if (!VecMatch(v1,v2)) +	{ +	    return false; +	} +    } + +    return true; +} + + +static void SetName(char *name, const char *base, int num) +{ +    int len=std::min(static_cast<int>(std::strlen(base)),MS_MAX_NAME-10); + +    std::sprintf(name,"%*.*s_%d",len,len,base,num); +} + + +static void DEBUG(const char *fmt, ...) +{ +    static char buff[4096]; + +    va_list va; +    va_start(va,fmt); +    std::vsprintf(buff,fmt,va); +    va_end(va); + +    W32DLib::Common::Message(0,"DEBUG",buff); +} + + +// ---------------------------------------------------------------------- +// GROUP SPLITTER -- This is *very* ugly code, so look away if you're of +//		     a nervous disposition. +// +static void SplitGroup(msModel *model, int group) +{ +    TriangleList list; +    msMesh *orig_mesh=msModel_GetMeshAt(model,group); +    int num=orig_mesh->nNumTriangles; +    bool *used=new bool[num]; +    std::string name=orig_mesh->szName; + +    for(int f=0;f<num;f++) +    { +    	used[f]=false; +    } + +    for(int f=0;f<num;f++) +    { +    	if (!used[f]) +	{ +	    IntList sublist; + +	    sublist.push_back(f); +	    used[f]=true; + +	    if (Config::Collate()) +	    { +	    	for(int i=0;i<num;i++) +		{ +		    if (!used[i] && VertexNormalsMatch(orig_mesh,f,i)) +		    { +		    	sublist.push_back(i); +			used[i]=true; +		    } +		} +	    } + +	    list.push_back(sublist); +	} +    } + +    delete[] used; + +    TriangleList::const_iterator i; +    IntList::const_iterator j; + +    num=1; + +    for(i=list.begin();i!=list.end();++i) +    { +	IndexMap vmap; +	IndexMap nmap; + +	msMesh *mesh=msModel_GetMeshAt(model,msModel_AddMesh(model)); + +	SetName(mesh->szName,name.c_str(),num++); + +	mesh->nMaterialIndex=orig_mesh->nMaterialIndex; + +    	for(j=i->begin();j!=i->end();++j) +	{ +	    msTriangle *old_tri=msMesh_GetTriangleAt(orig_mesh,*j); +	    msTriangle *new_tri=msMesh_GetTriangleAt +	    				(mesh,msMesh_AddTriangle(mesh)); + +	    CopyVec3(new_tri->Normal,old_tri->Normal); +	    new_tri->nFlags=old_tri->nFlags; + +	    for(int f=0;f<3;f++) +	    { +		int old_vi=old_tri->nVertexIndices[f]; +		int new_vi; +		int old_ni=old_tri->nNormalIndices[f]; +		int new_ni; + +		if (vmap.Has(old_vi)) +		{ +		    new_vi=vmap[old_vi]; +		} +		else +		{ +		    new_vi=msMesh_AddVertex(mesh); +		    vmap[old_vi]=new_vi; +		} + +		if (nmap.Has(old_ni)) +		{ +		    new_ni=nmap[old_ni]; +		} +		else +		{ +		    new_ni=msMesh_AddVertexNormal(mesh); +		    nmap[old_ni]=new_ni; +		} + +	    	msVertex *old_ver=msMesh_GetVertexAt(orig_mesh,old_vi); +	    	msVertex *new_ver=msMesh_GetVertexAt(mesh,new_vi); + +		*new_ver=*old_ver; + +		msVec3 normal; + +		msMesh_GetVertexNormalAt(orig_mesh,old_ni,normal); +		msMesh_SetVertexNormalAt(mesh,new_ni,normal); + +		new_tri->nVertexIndices[f]=new_vi; +		new_tri->nNormalIndices[f]=new_ni; +	    } +	} +    } + +    if (Config::RemoveOriginal()) +    { +    	msMesh_Destroy(orig_mesh); + +	for(int f=group;f<model->nNumMeshes-1;f++) +	{ +	    model->pMeshes[f]=model->pMeshes[f+1]; +	} + +	model->nNumMeshes--; +	model->nNumAllocedMeshes--; +    } +} +  // ----------------------------------------------------------------------  // MINGW WRAPPER FUNCTIONS @@ -38,8 +257,6 @@ static int Execute(msModel* model)      W32DLib::Common::Initialise();      W32DLib::Common::MessageTitle("Group Exploder"); -    // Unfortunately this is the best you can hope for with Milkshape... -    //      HWND parent=GetForegroundWindow();      if (!model) @@ -67,12 +284,17 @@ static int Execute(msModel* model)      if (dlg.ShowModal(W32DLib::Common::GetInstance(),parent)==IDOK)      { -    	int sel=dlg.GetSelectedGroup(); +        SetCursor(LoadCursor(NULL,IDC_WAIT)); +	SplitGroup(model,dlg.GetSelectedGroup()); +	SetCursor(LoadCursor(NULL,IDC_ARROW)); + +	return MS_MODEL_CHANGED;      } -    return 1; +    return MS_MODEL_UNCHANGED;  } +  PLUGIN_SPEC void* CreatePlugIn()  {      return CreateMINGWPlugin(MS_TYPE_TOOL, GetTitle, Execute); diff --git a/groupexplode/resource.h b/groupexplode/resource.h index 1da17e5..445191d 100644 --- a/groupexplode/resource.h +++ b/groupexplode/resource.h @@ -28,3 +28,4 @@  #define IDC_CANCELBUT	4  #define IDC_GROUP	5  #define IDC_RMORIG	6 +#define IDC_COLLATE	7 diff --git a/groupexplode/resource.rc b/groupexplode/resource.rc index 31ddf19..470ba45 100644 --- a/groupexplode/resource.rc +++ b/groupexplode/resource.rc @@ -1,7 +1,7 @@  #include <windows.h>  #include "resource.h" -GR_DIALOG DIALOG  100, 100, 200, 85 +GR_DIALOG DIALOG  100, 100, 200, 105  		STYLE WS_POPUP | WS_BORDER  		CAPTION "Group Exploder"  		FONT 8,"MS Shell Dlg" @@ -10,8 +10,9 @@ GR_DIALOG DIALOG  100, 100, 200, 85      COMBOBOX IDC_GROUP, 10, 20, 180, 200, CBS_DROPDOWNLIST | WS_TABSTOP  -    AUTOCHECKBOX "Remove Original Group", IDC_RMORIG, 10,40,180,18 +    AUTOCHECKBOX "Remove original mesh", IDC_RMORIG, 10,40,180,18 +    AUTOCHECKBOX "Collate triangles with identical normals", IDC_COLLATE, 10,60,180,18 -    PUSHBUTTON "OK", IDC_OKBUT, 10,60,80,18 -    PUSHBUTTON "Cancel", IDC_CANCELBUT, 110,60,80,18 +    PUSHBUTTON "OK", IDC_OKBUT, 10,80,80,18 +    PUSHBUTTON "Cancel", IDC_CANCELBUT, 110,80,80,18  } | 
