Input model to subdivision.

master
Jeremy Hu 2017-01-04 08:13:01 +09:30
parent fcb4868d28
commit c271354ab1
6 changed files with 214 additions and 88 deletions

View File

@ -6,18 +6,26 @@
#include <time.h> #include <time.h>
#include "bmesh.h" #include "bmesh.h"
#include "array.h" #include "array.h"
#include "hashtable.h"
#include "matrix.h" #include "matrix.h"
#include "convexhull.h" #include "convexhull.h"
#include "subdivide.h"
#include "draw.h" #include "draw.h"
#define BMESH_MAX_PARENT_BALL_DEPTH 1000 #define BMESH_MAX_PARENT_BALL_DEPTH 1000
#define BMESH_INTVAL_DIST_DIV 10 #define BMESH_INTVAL_DIST_DIV 10
#define BMESH_MODEL_VERTEX_HASHTABLE_SIZE 100
typedef struct bmeshBallIndex { typedef struct bmeshBallIndex {
int ballIndex; int ballIndex;
int nextChildIndex; int nextChildIndex;
} bmeshBallIndex; } bmeshBallIndex;
typedef struct bmeshModelVertex {
vec3 vertex;
int indexOnModel;
} bmeshModelVertex;
struct bmesh { struct bmesh {
array *ballArray; array *ballArray;
array *boneArray; array *boneArray;
@ -26,8 +34,103 @@ struct bmesh {
int rootBallIndex; int rootBallIndex;
int roundColor; int roundColor;
bmeshBall *parentBallStack[BMESH_MAX_PARENT_BALL_DEPTH]; 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 *bmeshCreate(void) {
bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh)); bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh));
if (!bm) { if (!bm) {
@ -58,6 +161,25 @@ bmesh *bmeshCreate(void) {
bmeshDestroy(bm); bmeshDestroy(bm);
return 0; 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->rootBallIndex = -1;
bm->roundColor = 0; bm->roundColor = 0;
return bm; return bm;
@ -68,6 +190,10 @@ void bmeshDestroy(bmesh *bm) {
arrayDestroy(bm->boneArray); arrayDestroy(bm->boneArray);
arrayDestroy(bm->indexArray); arrayDestroy(bm->indexArray);
arrayDestroy(bm->quadArray); arrayDestroy(bm->quadArray);
subdivDestroyModel(bm->model);
subdivDestroyModel(bm->subdivModel);
arrayDestroy(bm->modelVertexArray);
hashtableDestroy(bm->modelVertexHashtable);
free(bm); free(bm);
} }
@ -698,69 +824,35 @@ static int bmeshStichFrom(bmesh *bm, int depth, bmeshBall *ball) {
} }
} }
glPushMatrix(); if (hull) {
int i;
if (hull) for (i = 0; i < convexHullGetFaceNum(hull); ++i) {
{ convexHullFace *face = (convexHullFace *)convexHullGetFace(hull, i);
int triIndex; if (4 == face->vertexNum) {
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) {
quad q; quad q;
vec3 normal;
int j;
q.pt[0] = convexHullGetVertex(hull, face->u.q.indices[0])->pt; q.pt[0] = convexHullGetVertex(hull, face->u.q.indices[0])->pt;
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);
glColor3f(1.0f, 1.0f, 1.0f); if (-1 == result) {
glBegin(GL_QUADS); break;
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);
} }
glEnd(); } else if (3 == face->vertexNum) {
triangle t;
glBegin(GL_LINE_STRIP); t.pt[0] = convexHullGetVertex(hull, face->u.t.indices[0])->pt;
for (j = 0; j < 4; ++j) { t.pt[1] = convexHullGetVertex(hull, face->u.t.indices[1])->pt;
glVertex3f(q.pt[j].x, q.pt[j].y, q.pt[j].z); t.pt[2] = convexHullGetVertex(hull, face->u.t.indices[2])->pt;
result = bmeshAddTriangleToModel(bm, &t);
if (-1 == result) {
break;
} }
glVertex3f(q.pt[0].x, q.pt[0].y, q.pt[0].z);
glEnd();
} }
} }
}
glPopMatrix();
if (hull) {
convexHullDestroy(hull); convexHullDestroy(hull);
} }
} }
for (child = bmeshGetBallFirstChild(bm, ball, &iterator); for (child = bmeshGetBallFirstChild(bm, ball, &iterator);
child; child;
child = bmeshGetBallNextChild(bm, ball, &iterator)) { child = bmeshGetBallNextChild(bm, ball, &iterator)) {
@ -817,8 +909,10 @@ void calculateBallQuad(bmeshBall *ball, quad *q) {
vec3Add(&q->pt[3], &z, &q->pt[3]); 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 i;
int result = 0;
vec3 normal; vec3 normal;
vec3 o2v; vec3 o2v;
matchTwoFaces(q1, q2); matchTwoFaces(q1, q2);
@ -834,8 +928,13 @@ static void drawWallsBetweenQuads(vec3 *origin, quad *q1, quad *q2) {
wall.pt[j] = oldWall.pt[3 - j]; 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) { 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, vec3Lerp(&parent->position, &ball->position, BMESH_INTVAL_DIST_DIV,
&fakeBall.position); &fakeBall.position);
calculateBallQuad(&fakeBall, &childFace); calculateBallQuad(&fakeBall, &childFace);
drawWallsBetweenQuads(&ball->position, &currentFace, &childFace); bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace);
result = bmeshAddQuadToModel(bm, &childFace);
if (-1 == result) {
return result;
}
drawQuad(&childFace); drawQuad(&childFace);
} }
} }
@ -888,7 +992,11 @@ static int bmeshGenerateInbetweenMeshFrom(bmesh *bm, int depth,
//} else { //} else {
child = bmeshFindChildBallForInbetweenMesh(bm, child); child = bmeshFindChildBallForInbetweenMesh(bm, child);
calculateBallQuad(child, &childFace); calculateBallQuad(child, &childFace);
drawWallsBetweenQuads(&ball->position, &currentFace, &childFace); result = bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&childFace);
if (-1 == result) {
return result;
}
//} //}
ball->meshGenerated = 1; ball->meshGenerated = 1;
child->meshGenerated = 1; child->meshGenerated = 1;
@ -913,3 +1021,25 @@ int bmeshGenerateInbetweenMesh(bmesh *bm) {
return bmeshGenerateInbetweenMeshFrom(bm, 0, bmeshGetRootBall(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;
}

View File

@ -60,6 +60,8 @@ int bmeshAddQuad(bmesh *bm, quad *q);
int bmeshSweep(bmesh *bm); int bmeshSweep(bmesh *bm);
int bmeshStitch(bmesh *bm); int bmeshStitch(bmesh *bm);
int bmeshGenerateInbetweenMesh(bmesh *bm); int bmeshGenerateInbetweenMesh(bmesh *bm);
int bmeshGenerate(bmesh *bm);
int bmeshDraw(bmesh *bm);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -189,7 +189,8 @@ int convexHullAddEdge(convexHull *hull, int p1, int p2, int hill,
void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex, void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
int secondVertex) { int secondVertex) {
int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) + secondVertex; int mapIndex = firstVertex * arrayGetLength(hull->vertexArray) +
secondVertex;
int unitIndex = mapIndex / (sizeof(unsigned int) * 8); int unitIndex = mapIndex / (sizeof(unsigned int) * 8);
int unitOffset = mapIndex % (sizeof(unsigned int) * 8); int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
hull->openEdgeProcessedMap[unitIndex] |= (0x00000001 << unitOffset); hull->openEdgeProcessedMap[unitIndex] |= (0x00000001 << unitOffset);
@ -198,7 +199,8 @@ void convexHullMarkEdgeAsProcessed(convexHull *hull, int firstVertex,
int convexHullOpenEdgeProcessed(convexHull *hull, int firstVertex, int convexHullOpenEdgeProcessed(convexHull *hull, int firstVertex,
int secondVertex) { int secondVertex) {
if (hull->openEdgeProcessedMap) { 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 unitIndex = mapIndex / (sizeof(unsigned int) * 8);
int unitOffset = mapIndex % (sizeof(unsigned int) * 8); int unitOffset = mapIndex % (sizeof(unsigned int) * 8);
return hull->openEdgeProcessedMap[unitIndex] & (0x00000001 << unitOffset); return hull->openEdgeProcessedMap[unitIndex] & (0x00000001 << unitOffset);

View File

@ -216,7 +216,7 @@ void Render::initializeGL() {
#include "../data/bmesh_test_2.h" #include "../data/bmesh_test_2.h"
void Render::paintGL() { void Render::paintGL() {
bmesh *bm = 0; static bmesh *bm = 0;
_this = this; _this = this;
debugOutputTop = 0; debugOutputTop = 0;
@ -237,17 +237,6 @@ void Render::paintGL() {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
/*
{
subdivModel *input = subdivCreateModel();
subdivModel *output;
subdivAddCube(input);
output = subdivCatmullClarkWithLoops(input, 2);
subdivDestroyModel(input);
subdivDestroyModel(output);
}
*/
if (0 == bm) { if (0 == bm) {
bmeshBall ball; bmeshBall ball;
bmeshBone bone; bmeshBone bone;
@ -271,14 +260,13 @@ void Render::paintGL() {
bmeshAddBone(bm, &bone); bmeshAddBone(bm, &bone);
} }
bmeshGenerateInbetweenBalls(bm); bmeshGenerate(bm);
bmeshSweep(bm);
bmeshStitch(bm);
bmeshGenerateInbetweenMesh(bm);
} }
if (bm) { if (bm) {
bmeshDraw(bm);
drawBmeshBallRecursively(bm, bmeshGetRootBall(bm)); drawBmeshBallRecursively(bm, bmeshGetRootBall(bm));
//glBegin(GL_QUADS); //glBegin(GL_QUADS);
@ -327,10 +315,10 @@ void Render::paintGL() {
glPopMatrix(); glPopMatrix();
if (bm) { //if (bm) {
bmeshDestroy(bm); // bmeshDestroy(bm);
bm = 0; // bm = 0;
} //}
} }
void Render::resizeGL(int w, int h) { void Render::resizeGL(int w, int h) {

View File

@ -114,11 +114,13 @@ subdivModel *subdivCreateModel(void) {
} }
void subdivDestroyModel(subdivModel *model) { void subdivDestroyModel(subdivModel *model) {
arrayDestroy(model->vertexArray); if (model) {
arrayDestroy(model->faceArray); arrayDestroy(model->vertexArray);
arrayDestroy(model->edgeArray); arrayDestroy(model->faceArray);
arrayDestroy(model->indexArray); arrayDestroy(model->edgeArray);
free(model); arrayDestroy(model->indexArray);
free(model);
}
} }
static int allocLink(subdivModel *model, int index) { static int allocLink(subdivModel *model, int index) {
@ -402,7 +404,7 @@ static int updatedPoint(subdivModel *model, int p) {
return nv; return nv;
} }
static int subdivCalculteNorms(subdivModel *model) { int subdivCalculteNorms(subdivModel *model) {
int i, j, n; int i, j, n;
int faceIterator; int faceIterator;
int nextFaceIterator; int nextFaceIterator;
@ -470,14 +472,14 @@ static int subdivCalculteNorms(subdivModel *model) {
return 0; return 0;
} }
static void drawModel(subdivModel *model) { void subdivDrawModel(subdivModel *model) {
subdivLink *linkItem; subdivLink *linkItem;
subdivFace *f; subdivFace *f;
subdivVertex *v; subdivVertex *v;
int faceIterator; int faceIterator;
int vertexIterator; int vertexIterator;
faceIterator = model->faceLink; faceIterator = model->faceLink;
glColor3f(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 = (subdivLink *)arrayGetItem(model->indexArray, faceIterator);
f = getFace(model, linkItem->index); f = getFace(model, linkItem->index);
@ -745,6 +747,6 @@ subdivModel *subdivCatmullClarkWithLoops(subdivModel *model, int loops) {
} }
} }
drawDebugPrintf("faces: %d", outputModel->faceNum); drawDebugPrintf("faces: %d", outputModel->faceNum);
drawModel(outputModel); subdivDrawModel(outputModel);
return outputModel; return outputModel;
} }

View File

@ -17,6 +17,8 @@ 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); int subdivAddCube(subdivModel *model);
int subdivCalculteNorms(subdivModel *model);
void subdivDrawModel(subdivModel *model);
#ifdef __cplusplus #ifdef __cplusplus
} }