parent
e9e9a170e3
commit
3ca8e64b68
|
@ -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
|
|
@ -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 "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;
|
||||||
|
|
108
src/convexhull.c
108
src/convexhull.c
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
15
src/draw.h
15
src/draw.h
|
@ -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);
|
||||||
|
|
|
@ -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