Add tree data struct of nodes
parent
9b31fa85e8
commit
5bf806f363
|
@ -2,6 +2,7 @@ TARGET = dust3d
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
QT += widgets opengl
|
QT += widgets opengl
|
||||||
|
CONFIG += debug
|
||||||
|
|
||||||
VPATH += ../src
|
VPATH += ../src
|
||||||
INCLUDEPATH += ../src
|
INCLUDEPATH += ../src
|
||||||
|
|
169
src/bmesh.c
169
src/bmesh.c
|
@ -1,12 +1,21 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
|
||||||
|
typedef struct bmeshNodeIndex {
|
||||||
|
int nodeIndex;
|
||||||
|
int nextChildIndex;
|
||||||
|
} bmeshNodeIndex;
|
||||||
|
|
||||||
struct bmesh {
|
struct bmesh {
|
||||||
array *nodeArray;
|
array *nodeArray;
|
||||||
array *edgeArray;
|
array *edgeArray;
|
||||||
|
array *indexArray;
|
||||||
|
int rootNodeIndex;
|
||||||
|
int roundColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
bmesh *bmeshCreate(void) {
|
bmesh *bmeshCreate(void) {
|
||||||
|
@ -27,12 +36,21 @@ bmesh *bmeshCreate(void) {
|
||||||
bmeshDestroy(bm);
|
bmeshDestroy(bm);
|
||||||
return 0;
|
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;
|
return bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bmeshDestroy(bmesh *bm) {
|
void bmeshDestroy(bmesh *bm) {
|
||||||
arrayDestroy(bm->nodeArray);
|
arrayDestroy(bm->nodeArray);
|
||||||
arrayDestroy(bm->edgeArray);
|
arrayDestroy(bm->edgeArray);
|
||||||
|
arrayDestroy(bm->indexArray);
|
||||||
free(bm);
|
free(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +73,36 @@ bmeshEdge *bmeshGetEdge(bmesh *bm, int index) {
|
||||||
int bmeshAddNode(bmesh *bm, bmeshNode *node) {
|
int bmeshAddNode(bmesh *bm, bmeshNode *node) {
|
||||||
int index = arrayGetLength(bm->nodeArray);
|
int index = arrayGetLength(bm->nodeArray);
|
||||||
node->index = index;
|
node->index = index;
|
||||||
|
node->firstChildIndex = -1;
|
||||||
|
node->childrenIndices = 0;
|
||||||
if (0 != arraySetLength(bm->nodeArray, index + 1)) {
|
if (0 != arraySetLength(bm->nodeArray, index + 1)) {
|
||||||
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(arrayGetItem(bm->nodeArray, index), node, sizeof(bmeshNode));
|
memcpy(arrayGetItem(bm->nodeArray, index), node, sizeof(bmeshNode));
|
||||||
|
if (BMESH_NODE_TYPE_ROOT == node->type) {
|
||||||
|
bm->rootNodeIndex = index;
|
||||||
|
}
|
||||||
return 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 bmeshAddEdge(bmesh *bm, bmeshEdge *edge) {
|
||||||
int index = arrayGetLength(bm->edgeArray);
|
int index = arrayGetLength(bm->edgeArray);
|
||||||
edge->index = index;
|
edge->index = index;
|
||||||
|
@ -71,11 +111,22 @@ int bmeshAddEdge(bmesh *bm, bmeshEdge *edge) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(arrayGetItem(bm->edgeArray, index), edge, sizeof(bmeshEdge));
|
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;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bmeshAddInbetweenNodeBetween(bmesh *bm,
|
static int bmeshAddInbetweenNodeBetween(bmesh *bm,
|
||||||
bmeshNode *firstNode, bmeshNode *secondNode, float frac) {
|
bmeshNode *firstNode, bmeshNode *secondNode, float frac,
|
||||||
|
int parentNodeIndex) {
|
||||||
bmeshNode newNode;
|
bmeshNode newNode;
|
||||||
memset(&newNode, 0, sizeof(newNode));
|
memset(&newNode, 0, sizeof(newNode));
|
||||||
newNode.type = BMESH_NODE_TYPE_INBETWEEN;
|
newNode.type = BMESH_NODE_TYPE_INBETWEEN;
|
||||||
|
@ -83,29 +134,125 @@ static int bmeshAddInbetweenNodeBetween(bmesh *bm,
|
||||||
secondNode->radius * frac;
|
secondNode->radius * frac;
|
||||||
vec3Lerp(&firstNode->position, &secondNode->position, frac,
|
vec3Lerp(&firstNode->position, &secondNode->position, frac,
|
||||||
&newNode.position);
|
&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) {
|
static int bmeshGenerateInbetweenNodesBetween(bmesh *bm,
|
||||||
int edgeIdx;
|
int firstNodeIndex, int secondNodeIndex) {
|
||||||
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 step = 0.5;
|
||||||
float distance = vec3Distance(&firstNode->position, &secondNode->position);
|
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) {
|
if (distance > 0) {
|
||||||
float offset = step;
|
float offset = step;
|
||||||
if (offset + step <= distance) {
|
if (offset + step <= distance) {
|
||||||
while (offset + step <= distance) {
|
while (offset + step <= distance) {
|
||||||
float frac = offset / distance;
|
float frac = offset / distance;
|
||||||
bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, frac);
|
parentNodeIndex = bmeshAddInbetweenNodeBetween(bm,
|
||||||
|
firstNode, secondNode, frac, parentNodeIndex);
|
||||||
|
if (-1 == parentNodeIndex) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
offset += step;
|
offset += step;
|
||||||
}
|
}
|
||||||
} else if (distance > step) {
|
} else if (distance > step) {
|
||||||
bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, 0.5);
|
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;
|
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;
|
vec3 position;
|
||||||
float radius;
|
float radius;
|
||||||
int type;
|
int type;
|
||||||
|
int childrenIndices;
|
||||||
|
int firstChildIndex;
|
||||||
|
int roundColor;
|
||||||
} bmeshNode;
|
} bmeshNode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int index;
|
int index;
|
||||||
int firstNode;
|
int firstNodeIndex;
|
||||||
int secondNode;
|
int secondNodeIndex;
|
||||||
} bmeshEdge;
|
} bmeshEdge;
|
||||||
|
|
||||||
bmesh *bmeshCreate(void);
|
bmesh *bmeshCreate(void);
|
||||||
|
@ -36,6 +39,8 @@ bmeshEdge *bmeshGetEdge(bmesh *bm, int index);
|
||||||
int bmeshAddNode(bmesh *bm, bmeshNode *node);
|
int bmeshAddNode(bmesh *bm, bmeshNode *node);
|
||||||
int bmeshAddEdge(bmesh *bm, bmeshEdge *edge);
|
int bmeshAddEdge(bmesh *bm, bmeshEdge *edge);
|
||||||
int bmeshGenerateInbetweenNodes(bmesh *bm);
|
int bmeshGenerateInbetweenNodes(bmesh *bm);
|
||||||
|
int bmeshGetNodeNextChild(bmesh *bm, bmeshNode *node, int *childIndex);
|
||||||
|
bmeshNode *bmeshGetRootNode(bmesh *bm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ typedef struct {
|
||||||
vec3 pt[3];
|
vec3 pt[3];
|
||||||
} triangle;
|
} triangle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3 pt[4];
|
||||||
|
} quard;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int npoly;
|
int npoly;
|
||||||
triangle *poly;
|
triangle *poly;
|
||||||
|
|
|
@ -23,10 +23,24 @@ static int drawBmeshNode(bmesh *bm, bmeshNode *node) {
|
||||||
return 0;
|
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) {
|
static int drawBmeshEdge(bmesh *bm, bmeshEdge *edge) {
|
||||||
glColor3fv(bmeshEdgeColor);
|
glColor3fv(bmeshEdgeColor);
|
||||||
bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNode);
|
bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNodeIndex);
|
||||||
bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNode);
|
bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNodeIndex);
|
||||||
drawCylinder(&firstNode->position, &secondNode->position, 0.1, 36, 24);
|
drawCylinder(&firstNode->position, &secondNode->position, 0.1, 36, 24);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -133,20 +147,23 @@ void Render::paintGL() {
|
||||||
|
|
||||||
for (i = 0; i < sizeof(bmeshTest1Edges) / sizeof(bmeshTest1Edges[0]); ++i) {
|
for (i = 0; i < sizeof(bmeshTest1Edges) / sizeof(bmeshTest1Edges[0]); ++i) {
|
||||||
memset(&edge, 0, sizeof(edge));
|
memset(&edge, 0, sizeof(edge));
|
||||||
edge.firstNode = bmeshTest1Edges[i][0];
|
edge.firstNodeIndex = bmeshTest1Edges[i][0];
|
||||||
edge.secondNode = bmeshTest1Edges[i][1];
|
edge.secondNodeIndex = bmeshTest1Edges[i][1];
|
||||||
bmeshAddEdge(bm, &edge);
|
bmeshAddEdge(bm, &edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
bmeshGenerateInbetweenNodes(bm);
|
bmeshGenerateInbetweenNodes(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawBmeshNodeRecursively(bm, bmeshGetRootNode(bm));
|
||||||
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
/*
|
||||||
for (index = 0; index < bmeshGetNodeNum(bm); ++index) {
|
for (index = 0; index < bmeshGetNodeNum(bm); ++index) {
|
||||||
bmeshNode *node = bmeshGetNode(bm, index);
|
bmeshNode *node = bmeshGetNode(bm, index);
|
||||||
drawBmeshNode(bm, node);
|
drawBmeshNode(bm, node);
|
||||||
}
|
}*/
|
||||||
for (index = 0; index < bmeshGetEdgeNum(bm); ++index) {
|
for (index = 0; index < bmeshGetEdgeNum(bm); ++index) {
|
||||||
bmeshEdge *edge = bmeshGetEdge(bm, index);
|
bmeshEdge *edge = bmeshGetEdge(bm, index);
|
||||||
drawBmeshEdge(bm, edge);
|
drawBmeshEdge(bm, edge);
|
||||||
|
@ -161,7 +178,7 @@ void Render::resizeGL(int w, int h) {
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluPerspective(60.0f, w/h, 1, 100);
|
gluPerspective(60.0f, w/h, 1, 1000);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
Loading…
Reference in New Issue