Add tree data struct of nodes
parent
9b31fa85e8
commit
5bf806f363
|
@ -2,6 +2,7 @@ TARGET = dust3d
|
|||
TEMPLATE = app
|
||||
|
||||
QT += widgets opengl
|
||||
CONFIG += debug
|
||||
|
||||
VPATH += ../src
|
||||
INCLUDEPATH += ../src
|
||||
|
|
185
src/bmesh.c
185
src/bmesh.c
|
@ -1,12 +1,21 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@ typedef struct {
|
|||
vec3 pt[3];
|
||||
} triangle;
|
||||
|
||||
typedef struct {
|
||||
vec3 pt[4];
|
||||
} quard;
|
||||
|
||||
typedef struct {
|
||||
int npoly;
|
||||
triangle *poly;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue