Add tree data struct of nodes

master
Jeremy Hu 2016-12-21 23:36:47 +09:30
parent 9b31fa85e8
commit 5bf806f363
5 changed files with 201 additions and 27 deletions

View File

@ -2,6 +2,7 @@ TARGET = dust3d
TEMPLATE = app
QT += widgets opengl
CONFIG += debug
VPATH += ../src
INCLUDEPATH += ../src

View File

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

View File

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

View File

@ -15,6 +15,10 @@ typedef struct {
vec3 pt[3];
} triangle;
typedef struct {
vec3 pt[4];
} quard;
typedef struct {
int npoly;
triangle *poly;

View File

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