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.
|
||||
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.
|
||||
|
@ -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.
|
||||
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">
|
||||
<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">
|
||||
<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
|
||||
|
|
|
@ -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 |
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));
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue