Handle out of memory in one place
parent
be9e73b83d
commit
a4569fbe1e
|
@ -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
|
35
src/array.c
35
src/array.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
427
src/bmesh.c
427
src/bmesh.c
|
@ -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);
|
||||
//}
|
||||
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;
|
||||
bmeshGenerateInbetweenBallsBetween(bm, parentBallIndex, ballIndex);
|
||||
bmeshGenerateInbetweenBallsFrom(bm, ballIndex);
|
||||
}
|
||||
if (0 != bmeshGenerateInbetweenBallsFrom(bm, ballIndex)) {
|
||||
fprintf(stderr,
|
||||
"%s:bmeshGenerateInbetweenBallsFrom failed(ballIndex:%d).\n",
|
||||
__FUNCTION__, ballIndex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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, ¤tFace,
|
||||
&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, ¤tFace,
|
||||
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
||||
&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) {
|
||||
|
|
334
src/convexhull.c
334
src/convexhull.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
244
src/subdivide.c
244
src/subdivide.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue