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 "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, &currentFace, &childFace);
bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&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, &currentFace, &childFace);
result = bmeshAddWallsBetweenQuadsToModel(bm, &ball->position, &currentFace,
&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;
}

View File

@ -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
}

View File

@ -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);

View File

@ -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) {

View File

@ -114,11 +114,13 @@ 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) {
@ -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;
}

View File

@ -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
}