From 5bf806f36383596b7e306cee205a99aad2471a86 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Wed, 21 Dec 2016 23:36:47 +0930 Subject: [PATCH] Add tree data struct of nodes --- build/dust3d.pro | 1 + src/bmesh.c | 185 ++++++++++++++++++++++++++++++++++++++++++----- src/bmesh.h | 9 ++- src/draw.h | 4 + src/render.cpp | 29 ++++++-- 5 files changed, 201 insertions(+), 27 deletions(-) diff --git a/build/dust3d.pro b/build/dust3d.pro index 5c8eef14..75f7809d 100644 --- a/build/dust3d.pro +++ b/build/dust3d.pro @@ -2,6 +2,7 @@ TARGET = dust3d TEMPLATE = app QT += widgets opengl +CONFIG += debug VPATH += ../src INCLUDEPATH += ../src diff --git a/src/bmesh.c b/src/bmesh.c index f136b9b4..e2e9a938 100644 --- a/src/bmesh.c +++ b/src/bmesh.c @@ -1,12 +1,21 @@ #include #include #include +#include #include "bmesh.h" #include "array.h" +typedef struct bmeshNodeIndex { + int nodeIndex; + int nextChildIndex; +} bmeshNodeIndex; + struct bmesh { array *nodeArray; array *edgeArray; + array *indexArray; + int rootNodeIndex; + int roundColor; }; bmesh *bmeshCreate(void) { @@ -27,12 +36,21 @@ bmesh *bmeshCreate(void) { bmeshDestroy(bm); return 0; } + bm->indexArray = arrayCreate(sizeof(bmeshNodeIndex)); + if (!bm->indexArray) { + fprintf(stderr, "%s:arrayCreate bmeshNodeIndex failed.\n", __FUNCTION__); + bmeshDestroy(bm); + return 0; + } + bm->rootNodeIndex = -1; + bm->roundColor = 0; return bm; } void bmeshDestroy(bmesh *bm) { arrayDestroy(bm->nodeArray); arrayDestroy(bm->edgeArray); + arrayDestroy(bm->indexArray); free(bm); } @@ -55,14 +73,36 @@ bmeshEdge *bmeshGetEdge(bmesh *bm, int index) { int bmeshAddNode(bmesh *bm, bmeshNode *node) { int index = arrayGetLength(bm->nodeArray); node->index = index; + node->firstChildIndex = -1; + node->childrenIndices = 0; if (0 != arraySetLength(bm->nodeArray, index + 1)) { fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); return -1; } memcpy(arrayGetItem(bm->nodeArray, index), node, sizeof(bmeshNode)); + if (BMESH_NODE_TYPE_ROOT == node->type) { + bm->rootNodeIndex = index; + } return index; } +static int bmeshAddChildNodeRelation(bmesh *bm, int parentNodeIndex, + int childNodeIndex) { + bmeshNode *parentNode = bmeshGetNode(bm, parentNodeIndex); + bmeshNodeIndex *indexItem; + int newChildIndex = arrayGetLength(bm->indexArray); + if (0 != arraySetLength(bm->indexArray, newChildIndex + 1)) { + fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__); + return -1; + } + indexItem = (bmeshNodeIndex *)arrayGetItem(bm->indexArray, newChildIndex); + indexItem->nodeIndex = childNodeIndex; + indexItem->nextChildIndex = parentNode->firstChildIndex; + parentNode->firstChildIndex = newChildIndex; + parentNode->childrenIndices++; + return 0; +} + int bmeshAddEdge(bmesh *bm, bmeshEdge *edge) { int index = arrayGetLength(bm->edgeArray); edge->index = index; @@ -71,11 +111,22 @@ int bmeshAddEdge(bmesh *bm, bmeshEdge *edge) { return -1; } memcpy(arrayGetItem(bm->edgeArray, index), edge, sizeof(bmeshEdge)); + if (0 != bmeshAddChildNodeRelation(bm, edge->firstNodeIndex, + edge->secondNodeIndex)) { + fprintf(stderr, "%s:bmeshAddChildNodeRelation failed.\n", __FUNCTION__); + return -1; + } + if (0 != bmeshAddChildNodeRelation(bm, edge->secondNodeIndex, + edge->firstNodeIndex)) { + fprintf(stderr, "%s:bmeshAddChildNodeRelation failed.\n", __FUNCTION__); + return -1; + } return index; } static int bmeshAddInbetweenNodeBetween(bmesh *bm, - bmeshNode *firstNode, bmeshNode *secondNode, float frac) { + bmeshNode *firstNode, bmeshNode *secondNode, float frac, + int parentNodeIndex) { bmeshNode newNode; memset(&newNode, 0, sizeof(newNode)); newNode.type = BMESH_NODE_TYPE_INBETWEEN; @@ -83,29 +134,125 @@ static int bmeshAddInbetweenNodeBetween(bmesh *bm, secondNode->radius * frac; vec3Lerp(&firstNode->position, &secondNode->position, frac, &newNode.position); - return bmeshAddNode(bm, &newNode); + if (-1 == bmeshAddNode(bm, &newNode)) { + fprintf(stderr, "%s:bmeshAddNode failed.\n", __FUNCTION__); + return -1; + } + if (-1 == bmeshAddChildNodeRelation(bm, parentNodeIndex, newNode.index)) { + fprintf(stderr, "%s:bmeshAddChildNodeRelation failed.\n", __FUNCTION__); + return -1; + } + return newNode.index; } -int bmeshGenerateInbetweenNodes(bmesh *bm) { - int edgeIdx; - for (edgeIdx = 0; edgeIdx < bmeshGetEdgeNum(bm); ++edgeIdx) { - bmeshEdge *edge = bmeshGetEdge(bm, edgeIdx); - bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNode); - bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNode); - float step = 0.5; - float distance = vec3Distance(&firstNode->position, &secondNode->position); - if (distance > 0) { - float offset = step; - if (offset + step <= distance) { - while (offset + step <= distance) { - float frac = offset / distance; - bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, frac); - offset += step; +static int bmeshGenerateInbetweenNodesBetween(bmesh *bm, + int firstNodeIndex, int secondNodeIndex) { + float step = 0.5; + float distance; + int parentNodeIndex = firstNodeIndex; + bmeshNode *firstNode = bmeshGetNode(bm, firstNodeIndex); + bmeshNode *secondNode = bmeshGetNode(bm, secondNodeIndex); + if (secondNode->roundColor == bm->roundColor) { + return 0; + } + distance = vec3Distance(&firstNode->position, &secondNode->position); + if (distance > 0) { + float offset = step; + if (offset + step <= distance) { + while (offset + step <= distance) { + float frac = offset / distance; + parentNodeIndex = bmeshAddInbetweenNodeBetween(bm, + firstNode, secondNode, frac, parentNodeIndex); + if (-1 == parentNodeIndex) { + return -1; } - } else if (distance > step) { - bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, 0.5); + offset += step; + } + } else if (distance > step) { + parentNodeIndex = bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, 0.5, + parentNodeIndex); + if (-1 == parentNodeIndex) { + return -1; } } } + if (-1 == bmeshAddChildNodeRelation(bm, parentNodeIndex, secondNodeIndex)) { + fprintf(stderr, "%s:bmeshAddChildNodeRelation failed.\n", __FUNCTION__); + return -1; + } return 0; } + +int bmeshGetNodeNextChild(bmesh *bm, bmeshNode *node, int *childIndex) { + int currentChildIndex = *childIndex; + bmeshNodeIndex *indexItem; + if (-1 == currentChildIndex) { + if (-1 == node->firstChildIndex) { + return -1; + } + currentChildIndex = node->firstChildIndex; + } + indexItem = (bmeshNodeIndex *)arrayGetItem(bm->indexArray, currentChildIndex); + *childIndex = indexItem->nextChildIndex; + return indexItem->nodeIndex; +} + +bmeshNode *bmeshGetRootNode(bmesh *bm) { + if (-1 == bm->rootNodeIndex) { + return 0; + } + return bmeshGetNode(bm, bm->rootNodeIndex); +} + +static int bmeshGenerateInbetweenNodesFrom(bmesh *bm, int parentNodeIndex) { + int childIndex = -1; + int nodeIndex; + bmeshNode *parent; + + parent = bmeshGetNode(bm, parentNodeIndex); + if (parent->roundColor == bm->roundColor) { + return 0; + } + parent->roundColor = bm->roundColor; + + // + // Old indices came from user's input will be removed + // after the inbetween nodes are genereated, though + // the space occupied in indexArray will not been release. + // + + childIndex = parent->firstChildIndex; + parent->firstChildIndex = -1; + parent->childrenIndices = 0; + + while (-1 != childIndex) { + nodeIndex = bmeshGetNodeNextChild(bm, parent, &childIndex); + if (-1 == nodeIndex) { + break; + } + if (0 != bmeshGenerateInbetweenNodesBetween(bm, parentNodeIndex, + nodeIndex)) { + fprintf(stderr, + "%s:bmeshGenerateInbetweenNodesBetween failed(parentNodeIndex:%d).\n", + __FUNCTION__, parentNodeIndex); + return -1; + } + if (0 != bmeshGenerateInbetweenNodesFrom(bm, nodeIndex)) { + fprintf(stderr, + "%s:bmeshGenerateInbetweenNodesFrom failed(nodeIndex:%d).\n", + __FUNCTION__, nodeIndex); + return -1; + } + } + + return 0; +} + +int bmeshGenerateInbetweenNodes(bmesh *bm) { + if (-1 == bm->rootNodeIndex) { + fprintf(stderr, "%s:No root node.\n", __FUNCTION__); + return -1; + } + bm->roundColor++; + return bmeshGenerateInbetweenNodesFrom(bm, bm->rootNodeIndex); +} diff --git a/src/bmesh.h b/src/bmesh.h index 83b8de8b..36835937 100644 --- a/src/bmesh.h +++ b/src/bmesh.h @@ -19,12 +19,15 @@ typedef struct { vec3 position; float radius; int type; + int childrenIndices; + int firstChildIndex; + int roundColor; } bmeshNode; typedef struct { int index; - int firstNode; - int secondNode; + int firstNodeIndex; + int secondNodeIndex; } bmeshEdge; bmesh *bmeshCreate(void); @@ -36,6 +39,8 @@ bmeshEdge *bmeshGetEdge(bmesh *bm, int index); int bmeshAddNode(bmesh *bm, bmeshNode *node); int bmeshAddEdge(bmesh *bm, bmeshEdge *edge); int bmeshGenerateInbetweenNodes(bmesh *bm); +int bmeshGetNodeNextChild(bmesh *bm, bmeshNode *node, int *childIndex); +bmeshNode *bmeshGetRootNode(bmesh *bm); #ifdef __cplusplus } diff --git a/src/draw.h b/src/draw.h index a3acb605..4761976c 100644 --- a/src/draw.h +++ b/src/draw.h @@ -15,6 +15,10 @@ typedef struct { vec3 pt[3]; } triangle; +typedef struct { + vec3 pt[4]; +} quard; + typedef struct { int npoly; triangle *poly; diff --git a/src/render.cpp b/src/render.cpp index 4c7a6cda..a0e2f06c 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -23,10 +23,24 @@ static int drawBmeshNode(bmesh *bm, bmeshNode *node) { return 0; } +static void drawBmeshNodeRecursively(bmesh *bm, bmeshNode *node) { + int childIndex = node->firstChildIndex; + int childNodeIndex; + + drawBmeshNode(bm, node); + while (-1 != childIndex) { + childNodeIndex = bmeshGetNodeNextChild(bm, node, &childIndex); + if (-1 == childNodeIndex) { + break; + } + drawBmeshNodeRecursively(bm, bmeshGetNode(bm, childNodeIndex)); + } +} + static int drawBmeshEdge(bmesh *bm, bmeshEdge *edge) { glColor3fv(bmeshEdgeColor); - bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNode); - bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNode); + bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNodeIndex); + bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNodeIndex); drawCylinder(&firstNode->position, &secondNode->position, 0.1, 36, 24); return 0; } @@ -133,20 +147,23 @@ void Render::paintGL() { for (i = 0; i < sizeof(bmeshTest1Edges) / sizeof(bmeshTest1Edges[0]); ++i) { memset(&edge, 0, sizeof(edge)); - edge.firstNode = bmeshTest1Edges[i][0]; - edge.secondNode = bmeshTest1Edges[i][1]; + edge.firstNodeIndex = bmeshTest1Edges[i][0]; + edge.secondNodeIndex = bmeshTest1Edges[i][1]; bmeshAddEdge(bm, &edge); } bmeshGenerateInbetweenNodes(bm); } + drawBmeshNodeRecursively(bm, bmeshGetRootNode(bm)); + { int index; + /* for (index = 0; index < bmeshGetNodeNum(bm); ++index) { bmeshNode *node = bmeshGetNode(bm, index); drawBmeshNode(bm, node); - } + }*/ for (index = 0; index < bmeshGetEdgeNum(bm); ++index) { bmeshEdge *edge = bmeshGetEdge(bm, index); drawBmeshEdge(bm, edge); @@ -161,7 +178,7 @@ void Render::resizeGL(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(60.0f, w/h, 1, 100); + gluPerspective(60.0f, w/h, 1, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity();