diff --git a/DSMeshConvert/DSMeshConvert.vcxproj b/DSMeshConvert/DSMeshConvert.vcxproj
index d8993b8..5c52abd 100644
--- a/DSMeshConvert/DSMeshConvert.vcxproj
+++ b/DSMeshConvert/DSMeshConvert.vcxproj
@@ -59,7 +59,7 @@
EditAndContinue
- assimp.lib;%(AdditionalDependencies)
+ assimp.lib;%(AdditionalDependencies);OpenGL32.lib;glu32.lib
assimp--1.1.700-sdk\lib\assimp_debug-dll_win32;%(AdditionalLibraryDirectories)
true
MachineX86
@@ -86,6 +86,7 @@
+
@@ -95,9 +96,11 @@
+
+
@@ -106,6 +109,7 @@
+
diff --git a/DSMeshConvert/DSMeshConvert.vcxproj.filters b/DSMeshConvert/DSMeshConvert.vcxproj.filters
index 003e1ea..a001a47 100644
--- a/DSMeshConvert/DSMeshConvert.vcxproj.filters
+++ b/DSMeshConvert/DSMeshConvert.vcxproj.filters
@@ -38,6 +38,8 @@
+
+
@@ -66,5 +68,7 @@
+
+
\ No newline at end of file
diff --git a/DSMeshConvert/List.h b/DSMeshConvert/List.h
new file mode 100644
index 0000000..1f8e0c3
--- /dev/null
+++ b/DSMeshConvert/List.h
@@ -0,0 +1,491 @@
+/******************************************************************************
+*
+* List.h
+*
+*
+* By Patrick Wyatt - 5/16/2010
+*
+***/
+
+
+/******************************************************************************
+*
+* WHAT IT IS
+*
+* This module defines a linked-list implementation that uses "embedded"
+* links rather than separately allocated link-nodes as does STL and
+* more or less all other linked-list implementations.
+*
+* Why is this cool:
+* 1. No additional memory allocations (malloc) required to link
+* an object into a linked list.
+* 2. Not necessary to traverse an additional pointer references
+* to get to the object being dereferenced.
+* 3. Probably most importantly, when objects get deleted, they
+* automatically unlink themselves from the lists they're
+* linked to, eliminating many common types of bugs.
+*
+* HOW TO USE IT
+*
+* Declare a structure that will be contained in one or more linked lists:
+* class CFoo {
+* LIST_LINK(CFoo) m_linkByData;
+* LIST_LINK(CFoo) m_linkByType;
+* int m_data;
+* int m_type;
+* ...
+* };
+*
+* Declare list variables:
+* LIST_DECLARE(CFoo, m_linkByData) listByData;
+* LIST_DECLARE(CFoo, m_linkByType) listByType;
+* LIST_PTR(CFoo) m_listPtr = foo ? &listByData : &listByType;
+*
+* Operations on links:
+* T * Prev ();
+* T * Next ();
+* void Unlink ();
+* bool IsLinked () const;
+*
+* Operations on lists:
+* bool Empty () const;
+* void UnlinkAll ();
+* void DeleteAll ();
+*
+* T * Head ();
+* T * Tail ();
+* T * Prev (T * node);
+* T * Next (T * node);
+*
+* void InsertHead (T * node);
+* void InsertTail (T * node);
+* void InsertBefore (T * node, T * before);
+* void InsertAfter (T * node, T * after);
+*
+* NOTES
+*
+* Limitations:
+* All nodes must be allocated on (at least) two-byte boundaries
+* because the low bit is used as a sentinel to signal end-of-list.
+*
+* Thanks to:
+* Something like this code was originally implemented by Mike
+* O'Brien in storm.dll for Diablo in 1995, and again at ArenaNet
+* for Guild Wars.
+*
+***/
+
+
+#ifdef LIST_H
+#error "Header included more than once"
+#endif
+#define LIST_H
+
+
+/******************************************************************************
+*
+* List definition macros
+*
+***/
+
+// Define a linked list:
+// T = type of object being linked
+// link = member within object which is the link field
+#define LIST_DECLARE(T, link) TListDeclare
+
+// Define a field within a structure that will be used to link it into a list
+#define LIST_LINK(T) TLink
+
+// Define a pointer to a list
+#define LIST_PTR(T) TList *
+
+
+/******************************************************************************
+*
+* TLink
+*
+***/
+
+//=============================================================================
+template
+class TLink {
+public:
+ ~TLink ();
+ TLink ();
+
+ bool IsLinked () const;
+ void Unlink ();
+
+ T * Prev ();
+ T * Next ();
+ const T * Prev () const;
+ const T * Next () const;
+
+ // For use by list-type classes, not user code;
+ // the alternative is to friend TList, THash,
+ // and (eventually) many other structures.
+ TLink (size_t offset);
+ void SetOffset (size_t offset);
+ TLink * NextLink ();
+ TLink * PrevLink ();
+ void InsertBefore (T * node, TLink * nextLink);
+ void InsertAfter (T * node, TLink * prevLink);
+
+private:
+ T * m_nextNode; // pointer to the next >object<
+ TLink * m_prevLink; // pointer to the previous >link field<
+ void RemoveFromList ();
+
+ // Hide copy-constructor and assignment operator
+ TLink (const TLink &);
+ TLink & operator= (const TLink &);
+};
+
+//=============================================================================
+template
+TLink::~TLink () {
+ RemoveFromList();
+}
+
+//=============================================================================
+template
+TLink::TLink () {
+ // Mark this node as the end of the list, with no link offset
+ m_nextNode = (T *) ((size_t) this + 1 - 0);
+ m_prevLink = this;
+}
+
+//=============================================================================
+template
+TLink::TLink (size_t offset) {
+ // Mark this node as the end of the list, with the link offset set
+ m_nextNode = (T *) ((size_t) this + 1 - offset);
+ m_prevLink = this;
+}
+
+//=============================================================================
+template
+void TLink::SetOffset (size_t offset) {
+ // Mark this node as the end of the list, with the link offset set
+ m_nextNode = (T *) ((size_t) this + 1 - offset);
+ m_prevLink = this;
+}
+
+//=============================================================================
+template
+TLink * TLink::NextLink () {
+ // Calculate the offset from a node pointer to a link structure
+ size_t offset = (size_t) this - ((size_t) m_prevLink->m_nextNode & ~1);
+
+ // Get the link field for the next node
+ return (TLink *) (((size_t) m_nextNode & ~1) + offset);
+}
+
+//=============================================================================
+template
+void TLink::RemoveFromList () {
+ NextLink()->m_prevLink = m_prevLink;
+ m_prevLink->m_nextNode = m_nextNode;
+}
+
+//=============================================================================
+template
+void TLink::InsertBefore (T * node, TLink * nextLink) {
+ RemoveFromList();
+
+ m_prevLink = nextLink->m_prevLink;
+ m_nextNode = m_prevLink->m_nextNode;
+
+ nextLink->m_prevLink->m_nextNode = node;
+ nextLink->m_prevLink = this;
+}
+
+//=============================================================================
+template
+void TLink::InsertAfter (T * node, TLink * prevLink) {
+ RemoveFromList();
+
+ m_prevLink = prevLink;
+ m_nextNode = prevLink->m_nextNode;
+
+ prevLink->NextLink()->m_prevLink = this;
+ prevLink->m_nextNode = node;
+}
+
+//=============================================================================
+template
+bool TLink::IsLinked () const {
+ return m_prevLink != this;
+}
+
+//=============================================================================
+template
+void TLink::Unlink () {
+ RemoveFromList();
+
+ // Mark this node as the end of the list with no link offset
+ m_nextNode = (T *) ((size_t) this + 1);
+ m_prevLink = this;
+}
+
+//=============================================================================
+template
+TLink * TLink::PrevLink () {
+ return m_prevLink;
+}
+
+//=============================================================================
+template
+T * TLink::Prev () {
+ T * prevNode = m_prevLink->m_prevLink->m_nextNode;
+ if ((size_t) prevNode & 1)
+ return NULL;
+ return prevNode;
+}
+
+//=============================================================================
+template
+const T * TLink::Prev () const {
+ const T * prevNode = m_prevLink->m_prevLink->m_nextNode;
+ if ((size_t) prevNode & 1)
+ return NULL;
+ return prevNode;
+}
+
+//=============================================================================
+template
+T * TLink::Next () {
+ if ((size_t) m_nextNode & 1)
+ return NULL;
+ return m_nextNode;
+}
+
+//=============================================================================
+template
+const T * TLink::Next () const {
+ if ((size_t) m_nextNode & 1)
+ return NULL;
+ return m_nextNode;
+}
+
+
+/******************************************************************************
+*
+* TList
+*
+***/
+
+//=============================================================================
+template
+class TList {
+public:
+ ~TList ();
+ TList ();
+
+ bool Empty () const;
+ void UnlinkAll ();
+ void DeleteAll ();
+
+ T * Head ();
+ T * Tail ();
+ const T * Head () const;
+ const T * Tail () const;
+
+ T * Prev (T * node);
+ T * Next (T * node);
+ const T * Prev (const T * node) const;
+ const T * Next (const T * node) const;
+
+ void InsertHead (T * node);
+ void InsertTail (T * node);
+ void InsertBefore (T * node, T * before);
+ void InsertAfter (T * node, T * after);
+
+private:
+ TLink m_link;
+ size_t m_offset;
+
+ TList (size_t offset);
+ TLink * GetLinkFromNode (const T * node) const;
+ template friend class TListDeclare;
+
+ // Hide copy-constructor and assignment operator
+ TList (const TList &);
+ TList & operator= (const TList &);
+};
+
+//=============================================================================
+template
+TList::~TList () {
+ UnlinkAll();
+}
+
+//=============================================================================
+template
+TList::TList () :
+ m_link(),
+ m_offset((size_t) -1)
+{}
+
+//=============================================================================
+template
+TList::TList (size_t offset) :
+ m_link(offset),
+ m_offset(offset)
+{}
+
+//=============================================================================
+template
+bool TList::Empty () const {
+ return m_link.Next() == NULL;
+}
+
+//=============================================================================
+template
+void TList::UnlinkAll () {
+ for (;;) {
+ TLink * link = m_link.PrevLink();
+ if (link == &m_link)
+ break;
+ link->Unlink();
+ }
+}
+
+//=============================================================================
+template
+void TList::DeleteAll () {
+ while (T * node = m_link.Next())
+ delete node;
+}
+
+//=============================================================================
+template
+T * TList::Head () {
+ return m_link.Next();
+}
+
+//=============================================================================
+template
+T * TList::Tail () {
+ return m_link.Prev();
+}
+
+//=============================================================================
+template
+const T * TList::Head () const {
+ return m_link.Next();
+}
+
+//=============================================================================
+template
+const T * TList::Tail () const {
+ return m_link.Prev();
+}
+
+//=============================================================================
+template
+T * TList::Prev (T * node) {
+ return GetLinkFromNode(node)->Prev();
+}
+
+//=============================================================================
+template
+const T * TList::Prev (const T * node) const {
+ return GetLinkFromNode(node)->Prev();
+}
+
+//=============================================================================
+template
+T * TList::Next (T * node) {
+ return GetLinkFromNode(node)->Next();
+}
+
+//=============================================================================
+template
+const T * TList::Next (const T * node) const {
+ return GetLinkFromNode(node)->Next();
+}
+
+//=============================================================================
+template
+void TList::InsertHead (T * node) {
+ InsertAfter(node, NULL);
+}
+
+//=============================================================================
+template
+void TList::InsertTail (T * node) {
+ InsertBefore(node, NULL);
+}
+
+//=============================================================================
+template
+void TList::InsertBefore (T * node, T * before) {
+ assert(!((size_t) node & 1));
+ assert(!GetLinkFromNode(node)->IsLinked());
+ GetLinkFromNode(node)->InsertBefore(
+ node,
+ before ? GetLinkFromNode(before) : &m_link
+ );
+}
+
+//=============================================================================
+template
+void TList::InsertAfter (T * node, T * after) {
+ assert(!((size_t) node & 1));
+ assert(!GetLinkFromNode(node)->IsLinked());
+ GetLinkFromNode(node)->InsertAfter(
+ node,
+ after ? GetLinkFromNode(after) : &m_link
+ );
+}
+
+//=============================================================================
+template
+TLink * TList::GetLinkFromNode (const T * node) const {
+ assert(m_offset != (size_t) -1);
+ return (TLink *) ((size_t) node + m_offset);
+}
+
+/******************************************************************************
+*
+* TListDeclare - declare a list with a known link offset
+*
+***/
+
+//=============================================================================
+template
+class TListDeclare : public TList {
+public:
+ TListDeclare ();
+};
+
+//=============================================================================
+template
+TListDeclare::TListDeclare () : TList(offset)
+{}
+
+
+//===================================
+// MIT License
+//
+// Copyright (c) 2010 by Patrick Wyatt
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//===================================
\ No newline at end of file
diff --git a/DSMeshConvert/main.cpp b/DSMeshConvert/main.cpp
index f21ab1e..1e886a8 100644
--- a/DSMeshConvert/main.cpp
+++ b/DSMeshConvert/main.cpp
@@ -14,7 +14,8 @@
//#define NVTRISTRIP // buggy?!!
//#define CETS_PTERDIMAN // http://www.codercorner.com/Strips.htm // memory corruption...
-#define ACTC // http://plunk.org/~grantham/public/actc/
+//#define ACTC // http://plunk.org/~grantham/public/actc/
+#define MULTIPATH // "Multi-Path Algorithm for Triangle Strips" implementation
#include "NvTriStrip.h"
#include "cets-pterdiman/Striper.h"
#include "ac/tc.h"
@@ -22,6 +23,11 @@
#include "stripping.h"
#include "types.h"
+#include
+
+#include "List.h"
+
+#include "opengl.h"
struct Box
{
@@ -76,6 +82,8 @@ void PushValue(std::vector& list, u32& cmdOffset, u32& cmdIndex, u32 cmd, u
}
}
+void MultiPathStripper(const std::vector& indices, std::vector& stripLengths, std::vector& stripIndices);
+
int Convert(const char* input, const char* output)
{
#ifdef NVTRISTRIP
@@ -141,6 +149,8 @@ int Convert(const char* input, const char* output)
return 3;
}
+ InitOpenGL();
+
//std::vector indices;
//for ( u32 i = 0 ; i < mesh->mNumFaces ; i++ )
//{
@@ -229,6 +239,29 @@ int Convert(const char* input, const char* output)
stripLengths.push_back(len);
}
actcEndOutput(tc);
+#endif
+#ifdef MULTIPATH
+ std::vector indices;
+ u32 nbIndices = mesh->mNumFaces * 3;
+ indices.reserve(nbIndices);
+ for ( u32 i = 0 ; i < nbIndices / 3 ; i++ )
+ {
+ indices.push_back(mesh->mFaces[i].mIndices[0]);
+ indices.push_back(mesh->mFaces[i].mIndices[1]);
+ indices.push_back(mesh->mFaces[i].mIndices[2]);
+ }
+ u32 nbStrips = 0;
+ std::vector stripLengths;
+ std::vector stripIndices;
+ extern float* vertices;
+ vertices = new float[mesh->mNumVertices * 3];
+ for ( u32 i = 0 ; i < mesh->mNumVertices ; i++ )
+ {
+ vertices[i * 3 + 0] = mesh->mVertices[i].x;
+ vertices[i * 3 + 1] = mesh->mVertices[i].y;
+ vertices[i * 3 + 2] = mesh->mVertices[i].z;
+ }
+ MultiPathStripper(indices, stripLengths, stripIndices);
#endif
printf("%d strips generated for %d triangles\n", nbStrips, mesh->mNumFaces);
@@ -304,6 +337,10 @@ int Convert(const char* input, const char* output)
PushValue(list, command, cmdindex, 0x40, 2); // begin triangle strip
//printf("begin strip\n");
#endif
+#ifdef MULTIPATH
+ u32 idxLen = stripLengths[i];
+ PushValue(list, command, cmdindex, 0x40, 2); // start strip
+#endif
for ( u32 j = idxLen ; j > 0 ; j--, idx++ )
{
diff --git a/DSMeshConvert/multipath.cpp b/DSMeshConvert/multipath.cpp
new file mode 100644
index 0000000..c791e0d
--- /dev/null
+++ b/DSMeshConvert/multipath.cpp
@@ -0,0 +1,662 @@
+#include "types.h"
+#include
+#include
+#include