Handle out of memory in one place
parent
be9e73b83d
commit
a4569fbe1e
|
@ -16,10 +16,11 @@ SOURCES += main.cpp \
|
||||||
bmesh.c \
|
bmesh.c \
|
||||||
matrix.c \
|
matrix.c \
|
||||||
convexhull.c \
|
convexhull.c \
|
||||||
hashtable.c \
|
dict.c \
|
||||||
osutil.cpp \
|
osutil.cpp \
|
||||||
subdivide.c \
|
subdivide.c \
|
||||||
skinnedmesh.c
|
skinnedmesh.c \
|
||||||
|
dmemory.c
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
render.h \
|
render.h \
|
||||||
|
@ -29,8 +30,9 @@ HEADERS += mainwindow.h \
|
||||||
bmesh.h \
|
bmesh.h \
|
||||||
matrix.h \
|
matrix.h \
|
||||||
convexhull.h \
|
convexhull.h \
|
||||||
hashtable.h \
|
dict.h \
|
||||||
3dstruct.h \
|
3dstruct.h \
|
||||||
osutil.h \
|
osutil.h \
|
||||||
subdivide.h \
|
subdivide.h \
|
||||||
skinnedmesh.h
|
skinnedmesh.h \
|
||||||
|
dmemory.h
|
35
src/array.c
35
src/array.c
|
@ -1,6 +1,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "dmemory.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
|
||||||
struct array {
|
struct array {
|
||||||
|
@ -11,34 +12,29 @@ struct array {
|
||||||
};
|
};
|
||||||
|
|
||||||
array *arrayCreate(int nodeSize) {
|
array *arrayCreate(int nodeSize) {
|
||||||
array *arr = (array *)calloc(1, sizeof(array));
|
array *arr = dcalloc(1, sizeof(array));
|
||||||
if (!arr) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
arr->nodeSize = nodeSize;
|
arr->nodeSize = nodeSize;
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arraySetLength(array *arr, int length) {
|
int arrayGetNodeSize(array *arr) {
|
||||||
|
return arr->nodeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arraySetLength(array *arr, int length) {
|
||||||
char *newNodes;
|
char *newNodes;
|
||||||
if (length > arr->capacity) {
|
if (length > arr->capacity) {
|
||||||
int newCapacity = (arr->capacity + 1) * 2;
|
int newCapacity = (arr->capacity + 1) * 2;
|
||||||
if (newCapacity < length) {
|
if (newCapacity < length) {
|
||||||
newCapacity = length;
|
newCapacity = length;
|
||||||
}
|
}
|
||||||
newNodes = (char *)realloc(arr->nodes, arr->nodeSize * newCapacity);
|
newNodes = drealloc(arr->nodes, arr->nodeSize * newCapacity);
|
||||||
if (!newNodes) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(newNodes + arr->nodeSize * arr->capacity, 0,
|
memset(newNodes + arr->nodeSize * arr->capacity, 0,
|
||||||
arr->nodeSize * (newCapacity - arr->capacity));
|
arr->nodeSize * (newCapacity - arr->capacity));
|
||||||
arr->capacity = newCapacity;
|
arr->capacity = newCapacity;
|
||||||
arr->nodes = newNodes;
|
arr->nodes = newNodes;
|
||||||
}
|
}
|
||||||
arr->length = length;
|
arr->length = length;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *arrayGetItem(array *arr, int index) {
|
void *arrayGetItem(array *arr, int index) {
|
||||||
|
@ -54,16 +50,19 @@ int arrayGetLength(array *arr) {
|
||||||
|
|
||||||
void arrayDestroy(array *arr) {
|
void arrayDestroy(array *arr) {
|
||||||
if (arr) {
|
if (arr) {
|
||||||
free(arr->nodes);
|
dfree(arr->nodes);
|
||||||
free(arr);
|
dfree(arr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *arrayNewItem(array *arr) {
|
void *arrayNewItem(array *arr) {
|
||||||
int newIndex = arrayGetLength(arr);
|
int newIndex = arrayGetLength(arr);
|
||||||
if (0 != arraySetLength(arr, newIndex + 1)) {
|
arraySetLength(arr, newIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return arrayGetItem(arr, newIndex);
|
return arrayGetItem(arr, newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *arrayNewItemClear(array *arr) {
|
||||||
|
void *ptr = arrayNewItem(arr);
|
||||||
|
memset(ptr, 0, arr->nodeSize);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
|
@ -8,10 +8,12 @@ extern "C" {
|
||||||
typedef struct array array;
|
typedef struct array array;
|
||||||
|
|
||||||
array *arrayCreate(int nodeSize);
|
array *arrayCreate(int nodeSize);
|
||||||
|
int arrayGetNodeSize(array *arr);
|
||||||
void *arrayGetItem(array *arr, int index);
|
void *arrayGetItem(array *arr, int index);
|
||||||
int arrayGetLength(array *arr);
|
int arrayGetLength(array *arr);
|
||||||
int arraySetLength(array *arr, int length);
|
void arraySetLength(array *arr, int length);
|
||||||
void *arrayNewItem(array *arr);
|
void *arrayNewItem(array *arr);
|
||||||
|
void *arrayNewItemClear(array *arr);
|
||||||
void arrayDestroy(array *arr);
|
void arrayDestroy(array *arr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
429
src/bmesh.c
429
src/bmesh.c
|
@ -4,9 +4,10 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "dmemory.h"
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "hashtable.h"
|
#include "dict.h"
|
||||||
#include "matrix.h"
|
#include "matrix.h"
|
||||||
#include "convexhull.h"
|
#include "convexhull.h"
|
||||||
#include "subdivide.h"
|
#include "subdivide.h"
|
||||||
|
@ -37,97 +38,50 @@ struct bmesh {
|
||||||
subdivModel *model;
|
subdivModel *model;
|
||||||
subdivModel *subdivModel;
|
subdivModel *subdivModel;
|
||||||
array *modelVertexArray;
|
array *modelVertexArray;
|
||||||
hashtable *modelVertexHashtable;
|
dict *modelVertexDict;
|
||||||
bmeshModelVertex findModelVertex;
|
bmeshModelVertex findModelVertex;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bmeshModelVertex *bmeshFindModelVertex(bmesh *bm, vec3 *vertex) {
|
static bmeshModelVertex *bmeshFindModelVertex(bmesh *bm, vec3 *vertex) {
|
||||||
int index;
|
return dictFind(bm->modelVertexDict, vertex);
|
||||||
bm->findModelVertex.vertex = *vertex;
|
|
||||||
index = (char *)hashtableGet(bm->modelVertexHashtable, (char *)0) - (char *)0;
|
|
||||||
if (0 == index) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshAddModelVertex(bmesh *bm, vec3 *vertex) {
|
static int bmeshAddModelVertex(bmesh *bm, vec3 *vertex) {
|
||||||
bmeshModelVertex *v = bmeshFindModelVertex(bm, vertex);
|
bmeshModelVertex *v = bmeshFindModelVertex(bm, vertex);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
v = (bmeshModelVertex *)arrayNewItem(bm->modelVertexArray);
|
v = dictGetClear(bm->modelVertexDict, vertex);
|
||||||
if (!v) {
|
|
||||||
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(v, 0, sizeof(bmeshModelVertex));
|
|
||||||
v->vertex = *vertex;
|
v->vertex = *vertex;
|
||||||
v->indexOnModel = subdivAddVertex(bm->model, &v->vertex);
|
v->indexOnModel = subdivAddVertex(bm->model, &v->vertex);
|
||||||
if (-1 == hashtableInsert(bm->modelVertexHashtable,
|
|
||||||
(char *)0 + arrayGetLength(bm->modelVertexArray))) {
|
|
||||||
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return v->indexOnModel;
|
return v->indexOnModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshAddQuadToModel(bmesh *bm, quad *q) {
|
static void bmeshAddQuadToModel(bmesh *bm, quad *q) {
|
||||||
int indices[4];
|
int indices[4];
|
||||||
indices[0] = bmeshAddModelVertex(bm, &q->pt[0]);
|
indices[0] = bmeshAddModelVertex(bm, &q->pt[0]);
|
||||||
indices[1] = bmeshAddModelVertex(bm, &q->pt[1]);
|
indices[1] = bmeshAddModelVertex(bm, &q->pt[1]);
|
||||||
indices[2] = bmeshAddModelVertex(bm, &q->pt[2]);
|
indices[2] = bmeshAddModelVertex(bm, &q->pt[2]);
|
||||||
indices[3] = bmeshAddModelVertex(bm, &q->pt[3]);
|
indices[3] = bmeshAddModelVertex(bm, &q->pt[3]);
|
||||||
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2] ||
|
subdivAddQuadFace(bm->model, indices[0], indices[1], indices[2], indices[3]);
|
||||||
-1 == indices[3]) {
|
|
||||||
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (-1 == subdivAddQuadFace(bm->model, indices[0], indices[1], indices[2],
|
|
||||||
indices[3])) {
|
|
||||||
fprintf(stderr, "%s:subdivAddQuadFace failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshAddTriangleToModel(bmesh *bm, triangle *t) {
|
static void bmeshAddTriangleToModel(bmesh *bm, triangle *t) {
|
||||||
int indices[3];
|
int indices[3];
|
||||||
indices[0] = bmeshAddModelVertex(bm, &t->pt[0]);
|
indices[0] = bmeshAddModelVertex(bm, &t->pt[0]);
|
||||||
indices[1] = bmeshAddModelVertex(bm, &t->pt[1]);
|
indices[1] = bmeshAddModelVertex(bm, &t->pt[1]);
|
||||||
indices[2] = bmeshAddModelVertex(bm, &t->pt[2]);
|
indices[2] = bmeshAddModelVertex(bm, &t->pt[2]);
|
||||||
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2]) {
|
subdivAddTriangleFace(bm->model, indices[0], indices[1], indices[2]);
|
||||||
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (-1 == subdivAddTriangleFace(bm->model, indices[0], indices[1],
|
|
||||||
indices[2])) {
|
|
||||||
fprintf(stderr, "%s:subdivAddTriangleFace failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bmeshModelVertex *bmeshGetModelVertexByHashtableParam(void *userData,
|
|
||||||
const void *node) {
|
|
||||||
bmesh *bm = (bmesh *)userData;
|
|
||||||
int index = (char *)node - (char *)0;
|
|
||||||
if (0 == index) {
|
|
||||||
return &bm->findModelVertex;
|
|
||||||
}
|
|
||||||
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int modelVertexHash(void *userData, const void *node) {
|
static int modelVertexHash(void *userData, const void *node) {
|
||||||
bmeshModelVertex *v = bmeshGetModelVertexByHashtableParam(userData, node);
|
const bmeshModelVertex *v = node;
|
||||||
return abs(*((int *)v));
|
return abs(*((int *)v));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int modelVertexCompare(void *userData, const void *firstNode,
|
static int modelVertexCompare(void *userData, const void *firstNode,
|
||||||
const void *secondNode) {
|
const void *secondNode) {
|
||||||
bmeshModelVertex *v1 = bmeshGetModelVertexByHashtableParam(userData,
|
const bmeshModelVertex *v1 = firstNode;
|
||||||
firstNode);
|
const bmeshModelVertex *v2 = secondNode;
|
||||||
bmeshModelVertex *v2 = bmeshGetModelVertexByHashtableParam(userData,
|
|
||||||
secondNode);
|
|
||||||
if (0 == v1->vertex.x - v2->vertex.x &&
|
if (0 == v1->vertex.x - v2->vertex.x &&
|
||||||
0 == v1->vertex.y - v2->vertex.y &&
|
0 == v1->vertex.y - v2->vertex.y &&
|
||||||
0 == v1->vertex.z - v2->vertex.z) {
|
0 == v1->vertex.z - v2->vertex.z) {
|
||||||
|
@ -137,54 +91,16 @@ static int modelVertexCompare(void *userData, const void *firstNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
bmesh *bmeshCreate(void) {
|
bmesh *bmeshCreate(void) {
|
||||||
bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh));
|
bmesh *bm = dcalloc(1, sizeof(bmesh));
|
||||||
if (!bm) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->ballArray = arrayCreate(sizeof(bmeshBall));
|
bm->ballArray = arrayCreate(sizeof(bmeshBall));
|
||||||
if (!bm->ballArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate bmeshBall failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->boneArray = arrayCreate(sizeof(bmeshBone));
|
bm->boneArray = arrayCreate(sizeof(bmeshBone));
|
||||||
if (!bm->boneArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate bmeshBone failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->indexArray = arrayCreate(sizeof(bmeshBallIndex));
|
bm->indexArray = arrayCreate(sizeof(bmeshBallIndex));
|
||||||
if (!bm->indexArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate bmeshBallIndex failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->quadArray = arrayCreate(sizeof(quad));
|
bm->quadArray = arrayCreate(sizeof(quad));
|
||||||
if (!bm->quadArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->model = subdivCreateModel();
|
bm->model = subdivCreateModel();
|
||||||
if (!bm->model) {
|
|
||||||
fprintf(stderr, "%s:subdivCreateModel failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->modelVertexArray = arrayCreate(sizeof(bmeshModelVertex));
|
bm->modelVertexArray = arrayCreate(sizeof(bmeshModelVertex));
|
||||||
if (!bm->modelVertexArray) {
|
bm->modelVertexDict = dictCreate(bm->modelVertexArray,
|
||||||
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__);
|
BMESH_MODEL_VERTEX_HASHTABLE_SIZE,
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->modelVertexHashtable = hashtableCreate(BMESH_MODEL_VERTEX_HASHTABLE_SIZE,
|
|
||||||
modelVertexHash, modelVertexCompare, bm);
|
modelVertexHash, modelVertexCompare, bm);
|
||||||
if (!bm->modelVertexHashtable) {
|
|
||||||
fprintf(stderr, "%s:hashtableCreate quad failed.\n", __FUNCTION__);
|
|
||||||
bmeshDestroy(bm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bm->rootBallIndex = -1;
|
bm->rootBallIndex = -1;
|
||||||
bm->roundColor = 0;
|
bm->roundColor = 0;
|
||||||
return bm;
|
return bm;
|
||||||
|
@ -198,8 +114,8 @@ void bmeshDestroy(bmesh *bm) {
|
||||||
subdivDestroyModel(bm->model);
|
subdivDestroyModel(bm->model);
|
||||||
subdivDestroyModel(bm->subdivModel);
|
subdivDestroyModel(bm->subdivModel);
|
||||||
arrayDestroy(bm->modelVertexArray);
|
arrayDestroy(bm->modelVertexArray);
|
||||||
hashtableDestroy(bm->modelVertexHashtable);
|
dictDestroy(bm->modelVertexDict);
|
||||||
free(bm);
|
dfree(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshGetBallNum(bmesh *bm) {
|
int bmeshGetBallNum(bmesh *bm) {
|
||||||
|
@ -211,11 +127,11 @@ int bmeshGetBoneNum(bmesh *bm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bmeshBall *bmeshGetBall(bmesh *bm, int index) {
|
bmeshBall *bmeshGetBall(bmesh *bm, int index) {
|
||||||
return (bmeshBall *)arrayGetItem(bm->ballArray, index);
|
return arrayGetItem(bm->ballArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmeshBone *bmeshGetBone(bmesh *bm, int index) {
|
bmeshBone *bmeshGetBone(bmesh *bm, int index) {
|
||||||
return (bmeshBone *)arrayGetItem(bm->boneArray, index);
|
return arrayGetItem(bm->boneArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
|
int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
|
||||||
|
@ -224,10 +140,7 @@ int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
|
||||||
ball->firstChildIndex = -1;
|
ball->firstChildIndex = -1;
|
||||||
ball->childrenIndices = 0;
|
ball->childrenIndices = 0;
|
||||||
ball->notFitHull = 0;
|
ball->notFitHull = 0;
|
||||||
if (0 != arraySetLength(bm->ballArray, index + 1)) {
|
arraySetLength(bm->ballArray, index + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(arrayGetItem(bm->ballArray, index), ball, sizeof(bmeshBall));
|
memcpy(arrayGetItem(bm->ballArray, index), ball, sizeof(bmeshBall));
|
||||||
if (BMESH_BALL_TYPE_ROOT == ball->type) {
|
if (BMESH_BALL_TYPE_ROOT == ball->type) {
|
||||||
bm->rootBallIndex = index;
|
bm->rootBallIndex = index;
|
||||||
|
@ -235,41 +148,26 @@ int bmeshAddBall(bmesh *bm, bmeshBall *ball) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshAddChildBallRelation(bmesh *bm, int parentBallIndex,
|
static void bmeshAddChildBallRelation(bmesh *bm, int parentBallIndex,
|
||||||
int childBallIndex) {
|
int childBallIndex) {
|
||||||
bmeshBall *parentBall = bmeshGetBall(bm, parentBallIndex);
|
bmeshBall *parentBall = bmeshGetBall(bm, parentBallIndex);
|
||||||
bmeshBallIndex *indexItem;
|
bmeshBallIndex *indexItem;
|
||||||
int newChildIndex = arrayGetLength(bm->indexArray);
|
int newChildIndex = arrayGetLength(bm->indexArray);
|
||||||
if (0 != arraySetLength(bm->indexArray, newChildIndex + 1)) {
|
arraySetLength(bm->indexArray, newChildIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
indexItem = arrayGetItem(bm->indexArray, newChildIndex);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
indexItem = (bmeshBallIndex *)arrayGetItem(bm->indexArray, newChildIndex);
|
|
||||||
indexItem->ballIndex = childBallIndex;
|
indexItem->ballIndex = childBallIndex;
|
||||||
indexItem->nextChildIndex = parentBall->firstChildIndex;
|
indexItem->nextChildIndex = parentBall->firstChildIndex;
|
||||||
parentBall->firstChildIndex = newChildIndex;
|
parentBall->firstChildIndex = newChildIndex;
|
||||||
parentBall->childrenIndices++;
|
parentBall->childrenIndices++;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshAddBone(bmesh *bm, bmeshBone *bone) {
|
int bmeshAddBone(bmesh *bm, bmeshBone *bone) {
|
||||||
int index = arrayGetLength(bm->boneArray);
|
int index = arrayGetLength(bm->boneArray);
|
||||||
bone->index = index;
|
bone->index = index;
|
||||||
if (0 != arraySetLength(bm->boneArray, index + 1)) {
|
arraySetLength(bm->boneArray, index + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(arrayGetItem(bm->boneArray, index), bone, sizeof(bmeshBone));
|
memcpy(arrayGetItem(bm->boneArray, index), bone, sizeof(bmeshBone));
|
||||||
if (0 != bmeshAddChildBallRelation(bm, bone->firstBallIndex,
|
bmeshAddChildBallRelation(bm, bone->firstBallIndex, bone->secondBallIndex);
|
||||||
bone->secondBallIndex)) {
|
bmeshAddChildBallRelation(bm, bone->secondBallIndex, bone->firstBallIndex);
|
||||||
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (0 != bmeshAddChildBallRelation(bm, bone->secondBallIndex,
|
|
||||||
bone->firstBallIndex)) {
|
|
||||||
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,79 +181,21 @@ static int bmeshAddInbetweenBallBetween(bmesh *bm,
|
||||||
secondBall->radius * frac;
|
secondBall->radius * frac;
|
||||||
vec3Lerp(&firstBall->position, &secondBall->position, frac,
|
vec3Lerp(&firstBall->position, &secondBall->position, frac,
|
||||||
&newBall.position);
|
&newBall.position);
|
||||||
if (-1 == bmeshAddBall(bm, &newBall)) {
|
bmeshAddBall(bm, &newBall);
|
||||||
fprintf(stderr, "%s:bmeshAddBall failed.\n", __FUNCTION__);
|
bmeshAddChildBallRelation(bm, parentBallIndex, newBall.index);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (-1 == bmeshAddChildBallRelation(bm, parentBallIndex, newBall.index)) {
|
|
||||||
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return newBall.index;
|
return newBall.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static int bmeshGenerateBallCrossSection(bmesh *bm, bmeshBall *ball,
|
|
||||||
vec3 *boneDirection, vec3 *localYaxis, vec3 *localZaxis) {
|
|
||||||
//int i;
|
|
||||||
//quad q;
|
|
||||||
vec3 z, y;
|
|
||||||
//vec3Scale(localYaxis, ball->radius, &y);
|
|
||||||
//vec3Scale(localZaxis, ball->radius, &z);
|
|
||||||
vec3Sub(&ball->position, &y, &q.pt[0]);
|
|
||||||
vec3Add(&q.pt[0], &z, &q.pt[0]);
|
|
||||||
vec3Sub(&ball->position, &y, &q.pt[1]);
|
|
||||||
vec3Sub(&q.pt[1], &z, &q.pt[1]);
|
|
||||||
vec3Add(&ball->position, &y, &q.pt[2]);
|
|
||||||
vec3Sub(&q.pt[2], &z, &q.pt[2]);
|
|
||||||
vec3Add(&ball->position, &y, &q.pt[3]);
|
|
||||||
vec3Add(&q.pt[3], &z, &q.pt[3]);
|
|
||||||
ball->crossSection = q;
|
|
||||||
ball->boneDirection = *boneDirection;
|
|
||||||
if (-1 == bmeshAddQuad(bm, &q)) {
|
|
||||||
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (connectWithQuad >= 0) {
|
|
||||||
for (i = 0; i < 4; ++i) {
|
|
||||||
quad face;
|
|
||||||
quad *lastQ = bmeshGetQuad(bm, connectWithQuad);
|
|
||||||
face.pt[0].x = lastQ->pt[(0 + i) % 4].x;
|
|
||||||
face.pt[0].y = lastQ->pt[(0 + i) % 4].y;
|
|
||||||
face.pt[0].z = lastQ->pt[(0 + i) % 4].z;
|
|
||||||
face.pt[1].x = q.pt[(0 + i) % 4].x;
|
|
||||||
face.pt[1].y = q.pt[(0 + i) % 4].y;
|
|
||||||
face.pt[1].z = q.pt[(0 + i) % 4].z;
|
|
||||||
face.pt[2].x = q.pt[(1 + i) % 4].x;
|
|
||||||
face.pt[2].y = q.pt[(1 + i) % 4].y;
|
|
||||||
face.pt[2].z = q.pt[(1 + i) % 4].z;
|
|
||||||
face.pt[3].x = lastQ->pt[(1 + i) % 4].x;
|
|
||||||
face.pt[3].y = lastQ->pt[(1 + i) % 4].y;
|
|
||||||
face.pt[3].z = lastQ->pt[(1 + i) % 4].z;
|
|
||||||
if (-1 == bmeshAddQuad(bm, &face)) {
|
|
||||||
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static void generateYZfromBoneDirection(vec3 *boneDirection,
|
static void generateYZfromBoneDirection(vec3 *boneDirection,
|
||||||
vec3 *localYaxis, vec3 *localZaxis) {
|
vec3 *localYaxis, vec3 *localZaxis) {
|
||||||
vec3 worldYaxis = {0, 1, 0};
|
vec3 worldYaxis = {0, 1, 0};
|
||||||
vec3 worldXaxis = {1, 0, 0};
|
vec3CrossProduct(&worldYaxis, boneDirection, localYaxis);
|
||||||
//if (0 == vec3Angle(boneDirection, &worldYaxis)) {
|
|
||||||
// vec3CrossProduct(&worldXaxis, boneDirection, localYaxis);
|
|
||||||
//} else {
|
|
||||||
vec3CrossProduct(&worldYaxis, boneDirection, localYaxis);
|
|
||||||
//}
|
|
||||||
vec3Normalize(localYaxis);
|
vec3Normalize(localYaxis);
|
||||||
vec3CrossProduct(localYaxis, boneDirection, localZaxis);
|
vec3CrossProduct(localYaxis, boneDirection, localZaxis);
|
||||||
vec3Normalize(localZaxis);
|
vec3Normalize(localZaxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
static void bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
int firstBallIndex, int secondBallIndex) {
|
int firstBallIndex, int secondBallIndex) {
|
||||||
float step;
|
float step;
|
||||||
float distance;
|
float distance;
|
||||||
|
@ -368,8 +208,9 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
bmeshBall *secondBall = bmeshGetBall(bm, secondBallIndex);
|
bmeshBall *secondBall = bmeshGetBall(bm, secondBallIndex);
|
||||||
bmeshBall *newBall;
|
bmeshBall *newBall;
|
||||||
float intvalDist;
|
float intvalDist;
|
||||||
|
|
||||||
if (secondBall->roundColor == bm->roundColor) {
|
if (secondBall->roundColor == bm->roundColor) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3Sub(&firstBall->position, &secondBall->position, &boneDirection);
|
vec3Sub(&firstBall->position, &secondBall->position, &boneDirection);
|
||||||
|
@ -392,9 +233,6 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
float frac = offset / distance;
|
float frac = offset / distance;
|
||||||
parentBallIndex = bmeshAddInbetweenBallBetween(bm,
|
parentBallIndex = bmeshAddInbetweenBallBetween(bm,
|
||||||
firstBall, secondBall, frac, parentBallIndex);
|
firstBall, secondBall, frac, parentBallIndex);
|
||||||
if (-1 == parentBallIndex) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newBall = bmeshGetBall(bm, parentBallIndex);
|
newBall = bmeshGetBall(bm, parentBallIndex);
|
||||||
newBall->localYaxis = localYaxis;
|
newBall->localYaxis = localYaxis;
|
||||||
newBall->localZaxis = localZaxis;
|
newBall->localZaxis = localZaxis;
|
||||||
|
@ -404,20 +242,13 @@ static int bmeshGenerateInbetweenBallsBetween(bmesh *bm,
|
||||||
} else if (distance > step) {
|
} else if (distance > step) {
|
||||||
parentBallIndex = bmeshAddInbetweenBallBetween(bm, firstBall, secondBall,
|
parentBallIndex = bmeshAddInbetweenBallBetween(bm, firstBall, secondBall,
|
||||||
0.5, parentBallIndex);
|
0.5, parentBallIndex);
|
||||||
if (-1 == parentBallIndex) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newBall = bmeshGetBall(bm, parentBallIndex);
|
newBall = bmeshGetBall(bm, parentBallIndex);
|
||||||
newBall->localYaxis = localYaxis;
|
newBall->localYaxis = localYaxis;
|
||||||
newBall->localZaxis = localZaxis;
|
newBall->localZaxis = localZaxis;
|
||||||
newBall->boneDirection = normalizedBoneDirection;
|
newBall->boneDirection = normalizedBoneDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (-1 == bmeshAddChildBallRelation(bm, parentBallIndex, secondBallIndex)) {
|
bmeshAddChildBallRelation(bm, parentBallIndex, secondBallIndex);
|
||||||
fprintf(stderr, "%s:bmeshAddChildBallRelation failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bmeshBall *bmeshGetBallFirstChild(bmesh *bm, bmeshBall *ball,
|
bmeshBall *bmeshGetBallFirstChild(bmesh *bm, bmeshBall *ball,
|
||||||
|
@ -435,7 +266,7 @@ bmeshBall *bmeshGetBallNextChild(bmesh *bm, bmeshBall *ball,
|
||||||
if (-1 == *iterator) {
|
if (-1 == *iterator) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
indexItem = (bmeshBallIndex *)arrayGetItem(bm->indexArray, *iterator);
|
indexItem = arrayGetItem(bm->indexArray, *iterator);
|
||||||
*iterator = indexItem->nextChildIndex;
|
*iterator = indexItem->nextChildIndex;
|
||||||
return bmeshGetBall(bm, indexItem->ballIndex);
|
return bmeshGetBall(bm, indexItem->ballIndex);
|
||||||
}
|
}
|
||||||
|
@ -447,7 +278,7 @@ bmeshBall *bmeshGetRootBall(bmesh *bm) {
|
||||||
return bmeshGetBall(bm, bm->rootBallIndex);
|
return bmeshGetBall(bm, bm->rootBallIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
|
static void bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
|
||||||
bmeshBallIterator iterator;
|
bmeshBallIterator iterator;
|
||||||
int ballIndex;
|
int ballIndex;
|
||||||
bmeshBall *parent;
|
bmeshBall *parent;
|
||||||
|
@ -456,8 +287,9 @@ static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
|
||||||
|
|
||||||
parent = bmeshGetBall(bm, parentBallIndex);
|
parent = bmeshGetBall(bm, parentBallIndex);
|
||||||
if (parent->roundColor == bm->roundColor) {
|
if (parent->roundColor == bm->roundColor) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent->roundColor = bm->roundColor;
|
parent->roundColor = bm->roundColor;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -471,26 +303,11 @@ static int bmeshGenerateInbetweenBallsFrom(bmesh *bm, int parentBallIndex) {
|
||||||
oldChildrenIndices = parent->childrenIndices;
|
oldChildrenIndices = parent->childrenIndices;
|
||||||
parent->childrenIndices = 0;
|
parent->childrenIndices = 0;
|
||||||
|
|
||||||
for (;
|
for (; ball; ball = bmeshGetBallNextChild(bm, parent, &iterator)) {
|
||||||
ball;
|
|
||||||
ball = bmeshGetBallNextChild(bm, parent, &iterator)) {
|
|
||||||
ballIndex = ball->index;
|
ballIndex = ball->index;
|
||||||
if (0 != bmeshGenerateInbetweenBallsBetween(bm, parentBallIndex,
|
bmeshGenerateInbetweenBallsBetween(bm, parentBallIndex, ballIndex);
|
||||||
ballIndex)) {
|
bmeshGenerateInbetweenBallsFrom(bm, ballIndex);
|
||||||
fprintf(stderr,
|
|
||||||
"%s:bmeshGenerateInbetweenBallsBetween failed(parentBallIndex:%d).\n",
|
|
||||||
__FUNCTION__, parentBallIndex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (0 != bmeshGenerateInbetweenBallsFrom(bm, ballIndex)) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s:bmeshGenerateInbetweenBallsFrom failed(ballIndex:%d).\n",
|
|
||||||
__FUNCTION__, ballIndex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshGenerateInbetweenBalls(bmesh *bm) {
|
int bmeshGenerateInbetweenBalls(bmesh *bm) {
|
||||||
|
@ -499,7 +316,8 @@ int bmeshGenerateInbetweenBalls(bmesh *bm) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bm->roundColor++;
|
bm->roundColor++;
|
||||||
return bmeshGenerateInbetweenBallsFrom(bm, bm->rootBallIndex);
|
bmeshGenerateInbetweenBallsFrom(bm, bm->rootBallIndex);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshGetQuadNum(bmesh *bm) {
|
int bmeshGetQuadNum(bmesh *bm) {
|
||||||
|
@ -507,25 +325,21 @@ int bmeshGetQuadNum(bmesh *bm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
quad *bmeshGetQuad(bmesh *bm, int index) {
|
quad *bmeshGetQuad(bmesh *bm, int index) {
|
||||||
return (quad *)arrayGetItem(bm->quadArray, index);
|
return arrayGetItem(bm->quadArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshAddQuad(bmesh *bm, quad *q) {
|
int bmeshAddQuad(bmesh *bm, quad *q) {
|
||||||
int index = arrayGetLength(bm->quadArray);
|
int index = arrayGetLength(bm->quadArray);
|
||||||
if (0 != arraySetLength(bm->quadArray, index + 1)) {
|
arraySetLength(bm->quadArray, index + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(arrayGetItem(bm->quadArray, index), q, sizeof(quad));
|
memcpy(arrayGetItem(bm->quadArray, index), q, sizeof(quad));
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
static void bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
||||||
int result = 0;
|
|
||||||
bmeshBallIterator iterator;
|
bmeshBallIterator iterator;
|
||||||
bmeshBall *child = 0;
|
bmeshBall *child = 0;
|
||||||
if (bm->roundColor == ball->roundColor) {
|
if (bm->roundColor == ball->roundColor) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
ball->roundColor = bm->roundColor;
|
ball->roundColor = bm->roundColor;
|
||||||
if (BMESH_BALL_TYPE_KEY == ball->type) {
|
if (BMESH_BALL_TYPE_KEY == ball->type) {
|
||||||
|
@ -555,18 +369,14 @@ static int bmeshSweepFrom(bmesh *bm, bmeshBall *parent, bmeshBall *ball) {
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||||
result = bmeshSweepFrom(bm, ball, child);
|
bmeshSweepFrom(bm, ball, child);
|
||||||
if (0 != result) {
|
|
||||||
fprintf(stderr, "%s:bmeshSweepFrom failed.\n", __FUNCTION__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshSweep(bmesh *bm) {
|
int bmeshSweep(bmesh *bm) {
|
||||||
bm->roundColor++;
|
bm->roundColor++;
|
||||||
return bmeshSweepFrom(bm, 0, bmeshGetRootBall(bm));
|
bmeshSweepFrom(bm, 0, bmeshGetRootBall(bm));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isDistanceEnoughForConvexHull(bmeshBall *root,
|
static int isDistanceEnoughForConvexHull(bmeshBall *root,
|
||||||
|
@ -609,7 +419,7 @@ static bmeshBall *bmeshFindParentBallForConvexHull(bmesh *bm, bmeshBall *root,
|
||||||
bm->parentBallStack[depth - 1]);
|
bm->parentBallStack[depth - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
|
static void addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
|
||||||
bmeshBall **outmostBall, int *outmostBallFirstVertexIndex) {
|
bmeshBall **outmostBall, int *outmostBallFirstVertexIndex) {
|
||||||
vec3 z, y;
|
vec3 z, y;
|
||||||
quad q;
|
quad q;
|
||||||
|
@ -635,11 +445,6 @@ static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
|
||||||
ballForConvexHull->index, 2);
|
ballForConvexHull->index, 2);
|
||||||
vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3],
|
vertexIndex[3] = convexHullAddVertex(hull, &q.pt[3],
|
||||||
ballForConvexHull->index, 3);
|
ballForConvexHull->index, 3);
|
||||||
if (-1 == vertexIndex[0] || -1 == vertexIndex[1] || -1 == vertexIndex[2] ||
|
|
||||||
-1 == vertexIndex[3]) {
|
|
||||||
fprintf(stderr, "%s:convexHullAddVertex failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*outmostBall) {
|
if (*outmostBall) {
|
||||||
if (ballForConvexHull->radius > (*outmostBall)->radius) {
|
if (ballForConvexHull->radius > (*outmostBall)->radius) {
|
||||||
|
@ -652,14 +457,8 @@ static int addBallToHull(convexHull *hull, bmeshBall *ballForConvexHull,
|
||||||
*outmostBall = ballForConvexHull;
|
*outmostBall = ballForConvexHull;
|
||||||
*outmostBallFirstVertexIndex = vertexIndex[0];
|
*outmostBallFirstVertexIndex = vertexIndex[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "osutil.h"
|
|
||||||
int showFaceIndex = 10000000;
|
|
||||||
static long long lastShowFaceIndexIncTime = 0;
|
|
||||||
|
|
||||||
static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
||||||
bmeshBall *ball, int *needRetry) {
|
bmeshBall *ball, int *needRetry) {
|
||||||
convexHull *hull;
|
convexHull *hull;
|
||||||
|
@ -676,74 +475,33 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
||||||
*needRetry = 0;
|
*needRetry = 0;
|
||||||
|
|
||||||
ballPtrArray = arrayCreate(sizeof(bmeshBall *));
|
ballPtrArray = arrayCreate(sizeof(bmeshBall *));
|
||||||
if (!ballPtrArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull = convexHullCreate();
|
hull = convexHullCreate();
|
||||||
if (!hull) {
|
|
||||||
fprintf(stderr, "%s:convexHullCreate failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (BMESH_BALL_TYPE_KEY == ball->type) {
|
if (BMESH_BALL_TYPE_KEY == ball->type) {
|
||||||
bmeshBall reduceBall = *ball;
|
bmeshBall reduceBall = *ball;
|
||||||
reduceBall.radius *= 0.4;
|
reduceBall.radius *= 0.4;
|
||||||
if (-1 == addBallToHull(hull, &reduceBall,
|
addBallToHull(hull, &reduceBall, &outmostBall,
|
||||||
&outmostBall, &outmostBallFirstVertexIndex)) {
|
&outmostBallFirstVertexIndex);
|
||||||
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||||
ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child);
|
ballForConvexHull = bmeshFindChildBallForConvexHull(bm, ball, child);
|
||||||
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
|
ballPtr = arrayNewItem(ballPtrArray);
|
||||||
if (!ballPtr) {
|
|
||||||
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*ballPtr = ballForConvexHull;
|
*ballPtr = ballForConvexHull;
|
||||||
if (-1 == addBallToHull(hull, ballForConvexHull,
|
addBallToHull(hull, ballForConvexHull, &outmostBall,
|
||||||
&outmostBall, &outmostBallFirstVertexIndex)) {
|
&outmostBallFirstVertexIndex);
|
||||||
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) {
|
if (depth > 0 && depth - 1 < BMESH_MAX_PARENT_BALL_DEPTH) {
|
||||||
ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1,
|
ballForConvexHull = bmeshFindParentBallForConvexHull(bm, ball, depth - 1,
|
||||||
bm->parentBallStack[depth - 1]);
|
bm->parentBallStack[depth - 1]);
|
||||||
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
|
ballPtr = (bmeshBall **)arrayNewItem(ballPtrArray);
|
||||||
if (!ballPtr) {
|
|
||||||
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*ballPtr = ballForConvexHull;
|
*ballPtr = ballForConvexHull;
|
||||||
if (-1 == addBallToHull(hull, ballForConvexHull,
|
addBallToHull(hull, ballForConvexHull, &outmostBall,
|
||||||
&outmostBall, &outmostBallFirstVertexIndex)) {
|
&outmostBallFirstVertexIndex);
|
||||||
fprintf(stderr, "%s:addBallToHull failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (outmostBall) {
|
if (outmostBall) {
|
||||||
if (-1 == convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0,
|
convexHullAddTodo(hull, outmostBallFirstVertexIndex + 0,
|
||||||
outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2)) {
|
outmostBallFirstVertexIndex + 1, outmostBallFirstVertexIndex + 2);
|
||||||
fprintf(stderr, "%s:convexHullAddTodo failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
|
for (i = 0; i < arrayGetLength(ballPtrArray); ++i) {
|
||||||
|
@ -751,12 +509,7 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
||||||
ballItem->flagForHull = 0;
|
ballItem->flagForHull = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 == convexHullGenerate(hull)) {
|
convexHullGenerate(hull);
|
||||||
fprintf(stderr, "%s:convexHullGenerate failed.\n", __FUNCTION__);
|
|
||||||
arrayDestroy(ballPtrArray);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
convexHullUnifyNormals(hull, &ball->position);
|
convexHullUnifyNormals(hull, &ball->position);
|
||||||
convexHullMergeTriangles(hull);
|
convexHullMergeTriangles(hull);
|
||||||
|
@ -764,7 +517,7 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
||||||
for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
|
for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
|
||||||
convexHullFace *f = (convexHullFace *)convexHullGetFace(hull, i);
|
convexHullFace *f = (convexHullFace *)convexHullGetFace(hull, i);
|
||||||
if (-1 != f->plane) {
|
if (-1 != f->plane) {
|
||||||
bmeshBall *ballItem = (bmeshBall *)arrayGetItem(bm->ballArray, f->plane);
|
bmeshBall *ballItem = arrayGetItem(bm->ballArray, f->plane);
|
||||||
ballItem->flagForHull = 1;
|
ballItem->flagForHull = 1;
|
||||||
f->vertexNum = 0;
|
f->vertexNum = 0;
|
||||||
}
|
}
|
||||||
|
@ -804,13 +557,14 @@ static convexHull *createConvexHullForBall(bmesh *bm, int depth,
|
||||||
return hull;
|
return hull;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
|
static void bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
|
||||||
bmeshBallIterator iterator;
|
bmeshBallIterator iterator;
|
||||||
bmeshBall *child;
|
bmeshBall *child;
|
||||||
int result = 0;
|
|
||||||
if (bm->roundColor == ball->roundColor) {
|
if (bm->roundColor == ball->roundColor) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
|
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
|
||||||
bm->parentBallStack[depth] = ball;
|
bm->parentBallStack[depth] = ball;
|
||||||
}
|
}
|
||||||
|
@ -841,19 +595,13 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
|
||||||
q.pt[1] = convexHullGetVertex(hull, face->u.q.indices[1])->pt;
|
q.pt[1] = convexHullGetVertex(hull, face->u.q.indices[1])->pt;
|
||||||
q.pt[2] = convexHullGetVertex(hull, face->u.q.indices[2])->pt;
|
q.pt[2] = convexHullGetVertex(hull, face->u.q.indices[2])->pt;
|
||||||
q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt;
|
q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt;
|
||||||
result = bmeshAddQuadToModel(bm, &q);
|
bmeshAddQuadToModel(bm, &q);
|
||||||
if (-1 == result) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (3 == face->vertexNum) {
|
} else if (3 == face->vertexNum) {
|
||||||
triangle t;
|
triangle t;
|
||||||
t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
|
t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
|
||||||
t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
|
t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
|
||||||
t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
|
t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
|
||||||
result = bmeshAddTriangleToModel(bm, &t);
|
bmeshAddTriangleToModel(bm, &t);
|
||||||
if (-1 == result) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
convexHullDestroy(hull);
|
convexHullDestroy(hull);
|
||||||
|
@ -863,19 +611,15 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||||
result = bmeshStichFrom(bm, depth + 1, child);
|
bmeshStichFrom(bm, depth + 1, child);
|
||||||
if (0 != result) {
|
|
||||||
fprintf(stderr, "%s:bmeshSweepFrom failed.\n", __FUNCTION__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshStitch(bmesh *bm) {
|
int bmeshStitch(bmesh *bm) {
|
||||||
bm->roundColor++;
|
bm->roundColor++;
|
||||||
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
|
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
|
||||||
return bmeshStichFrom(bm, 0, bmeshGetRootBall(bm));
|
bmeshStichFrom(bm, 0, bmeshGetRootBall(bm));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rollQuadVertexs(quad *q) {
|
static void rollQuadVertexs(quad *q) {
|
||||||
|
@ -938,11 +682,7 @@ static int bmeshAddWallsBetweenQuadsToModel(bmesh *bm, vec3 *origin, quad *q1,
|
||||||
wall.pt[j] = oldWall.pt[3 - j];
|
wall.pt[j] = oldWall.pt[3 - j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = bmeshAddQuadToModel(bm, &wall);
|
bmeshAddQuadToModel(bm, &wall);
|
||||||
if (-1 == result) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//drawQuad(&wall);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -960,15 +700,15 @@ static bmeshBall *bmeshFindChildBallForInbetweenMesh(bmesh *bm, bmeshBall *ball)
|
||||||
return bmeshFindChildBallForInbetweenMesh(bm, child);
|
return bmeshFindChildBallForInbetweenMesh(bm, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
static void bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
||||||
bmeshBall *ball) {
|
bmeshBall *ball) {
|
||||||
int result = 0;
|
|
||||||
bmeshBallIterator iterator;
|
bmeshBallIterator iterator;
|
||||||
bmeshBall *child = 0;
|
bmeshBall *child = 0;
|
||||||
bmeshBall *parent;
|
bmeshBall *parent;
|
||||||
quad currentFace, childFace;
|
quad currentFace, childFace;
|
||||||
|
|
||||||
if (bm->roundColor == ball->roundColor) {
|
if (bm->roundColor == ball->roundColor) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
|
if (depth < BMESH_MAX_PARENT_BALL_DEPTH) {
|
||||||
bm->parentBallStack[depth] = ball;
|
bm->parentBallStack[depth] = ball;
|
||||||
|
@ -986,10 +726,7 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
||||||
calculateBallQuad(&fakeBall, &childFace);
|
calculateBallQuad(&fakeBall, &childFace);
|
||||||
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
||||||
&childFace);
|
&childFace);
|
||||||
result = bmeshAddQuadToModel(bm, &childFace);
|
bmeshAddQuadToModel(bm, &childFace);
|
||||||
if (-1 == result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
drawQuad(&childFace);
|
drawQuad(&childFace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,11 +739,8 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
||||||
//} else {
|
//} else {
|
||||||
child = bmeshFindChildBallForInbetweenMesh(bm, child);
|
child = bmeshFindChildBallForInbetweenMesh(bm, child);
|
||||||
calculateBallQuad(child, &childFace);
|
calculateBallQuad(child, &childFace);
|
||||||
result = bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
||||||
&childFace);
|
&childFace);
|
||||||
if (-1 == result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
//}
|
//}
|
||||||
ball->meshGenerated = 1;
|
ball->meshGenerated = 1;
|
||||||
child->meshGenerated = 1;
|
child->meshGenerated = 1;
|
||||||
|
@ -1015,20 +749,15 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
||||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||||
child;
|
child;
|
||||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||||
result = bmeshGenerateInbetweenMeshFrom(bm, depth + 1, child);
|
bmeshGenerateInbetweenMeshFrom(bm, depth + 1, child);
|
||||||
if (0 != result) {
|
|
||||||
fprintf(stderr, "%s:bmeshGenerateInbetweenMeshFrom failed.\n",
|
|
||||||
__FUNCTION__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshGenerateInbetweenMesh(bmesh *bm) {
|
int bmeshGenerateInbetweenMesh(bmesh *bm) {
|
||||||
bm->roundColor++;
|
bm->roundColor++;
|
||||||
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
|
memset(bm->parentBallStack, 0, sizeof(bm->parentBallStack));
|
||||||
return bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(bm));
|
bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(bm));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bmeshGenerate(bmesh *bm) {
|
int bmeshGenerate(bmesh *bm) {
|
||||||
|
|
334
src/convexhull.c
334
src/convexhull.c
|
@ -2,9 +2,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "dmemory.h"
|
||||||
#include "convexhull.h"
|
#include "convexhull.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "hashtable.h"
|
#include "dict.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -32,11 +33,9 @@ struct convexHull {
|
||||||
array *faceArray;
|
array *faceArray;
|
||||||
int nextTodoIndex;
|
int nextTodoIndex;
|
||||||
unsigned int *openEdgeProcessedMap;
|
unsigned int *openEdgeProcessedMap;
|
||||||
hashtable *face3Hashtable;
|
dict *face3Dict;
|
||||||
face3 findFace3;
|
|
||||||
array *edgeArray;
|
array *edgeArray;
|
||||||
hashtable *edgeHashtable;
|
dict *edgeDict;
|
||||||
edge findEdge;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -49,46 +48,26 @@ static int cantorPair(int k1, int k2) {
|
||||||
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
|
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
|
||||||
}
|
}
|
||||||
|
|
||||||
face3 *convexHullGetFaceByHashtableParam(void *userData, const void *node) {
|
|
||||||
convexHull *hull = (convexHull *)userData;
|
|
||||||
int index = (char *)node - (char *)0;
|
|
||||||
if (0 == index) {
|
|
||||||
return &hull->findFace3;
|
|
||||||
}
|
|
||||||
return (face3 *)arrayGetItem(hull->faceArray, index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int face3Hash(void *userData, const void *node) {
|
static int face3Hash(void *userData, const void *node) {
|
||||||
face3 *face = convexHullGetFaceByHashtableParam(userData, node);
|
const face3 *face = node;
|
||||||
return cantorPair(cantorPair(face->indices[0], face->indices[1]),
|
return cantorPair(cantorPair(face->indices[0], face->indices[1]),
|
||||||
face->indices[2]);
|
face->indices[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
edge *convexHullGetEdgeByHashtableParam(void *userData, const void *node) {
|
|
||||||
convexHull *hull = (convexHull *)userData;
|
|
||||||
int index = (char *)node - (char *)0;
|
|
||||||
if (0 == index) {
|
|
||||||
return &hull->findEdge;
|
|
||||||
}
|
|
||||||
return (edge *)arrayGetItem(hull->edgeArray, index - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int edgeHash(void *userData, const void *node) {
|
static int edgeHash(void *userData, const void *node) {
|
||||||
edge *e = convexHullGetEdgeByHashtableParam(userData, node);
|
const edge *e = node;
|
||||||
return e->p1 < e->p2 ? cantorPair(e->p1, e->p2) : cantorPair(e->p2, e->p1);
|
return e->p1 < e->p2 ? cantorPair(e->p1, e->p2) : cantorPair(e->p2, e->p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int face3Compare(void *userData, const void *node1,
|
static int face3Compare(void *userData, const void *node1,
|
||||||
const void *node2) {
|
const void *node2) {
|
||||||
face3 *f1 = convexHullGetFaceByHashtableParam(userData, node1);
|
return memcmp(node1, node2, sizeof(face3));
|
||||||
face3 *f2 = convexHullGetFaceByHashtableParam(userData, node2);
|
|
||||||
return memcmp(f1, f2, sizeof(face3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edgeCompare(void *userData, const void *node1,
|
static int edgeCompare(void *userData, const void *node1,
|
||||||
const void *node2) {
|
const void *node2) {
|
||||||
edge *e1 = convexHullGetEdgeByHashtableParam(userData, node1);
|
const edge *e1 = node1;
|
||||||
edge *e2 = convexHullGetEdgeByHashtableParam(userData, node2);
|
const edge *e2 = node2;
|
||||||
if ((e1->p1 == e2->p1 && e1->p2 == e2->p2) ||
|
if ((e1->p1 == e2->p1 && e1->p2 == e2->p2) ||
|
||||||
(e1->p2 == e2->p1 && e1->p1 == e2->p2)) {
|
(e1->p2 == e2->p1 && e1->p1 == e2->p2)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -97,74 +76,34 @@ static int edgeCompare(void *userData, const void *node1,
|
||||||
}
|
}
|
||||||
|
|
||||||
convexHull *convexHullCreate(void) {
|
convexHull *convexHullCreate(void) {
|
||||||
convexHull *hull = (convexHull *)calloc(1, sizeof(convexHull));
|
convexHull *hull = dcalloc(1, sizeof(convexHull));
|
||||||
if (!hull) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->vertexArray = arrayCreate(sizeof(convexHullVertex));
|
hull->vertexArray = arrayCreate(sizeof(convexHullVertex));
|
||||||
if (!hull->vertexArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->todoArray = arrayCreate(sizeof(todo));
|
hull->todoArray = arrayCreate(sizeof(todo));
|
||||||
if (!hull->todoArray) {
|
|
||||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->faceArray = arrayCreate(sizeof(convexHullFace));
|
hull->faceArray = arrayCreate(sizeof(convexHullFace));
|
||||||
if (!hull->faceArray) {
|
hull->face3Dict = dictCreate(hull->faceArray, FACE3_HASHTABLE_SIZE,
|
||||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->face3Hashtable = hashtableCreate(FACE3_HASHTABLE_SIZE,
|
|
||||||
face3Hash, face3Compare, hull);
|
face3Hash, face3Compare, hull);
|
||||||
if (!hull->face3Hashtable) {
|
|
||||||
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->edgeArray = arrayCreate(sizeof(edge));
|
hull->edgeArray = arrayCreate(sizeof(edge));
|
||||||
if (!hull->edgeArray) {
|
hull->edgeDict = dictCreate(hull->edgeArray, EDGE_HASHTABLE_SIZE,
|
||||||
fprintf(stderr, "%s:arrayCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
hull->edgeHashtable = hashtableCreate(EDGE_HASHTABLE_SIZE,
|
|
||||||
edgeHash, edgeCompare, hull);
|
edgeHash, edgeCompare, hull);
|
||||||
if (!hull->edgeHashtable) {
|
|
||||||
fprintf(stderr, "%s:hashtableCreate failed.\n", __FUNCTION__);
|
|
||||||
convexHullDestroy(hull);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return hull;
|
return hull;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge *convexHullFindEdge(convexHull *hull, int p1, int p2) {
|
edge *convexHullFindEdge(convexHull *hull, int p1, int p2) {
|
||||||
int index;
|
edge findEdge;
|
||||||
hull->findEdge.p1 = p1;
|
findEdge.p1 = p1;
|
||||||
hull->findEdge.p2 = p2;
|
findEdge.p2 = p2;
|
||||||
index = (char *)hashtableGet(hull->edgeHashtable, 0) - (char *)0;
|
return dictFind(hull->edgeDict, &findEdge);
|
||||||
if (0 == index) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return arrayGetItem(hull->edgeArray, index - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
|
void convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
|
||||||
int face) {
|
int face) {
|
||||||
edge *e = convexHullFindEdge(hull, p1, p2);
|
edge findEdge;
|
||||||
|
edge *e;
|
||||||
|
findEdge.p1 = p1;
|
||||||
|
findEdge.p2 = p2;
|
||||||
|
e = dictFind(hull->edgeDict, &findEdge);
|
||||||
if (!e) {
|
if (!e) {
|
||||||
int newIndex = arrayGetLength(hull->edgeArray);
|
e = dictGetClear(hull->edgeDict, &findEdge);
|
||||||
if (0 != arraySetLength(hull->edgeArray, newIndex + 1)) {
|
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
e = (edge *)arrayGetItem(hull->edgeArray, newIndex);
|
|
||||||
memset(e, 0, sizeof(edge));
|
|
||||||
e->p1 = p1;
|
e->p1 = p1;
|
||||||
e->p2 = p2;
|
e->p2 = p2;
|
||||||
e->hill1 = hill;
|
e->hill1 = hill;
|
||||||
|
@ -174,17 +113,12 @@ int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
|
||||||
vec3Normal((vec3 *)arrayGetItem(hull->vertexArray, e->p1),
|
vec3Normal((vec3 *)arrayGetItem(hull->vertexArray, e->p1),
|
||||||
(vec3 *)arrayGetItem(hull->vertexArray, e->p2),
|
(vec3 *)arrayGetItem(hull->vertexArray, e->p2),
|
||||||
(vec3 *)arrayGetItem(hull->vertexArray, e->hill1), &e->hill1Normal);
|
(vec3 *)arrayGetItem(hull->vertexArray, e->hill1), &e->hill1Normal);
|
||||||
if (0 != hashtableInsert(hull->edgeHashtable, (char *)0 + newIndex + 1)) {
|
return;
|
||||||
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
assert(-1 == e->hill2);
|
assert(-1 == e->hill2);
|
||||||
assert(-1 == e->face2);
|
assert(-1 == e->face2);
|
||||||
e->hill2 = hill;
|
e->hill2 = hill;
|
||||||
e->face2 = face;
|
e->face2 = face;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
|
void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
|
||||||
|
@ -212,41 +146,20 @@ int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
|
||||||
int orderOnPlane) {
|
int orderOnPlane) {
|
||||||
convexHullVertex *vtx;
|
convexHullVertex *vtx;
|
||||||
int newVertex = arrayGetLength(hull->vertexArray);
|
int newVertex = arrayGetLength(hull->vertexArray);
|
||||||
if (0 != arraySetLength(hull->vertexArray, newVertex + 1)) {
|
arraySetLength(hull->vertexArray, newVertex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
vtx = arrayGetItem(hull->vertexArray, newVertex);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
vtx = (convexHullVertex *)arrayGetItem(hull->vertexArray, newVertex);
|
|
||||||
vtx->plane = plane;
|
vtx->plane = plane;
|
||||||
vtx->orderOnPlane = orderOnPlane;
|
vtx->orderOnPlane = orderOnPlane;
|
||||||
vtx->pt = *vertex;
|
vtx->pt = *vertex;
|
||||||
return newVertex;
|
return newVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullAddTodoNoCheck(convexHull *hull, int firstVertex,
|
void convexHullAddTodoNoCheck(convexHull *hull, int firstVertex,
|
||||||
int secondVertex, int thirdVertex) {
|
int secondVertex, int thirdVertex) {
|
||||||
todo *t;
|
todo *t = arrayNewItemClear(hull->todoArray);
|
||||||
int newEdge = arrayGetLength(hull->todoArray);
|
|
||||||
if (firstVertex < 0 || secondVertex < 0) {
|
|
||||||
fprintf(stderr, "%s:Invalid params(firstVertex:%d secondVertex:%d).\n",
|
|
||||||
__FUNCTION__, firstVertex, secondVertex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (0 != arraySetLength(hull->todoArray, newEdge + 1)) {
|
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
t = (todo *)arrayGetItem(hull->todoArray, newEdge);
|
|
||||||
memset(t, 0, sizeof(todo));
|
|
||||||
t->firstVertex = firstVertex;
|
t->firstVertex = firstVertex;
|
||||||
t->secondVertex = secondVertex;
|
t->secondVertex = secondVertex;
|
||||||
t->thirdVertex = thirdVertex;
|
t->thirdVertex = thirdVertex;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isInAdjacentOrder(int order1, int order2) {
|
|
||||||
return ((order1 + 1) % 4 == order2 ||
|
|
||||||
(order2 + 1) % 4 == order1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sortface(const void *first, const void *second) {
|
static int sortface(const void *first, const void *second) {
|
||||||
|
@ -255,7 +168,7 @@ static int sortface(const void *first, const void *second) {
|
||||||
return *firstIndex - *secondIndex;
|
return *firstIndex - *secondIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
|
void convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
|
||||||
int thirdVertex) {
|
int thirdVertex) {
|
||||||
face3 *tri;
|
face3 *tri;
|
||||||
convexHullVertex *vtx1;
|
convexHullVertex *vtx1;
|
||||||
|
@ -263,62 +176,35 @@ int convexHullAddFace3(convexHull *hull, int firstVertex, int secondVertex,
|
||||||
convexHullVertex *vtx3;
|
convexHullVertex *vtx3;
|
||||||
int newTri;
|
int newTri;
|
||||||
int facePlane = -1;
|
int facePlane = -1;
|
||||||
|
face3 findFace3;
|
||||||
|
|
||||||
vtx1 = (convexHullVertex *)arrayGetItem(hull->vertexArray, firstVertex);
|
vtx1 = arrayGetItem(hull->vertexArray, firstVertex);
|
||||||
vtx2 = (convexHullVertex *)arrayGetItem(hull->vertexArray, secondVertex);
|
vtx2 = arrayGetItem(hull->vertexArray, secondVertex);
|
||||||
vtx3 = (convexHullVertex *)arrayGetItem(hull->vertexArray, thirdVertex);
|
vtx3 = arrayGetItem(hull->vertexArray, thirdVertex);
|
||||||
|
|
||||||
if (vtx1->plane == vtx2->plane && vtx1->plane == vtx3->plane) {
|
if (vtx1->plane == vtx2->plane && vtx1->plane == vtx3->plane) {
|
||||||
facePlane = vtx1->plane;
|
facePlane = vtx1->plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
memset(&findFace3, 0, sizeof(findFace3));
|
||||||
if (vtx1->plane == vtx2->plane) {
|
findFace3.indices[0] = firstVertex;
|
||||||
if (!isInAdjacentOrder(vtx1->orderOnPlane, vtx2->orderOnPlane)) {
|
findFace3.indices[1] = secondVertex;
|
||||||
return 0;
|
findFace3.indices[2] = thirdVertex;
|
||||||
}
|
qsort(&findFace3.indices, 3, sizeof(findFace3.indices[0]), sortface);
|
||||||
}
|
if (!dictFind(hull->face3Dict, &findFace3)) {
|
||||||
if (vtx1->plane == vtx3->plane) {
|
|
||||||
if (!isInAdjacentOrder(vtx1->orderOnPlane, vtx3->orderOnPlane)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vtx2->plane == vtx3->plane) {
|
|
||||||
if (!isInAdjacentOrder(vtx2->orderOnPlane, vtx3->orderOnPlane)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
memset(&hull->findFace3, 0, sizeof(hull->findFace3));
|
|
||||||
hull->findFace3.indices[0] = firstVertex;
|
|
||||||
hull->findFace3.indices[1] = secondVertex;
|
|
||||||
hull->findFace3.indices[2] = thirdVertex;
|
|
||||||
qsort(hull->findFace3.indices, 3,
|
|
||||||
sizeof(hull->findFace3.indices[0]), sortface);
|
|
||||||
if (0 == hashtableGet(hull->face3Hashtable, 0)) {
|
|
||||||
newTri = arrayGetLength(hull->faceArray);
|
newTri = arrayGetLength(hull->faceArray);
|
||||||
if (0 != arraySetLength(hull->faceArray, newTri + 1)) {
|
tri = dictGetClear(hull->face3Dict, &findFace3);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
*tri = findFace3;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tri = (face3 *)arrayGetItem(hull->faceArray, newTri);
|
|
||||||
((convexHullFace *)tri)->vertexNum = 3;
|
((convexHullFace *)tri)->vertexNum = 3;
|
||||||
((convexHullFace *)tri)->plane = facePlane;
|
((convexHullFace *)tri)->plane = facePlane;
|
||||||
*tri = hull->findFace3;
|
|
||||||
if (0 != hashtableInsert(hull->face3Hashtable,
|
|
||||||
(char *)0 + newTri + 1)) {
|
|
||||||
fprintf(stderr, "%s:hashtableInsert failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
convexHullAddEdge(hull, firstVertex, secondVertex, thirdVertex, newTri);
|
convexHullAddEdge(hull, firstVertex, secondVertex, thirdVertex, newTri);
|
||||||
convexHullAddEdge(hull, secondVertex, thirdVertex, firstVertex, newTri);
|
convexHullAddEdge(hull, secondVertex, thirdVertex, firstVertex, newTri);
|
||||||
convexHullAddEdge(hull, thirdVertex, firstVertex, secondVertex, newTri);
|
convexHullAddEdge(hull, thirdVertex, firstVertex, secondVertex, newTri);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convexHullReleaseForGenerate(convexHull *hull) {
|
static void convexHullReleaseForGenerate(convexHull *hull) {
|
||||||
free(hull->openEdgeProcessedMap);
|
dfree(hull->openEdgeProcessedMap);
|
||||||
hull->openEdgeProcessedMap = 0;
|
hull->openEdgeProcessedMap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,31 +213,26 @@ void convexHullDestroy(convexHull *hull) {
|
||||||
arrayDestroy(hull->todoArray);
|
arrayDestroy(hull->todoArray);
|
||||||
arrayDestroy(hull->faceArray);
|
arrayDestroy(hull->faceArray);
|
||||||
arrayDestroy(hull->edgeArray);
|
arrayDestroy(hull->edgeArray);
|
||||||
hashtableDestroy(hull->edgeHashtable);
|
dictDestroy(hull->edgeDict);
|
||||||
hashtableDestroy(hull->face3Hashtable);
|
dictDestroy(hull->face3Dict);
|
||||||
convexHullReleaseForGenerate(hull);
|
convexHullReleaseForGenerate(hull);
|
||||||
free(hull);
|
dfree(hull);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int convexHullPrepareForGenerate(convexHull *hull) {
|
static void convexHullPrepareForGenerate(convexHull *hull) {
|
||||||
free(hull->openEdgeProcessedMap);
|
dfree(hull->openEdgeProcessedMap);
|
||||||
hull->openEdgeProcessedMap = (unsigned int *)calloc(
|
hull->openEdgeProcessedMap = dcalloc(
|
||||||
arrayGetLength(hull->vertexArray) * arrayGetLength(hull->vertexArray) /
|
arrayGetLength(hull->vertexArray) * arrayGetLength(hull->vertexArray) /
|
||||||
(sizeof(unsigned int) * 8) + 1,
|
(sizeof(unsigned int) * 8) + 1,
|
||||||
sizeof(unsigned int));
|
sizeof(unsigned int));
|
||||||
if (!hull->openEdgeProcessedMap) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
hull->nextTodoIndex = 0;
|
hull->nextTodoIndex = 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
|
int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
|
||||||
int p3Index) {
|
int p3Index) {
|
||||||
vec3 *p1 = (vec3 *)arrayGetItem(hull->vertexArray, p1Index);
|
vec3 *p1 = arrayGetItem(hull->vertexArray, p1Index);
|
||||||
vec3 *p2 = (vec3 *)arrayGetItem(hull->vertexArray, p2Index);
|
vec3 *p2 = arrayGetItem(hull->vertexArray, p2Index);
|
||||||
vec3 *p3 = (vec3 *)arrayGetItem(hull->vertexArray, p3Index);
|
vec3 *p3 = arrayGetItem(hull->vertexArray, p3Index);
|
||||||
vec3 beginNormal;
|
vec3 beginNormal;
|
||||||
vec3 endNormal;
|
vec3 endNormal;
|
||||||
int i;
|
int i;
|
||||||
|
@ -363,8 +244,7 @@ int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
|
||||||
|
|
||||||
for (i = 0; i < arrayGetLength(hull->vertexArray); ++i) {
|
for (i = 0; i < arrayGetLength(hull->vertexArray); ++i) {
|
||||||
if (i != p1Index && i != p2Index && i != p3Index) {
|
if (i != p1Index && i != p2Index && i != p3Index) {
|
||||||
vec3Normal(p1, p2, (vec3 *)arrayGetItem(hull->vertexArray, i),
|
vec3Normal(p1, p2, arrayGetItem(hull->vertexArray, i), &endNormal);
|
||||||
&endNormal);
|
|
||||||
angle = vec3Angle(&beginNormal, &endNormal);
|
angle = vec3Angle(&beginNormal, &endNormal);
|
||||||
if (angle > maxAngle) {
|
if (angle > maxAngle) {
|
||||||
candidateIndex = i;
|
candidateIndex = i;
|
||||||
|
@ -376,26 +256,18 @@ int convexHullGetNextVertex(convexHull *hull, int p1Index, int p2Index,
|
||||||
return candidateIndex;
|
return candidateIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2,
|
void convexHullAddTodo(convexHull *hull, int vertex1, int vertex2,
|
||||||
int vertex3) {
|
int vertex3) {
|
||||||
if (!convexHullOpenEdgeProcessed(hull, vertex1, vertex2)) {
|
if (!convexHullOpenEdgeProcessed(hull, vertex1, vertex2)) {
|
||||||
return convexHullAddTodoNoCheck(hull, vertex1, vertex2, vertex3);
|
convexHullAddTodoNoCheck(hull, vertex1, vertex2, vertex3);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int showFaceIndex;
|
|
||||||
|
|
||||||
static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
|
static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
|
||||||
int index3) {
|
int index3) {
|
||||||
int i;
|
int i;
|
||||||
int indices[] = {index1, index2, index3};
|
int indices[] = {index1, index2, index3};
|
||||||
|
|
||||||
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
|
|
||||||
drawDebugPrintf("showFaceIndex:%d can add (%d,%d,%d)", showFaceIndex,
|
|
||||||
index1, index2, index3);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
int p1 = indices[i];
|
int p1 = indices[i];
|
||||||
int p2 = indices[(i + 1) % 3];
|
int p2 = indices[(i + 1) % 3];
|
||||||
|
@ -412,15 +284,6 @@ static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
|
||||||
(vec3 *)arrayGetItem(hull->vertexArray, hill), &normal);
|
(vec3 *)arrayGetItem(hull->vertexArray, hill), &normal);
|
||||||
angle = vec3Angle(&e->hill1Normal, &normal);
|
angle = vec3Angle(&e->hill1Normal, &normal);
|
||||||
|
|
||||||
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
|
|
||||||
drawDebugPrintf("showFaceIndex:%d angle:%f (%d,%d,%d)",
|
|
||||||
showFaceIndex, angle, e->p1, e->p2, e->hill1);
|
|
||||||
drawSphere((vec3 *)arrayGetItem(hull->vertexArray, 9),
|
|
||||||
0.1, 36, 24);
|
|
||||||
drawSphere((vec3 *)arrayGetItem(hull->vertexArray, 6),
|
|
||||||
0.1, 36, 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (angle < 1) {
|
if (angle < 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -429,15 +292,12 @@ static int convexHullCanAddFace3(convexHull *hull, int index1, int index2,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullGenerate(convexHull *hull) {
|
void convexHullGenerate(convexHull *hull) {
|
||||||
int index1, index2, index3;
|
int index1, index2, index3;
|
||||||
convexHullReleaseForGenerate(hull);
|
convexHullReleaseForGenerate(hull);
|
||||||
if (0 != convexHullPrepareForGenerate(hull)) {
|
convexHullPrepareForGenerate(hull);
|
||||||
fprintf(stderr, "%s:convexHullPrepareForGenerate failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while (hull->nextTodoIndex < arrayGetLength(hull->todoArray)) {
|
while (hull->nextTodoIndex < arrayGetLength(hull->todoArray)) {
|
||||||
todo *t = (todo *)arrayGetItem(hull->todoArray, hull->nextTodoIndex++);
|
todo *t = arrayGetItem(hull->todoArray, hull->nextTodoIndex++);
|
||||||
index1 = t->firstVertex;
|
index1 = t->firstVertex;
|
||||||
index2 = t->secondVertex;
|
index2 = t->secondVertex;
|
||||||
if (convexHullOpenEdgeProcessed(hull, index1, index2) ||
|
if (convexHullOpenEdgeProcessed(hull, index1, index2) ||
|
||||||
|
@ -452,28 +312,19 @@ int convexHullGenerate(convexHull *hull) {
|
||||||
if (!convexHullCanAddFace3(hull, index1, index2, index3)) {
|
if (!convexHullCanAddFace3(hull, index1, index2, index3)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (showFaceIndex == arrayGetLength(hull->faceArray)) {
|
|
||||||
drawDebugPrintf("showFaceIndex:%d added face3 (%d,%d,%d)",
|
|
||||||
showFaceIndex, index1, index2, index3);
|
|
||||||
}
|
|
||||||
convexHullAddFace3(hull, index1, index2, index3);
|
convexHullAddFace3(hull, index1, index2, index3);
|
||||||
convexHullAddTodo(hull, index2, index3, index1);
|
convexHullAddTodo(hull, index2, index3, index1);
|
||||||
convexHullAddTodo(hull, index3, index1, index2);
|
convexHullAddTodo(hull, index3, index1, index2);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
|
void convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < arrayGetLength(hull->faceArray); ++i) {
|
for (i = 0; i < arrayGetLength(hull->faceArray); ++i) {
|
||||||
face3 *triIdx = (face3 *)arrayGetItem(
|
face3 *triIdx = arrayGetItem(hull->faceArray, i);
|
||||||
hull->faceArray, i);
|
convexHullVertex *p1 = arrayGetItem(hull->vertexArray, triIdx->indices[0]);
|
||||||
convexHullVertex *p1 = (convexHullVertex *)arrayGetItem(
|
convexHullVertex *p2 = arrayGetItem(hull->vertexArray, triIdx->indices[1]);
|
||||||
hull->vertexArray, triIdx->indices[0]);
|
convexHullVertex *p3 = arrayGetItem(hull->vertexArray, triIdx->indices[2]);
|
||||||
convexHullVertex *p2 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, triIdx->indices[1]);
|
|
||||||
convexHullVertex *p3 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, triIdx->indices[2]);
|
|
||||||
vec3 normal;
|
vec3 normal;
|
||||||
vec3 o2v;
|
vec3 o2v;
|
||||||
vec3Normal(&p1->pt, &p2->pt, &p3->pt, &normal);
|
vec3Normal(&p1->pt, &p2->pt, &p3->pt, &normal);
|
||||||
|
@ -484,7 +335,6 @@ int convexHullUnifyNormals(convexHull *hull, vec3 *origin) {
|
||||||
triIdx->indices[2] = index;
|
triIdx->indices[2] = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sortEdgeByScore(const void *first, const void *second) {
|
static int sortEdgeByScore(const void *first, const void *second) {
|
||||||
|
@ -507,38 +357,20 @@ static void rollTriangleIndices(face3 *face) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int convexHullMergeTriangles(convexHull *hull) {
|
void convexHullMergeTriangles(convexHull *hull) {
|
||||||
int edgeIndex;
|
int edgeIndex;
|
||||||
|
|
||||||
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
|
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
|
||||||
++edgeIndex) {
|
++edgeIndex) {
|
||||||
edge *e = (edge *)arrayGetItem(hull->edgeArray, edgeIndex);
|
edge *e = arrayGetItem(hull->edgeArray, edgeIndex);
|
||||||
if (-1 != e->face1 && -1 != e->face2) {
|
if (-1 != e->face1 && -1 != e->face2) {
|
||||||
//face3 *f1 = (face3 *)arrayGetItem(hull->faceArray, e->face1);
|
|
||||||
//face3 *f2 = (face3 *)arrayGetItem(hull->faceArray, e->face2);
|
|
||||||
vec3 f1normal;
|
vec3 f1normal;
|
||||||
vec3 f2normal;
|
vec3 f2normal;
|
||||||
const vec3 yAxis = {0, 1, 0};
|
const vec3 yAxis = {0, 1, 0};
|
||||||
/*
|
vec3 *v1 = arrayGetItem(hull->vertexArray, e->p1);
|
||||||
convexHullVertex *f1p1 = (convexHullVertex *)arrayGetItem(
|
vec3 *v2 = arrayGetItem(hull->vertexArray, e->p2);
|
||||||
hull->vertexArray, f1->indices[0]);
|
vec3 *vHill1 = arrayGetItem(hull->vertexArray, e->hill1);
|
||||||
convexHullVertex *f1p2 = (convexHullVertex *)arrayGetItem(
|
vec3 *vHill2 = arrayGetItem(hull->vertexArray, e->hill2);
|
||||||
hull->vertexArray, f1->indices[1]);
|
|
||||||
convexHullVertex *f1p3 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, f1->indices[2]);
|
|
||||||
convexHullVertex *f2p1 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, f2->indices[0]);
|
|
||||||
convexHullVertex *f2p2 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, f2->indices[1]);
|
|
||||||
convexHullVertex *f2p3 = (convexHullVertex *)arrayGetItem(
|
|
||||||
hull->vertexArray, f2->indices[2]);
|
|
||||||
vec3Normal(&f1p1->pt, &f1p2->pt, &f1p3->pt, &f1normal);
|
|
||||||
vec3Normal(&f2p1->pt, &f2p2->pt, &f2p3->pt, &f2normal);
|
|
||||||
*/
|
|
||||||
vec3 *v1 = (vec3 *)arrayGetItem(hull->vertexArray, e->p1);
|
|
||||||
vec3 *v2 = (vec3 *)arrayGetItem(hull->vertexArray, e->p2);
|
|
||||||
vec3 *vHill1 = (vec3 *)arrayGetItem(hull->vertexArray, e->hill1);
|
|
||||||
vec3 *vHill2 = (vec3 *)arrayGetItem(hull->vertexArray, e->hill2);
|
|
||||||
vec3 v12;
|
vec3 v12;
|
||||||
vec3Sub(v1, v2, &v12);
|
vec3Sub(v1, v2, &v12);
|
||||||
vec3Normal(v1, vHill1, v2, &f1normal);
|
vec3Normal(v1, vHill1, v2, &f1normal);
|
||||||
|
@ -554,17 +386,15 @@ int convexHullMergeTriangles(convexHull *hull) {
|
||||||
//
|
//
|
||||||
// After sort by score, the edge hashmap can not be used anymore.
|
// After sort by score, the edge hashmap can not be used anymore.
|
||||||
//
|
//
|
||||||
hashtableDestroy(hull->edgeHashtable);
|
dictDestroy(hull->edgeDict);
|
||||||
hull->edgeHashtable = 0;
|
hull->edgeDict = 0;
|
||||||
|
|
||||||
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
|
for (edgeIndex = 0; edgeIndex < arrayGetLength(hull->edgeArray);
|
||||||
++edgeIndex) {
|
++edgeIndex) {
|
||||||
edge *e = (edge *)arrayGetItem(hull->edgeArray, edgeIndex);
|
edge *e = arrayGetItem(hull->edgeArray, edgeIndex);
|
||||||
if (-1 != e->face1 && -1 != e->face2) {
|
if (-1 != e->face1 && -1 != e->face2) {
|
||||||
convexHullFace *f1 = (convexHullFace *)arrayGetItem(hull->faceArray,
|
convexHullFace *f1 = arrayGetItem(hull->faceArray, e->face1);
|
||||||
e->face1);
|
convexHullFace *f2 = arrayGetItem(hull->faceArray, e->face2);
|
||||||
convexHullFace *f2 = (convexHullFace *)arrayGetItem(hull->faceArray,
|
|
||||||
e->face2);
|
|
||||||
if (3 == f1->vertexNum && 3 == f2->vertexNum) {
|
if (3 == f1->vertexNum && 3 == f2->vertexNum) {
|
||||||
if (e->angleBetweenFaces <= 40 &&
|
if (e->angleBetweenFaces <= 40 &&
|
||||||
f1->plane == f2->plane) {
|
f1->plane == f2->plane) {
|
||||||
|
@ -575,33 +405,23 @@ int convexHullMergeTriangles(convexHull *hull) {
|
||||||
f1->u.q.indices[2] = e->hill2;
|
f1->u.q.indices[2] = e->hill2;
|
||||||
f1->vertexNum = 4;
|
f1->vertexNum = 4;
|
||||||
f2->vertexNum = 0;
|
f2->vertexNum = 0;
|
||||||
//if (edgeIndex >= 12 && edgeIndex <= 12) {
|
|
||||||
// drawDebugPoint((vec3 *)arrayGetItem(
|
|
||||||
// hull->vertexArray, e->p1), edgeIndex);
|
|
||||||
// drawDebugPoint((vec3 *)arrayGetItem(
|
|
||||||
// hull->vertexArray, e->p2), edgeIndex);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After merge, face3 hashtable can not be used anymore.
|
// After merge, face3 hashtable can not be used anymore.
|
||||||
hashtableDestroy(hull->face3Hashtable);
|
dictDestroy(hull->face3Dict);
|
||||||
hull->face3Hashtable = 0;
|
hull->face3Dict = 0;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex) {
|
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex) {
|
||||||
convexHullFace *face = (convexHullFace *)arrayGetItem(hull->faceArray,
|
convexHullFace *face = arrayGetItem(hull->faceArray, faceIndex);
|
||||||
faceIndex);
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex) {
|
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex) {
|
||||||
convexHullVertex *vertex = (convexHullVertex *)arrayGetItem(
|
convexHullVertex *vertex = arrayGetItem(hull->vertexArray, vertexIndex);
|
||||||
hull->vertexArray, vertexIndex);
|
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,12 @@ convexHull *convexHullCreate(void);
|
||||||
int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
|
int convexHullAddVertex(convexHull *hull, vec3 *vertex, int plane,
|
||||||
int orderOnPlane);
|
int orderOnPlane);
|
||||||
void convexHullDestroy(convexHull *hull);
|
void convexHullDestroy(convexHull *hull);
|
||||||
int convexHullGenerate(convexHull *hull);
|
void convexHullGenerate(convexHull *hull);
|
||||||
int convexHullUnifyNormals(convexHull *hull, vec3 *origin);
|
void convexHullUnifyNormals(convexHull *hull, vec3 *origin);
|
||||||
int convexHullMergeTriangles(convexHull *hull);
|
void convexHullMergeTriangles(convexHull *hull);
|
||||||
int convexHullGetFaceNum(convexHull *hull);
|
int convexHullGetFaceNum(convexHull *hull);
|
||||||
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex);
|
convexHullFace *convexHullGetFace(convexHull *hull, int faceIndex);
|
||||||
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex);
|
convexHullVertex *convexHullGetVertex(convexHull *hull, int vertexIndex);
|
||||||
int convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
|
void convexHullAddTodo(convexHull *hull, int vertex1, int vertex2, int vertex3);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "hashtable.h"
|
#include "dmemory.h"
|
||||||
#include "array.h"
|
#include "dict.h"
|
||||||
|
|
||||||
typedef struct hashtableEntry {
|
typedef struct hashtableEntry {
|
||||||
const void *node;
|
const void *node;
|
||||||
|
@ -15,14 +15,22 @@ typedef struct hashtableKey {
|
||||||
int firstEntryIndex;
|
int firstEntryIndex;
|
||||||
} hashtableKey;
|
} hashtableKey;
|
||||||
|
|
||||||
struct hashtable {
|
typedef struct hashtable {
|
||||||
array *keyArray;
|
array *keyArray;
|
||||||
array *entryArray;
|
array *entryArray;
|
||||||
int bucketSize;
|
int bucketSize;
|
||||||
int (*hashCallback)(void *userData, const void *node);
|
int (*hashCallback)(void *userData, const void *node);
|
||||||
int (*compareCallback)(void *userData, const void *node1, const void *node2);
|
int (*compareCallback)(void *userData, const void *node1, const void *node2);
|
||||||
void *userData;
|
void *userData;
|
||||||
};
|
} hashtable;
|
||||||
|
|
||||||
|
void hashtableDestroy(hashtable *ht) {
|
||||||
|
if (ht) {
|
||||||
|
arrayDestroy(ht->keyArray);
|
||||||
|
arrayDestroy(ht->entryArray);
|
||||||
|
dfree(ht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hashtable *hashtableCreate(int bucketSize,
|
hashtable *hashtableCreate(int bucketSize,
|
||||||
int (*hashCallback)(void *userData, const void *node),
|
int (*hashCallback)(void *userData, const void *node),
|
||||||
|
@ -50,23 +58,10 @@ hashtable *hashtableCreate(int bucketSize,
|
||||||
ht->hashCallback = hashCallback;
|
ht->hashCallback = hashCallback;
|
||||||
ht->compareCallback = compareCallback;
|
ht->compareCallback = compareCallback;
|
||||||
ht->userData = userData;
|
ht->userData = userData;
|
||||||
if (0 != arraySetLength(ht->keyArray, bucketSize)) {
|
arraySetLength(ht->keyArray, bucketSize);
|
||||||
fprintf(stderr, "%s:arraySetLength failed(bucketSize:%d).\n", __FUNCTION__,
|
|
||||||
bucketSize);
|
|
||||||
hashtableDestroy(ht);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ht;
|
return ht;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hashtableDestroy(hashtable *ht) {
|
|
||||||
if (ht) {
|
|
||||||
arrayDestroy(ht->keyArray);
|
|
||||||
arrayDestroy(ht->entryArray);
|
|
||||||
free(ht);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hashtableGetNodeHash(hashtable *ht, const void *node) {
|
static int hashtableGetNodeHash(hashtable *ht, const void *node) {
|
||||||
return (int)((unsigned int)ht->hashCallback(ht->userData,
|
return (int)((unsigned int)ht->hashCallback(ht->userData,
|
||||||
node) % ht->bucketSize);
|
node) % ht->bucketSize);
|
||||||
|
@ -88,26 +83,19 @@ static hashtableEntry *findEntry(hashtable *ht, hashtableKey *key,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hashtableInsert(hashtable *ht, const void *node) {
|
static void hashtableInsert(hashtable *ht, const void *keyNode,
|
||||||
|
const void *node) {
|
||||||
int newEntryIndex;
|
int newEntryIndex;
|
||||||
int hash = hashtableGetNodeHash(ht, node);
|
hashtableEntry *entry;
|
||||||
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash);
|
int hash = hashtableGetNodeHash(ht, keyNode);
|
||||||
hashtableEntry *entry = findEntry(ht, key, node);
|
hashtableKey *key = arrayGetItem(ht->keyArray, hash);
|
||||||
if (entry) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newEntryIndex = arrayGetLength(ht->entryArray);
|
newEntryIndex = arrayGetLength(ht->entryArray);
|
||||||
if (0 != arraySetLength(ht->entryArray, newEntryIndex + 1)) {
|
arraySetLength(ht->entryArray, newEntryIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed(newEntryIndex:%d).\n",
|
entry = arrayGetItem(ht->entryArray, newEntryIndex);
|
||||||
__FUNCTION__, newEntryIndex);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
entry = (hashtableEntry *)arrayGetItem(ht->entryArray, newEntryIndex);
|
|
||||||
entry->node = node;
|
entry->node = node;
|
||||||
entry->nextEntryIndex = 0 == key->entryNum ? -1 : key->firstEntryIndex;
|
entry->nextEntryIndex = 0 == key->entryNum ? -1 : key->firstEntryIndex;
|
||||||
key->firstEntryIndex = newEntryIndex;
|
key->firstEntryIndex = newEntryIndex;
|
||||||
key->entryNum++;
|
key->entryNum++;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *hashtableGet(hashtable *ht, const void *node) {
|
void *hashtableGet(hashtable *ht, const void *node) {
|
||||||
|
@ -115,3 +103,80 @@ void *hashtableGet(hashtable *ht, const void *node) {
|
||||||
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash);
|
hashtableKey *key = (hashtableKey *)arrayGetItem(ht->keyArray, hash);
|
||||||
return findEntry(ht, key, node);
|
return findEntry(ht, key, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dict {
|
||||||
|
hashtable *ht;
|
||||||
|
array *arr;
|
||||||
|
int (*hashCallback)(void *userData, const void *key);
|
||||||
|
int (*compareCallback)(void *userData, const void *key1, const void *key2);
|
||||||
|
void *userData;
|
||||||
|
void *findKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const void *dictKeyTranslate(dict *dct, const void *key) {
|
||||||
|
if (0 == key) {
|
||||||
|
key = dct->findKey;
|
||||||
|
} else {
|
||||||
|
key = arrayGetItem(dct->arr, ((char *)key - 0) - 1);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dictHash(void *userData, const void *key) {
|
||||||
|
dict *dct = userData;
|
||||||
|
return dct->hashCallback(dct->userData, dictKeyTranslate(dct, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dictCompare(void *userData, const void *key1, const void *key2) {
|
||||||
|
dict *dct = userData;
|
||||||
|
return dct->compareCallback(dct->userData, dictKeyTranslate(dct, key1),
|
||||||
|
dictKeyTranslate(dct, key2));
|
||||||
|
}
|
||||||
|
|
||||||
|
dict *dictCreate(array *arr, int bucketSize,
|
||||||
|
int (*hashCallback)(void *userData, const void *key),
|
||||||
|
int (*compareCallback)(void *userData, const void *key1, const void *key2),
|
||||||
|
void *userData) {
|
||||||
|
dict *dct = dcalloc(1, sizeof(dict));
|
||||||
|
dct->arr = arr;
|
||||||
|
dct->hashCallback = hashCallback;
|
||||||
|
dct->compareCallback = compareCallback;
|
||||||
|
dct->userData = userData;
|
||||||
|
dct->findKey = 0;
|
||||||
|
dct->ht = hashtableCreate(bucketSize, dictHash, dictCompare, dct);
|
||||||
|
return dct;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dictDestroy(dict *dct) {
|
||||||
|
if (dct && dct->ht) {
|
||||||
|
hashtableDestroy(dct->ht);
|
||||||
|
}
|
||||||
|
dfree(dct);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dictFind(dict *dct, void *key) {
|
||||||
|
int index;
|
||||||
|
dct->findKey = key;
|
||||||
|
index = (char *)hashtableGet(dct->ht, 0) - 0;
|
||||||
|
if (0 == index) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return arrayGetItem(dct->arr, index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dictGet(dict *dct, void *key) {
|
||||||
|
void *value = dictFind(dct, key);
|
||||||
|
if (!value) {
|
||||||
|
int newIndex = arrayGetLength(dct->arr);
|
||||||
|
value = arrayNewItem(dct->arr);
|
||||||
|
dct->findKey = key;
|
||||||
|
hashtableInsert(dct->ht, 0, (char *)0 + newIndex + 1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dictGetClear(dict *dct, void *key) {
|
||||||
|
void *ptr = dictGet(dct, key);
|
||||||
|
memset(ptr, 0, arrayGetNodeSize(dct->arr));
|
||||||
|
return ptr;
|
||||||
|
}
|
|
@ -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) {
|
if (0 == bm) {
|
||||||
bmeshBall ball;
|
bmeshBall ball;
|
||||||
bmeshBone bone;
|
bmeshBone bone;
|
||||||
int i;
|
unsigned int i;
|
||||||
bm = bmeshCreate();
|
bm = bmeshCreate();
|
||||||
|
|
||||||
for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) {
|
for (i = 0; i < sizeof(bmeshTestBalls) / sizeof(bmeshTestBalls[0]); ++i) {
|
||||||
|
|
246
src/subdivide.c
246
src/subdivide.c
|
@ -1,6 +1,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "dmemory.h"
|
||||||
#include "subdivide.h"
|
#include "subdivide.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
|
@ -82,34 +83,14 @@ static void initFace(subdivFace *f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
subdivModel *subdivCreateModel(void) {
|
subdivModel *subdivCreateModel(void) {
|
||||||
subdivModel *model = (subdivModel *)calloc(1, sizeof(subdivModel));
|
subdivModel *model = (subdivModel *)dcalloc(1, sizeof(subdivModel));
|
||||||
if (!model) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
model->faceLink = -1;
|
model->faceLink = -1;
|
||||||
model->edgeLink = -1;
|
model->edgeLink = -1;
|
||||||
model->vertexLink = -1;
|
model->vertexLink = -1;
|
||||||
model->vertexArray = arrayCreate(sizeof(subdivVertex));
|
model->vertexArray = arrayCreate(sizeof(subdivVertex));
|
||||||
if (!model->vertexArray) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
model->faceArray = arrayCreate(sizeof(subdivFace));
|
model->faceArray = arrayCreate(sizeof(subdivFace));
|
||||||
if (!model->faceArray) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
model->edgeArray = arrayCreate(sizeof(subdivEdge));
|
model->edgeArray = arrayCreate(sizeof(subdivEdge));
|
||||||
if (!model->edgeArray) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
model->indexArray = arrayCreate(sizeof(subdivLink));
|
model->indexArray = arrayCreate(sizeof(subdivLink));
|
||||||
if (!model->indexArray) {
|
|
||||||
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,18 +100,15 @@ void subdivDestroyModel(subdivModel *model) {
|
||||||
arrayDestroy(model->faceArray);
|
arrayDestroy(model->faceArray);
|
||||||
arrayDestroy(model->edgeArray);
|
arrayDestroy(model->edgeArray);
|
||||||
arrayDestroy(model->indexArray);
|
arrayDestroy(model->indexArray);
|
||||||
free(model);
|
dfree(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int allocLink(subdivModel *model, int index) {
|
static int allocLink(subdivModel *model, int index) {
|
||||||
subdivLink *linkItem;
|
subdivLink *linkItem;
|
||||||
int newLink = arrayGetLength(model->indexArray);
|
int newLink = arrayGetLength(model->indexArray);
|
||||||
if (0 != arraySetLength(model->indexArray, newLink + 1)) {
|
arraySetLength(model->indexArray, newLink + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
linkItem = arrayGetItem(model->indexArray, newLink);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, newLink);
|
|
||||||
linkItem->index = index;
|
linkItem->index = index;
|
||||||
linkItem->nextLink = -1;
|
linkItem->nextLink = -1;
|
||||||
return newLink;
|
return newLink;
|
||||||
|
@ -142,25 +120,21 @@ static int subdivLinkElement(subdivModel *model, int current, int order) {
|
||||||
subdivLink *linkItem;
|
subdivLink *linkItem;
|
||||||
iterator = current;
|
iterator = current;
|
||||||
for (i = 0; i <= order && -1 != iterator; ++i) {
|
for (i = 0; i <= order && -1 != iterator; ++i) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
linkItem = arrayGetItem(model->indexArray, iterator);
|
||||||
element = linkItem->index;
|
element = linkItem->index;
|
||||||
iterator = linkItem->nextLink;
|
iterator = linkItem->nextLink;
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pushLink(subdivModel *model, int *link, int *num, int index) {
|
static void pushLink(subdivModel *model, int *link, int *num, int index) {
|
||||||
int newLink = allocLink(model, index);
|
int newLink = allocLink(model, index);
|
||||||
int i, iterator;
|
int i, iterator;
|
||||||
subdivLink *linkItem = 0;
|
subdivLink *linkItem = 0;
|
||||||
if (-1 == newLink) {
|
|
||||||
fprintf(stderr, "%s:allocLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (-1 != *link) {
|
if (-1 != *link) {
|
||||||
iterator = *link;
|
iterator = *link;
|
||||||
for (i = 0; i < *num; ++i) {
|
for (i = 0; i < *num; ++i) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
linkItem = arrayGetItem(model->indexArray, iterator);
|
||||||
iterator = linkItem->nextLink;
|
iterator = linkItem->nextLink;
|
||||||
}
|
}
|
||||||
linkItem->nextLink = newLink;
|
linkItem->nextLink = newLink;
|
||||||
|
@ -168,34 +142,23 @@ static int pushLink(subdivModel *model, int *link, int *num, int index) {
|
||||||
*link = newLink;
|
*link = newLink;
|
||||||
}
|
}
|
||||||
(*num)++;
|
(*num)++;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static subdivVertex *allocVertex(subdivModel *model) {
|
static subdivVertex *allocVertex(subdivModel *model) {
|
||||||
subdivVertex *vertex;
|
subdivVertex *vertex;
|
||||||
int newVertexIndex = arrayGetLength(model->vertexArray);
|
int newVertexIndex = arrayGetLength(model->vertexArray);
|
||||||
if (0 != arraySetLength(model->vertexArray, newVertexIndex + 1)) {
|
arraySetLength(model->vertexArray, newVertexIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vertex = arrayGetItem(model->vertexArray, newVertexIndex);
|
vertex = arrayGetItem(model->vertexArray, newVertexIndex);
|
||||||
initVertex(vertex);
|
initVertex(vertex);
|
||||||
vertex->index = newVertexIndex;
|
vertex->index = newVertexIndex;
|
||||||
if (0 != pushLink(model, &model->vertexLink, &model->vertexNum,
|
pushLink(model, &model->vertexLink, &model->vertexNum, vertex->index);
|
||||||
vertex->index)) {
|
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static subdivEdge *allocEdge(subdivModel *model) {
|
static subdivEdge *allocEdge(subdivModel *model) {
|
||||||
subdivEdge *edge;
|
subdivEdge *edge;
|
||||||
int newEdgeIndex = arrayGetLength(model->edgeArray);
|
int newEdgeIndex = arrayGetLength(model->edgeArray);
|
||||||
if (0 != arraySetLength(model->edgeArray, newEdgeIndex + 1)) {
|
arraySetLength(model->edgeArray, newEdgeIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
edge = arrayGetItem(model->edgeArray, newEdgeIndex);
|
edge = arrayGetItem(model->edgeArray, newEdgeIndex);
|
||||||
initEdge(edge);
|
initEdge(edge);
|
||||||
edge->index = newEdgeIndex;
|
edge->index = newEdgeIndex;
|
||||||
|
@ -205,10 +168,7 @@ static subdivEdge *allocEdge(subdivModel *model) {
|
||||||
static subdivFace *allocFace(subdivModel *model) {
|
static subdivFace *allocFace(subdivModel *model) {
|
||||||
subdivFace *face;
|
subdivFace *face;
|
||||||
int newFaceIndex = arrayGetLength(model->faceArray);
|
int newFaceIndex = arrayGetLength(model->faceArray);
|
||||||
if (0 != arraySetLength(model->faceArray, newFaceIndex + 1)) {
|
arraySetLength(model->faceArray, newFaceIndex + 1);
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
face = arrayGetItem(model->faceArray, newFaceIndex);
|
face = arrayGetItem(model->faceArray, newFaceIndex);
|
||||||
initFace(face);
|
initFace(face);
|
||||||
face->index = newFaceIndex;
|
face->index = newFaceIndex;
|
||||||
|
@ -219,21 +179,21 @@ static subdivVertex *getVertex(subdivModel *model, int index) {
|
||||||
if (-1 == index) {
|
if (-1 == index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (subdivVertex *)arrayGetItem(model->vertexArray, index);
|
return arrayGetItem(model->vertexArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static subdivEdge *getEdge(subdivModel *model, int index) {
|
static subdivEdge *getEdge(subdivModel *model, int index) {
|
||||||
if (-1 == index) {
|
if (-1 == index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (subdivEdge *)arrayGetItem(model->edgeArray, index);
|
return arrayGetItem(model->edgeArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static subdivFace *getFace(subdivModel *model, int index) {
|
static subdivFace *getFace(subdivModel *model, int index) {
|
||||||
if (-1 == index) {
|
if (-1 == index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (subdivFace *)arrayGetItem(model->faceArray, index);
|
return arrayGetItem(model->faceArray, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isHoleEdge(subdivModel *model, int e) {
|
static int isHoleEdge(subdivModel *model, int e) {
|
||||||
|
@ -250,10 +210,6 @@ static int edgePoint(subdivModel *model, int e) {
|
||||||
int nv = getEdge(model, e)->edgePt;
|
int nv = getEdge(model, e)->edgePt;
|
||||||
if (-1 == nv) {
|
if (-1 == nv) {
|
||||||
subdivVertex *newVertex = allocVertex(model);
|
subdivVertex *newVertex = allocVertex(model);
|
||||||
if (!newVertex) {
|
|
||||||
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
nv = newVertex->index;
|
nv = newVertex->index;
|
||||||
getEdge(model, e)->edgePt = nv;
|
getEdge(model, e)->edgePt = nv;
|
||||||
getEdge(model, e)->avg = getVertex(model, getEdge(model, e)->v[0])->v;
|
getEdge(model, e)->avg = getVertex(model, getEdge(model, e)->v[0])->v;
|
||||||
|
@ -266,15 +222,11 @@ static int edgePoint(subdivModel *model, int e) {
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
int f;
|
int f;
|
||||||
int fp;
|
int fp;
|
||||||
subdivLink *linkItem = (subdivLink *)arrayGetItem(model->indexArray,
|
subdivLink *linkItem = arrayGetItem(model->indexArray,
|
||||||
iterator);
|
iterator);
|
||||||
f = linkItem->index;
|
f = linkItem->index;
|
||||||
iterator = linkItem->nextLink;
|
iterator = linkItem->nextLink;
|
||||||
fp = facePoint(model, f);
|
fp = facePoint(model, f);
|
||||||
if (-1 == fp) {
|
|
||||||
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vec3Add(&getVertex(model, nv)->v, &getVertex(model, fp)->v,
|
vec3Add(&getVertex(model, nv)->v, &getVertex(model, fp)->v,
|
||||||
&getVertex(model, nv)->v);
|
&getVertex(model, nv)->v);
|
||||||
}
|
}
|
||||||
|
@ -293,18 +245,13 @@ static int facePoint(subdivModel *model, int f) {
|
||||||
int iterator;
|
int iterator;
|
||||||
int i;
|
int i;
|
||||||
subdivVertex *newVertex = allocVertex(model);
|
subdivVertex *newVertex = allocVertex(model);
|
||||||
if (!newVertex) {
|
|
||||||
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
nv = newVertex->index;
|
nv = newVertex->index;
|
||||||
getFace(model, f)->avg = nv;
|
getFace(model, f)->avg = nv;
|
||||||
iterator = getFace(model, f)->vertexLink;
|
iterator = getFace(model, f)->vertexLink;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
int p;
|
int p;
|
||||||
subdivLink *linkItem = (subdivLink *)arrayGetItem(model->indexArray,
|
subdivLink *linkItem = arrayGetItem(model->indexArray, iterator);
|
||||||
iterator);
|
|
||||||
p = linkItem->index;
|
p = linkItem->index;
|
||||||
iterator = linkItem->nextLink;
|
iterator = linkItem->nextLink;
|
||||||
if (!i) {
|
if (!i) {
|
||||||
|
@ -345,27 +292,19 @@ static int updatedPoint(subdivModel *model, int p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
newVertex = allocVertex(model);
|
newVertex = allocVertex(model);
|
||||||
if (!newVertex) {
|
|
||||||
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
nv = newVertex->index;
|
nv = newVertex->index;
|
||||||
getVertex(model, p)->newVertexIndex = nv;
|
getVertex(model, p)->newVertexIndex = nv;
|
||||||
if (isHoleVertex(model, p)) {
|
if (isHoleVertex(model, p)) {
|
||||||
getVertex(model, nv)->v = getVertex(model, p)->v;
|
getVertex(model, nv)->v = getVertex(model, p)->v;
|
||||||
iterator = getVertex(model, p)->edgeLink;
|
iterator = getVertex(model, p)->edgeLink;
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
link = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
link = arrayGetItem(model->indexArray, iterator);
|
||||||
e = link->index;
|
e = link->index;
|
||||||
iterator = link->nextLink;
|
iterator = link->nextLink;
|
||||||
if (!isHoleEdge(model, e)) {
|
if (!isHoleEdge(model, e)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ep = edgePoint(model, e);
|
ep = edgePoint(model, e);
|
||||||
if (-1 == ep) {
|
|
||||||
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vec3Add(&getVertex(model, nv)->v, &getVertex(model, ep)->v,
|
vec3Add(&getVertex(model, nv)->v, &getVertex(model, ep)->v,
|
||||||
&getVertex(model, nv)->v);
|
&getVertex(model, nv)->v);
|
||||||
n++;
|
n++;
|
||||||
|
@ -376,26 +315,18 @@ static int updatedPoint(subdivModel *model, int p) {
|
||||||
n = getVertex(model, p)->faceNum;
|
n = getVertex(model, p)->faceNum;
|
||||||
iterator = getVertex(model, p)->faceLink;
|
iterator = getVertex(model, p)->faceLink;
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
link = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
link = arrayGetItem(model->indexArray, iterator);
|
||||||
f = link->index;
|
f = link->index;
|
||||||
iterator = link->nextLink;
|
iterator = link->nextLink;
|
||||||
facePt = facePoint(model, f);
|
facePt = facePoint(model, f);
|
||||||
if (-1 == facePt) {
|
|
||||||
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
vec3Add(&sum, &getVertex(model, facePt)->v, &sum);
|
vec3Add(&sum, &getVertex(model, facePt)->v, &sum);
|
||||||
}
|
}
|
||||||
iterator = getVertex(model, p)->edgeLink;
|
iterator = getVertex(model, p)->edgeLink;
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
link = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
link = arrayGetItem(model->indexArray, iterator);
|
||||||
e = link->index;
|
e = link->index;
|
||||||
iterator = link->nextLink;
|
iterator = link->nextLink;
|
||||||
ep = edgePoint(model, e);
|
ep = edgePoint(model, e);
|
||||||
if (-1 == ep) {
|
|
||||||
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
scaleAdd(&sum, &getVertex(model, ep)->v, 2, &sum);
|
scaleAdd(&sum, &getVertex(model, ep)->v, 2, &sum);
|
||||||
}
|
}
|
||||||
vec3Scale(&sum, 1.0 / n, &sum);
|
vec3Scale(&sum, 1.0 / n, &sum);
|
||||||
|
@ -407,7 +338,7 @@ static int updatedPoint(subdivModel *model, int p) {
|
||||||
return nv;
|
return nv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int subdivCalculteNorms(subdivModel *model) {
|
void subdivCalculteNorms(subdivModel *model) {
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
int faceIterator;
|
int faceIterator;
|
||||||
int nextFaceIterator;
|
int nextFaceIterator;
|
||||||
|
@ -423,16 +354,16 @@ int subdivCalculteNorms(subdivModel *model) {
|
||||||
faceIterator = model->faceLink;
|
faceIterator = model->faceLink;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (-1 != faceIterator) {
|
while (-1 != faceIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
linkItem = arrayGetItem(model->indexArray, faceIterator);
|
||||||
f = getFace(model, linkItem->index);
|
f = getFace(model, linkItem->index);
|
||||||
nextFaceIterator = linkItem->nextLink;
|
nextFaceIterator = linkItem->nextLink;
|
||||||
vertexIterator = f->vertexLink;
|
vertexIterator = f->vertexLink;
|
||||||
n = f->vertexNum;
|
n = f->vertexNum;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (-1 != vertexIterator) {
|
while (-1 != vertexIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
linkItem = arrayGetItem(model->indexArray, faceIterator);
|
||||||
f = getFace(model, linkItem->index);
|
f = getFace(model, linkItem->index);
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator);
|
linkItem = arrayGetItem(model->indexArray, vertexIterator);
|
||||||
v = getVertex(model, linkItem->index);
|
v = getVertex(model, linkItem->index);
|
||||||
vertexIterator = linkItem->nextLink;
|
vertexIterator = linkItem->nextLink;
|
||||||
v0 = getVertex(model,
|
v0 = getVertex(model,
|
||||||
|
@ -454,13 +385,13 @@ int subdivCalculteNorms(subdivModel *model) {
|
||||||
|
|
||||||
vertexIterator = model->vertexLink;
|
vertexIterator = model->vertexLink;
|
||||||
while (-1 != vertexIterator) {
|
while (-1 != vertexIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator);
|
linkItem = arrayGetItem(model->indexArray, vertexIterator);
|
||||||
v = getVertex(model, linkItem->index);
|
v = getVertex(model, linkItem->index);
|
||||||
nextVertexIterator = linkItem->nextLink;
|
nextVertexIterator = linkItem->nextLink;
|
||||||
faceIterator = v->faceLink;
|
faceIterator = v->faceLink;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (-1 != faceIterator) {
|
while (-1 != faceIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
linkItem = arrayGetItem(model->indexArray, faceIterator);
|
||||||
f = getFace(model, linkItem->index);
|
f = getFace(model, linkItem->index);
|
||||||
faceIterator = linkItem->nextLink;
|
faceIterator = linkItem->nextLink;
|
||||||
vec3Add(&v->avgNorm, &f->norm, &v->avgNorm);
|
vec3Add(&v->avgNorm, &f->norm, &v->avgNorm);
|
||||||
|
@ -471,8 +402,6 @@ int subdivCalculteNorms(subdivModel *model) {
|
||||||
}
|
}
|
||||||
vertexIterator = nextVertexIterator;
|
vertexIterator = nextVertexIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subdivDrawModel(subdivModel *model) {
|
void subdivDrawModel(subdivModel *model) {
|
||||||
|
@ -484,13 +413,13 @@ void subdivDrawModel(subdivModel *model) {
|
||||||
faceIterator = model->faceLink;
|
faceIterator = model->faceLink;
|
||||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||||
while (-1 != faceIterator) {
|
while (-1 != faceIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
linkItem = arrayGetItem(model->indexArray, faceIterator);
|
||||||
f = getFace(model, linkItem->index);
|
f = getFace(model, linkItem->index);
|
||||||
faceIterator = linkItem->nextLink;
|
faceIterator = linkItem->nextLink;
|
||||||
vertexIterator = f->vertexLink;
|
vertexIterator = f->vertexLink;
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_POLYGON);
|
||||||
while (-1 != vertexIterator) {
|
while (-1 != vertexIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator);
|
linkItem = arrayGetItem(model->indexArray, vertexIterator);
|
||||||
v = getVertex(model, linkItem->index);
|
v = getVertex(model, linkItem->index);
|
||||||
vertexIterator = linkItem->nextLink;
|
vertexIterator = linkItem->nextLink;
|
||||||
glNormal3fv(&(f->norm.x));
|
glNormal3fv(&(f->norm.x));
|
||||||
|
@ -512,48 +441,24 @@ subdivModel *subdivCatmullClark(subdivModel *model) {
|
||||||
subdivModel *outputModel;
|
subdivModel *outputModel;
|
||||||
|
|
||||||
outputModel = subdivCreateModel();
|
outputModel = subdivCreateModel();
|
||||||
if (!outputModel) {
|
|
||||||
fprintf(stderr, "%s:subdivCreateModel failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
faceIterator = model->faceLink;
|
faceIterator = model->faceLink;
|
||||||
while (-1 != faceIterator) {
|
while (-1 != faceIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
linkItem = arrayGetItem(model->indexArray, faceIterator);
|
||||||
f = linkItem->index;
|
f = linkItem->index;
|
||||||
j = 0;
|
j = 0;
|
||||||
nextFaceIterator = linkItem->nextLink;
|
nextFaceIterator = linkItem->nextLink;
|
||||||
vertexIterator = getFace(model, f)->vertexLink;
|
vertexIterator = getFace(model, f)->vertexLink;
|
||||||
while (-1 != vertexIterator) {
|
while (-1 != vertexIterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, vertexIterator);
|
linkItem = arrayGetItem(model->indexArray, vertexIterator);
|
||||||
p = linkItem->index;
|
p = linkItem->index;
|
||||||
vertexIterator = linkItem->nextLink;
|
vertexIterator = linkItem->nextLink;
|
||||||
ai = updatedPoint(model, p);
|
ai = updatedPoint(model, p);
|
||||||
if (-1 == ai) {
|
|
||||||
fprintf(stderr, "%s:updatedPoint failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bi = edgePoint(model, subdivLinkElement(model,
|
bi = edgePoint(model, subdivLinkElement(model,
|
||||||
getFace(model, f)->edgeLink, (j + 1) % getFace(model, f)->edgeNum));
|
getFace(model, f)->edgeLink, (j + 1) % getFace(model, f)->edgeNum));
|
||||||
if (-1 == bi) {
|
|
||||||
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ci = facePoint(model, f);
|
ci = facePoint(model, f);
|
||||||
if (-1 == ci) {
|
|
||||||
fprintf(stderr, "%s:facePoint failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
di = edgePoint(model, subdivLinkElement(model,
|
di = edgePoint(model, subdivLinkElement(model,
|
||||||
getFace(model, f)->edgeLink, j));
|
getFace(model, f)->edgeLink, j));
|
||||||
if (-1 == di) {
|
|
||||||
fprintf(stderr, "%s:edgePoint failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
a = getVertex(model, ai)->indexOnNewModel;
|
a = getVertex(model, ai)->indexOnNewModel;
|
||||||
if (-1 == a) {
|
if (-1 == a) {
|
||||||
a = subdivAddVertex(outputModel, &getVertex(model, ai)->v);
|
a = subdivAddVertex(outputModel, &getVertex(model, ai)->v);
|
||||||
|
@ -574,36 +479,19 @@ subdivModel *subdivCatmullClark(subdivModel *model) {
|
||||||
d = subdivAddVertex(outputModel, &getVertex(model, di)->v);
|
d = subdivAddVertex(outputModel, &getVertex(model, di)->v);
|
||||||
getVertex(model, di)->indexOnNewModel = d;
|
getVertex(model, di)->indexOnNewModel = d;
|
||||||
}
|
}
|
||||||
if (-1 == a || -1 == b || -1 == c || -1 == d) {
|
subdivAddQuadFace(outputModel, a, b, c, d);
|
||||||
fprintf(stderr, "%s:subdivAddVertex failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (-1 == subdivAddQuadFace(outputModel, a, b, c, d)) {
|
|
||||||
fprintf(stderr, "%s:subdivAddFace failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
faceIterator = nextFaceIterator;
|
faceIterator = nextFaceIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != subdivCalculteNorms(outputModel)) {
|
subdivCalculteNorms(outputModel);
|
||||||
fprintf(stderr, "%s:subdivCalculteNorms failed.\n", __FUNCTION__);
|
|
||||||
subdivDestroyModel(outputModel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputModel;
|
return outputModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int subdivAddVertex(subdivModel *model, vec3 *v) {
|
int subdivAddVertex(subdivModel *model, vec3 *v) {
|
||||||
subdivVertex *newVertex = allocVertex(model);
|
subdivVertex *newVertex = allocVertex(model);
|
||||||
if (!newVertex) {
|
|
||||||
fprintf(stderr, "%s:allocVertex failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newVertex->v = *v;
|
newVertex->v = *v;
|
||||||
return newVertex->index;
|
return newVertex->index;
|
||||||
}
|
}
|
||||||
|
@ -612,27 +500,13 @@ static int subdivAddEdge(subdivModel *model, int p1, int p2) {
|
||||||
subdivEdge *newEdge = allocEdge(model);
|
subdivEdge *newEdge = allocEdge(model);
|
||||||
subdivVertex *v1;
|
subdivVertex *v1;
|
||||||
subdivVertex *v2;
|
subdivVertex *v2;
|
||||||
if (!newEdge) {
|
|
||||||
fprintf(stderr, "%s:allocEdge failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newEdge->v[0] = p1;
|
newEdge->v[0] = p1;
|
||||||
newEdge->v[1] = p2;
|
newEdge->v[1] = p2;
|
||||||
v1 = getVertex(model, p1);
|
v1 = getVertex(model, p1);
|
||||||
v2 = getVertex(model, p2);
|
v2 = getVertex(model, p2);
|
||||||
if (-1 == pushLink(model, &v1->edgeLink, &v1->edgeNum, newEdge->index)) {
|
pushLink(model, &v1->edgeLink, &v1->edgeNum, newEdge->index);
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
pushLink(model, &v2->edgeLink, &v2->edgeNum, newEdge->index);
|
||||||
return -1;
|
pushLink(model, &model->edgeLink, &model->edgeNum, newEdge->index);
|
||||||
}
|
|
||||||
if (-1 == pushLink(model, &v2->edgeLink, &v2->edgeNum, newEdge->index)) {
|
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (-1 == pushLink(model, &model->edgeLink, &model->edgeNum,
|
|
||||||
newEdge->index)) {
|
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return newEdge->index;
|
return newEdge->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +517,7 @@ static int subdivEdgeByVertexs(subdivModel *model, int p1, int p2) {
|
||||||
int newEdgeIndex;
|
int newEdgeIndex;
|
||||||
int iterator = v1->edgeLink;
|
int iterator = v1->edgeLink;
|
||||||
while (-1 != iterator) {
|
while (-1 != iterator) {
|
||||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, iterator);
|
linkItem = arrayGetItem(model->indexArray, iterator);
|
||||||
e = getEdge(model, linkItem->index);
|
e = getEdge(model, linkItem->index);
|
||||||
iterator = linkItem->nextLink;
|
iterator = linkItem->nextLink;
|
||||||
if (e->v[0] == p2 || e->v[1] == p2) {
|
if (e->v[0] == p2 || e->v[1] == p2) {
|
||||||
|
@ -660,44 +534,21 @@ static int subdivAddFace(subdivModel *model, int *vertexs, int vertexNum) {
|
||||||
int p0, p1;
|
int p0, p1;
|
||||||
int newFaceIndex;
|
int newFaceIndex;
|
||||||
int edgeIndex;
|
int edgeIndex;
|
||||||
if (!f) {
|
|
||||||
fprintf(stderr, "%s:allocFace failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
newFaceIndex = f->index;
|
newFaceIndex = f->index;
|
||||||
if (0 != pushLink(model, &model->faceLink, &model->faceNum, newFaceIndex)) {
|
pushLink(model, &model->faceLink, &model->faceNum, newFaceIndex);
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
p0 = vertexs[0];
|
p0 = vertexs[0];
|
||||||
for (i = 1; i <= vertexNum; ++i, p0 = p1) {
|
for (i = 1; i <= vertexNum; ++i, p0 = p1) {
|
||||||
subdivVertex *v1;
|
subdivVertex *v1;
|
||||||
subdivEdge *e;
|
subdivEdge *e;
|
||||||
p1 = vertexs[i % vertexNum];
|
p1 = vertexs[i % vertexNum];
|
||||||
v1 = getVertex(model, p1);
|
v1 = getVertex(model, p1);
|
||||||
if (0 != pushLink(model, &v1->faceLink, &v1->faceNum, newFaceIndex)) {
|
pushLink(model, &v1->faceLink, &v1->faceNum, newFaceIndex);
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
edgeIndex = subdivEdgeByVertexs(model, p0, p1);
|
edgeIndex = subdivEdgeByVertexs(model, p0, p1);
|
||||||
if (-1 == edgeIndex) {
|
|
||||||
fprintf(stderr, "%s:subdivEdgeByVertexs failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
e = getEdge(model, edgeIndex);
|
e = getEdge(model, edgeIndex);
|
||||||
if (0 != pushLink(model, &e->faceLink, &e->faceNum, newFaceIndex)) {
|
pushLink(model, &e->faceLink, &e->faceNum, newFaceIndex);
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
f = getFace(model, newFaceIndex);
|
f = getFace(model, newFaceIndex);
|
||||||
if (0 != pushLink(model, &f->edgeLink, &f->edgeNum, edgeIndex)) {
|
pushLink(model, &f->edgeLink, &f->edgeNum, edgeIndex);
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
pushLink(model, &f->vertexLink, &f->vertexNum, p1);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (0 != pushLink(model, &f->vertexLink, &f->vertexNum, p1)) {
|
|
||||||
fprintf(stderr, "%s:pushLink failed.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return newFaceIndex;
|
return newFaceIndex;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +563,7 @@ int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4) {
|
||||||
return subdivAddFace(model, vertexs, 4);
|
return subdivAddFace(model, vertexs, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subdivAddCube(subdivModel *model) {
|
void subdivAddCube(subdivModel *model) {
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
for (x = -1; x <= 1; x += 2) {
|
for (x = -1; x <= 1; x += 2) {
|
||||||
for (y = -1; y <= 1; y += 2) {
|
for (y = -1; y <= 1; y += 2) {
|
||||||
|
@ -729,28 +580,17 @@ int subdivAddCube(subdivModel *model) {
|
||||||
subdivAddQuadFace(model, 0, 2, 6, 4);
|
subdivAddQuadFace(model, 0, 2, 6, 4);
|
||||||
subdivAddQuadFace(model, 5, 7, 3, 1);
|
subdivAddQuadFace(model, 5, 7, 3, 1);
|
||||||
subdivCalculteNorms(model);
|
subdivCalculteNorms(model);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) {
|
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) {
|
||||||
int i;
|
int i;
|
||||||
subdivModel *outputModel;
|
subdivModel *outputModel;
|
||||||
outputModel = subdivCatmullClark(model);
|
outputModel = subdivCatmullClark(model);
|
||||||
if (!outputModel) {
|
|
||||||
fprintf(stderr, "%s:subdivCatmullClark failed.\n", __FUNCTION__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
for (i = 1; i < loops; ++i) {
|
for (i = 1; i < loops; ++i) {
|
||||||
subdivModel *loopInput = outputModel;
|
subdivModel *loopInput = outputModel;
|
||||||
outputModel = subdivCatmullClark(loopInput);
|
outputModel = subdivCatmullClark(loopInput);
|
||||||
subdivDestroyModel(loopInput);
|
subdivDestroyModel(loopInput);
|
||||||
if (!outputModel) {
|
|
||||||
fprintf(stderr, "%s:subdivCatmullClark failed(loops:%d i:%d).\n",
|
|
||||||
__FUNCTION__, loops, i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
drawDebugPrintf("faces: %d", outputModel->faceNum);
|
|
||||||
subdivDrawModel(outputModel);
|
subdivDrawModel(outputModel);
|
||||||
return outputModel;
|
return outputModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ int subdivAddTriangleFace(subdivModel *model, int p1, int p2, int p3);
|
||||||
int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4);
|
int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4);
|
||||||
subdivModel *subdivCatmullClark(subdivModel *model);
|
subdivModel *subdivCatmullClark(subdivModel *model);
|
||||||
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops);
|
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops);
|
||||||
int subdivAddCube(subdivModel *model);
|
void subdivAddCube(subdivModel *model);
|
||||||
int subdivCalculteNorms(subdivModel *model);
|
void subdivCalculteNorms(subdivModel *model);
|
||||||
void subdivDrawModel(subdivModel *model);
|
void subdivDrawModel(subdivModel *model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in New Issue