Make sure all cross sections on the convex hull.

master
Jeremy Hu 2017-01-02 18:20:05 +09:30
parent 68cb7d499f
commit 2f022b337c
7 changed files with 247 additions and 85 deletions

View File

@ -57,3 +57,12 @@ void arrayDestroy(array *arr) {
free(arr);
}
}
void *arrayNewItem(array *arr) {
int newIndex = arrayGetLength(arr);
if (0 != arraySetLength(arr, newIndex + 1)) {
fprintf(stderr, "%s:arraySetLength.\n", __FUNCTION__);
return 0;
}
return arrayGetItem(arr, newIndex);
}

View File

@ -11,6 +11,7 @@ array *arrayCreate(int nodeSize);
void *arrayGetItem(array *arr, int index);
int arrayGetLength(array *arr);
int arraySetLength(array *arr, int length);
void *arrayNewItem(array *arr);
void arrayDestroy(array *arr);
#ifdef __cplusplus

View File

@ -10,7 +10,6 @@
#include "convexhull.h"
#include "draw.h"
#define BMESH_STEP_DISTANCE 0.2
#define BMESH_MAX_PARENT_BALL_DEPTH 1000
typedef struct bmeshBallIndex {
@ -92,6 +91,7 @@ int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
ball->index = index;
ball->firstChildIndex = -1;
ball->childrenIndices = 0;
ball->notFitHull = 0;
if (0 != arraySetLength(bm->ballArray, index + 1)) {
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
@ -235,12 +235,11 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
bmeshBall *firstBall = bmeshGetBall(bm, firstBallIndex);
bmeshBall *secondBall = bmeshGetBall(bm, secondBallIndex);
bmeshBall *newBall;
float intvalDist;
if (secondBall->roundColor == bm->roundColor) {
return 0;
}
step = BMESH_STEP_DISTANCE;
vec3Sub(&firstBall->position, &secondBall->position, &boneDirection);
normalizedBoneDirection = boneDirection;
vec3Normalize(&normalizedBoneDirection);
@ -261,15 +260,17 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
boneDirection.z);
*/
intvalDist = (firstBall->radius + secondBall->radius) / 3;
step = intvalDist;
distance = vec3Length(&boneDirection);
if (distance > BMESH_STEP_DISTANCE) {
if (distance > intvalDist) {
float offset;
int calculatedStepCount = (int)(distance / BMESH_STEP_DISTANCE);
float remaining = distance - BMESH_STEP_DISTANCE * calculatedStepCount;
int calculatedStepCount = (int)(distance / intvalDist);
float remaining = distance - intvalDist * calculatedStepCount;
step += remaining / calculatedStepCount;
offset = step;
if (offset < distance) {
while (offset < distance && offset + BMESH_STEP_DISTANCE <= distance) {
while (offset < distance && offset + intvalDist <= distance) {
float frac = offset / distance;
parentBallIndex = bmeshAddInbetweenBallBetween(bm,
firstBall, secondBall, frac, parentBallIndex);
@ -508,7 +509,7 @@ int bmeshSweep(bmesh *bm) {
static int isDistanceEnoughForConvexHull(bmeshBall *root,
bmeshBall *ball) {
float distance = vec3Distance(&root->position, &ball->position);
if (distance >= root->radius + BMESH_STEP_DISTANCE) {
if (distance >= root->radius) {
return 1;
}
return 0;
@ -518,14 +519,13 @@ static bmeshBall *bmeshFindChildBallForConvexHull(bmesh *bm, bmeshBall *root,
bmeshBall *ball) {
bmeshBallIterator iterator;
bmeshBall *child;
if (isDistanceEnoughForConvexHull(root, ball)) {
if (!ball->notFitHull && isDistanceEnoughForConvexHull(root, ball)) {
return ball;
}
child = bmeshGetBallFirstChild(bm, ball, &iterator);
if (!child) {
return ball;
}
ball->radius = 0;
return bmeshFindChildBallForConvexHull(bm, root, child);
}
@ -534,15 +534,14 @@ static bmeshBall *bmeshFindParentBallForConvexHull(bmesh *bm, bmeshBall *root,
if (depth <= 0) {
return ball;
}
if (isDistanceEnoughForConvexHull(root, ball)) {
if (!ball->notFitHull && isDistanceEnoughForConvexHull(root, ball)) {
return ball;
}
ball->radius = 0;
return bmeshFindParentBallForConvexHull(bm, root, depth - 1,
bm->parentBallStack[depth - 1]);
}
static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
bmeshBall **outmostBall, int *outmostBallFirstVertexIndex) {
vec3 z, y;
quad q;
@ -560,10 +559,19 @@ static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
vec3Add(&ballForConvexHull->position, &y, &q.pt[3]);
vec3Add(&q.pt[3], &z, &q.pt[3]);
vertexIndex[0] = convexHullAddVertex(hull, &q.pt[0], ballForConvexHull->index, 0);
vertexIndex[1] = convexHullAddVertex(hull, &q.pt[1], ballForConvexHull->index, 1);
vertexIndex[2] = convexHullAddVertex(hull, &q.pt[2], ballForConvexHull->index, 2);
vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3], ballForConvexHull->index, 3);
vertexIndex[0] = convexHullAddVertex(hull, &q.pt[0],
ballForConvexHull->index, 0);
vertexIndex[1] = convexHullAddVertex(hull, &q.pt[1],
ballForConvexHull->index, 1);
vertexIndex[2] = convexHullAddVertex(hull, &q.pt[2],
ballForConvexHull->index, 2);
vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3],
ballForConvexHull->index, 3);
if (-1 == vertexIndex[0] || -1 == vertexIndex[1] || -1 == vertexIndex[2] ||
-1 == vertexIndex[3]) {
fprintf(stderr, "%s:convexHullAddVertex failed.\n", __FUNCTION__);
return -1;
}
if (*outmostBall) {
if (ballForConvexHull->radius > (*outmostBall)->radius) {
@ -576,17 +584,162 @@ static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
*outmostBall = ballForConvexHull;
*outmostBallFirstVertexIndex = vertexIndex[0];
}
return 0;
}
#include "osutil.h"
int showFaceIndex = 10000000;
static long long lastShowFaceIndexIncTime = 0;
static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
int result = 0;
static convexHull *createConvexHullForBall(bmesh *bm, int depth,
bmeshBall *ball, int *needRetry) {
convexHull *hull;
bmeshBallIterator iterator;
bmeshBall *child;
bmeshBall *ballForConvexHull;
bmeshBall *outmostBall = 0;
int outmostBallFirstVertexIndex = 0;
array *ballPtrArray;
bmeshBall **ballPtr;
int i;
int hasVertexNotFitOnHull = 0;
*needRetry = 0;
ballPtrArray = arrayCreate(sizeof(bmeshBall *));
if (!ballPtrArray) {
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
return 0;
}
hull = convexHullCreate();
if (!hull) {
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
return 0;
}
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child);
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
if (!ballPtr) {
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
*ballPtr = ballForConvexHull;
if (-1 == addBallToHull(hull, ballForConvexHull,
&outmostBall, &outmostBallFirstVertexIndex)) {
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
}
if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) {
ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1,
bm->parentBallStack[depth - 1]);
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
if (!ballPtr) {
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
*ballPtr = ballForConvexHull;
if (-1 == addBallToHull(hull, ballForConvexHull,
&outmostBall, &outmostBallFirstVertexIndex)) {
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
}
if (outmostBall) {
if (-1 == convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0,
outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2)) {
fprintf(stderr, "%s:convexHullAddTodo failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
}
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i));
ballItem->flagForHull = 0;
}
if (-1 == convexHullGenerate(hull)) {
fprintf(stderr, "%s:convexHullGenerate failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
convexHullUnifyNormals(hull, &ball->position);
convexHullMergeTriangles(hull);
for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
convexHullFace *f = (convexHullFace *)convexHullGetFace(hull, i);
if (-1 != f->plane) {
bmeshBall *ballItem = (bmeshBall *)arrayGetItem(bm->ballArray, f->plane);
ballItem->flagForHull = 1;
f->vertexNum = 0;
}
}
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i));
if (!ballItem->flagForHull) {
hasVertexNotFitOnHull = 1;
if (!ballItem->notFitHull) {
*needRetry = 1;
ballItem->notFitHull = 1;
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
}
}
/*
if (!hasVertexNotFitOnHull) {
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
bmeshBall *ballItem = *((bmeshBall **)arrayGetItem(ballPtrArray, i));
if (-1 == ballItem->countsForHull[0] ||
ballItem->countsForHull[0] != ballItem->countsForHull[1] ||
ballItem->countsForHull[1] != ballItem->countsForHull[2] ||
ballItem->countsForHull[2] != ballItem->countsForHull[3]) {
hasVertexNotFitOnHull = 1;
if (!ballItem->notFitHull) {
*needRetry = 1;
ballItem->notFitHull = 1;
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
}
}
}*/
if (hasVertexNotFitOnHull) {
fprintf(stderr, "%s:hasVertexNotFitOnHull.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
arrayDestroy(ballPtrArray);
return hull;
}
static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
bmeshBallIterator iterator;
bmeshBall *child;
int result = 0;
if (bm->roundColor == ball->roundColor) {
return 0;
}
@ -594,38 +747,20 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
bm->parentBallStack[depth] = ball;
}
ball->roundColor = bm->roundColor;
if (BMESH_BALL_TYPE_ROOT == ball->type) {
convexHull *hull;
bmeshBall *outmostBall = 0;
int outmostBallFirstVertexIndex = 0;
hull = convexHullCreate();
if (!hull) {
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
return -1;
if (BMESH_BALL_TYPE_ROOT == ball->type/* && 2 == ball->index*/) {
convexHull *hull = 0;
for (;;) {
int needRetry = 0;
hull = createConvexHullForBall(bm, depth, ball, &needRetry);
if (hull) {
break;
}
glColor3f(0.0, 0.0, 0.0);
drawDebugPrintf("root <%f,%f,%f>", ball->position.x,
ball->position.y, ball->position.z);
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child);
addBallToHull(hull, ballForConvexHull,
&outmostBall, &outmostBallFirstVertexIndex);
if (!needRetry) {
break;
}
if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) {
ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1,
bm->parentBallStack[depth - 1]);
addBallToHull(hull, ballForConvexHull,
&outmostBall, &outmostBallFirstVertexIndex);
}
if (outmostBall) {
convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0,
outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2);
}
convexHullGenerate(hull);
convexHullUnifyNormals(hull, &ball->position);
convexHullMergeTriangles(hull);
glPushMatrix();
/*
@ -649,6 +784,7 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
}
}*/
if (hull)
{
int triIndex;
for (triIndex = 0; triIndex < convexHullGetFaceNum(hull);
@ -658,9 +794,9 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
if (3 == face->vertexNum) {
triangle tri;
int j;
tri.pt[0] = *convexHullGetVertex(hull, face->u.t.indices[0]);
tri.pt[1] = *convexHullGetVertex(hull, face->u.t.indices[1]);
tri.pt[2] = *convexHullGetVertex(hull, face->u.t.indices[2]);
tri.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
tri.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
tri.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
if (triIndex >= showFaceIndex) {
break;
@ -680,10 +816,10 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
quad q;
vec3 normal;
int j;
q.pt[0] = *convexHullGetVertex(hull, face->u.q.indices[0]);
q.pt[1] = *convexHullGetVertex(hull, face->u.q.indices[1]);
q.pt[2] = *convexHullGetVertex(hull, face->u.q.indices[2]);
q.pt[3] = *convexHullGetVertex(hull, face->u.q.indices[3]);
q.pt[0] = convexHullGetVertex(hull, face->u.q.indices[0])->pt;
q.pt[1] = convexHullGetVertex(hull, face->u.q.indices[1])->pt;
q.pt[2] = convexHullGetVertex(hull, face->u.q.indices[2])->pt;
q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt;
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
@ -788,8 +924,10 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
}*/
glPopMatrix();
if (hull) {
convexHullDestroy(hull);
}
}
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) {

View File

@ -26,6 +26,8 @@ typedef struct {
vec3 localYaxis;
vec3 localZaxis;
int roundColor;
int notFitHull;
int flagForHull;
} bmeshBall;
typedef int bmeshBallIterator;

View File

@ -14,19 +14,14 @@
#define FACE3_HASHTABLE_SIZE 100
#define EDGE_HASHTABLE_SIZE 100
typedef struct {
vec3 pt;
int plane;
int orderOnPlane;
} convexHullVertex;
typedef struct {
int p1;
int p2;
int hill1;
int hill2;
vec3 hill1Normal;
int score;
int angleBetweenFaces;
int angleWithLevel;
int face1;
int face2;
} edge;
@ -265,13 +260,17 @@ int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
convexHullVertex *vtx2;
convexHullVertex *vtx3;
int newTri;
int facePlane = -1;
vtx1 = (convexHullVertex *)arrayGetItem(hull->vertexArray, firstVertex);
vtx2 = (convexHullVertex *)arrayGetItem(hull->vertexArray, secondVertex);
vtx3 = (convexHullVertex *)arrayGetItem(hull->vertexArray, thirdVertex);
if (vtx1->plane == vtx2->plane && vtx1->plane == vtx3->plane) {
return 0;
facePlane = vtx1->plane;
}
/*
if (vtx1->plane == vtx2->plane) {
if (!isInAdjacentOrder(vtx1->orderOnPlane, vtx2->orderOnPlane)) {
return 0;
@ -286,7 +285,7 @@ int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
if (!isInAdjacentOrder(vtx2->orderOnPlane, vtx3->orderOnPlane)) {
return 0;
}
}
}*/
memset(&hull->findFace3, 0, sizeof(hull->findFace3));
hull->findFace3.indices[0] = firstVertex;
@ -302,6 +301,7 @@ int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
}
tri = (face3 *)arrayGetItem(hull->faceArray, newTri);
((convexHullFace *)tri)->vertexNum = 3;
((convexHullFace *)tri)->plane = facePlane;
*tri = hull->findFace3;
if (0 != hashtableInsert(hull->face3Hashtable,
(char *)0 + newTri + 1)) {
@ -488,7 +488,11 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
static int sortEdgeByScore(const void *first, const void *second) {
edge *e1 = (edge *)first;
edge *e2 = (edge *)second;
return e1->score - e2->score;
int result = e1->angleBetweenFaces - e2->angleBetweenFaces;
if (0 == result) {
result = e2->angleWithLevel - e1->angleWithLevel;
}
return result;
}
static void rollTriangleIndices(face3 *face) {
@ -512,7 +516,7 @@ int convexHullMergeTriangles(convexHull *hull) {
//face3 *f2 = (face3 *)arrayGetItem(hull->faceArray, e->face2);
vec3 f1normal;
vec3 f2normal;
float angle;
const vec3 yAxis = {0, 1, 0};
/*
convexHullVertex *f1p1 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, f1->indices[0]);
@ -533,15 +537,12 @@ int convexHullMergeTriangles(convexHull *hull) {
vec3 *v2 = (vec3 *)arrayGetItem(hull->vertexArray, e->p2);
vec3 *vHill1 = (vec3 *)arrayGetItem(hull->vertexArray, e->hill1);
vec3 *vHill2 = (vec3 *)arrayGetItem(hull->vertexArray, e->hill2);
vec3 v12;
vec3Sub(v1, v2, &v12);
vec3Normal(v1, vHill1, v2, &f1normal);
vec3Normal(v2, vHill2, v1, &f2normal);
angle = (int)vec3Angle(&f1normal, &f2normal);
e->score = (int)angle;
//if (edgeIndex >= 12 && edgeIndex <= 12) {
// angle = (int)vec3Angle(&f1normal, &f2normal);
drawDebugPrintf("edgeIndex:%d angle:%f",
edgeIndex, angle);
//}
e->angleBetweenFaces = (int)vec3Angle(&f1normal, &f2normal);
e->angleWithLevel = (int)vec3Angle(&v12, (vec3 *)&yAxis);
}
}
@ -563,7 +564,8 @@ int convexHullMergeTriangles(convexHull *hull) {
convexHullFace *f2 = (convexHullFace *)arrayGetItem(hull->faceArray,
e->face2);
if (3 == f1->vertexNum && 3 == f2->vertexNum) {
if (e->score <= 40) {
if (e->angleBetweenFaces <= 40 &&
f1->plane == f2->plane) {
while (e->p1 == f1->u.t.indices[0] || e->p2 == f1->u.t.indices[0]) {
rollTriangleIndices((face3 *)f1);
}
@ -595,10 +597,10 @@ convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex) {
return face;
}
vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex) {
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex) {
convexHullVertex *vertex = (convexHullVertex *)arrayGetItem(
hull->vertexArray, vertexIndex);
return &vertex->pt;
return vertex;
}
int convexHullGetFaceNum(convexHull *hull) {

View File

@ -3,14 +3,22 @@
#include "3dstruct.h"
typedef struct convexHull convexHull;
typedef struct {
union {
face4 q;
face3 t;
} u;
int vertexNum;
int plane;
} convexHullFace;
typedef struct {
vec3 pt;
int plane;
int orderOnPlane;
} convexHullVertex;
convexHull *convexHullCreate(void);
int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
int orderOnPlane);
@ -20,7 +28,7 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin);
int convexHullMergeTriangles(convexHull *hull);
int convexHullGetFaceNum(convexHull *hull);
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex);
vec3 *convexHullGetVertex(convexHull *hull, int vertexIndex);
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex);
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
#endif

View File

@ -213,7 +213,7 @@ void Render::initializeGL() {
drawInit();
}
#include "../data/bmesh_test_1.h"
#include "../data/bmesh_test_2.h"
void Render::paintGL() {
bmesh *bm = 0;
@ -237,6 +237,7 @@ void Render::paintGL() {
glEnable(GL_LIGHTING);
/*
{
subdivModel *input = subdivCreateModel();
subdivModel *output;
@ -245,8 +246,9 @@ void Render::paintGL() {
subdivDestroyModel(input);
subdivDestroyModel(output);
}
*/
if (0 && 0 == bm) {
if (0 == bm) {
bmeshBall ball;
bmeshBone bone;
int i;
@ -272,7 +274,7 @@ void Render::paintGL() {
bmeshGenerateInbetweenBalls(bm);
bmeshSweep(bm);
bmeshStitch(bm);
bmeshGenerateInbetweenMesh(bm);
//bmeshGenerateInbetweenMesh(bm);
}
if (bm) {