Generate inbetween nodes between bmesh key nodes

master
Jeremy Hu 2016-12-20 21:45:23 +09:30
parent b6af60f08c
commit a73f351fd6
10 changed files with 95 additions and 30 deletions

View File

@ -21,18 +21,20 @@ Two caps and many strips composites a cylinder.
Almost all 3D editor have a infinite grid ground, I just made a finite one, in the future, I should expand the grid outside of the screen to make it infinite.
Now, for just beginning, I think it's a not bad start.
<img src="screenshot/dust3d_sphere_cylinder.png">
- [ ] Implement B-Mesh algorithm (Dec 18, 2016 ~ Dec 19, 2016)
- [ ] Implement B-Mesh algorithm (Dec 18, 2016 ~ Dec 20, 2016)
*Drawing Skeletal Shape Balls*
Draw shape ball is easy, no need to rotate, I just need scale it along the ball's radius.
Draw the cylinder which connects two shape balls is more difficult, I need do some math to rotate it. [Here](http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c) described it.
*Camera Control*
Camera rotate/zoom implemented, [here](http://www.songho.ca/opengl/gl_transform.html) is a good article which explained the theory of OpenGL Transformation. Most important is that the demo app is very beautiful.
Added x,z axis, looks better than last screenshot.
I have to use the GLU library, the previous implementation of drawSphere and drawCylinder looks not good, and take too much time to debug.
<img src="screenshot/dust3d_node_edge_with_glu.png">
I have to use the GLU library, the previous implementation of drawSphere and drawCylinder looks not good, and take too much time to debug.
<img src="screenshot/dust3d_node_edge_with_glu.png" style="width:170px; height:140px;">
*B-Mesh data struct*
I created the test nodes's geometry information from Blender. Here is the render result of `data/bmesh_test_1.h`
<img src="screenshot/dust3d_bmesh_nodes.png">
I created the test nodes's geometry information from Blender. Here is the render result of `data/bmesh_test_1.h`
<img src="screenshot/dust3d_bmesh_nodes.png" style="width:206px; height:164px;">
*Generate Inbetween Nodes*
<img src="screenshot/dust3d_bmesh_skeleton.png" style="width:124px; height:128px;"> <img src="screenshot/dust3d_bmesh_inbetween.png" style="width:124px; height:128px;">
- [ ] Export Wavefront .obj
- [ ] Render B-Mesh result
- [ ] Design UI for monster parts configuration

View File

@ -1,9 +1,9 @@
const float bmeshTest1Nodes[][4] = {
{0, -2.07575, 1.53902, 0.04122}, {1, 2.40837, 2.34882, 0.48585},
{2, -0.91403, 0.77069, 0.62299}, {3, 2.25224, 0.74973, 0.85115},
{4, 0, 0, 0},
{5, 0.00920, -0.66115, -2.04601},
{6, 0.01726, -0.88224, -2.87471}
const float bmeshTest1Nodes[][6] = {
{0, -2.07575, 1.53902, 0.04122, 0.25}, {1, 2.40837, 2.34882, 0.48585, 0.3},
{2, -0.91403, 0.77069, 0.62299, 0.5}, {3, 2.25224, 0.74973, 0.85115, 0.5},
{4, 0, 0, 0, 0.8, 1},
{5, 0.00920, -0.66115, -2.04601, 0.5},
{6, 0.01726, -0.88224, -2.87471, 0.2}
};
const int bmeshTest1Edges[][2] = {

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View File

@ -73,3 +73,39 @@ int bmeshAddEdge(bmesh *bm, bmeshEdge *edge) {
memcpy(arrayGetItem(bm->edgeArray, index), edge, sizeof(bmeshEdge));
return index;
}
static int bmeshAddInbetweenNodeBetween(bmesh *bm,
bmeshNode *firstNode, bmeshNode *secondNode, float frac) {
bmeshNode newNode;
memset(&newNode, 0, sizeof(newNode));
newNode.type = BMESH_NODE_TYPE_INBETWEEN;
newNode.radius = firstNode->radius * (1 - frac) +
secondNode->radius * frac;
vec3Lerp(&firstNode->position, &secondNode->position, frac,
&newNode.position);
return bmeshAddNode(bm, &newNode);
}
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;
}
} else if (distance > step) {
bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, 0.5);
}
}
}
return 0;
}

View File

@ -7,10 +7,10 @@ extern "C" {
#endif
typedef enum {
BMESH_NODE_FLAG_KEY = 0x00000001,
BMESH_NODE_FLAG_INBETWEEN = 0x00000002,
BMESH_NODE_FLAG_ROOT = 0x00000010,
} bmeshNodeFlag;
BMESH_NODE_TYPE_KEY = 0,
BMESH_NODE_TYPE_ROOT = 1,
BMESH_NODE_TYPE_INBETWEEN = 2,
} bmeshNodeType;
typedef struct bmesh bmesh;
@ -18,7 +18,7 @@ typedef struct {
int index;
vec3 position;
float radius;
unsigned int flag;
int type;
} bmeshNode;
typedef struct {
@ -35,6 +35,7 @@ bmeshNode *bmeshGetNode(bmesh *bm, int index);
bmeshEdge *bmeshGetEdge(bmesh *bm, int index);
int bmeshAddNode(bmesh *bm, bmeshNode *node);
int bmeshAddEdge(bmesh *bm, bmeshEdge *edge);
int bmeshGenerateInbetweenNodes(bmesh *bm);
#ifdef __cplusplus
}

View File

@ -6,7 +6,8 @@
MainWindow::MainWindow(void) {
render = new Render;
resize(QDesktopWidget().availableGeometry(this).size() * 0.7);
int size = QDesktopWidget().availableGeometry(this).size().height() * 0.7;
resize(QSize(size, size));
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(render);
setLayout(mainLayout);

View File

@ -7,18 +7,24 @@
#include "bmesh.h"
#include "matrix.h"
static const float bmeshNodeColors[][3] {
{0, 0.78, 1},
{1, 0, 0},
{1, 1, 1}
};
static const float bmeshEdgeColor[3] = {1, 1, 0};
static QGLWidget *_this = 0;
static int drawBmeshNode(bmesh *bm, bmeshNode *node) {
float color1[3] = {1, 0, 0};
glColor3fv(color1);
glColor3fv(bmeshNodeColors[node->type]);
drawSphere(&node->position, node->radius, 36, 24);
return 0;
}
static int drawBmeshEdge(bmesh *bm, bmeshEdge *edge) {
float color2[3] = {1, 1, 0};
glColor3fv(color2);
glColor3fv(bmeshEdgeColor);
bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNode);
bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNode);
drawCylinder(&firstNode->position, &secondNode->position, 0.1, 36, 24);
@ -26,7 +32,10 @@ static int drawBmeshEdge(bmesh *bm, bmeshEdge *edge) {
}
int drawText(int x, int y, char *text) {
_this->renderText(x, y, QString(text));
QFont font = QFont("Arial");
font.setPointSize(9);
font.setBold(false);
_this->renderText(x, y, QString(text), font);
return 0;
}
@ -40,7 +49,7 @@ Render::Render(QWidget *parent)
mouseY = 0;
cameraAngleX = 20;
cameraAngleY = -225;
cameraDistance = 3;
cameraDistance = 7;
}
Render::~Render(void) {
@ -99,8 +108,8 @@ void Render::paintGL() {
glRotatef(cameraAngleY, 0, 1, 0);
glColor3f(0, 0, 0);
drawPrintf(0, 10, "cameraAngleX:%f cameraAngleY:%f", cameraAngleX,
cameraAngleY);
drawPrintf(0, 10, "cameraAngleX:%f cameraAngleY:%f cameraDistance:%f",
cameraAngleX, cameraAngleY, cameraDistance);
drawGrid(10, 1);
@ -117,7 +126,8 @@ void Render::paintGL() {
node.position.x = bmeshTest1Nodes[i][1];
node.position.y = bmeshTest1Nodes[i][2];
node.position.z = bmeshTest1Nodes[i][3];
node.radius = 0.35;
node.radius = bmeshTest1Nodes[i][4];
node.type = bmeshTest1Nodes[i][5];
bmeshAddNode(bm, &node);
}
@ -127,6 +137,8 @@ void Render::paintGL() {
edge.secondNode = bmeshTest1Edges[i][1];
bmeshAddEdge(bm, &edge);
}
bmeshGenerateInbetweenNodes(bm);
}
{
@ -149,7 +161,7 @@ void Render::resizeGL(int w, int h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, w/(h/2.0f), 1, 100);
gluPerspective(60.0f, w/h, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

View File

@ -1,3 +1,4 @@
#include <math.h>
#include "vector3d.h"
float vec3Length(vec3 *p) {
@ -18,9 +19,13 @@ void vec3Normalize(vec3 *p) {
}
void vec3Midpoint(vec3 *a, vec3 *b, vec3 *mid) {
mid->x = (a->x + b->x) * 0.5;
mid->y = (a->y + b->y) * 0.5;
mid->z = (a->z + b->z) * 0.5;
vec3Lerp(a, b, 0.5, mid);
}
void vec3Lerp(vec3 *a, vec3 *b, float frac, vec3 *result) {
result->x = a->x + (b->x - a->x) * frac;
result->y = a->y + (b->y - a->y) * frac;
result->z = a->z + (b->z - a->z) * frac;
}
void vec3Sub(vec3 *a, vec3 *b, vec3 *result) {
@ -38,3 +43,9 @@ void vec3CrossProduct(vec3 *a, vec3 *b, vec3 *result) {
float vec3DotProduct(vec3 *a, vec3 *b) {
return a->x * b->x + a->y * b->y + a->z * b->z;
}
float vec3Distance(vec3 *a, vec3 *b) {
vec3 p;
vec3Sub(a, b, &p);
return vec3Length(&p);
}

View File

@ -13,10 +13,12 @@ typedef struct {
void vec3Normalize(vec3 *p);
void vec3Midpoint(vec3 *a, vec3 *b, vec3 *mid);
void vec3Lerp(vec3 *a, vec3 *b, float frac, vec3 *result);
void vec3CrossProduct(vec3 *a, vec3 *b, vec3 *result);
void vec3Sub(vec3 *a, vec3 *b, vec3 *result);
float vec3DotProduct(vec3 *a, vec3 *b);
float vec3Length(vec3 *p);
float vec3Distance(vec3 *a, vec3 *b);
#ifdef __cplusplus
}