diff options
Diffstat (limited to 'groupexplode/main.cpp')
-rw-r--r-- | groupexplode/main.cpp | 230 |
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); |