parent
e9e9a170e3
commit
3ca8e64b68
|
@ -16,8 +16,8 @@ SOURCES += main.cpp \
|
|||
bmesh.c \
|
||||
matrix.c \
|
||||
convexhull.c \
|
||||
tri2quad.c \
|
||||
hashtable.c
|
||||
hashtable.c \
|
||||
osutil.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
render.h \
|
||||
|
@ -27,5 +27,6 @@ HEADERS += mainwindow.h \
|
|||
bmesh.h \
|
||||
matrix.h \
|
||||
convexhull.h \
|
||||
tri2quad.h \
|
||||
hashtable.h
|
||||
hashtable.h \
|
||||
3dstruct.h \
|
||||
osutil.h
|
|
@ -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
|
67
src/bmesh.c
67
src/bmesh.c
|
@ -8,7 +8,6 @@
|
|||
#include "array.h"
|
||||
#include "matrix.h"
|
||||
#include "convexhull.h"
|
||||
#include "tri2quad.h"
|
||||
#include "draw.h"
|
||||
|
||||
#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) {
|
||||
int result = 0;
|
||||
bmeshBallIterator iterator;
|
||||
|
@ -566,7 +569,6 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
|||
}
|
||||
ball->roundColor = bm->roundColor;
|
||||
if (BMESH_BALL_TYPE_ROOT == ball->type && 4 == ball->index) {
|
||||
tri2QuadContext *t2q;
|
||||
convexHull *hull;
|
||||
bmeshBall *outmostBall = 0;
|
||||
int outmostBallFirstVertexIndex = 0;
|
||||
|
@ -575,12 +577,6 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
|||
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
t2q = tri2QuadContextCreate();
|
||||
if (!t2q) {
|
||||
fprintf(stderr, "%s:tri2QuadContextCreate failed.\n", __FUNCTION__);
|
||||
convexHullDestroy(hull);
|
||||
return -1;
|
||||
}
|
||||
glColor3f(0.0, 0.0, 0.0);
|
||||
drawDebugPrintf("root <%f,%f,%f>", ball->position.x,
|
||||
ball->position.y, ball->position.z);
|
||||
|
@ -600,48 +596,54 @@ static int bmeshStichFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
|||
}
|
||||
convexHullGenerate(hull);
|
||||
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();
|
||||
|
||||
/*
|
||||
if (lastShowFaceIndexIncTime + 300 < osGetMilliseconds()) {
|
||||
if (showFaceIndex > convexHullGetFace3Num(hull)) {
|
||||
showFaceIndex = 0;
|
||||
} else {
|
||||
showFaceIndex++;
|
||||
}
|
||||
lastShowFaceIndexIncTime = osGetMilliseconds();
|
||||
}
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
{
|
||||
int triIndex;
|
||||
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull);
|
||||
for (triIndex = 0; triIndex < convexHullGetFace3Num(hull);
|
||||
++triIndex) {
|
||||
triangle *tri = (triangle *)convexHullGetTriangle(hull, triIndex);
|
||||
//if (triIndex > displayTriangleFaceIndex) {
|
||||
// continue;
|
||||
//}
|
||||
drawTriangle(tri);
|
||||
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]);
|
||||
if (triIndex > showFaceIndex) {
|
||||
break;
|
||||
}
|
||||
drawTriangle(&tri);
|
||||
}
|
||||
}
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
{
|
||||
int triIndex;
|
||||
int j;
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
for (triIndex = 0; triIndex < convexHullGetTriangleNum(hull);
|
||||
for (triIndex = 0; triIndex < convexHullGetFace3Num(hull);
|
||||
++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);
|
||||
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();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
{
|
||||
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);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
glPopMatrix();
|
||||
convexHullDestroy(hull);
|
||||
tri2QuadContextDestroy(t2q);
|
||||
}
|
||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||
child;
|
||||
|
|
104
src/convexhull.c
104
src/convexhull.c
|
@ -4,7 +4,6 @@
|
|||
#include "convexhull.h"
|
||||
#include "array.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
|
||||
|
@ -18,19 +17,14 @@ typedef struct {
|
|||
int orderOnPlane;
|
||||
} converHullVertex;
|
||||
|
||||
typedef struct face {
|
||||
int indices[3];
|
||||
} face;
|
||||
|
||||
struct convexHull {
|
||||
array *vertexArray;
|
||||
array *todoArray;
|
||||
array *faceArray;
|
||||
array *face3Array;
|
||||
int nextTodoIndex;
|
||||
unsigned int *openEdgeExistMap;
|
||||
hashtable *faceHashtable;
|
||||
face findFace;
|
||||
triangle returnTriangle;
|
||||
hashtable *face3Hashtable;
|
||||
face3 findFace3;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -39,28 +33,33 @@ typedef struct {
|
|||
int thirdVertex;
|
||||
} 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) {
|
||||
int index = (char *)param - (char *)0;
|
||||
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) {
|
||||
face *triIdx = convexHullGetFaceByHashtableParam(
|
||||
face3 *triIdx = convexHullGetFaceByHashtableParam(
|
||||
(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,
|
||||
const void *node2) {
|
||||
face *triIdx1 = convexHullGetFaceByHashtableParam(
|
||||
face3 *triIdx1 = convexHullGetFaceByHashtableParam(
|
||||
(convexHull *)userData, node1);
|
||||
face *triIdx2 = convexHullGetFaceByHashtableParam(
|
||||
face3 *triIdx2 = convexHullGetFaceByHashtableParam(
|
||||
(convexHull *)userData, node2);
|
||||
return memcmp(triIdx1, triIdx2, sizeof(face));
|
||||
return memcmp(triIdx1, triIdx2, sizeof(face3));
|
||||
}
|
||||
|
||||
convexHull *convexHullCreate(void) {
|
||||
|
@ -81,15 +80,15 @@ convexHull *convexHullCreate(void) {
|
|||
convexHullDestroy(hull);
|
||||
return 0;
|
||||
}
|
||||
hull->faceArray = arrayCreate(sizeof(face));
|
||||
if (!hull->faceArray) {
|
||||
hull->face3Array = arrayCreate(sizeof(face3));
|
||||
if (!hull->face3Array) {
|
||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
||||
convexHullDestroy(hull);
|
||||
return 0;
|
||||
}
|
||||
hull->faceHashtable = hashtableCreate(TRIANGLE_INDEX_HASHTABLE_SIZE,
|
||||
hull->face3Hashtable = hashtableCreate(TRIANGLE_INDEX_HASHTABLE_SIZE,
|
||||
faceHash, faceCompare, hull);
|
||||
if (!hull->faceHashtable) {
|
||||
if (!hull->face3Hashtable) {
|
||||
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
|
||||
convexHullDestroy(hull);
|
||||
return 0;
|
||||
|
@ -163,9 +162,9 @@ static int sortface(const void *first, const void *second) {
|
|||
return *firstIndex - *secondIndex;
|
||||
}
|
||||
|
||||
int convexHullAddFace(convexHull *hull, int firstVertex, int secondVertex,
|
||||
int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
|
||||
int thirdVertex) {
|
||||
face *tri;
|
||||
face3 *tri;
|
||||
converHullVertex *vtx1;
|
||||
converHullVertex *vtx2;
|
||||
converHullVertex *vtx3;
|
||||
|
@ -191,21 +190,21 @@ int convexHullAddFace(convexHull *hull, int firstVertex, int secondVertex,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
memset(&hull->findFace, 0, sizeof(hull->findFace));
|
||||
hull->findFace.indices[0] = firstVertex;
|
||||
hull->findFace.indices[1] = secondVertex;
|
||||
hull->findFace.indices[2] = thirdVertex;
|
||||
if (0 == hashtableGet(hull->faceHashtable, 0)) {
|
||||
qsort(hull->findFace.indices, 3,
|
||||
sizeof(hull->findFace.indices[0]), sortface);
|
||||
newTri = arrayGetLength(hull->faceArray);
|
||||
if (0 != arraySetLength(hull->faceArray, newTri + 1)) {
|
||||
memset(&hull->findFace3, 0, sizeof(hull->findFace3));
|
||||
hull->findFace3.indices[0] = firstVertex;
|
||||
hull->findFace3.indices[1] = secondVertex;
|
||||
hull->findFace3.indices[2] = thirdVertex;
|
||||
qsort(hull->findFace3.indices, 3,
|
||||
sizeof(hull->findFace3.indices[0]), sortface);
|
||||
if (0 == hashtableGet(hull->face3Hashtable, 0)) {
|
||||
newTri = arrayGetLength(hull->face3Array);
|
||||
if (0 != arraySetLength(hull->face3Array, newTri + 1)) {
|
||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
tri = (face *)arrayGetItem(hull->faceArray, newTri);
|
||||
*tri = hull->findFace;
|
||||
if (0 != hashtableInsert(hull->faceHashtable,
|
||||
tri = (face3 *)arrayGetItem(hull->face3Array, newTri);
|
||||
*tri = hull->findFace3;
|
||||
if (0 != hashtableInsert(hull->face3Hashtable,
|
||||
(char *)0 + newTri + 1)) {
|
||||
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
|
@ -222,8 +221,8 @@ static void convexHullReleaseForGenerate(convexHull *hull) {
|
|||
void convexHullDestroy(convexHull *hull) {
|
||||
arrayDestroy(hull->vertexArray);
|
||||
arrayDestroy(hull->todoArray);
|
||||
arrayDestroy(hull->faceArray);
|
||||
hashtableDestroy(hull->faceHashtable);
|
||||
arrayDestroy(hull->face3Array);
|
||||
hashtableDestroy(hull->face3Hashtable);
|
||||
convexHullReleaseForGenerate(hull);
|
||||
free(hull);
|
||||
}
|
||||
|
@ -290,7 +289,8 @@ int convexHullGenerate(convexHull *hull) {
|
|||
todo *t = (todo *)arrayGetItem(hull->todoArray, hull->nextTodoIndex++);
|
||||
index1 = t->firstVertex;
|
||||
index2 = t->secondVertex;
|
||||
if (convexHullEdgeExsits(hull, index1, index2)) {
|
||||
if (convexHullEdgeExsits(hull, index1, index2) ||
|
||||
convexHullEdgeExsits(hull, index2, index1)) {
|
||||
continue;
|
||||
}
|
||||
convexHullMarkEdgeAsExsits(hull, index1, index2);
|
||||
|
@ -298,8 +298,7 @@ int convexHullGenerate(convexHull *hull) {
|
|||
if (-1 == index3) {
|
||||
continue;
|
||||
}
|
||||
convexHullAddFace(hull, index1, index2, index3);
|
||||
convexHullAddTodo(hull, index1, index2, index3);
|
||||
convexHullAddFace3(hull, index1, index2, index3);
|
||||
convexHullAddTodo(hull, index2, index3, index1);
|
||||
convexHullAddTodo(hull, index3, index1, index2);
|
||||
}
|
||||
|
@ -308,9 +307,9 @@ int convexHullGenerate(convexHull *hull) {
|
|||
|
||||
int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
|
||||
int i;
|
||||
for (i = 0; i < arrayGetLength(hull->faceArray); ++i) {
|
||||
face *triIdx = (face *)arrayGetItem(
|
||||
hull->faceArray, i);
|
||||
for (i = 0; i < arrayGetLength(hull->face3Array); ++i) {
|
||||
face3 *triIdx = (face3 *)arrayGetItem(
|
||||
hull->face3Array, i);
|
||||
converHullVertex *p1 = (converHullVertex *)arrayGetItem(
|
||||
hull->vertexArray, triIdx->indices[0]);
|
||||
converHullVertex *p2 = (converHullVertex *)arrayGetItem(
|
||||
|
@ -330,19 +329,16 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int convexHullGetTriangleNum(convexHull *hull) {
|
||||
return arrayGetLength(hull->faceArray);
|
||||
face3 *convexHullGetFace3(convexHull *hull, int faceIndex) {
|
||||
return (face3 *)arrayGetItem(hull->face3Array, faceIndex);
|
||||
}
|
||||
|
||||
triangle *convexHullGetTriangle(convexHull *hull, int index) {
|
||||
int i;
|
||||
face *triIdx = (face *)arrayGetItem(
|
||||
hull->faceArray, index);
|
||||
memset(&hull->returnTriangle, 0, sizeof(hull->returnTriangle));
|
||||
for (i = 0; i < 3; ++i) {
|
||||
vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex) {
|
||||
converHullVertex *vertex = (converHullVertex *)arrayGetItem(
|
||||
hull->vertexArray, triIdx->indices[i]);
|
||||
hull->returnTriangle.pt[i] = vertex->pt;
|
||||
hull->vertexArray, vertexIndex);
|
||||
return &vertex->pt;
|
||||
}
|
||||
return &hull->returnTriangle;
|
||||
|
||||
int convexHullGetFace3Num(convexHull *hull) {
|
||||
return arrayGetLength(hull->face3Array);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef CONVEX_HULL_H
|
||||
#define CONVEX_HULL_H
|
||||
#include "vector3d.h"
|
||||
#include "draw.h"
|
||||
#include "3dstruct.h"
|
||||
|
||||
typedef struct convexHull convexHull;
|
||||
convexHull *convexHullCreate(void);
|
||||
|
@ -10,8 +9,9 @@ int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
|
|||
void convexHullDestroy(convexHull *hull);
|
||||
int convexHullGenerate(convexHull *hull);
|
||||
int convexHullUnifyNormals(convexHull *hull, vec3 *origin);
|
||||
int convexHullGetTriangleNum(convexHull *hull);
|
||||
triangle *convexHullGetTriangle(convexHull *hull, int index);
|
||||
int convexHullGetFace3Num(convexHull *hull);
|
||||
face3 *convexHullGetFace3(convexHull *hull, int faceIndex);
|
||||
vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex);
|
||||
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
|
||||
|
||||
#endif
|
||||
|
|
15
src/draw.h
15
src/draw.h
|
@ -1,6 +1,6 @@
|
|||
#ifndef DRAW_SPHERE_H
|
||||
#define DRAW_SPHERE_H
|
||||
#include "vector3d.h"
|
||||
#include "3dstruct.h"
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
|
@ -11,19 +11,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
vec3 pt[3];
|
||||
} triangle;
|
||||
|
||||
typedef struct {
|
||||
vec3 pt[4];
|
||||
} quad;
|
||||
|
||||
typedef struct {
|
||||
int npoly;
|
||||
triangle *poly;
|
||||
} object;
|
||||
|
||||
int drawInit(void);
|
||||
int drawSphere(vec3 *origin, float radius, int slices, int stacks);
|
||||
void drawTriangle(triangle *poly);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#include "osutil.h"
|
||||
#include <QDateTime>
|
||||
|
||||
long long osGetMilliseconds(void) {
|
||||
return (long long)QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
|
@ -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
|
324
src/tri2quad.c
324
src/tri2quad.c
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue