summaryrefslogtreecommitdiff
path: root/groupexplode/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'groupexplode/main.cpp')
-rw-r--r--groupexplode/main.cpp230
1 files changed, 226 insertions, 4 deletions
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);