Handle out of memory in one place

master
Jeremy Hu 2017-01-31 08:26:24 +09:30
parent be9e73b83d
commit a4569fbe1e
14 changed files with 390 additions and 887 deletions

View File

@ -16,10 +16,11 @@ SOURCES += main.cpp \
bmesh.c \ bmesh.c \
matrix.c \ matrix.c \
convexhull.c \ convexhull.c \
hashtable.c \ dict.c \
osutil.cpp \ osutil.cpp \
subdivide.c \ subdivide.c \
skinnedmesh.c skinnedmesh.c \
dmemory.c
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
render.h \ render.h \
@ -29,8 +30,9 @@ HEADERS += mainwindow.h \
bmesh.h \ bmesh.h \
matrix.h \ matrix.h \
convexhull.h \ convexhull.h \
hashtable.h \ dict.h \
3dstruct.h \ 3dstruct.h \
osutil.h \ osutil.h \
subdivide.h \ subdivide.h \
skinnedmesh.h skinnedmesh.h \
dmemory.h

View File

@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "dmemory.h"
#include "array.h" #include "array.h"
struct array { struct array {
@ -11,34 +12,29 @@ struct array {
}; };
array *arrayCreate(int nodeSize) { array *arrayCreate(int nodeSize) {
array *arr = (array *)calloc(1, sizeof(array)); array *arr = dcalloc(1, sizeof(array));
if (!arr) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
arr->nodeSize = nodeSize; arr->nodeSize = nodeSize;
return arr; return arr;
} }
int arraySetLength(array *arr, int length) { int arrayGetNodeSize(array *arr) {
return arr->nodeSize;
}
void arraySetLength(array *arr, int length) {
char *newNodes; char *newNodes;
if (length > arr->capacity) { if (length > arr->capacity) {
int newCapacity = (arr->capacity + 1) * 2; int newCapacity = (arr->capacity + 1) * 2;
if (newCapacity < length) { if (newCapacity < length) {
newCapacity = length; newCapacity = length;
} }
newNodes = (char *)realloc(arr->nodes, arr->nodeSize * newCapacity); newNodes = drealloc(arr->nodes, arr->nodeSize * newCapacity);
if (!newNodes) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return -1;
}
memset(newNodes + arr->nodeSize * arr->capacity, 0, memset(newNodes + arr->nodeSize * arr->capacity, 0,
arr->nodeSize * (newCapacity - arr->capacity)); arr->nodeSize * (newCapacity - arr->capacity));
arr->capacity = newCapacity; arr->capacity = newCapacity;
arr->nodes = newNodes; arr->nodes = newNodes;
} }
arr->length = length; arr->length = length;
return 0;
} }
void *arrayGetItem(array *arr, int index) { void *arrayGetItem(array *arr, int index) {
@ -54,16 +50,19 @@ int arrayGetLength(array *arr) {
void arrayDestroy(array *arr) { void arrayDestroy(array *arr) {
if (arr) { if (arr) {
free(arr->nodes); dfree(arr->nodes);
free(arr); dfree(arr);
} }
} }
void *arrayNewItem(array *arr) { void *arrayNewItem(array *arr) {
int newIndex = arrayGetLength(arr); int newIndex = arrayGetLength(arr);
if (0 != arraySetLength(arr, newIndex + 1)) { arraySetLength(arr, newIndex + 1);
fprintf(stderr, "%s:arraySetLength.\n", __FUNCTION__);
return 0;
}
return arrayGetItem(arr, newIndex); return arrayGetItem(arr, newIndex);
} }
void *arrayNewItemClear(array *arr) {
void *ptr = arrayNewItem(arr);
memset(ptr, 0, arr->nodeSize);
return ptr;
}

View File

@ -8,10 +8,12 @@ extern "C" {
typedef struct array array; typedef struct array array;
array *arrayCreate(int nodeSize); array *arrayCreate(int nodeSize);
int arrayGetNodeSize(array *arr);
void *arrayGetItem(array *arr, int index); void *arrayGetItem(array *arr, int index);
int arrayGetLength(array *arr); int arrayGetLength(array *arr);
int arraySetLength(array *arr, int length); void arraySetLength(array *arr, int length);
void *arrayNewItem(array *arr); void *arrayNewItem(array *arr);
void *arrayNewItemClear(array *arr);
void arrayDestroy(array *arr); void arrayDestroy(array *arr);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -4,9 +4,10 @@
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include "dmemory.h"
#include "bmesh.h" #include "bmesh.h"
#include "array.h" #include "array.h"
#include "hashtable.h" #include "dict.h"
#include "matrix.h" #include "matrix.h"
#include "convexhull.h" #include "convexhull.h"
#include "subdivide.h" #include "subdivide.h"
@ -37,97 +38,50 @@ struct bmesh {
subdivModel *model; subdivModel *model;
subdivModel *subdivModel; subdivModel *subdivModel;
array *modelVertexArray; array *modelVertexArray;
hashtable *modelVertexHashtable; dict *modelVertexDict;
bmeshModelVertex findModelVertex; bmeshModelVertex findModelVertex;
}; };
static bmeshModelVertex *bmeshFindModelVertex(bmesh *bm, vec3 *vertex) { static bmeshModelVertex *bmeshFindModelVertex(bmesh *bm, vec3 *vertex) {
int index; return dictFind(bm->modelVertexDict, vertex);
bm->findModelVertex.vertex = *vertex;
index = (char *)hashtableGet(bm->modelVertexHashtable, (char *)0) - (char *)0;
if (0 == index) {
return 0;
}
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
} }
static int bmeshAddModelVertex(bmesh *bm, vec3 *vertex) { static int bmeshAddModelVertex(bmesh *bm, vec3 *vertex) {
bmeshModelVertex *v = bmeshFindModelVertex(bm, vertex); bmeshModelVertex *v = bmeshFindModelVertex(bm, vertex);
if (!v) { if (!v) {
v = (bmeshModelVertex *)arrayNewItem(bm->modelVertexArray); v = dictGetClear(bm->modelVertexDict, vertex);
if (!v) {
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
return -1;
}
memset(v, 0, sizeof(bmeshModelVertex));
v->vertex = *vertex; v->vertex = *vertex;
v->indexOnModel = subdivAddVertex(bm->model, &v->vertex); v->indexOnModel = subdivAddVertex(bm->model, &v->vertex);
if (-1 == hashtableInsert(bm->modelVertexHashtable,
(char *)0 + arrayGetLength(bm->modelVertexArray))) {
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
return -1;
}
} }
return v->indexOnModel; return v->indexOnModel;
} }
static int bmeshAddQuadToModel(bmesh *bm, quad *q) { static void bmeshAddQuadToModel(bmesh *bm, quad *q) {
int indices[4]; int indices[4];
indices[0] = bmeshAddModelVertex(bm, &q->pt[0]); indices[0] = bmeshAddModelVertex(bm, &q->pt[0]);
indices[1] = bmeshAddModelVertex(bm, &q->pt[1]); indices[1] = bmeshAddModelVertex(bm, &q->pt[1]);
indices[2] = bmeshAddModelVertex(bm, &q->pt[2]); indices[2] = bmeshAddModelVertex(bm, &q->pt[2]);
indices[3] = bmeshAddModelVertex(bm, &q->pt[3]); indices[3] = bmeshAddModelVertex(bm, &q->pt[3]);
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2] || subdivAddQuadFace(bm->model, indices[0], indices[1], indices[2], indices[3]);
-1 == indices[3]) {
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
return -1;
}
if (-1 == subdivAddQuadFace(bm->model, indices[0], indices[1], indices[2],
indices[3])) {
fprintf(stderr, "%s:subdivAddQuadFace failed.\n", __FUNCTION__);
return -1;
}
return 0;
} }
static int bmeshAddTriangleToModel(bmesh *bm, triangle *t) { static void bmeshAddTriangleToModel(bmesh *bm, triangle *t) {
int indices[3]; int indices[3];
indices[0] = bmeshAddModelVertex(bm, &t->pt[0]); indices[0] = bmeshAddModelVertex(bm, &t->pt[0]);
indices[1] = bmeshAddModelVertex(bm, &t->pt[1]); indices[1] = bmeshAddModelVertex(bm, &t->pt[1]);
indices[2] = bmeshAddModelVertex(bm, &t->pt[2]); indices[2] = bmeshAddModelVertex(bm, &t->pt[2]);
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2]) { subdivAddTriangleFace(bm->model, indices[0], indices[1], indices[2]);
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
return -1;
}
if (-1 == subdivAddTriangleFace(bm->model, indices[0], indices[1],
indices[2])) {
fprintf(stderr, "%s:subdivAddTriangleFace failed.\n", __FUNCTION__);
return -1;
}
return 0;
}
bmeshModelVertex *bmeshGetModelVertexByHashtableParam(void *userData,
const void *node) {
bmesh *bm = (bmesh *)userData;
int index = (char *)node - (char *)0;
if (0 == index) {
return &bm->findModelVertex;
}
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
} }
static int modelVertexHash(void *userData, const void *node) { static int modelVertexHash(void *userData, const void *node) {
bmeshModelVertex *v = bmeshGetModelVertexByHashtableParam(userData, node); const bmeshModelVertex *v = node;
return abs(*((int *)v)); return abs(*((int *)v));
} }
static int modelVertexCompare(void *userData, const void *firstNode, static int modelVertexCompare(void *userData, const void *firstNode,
const void *secondNode) { const void *secondNode) {
bmeshModelVertex *v1 = bmeshGetModelVertexByHashtableParam(userData, const bmeshModelVertex *v1 = firstNode;
firstNode); const bmeshModelVertex *v2 = secondNode;
bmeshModelVertex *v2 = bmeshGetModelVertexByHashtableParam(userData,
secondNode);
if (0 == v1->vertex.x - v2->vertex.x && if (0 == v1->vertex.x - v2->vertex.x &&
0 == v1->vertex.y - v2->vertex.y && 0 == v1->vertex.y - v2->vertex.y &&
0 == v1->vertex.z - v2->vertex.z) { 0 == v1->vertex.z - v2->vertex.z) {
@ -137,54 +91,16 @@ static int modelVertexCompare(void *userData, const void *firstNode,
} }
bmesh *bmeshCreate(void) { bmesh *bmeshCreate(void) {
bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh)); bmesh *bm = dcalloc(1, sizeof(bmesh));
if (!bm) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
bm->ballArray = arrayCreate(sizeof(bmeshBall)); bm->ballArray = arrayCreate(sizeof(bmeshBall));
if (!bm->ballArray) {
fprintf(stderr, "%s:arrayCreate bmeshBall failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->boneArray = arrayCreate(sizeof(bmeshBone)); bm->boneArray = arrayCreate(sizeof(bmeshBone));
if (!bm->boneArray) {
fprintf(stderr, "%s:arrayCreate bmeshBone failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->indexArray = arrayCreate(sizeof(bmeshBallIndex)); bm->indexArray = arrayCreate(sizeof(bmeshBallIndex));
if (!bm->indexArray) {
fprintf(stderr, "%s:arrayCreate bmeshBallIndex failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->quadArray = arrayCreate(sizeof(quad)); bm->quadArray = arrayCreate(sizeof(quad));
if (!bm->quadArray) {
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->model = subdivCreateModel(); bm->model = subdivCreateModel();
if (!bm->model) {
fprintf(stderr, "%s:subdivCreateModel failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->modelVertexArray = arrayCreate(sizeof(bmeshModelVertex)); bm->modelVertexArray = arrayCreate(sizeof(bmeshModelVertex));
if (!bm->modelVertexArray) { bm->modelVertexDict = dictCreate(bm->modelVertexArray,
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__); BMESH_MODEL_VERTEX_HASHTABLE_SIZE,
bmeshDestroy(bm);
return 0;
}
bm->modelVertexHashtable = hashtableCreate(BMESH_MODEL_VERTEX_HASHTABLE_SIZE,
modelVertexHash, modelVertexCompare, bm); modelVertexHash, modelVertexCompare, bm);
if (!bm->modelVertexHashtable) {
fprintf(stderr, "%s:hashtableCreate quad failed.\n", __FUNCTION__);
bmeshDestroy(bm);
return 0;
}
bm->rootBallIndex = -1; bm->rootBallIndex = -1;
bm->roundColor = 0; bm->roundColor = 0;
return bm; return bm;
@ -198,8 +114,8 @@ void bmeshDestroy(bmesh *bm) {
subdivDestroyModel(bm->model); subdivDestroyModel(bm->model);
subdivDestroyModel(bm->subdivModel); subdivDestroyModel(bm->subdivModel);
arrayDestroy(bm->modelVertexArray); arrayDestroy(bm->modelVertexArray);
hashtableDestroy(bm->modelVertexHashtable); dictDestroy(bm->modelVertexDict);
free(bm); dfree(bm);
} }
int bmeshGetBallNum(bmesh *bm) { int bmeshGetBallNum(bmesh *bm) {
@ -211,11 +127,11 @@ int bmeshGetBoneNum(bmesh *bm) {
} }
bmeshBall *bmeshGetBall(bmesh *bm, int index) { bmeshBall *bmeshGetBall(bmesh *bm, int index) {
return (bmeshBall *)arrayGetItem(bm->ballArray, index); return arrayGetItem(bm->ballArray, index);
} }
bmeshBone *bmeshGetBone(bmesh *bm, int index) { bmeshBone *bmeshGetBone(bmesh *bm, int index) {
return (bmeshBone *)arrayGetItem(bm->boneArray, index); return arrayGetItem(bm->boneArray, index);
} }
int bmeshAddBall(bmesh *bm, bmeshBall *ball) { int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
@ -224,10 +140,7 @@ int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
ball->firstChildIndex = -1; ball->firstChildIndex = -1;
ball->childrenIndices = 0; ball->childrenIndices = 0;
ball->notFitHull = 0; ball->notFitHull = 0;
if (0 != arraySetLength(bm->ballArray, index + 1)) { arraySetLength(bm->ballArray, index + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
}
memcpy(arrayGetItem(bm->ballArray, index), ball, sizeof(bmeshBall)); memcpy(arrayGetItem(bm->ballArray, index), ball, sizeof(bmeshBall));
if (BMESH_BALL_TYPE_ROOT == ball->type) { if (BMESH_BALL_TYPE_ROOT == ball->type) {
bm->rootBallIndex = index; bm->rootBallIndex = index;
@ -235,41 +148,26 @@ int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
return index; return index;
} }
static int bmeshAddChildBallRelation(bmesh *bm, int parentBallIndex, static void bmeshAddChildBallRelation(bmesh *bm, int parentBallIndex,
int childBallIndex) { int childBallIndex) {
bmeshBall *parentBall = bmeshGetBall(bm, parentBallIndex); bmeshBall *parentBall = bmeshGetBall(bm, parentBallIndex);
bmeshBallIndex *indexItem; bmeshBallIndex *indexItem;
int newChildIndex = arrayGetLength(bm->indexArray); int newChildIndex = arrayGetLength(bm->indexArray);
if (0 != arraySetLength(bm->indexArray, newChildIndex + 1)) { arraySetLength(bm->indexArray, newChildIndex + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); indexItem = arrayGetItem(bm->indexArray, newChildIndex);
return -1;
}
indexItem = (bmeshBallIndex *)arrayGetItem(bm->indexArray, newChildIndex);
indexItem->ballIndex = childBallIndex; indexItem->ballIndex = childBallIndex;
indexItem->nextChildIndex = parentBall->firstChildIndex; indexItem->nextChildIndex = parentBall->firstChildIndex;
parentBall->firstChildIndex = newChildIndex; parentBall->firstChildIndex = newChildIndex;
parentBall->childrenIndices++; parentBall->childrenIndices++;
return 0;
} }
int bmeshAddBone(bmesh *bm, bmeshBone *bone) { int bmeshAddBone(bmesh *bm, bmeshBone *bone) {
int index = arrayGetLength(bm->boneArray); int index = arrayGetLength(bm->boneArray);
bone->index = index; bone->index = index;
if (0 != arraySetLength(bm->boneArray, index + 1)) { arraySetLength(bm->boneArray, index + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
}
memcpy(arrayGetItem(bm->boneArray, index), bone, sizeof(bmeshBone)); memcpy(arrayGetItem(bm->boneArray, index), bone, sizeof(bmeshBone));
if (0 != bmeshAddChildBallRelation(bm, bone->firstBallIndex, bmeshAddChildBallRelation(bm, bone->firstBallIndex, bone->secondBallIndex);
bone->secondBallIndex)) { bmeshAddChildBallRelation(bm, bone->secondBallIndex, bone->firstBallIndex);
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
return -1;
}
if (0 != bmeshAddChildBallRelation(bm, bone->secondBallIndex,
bone->firstBallIndex)) {
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
return -1;
}
return index; return index;
} }
@ -283,79 +181,21 @@ static int bmeshAddInbetweenBallBetween(bmesh *bm,
secondBall->radius * frac; secondBall->radius * frac;
vec3Lerp(&firstBall->position, &secondBall->position, frac, vec3Lerp(&firstBall->position, &secondBall->position, frac,
&newBall.position); &newBall.position);
if (-1 == bmeshAddBall(bm, &newBall)) { bmeshAddBall(bm, &newBall);
fprintf(stderr, "%s:bmeshAddBall failed.\n", __FUNCTION__); bmeshAddChildBallRelation(bm, parentBallIndex, newBall.index);
return -1;
}
if (-1 == bmeshAddChildBallRelation(bm, parentBallIndex, newBall.index)) {
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
return -1;
}
return newBall.index; return newBall.index;
} }
/*
static int bmeshGenerateBallCrossSection(bmesh *bm, bmeshBall *ball,
vec3 *boneDirection, vec3 *localYaxis, vec3 *localZaxis) {
//int i;
//quad q;
vec3 z, y;
//vec3Scale(localYaxis, ball->radius, &y);
//vec3Scale(localZaxis, ball->radius, &z);
vec3Sub(&ball->position, &y, &q.pt[0]);
vec3Add(&q.pt[0], &z, &q.pt[0]);
vec3Sub(&ball->position, &y, &q.pt[1]);
vec3Sub(&q.pt[1], &z, &q.pt[1]);
vec3Add(&ball->position, &y, &q.pt[2]);
vec3Sub(&q.pt[2], &z, &q.pt[2]);
vec3Add(&ball->position, &y, &q.pt[3]);
vec3Add(&q.pt[3], &z, &q.pt[3]);
ball->crossSection = q;
ball->boneDirection = *boneDirection;
if (-1 == bmeshAddQuad(bm, &q)) {
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
return -1;
}
if (connectWithQuad >= 0) {
for (i = 0; i < 4; ++i) {
quad face;
quad *lastQ = bmeshGetQuad(bm, connectWithQuad);
face.pt[0].x = lastQ->pt[(0 + i) % 4].x;
face.pt[0].y = lastQ->pt[(0 + i) % 4].y;
face.pt[0].z = lastQ->pt[(0 + i) % 4].z;
face.pt[1].x = q.pt[(0 + i) % 4].x;
face.pt[1].y = q.pt[(0 + i) % 4].y;
face.pt[1].z = q.pt[(0 + i) % 4].z;
face.pt[2].x = q.pt[(1 + i) % 4].x;
face.pt[2].y = q.pt[(1 + i) % 4].y;
face.pt[2].z = q.pt[(1 + i) % 4].z;
face.pt[3].x = lastQ->pt[(1 + i) % 4].x;
face.pt[3].y = lastQ->pt[(1 + i) % 4].y;
face.pt[3].z = lastQ->pt[(1 + i) % 4].z;
if (-1 == bmeshAddQuad(bm, &face)) {
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
return -1;
}
}
}
return 0;
}*/
static void generateYZfromBoneDirection(vec3 *boneDirection, static void generateYZfromBoneDirection(vec3 *boneDirection,
vec3 *localYaxis, vec3 *localZaxis) { vec3 *localYaxis, vec3 *localZaxis) {
vec3 worldYaxis = {0, 1, 0}; vec3 worldYaxis = {0, 1, 0};
vec3 worldXaxis = {1, 0, 0}; vec3CrossProduct(&worldYaxis, boneDirection, localYaxis);
//if (0 == vec3Angle(boneDirection, &worldYaxis)) {
// vec3CrossProduct(&worldXaxis, boneDirection, localYaxis);
//} else {
vec3CrossProduct(&worldYaxis, boneDirection, localYaxis);
//}
vec3Normalize(localYaxis); vec3Normalize(localYaxis);
vec3CrossProduct(localYaxis, boneDirection, localZaxis); vec3CrossProduct(localYaxis, boneDirection, localZaxis);
vec3Normalize(localZaxis); vec3Normalize(localZaxis);
} }
static int bmeshGenerateInbetweenBallsBetween(bmesh *bm, static void bmeshGenerateInbetweenBallsBetween(bmesh *bm,
int firstBallIndex, int secondBallIndex) { int firstBallIndex, int secondBallIndex) {
float step; float step;
float distance; float distance;
@ -368,8 +208,9 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
bmeshBall *secondBall = bmeshGetBall(bm, secondBallIndex); bmeshBall *secondBall = bmeshGetBall(bm, secondBallIndex);
bmeshBall *newBall; bmeshBall *newBall;
float intvalDist; float intvalDist;
if (secondBall->roundColor == bm->roundColor) { if (secondBall->roundColor == bm->roundColor) {
return 0; return;
} }
vec3Sub(&firstBall->position, &secondBall->position, &boneDirection); vec3Sub(&firstBall->position, &secondBall->position, &boneDirection);
@ -392,9 +233,6 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
float frac = offset / distance; float frac = offset / distance;
parentBallIndex = bmeshAddInbetweenBallBetween(bm, parentBallIndex = bmeshAddInbetweenBallBetween(bm,
firstBall, secondBall, frac, parentBallIndex); firstBall, secondBall, frac, parentBallIndex);
if (-1 == parentBallIndex) {
return -1;
}
newBall = bmeshGetBall(bm, parentBallIndex); newBall = bmeshGetBall(bm, parentBallIndex);
newBall->localYaxis = localYaxis; newBall->localYaxis = localYaxis;
newBall->localZaxis = localZaxis; newBall->localZaxis = localZaxis;
@ -404,20 +242,13 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
} else if (distance > step) { } else if (distance > step) {
parentBallIndex = bmeshAddInbetweenBallBetween(bm, firstBall, secondBall, parentBallIndex = bmeshAddInbetweenBallBetween(bm, firstBall, secondBall,
0.5, parentBallIndex); 0.5, parentBallIndex);
if (-1 == parentBallIndex) {
return -1;
}
newBall = bmeshGetBall(bm, parentBallIndex); newBall = bmeshGetBall(bm, parentBallIndex);
newBall->localYaxis = localYaxis; newBall->localYaxis = localYaxis;
newBall->localZaxis = localZaxis; newBall->localZaxis = localZaxis;
newBall->boneDirection = normalizedBoneDirection; newBall->boneDirection = normalizedBoneDirection;
} }
} }
if (-1 == bmeshAddChildBallRelation(bm, parentBallIndex, secondBallIndex)) { bmeshAddChildBallRelation(bm, parentBallIndex, secondBallIndex);
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
return -1;
}
return 0;
} }
bmeshBall *bmeshGetBallFirstChild(bmesh *bm, bmeshBall *ball, bmeshBall *bmeshGetBallFirstChild(bmesh *bm, bmeshBall *ball,
@ -435,7 +266,7 @@ bmeshBall *bmeshGetBallNextChild(bmesh *bm, bmeshBall *ball,
if (-1 == *iterator) { if (-1 == *iterator) {
return 0; return 0;
} }
indexItem = (bmeshBallIndex *)arrayGetItem(bm->indexArray, *iterator); indexItem = arrayGetItem(bm->indexArray, *iterator);
*iterator = indexItem->nextChildIndex; *iterator = indexItem->nextChildIndex;
return bmeshGetBall(bm, indexItem->ballIndex); return bmeshGetBall(bm, indexItem->ballIndex);
} }
@ -447,7 +278,7 @@ bmeshBall *bmeshGetRootBall(bmesh *bm) {
return bmeshGetBall(bm, bm->rootBallIndex); return bmeshGetBall(bm, bm->rootBallIndex);
} }
static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) { static void bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
bmeshBallIterator iterator; bmeshBallIterator iterator;
int ballIndex; int ballIndex;
bmeshBall *parent; bmeshBall *parent;
@ -456,8 +287,9 @@ static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
parent = bmeshGetBall(bm, parentBallIndex); parent = bmeshGetBall(bm, parentBallIndex);
if (parent->roundColor == bm->roundColor) { if (parent->roundColor == bm->roundColor) {
return 0; return;
} }
parent->roundColor = bm->roundColor; parent->roundColor = bm->roundColor;
// //
@ -471,26 +303,11 @@ static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
oldChildrenIndices = parent->childrenIndices; oldChildrenIndices = parent->childrenIndices;
parent->childrenIndices = 0; parent->childrenIndices = 0;
for (; for (; ball; ball = bmeshGetBallNextChild(bm, parent, &iterator)) {
ball;
ball = bmeshGetBallNextChild(bm, parent, &iterator)) {
ballIndex = ball->index; ballIndex = ball->index;
if (0 != bmeshGenerateInbetweenBallsBetween(bm, parentBallIndex, bmeshGenerateInbetweenBallsBetween(bm, parentBallIndex, ballIndex);
ballIndex)) { bmeshGenerateInbetweenBallsFrom(bm, ballIndex);
fprintf(stderr,
"%s:bmeshGenerateInbetweenBallsBetween failed(parentBallIndex:%d).\n",
__FUNCTION__, parentBallIndex);
return -1;
}
if (0 != bmeshGenerateInbetweenBallsFrom(bm, ballIndex)) {
fprintf(stderr,
"%s:bmeshGenerateInbetweenBallsFrom failed(ballIndex:%d).\n",
__FUNCTION__, ballIndex);
return -1;
}
} }
return 0;
} }
int bmeshGenerateInbetweenBalls(bmesh *bm) { int bmeshGenerateInbetweenBalls(bmesh *bm) {
@ -499,7 +316,8 @@ int bmeshGenerateInbetweenBalls(bmesh *bm) {
return -1; return -1;
} }
bm->roundColor++; bm->roundColor++;
return bmeshGenerateInbetweenBallsFrom(bm, bm->rootBallIndex); bmeshGenerateInbetweenBallsFrom(bm, bm->rootBallIndex);
return 0;
} }
int bmeshGetQuadNum(bmesh *bm) { int bmeshGetQuadNum(bmesh *bm) {
@ -507,25 +325,21 @@ int bmeshGetQuadNum(bmesh *bm) {
} }
quad *bmeshGetQuad(bmesh *bm, int index) { quad *bmeshGetQuad(bmesh *bm, int index) {
return (quad *)arrayGetItem(bm->quadArray, index); return arrayGetItem(bm->quadArray, index);
} }
int bmeshAddQuad(bmesh *bm, quad *q) { int bmeshAddQuad(bmesh *bm, quad *q) {
int index = arrayGetLength(bm->quadArray); int index = arrayGetLength(bm->quadArray);
if (0 != arraySetLength(bm->quadArray, index + 1)) { arraySetLength(bm->quadArray, index + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
}
memcpy(arrayGetItem(bm->quadArray, index), q, sizeof(quad)); memcpy(arrayGetItem(bm->quadArray, index), q, sizeof(quad));
return index; return index;
} }
static int bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) { static void bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
int result = 0;
bmeshBallIterator iterator; bmeshBallIterator iterator;
bmeshBall *child = 0; bmeshBall *child = 0;
if (bm->roundColor == ball->roundColor) { if (bm->roundColor == ball->roundColor) {
return 0; return;
} }
ball->roundColor = bm->roundColor; ball->roundColor = bm->roundColor;
if (BMESH_BALL_TYPE_KEY == ball->type) { if (BMESH_BALL_TYPE_KEY == ball->type) {
@ -555,18 +369,14 @@ static int bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) { child = bmeshGetBallNextChild(bm, ball, &iterator)) {
result = bmeshSweepFrom(bm, ball, child); bmeshSweepFrom(bm, ball, child);
if (0 != result) {
fprintf(stderr, "%s:bmeshSweepFrom failed.\n", __FUNCTION__);
return result;
}
} }
return result;
} }
int bmeshSweep(bmesh *bm) { int bmeshSweep(bmesh *bm) {
bm->roundColor++; bm->roundColor++;
return bmeshSweepFrom(bm, 0, bmeshGetRootBall(bm)); bmeshSweepFrom(bm, 0, bmeshGetRootBall(bm));
return 0;
} }
static int isDistanceEnoughForConvexHull(bmeshBall *root, static int isDistanceEnoughForConvexHull(bmeshBall *root,
@ -609,7 +419,7 @@ static bmeshBall *bmeshFindParentBallForConvexHull(bmesh *bm, bmeshBall *root,
bm->parentBallStack[depth - 1]); bm->parentBallStack[depth - 1]);
} }
static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull, static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
bmeshBall **outmostBall, int *outmostBallFirstVertexIndex) { bmeshBall **outmostBall, int *outmostBallFirstVertexIndex) {
vec3 z, y; vec3 z, y;
quad q; quad q;
@ -635,11 +445,6 @@ static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
ballForConvexHull->index, 2); ballForConvexHull->index, 2);
vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3], vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3],
ballForConvexHull->index, 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 (*outmostBall) {
if (ballForConvexHull->radius > (*outmostBall)->radius) { if (ballForConvexHull->radius > (*outmostBall)->radius) {
@ -652,14 +457,8 @@ static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
*outmostBall = ballForConvexHull; *outmostBall = ballForConvexHull;
*outmostBallFirstVertexIndex = vertexIndex[0]; *outmostBallFirstVertexIndex = vertexIndex[0];
} }
return 0;
} }
#include "osutil.h"
int showFaceIndex = 10000000;
static long long lastShowFaceIndexIncTime = 0;
static convexHull *createConvexHullForBall(bmesh *bm, int depth, static convexHull *createConvexHullForBall(bmesh *bm, int depth,
bmeshBall *ball, int *needRetry) { bmeshBall *ball, int *needRetry) {
convexHull *hull; convexHull *hull;
@ -676,74 +475,33 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
*needRetry = 0; *needRetry = 0;
ballPtrArray = arrayCreate(sizeof(bmeshBall *)); ballPtrArray = arrayCreate(sizeof(bmeshBall *));
if (!ballPtrArray) {
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
return 0;
}
hull = convexHullCreate(); hull = convexHullCreate();
if (!hull) {
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
return 0;
}
if (BMESH_BALL_TYPE_KEY == ball->type) { if (BMESH_BALL_TYPE_KEY == ball->type) {
bmeshBall reduceBall = *ball; bmeshBall reduceBall = *ball;
reduceBall.radius *= 0.4; reduceBall.radius *= 0.4;
if (-1 == addBallToHull(hull, &reduceBall, addBallToHull(hull, &reduceBall, &outmostBall,
&outmostBall, &outmostBallFirstVertexIndex)) { &outmostBallFirstVertexIndex);
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
} }
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) { child = bmeshGetBallNextChild(bm, ball, &iterator)) {
ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child); ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child);
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray); ballPtr = arrayNewItem(ballPtrArray);
if (!ballPtr) {
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
*ballPtr = ballForConvexHull; *ballPtr = ballForConvexHull;
if (-1 == addBallToHull(hull, ballForConvexHull, addBallToHull(hull, ballForConvexHull, &outmostBall,
&outmostBall, &outmostBallFirstVertexIndex)) { &outmostBallFirstVertexIndex);
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
} }
if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) { if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) {
ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1, ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1,
bm->parentBallStack[depth - 1]); bm->parentBallStack[depth - 1]);
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray); ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
if (!ballPtr) {
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
*ballPtr = ballForConvexHull; *ballPtr = ballForConvexHull;
if (-1 == addBallToHull(hull, ballForConvexHull, addBallToHull(hull, ballForConvexHull, &outmostBall,
&outmostBall, &outmostBallFirstVertexIndex)) { &outmostBallFirstVertexIndex);
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
} }
if (outmostBall) { if (outmostBall) {
if (-1 == convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0, convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0,
outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2)) { outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2);
fprintf(stderr, "%s:convexHullAddTodo failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
} }
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) { for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
@ -751,12 +509,7 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
ballItem->flagForHull = 0; ballItem->flagForHull = 0;
} }
if (-1 == convexHullGenerate(hull)) { convexHullGenerate(hull);
fprintf(stderr, "%s:convexHullGenerate failed.\n", __FUNCTION__);
arrayDestroy(ballPtrArray);
convexHullDestroy(hull);
return 0;
}
convexHullUnifyNormals(hull, &ball->position); convexHullUnifyNormals(hull, &ball->position);
convexHullMergeTriangles(hull); convexHullMergeTriangles(hull);
@ -764,7 +517,7 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
for (i = 0; i < convexHullGetFaceNum(hull); ++i) { for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
convexHullFace *f = (convexHullFace *)convexHullGetFace(hull, i); convexHullFace *f = (convexHullFace *)convexHullGetFace(hull, i);
if (-1 != f->plane) { if (-1 != f->plane) {
bmeshBall *ballItem = (bmeshBall *)arrayGetItem(bm->ballArray, f->plane); bmeshBall *ballItem = arrayGetItem(bm->ballArray, f->plane);
ballItem->flagForHull = 1; ballItem->flagForHull = 1;
f->vertexNum = 0; f->vertexNum = 0;
} }
@ -804,13 +557,14 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
return hull; return hull;
} }
static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) { static void bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
bmeshBallIterator iterator; bmeshBallIterator iterator;
bmeshBall *child; bmeshBall *child;
int result = 0;
if (bm->roundColor == ball->roundColor) { if (bm->roundColor == ball->roundColor) {
return 0; return;
} }
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) { if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
bm->parentBallStack[depth] = ball; bm->parentBallStack[depth] = ball;
} }
@ -841,19 +595,13 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
q.pt[1] = convexHullGetVertex(hull, face->u.q.indices[1])->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[2] = convexHullGetVertex(hull, face->u.q.indices[2])->pt;
q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt; q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt;
result = bmeshAddQuadToModel(bm, &q); bmeshAddQuadToModel(bm, &q);
if (-1 == result) {
break;
}
} else if (3 == face->vertexNum) { } else if (3 == face->vertexNum) {
triangle t; triangle t;
t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt; t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt; t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt; t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
result = bmeshAddTriangleToModel(bm, &t); bmeshAddTriangleToModel(bm, &t);
if (-1 == result) {
break;
}
} }
} }
convexHullDestroy(hull); convexHullDestroy(hull);
@ -863,19 +611,15 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) { child = bmeshGetBallNextChild(bm, ball, &iterator)) {
result = bmeshStichFrom(bm, depth + 1, child); bmeshStichFrom(bm, depth + 1, child);
if (0 != result) {
fprintf(stderr, "%s:bmeshSweepFrom failed.\n", __FUNCTION__);
return result;
}
} }
return result;
} }
int bmeshStitch(bmesh *bm) { int bmeshStitch(bmesh *bm) {
bm->roundColor++; bm->roundColor++;
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack)); memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
return bmeshStichFrom(bm, 0, bmeshGetRootBall(bm)); bmeshStichFrom(bm, 0, bmeshGetRootBall(bm));
return 0;
} }
static void rollQuadVertexs(quad *q) { static void rollQuadVertexs(quad *q) {
@ -938,11 +682,7 @@ static int bmeshAddWallsBetweenQuadsToModel(bmesh *bm, vec3 *origin, quad *q1,
wall.pt[j] = oldWall.pt[3 - j]; wall.pt[j] = oldWall.pt[3 - j];
} }
} }
result = bmeshAddQuadToModel(bm, &wall); bmeshAddQuadToModel(bm, &wall);
if (-1 == result) {
break;
}
//drawQuad(&wall);
} }
return result; return result;
} }
@ -960,15 +700,15 @@ static bmeshBall *bmeshFindChildBallForInbetweenMesh(bmesh *bm, bmeshBall *ball)
return bmeshFindChildBallForInbetweenMesh(bm, child); return bmeshFindChildBallForInbetweenMesh(bm, child);
} }
static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth, static void bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
bmeshBall *ball) { bmeshBall *ball) {
int result = 0;
bmeshBallIterator iterator; bmeshBallIterator iterator;
bmeshBall *child = 0; bmeshBall *child = 0;
bmeshBall *parent; bmeshBall *parent;
quad currentFace, childFace; quad currentFace, childFace;
if (bm->roundColor == ball->roundColor) { if (bm->roundColor == ball->roundColor) {
return 0; return;
} }
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) { if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
bm->parentBallStack[depth] = ball; bm->parentBallStack[depth] = ball;
@ -986,10 +726,7 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
calculateBallQuad(&fakeBall, &childFace); calculateBallQuad(&fakeBall, &childFace);
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace, bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace); &childFace);
result = bmeshAddQuadToModel(bm, &childFace); bmeshAddQuadToModel(bm, &childFace);
if (-1 == result) {
return result;
}
drawQuad(&childFace); drawQuad(&childFace);
} }
} }
@ -1002,11 +739,8 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
//} else { //} else {
child = bmeshFindChildBallForInbetweenMesh(bm, child); child = bmeshFindChildBallForInbetweenMesh(bm, child);
calculateBallQuad(child, &childFace); calculateBallQuad(child, &childFace);
result = bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace, bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace); &childFace);
if (-1 == result) {
return result;
}
//} //}
ball->meshGenerated = 1; ball->meshGenerated = 1;
child->meshGenerated = 1; child->meshGenerated = 1;
@ -1015,20 +749,15 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) { child = bmeshGetBallNextChild(bm, ball, &iterator)) {
result = bmeshGenerateInbetweenMeshFrom(bm, depth + 1, child); bmeshGenerateInbetweenMeshFrom(bm, depth + 1, child);
if (0 != result) {
fprintf(stderr, "%s:bmeshGenerateInbetweenMeshFrom failed.\n",
__FUNCTION__);
return result;
}
} }
return result;
} }
int bmeshGenerateInbetweenMesh(bmesh *bm) { int bmeshGenerateInbetweenMesh(bmesh *bm) {
bm->roundColor++; bm->roundColor++;
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack)); memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
return bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(bm)); bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(bm));
return 0;
} }
int bmeshGenerate(bmesh *bm) { int bmeshGenerate(bmesh *bm) {

View File

@ -2,9 +2,10 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "dmemory.h"
#include "convexhull.h" #include "convexhull.h"
#include "array.h" #include "array.h"
#include "hashtable.h" #include "dict.h"
#include "draw.h" #include "draw.h"
// //
@ -32,11 +33,9 @@ struct convexHull {
array *faceArray; array *faceArray;
int nextTodoIndex; int nextTodoIndex;
unsigned int *openEdgeProcessedMap; unsigned int *openEdgeProcessedMap;
hashtable *face3Hashtable; dict *face3Dict;
face3 findFace3;
array *edgeArray; array *edgeArray;
hashtable *edgeHashtable; dict *edgeDict;
edge findEdge;
}; };
typedef struct { typedef struct {
@ -49,46 +48,26 @@ static int cantorPair(int k1, int k2) {
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2; return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
} }
face3 *convexHullGetFaceByHashtableParam(void *userData, const void *node) {
convexHull *hull = (convexHull *)userData;
int index = (char *)node - (char *)0;
if (0 == index) {
return &hull->findFace3;
}
return (face3 *)arrayGetItem(hull->faceArray, index - 1);
}
static int face3Hash(void *userData, const void *node) { static int face3Hash(void *userData, const void *node) {
face3 *face = convexHullGetFaceByHashtableParam(userData, node); const face3 *face = node;
return cantorPair(cantorPair(face->indices[0], face->indices[1]), return cantorPair(cantorPair(face->indices[0], face->indices[1]),
face->indices[2]); face->indices[2]);
} }
edge *convexHullGetEdgeByHashtableParam(void *userData, const void *node) {
convexHull *hull = (convexHull *)userData;
int index = (char *)node - (char *)0;
if (0 == index) {
return &hull->findEdge;
}
return (edge *)arrayGetItem(hull->edgeArray, index - 1);
}
static int edgeHash(void *userData, const void *node) { static int edgeHash(void *userData, const void *node) {
edge *e = convexHullGetEdgeByHashtableParam(userData, node); const edge *e = node;
return e->p1 < e->p2 ? cantorPair(e->p1, e->p2) : cantorPair(e->p2, e->p1); return e->p1 < e->p2 ? cantorPair(e->p1, e->p2) : cantorPair(e->p2, e->p1);
} }
static int face3Compare(void *userData, const void *node1, static int face3Compare(void *userData, const void *node1,
const void *node2) { const void *node2) {
face3 *f1 = convexHullGetFaceByHashtableParam(userData, node1); return memcmp(node1, node2, sizeof(face3));
face3 *f2 = convexHullGetFaceByHashtableParam(userData, node2);
return memcmp(f1, f2, sizeof(face3));
} }
static int edgeCompare(void *userData, const void *node1, static int edgeCompare(void *userData, const void *node1,
const void *node2) { const void *node2) {
edge *e1 = convexHullGetEdgeByHashtableParam(userData, node1); const edge *e1 = node1;
edge *e2 = convexHullGetEdgeByHashtableParam(userData, node2); const edge *e2 = node2;
if ((e1->p1 == e2->p1 && e1->p2 == e2->p2) || if ((e1->p1 == e2->p1 && e1->p2 == e2->p2) ||
(e1->p2 == e2->p1 && e1->p1 == e2->p2)) { (e1->p2 == e2->p1 && e1->p1 == e2->p2)) {
return 0; return 0;
@ -97,74 +76,34 @@ static int edgeCompare(void *userData, const void *node1,
} }
convexHull *convexHullCreate(void) { convexHull *convexHullCreate(void) {
convexHull *hull = (convexHull *)calloc(1, sizeof(convexHull)); convexHull *hull = dcalloc(1, sizeof(convexHull));
if (!hull) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
hull->vertexArray = arrayCreate(sizeof(convexHullVertex)); hull->vertexArray = arrayCreate(sizeof(convexHullVertex));
if (!hull->vertexArray) {
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
hull->todoArray = arrayCreate(sizeof(todo)); hull->todoArray = arrayCreate(sizeof(todo));
if (!hull->todoArray) {
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
hull->faceArray = arrayCreate(sizeof(convexHullFace)); hull->faceArray = arrayCreate(sizeof(convexHullFace));
if (!hull->faceArray) { hull->face3Dict = dictCreate(hull->faceArray, FACE3_HASHTABLE_SIZE,
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
hull->face3Hashtable = hashtableCreate(FACE3_HASHTABLE_SIZE,
face3Hash, face3Compare, hull); face3Hash, face3Compare, hull);
if (!hull->face3Hashtable) {
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
hull->edgeArray = arrayCreate(sizeof(edge)); hull->edgeArray = arrayCreate(sizeof(edge));
if (!hull->edgeArray) { hull->edgeDict = dictCreate(hull->edgeArray, EDGE_HASHTABLE_SIZE,
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
hull->edgeHashtable = hashtableCreate(EDGE_HASHTABLE_SIZE,
edgeHash, edgeCompare, hull); edgeHash, edgeCompare, hull);
if (!hull->edgeHashtable) {
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
convexHullDestroy(hull);
return 0;
}
return hull; return hull;
} }
edge *convexHullFindEdge(convexHull *hull, int p1, int p2) { edge *convexHullFindEdge(convexHull *hull, int p1, int p2) {
int index; edge findEdge;
hull->findEdge.p1 = p1; findEdge.p1 = p1;
hull->findEdge.p2 = p2; findEdge.p2 = p2;
index = (char *)hashtableGet(hull->edgeHashtable, 0) - (char *)0; return dictFind(hull->edgeDict, &findEdge);
if (0 == index) {
return 0;
}
return arrayGetItem(hull->edgeArray, index - 1);
} }
int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill, void convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
int face) { int face) {
edge *e = convexHullFindEdge(hull, p1, p2); edge findEdge;
edge *e;
findEdge.p1 = p1;
findEdge.p2 = p2;
e = dictFind(hull->edgeDict, &findEdge);
if (!e) { if (!e) {
int newIndex = arrayGetLength(hull->edgeArray); e = dictGetClear(hull->edgeDict, &findEdge);
if (0 != arraySetLength(hull->edgeArray, newIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
}
e = (edge *)arrayGetItem(hull->edgeArray, newIndex);
memset(e, 0, sizeof(edge));
e->p1 = p1; e->p1 = p1;
e->p2 = p2; e->p2 = p2;
e->hill1 = hill; e->hill1 = hill;
@ -174,17 +113,12 @@ int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
vec3Normal((vec3 *)arrayGetItem(hull->vertexArray, e->p1), vec3Normal((vec3 *)arrayGetItem(hull->vertexArray, e->p1),
(vec3 *)arrayGetItem(hull->vertexArray, e->p2), (vec3 *)arrayGetItem(hull->vertexArray, e->p2),
(vec3 *)arrayGetItem(hull->vertexArray, e->hill1), &e->hill1Normal); (vec3 *)arrayGetItem(hull->vertexArray, e->hill1), &e->hill1Normal);
if (0 != hashtableInsert(hull->edgeHashtable, (char *)0 + newIndex + 1)) { return;
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
return -1;
}
return 0;
} }
assert(-1 == e->hill2); assert(-1 == e->hill2);
assert(-1 == e->face2); assert(-1 == e->face2);
e->hill2 = hill; e->hill2 = hill;
e->face2 = face; e->face2 = face;
return 0;
} }
void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex, void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
@ -212,41 +146,20 @@ int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
int orderOnPlane) { int orderOnPlane) {
convexHullVertex *vtx; convexHullVertex *vtx;
int newVertex = arrayGetLength(hull->vertexArray); int newVertex = arrayGetLength(hull->vertexArray);
if (0 != arraySetLength(hull->vertexArray, newVertex + 1)) { arraySetLength(hull->vertexArray, newVertex + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); vtx = arrayGetItem(hull->vertexArray, newVertex);
return -1;
}
vtx = (convexHullVertex *)arrayGetItem(hull->vertexArray, newVertex);
vtx->plane = plane; vtx->plane = plane;
vtx->orderOnPlane = orderOnPlane; vtx->orderOnPlane = orderOnPlane;
vtx->pt = *vertex; vtx->pt = *vertex;
return newVertex; return newVertex;
} }
int convexHullAddTodoNoCheck(convexHull *hull, int firstVertex, void convexHullAddTodoNoCheck(convexHull *hull, int firstVertex,
int secondVertex, int thirdVertex) { int secondVertex, int thirdVertex) {
todo *t; todo *t = arrayNewItemClear(hull->todoArray);
int newEdge = arrayGetLength(hull->todoArray);
if (firstVertex < 0 || secondVertex < 0) {
fprintf(stderr, "%s:Invalid params(firstVertex:%d secondVertex:%d).\n",
__FUNCTION__, firstVertex, secondVertex);
return -1;
}
if (0 != arraySetLength(hull->todoArray, newEdge + 1)) {
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return -1;
}
t = (todo *)arrayGetItem(hull->todoArray, newEdge);
memset(t, 0, sizeof(todo));
t->firstVertex = firstVertex; t->firstVertex = firstVertex;
t->secondVertex = secondVertex; t->secondVertex = secondVertex;
t->thirdVertex = thirdVertex; t->thirdVertex = thirdVertex;
return 0;
}
static int isInAdjacentOrder(int order1, int order2) {
return ((order1 + 1) % 4 == order2 ||
(order2 + 1) % 4 == order1);
} }
static int sortface(const void *first, const void *second) { static int sortface(const void *first, const void *second) {
@ -255,7 +168,7 @@ static int sortface(const void *first, const void *second) {
return *firstIndex - *secondIndex; return *firstIndex - *secondIndex;
} }
int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex, void convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
int thirdVertex) { int thirdVertex) {
face3 *tri; face3 *tri;
convexHullVertex *vtx1; convexHullVertex *vtx1;
@ -263,62 +176,35 @@ int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
convexHullVertex *vtx3; convexHullVertex *vtx3;
int newTri; int newTri;
int facePlane = -1; int facePlane = -1;
face3 findFace3;
vtx1 = (convexHullVertex *)arrayGetItem(hull->vertexArray, firstVertex); vtx1 = arrayGetItem(hull->vertexArray, firstVertex);
vtx2 = (convexHullVertex *)arrayGetItem(hull->vertexArray, secondVertex); vtx2 = arrayGetItem(hull->vertexArray, secondVertex);
vtx3 = (convexHullVertex *)arrayGetItem(hull->vertexArray, thirdVertex); vtx3 = arrayGetItem(hull->vertexArray, thirdVertex);
if (vtx1->plane == vtx2->plane && vtx1->plane == vtx3->plane) { if (vtx1->plane == vtx2->plane && vtx1->plane == vtx3->plane) {
facePlane = vtx1->plane; facePlane = vtx1->plane;
} }
/* memset(&findFace3, 0, sizeof(findFace3));
if (vtx1->plane == vtx2->plane) { findFace3.indices[0] = firstVertex;
if (!isInAdjacentOrder(vtx1->orderOnPlane, vtx2->orderOnPlane)) { findFace3.indices[1] = secondVertex;
return 0; findFace3.indices[2] = thirdVertex;
} qsort(&findFace3.indices, 3, sizeof(findFace3.indices[0]), sortface);
} if (!dictFind(hull->face3Dict, &findFace3)) {
if (vtx1->plane == vtx3->plane) {
if (!isInAdjacentOrder(vtx1->orderOnPlane, vtx3->orderOnPlane)) {
return 0;
}
}
if (vtx2->plane == vtx3->plane) {
if (!isInAdjacentOrder(vtx2->orderOnPlane, vtx3->orderOnPlane)) {
return 0;
}
}*/
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->faceArray); newTri = arrayGetLength(hull->faceArray);
if (0 != arraySetLength(hull->faceArray, newTri + 1)) { tri = dictGetClear(hull->face3Dict, &findFace3);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); *tri = findFace3;
return -1;
}
tri = (face3 *)arrayGetItem(hull->faceArray, newTri);
((convexHullFace *)tri)->vertexNum = 3; ((convexHullFace *)tri)->vertexNum = 3;
((convexHullFace *)tri)->plane = facePlane; ((convexHullFace *)tri)->plane = facePlane;
*tri = hull->findFace3;
if (0 != hashtableInsert(hull->face3Hashtable,
(char *)0 + newTri + 1)) {
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
return -1;
}
convexHullAddEdge(hull, firstVertex, secondVertex, thirdVertex, newTri); convexHullAddEdge(hull, firstVertex, secondVertex, thirdVertex, newTri);
convexHullAddEdge(hull, secondVertex, thirdVertex, firstVertex, newTri); convexHullAddEdge(hull, secondVertex, thirdVertex, firstVertex, newTri);
convexHullAddEdge(hull, thirdVertex, firstVertex, secondVertex, newTri); convexHullAddEdge(hull, thirdVertex, firstVertex, secondVertex, newTri);
} }
return 0;
} }
static void convexHullReleaseForGenerate(convexHull *hull) { static void convexHullReleaseForGenerate(convexHull *hull) {
free(hull->openEdgeProcessedMap); dfree(hull->openEdgeProcessedMap);
hull->openEdgeProcessedMap = 0; hull->openEdgeProcessedMap = 0;
} }
@ -327,31 +213,26 @@ void convexHullDestroy(convexHull *hull) {
arrayDestroy(hull->todoArray); arrayDestroy(hull->todoArray);
arrayDestroy(hull->faceArray); arrayDestroy(hull->faceArray);
arrayDestroy(hull->edgeArray); arrayDestroy(hull->edgeArray);
hashtableDestroy(hull->edgeHashtable); dictDestroy(hull->edgeDict);
hashtableDestroy(hull->face3Hashtable); dictDestroy(hull->face3Dict);
convexHullReleaseForGenerate(hull); convexHullReleaseForGenerate(hull);
free(hull); dfree(hull);
} }
static int convexHullPrepareForGenerate(convexHull *hull) { static void convexHullPrepareForGenerate(convexHull *hull) {
free(hull->openEdgeProcessedMap); dfree(hull->openEdgeProcessedMap);
hull->openEdgeProcessedMap = (unsigned int *)calloc( hull->openEdgeProcessedMap = dcalloc(
arrayGetLength(hull->vertexArray) * arrayGetLength(hull->vertexArray) / arrayGetLength(hull->vertexArray) * arrayGetLength(hull->vertexArray) /
(sizeof(unsigned int) * 8) + 1, (sizeof(unsigned int) * 8) + 1,
sizeof(unsigned int)); sizeof(unsigned int));
if (!hull->openEdgeProcessedMap) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return -1;
}
hull->nextTodoIndex = 0; hull->nextTodoIndex = 0;
return 0;
} }
int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index, int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
int p3Index) { int p3Index) {
vec3 *p1 = (vec3 *)arrayGetItem(hull->vertexArray, p1Index); vec3 *p1 = arrayGetItem(hull->vertexArray, p1Index);
vec3 *p2 = (vec3 *)arrayGetItem(hull->vertexArray, p2Index); vec3 *p2 = arrayGetItem(hull->vertexArray, p2Index);
vec3 *p3 = (vec3 *)arrayGetItem(hull->vertexArray, p3Index); vec3 *p3 = arrayGetItem(hull->vertexArray, p3Index);
vec3 beginNormal; vec3 beginNormal;
vec3 endNormal; vec3 endNormal;
int i; int i;
@ -363,8 +244,7 @@ int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
for (i = 0; i < arrayGetLength(hull->vertexArray); ++i) { for (i = 0; i < arrayGetLength(hull->vertexArray); ++i) {
if (i != p1Index && i != p2Index && i != p3Index) { if (i != p1Index && i != p2Index && i != p3Index) {
vec3Normal(p1, p2, (vec3 *)arrayGetItem(hull->vertexArray, i), vec3Normal(p1, p2, arrayGetItem(hull->vertexArray, i), &endNormal);
&endNormal);
angle = vec3Angle(&beginNormal, &endNormal); angle = vec3Angle(&beginNormal, &endNormal);
if (angle > maxAngle) { if (angle > maxAngle) {
candidateIndex = i; candidateIndex = i;
@ -376,26 +256,18 @@ int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
return candidateIndex; return candidateIndex;
} }
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, void convexHullAddTodo(convexHull *hull, int vertex1, int vertex2,
int vertex3) { int vertex3) {
if (!convexHullOpenEdgeProcessed(hull, vertex1, vertex2)) { if (!convexHullOpenEdgeProcessed(hull, vertex1, vertex2)) {
return convexHullAddTodoNoCheck(hull, vertex1, vertex2, vertex3); convexHullAddTodoNoCheck(hull, vertex1, vertex2, vertex3);
} }
return 0;
} }
extern int showFaceIndex;
static int convexHullCanAddFace3(convexHull *hull, int index1, int index2, static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
int index3) { int index3) {
int i; int i;
int indices[] = {index1, index2, index3}; int indices[] = {index1, index2, index3};
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
drawDebugPrintf("showFaceIndex:%d can add (%d,%d,%d)", showFaceIndex,
index1, index2, index3);
}
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
int p1 = indices[i]; int p1 = indices[i];
int p2 = indices[(i + 1) % 3]; int p2 = indices[(i + 1) % 3];
@ -412,15 +284,6 @@ static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
(vec3 *)arrayGetItem(hull->vertexArray, hill), &normal); (vec3 *)arrayGetItem(hull->vertexArray, hill), &normal);
angle = vec3Angle(&e->hill1Normal, &normal); angle = vec3Angle(&e->hill1Normal, &normal);
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
drawDebugPrintf("showFaceIndex:%d angle:%f (%d,%d,%d)",
showFaceIndex, angle, e->p1, e->p2, e->hill1);
drawSphere((vec3 *)arrayGetItem(hull->vertexArray, 9),
0.1, 36, 24);
drawSphere((vec3 *)arrayGetItem(hull->vertexArray, 6),
0.1, 36, 24);
}
if (angle < 1) { if (angle < 1) {
return 0; return 0;
} }
@ -429,15 +292,12 @@ static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
return 1; return 1;
} }
int convexHullGenerate(convexHull *hull) { void convexHullGenerate(convexHull *hull) {
int index1, index2, index3; int index1, index2, index3;
convexHullReleaseForGenerate(hull); convexHullReleaseForGenerate(hull);
if (0 != convexHullPrepareForGenerate(hull)) { convexHullPrepareForGenerate(hull);
fprintf(stderr, "%s:convexHullPrepareForGenerate failed.\n", __FUNCTION__);
return -1;
}
while (hull->nextTodoIndex < arrayGetLength(hull->todoArray)) { while (hull->nextTodoIndex < arrayGetLength(hull->todoArray)) {
todo *t = (todo *)arrayGetItem(hull->todoArray, hull->nextTodoIndex++); todo *t = arrayGetItem(hull->todoArray, hull->nextTodoIndex++);
index1 = t->firstVertex; index1 = t->firstVertex;
index2 = t->secondVertex; index2 = t->secondVertex;
if (convexHullOpenEdgeProcessed(hull, index1, index2) || if (convexHullOpenEdgeProcessed(hull, index1, index2) ||
@ -452,28 +312,19 @@ int convexHullGenerate(convexHull *hull) {
if (!convexHullCanAddFace3(hull, index1, index2, index3)) { if (!convexHullCanAddFace3(hull, index1, index2, index3)) {
continue; continue;
} }
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
drawDebugPrintf("showFaceIndex:%d added face3 (%d,%d,%d)",
showFaceIndex, index1, index2, index3);
}
convexHullAddFace3(hull, index1, index2, index3); convexHullAddFace3(hull, index1, index2, index3);
convexHullAddTodo(hull, index2, index3, index1); convexHullAddTodo(hull, index2, index3, index1);
convexHullAddTodo(hull, index3, index1, index2); convexHullAddTodo(hull, index3, index1, index2);
} }
return 0;
} }
int convexHullUnifyNormals(convexHull *hull, vec3 *origin) { void convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
int i; int i;
for (i = 0; i < arrayGetLength(hull->faceArray); ++i) { for (i = 0; i < arrayGetLength(hull->faceArray); ++i) {
face3 *triIdx = (face3 *)arrayGetItem( face3 *triIdx = arrayGetItem(hull->faceArray, i);
hull->faceArray, i); convexHullVertex *p1 = arrayGetItem(hull->vertexArray, triIdx->indices[0]);
convexHullVertex *p1 = (convexHullVertex *)arrayGetItem( convexHullVertex *p2 = arrayGetItem(hull->vertexArray, triIdx->indices[1]);
hull->vertexArray, triIdx->indices[0]); convexHullVertex *p3 = arrayGetItem(hull->vertexArray, triIdx->indices[2]);
convexHullVertex *p2 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, triIdx->indices[1]);
convexHullVertex *p3 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, triIdx->indices[2]);
vec3 normal; vec3 normal;
vec3 o2v; vec3 o2v;
vec3Normal(&p1->pt, &p2->pt, &p3->pt, &normal); vec3Normal(&p1->pt, &p2->pt, &p3->pt, &normal);
@ -484,7 +335,6 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
triIdx->indices[2] = index; triIdx->indices[2] = index;
} }
} }
return 0;
} }
static int sortEdgeByScore(const void *first, const void *second) { static int sortEdgeByScore(const void *first, const void *second) {
@ -507,38 +357,20 @@ static void rollTriangleIndices(face3 *face) {
} }
} }
int convexHullMergeTriangles(convexHull *hull) { void convexHullMergeTriangles(convexHull *hull) {
int edgeIndex; int edgeIndex;
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray); for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
++edgeIndex) { ++edgeIndex) {
edge *e = (edge *)arrayGetItem(hull->edgeArray, edgeIndex); edge *e = arrayGetItem(hull->edgeArray, edgeIndex);
if (-1 != e->face1 && -1 != e->face2) { if (-1 != e->face1 && -1 != e->face2) {
//face3 *f1 = (face3 *)arrayGetItem(hull->faceArray, e->face1);
//face3 *f2 = (face3 *)arrayGetItem(hull->faceArray, e->face2);
vec3 f1normal; vec3 f1normal;
vec3 f2normal; vec3 f2normal;
const vec3 yAxis = {0, 1, 0}; const vec3 yAxis = {0, 1, 0};
/* vec3 *v1 = arrayGetItem(hull->vertexArray, e->p1);
convexHullVertex *f1p1 = (convexHullVertex *)arrayGetItem( vec3 *v2 = arrayGetItem(hull->vertexArray, e->p2);
hull->vertexArray, f1->indices[0]); vec3 *vHill1 = arrayGetItem(hull->vertexArray, e->hill1);
convexHullVertex *f1p2 = (convexHullVertex *)arrayGetItem( vec3 *vHill2 = arrayGetItem(hull->vertexArray, e->hill2);
hull->vertexArray, f1->indices[1]);
convexHullVertex *f1p3 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, f1->indices[2]);
convexHullVertex *f2p1 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, f2->indices[0]);
convexHullVertex *f2p2 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, f2->indices[1]);
convexHullVertex *f2p3 = (convexHullVertex *)arrayGetItem(
hull->vertexArray, f2->indices[2]);
vec3Normal(&f1p1->pt, &f1p2->pt, &f1p3->pt, &f1normal);
vec3Normal(&f2p1->pt, &f2p2->pt, &f2p3->pt, &f2normal);
*/
vec3 *v1 = (vec3 *)arrayGetItem(hull->vertexArray, e->p1);
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; vec3 v12;
vec3Sub(v1, v2, &v12); vec3Sub(v1, v2, &v12);
vec3Normal(v1, vHill1, v2, &f1normal); vec3Normal(v1, vHill1, v2, &f1normal);
@ -554,17 +386,15 @@ int convexHullMergeTriangles(convexHull *hull) {
// //
// After sort by score, the edge hashmap can not be used anymore. // After sort by score, the edge hashmap can not be used anymore.
// //
hashtableDestroy(hull->edgeHashtable); dictDestroy(hull->edgeDict);
hull->edgeHashtable = 0; hull->edgeDict = 0;
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray); for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
++edgeIndex) { ++edgeIndex) {
edge *e = (edge *)arrayGetItem(hull->edgeArray, edgeIndex); edge *e = arrayGetItem(hull->edgeArray, edgeIndex);
if (-1 != e->face1 && -1 != e->face2) { if (-1 != e->face1 && -1 != e->face2) {
convexHullFace *f1 = (convexHullFace *)arrayGetItem(hull->faceArray, convexHullFace *f1 = arrayGetItem(hull->faceArray, e->face1);
e->face1); convexHullFace *f2 = arrayGetItem(hull->faceArray, e->face2);
convexHullFace *f2 = (convexHullFace *)arrayGetItem(hull->faceArray,
e->face2);
if (3 == f1->vertexNum && 3 == f2->vertexNum) { if (3 == f1->vertexNum && 3 == f2->vertexNum) {
if (e->angleBetweenFaces <= 40 && if (e->angleBetweenFaces <= 40 &&
f1->plane == f2->plane) { f1->plane == f2->plane) {
@ -575,33 +405,23 @@ int convexHullMergeTriangles(convexHull *hull) {
f1->u.q.indices[2] = e->hill2; f1->u.q.indices[2] = e->hill2;
f1->vertexNum = 4; f1->vertexNum = 4;
f2->vertexNum = 0; f2->vertexNum = 0;
//if (edgeIndex >= 12 && edgeIndex <= 12) {
// drawDebugPoint((vec3 *)arrayGetItem(
// hull->vertexArray, e->p1), edgeIndex);
// drawDebugPoint((vec3 *)arrayGetItem(
// hull->vertexArray, e->p2), edgeIndex);
//}
} }
} }
} }
} }
// After merge, face3 hashtable can not be used anymore. // After merge, face3 hashtable can not be used anymore.
hashtableDestroy(hull->face3Hashtable); dictDestroy(hull->face3Dict);
hull->face3Hashtable = 0; hull->face3Dict = 0;
return 0;
} }
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex) { convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex) {
convexHullFace *face = (convexHullFace *)arrayGetItem(hull->faceArray, convexHullFace *face = arrayGetItem(hull->faceArray, faceIndex);
faceIndex);
return face; return face;
} }
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex) { convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex) {
convexHullVertex *vertex = (convexHullVertex *)arrayGetItem( convexHullVertex *vertex = arrayGetItem(hull->vertexArray, vertexIndex);
hull->vertexArray, vertexIndex);
return vertex; return vertex;
} }

View File

@ -23,12 +23,12 @@ convexHull *convexHullCreate(void);
int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane, int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
int orderOnPlane); int orderOnPlane);
void convexHullDestroy(convexHull *hull); void convexHullDestroy(convexHull *hull);
int convexHullGenerate(convexHull *hull); void convexHullGenerate(convexHull *hull);
int convexHullUnifyNormals(convexHull *hull, vec3 *origin); void convexHullUnifyNormals(convexHull *hull, vec3 *origin);
int convexHullMergeTriangles(convexHull *hull); void convexHullMergeTriangles(convexHull *hull);
int convexHullGetFaceNum(convexHull *hull); int convexHullGetFaceNum(convexHull *hull);
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex); convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex);
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex); convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex);
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3); void convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
#endif #endif

View File

@ -2,8 +2,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "hashtable.h" #include "dmemory.h"
#include "array.h" #include "dict.h"
typedef struct hashtableEntry { typedef struct hashtableEntry {
const void *node; const void *node;
@ -15,14 +15,22 @@ typedef struct hashtableKey {
int firstEntryIndex; int firstEntryIndex;
} hashtableKey; } hashtableKey;
struct hashtable { typedef struct hashtable {
array *keyArray; array *keyArray;
array *entryArray; array *entryArray;
int bucketSize; int bucketSize;
int (*hashCallback)(void *userData, const void *node); int (*hashCallback)(void *userData, const void *node);
int (*compareCallback)(void *userData, const void *node1, const void *node2); int (*compareCallback)(void *userData, const void *node1, const void *node2);
void *userData; void *userData;
}; } hashtable;
void hashtableDestroy(hashtable *ht) {
if (ht) {
arrayDestroy(ht->keyArray);
arrayDestroy(ht->entryArray);
dfree(ht);
}
}
hashtable *hashtableCreate(int bucketSize, hashtable *hashtableCreate(int bucketSize,
int (*hashCallback)(void *userData, const void *node), int (*hashCallback)(void *userData, const void *node),
@ -50,23 +58,10 @@ hashtable *hashtableCreate(int bucketSize,
ht->hashCallback = hashCallback; ht->hashCallback = hashCallback;
ht->compareCallback = compareCallback; ht->compareCallback = compareCallback;
ht->userData = userData; ht->userData = userData;
if (0 != arraySetLength(ht->keyArray, bucketSize)) { arraySetLength(ht->keyArray, bucketSize);
fprintf(stderr, "%s:arraySetLength failed(bucketSize:%d).\n", __FUNCTION__,
bucketSize);
hashtableDestroy(ht);
return 0;
}
return ht; return ht;
} }
void hashtableDestroy(hashtable *ht) {
if (ht) {
arrayDestroy(ht->keyArray);
arrayDestroy(ht->entryArray);
free(ht);
}
}
static int hashtableGetNodeHash(hashtable *ht, const void *node) { static int hashtableGetNodeHash(hashtable *ht, const void *node) {
return (int)((unsigned int)ht->hashCallback(ht->userData, return (int)((unsigned int)ht->hashCallback(ht->userData,
node) % ht->bucketSize); node) % ht->bucketSize);
@ -88,26 +83,19 @@ static hashtableEntry *findEntry(hashtable *ht, hashtableKey *key,
return 0; return 0;
} }
int hashtableInsert(hashtable *ht, const void *node) { static void hashtableInsert(hashtable *ht, const void *keyNode,
const void *node) {
int newEntryIndex; int newEntryIndex;
int hash = hashtableGetNodeHash(ht, node); hashtableEntry *entry;
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash); int hash = hashtableGetNodeHash(ht, keyNode);
hashtableEntry *entry = findEntry(ht, key, node); hashtableKey *key = arrayGetItem(ht->keyArray, hash);
if (entry) {
return -1;
}
newEntryIndex = arrayGetLength(ht->entryArray); newEntryIndex = arrayGetLength(ht->entryArray);
if (0 != arraySetLength(ht->entryArray, newEntryIndex + 1)) { arraySetLength(ht->entryArray, newEntryIndex + 1);
fprintf(stderr, "%s:arraySetLength failed(newEntryIndex:%d).\n", entry = arrayGetItem(ht->entryArray, newEntryIndex);
__FUNCTION__, newEntryIndex);
return -1;
}
entry = (hashtableEntry *)arrayGetItem(ht->entryArray, newEntryIndex);
entry->node = node; entry->node = node;
entry->nextEntryIndex = 0 == key->entryNum ? -1 : key->firstEntryIndex; entry->nextEntryIndex = 0 == key->entryNum ? -1 : key->firstEntryIndex;
key->firstEntryIndex = newEntryIndex; key->firstEntryIndex = newEntryIndex;
key->entryNum++; key->entryNum++;
return 0;
} }
void *hashtableGet(hashtable *ht, const void *node) { void *hashtableGet(hashtable *ht, const void *node) {
@ -115,3 +103,80 @@ void *hashtableGet(hashtable *ht, const void *node) {
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash); hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash);
return findEntry(ht, key, node); return findEntry(ht, key, node);
} }
struct dict {
hashtable *ht;
array *arr;
int (*hashCallback)(void *userData, const void *key);
int (*compareCallback)(void *userData, const void *key1, const void *key2);
void *userData;
void *findKey;
};
static const void *dictKeyTranslate(dict *dct, const void *key) {
if (0 == key) {
key = dct->findKey;
} else {
key = arrayGetItem(dct->arr, ((char *)key - 0) - 1);
}
return key;
}
static int dictHash(void *userData, const void *key) {
dict *dct = userData;
return dct->hashCallback(dct->userData, dictKeyTranslate(dct, key));
}
static int dictCompare(void *userData, const void *key1, const void *key2) {
dict *dct = userData;
return dct->compareCallback(dct->userData, dictKeyTranslate(dct, key1),
dictKeyTranslate(dct, key2));
}
dict *dictCreate(array *arr, int bucketSize,
int (*hashCallback)(void *userData, const void *key),
int (*compareCallback)(void *userData, const void *key1, const void *key2),
void *userData) {
dict *dct = dcalloc(1, sizeof(dict));
dct->arr = arr;
dct->hashCallback = hashCallback;
dct->compareCallback = compareCallback;
dct->userData = userData;
dct->findKey = 0;
dct->ht = hashtableCreate(bucketSize, dictHash, dictCompare, dct);
return dct;
}
void dictDestroy(dict *dct) {
if (dct && dct->ht) {
hashtableDestroy(dct->ht);
}
dfree(dct);
}
void *dictFind(dict *dct, void *key) {
int index;
dct->findKey = key;
index = (char *)hashtableGet(dct->ht, 0) - 0;
if (0 == index) {
return 0;
}
return arrayGetItem(dct->arr, index - 1);
}
void *dictGet(dict *dct, void *key) {
void *value = dictFind(dct, key);
if (!value) {
int newIndex = arrayGetLength(dct->arr);
value = arrayNewItem(dct->arr);
dct->findKey = key;
hashtableInsert(dct->ht, 0, (char *)0 + newIndex + 1);
}
return value;
}
void *dictGetClear(dict *dct, void *key) {
void *ptr = dictGet(dct, key);
memset(ptr, 0, arrayGetNodeSize(dct->arr));
return ptr;
}

16
src/dict.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef DICT_H
#define DICT_H
#include "array.h"
typedef struct dict dict;
dict *dictCreate(array *arr, int bucketSize,
int (*hashCallback)(void *userData, const void *key),
int (*compareCallback)(void *userData, const void *key1, const void *key2),
void *userData);
void dictDestroy(dict *dct);
void *dictFind(dict *dct, void *key);
void *dictGet(dict *dct, void *key);
void *dictGetClear(dict *dct, void *key);
#endif

36
src/dmemory.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include "dmemory.h"
static void outOfMemory(void) {
fprintf(stderr, "Out of memory\n");
abort();
}
void *dmalloc(int size) {
void *ptr = malloc(size);
if (!ptr) {
outOfMemory();
}
return ptr;
}
void *dcalloc(int nitems, int size) {
void *ptr = calloc(nitems, size);
if (!ptr) {
outOfMemory();
}
return ptr;
}
void *drealloc(void *ptr, int size) {
ptr = realloc(ptr, size);
if (!ptr) {
outOfMemory();
}
return ptr;
}
void dfree(void *ptr) {
free(ptr);
}

9
src/dmemory.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef DMEMORY_H
#define DMEMORY_H
void *dmalloc(int size);
void *dcalloc(int nitems, int size);
void *drealloc(void *ptr, int size);
void dfree(void *ptr);
#endif

View File

@ -1,15 +0,0 @@
#ifndef HASHTABLE_H
#define HASHTABLE_H
typedef struct hashtable hashtable;
hashtable *hashtableCreate(int bucketSize,
int (*hashCallback)(void *userData, const void *node),
int (*compareCallback)(void *userData, const void *node1, const void *node2),
void *userData);
void hashtableDestroy(hashtable *ht);
int hashtableInsert(hashtable *ht, const void *node);
void *hashtableGet(hashtable *ht, const void *node);
#endif

View File

@ -340,7 +340,7 @@ void Render::paintGL() {
if (0 == bm) { if (0 == bm) {
bmeshBall ball; bmeshBall ball;
bmeshBone bone; bmeshBone bone;
int i; unsigned int i;
bm = bmeshCreate(); bm = bmeshCreate();
for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) { for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) {

View File

@ -1,6 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "dmemory.h"
#include "subdivide.h" #include "subdivide.h"
#include "draw.h" #include "draw.h"
@ -82,34 +83,14 @@ static void initFace(subdivFace *f) {
} }
subdivModel *subdivCreateModel(void) { subdivModel *subdivCreateModel(void) {
subdivModel *model = (subdivModel *)calloc(1, sizeof(subdivModel)); subdivModel *model = (subdivModel *)dcalloc(1, sizeof(subdivModel));
if (!model) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
model->faceLink = -1; model->faceLink = -1;
model->edgeLink = -1; model->edgeLink = -1;
model->vertexLink = -1; model->vertexLink = -1;
model->vertexArray = arrayCreate(sizeof(subdivVertex)); model->vertexArray = arrayCreate(sizeof(subdivVertex));
if (!model->vertexArray) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
model->faceArray = arrayCreate(sizeof(subdivFace)); model->faceArray = arrayCreate(sizeof(subdivFace));
if (!model->faceArray) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
model->edgeArray = arrayCreate(sizeof(subdivEdge)); model->edgeArray = arrayCreate(sizeof(subdivEdge));
if (!model->edgeArray) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
model->indexArray = arrayCreate(sizeof(subdivLink)); model->indexArray = arrayCreate(sizeof(subdivLink));
if (!model->indexArray) {
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
return 0;
}
return model; return model;
} }
@ -119,18 +100,15 @@ void subdivDestroyModel(subdivModel *model) {
arrayDestroy(model->faceArray); arrayDestroy(model->faceArray);
arrayDestroy(model->edgeArray); arrayDestroy(model->edgeArray);
arrayDestroy(model->indexArray); arrayDestroy(model->indexArray);
free(model); dfree(model);
} }
} }
static int allocLink(subdivModel *model, int index) { static int allocLink(subdivModel *model, int index) {
subdivLink *linkItem; subdivLink *linkItem;
int newLink = arrayGetLength(model->indexArray); int newLink = arrayGetLength(model->indexArray);
if (0 != arraySetLength(model->indexArray, newLink + 1)) { arraySetLength(model->indexArray, newLink + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); linkItem = arrayGetItem(model->indexArray, newLink);
return -1;
}
linkItem = (subdivLink *)arrayGetItem(model->indexArray, newLink);
linkItem->index = index; linkItem->index = index;
linkItem->nextLink = -1; linkItem->nextLink = -1;
return newLink; return newLink;
@ -142,25 +120,21 @@ static int subdivLinkElement(subdivModel *model, int current, int order) {
subdivLink *linkItem; subdivLink *linkItem;
iterator = current; iterator = current;
for (i = 0; i <= order && -1 != iterator; ++i) { for (i = 0; i <= order && -1 != iterator; ++i) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator); linkItem = arrayGetItem(model->indexArray, iterator);
element = linkItem->index; element = linkItem->index;
iterator = linkItem->nextLink; iterator = linkItem->nextLink;
} }
return element; return element;
} }
static int pushLink(subdivModel *model, int *link, int *num, int index) { static void pushLink(subdivModel *model, int *link, int *num, int index) {
int newLink = allocLink(model, index); int newLink = allocLink(model, index);
int i, iterator; int i, iterator;
subdivLink *linkItem = 0; subdivLink *linkItem = 0;
if (-1 == newLink) {
fprintf(stderr, "%s:allocLink failed.\n", __FUNCTION__);
return -1;
}
if (-1 != *link) { if (-1 != *link) {
iterator = *link; iterator = *link;
for (i = 0; i < *num; ++i) { for (i = 0; i < *num; ++i) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator); linkItem = arrayGetItem(model->indexArray, iterator);
iterator = linkItem->nextLink; iterator = linkItem->nextLink;
} }
linkItem->nextLink = newLink; linkItem->nextLink = newLink;
@ -168,34 +142,23 @@ static int pushLink(subdivModel *model, int *link, int *num, int index) {
*link = newLink; *link = newLink;
} }
(*num)++; (*num)++;
return 0;
} }
static subdivVertex *allocVertex(subdivModel *model) { static subdivVertex *allocVertex(subdivModel *model) {
subdivVertex *vertex; subdivVertex *vertex;
int newVertexIndex = arrayGetLength(model->vertexArray); int newVertexIndex = arrayGetLength(model->vertexArray);
if (0 != arraySetLength(model->vertexArray, newVertexIndex + 1)) { arraySetLength(model->vertexArray, newVertexIndex + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return 0;
}
vertex = arrayGetItem(model->vertexArray, newVertexIndex); vertex = arrayGetItem(model->vertexArray, newVertexIndex);
initVertex(vertex); initVertex(vertex);
vertex->index = newVertexIndex; vertex->index = newVertexIndex;
if (0 != pushLink(model, &model->vertexLink, &model->vertexNum, pushLink(model, &model->vertexLink, &model->vertexNum, vertex->index);
vertex->index)) {
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
return vertex; return vertex;
} }
static subdivEdge *allocEdge(subdivModel *model) { static subdivEdge *allocEdge(subdivModel *model) {
subdivEdge *edge; subdivEdge *edge;
int newEdgeIndex = arrayGetLength(model->edgeArray); int newEdgeIndex = arrayGetLength(model->edgeArray);
if (0 != arraySetLength(model->edgeArray, newEdgeIndex + 1)) { arraySetLength(model->edgeArray, newEdgeIndex + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return 0;
}
edge = arrayGetItem(model->edgeArray, newEdgeIndex); edge = arrayGetItem(model->edgeArray, newEdgeIndex);
initEdge(edge); initEdge(edge);
edge->index = newEdgeIndex; edge->index = newEdgeIndex;
@ -205,10 +168,7 @@ static subdivEdge *allocEdge(subdivModel *model) {
static subdivFace *allocFace(subdivModel *model) { static subdivFace *allocFace(subdivModel *model) {
subdivFace *face; subdivFace *face;
int newFaceIndex = arrayGetLength(model->faceArray); int newFaceIndex = arrayGetLength(model->faceArray);
if (0 != arraySetLength(model->faceArray, newFaceIndex + 1)) { arraySetLength(model->faceArray, newFaceIndex + 1);
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
return 0;
}
face = arrayGetItem(model->faceArray, newFaceIndex); face = arrayGetItem(model->faceArray, newFaceIndex);
initFace(face); initFace(face);
face->index = newFaceIndex; face->index = newFaceIndex;
@ -219,21 +179,21 @@ static subdivVertex *getVertex(subdivModel *model, int index) {
if (-1 == index) { if (-1 == index) {
return 0; return 0;
} }
return (subdivVertex *)arrayGetItem(model->vertexArray, index); return arrayGetItem(model->vertexArray, index);
} }
static subdivEdge *getEdge(subdivModel *model, int index) { static subdivEdge *getEdge(subdivModel *model, int index) {
if (-1 == index) { if (-1 == index) {
return 0; return 0;
} }
return (subdivEdge *)arrayGetItem(model->edgeArray, index); return arrayGetItem(model->edgeArray, index);
} }
static subdivFace *getFace(subdivModel *model, int index) { static subdivFace *getFace(subdivModel *model, int index) {
if (-1 == index) { if (-1 == index) {
return 0; return 0;
} }
return (subdivFace *)arrayGetItem(model->faceArray, index); return arrayGetItem(model->faceArray, index);
} }
static int isHoleEdge(subdivModel *model, int e) { static int isHoleEdge(subdivModel *model, int e) {
@ -250,10 +210,6 @@ static int edgePoint(subdivModel *model, int e) {
int nv = getEdge(model, e)->edgePt; int nv = getEdge(model, e)->edgePt;
if (-1 == nv) { if (-1 == nv) {
subdivVertex *newVertex = allocVertex(model); subdivVertex *newVertex = allocVertex(model);
if (!newVertex) {
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
return 0;
}
nv = newVertex->index; nv = newVertex->index;
getEdge(model, e)->edgePt = nv; getEdge(model, e)->edgePt = nv;
getEdge(model, e)->avg = getVertex(model, getEdge(model, e)->v[0])->v; getEdge(model, e)->avg = getVertex(model, getEdge(model, e)->v[0])->v;
@ -266,15 +222,11 @@ static int edgePoint(subdivModel *model, int e) {
while (-1 != iterator) { while (-1 != iterator) {
int f; int f;
int fp; int fp;
subdivLink *linkItem = (subdivLink *)arrayGetItem(model->indexArray, subdivLink *linkItem = arrayGetItem(model->indexArray,
iterator); iterator);
f = linkItem->index; f = linkItem->index;
iterator = linkItem->nextLink; iterator = linkItem->nextLink;
fp = facePoint(model, f); fp = facePoint(model, f);
if (-1 == fp) {
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
return 0;
}
vec3Add(&getVertex(model, nv)->v, &getVertex(model, fp)->v, vec3Add(&getVertex(model, nv)->v, &getVertex(model, fp)->v,
&getVertex(model, nv)->v); &getVertex(model, nv)->v);
} }
@ -293,18 +245,13 @@ static int facePoint(subdivModel *model, int f) {
int iterator; int iterator;
int i; int i;
subdivVertex *newVertex = allocVertex(model); subdivVertex *newVertex = allocVertex(model);
if (!newVertex) {
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
return 0;
}
nv = newVertex->index; nv = newVertex->index;
getFace(model, f)->avg = nv; getFace(model, f)->avg = nv;
iterator = getFace(model, f)->vertexLink; iterator = getFace(model, f)->vertexLink;
i = 0; i = 0;
while (-1 != iterator) { while (-1 != iterator) {
int p; int p;
subdivLink *linkItem = (subdivLink *)arrayGetItem(model->indexArray, subdivLink *linkItem = arrayGetItem(model->indexArray, iterator);
iterator);
p = linkItem->index; p = linkItem->index;
iterator = linkItem->nextLink; iterator = linkItem->nextLink;
if (!i) { if (!i) {
@ -345,27 +292,19 @@ static int updatedPoint(subdivModel *model, int p) {
} }
newVertex = allocVertex(model); newVertex = allocVertex(model);
if (!newVertex) {
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
return 0;
}
nv = newVertex->index; nv = newVertex->index;
getVertex(model, p)->newVertexIndex = nv; getVertex(model, p)->newVertexIndex = nv;
if (isHoleVertex(model, p)) { if (isHoleVertex(model, p)) {
getVertex(model, nv)->v = getVertex(model, p)->v; getVertex(model, nv)->v = getVertex(model, p)->v;
iterator = getVertex(model, p)->edgeLink; iterator = getVertex(model, p)->edgeLink;
while (-1 != iterator) { while (-1 != iterator) {
link = (subdivLink *)arrayGetItem(model->indexArray, iterator); link = arrayGetItem(model->indexArray, iterator);
e = link->index; e = link->index;
iterator = link->nextLink; iterator = link->nextLink;
if (!isHoleEdge(model, e)) { if (!isHoleEdge(model, e)) {
continue; continue;
} }
ep = edgePoint(model, e); ep = edgePoint(model, e);
if (-1 == ep) {
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
return 0;
}
vec3Add(&getVertex(model, nv)->v, &getVertex(model, ep)->v, vec3Add(&getVertex(model, nv)->v, &getVertex(model, ep)->v,
&getVertex(model, nv)->v); &getVertex(model, nv)->v);
n++; n++;
@ -376,26 +315,18 @@ static int updatedPoint(subdivModel *model, int p) {
n = getVertex(model, p)->faceNum; n = getVertex(model, p)->faceNum;
iterator = getVertex(model, p)->faceLink; iterator = getVertex(model, p)->faceLink;
while (-1 != iterator) { while (-1 != iterator) {
link = (subdivLink *)arrayGetItem(model->indexArray, iterator); link = arrayGetItem(model->indexArray, iterator);
f = link->index; f = link->index;
iterator = link->nextLink; iterator = link->nextLink;
facePt = facePoint(model, f); facePt = facePoint(model, f);
if (-1 == facePt) {
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
return 0;
}
vec3Add(&sum, &getVertex(model, facePt)->v, &sum); vec3Add(&sum, &getVertex(model, facePt)->v, &sum);
} }
iterator = getVertex(model, p)->edgeLink; iterator = getVertex(model, p)->edgeLink;
while (-1 != iterator) { while (-1 != iterator) {
link = (subdivLink *)arrayGetItem(model->indexArray, iterator); link = arrayGetItem(model->indexArray, iterator);
e = link->index; e = link->index;
iterator = link->nextLink; iterator = link->nextLink;
ep = edgePoint(model, e); ep = edgePoint(model, e);
if (-1 == ep) {
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
return 0;
}
scaleAdd(&sum, &getVertex(model, ep)->v, 2, &sum); scaleAdd(&sum, &getVertex(model, ep)->v, 2, &sum);
} }
vec3Scale(&sum, 1.0 / n, &sum); vec3Scale(&sum, 1.0 / n, &sum);
@ -407,7 +338,7 @@ static int updatedPoint(subdivModel *model, int p) {
return nv; return nv;
} }
int subdivCalculteNorms(subdivModel *model) { void subdivCalculteNorms(subdivModel *model) {
int i, j, n; int i, j, n;
int faceIterator; int faceIterator;
int nextFaceIterator; int nextFaceIterator;
@ -423,16 +354,16 @@ int subdivCalculteNorms(subdivModel *model) {
faceIterator = model->faceLink; faceIterator = model->faceLink;
j = 0; j = 0;
while (-1 != faceIterator) { while (-1 != faceIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator); linkItem = arrayGetItem(model->indexArray, faceIterator);
f = getFace(model, linkItem->index); f = getFace(model, linkItem->index);
nextFaceIterator = linkItem->nextLink; nextFaceIterator = linkItem->nextLink;
vertexIterator = f->vertexLink; vertexIterator = f->vertexLink;
n = f->vertexNum; n = f->vertexNum;
i = 0; i = 0;
while (-1 != vertexIterator) { while (-1 != vertexIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator); linkItem = arrayGetItem(model->indexArray, faceIterator);
f = getFace(model, linkItem->index); f = getFace(model, linkItem->index);
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator); linkItem = arrayGetItem(model->indexArray, vertexIterator);
v = getVertex(model, linkItem->index); v = getVertex(model, linkItem->index);
vertexIterator = linkItem->nextLink; vertexIterator = linkItem->nextLink;
v0 = getVertex(model, v0 = getVertex(model,
@ -454,13 +385,13 @@ int subdivCalculteNorms(subdivModel *model) {
vertexIterator = model->vertexLink; vertexIterator = model->vertexLink;
while (-1 != vertexIterator) { while (-1 != vertexIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator); linkItem = arrayGetItem(model->indexArray, vertexIterator);
v = getVertex(model, linkItem->index); v = getVertex(model, linkItem->index);
nextVertexIterator = linkItem->nextLink; nextVertexIterator = linkItem->nextLink;
faceIterator = v->faceLink; faceIterator = v->faceLink;
j = 0; j = 0;
while (-1 != faceIterator) { while (-1 != faceIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator); linkItem = arrayGetItem(model->indexArray, faceIterator);
f = getFace(model, linkItem->index); f = getFace(model, linkItem->index);
faceIterator = linkItem->nextLink; faceIterator = linkItem->nextLink;
vec3Add(&v->avgNorm, &f->norm, &v->avgNorm); vec3Add(&v->avgNorm, &f->norm, &v->avgNorm);
@ -471,8 +402,6 @@ int subdivCalculteNorms(subdivModel *model) {
} }
vertexIterator = nextVertexIterator; vertexIterator = nextVertexIterator;
} }
return 0;
} }
void subdivDrawModel(subdivModel *model) { void subdivDrawModel(subdivModel *model) {
@ -484,13 +413,13 @@ void subdivDrawModel(subdivModel *model) {
faceIterator = model->faceLink; faceIterator = model->faceLink;
glColor4f(1.0, 1.0, 1.0, 1.0); glColor4f(1.0, 1.0, 1.0, 1.0);
while (-1 != faceIterator) { while (-1 != faceIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator); linkItem = arrayGetItem(model->indexArray, faceIterator);
f = getFace(model, linkItem->index); f = getFace(model, linkItem->index);
faceIterator = linkItem->nextLink; faceIterator = linkItem->nextLink;
vertexIterator = f->vertexLink; vertexIterator = f->vertexLink;
glBegin(GL_POLYGON); glBegin(GL_POLYGON);
while (-1 != vertexIterator) { while (-1 != vertexIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator); linkItem = arrayGetItem(model->indexArray, vertexIterator);
v = getVertex(model, linkItem->index); v = getVertex(model, linkItem->index);
vertexIterator = linkItem->nextLink; vertexIterator = linkItem->nextLink;
glNormal3fv(&(f->norm.x)); glNormal3fv(&(f->norm.x));
@ -512,48 +441,24 @@ subdivModel *subdivCatmullClark(subdivModel *model) {
subdivModel *outputModel; subdivModel *outputModel;
outputModel = subdivCreateModel(); outputModel = subdivCreateModel();
if (!outputModel) {
fprintf(stderr, "%s:subdivCreateModel failed.\n", __FUNCTION__);
return 0;
}
faceIterator = model->faceLink; faceIterator = model->faceLink;
while (-1 != faceIterator) { while (-1 != faceIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator); linkItem = arrayGetItem(model->indexArray, faceIterator);
f = linkItem->index; f = linkItem->index;
j = 0; j = 0;
nextFaceIterator = linkItem->nextLink; nextFaceIterator = linkItem->nextLink;
vertexIterator = getFace(model, f)->vertexLink; vertexIterator = getFace(model, f)->vertexLink;
while (-1 != vertexIterator) { while (-1 != vertexIterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator); linkItem = arrayGetItem(model->indexArray, vertexIterator);
p = linkItem->index; p = linkItem->index;
vertexIterator = linkItem->nextLink; vertexIterator = linkItem->nextLink;
ai = updatedPoint(model, p); ai = updatedPoint(model, p);
if (-1 == ai) {
fprintf(stderr, "%s:updatedPoint failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
bi = edgePoint(model, subdivLinkElement(model, bi = edgePoint(model, subdivLinkElement(model,
getFace(model, f)->edgeLink, (j + 1) % getFace(model, f)->edgeNum)); getFace(model, f)->edgeLink, (j + 1) % getFace(model, f)->edgeNum));
if (-1 == bi) {
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
ci = facePoint(model, f); ci = facePoint(model, f);
if (-1 == ci) {
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
di = edgePoint(model, subdivLinkElement(model, di = edgePoint(model, subdivLinkElement(model,
getFace(model, f)->edgeLink, j)); getFace(model, f)->edgeLink, j));
if (-1 == di) {
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
a = getVertex(model, ai)->indexOnNewModel; a = getVertex(model, ai)->indexOnNewModel;
if (-1 == a) { if (-1 == a) {
a = subdivAddVertex(outputModel, &getVertex(model, ai)->v); a = subdivAddVertex(outputModel, &getVertex(model, ai)->v);
@ -574,36 +479,19 @@ subdivModel *subdivCatmullClark(subdivModel *model) {
d = subdivAddVertex(outputModel, &getVertex(model, di)->v); d = subdivAddVertex(outputModel, &getVertex(model, di)->v);
getVertex(model, di)->indexOnNewModel = d; getVertex(model, di)->indexOnNewModel = d;
} }
if (-1 == a || -1 == b || -1 == c || -1 == d) { subdivAddQuadFace(outputModel, a, b, c, d);
fprintf(stderr, "%s:subdivAddVertex failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
if (-1 == subdivAddQuadFace(outputModel, a, b, c, d)) {
fprintf(stderr, "%s:subdivAddFace failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
++j; ++j;
} }
faceIterator = nextFaceIterator; faceIterator = nextFaceIterator;
} }
if (0 != subdivCalculteNorms(outputModel)) { subdivCalculteNorms(outputModel);
fprintf(stderr, "%s:subdivCalculteNorms failed.\n", __FUNCTION__);
subdivDestroyModel(outputModel);
return 0;
}
return outputModel; return outputModel;
} }
int subdivAddVertex(subdivModel *model, vec3 *v) { int subdivAddVertex(subdivModel *model, vec3 *v) {
subdivVertex *newVertex = allocVertex(model); subdivVertex *newVertex = allocVertex(model);
if (!newVertex) {
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
return -1;
}
newVertex->v = *v; newVertex->v = *v;
return newVertex->index; return newVertex->index;
} }
@ -612,27 +500,13 @@ static int subdivAddEdge(subdivModel *model, int p1, int p2) {
subdivEdge *newEdge = allocEdge(model); subdivEdge *newEdge = allocEdge(model);
subdivVertex *v1; subdivVertex *v1;
subdivVertex *v2; subdivVertex *v2;
if (!newEdge) {
fprintf(stderr, "%s:allocEdge failed.\n", __FUNCTION__);
return -1;
}
newEdge->v[0] = p1; newEdge->v[0] = p1;
newEdge->v[1] = p2; newEdge->v[1] = p2;
v1 = getVertex(model, p1); v1 = getVertex(model, p1);
v2 = getVertex(model, p2); v2 = getVertex(model, p2);
if (-1 == pushLink(model, &v1->edgeLink, &v1->edgeNum, newEdge->index)) { pushLink(model, &v1->edgeLink, &v1->edgeNum, newEdge->index);
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__); pushLink(model, &v2->edgeLink, &v2->edgeNum, newEdge->index);
return -1; pushLink(model, &model->edgeLink, &model->edgeNum, newEdge->index);
}
if (-1 == pushLink(model, &v2->edgeLink, &v2->edgeNum, newEdge->index)) {
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
if (-1 == pushLink(model, &model->edgeLink, &model->edgeNum,
newEdge->index)) {
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
return newEdge->index; return newEdge->index;
} }
@ -643,7 +517,7 @@ static int subdivEdgeByVertexs(subdivModel *model, int p1, int p2) {
int newEdgeIndex; int newEdgeIndex;
int iterator = v1->edgeLink; int iterator = v1->edgeLink;
while (-1 != iterator) { while (-1 != iterator) {
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator); linkItem = arrayGetItem(model->indexArray, iterator);
e = getEdge(model, linkItem->index); e = getEdge(model, linkItem->index);
iterator = linkItem->nextLink; iterator = linkItem->nextLink;
if (e->v[0] == p2 || e->v[1] == p2) { if (e->v[0] == p2 || e->v[1] == p2) {
@ -660,44 +534,21 @@ static int subdivAddFace(subdivModel *model, int *vertexs, int vertexNum) {
int p0, p1; int p0, p1;
int newFaceIndex; int newFaceIndex;
int edgeIndex; int edgeIndex;
if (!f) {
fprintf(stderr, "%s:allocFace failed.\n", __FUNCTION__);
return -1;
}
newFaceIndex = f->index; newFaceIndex = f->index;
if (0 != pushLink(model, &model->faceLink, &model->faceNum, newFaceIndex)) { pushLink(model, &model->faceLink, &model->faceNum, newFaceIndex);
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
p0 = vertexs[0]; p0 = vertexs[0];
for (i = 1; i <= vertexNum; ++i, p0 = p1) { for (i = 1; i <= vertexNum; ++i, p0 = p1) {
subdivVertex *v1; subdivVertex *v1;
subdivEdge *e; subdivEdge *e;
p1 = vertexs[i % vertexNum]; p1 = vertexs[i % vertexNum];
v1 = getVertex(model, p1); v1 = getVertex(model, p1);
if (0 != pushLink(model, &v1->faceLink, &v1->faceNum, newFaceIndex)) { pushLink(model, &v1->faceLink, &v1->faceNum, newFaceIndex);
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
edgeIndex = subdivEdgeByVertexs(model, p0, p1); edgeIndex = subdivEdgeByVertexs(model, p0, p1);
if (-1 == edgeIndex) {
fprintf(stderr, "%s:subdivEdgeByVertexs failed.\n", __FUNCTION__);
return -1;
}
e = getEdge(model, edgeIndex); e = getEdge(model, edgeIndex);
if (0 != pushLink(model, &e->faceLink, &e->faceNum, newFaceIndex)) { pushLink(model, &e->faceLink, &e->faceNum, newFaceIndex);
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
f = getFace(model, newFaceIndex); f = getFace(model, newFaceIndex);
if (0 != pushLink(model, &f->edgeLink, &f->edgeNum, edgeIndex)) { pushLink(model, &f->edgeLink, &f->edgeNum, edgeIndex);
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__); pushLink(model, &f->vertexLink, &f->vertexNum, p1);
return -1;
}
if (0 != pushLink(model, &f->vertexLink, &f->vertexNum, p1)) {
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
return -1;
}
} }
return newFaceIndex; return newFaceIndex;
} }
@ -712,7 +563,7 @@ int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4) {
return subdivAddFace(model, vertexs, 4); return subdivAddFace(model, vertexs, 4);
} }
int subdivAddCube(subdivModel *model) { void subdivAddCube(subdivModel *model) {
int x, y, z; int x, y, z;
for (x = -1; x <= 1; x += 2) { for (x = -1; x <= 1; x += 2) {
for (y = -1; y <= 1; y += 2) { for (y = -1; y <= 1; y += 2) {
@ -729,28 +580,17 @@ int subdivAddCube(subdivModel *model) {
subdivAddQuadFace(model, 0, 2, 6, 4); subdivAddQuadFace(model, 0, 2, 6, 4);
subdivAddQuadFace(model, 5, 7, 3, 1); subdivAddQuadFace(model, 5, 7, 3, 1);
subdivCalculteNorms(model); subdivCalculteNorms(model);
return 0;
} }
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) { subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) {
int i; int i;
subdivModel *outputModel; subdivModel *outputModel;
outputModel = subdivCatmullClark(model); outputModel = subdivCatmullClark(model);
if (!outputModel) {
fprintf(stderr, "%s:subdivCatmullClark failed.\n", __FUNCTION__);
return 0;
}
for (i = 1; i < loops; ++i) { for (i = 1; i < loops; ++i) {
subdivModel *loopInput = outputModel; subdivModel *loopInput = outputModel;
outputModel = subdivCatmullClark(loopInput); outputModel = subdivCatmullClark(loopInput);
subdivDestroyModel(loopInput); subdivDestroyModel(loopInput);
if (!outputModel) {
fprintf(stderr, "%s:subdivCatmullClark failed(loops:%d i:%d).\n",
__FUNCTION__, loops, i);
return 0;
}
} }
drawDebugPrintf("faces: %d", outputModel->faceNum);
subdivDrawModel(outputModel); subdivDrawModel(outputModel);
return outputModel; return outputModel;
} }

View File

@ -16,8 +16,8 @@ int subdivAddTriangleFace(subdivModel *model, int p1, int p2, int p3);
int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4); int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4);
subdivModel *subdivCatmullClark(subdivModel *model); subdivModel *subdivCatmullClark(subdivModel *model);
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops); subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops);
int subdivAddCube(subdivModel *model); void subdivAddCube(subdivModel *model);
int subdivCalculteNorms(subdivModel *model); void subdivCalculteNorms(subdivModel *model);
void subdivDrawModel(subdivModel *model); void subdivDrawModel(subdivModel *model);
#ifdef __cplusplus #ifdef __cplusplus