Input model to subdivision.
parent
fcb4868d28
commit
c271354ab1
240
src/bmesh.c
240
src/bmesh.c
|
@ -6,18 +6,26 @@
|
|||
#include <time.h>
|
||||
#include "bmesh.h"
|
||||
#include "array.h"
|
||||
#include "hashtable.h"
|
||||
#include "matrix.h"
|
||||
#include "convexhull.h"
|
||||
#include "subdivide.h"
|
||||
#include "draw.h"
|
||||
|
||||
#define BMESH_MAX_PARENT_BALL_DEPTH 1000
|
||||
#define BMESH_INTVAL_DIST_DIV 10
|
||||
#define BMESH_MODEL_VERTEX_HASHTABLE_SIZE 100
|
||||
|
||||
typedef struct bmeshBallIndex {
|
||||
int ballIndex;
|
||||
int nextChildIndex;
|
||||
} bmeshBallIndex;
|
||||
|
||||
typedef struct bmeshModelVertex {
|
||||
vec3 vertex;
|
||||
int indexOnModel;
|
||||
} bmeshModelVertex;
|
||||
|
||||
struct bmesh {
|
||||
array *ballArray;
|
||||
array *boneArray;
|
||||
|
@ -26,8 +34,103 @@ struct bmesh {
|
|||
int rootBallIndex;
|
||||
int roundColor;
|
||||
bmeshBall *parentBallStack[BMESH_MAX_PARENT_BALL_DEPTH];
|
||||
subdivModel *model;
|
||||
subdivModel *subdivModel;
|
||||
array *modelVertexArray;
|
||||
hashtable *modelVertexHashtable;
|
||||
bmeshModelVertex findModelVertex;
|
||||
};
|
||||
|
||||
static int cantorPair(int k1, int k2) {
|
||||
return (k1 + k2) * (k1 + k2 + 1) / 2 + k2;
|
||||
}
|
||||
|
||||
static bmeshModelVertex *bmeshFindModelVertex(bmesh *bm, vec3 *vertex) {
|
||||
int index;
|
||||
bm->findModelVertex.vertex = *vertex;
|
||||
index = (char *)hashtableGet(bm->modelVertexHashtable, (char *)0) - (char *)0;
|
||||
if (0 == index) {
|
||||
return 0;
|
||||
}
|
||||
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
|
||||
}
|
||||
|
||||
static int bmeshAddModelVertex(bmesh *bm, vec3 *vertex) {
|
||||
bmeshModelVertex *v = bmeshFindModelVertex(bm, vertex);
|
||||
if (!v) {
|
||||
v = (bmeshModelVertex *)arrayNewItem(bm->modelVertexArray);
|
||||
if (!v) {
|
||||
fprintf(stderr, "%s:arrayNewItem failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
memset(v, 0, sizeof(bmeshModelVertex));
|
||||
v->vertex = *vertex;
|
||||
v->indexOnModel = subdivAddVertex(bm->model, &v->vertex);
|
||||
}
|
||||
return v->indexOnModel;
|
||||
}
|
||||
|
||||
static int bmeshAddQuadToModel(bmesh *bm, quad *q) {
|
||||
int indices[4];
|
||||
indices[0] = bmeshAddModelVertex(bm, &q->pt[0]);
|
||||
indices[1] = bmeshAddModelVertex(bm, &q->pt[1]);
|
||||
indices[2] = bmeshAddModelVertex(bm, &q->pt[2]);
|
||||
indices[3] = bmeshAddModelVertex(bm, &q->pt[3]);
|
||||
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2] ||
|
||||
-1 == indices[3]) {
|
||||
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (-1 == subdivAddQuadFace(bm->model, indices[0], indices[1], indices[2],
|
||||
indices[3])) {
|
||||
fprintf(stderr, "%s:subdivAddQuadFace failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmeshAddTriangleToModel(bmesh *bm, triangle *t) {
|
||||
int indices[3];
|
||||
indices[0] = bmeshAddModelVertex(bm, &t->pt[0]);
|
||||
indices[1] = bmeshAddModelVertex(bm, &t->pt[1]);
|
||||
indices[2] = bmeshAddModelVertex(bm, &t->pt[2]);
|
||||
if (-1 == indices[0] || -1 == indices[1] || -1 == indices[2]) {
|
||||
fprintf(stderr, "%s:bmeshAddModelVertex failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (-1 == subdivAddTriangleFace(bm->model, indices[0], indices[1],
|
||||
indices[2])) {
|
||||
fprintf(stderr, "%s:subdivAddTriangleFace failed.\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bmeshModelVertex *bmeshGetModelVertexByHashtableParam(void *userData,
|
||||
const void *node) {
|
||||
bmesh *bm = (bmesh *)userData;
|
||||
int index = (char *)node - (char *)0;
|
||||
if (0 == index) {
|
||||
return &bm->findModelVertex;
|
||||
}
|
||||
return (bmeshModelVertex *)arrayGetItem(bm->modelVertexArray, index - 1);
|
||||
}
|
||||
|
||||
static int modelVertexHash(void *userData, const void *node) {
|
||||
bmeshModelVertex *v = bmeshGetModelVertexByHashtableParam(userData, node);
|
||||
return cantorPair(cantorPair(v->vertex.x, v->vertex.y),
|
||||
v->vertex.z);
|
||||
}
|
||||
|
||||
static int modelVertexCompare(void *userData, const void *firstNode,
|
||||
const void *secondNode) {
|
||||
bmeshModelVertex *v1 = bmeshGetModelVertexByHashtableParam(userData,
|
||||
firstNode);
|
||||
bmeshModelVertex *v2 = bmeshGetModelVertexByHashtableParam(userData,
|
||||
secondNode);
|
||||
return 0 == memcmp(&v1->vertex, &v2->vertex, sizeof(v1->vertex));
|
||||
}
|
||||
|
||||
bmesh *bmeshCreate(void) {
|
||||
bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh));
|
||||
if (!bm) {
|
||||
|
@ -58,6 +161,25 @@ bmesh *bmeshCreate(void) {
|
|||
bmeshDestroy(bm);
|
||||
return 0;
|
||||
}
|
||||
bm->model = subdivCreateModel();
|
||||
if (!bm->model) {
|
||||
fprintf(stderr, "%s:subdivCreateModel failed.\n", __FUNCTION__);
|
||||
bmeshDestroy(bm);
|
||||
return 0;
|
||||
}
|
||||
bm->modelVertexArray = arrayCreate(sizeof(bmeshModelVertex));
|
||||
if (!bm->modelVertexArray) {
|
||||
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__);
|
||||
bmeshDestroy(bm);
|
||||
return 0;
|
||||
}
|
||||
bm->modelVertexHashtable = hashtableCreate(BMESH_MODEL_VERTEX_HASHTABLE_SIZE,
|
||||
modelVertexHash, modelVertexCompare, bm);
|
||||
if (!bm->modelVertexHashtable) {
|
||||
fprintf(stderr, "%s:hashtableCreate quad failed.\n", __FUNCTION__);
|
||||
bmeshDestroy(bm);
|
||||
return 0;
|
||||
}
|
||||
bm->rootBallIndex = -1;
|
||||
bm->roundColor = 0;
|
||||
return bm;
|
||||
|
@ -68,6 +190,10 @@ void bmeshDestroy(bmesh *bm) {
|
|||
arrayDestroy(bm->boneArray);
|
||||
arrayDestroy(bm->indexArray);
|
||||
arrayDestroy(bm->quadArray);
|
||||
subdivDestroyModel(bm->model);
|
||||
subdivDestroyModel(bm->subdivModel);
|
||||
arrayDestroy(bm->modelVertexArray);
|
||||
hashtableDestroy(bm->modelVertexHashtable);
|
||||
free(bm);
|
||||
}
|
||||
|
||||
|
@ -698,69 +824,35 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
|
|||
}
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
if (hull)
|
||||
{
|
||||
int triIndex;
|
||||
for (triIndex = 0; triIndex < convexHullGetFaceNum(hull);
|
||||
++triIndex) {
|
||||
convexHullFace *face = (convexHullFace *)convexHullGetFace(hull,
|
||||
triIndex);
|
||||
if (3 == face->vertexNum) {
|
||||
triangle tri;
|
||||
int j;
|
||||
tri.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
|
||||
tri.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
|
||||
tri.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
|
||||
|
||||
if (triIndex >= showFaceIndex) {
|
||||
break;
|
||||
}
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
drawTriangle(&tri);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (j = 0; j < 3; ++j) {
|
||||
glVertex3f(tri.pt[j].x, tri.pt[j].y, tri.pt[j].z);
|
||||
}
|
||||
glVertex3f(tri.pt[0].x, tri.pt[0].y, tri.pt[0].z);
|
||||
glEnd();
|
||||
|
||||
} else if (4 == face->vertexNum) {
|
||||
if (hull) {
|
||||
int i;
|
||||
for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
|
||||
convexHullFace *face = (convexHullFace *)convexHullGetFace(hull, i);
|
||||
if (4 == face->vertexNum) {
|
||||
quad q;
|
||||
vec3 normal;
|
||||
int j;
|
||||
q.pt[0] = convexHullGetVertex(hull, face->u.q.indices[0])->pt;
|
||||
q.pt[1] = convexHullGetVertex(hull, face->u.q.indices[1])->pt;
|
||||
q.pt[2] = convexHullGetVertex(hull, face->u.q.indices[2])->pt;
|
||||
q.pt[3] = convexHullGetVertex(hull, face->u.q.indices[3])->pt;
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
vec3Normal(&q.pt[0], &q.pt[1], &q.pt[2], &normal);
|
||||
for (j = 0; j < 4; ++j) {
|
||||
glNormal3f(normal.x, normal.y, normal.z);
|
||||
glVertex3f(q.pt[j].x, q.pt[j].y, q.pt[j].z);
|
||||
result = bmeshAddQuadToModel(bm, &q);
|
||||
if (-1 == result) {
|
||||
break;
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (j = 0; j < 4; ++j) {
|
||||
glVertex3f(q.pt[j].x, q.pt[j].y, q.pt[j].z);
|
||||
}
|
||||
glVertex3f(q.pt[0].x, q.pt[0].y, q.pt[0].z);
|
||||
glEnd();
|
||||
} else if (3 == face->vertexNum) {
|
||||
triangle t;
|
||||
t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
|
||||
t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
|
||||
t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
|
||||
result = bmeshAddTriangleToModel(bm, &t);
|
||||
if (-1 == result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
if (hull) {
|
||||
convexHullDestroy(hull);
|
||||
}
|
||||
}
|
||||
|
||||
for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
|
||||
child;
|
||||
child = bmeshGetBallNextChild(bm, ball, &iterator)) {
|
||||
|
@ -817,8 +909,10 @@ void calculateBallQuad(bmeshBall *ball, quad *q) {
|
|||
vec3Add(&q->pt[3], &z, &q->pt[3]);
|
||||
}
|
||||
|
||||
static void drawWallsBetweenQuads(vec3 *origin, quad *q1, quad *q2) {
|
||||
static int bmeshAddWallsBetweenQuadsToModel(bmesh *bm, vec3 *origin, quad *q1,
|
||||
quad *q2) {
|
||||
int i;
|
||||
int result = 0;
|
||||
vec3 normal;
|
||||
vec3 o2v;
|
||||
matchTwoFaces(q1, q2);
|
||||
|
@ -834,8 +928,13 @@ static void drawWallsBetweenQuads(vec3 *origin, quad *q1, quad *q2) {
|
|||
wall.pt[j] = oldWall.pt[3 - j];
|
||||
}
|
||||
}
|
||||
drawQuad(&wall);
|
||||
result = bmeshAddQuadToModel(bm, &wall);
|
||||
if (-1 == result) {
|
||||
break;
|
||||
}
|
||||
//drawQuad(&wall);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bmeshBall *bmeshFindChildBallForInbetweenMesh(bmesh *bm, bmeshBall *ball) {
|
||||
|
@ -875,7 +974,12 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
|||
vec3Lerp(&parent->position, &ball->position, BMESH_INTVAL_DIST_DIV,
|
||||
&fakeBall.position);
|
||||
calculateBallQuad(&fakeBall, &childFace);
|
||||
drawWallsBetweenQuads(&ball->position, ¤tFace, &childFace);
|
||||
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
||||
&childFace);
|
||||
result = bmeshAddQuadToModel(bm, &childFace);
|
||||
if (-1 == result) {
|
||||
return result;
|
||||
}
|
||||
drawQuad(&childFace);
|
||||
}
|
||||
}
|
||||
|
@ -888,7 +992,11 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
|
|||
//} else {
|
||||
child = bmeshFindChildBallForInbetweenMesh(bm, child);
|
||||
calculateBallQuad(child, &childFace);
|
||||
drawWallsBetweenQuads(&ball->position, ¤tFace, &childFace);
|
||||
result = bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, ¤tFace,
|
||||
&childFace);
|
||||
if (-1 == result) {
|
||||
return result;
|
||||
}
|
||||
//}
|
||||
ball->meshGenerated = 1;
|
||||
child->meshGenerated = 1;
|
||||
|
@ -913,3 +1021,25 @@ int bmeshGenerateInbetweenMesh(bmesh *bm) {
|
|||
return bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(bm));
|
||||
}
|
||||
|
||||
int bmeshGenerate(bmesh *bm) {
|
||||
bmeshGenerateInbetweenBalls(bm);
|
||||
bmeshSweep(bm);
|
||||
bmeshStitch(bm);
|
||||
bmeshGenerateInbetweenMesh(bm);
|
||||
subdivCalculteNorms(bm->model);
|
||||
bm->subdivModel = subdivCatmullClarkWithLoops(bm->model, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bmeshDraw(bmesh *bm) {
|
||||
glPushMatrix();
|
||||
glTranslatef(-5, 0, 0);
|
||||
subdivDrawModel(bm->model);
|
||||
glPopMatrix();
|
||||
subdivDrawModel(bm->subdivModel);
|
||||
//subdivModel *model = subdivCreateModel();
|
||||
//subdivAddCube(model);
|
||||
//subdivDrawModel(subdivCatmullClarkWithLoops(model, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ int bmeshAddQuad(bmesh *bm, quad *q);
|
|||
int bmeshSweep(bmesh *bm);
|
||||
int bmeshStitch(bmesh *bm);
|
||||
int bmeshGenerateInbetweenMesh(bmesh *bm);
|
||||
int bmeshGenerate(bmesh *bm);
|
||||
int bmeshDraw(bmesh *bm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -189,7 +189,8 @@ int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
|
|||
|
||||
void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
|
||||
int secondVertex) {
|
||||
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) + secondVertex;
|
||||
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) +
|
||||
secondVertex;
|
||||
int unitIndex = mapIndex / (sizeof(unsigned int) * 8);
|
||||
int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
|
||||
hull->openEdgeProcessedMap[unitIndex] |= (0x00000001 << unitOffset);
|
||||
|
@ -198,7 +199,8 @@ void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
|
|||
int convexHullOpenEdgeProcessed(convexHull *hull, int firstVertex,
|
||||
int secondVertex) {
|
||||
if (hull->openEdgeProcessedMap) {
|
||||
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) + secondVertex;
|
||||
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) +
|
||||
secondVertex;
|
||||
int unitIndex = mapIndex / (sizeof(unsigned int) * 8);
|
||||
int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
|
||||
return hull->openEdgeProcessedMap[unitIndex] & (0x00000001 << unitOffset);
|
||||
|
|
|
@ -216,7 +216,7 @@ void Render::initializeGL() {
|
|||
#include "../data/bmesh_test_2.h"
|
||||
|
||||
void Render::paintGL() {
|
||||
bmesh *bm = 0;
|
||||
static bmesh *bm = 0;
|
||||
|
||||
_this = this;
|
||||
debugOutputTop = 0;
|
||||
|
@ -237,17 +237,6 @@ void Render::paintGL() {
|
|||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
/*
|
||||
{
|
||||
subdivModel *input = subdivCreateModel();
|
||||
subdivModel *output;
|
||||
subdivAddCube(input);
|
||||
output = subdivCatmullClarkWithLoops(input, 2);
|
||||
subdivDestroyModel(input);
|
||||
subdivDestroyModel(output);
|
||||
}
|
||||
*/
|
||||
|
||||
if (0 == bm) {
|
||||
bmeshBall ball;
|
||||
bmeshBone bone;
|
||||
|
@ -271,14 +260,13 @@ void Render::paintGL() {
|
|||
bmeshAddBone(bm, &bone);
|
||||
}
|
||||
|
||||
bmeshGenerateInbetweenBalls(bm);
|
||||
bmeshSweep(bm);
|
||||
bmeshStitch(bm);
|
||||
bmeshGenerateInbetweenMesh(bm);
|
||||
bmeshGenerate(bm);
|
||||
}
|
||||
|
||||
if (bm) {
|
||||
|
||||
bmeshDraw(bm);
|
||||
|
||||
drawBmeshBallRecursively(bm, bmeshGetRootBall(bm));
|
||||
|
||||
//glBegin(GL_QUADS);
|
||||
|
@ -327,10 +315,10 @@ void Render::paintGL() {
|
|||
|
||||
glPopMatrix();
|
||||
|
||||
if (bm) {
|
||||
bmeshDestroy(bm);
|
||||
bm = 0;
|
||||
}
|
||||
//if (bm) {
|
||||
// bmeshDestroy(bm);
|
||||
// bm = 0;
|
||||
//}
|
||||
}
|
||||
|
||||
void Render::resizeGL(int w, int h) {
|
||||
|
|
|
@ -114,12 +114,14 @@ subdivModel *subdivCreateModel(void) {
|
|||
}
|
||||
|
||||
void subdivDestroyModel(subdivModel *model) {
|
||||
if (model) {
|
||||
arrayDestroy(model->vertexArray);
|
||||
arrayDestroy(model->faceArray);
|
||||
arrayDestroy(model->edgeArray);
|
||||
arrayDestroy(model->indexArray);
|
||||
free(model);
|
||||
}
|
||||
}
|
||||
|
||||
static int allocLink(subdivModel *model, int index) {
|
||||
subdivLink *linkItem;
|
||||
|
@ -402,7 +404,7 @@ static int updatedPoint(subdivModel *model, int p) {
|
|||
return nv;
|
||||
}
|
||||
|
||||
static int subdivCalculteNorms(subdivModel *model) {
|
||||
int subdivCalculteNorms(subdivModel *model) {
|
||||
int i, j, n;
|
||||
int faceIterator;
|
||||
int nextFaceIterator;
|
||||
|
@ -470,14 +472,14 @@ static int subdivCalculteNorms(subdivModel *model) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void drawModel(subdivModel *model) {
|
||||
void subdivDrawModel(subdivModel *model) {
|
||||
subdivLink *linkItem;
|
||||
subdivFace *f;
|
||||
subdivVertex *v;
|
||||
int faceIterator;
|
||||
int vertexIterator;
|
||||
faceIterator = model->faceLink;
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
while (-1 != faceIterator) {
|
||||
linkItem = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
|
||||
f = getFace(model, linkItem->index);
|
||||
|
@ -745,6 +747,6 @@ subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) {
|
|||
}
|
||||
}
|
||||
drawDebugPrintf("faces: %d", outputModel->faceNum);
|
||||
drawModel(outputModel);
|
||||
subdivDrawModel(outputModel);
|
||||
return outputModel;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ int subdivAddQuadFace(subdivModel *model, int p1, int p2, int p3, int p4);
|
|||
subdivModel *subdivCatmullClark(subdivModel *model);
|
||||
subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops);
|
||||
int subdivAddCube(subdivModel *model);
|
||||
int subdivCalculteNorms(subdivModel *model);
|
||||
void subdivDrawModel(subdivModel *model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue