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 \
matrix.c \
convexhull.c \
hashtable.c \
dict.c \
osutil.cpp \
subdivide.c \
skinnedmesh.c
skinnedmesh.c \
dmemory.c
HEADERS += mainwindow.h \
render.h \
@ -29,8 +30,9 @@ HEADERS += mainwindow.h \
bmesh.h \
matrix.h \
convexhull.h \
hashtable.h \
dict.h \
3dstruct.h \
osutil.h \
subdivide.h \
skinnedmesh.h
skinnedmesh.h \
dmemory.h

View File

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

View File

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

View File

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

View File

@ -23,12 +23,12 @@ convexHull *convexHullCreate(void);
int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
int orderOnPlane);
void convexHullDestroy(convexHull *hull);
int convexHullGenerate(convexHull *hull);
int convexHullUnifyNormals(convexHull *hull, vec3 *origin);
int convexHullMergeTriangles(convexHull *hull);
void convexHullGenerate(convexHull *hull);
void convexHullUnifyNormals(convexHull *hull, vec3 *origin);
void convexHullMergeTriangles(convexHull *hull);
int convexHullGetFaceNum(convexHull *hull);
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex);
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

View File

@ -2,8 +2,8 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "hashtable.h"
#include "array.h"
#include "dmemory.h"
#include "dict.h"
typedef struct hashtableEntry {
const void *node;
@ -15,14 +15,22 @@ typedef struct hashtableKey {
int firstEntryIndex;
} hashtableKey;
struct hashtable {
typedef struct hashtable {
array *keyArray;
array *entryArray;
int bucketSize;
int (*hashCallback)(void *userData, const void *node);
int (*compareCallback)(void *userData, const void *node1, const void *node2);
void *userData;
};
} hashtable;
void hashtableDestroy(hashtable *ht) {
if (ht) {
arrayDestroy(ht->keyArray);
arrayDestroy(ht->entryArray);
dfree(ht);
}
}
hashtable *hashtableCreate(int bucketSize,
int (*hashCallback)(void *userData, const void *node),
@ -50,23 +58,10 @@ hashtable *hashtableCreate(int bucketSize,
ht->hashCallback = hashCallback;
ht->compareCallback = compareCallback;
ht->userData = userData;
if (0 != arraySetLength(ht->keyArray, bucketSize)) {
fprintf(stderr, "%s:arraySetLength failed(bucketSize:%d).\n", __FUNCTION__,
bucketSize);
hashtableDestroy(ht);
return 0;
}
arraySetLength(ht->keyArray, bucketSize);
return ht;
}
void hashtableDestroy(hashtable *ht) {
if (ht) {
arrayDestroy(ht->keyArray);
arrayDestroy(ht->entryArray);
free(ht);
}
}
static int hashtableGetNodeHash(hashtable *ht, const void *node) {
return (int)((unsigned int)ht->hashCallback(ht->userData,
node) % ht->bucketSize);
@ -88,26 +83,19 @@ static hashtableEntry *findEntry(hashtable *ht, hashtableKey *key,
return 0;
}
int hashtableInsert(hashtable *ht, const void *node) {
static void hashtableInsert(hashtable *ht, const void *keyNode,
const void *node) {
int newEntryIndex;
int hash = hashtableGetNodeHash(ht, node);
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash);
hashtableEntry *entry = findEntry(ht, key, node);
if (entry) {
return -1;
}
hashtableEntry *entry;
int hash = hashtableGetNodeHash(ht, keyNode);
hashtableKey *key = arrayGetItem(ht->keyArray, hash);
newEntryIndex = arrayGetLength(ht->entryArray);
if (0 != arraySetLength(ht->entryArray, newEntryIndex + 1)) {
fprintf(stderr, "%s:arraySetLength failed(newEntryIndex:%d).\n",
__FUNCTION__, newEntryIndex);
return -1;
}
entry = (hashtableEntry *)arrayGetItem(ht->entryArray, newEntryIndex);
arraySetLength(ht->entryArray, newEntryIndex + 1);
entry = arrayGetItem(ht->entryArray, newEntryIndex);
entry->node = node;
entry->nextEntryIndex = 0 == key->entryNum ? -1 : key->firstEntryIndex;
key->firstEntryIndex = newEntryIndex;
key->entryNum++;
return 0;
}
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);
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) {
bmeshBall ball;
bmeshBone bone;
int i;
unsigned int i;
bm = bmeshCreate();
for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) {

View File

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