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,7 +21,7 @@ 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. 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. Now, for just beginning, I think it's a not bad start.
<img src="screenshot/dust3d_sphere_cylinder.png"> <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* *Drawing Skeletal Shape Balls*
Draw shape ball is easy, no need to rotate, I just need scale it along the ball's radius. 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. 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.
@ -29,10 +29,12 @@ Draw the cylinder which connects two shape balls is more difficult, I need do so
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. 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. 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. 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"> <img src="screenshot/dust3d_node_edge_with_glu.png" style="width:170px; height:140px;">
*B-Mesh data struct* *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` 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"> <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 - [ ] Export Wavefront .obj
- [ ] Render B-Mesh result - [ ] Render B-Mesh result
- [ ] Design UI for monster parts configuration - [ ] Design UI for monster parts configuration

View File

@ -1,9 +1,9 @@
const float bmeshTest1Nodes[][4] = { const float bmeshTest1Nodes[][6] = {
{0, -2.07575, 1.53902, 0.04122}, {1, 2.40837, 2.34882, 0.48585}, {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}, {3, 2.25224, 0.74973, 0.85115}, {2, -0.91403, 0.77069, 0.62299, 0.5}, {3, 2.25224, 0.74973, 0.85115, 0.5},
{4, 0, 0, 0}, {4, 0, 0, 0, 0.8, 1},
{5, 0.00920, -0.66115, -2.04601}, {5, 0.00920, -0.66115, -2.04601, 0.5},
{6, 0.01726, -0.88224, -2.87471} {6, 0.01726, -0.88224, -2.87471, 0.2}
}; };
const int bmeshTest1Edges[][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)); memcpy(arrayGetItem(bm->edgeArray, index), edge, sizeof(bmeshEdge));
return index; 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 #endif
typedef enum { typedef enum {
BMESH_NODE_FLAG_KEY = 0x00000001, BMESH_NODE_TYPE_KEY = 0,
BMESH_NODE_FLAG_INBETWEEN = 0x00000002, BMESH_NODE_TYPE_ROOT = 1,
BMESH_NODE_FLAG_ROOT = 0x00000010, BMESH_NODE_TYPE_INBETWEEN = 2,
} bmeshNodeFlag; } bmeshNodeType;
typedef struct bmesh bmesh; typedef struct bmesh bmesh;
@ -18,7 +18,7 @@ typedef struct {
int index; int index;
vec3 position; vec3 position;
float radius; float radius;
unsigned int flag; int type;
} bmeshNode; } bmeshNode;
typedef struct { typedef struct {
@ -35,6 +35,7 @@ bmeshNode *bmeshGetNode(bmesh *bm, int index);
bmeshEdge *bmeshGetEdge(bmesh *bm, int index); 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);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -6,7 +6,8 @@
MainWindow::MainWindow(void) { MainWindow::MainWindow(void) {
render = new Render; 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; QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(render); mainLayout->addWidget(render);
setLayout(mainLayout); setLayout(mainLayout);

View File

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

View File

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