Generate inbetween nodes between bmesh key nodes
parent
b6af60f08c
commit
a73f351fd6
|
@ -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
|
||||||
|
|
|
@ -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 |
36
src/bmesh.c
36
src/bmesh.c
|
@ -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;
|
||||||
|
}
|
||||||
|
|
11
src/bmesh.h
11
src/bmesh.h
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue