Rearrange source filenames.

Remove tri2quad temporarily.
master
Jeremy Hu 2016-12-30 20:32:34 +09:30
parent e9e9a170e3
commit 3ca8e64b68
10 changed files with 137 additions and 452 deletions

View File

@ -16,8 +16,8 @@ SOURCES += main.cpp \
bmesh.c \ bmesh.c \
matrix.c \ matrix.c \
convexhull.c \ convexhull.c \
tri2quad.c \ hashtable.c \
hashtable.c osutil.cpp
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
render.h \ render.h \
@ -27,5 +27,6 @@ HEADERS += mainwindow.h \
bmesh.h \ bmesh.h \
matrix.h \ matrix.h \
convexhull.h \ convexhull.h \
tri2quad.h \ hashtable.h \
hashtable.h 3dstruct.h \
osutil.h

21
src/3dstruct.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _3DSTRUCT_H
#define _3DSTRUCT_H
#include "vector3d.h"
typedef struct {
vec3 pt[3];
} triangle;
typedef struct {
vec3 pt[4];
} quad;
typedef struct face3 {
int indices[3];
} face3;
typedef struct face4 {
int indices[4];
} face4;
#endif

View File

@ -8,7 +8,6 @@
#include "array.h" #include "array.h"
#include "matrix.h" #include "matrix.h"
#include "convexhull.h" #include "convexhull.h"
#include "tri2quad.h"
#include "draw.h" #include "draw.h"
#define BMESH_STEP_DISTANCE 0.4 #define BMESH_STEP_DISTANCE 0.4
@ -556,6 +555,10 @@ static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
} }
} }
#include "osutil.h"
static int showFaceIndex = 0;
static long long lastShowFaceIndexIncTime = 0;
static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) { static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
int result = 0; int result = 0;
bmeshBallIterator iterator; bmeshBallIterator iterator;
@ -566,7 +569,6 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
} }
ball->roundColor = bm->roundColor; ball->roundColor = bm->roundColor;
if (BMESH_BALL_TYPE_ROOT == ball->type && 4 == ball->index) { if (BMESH_BALL_TYPE_ROOT == ball->type && 4 == ball->index) {
tri2QuadContext *t2q;
convexHull *hull; convexHull *hull;
bmeshBall *outmostBall = 0; bmeshBall *outmostBall = 0;
int outmostBallFirstVertexIndex = 0; int outmostBallFirstVertexIndex = 0;
@ -575,12 +577,6 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__); fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
return -1; return -1;
} }
t2q = tri2QuadContextCreate();
if (!t2q) {
fprintf(stderr, "%s:tri2QuadContextCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return -1;
}
glColor3f(0.0, 0.0, 0.0); glColor3f(0.0, 0.0, 0.0);
drawDebugPrintf("root <%f,%f,%f>", ball->position.x, drawDebugPrintf("root <%f,%f,%f>", ball->position.x,
ball->position.y, ball->position.z); ball->position.y, ball->position.z);
@ -600,48 +596,54 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
} }
convexHullGenerate(hull); convexHullGenerate(hull);
convexHullUnifyNormals(hull, &ball->position); convexHullUnifyNormals(hull, &ball->position);
{
int triIndex;
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull);
++triIndex) {
triangle *tri = (triangle *)convexHullGetTriangle(hull, triIndex);
tri2QuadAddTriangle(t2q, tri);
}
}
tri2QuadConvert(t2q);
glPushMatrix(); glPushMatrix();
/* if (lastShowFaceIndexIncTime + 300 < osGetMilliseconds()) {
if (showFaceIndex > convexHullGetFace3Num(hull)) {
showFaceIndex = 0;
} else {
showFaceIndex++;
}
lastShowFaceIndexIncTime = osGetMilliseconds();
}
glColor3f(1.0f, 1.0f, 1.0f); glColor3f(1.0f, 1.0f, 1.0f);
{ {
int triIndex; int triIndex;
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull); for (triIndex = 0; triIndex < convexHullGetFace3Num(hull);
++triIndex) { ++triIndex) {
triangle *tri = (triangle *)convexHullGetTriangle(hull, triIndex); triangle tri;
//if (triIndex > displayTriangleFaceIndex) { face3 *face = (face3 *)convexHullGetFace3(hull, triIndex);
// continue; tri.pt[0] = *convexHullGetVertex(hull, face->indices[0]);
//} tri.pt[1] = *convexHullGetVertex(hull, face->indices[1]);
drawTriangle(tri); tri.pt[2] = *convexHullGetVertex(hull, face->indices[2]);
if (triIndex > showFaceIndex) {
break;
}
drawTriangle(&tri);
} }
} }
glColor3f(0.0f, 0.0f, 0.0f); glColor3f(0.0f, 0.0f, 0.0f);
{ {
int triIndex; int triIndex;
int j; int j;
glColor3f(1.0f, 1.0f, 1.0f); for (triIndex = 0; triIndex < convexHullGetFace3Num(hull);
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull);
++triIndex) { ++triIndex) {
triangle *tri = (triangle *)convexHullGetTriangle(hull, triIndex); triangle tri;
face3 *face = (face3 *)convexHullGetFace3(hull, triIndex);
tri.pt[0] = *convexHullGetVertex(hull, face->indices[0]);
tri.pt[1] = *convexHullGetVertex(hull, face->indices[1]);
tri.pt[2] = *convexHullGetVertex(hull, face->indices[2]);
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for (j = 0; j < 3; ++j) { for (j = 0; j < 3; ++j) {
glVertex3f(tri->pt[j].x, tri->pt[j].y, tri->pt[j].z); glVertex3f(tri.pt[j].x, tri.pt[j].y, tri.pt[j].z);
} }
glVertex3f(tri->pt[0].x, tri->pt[0].y, tri->pt[0].z); glVertex3f(tri.pt[0].x, tri.pt[0].y, tri.pt[0].z);
glEnd(); glEnd();
} }
} }
*/
/*
glColor3f(1.0f, 1.0f, 1.0f); glColor3f(1.0f, 1.0f, 1.0f);
{ {
int triIndex; int triIndex;
@ -698,11 +700,10 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
glVertex3f(q->pt[0].x, q->pt[0].y, q->pt[0].z); glVertex3f(q->pt[0].x, q->pt[0].y, q->pt[0].z);
glEnd(); glEnd();
} }
} }*/
glPopMatrix(); glPopMatrix();
convexHullDestroy(hull); convexHullDestroy(hull);
tri2QuadContextDestroy(t2q);
} }
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;

View File

@ -4,7 +4,6 @@
#include "convexhull.h" #include "convexhull.h"
#include "array.h" #include "array.h"
#include "hashtable.h" #include "hashtable.h"
#include "draw.h"
// //
// Implement Gift wrapping method which describled in http://dccg.upc.edu/people/vera/wp-content/uploads/2014/11/GA2014-ConvexHulls3D-Roger-Hernando.pdf // Implement Gift wrapping method which describled in http://dccg.upc.edu/people/vera/wp-content/uploads/2014/11/GA2014-ConvexHulls3D-Roger-Hernando.pdf
@ -18,19 +17,14 @@ typedef struct {
int orderOnPlane; int orderOnPlane;
} converHullVertex; } converHullVertex;
typedef struct face {
int indices[3];
} face;
struct convexHull { struct convexHull {
array *vertexArray; array *vertexArray;
array *todoArray; array *todoArray;
array *faceArray; array *face3Array;
int nextTodoIndex; int nextTodoIndex;
unsigned int *openEdgeExistMap; unsigned int *openEdgeExistMap;
hashtable *faceHashtable; hashtable *face3Hashtable;
face findFace; face3 findFace3;
triangle returnTriangle;
}; };
typedef struct { typedef struct {
@ -39,28 +33,33 @@ typedef struct {
int thirdVertex; int thirdVertex;
} todo; } todo;
face *convexHullGetFaceByHashtableParam(convexHull *hull, static int cantorPair(int k1, int k2) {
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
}
face3 *convexHullGetFaceByHashtableParam(convexHull *hull,
const void *param) { const void *param) {
int index = (char *)param - (char *)0; int index = (char *)param - (char *)0;
if (0 == index) { if (0 == index) {
return &hull->findFace; return &hull->findFace3;
} }
return (face *)arrayGetItem(hull->faceArray, index - 1); return (face3 *)arrayGetItem(hull->face3Array, index - 1);
} }
static int faceHash(void *userData, const void *node) { static int faceHash(void *userData, const void *node) {
face *triIdx = convexHullGetFaceByHashtableParam( face3 *triIdx = convexHullGetFaceByHashtableParam(
(convexHull *)userData, node); (convexHull *)userData, node);
return triIdx->indices[0] * triIdx->indices[1] * triIdx->indices[2]; return cantorPair(cantorPair(triIdx->indices[0], triIdx->indices[1]),
triIdx->indices[2]);
} }
static int faceCompare(void *userData, const void *node1, static int faceCompare(void *userData, const void *node1,
const void *node2) { const void *node2) {
face *triIdx1 = convexHullGetFaceByHashtableParam( face3 *triIdx1 = convexHullGetFaceByHashtableParam(
(convexHull *)userData, node1); (convexHull *)userData, node1);
face *triIdx2 = convexHullGetFaceByHashtableParam( face3 *triIdx2 = convexHullGetFaceByHashtableParam(
(convexHull *)userData, node2); (convexHull *)userData, node2);
return memcmp(triIdx1, triIdx2, sizeof(face)); return memcmp(triIdx1, triIdx2, sizeof(face3));
} }
convexHull *convexHullCreate(void) { convexHull *convexHullCreate(void) {
@ -81,15 +80,15 @@ convexHull *convexHullCreate(void) {
convexHullDestroy(hull); convexHullDestroy(hull);
return 0; return 0;
} }
hull->faceArray = arrayCreate(sizeof(face)); hull->face3Array = arrayCreate(sizeof(face3));
if (!hull->faceArray) { if (!hull->face3Array) {
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__); fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull); convexHullDestroy(hull);
return 0; return 0;
} }
hull->faceHashtable = hashtableCreate(TRIANGLE_INDEX_HASHTABLE_SIZE, hull->face3Hashtable = hashtableCreate(TRIANGLE_INDEX_HASHTABLE_SIZE,
faceHash, faceCompare, hull); faceHash, faceCompare, hull);
if (!hull->faceHashtable) { if (!hull->face3Hashtable) {
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__); fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull); convexHullDestroy(hull);
return 0; return 0;
@ -163,9 +162,9 @@ static int sortface(const void *first, const void *second) {
return *firstIndex - *secondIndex; return *firstIndex - *secondIndex;
} }
int convexHullAddFace(convexHull *hull, int firstVertex, int secondVertex, int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
int thirdVertex) { int thirdVertex) {
face *tri; face3 *tri;
converHullVertex *vtx1; converHullVertex *vtx1;
converHullVertex *vtx2; converHullVertex *vtx2;
converHullVertex *vtx3; converHullVertex *vtx3;
@ -191,21 +190,21 @@ int convexHullAddFace(convexHull *hull, int firstVertex, int secondVertex,
return 0; return 0;
} }
} }
memset(&hull->findFace, 0, sizeof(hull->findFace)); memset(&hull->findFace3, 0, sizeof(hull->findFace3));
hull->findFace.indices[0] = firstVertex; hull->findFace3.indices[0] = firstVertex;
hull->findFace.indices[1] = secondVertex; hull->findFace3.indices[1] = secondVertex;
hull->findFace.indices[2] = thirdVertex; hull->findFace3.indices[2] = thirdVertex;
if (0 == hashtableGet(hull->faceHashtable, 0)) { qsort(hull->findFace3.indices, 3,
qsort(hull->findFace.indices, 3, sizeof(hull->findFace3.indices[0]), sortface);
sizeof(hull->findFace.indices[0]), sortface); if (0 == hashtableGet(hull->face3Hashtable, 0)) {
newTri = arrayGetLength(hull->faceArray); newTri = arrayGetLength(hull->face3Array);
if (0 != arraySetLength(hull->faceArray, newTri + 1)) { if (0 != arraySetLength(hull->face3Array, newTri + 1)) {
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1; return -1;
} }
tri = (face *)arrayGetItem(hull->faceArray, newTri); tri = (face3 *)arrayGetItem(hull->face3Array, newTri);
*tri = hull->findFace; *tri = hull->findFace3;
if (0 != hashtableInsert(hull->faceHashtable, if (0 != hashtableInsert(hull->face3Hashtable,
(char *)0 + newTri + 1)) { (char *)0 + newTri + 1)) {
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__); fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
return -1; return -1;
@ -222,8 +221,8 @@ static void convexHullReleaseForGenerate(convexHull *hull) {
void convexHullDestroy(convexHull *hull) { void convexHullDestroy(convexHull *hull) {
arrayDestroy(hull->vertexArray); arrayDestroy(hull->vertexArray);
arrayDestroy(hull->todoArray); arrayDestroy(hull->todoArray);
arrayDestroy(hull->faceArray); arrayDestroy(hull->face3Array);
hashtableDestroy(hull->faceHashtable); hashtableDestroy(hull->face3Hashtable);
convexHullReleaseForGenerate(hull); convexHullReleaseForGenerate(hull);
free(hull); free(hull);
} }
@ -290,7 +289,8 @@ int convexHullGenerate(convexHull *hull) {
todo *t = (todo *)arrayGetItem(hull->todoArray, hull->nextTodoIndex++); todo *t = (todo *)arrayGetItem(hull->todoArray, hull->nextTodoIndex++);
index1 = t->firstVertex; index1 = t->firstVertex;
index2 = t->secondVertex; index2 = t->secondVertex;
if (convexHullEdgeExsits(hull, index1, index2)) { if (convexHullEdgeExsits(hull, index1, index2) ||
convexHullEdgeExsits(hull, index2, index1)) {
continue; continue;
} }
convexHullMarkEdgeAsExsits(hull, index1, index2); convexHullMarkEdgeAsExsits(hull, index1, index2);
@ -298,8 +298,7 @@ int convexHullGenerate(convexHull *hull) {
if (-1 == index3) { if (-1 == index3) {
continue; continue;
} }
convexHullAddFace(hull, index1, index2, index3); convexHullAddFace3(hull, index1, index2, index3);
convexHullAddTodo(hull, index1, index2, index3);
convexHullAddTodo(hull, index2, index3, index1); convexHullAddTodo(hull, index2, index3, index1);
convexHullAddTodo(hull, index3, index1, index2); convexHullAddTodo(hull, index3, index1, index2);
} }
@ -308,9 +307,9 @@ int convexHullGenerate(convexHull *hull) {
int convexHullUnifyNormals(convexHull *hull, vec3 *origin) { int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
int i; int i;
for (i = 0; i < arrayGetLength(hull->faceArray); ++i) { for (i = 0; i < arrayGetLength(hull->face3Array); ++i) {
face *triIdx = (face *)arrayGetItem( face3 *triIdx = (face3 *)arrayGetItem(
hull->faceArray, i); hull->face3Array, i);
converHullVertex *p1 = (converHullVertex *)arrayGetItem( converHullVertex *p1 = (converHullVertex *)arrayGetItem(
hull->vertexArray, triIdx->indices[0]); hull->vertexArray, triIdx->indices[0]);
converHullVertex *p2 = (converHullVertex *)arrayGetItem( converHullVertex *p2 = (converHullVertex *)arrayGetItem(
@ -330,19 +329,16 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
return 0; return 0;
} }
int convexHullGetTriangleNum(convexHull *hull) { face3 *convexHullGetFace3(convexHull *hull, int faceIndex) {
return arrayGetLength(hull->faceArray); return (face3 *)arrayGetItem(hull->face3Array, faceIndex);
} }
triangle *convexHullGetTriangle(convexHull *hull, int index) { vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex) {
int i; converHullVertex *vertex = (converHullVertex *)arrayGetItem(
face *triIdx = (face *)arrayGetItem( hull->vertexArray, vertexIndex);
hull->faceArray, index); return &vertex->pt;
memset(&hull->returnTriangle, 0, sizeof(hull->returnTriangle)); }
for (i = 0; i < 3; ++i) {
converHullVertex *vertex = (converHullVertex *)arrayGetItem( int convexHullGetFace3Num(convexHull *hull) {
hull->vertexArray, triIdx->indices[i]); return arrayGetLength(hull->face3Array);
hull->returnTriangle.pt[i] = vertex->pt;
}
return &hull->returnTriangle;
} }

View File

@ -1,7 +1,6 @@
#ifndef CONVEX_HULL_H #ifndef CONVEX_HULL_H
#define CONVEX_HULL_H #define CONVEX_HULL_H
#include "vector3d.h" #include "3dstruct.h"
#include "draw.h"
typedef struct convexHull convexHull; typedef struct convexHull convexHull;
convexHull *convexHullCreate(void); convexHull *convexHullCreate(void);
@ -10,8 +9,9 @@ int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
void convexHullDestroy(convexHull *hull); void convexHullDestroy(convexHull *hull);
int convexHullGenerate(convexHull *hull); int convexHullGenerate(convexHull *hull);
int convexHullUnifyNormals(convexHull *hull, vec3 *origin); int convexHullUnifyNormals(convexHull *hull, vec3 *origin);
int convexHullGetTriangleNum(convexHull *hull); int convexHullGetFace3Num(convexHull *hull);
triangle *convexHullGetTriangle(convexHull *hull, int index); face3 *convexHullGetFace3(convexHull *hull, int faceIndex);
vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex);
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3); int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
#endif #endif

View File

@ -1,6 +1,6 @@
#ifndef DRAW_SPHERE_H #ifndef DRAW_SPHERE_H
#define DRAW_SPHERE_H #define DRAW_SPHERE_H
#include "vector3d.h" #include "3dstruct.h"
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenGL/glu.h> #include <OpenGL/glu.h>
#else #else
@ -11,19 +11,6 @@
extern "C" { extern "C" {
#endif #endif
typedef struct {
vec3 pt[3];
} triangle;
typedef struct {
vec3 pt[4];
} quad;
typedef struct {
int npoly;
triangle *poly;
} object;
int drawInit(void); int drawInit(void);
int drawSphere(vec3 *origin, float radius, int slices, int stacks); int drawSphere(vec3 *origin, float radius, int slices, int stacks);
void drawTriangle(triangle *poly); void drawTriangle(triangle *poly);

6
src/osutil.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "osutil.h"
#include <QDateTime>
long long osGetMilliseconds(void) {
return (long long)QDateTime::currentMSecsSinceEpoch();
}

14
src/osutil.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef OS_UTIL_H
#define OS_UTIL_H
#ifdef __cplusplus
extern "C" {
#endif
long long osGetMilliseconds(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,324 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "tri2quad.h"
#include "vector3d.h"
#include "array.h"
#include "hashtable.h"
#define EDGE_HASHTABLE_SIZE 100
typedef struct edge {
vec3 p1;
vec3 p2;
int inputA;
int inputB;
int score;
} edge;
typedef struct inputTriangle {
triangle tri;
float area;
vec3 normal;
int merged;
} inputTriangle;
struct tri2QuadContext {
array *inputArray;
array *triangleArray;
array *quadArray;
array *edgeArray;
hashtable *edgeHashtable;
edge findEdge;
};
static edge *tri2QuadGetEdgeByHashtableParam(tri2QuadContext *ctx,
const void *param) {
int edgeIndex = (char *)param - (char *)0;
if (0 == edgeIndex) {
return &ctx->findEdge;
}
return (edge *)arrayGetItem(ctx->edgeArray, edgeIndex - 1);
}
static int edgeHash(void *userData, const void *node) {
edge *e = tri2QuadGetEdgeByHashtableParam((tri2QuadContext *)userData, node);
return (int)(e->p1.x + 1) * (e->p1.y + 1) * (e->p1.z + 1) *
(e->p2.x + 1) * (e->p2.y + 1) * (e->p2.z + 1);
}
static int edgeCompare(void *userData, const void *node1, const void *node2) {
const edge *e1 = (const edge *)tri2QuadGetEdgeByHashtableParam(
(tri2QuadContext *)userData, node1);
const edge *e2 = (const edge *)tri2QuadGetEdgeByHashtableParam(
(tri2QuadContext *)userData, node2);
if ((0 == memcmp(&e1->p1, &e2->p1, sizeof(e1->p1)) &&
0 == memcmp(&e1->p2, &e2->p2, sizeof(e1->p1))) ||
(0 == memcmp(&e1->p1, &e2->p2, sizeof(e1->p1)) &&
0 == memcmp(&e1->p2, &e2->p1, sizeof(e1->p1)))) {
return 0;
}
return -1;
}
tri2QuadContext *tri2QuadContextCreate(void) {
tri2QuadContext *ctx = (tri2QuadContext *)calloc(1, sizeof(tri2QuadContext));
if (!ctx) {
fprintf(stderr, "%s:Insufficient memory.", __FUNCTION__);
return 0;
}
ctx->inputArray = arrayCreate(sizeof(inputTriangle));
if (!ctx->inputArray) {
fprintf(stderr, "%s:arrayCreate failed.", __FUNCTION__);
tri2QuadContextDestroy(ctx);
return 0;
}
ctx->triangleArray = arrayCreate(sizeof(triangle));
if (!ctx->triangleArray) {
fprintf(stderr, "%s:arrayCreate failed.", __FUNCTION__);
tri2QuadContextDestroy(ctx);
return 0;
}
ctx->quadArray = arrayCreate(sizeof(quad));
if (!ctx->quadArray) {
fprintf(stderr, "%s:arrayCreate failed.", __FUNCTION__);
tri2QuadContextDestroy(ctx);
return 0;
}
ctx->edgeHashtable = hashtableCreate(EDGE_HASHTABLE_SIZE, edgeHash,
edgeCompare, ctx);
if (!ctx->edgeHashtable) {
fprintf(stderr, "%s:hashtableCreate failed.", __FUNCTION__);
tri2QuadContextDestroy(ctx);
return 0;
}
ctx->edgeArray = arrayCreate(sizeof(edge));
if (!ctx->edgeArray) {
fprintf(stderr, "%s:arrayCreate failed.", __FUNCTION__);
tri2QuadContextDestroy(ctx);
return 0;
}
return ctx;
}
int tri2QuadAddTriangle(tri2QuadContext *ctx, triangle *tri) {
int newInputIndex;
inputTriangle *newInput;
newInputIndex = arrayGetLength(ctx->inputArray);
if (0 != arraySetLength(ctx->inputArray, newInputIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed.", __FUNCTION__);
return -1;
}
newInput = (inputTriangle *)arrayGetItem(ctx->inputArray, newInputIndex);
newInput->merged = 0;
newInput->tri = *tri;
newInput->area = vec3TriangleArea(&tri->pt[0], &tri->pt[1], &tri->pt[2]);
vec3Normal(&tri->pt[0], &tri->pt[1], &tri->pt[2], &newInput->normal);
return newInputIndex;
}
static edge *tri2QuadFindEdge(tri2QuadContext *ctx,
vec3 *p1, vec3 *p2) {
int edgeIndex;
ctx->findEdge.p1 = *p1;
ctx->findEdge.p2 = *p2;
edgeIndex = (char *)hashtableGet(ctx->edgeHashtable, (char *)0) - (char *)0;
if (0 == edgeIndex) {
return 0;
}
return (edge *)arrayGetItem(ctx->edgeArray, edgeIndex - 1);
}
static int tri2QuadAddInitialEdge(tri2QuadContext *ctx,
vec3 *p1, vec3 *p2, int inputIndex) {
edge *existedEdge = tri2QuadFindEdge(ctx, p1, p2);
if (!existedEdge) {
edge *newEdge;
int newEdgeIndex = arrayGetLength(ctx->edgeArray);
if (0 != arraySetLength(ctx->edgeArray, newEdgeIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed(newEdgeIndex:%d).",
__FUNCTION__, newEdgeIndex);
return -1;
}
newEdge = (edge *)arrayGetItem(ctx->edgeArray, newEdgeIndex);
newEdge->p1 = *p1;
newEdge->p2 = *p2;
if (0 != hashtableInsert(ctx->edgeHashtable,
(char *)0 + newEdgeIndex + 1)) {
fprintf(stderr, "%s:hashtableInsert failed.", __FUNCTION__);
return -1;
}
newEdge->inputA = inputIndex;
newEdge->inputB = -1;
newEdge->score = 0;
} else {
existedEdge->inputB = inputIndex;
}
return 0;
}
static int tri2QuadAddOutputQuad(tri2QuadContext *ctx, vec3 *first,
vec3 *second, vec3 *third, vec3 *fourth) {
quad *q;
int newQuadIndex = arrayGetLength(ctx->quadArray);
if (0 != arraySetLength(ctx->quadArray, newQuadIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed(newQuadIndex:%d).", __FUNCTION__,
newQuadIndex);
return -1;
}
q = (quad *)arrayGetItem(ctx->quadArray, newQuadIndex);
memset(q, 0, sizeof(quad));
q->pt[0] = *first;
q->pt[1] = *second;
q->pt[2] = *third;
q->pt[3] = *fourth;
return newQuadIndex;
}
static int tri2QuadAddOutputTriangle(tri2QuadContext *ctx, vec3 *first,
vec3 *second, vec3 *third) {
triangle *tri;
int newTriangleIndex = arrayGetLength(ctx->triangleArray);
if (0 != arraySetLength(ctx->triangleArray, newTriangleIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed(newTriangleIndex:%d).",
__FUNCTION__, newTriangleIndex);
return -1;
}
tri = (triangle *)arrayGetItem(ctx->triangleArray, newTriangleIndex);
memset(tri, 0, sizeof(triangle));
tri->pt[0] = *first;
tri->pt[1] = *second;
tri->pt[2] = *third;
return newTriangleIndex;
}
static int tri2QuadAddOutputQuadByEdgeAndInput(tri2QuadContext *ctx, edge *e,
inputTriangle *input1, inputTriangle *input2) {
vec3 outputPt[4];
int i;
int nextSaveToIndex;
memset(outputPt, 0, sizeof(outputPt));
nextSaveToIndex = 0;
for (i = 0; i < 3; ++i) {
vec3 *pt = &input1->tri.pt[i];
if (0 == memcmp(&e->p1, pt, sizeof(e->p1))) {
outputPt[nextSaveToIndex] = *pt;
nextSaveToIndex += 2;
} else if (0 == memcmp(&e->p2, pt, sizeof(e->p2))) {
outputPt[nextSaveToIndex] = *pt;
nextSaveToIndex += 2;
} else {
outputPt[1] = *pt;
}
}
for (i = 0; i < 3; ++i) {
vec3 *pt = &input2->tri.pt[i];
if (0 != memcmp(&e->p1, pt, sizeof(e->p1)) &&
0 != memcmp(&e->p2, pt, sizeof(e->p2))) {
outputPt[3] = *pt;
break;
}
}
return tri2QuadAddOutputQuad(ctx, &outputPt[0], &outputPt[1],
&outputPt[2], &outputPt[3]);
}
static int sortEdgeByScoreDesc(const void *first, const void *second) {
const edge *e1 = (const edge *)first;
const edge *e2 = (const edge *)second;
return e2->score - e1->score;
}
int tri2QuadConvert(tri2QuadContext *ctx) {
int inputIndex;
int edgeIndex;
for (inputIndex = 0; inputIndex < arrayGetLength(ctx->inputArray);
++inputIndex) {
inputTriangle *inputItem = (inputTriangle *)arrayGetItem(ctx->inputArray,
inputIndex);
tri2QuadAddInitialEdge(ctx, &inputItem->tri.pt[0], &inputItem->tri.pt[1],
inputIndex);
tri2QuadAddInitialEdge(ctx, &inputItem->tri.pt[1], &inputItem->tri.pt[2],
inputIndex);
tri2QuadAddInitialEdge(ctx, &inputItem->tri.pt[2], &inputItem->tri.pt[0],
inputIndex);
}
for (edgeIndex = 0; edgeIndex < arrayGetLength(ctx->edgeArray); ++edgeIndex) {
edge *e = (edge *)arrayGetItem(ctx->edgeArray, edgeIndex);
inputTriangle *input1;
inputTriangle *input2;
if (-1 != e->inputA && -1 != e->inputB) {
input1 = (inputTriangle *)arrayGetItem(ctx->inputArray,
e->inputA);
input2 = (inputTriangle *)arrayGetItem(ctx->inputArray,
e->inputB);
e->score = (int)((input1->area + input2->area) *
vec3DotProduct(&input1->normal, &input2->normal) * 100);
}
}
qsort(arrayGetItem(ctx->edgeArray, 0), arrayGetLength(ctx->edgeArray),
sizeof(edge), sortEdgeByScoreDesc);
//
// After qsort, the edge indices inside the hashtable are no longer right.
//
hashtableDestroy(ctx->edgeHashtable);
ctx->edgeHashtable = 0;
for (edgeIndex = 0; edgeIndex < arrayGetLength(ctx->edgeArray); ++edgeIndex) {
edge *e = (edge *)arrayGetItem(ctx->edgeArray, edgeIndex);
inputTriangle *input1;
inputTriangle *input2;
if (-1 != e->inputA && -1 != e->inputB) {
input1 = (inputTriangle *)arrayGetItem(ctx->inputArray,
e->inputA);
input2 = (inputTriangle *)arrayGetItem(ctx->inputArray,
e->inputB);
if (!input1->merged && !input2->merged) {
//input1->merged = 1;
//input2->merged = 1;
//tri2QuadAddOutputQuadByEdgeAndInput(ctx, e, input1, input2);
}
}
}
for (inputIndex = 0; inputIndex < arrayGetLength(ctx->inputArray);
++inputIndex) {
inputTriangle *inputItem = (inputTriangle *)arrayGetItem(ctx->inputArray,
inputIndex);
if (!inputItem->merged) {
tri2QuadAddOutputTriangle(ctx, &inputItem->tri.pt[0],
&inputItem->tri.pt[1], &inputItem->tri.pt[2]);
}
}
return 0;
}
int tri2QuadGetTriangleNum(tri2QuadContext *ctx) {
return arrayGetLength(ctx->triangleArray);
}
triangle *tri2QuadGetTriangle(tri2QuadContext *ctx, int index) {
return (triangle *)arrayGetItem(ctx->triangleArray, index);
}
int tri2QuadGetQuadNum(tri2QuadContext *ctx) {
return arrayGetLength(ctx->quadArray);
}
quad *tri2QuadGetQuad(tri2QuadContext *ctx, int index) {
return (quad *)arrayGetItem(ctx->quadArray, index);
}
void tri2QuadContextDestroy(tri2QuadContext *ctx) {
arrayDestroy(ctx->inputArray);
arrayDestroy(ctx->triangleArray);
arrayDestroy(ctx->quadArray);
hashtableDestroy(ctx->edgeHashtable);
arrayDestroy(ctx->edgeArray);
free(ctx);
}

View File

@ -1,17 +0,0 @@
#ifndef TRI2QUAD_H
#define TRI2QUAD_H
#include "draw.h"
typedef struct tri2QuadContext tri2QuadContext;
tri2QuadContext *tri2QuadContextCreate(void);
int tri2QuadAddTriangle(tri2QuadContext *ctx, triangle *tri);
int tri2QuadConvert(tri2QuadContext *ctx);
int tri2QuadGetTriangleNum(tri2QuadContext *ctx);
triangle *tri2QuadGetTriangle(tri2QuadContext *ctx, int index);
int tri2QuadGetQuadNum(tri2QuadContext *ctx);
quad *tri2QuadGetQuad(tri2QuadContext *ctx, int index);
void tri2QuadContextDestroy(tri2QuadContext *ctx);
#endif