parent
5bf806f363
commit
ef1836ab06
17
README.md
17
README.md
|
@ -7,7 +7,18 @@ Idea
|
||||||
I was inspired by Jimmy Gunawan's blogs of monster generation, here is the first one [INSPIRATION / Pixar Monster Factory Part One](http://blendersushi.blogspot.com.au/2013/06/inspiration-pixar-monster-factory-part.html), and by search the Skin Modifier of Blender, I found the theory of Skin Modifier:
|
I was inspired by Jimmy Gunawan's blogs of monster generation, here is the first one [INSPIRATION / Pixar Monster Factory Part One](http://blendersushi.blogspot.com.au/2013/06/inspiration-pixar-monster-factory-part.html), and by search the Skin Modifier of Blender, I found the theory of Skin Modifier:
|
||||||
[B-Mesh: A Fast Modeling System for Base Meshes
|
[B-Mesh: A Fast Modeling System for Base Meshes
|
||||||
of 3D Articulated Shapes](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.357.7134&rep=rep1&type=pdf)(Authors: Zhongping Ji, Ligang Liu, Yigang Wang). I started to think of monster model generation for game development from years ago, thanks for this paper, Dust3D is achievable now.
|
of 3D Articulated Shapes](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.357.7134&rep=rep1&type=pdf)(Authors: Zhongping Ji, Ligang Liu, Yigang Wang). I started to think of monster model generation for game development from years ago, thanks for this paper, Dust3D is achievable now.
|
||||||
From my initial thought, Dust3D should be a tool like [Makehuman](http://www.makehuman.org), with more versatile features, not only can make human, but also be able to **generate monsters automatically**.
|
From my initial thought, Dust3D should be a tool like [Makehuman](http://www.makehuman.org), with more versatile features, not only can make human, but also be able to **generate monsters automatically**.
|
||||||
|
|
||||||
|
Build
|
||||||
|
============
|
||||||
|
*Generate Xcode Project*
|
||||||
|
```
|
||||||
|
$ qmake -spec macx-xcode
|
||||||
|
```
|
||||||
|
*Generate Makefile*
|
||||||
|
```
|
||||||
|
$ qmake
|
||||||
|
```
|
||||||
|
|
||||||
TODO & Progress
|
TODO & Progress
|
||||||
==============
|
==============
|
||||||
|
@ -35,6 +46,9 @@ I created the test nodes's geometry information from Blender. Here is the render
|
||||||
<img src="screenshot/dust3d_bmesh_nodes.png" width="206" height="164">
|
<img src="screenshot/dust3d_bmesh_nodes.png" width="206" height="164">
|
||||||
*Generate Inbetween Nodes*
|
*Generate Inbetween Nodes*
|
||||||
<img src="screenshot/dust3d_bmesh_skeleton.png" width="124" height="128"> <img src="screenshot/dust3d_bmesh_inbetween.png" width="124" height="128">
|
<img src="screenshot/dust3d_bmesh_skeleton.png" width="124" height="128"> <img src="screenshot/dust3d_bmesh_inbetween.png" width="124" height="128">
|
||||||
|
*Generate Mesh*
|
||||||
|
<img src="screenshot/dust3d_generate_quad.png" width="124" height="128">
|
||||||
|
When I am implementing the B-Mesh algorithm, I am also think in the future, how to create a library of bunch of initial base models. There is a paper [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf) described how to generate skeleton from mesh, this is the reverse progress of what I am doing, I think it can resolve the problem of insufficient initial base models, I can generate from tons of existed models.
|
||||||
- [ ] 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
|
||||||
|
@ -43,3 +57,4 @@ I created the test nodes's geometry information from Blender. Here is the render
|
||||||
- [ ] png exporter for isometric 2.5D game
|
- [ ] png exporter for isometric 2.5D game
|
||||||
- [ ] Version 0.01 release
|
- [ ] Version 0.01 release
|
||||||
- [ ] Materials merge of different parts
|
- [ ] Materials merge of different parts
|
||||||
|
- [ ] Implement [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 306 KiB |
121
src/bmesh.c
121
src/bmesh.c
|
@ -2,8 +2,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
typedef struct bmeshNodeIndex {
|
typedef struct bmeshNodeIndex {
|
||||||
int nodeIndex;
|
int nodeIndex;
|
||||||
|
@ -14,6 +16,7 @@ struct bmesh {
|
||||||
array *nodeArray;
|
array *nodeArray;
|
||||||
array *edgeArray;
|
array *edgeArray;
|
||||||
array *indexArray;
|
array *indexArray;
|
||||||
|
array *quadArray;
|
||||||
int rootNodeIndex;
|
int rootNodeIndex;
|
||||||
int roundColor;
|
int roundColor;
|
||||||
};
|
};
|
||||||
|
@ -42,6 +45,12 @@ bmesh *bmeshCreate(void) {
|
||||||
bmeshDestroy(bm);
|
bmeshDestroy(bm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
bm->quadArray = arrayCreate(sizeof(quad));
|
||||||
|
if (!bm->quadArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate quad failed.\n", __FUNCTION__);
|
||||||
|
bmeshDestroy(bm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
bm->rootNodeIndex = -1;
|
bm->rootNodeIndex = -1;
|
||||||
bm->roundColor = 0;
|
bm->roundColor = 0;
|
||||||
return bm;
|
return bm;
|
||||||
|
@ -51,6 +60,7 @@ void bmeshDestroy(bmesh *bm) {
|
||||||
arrayDestroy(bm->nodeArray);
|
arrayDestroy(bm->nodeArray);
|
||||||
arrayDestroy(bm->edgeArray);
|
arrayDestroy(bm->edgeArray);
|
||||||
arrayDestroy(bm->indexArray);
|
arrayDestroy(bm->indexArray);
|
||||||
|
arrayDestroy(bm->quadArray);
|
||||||
free(bm);
|
free(bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,19 +155,95 @@ static int bmeshAddInbetweenNodeBetween(bmesh *bm,
|
||||||
return newNode.index;
|
return newNode.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void floatsToQuad(float *floats, quad *q) {
|
||||||
|
int i;
|
||||||
|
int offset = 0;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
q->pt[i].x = floats[offset++];
|
||||||
|
q->pt[i].y = floats[offset++];
|
||||||
|
q->pt[i].z = floats[offset++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bmeshGenerateNodeQuad(bmesh *bm, bmeshNode *node,
|
||||||
|
matrix *matRotate, int connectWithQuad) {
|
||||||
|
quad q;
|
||||||
|
matrix matTranslate;
|
||||||
|
matrix matFinal;
|
||||||
|
int i;
|
||||||
|
float floats[4][3] = {
|
||||||
|
{-node->radius, +node->radius, 0},
|
||||||
|
{-node->radius, -node->radius, 0},
|
||||||
|
{+node->radius, -node->radius, 0},
|
||||||
|
{+node->radius, +node->radius, 0},
|
||||||
|
};
|
||||||
|
matrixTranslate(&matTranslate, node->position.x, node->position.y,
|
||||||
|
node->position.z);
|
||||||
|
matrixLoadIdentity(&matFinal);
|
||||||
|
matrixAppend(&matFinal, &matTranslate);
|
||||||
|
matrixAppend(&matFinal, matRotate);
|
||||||
|
matrixTransformVector(&matFinal, floats[0]);
|
||||||
|
matrixTransformVector(&matFinal, floats[1]);
|
||||||
|
matrixTransformVector(&matFinal, floats[2]);
|
||||||
|
matrixTransformVector(&matFinal, floats[3]);
|
||||||
|
floatsToQuad(&floats[0][0], &q);
|
||||||
|
if (-1 == bmeshAddQuad(bm, &q)) {
|
||||||
|
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (connectWithQuad >= 0) {
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
quad face;
|
||||||
|
quad *lastQ = bmeshGetQuad(bm, connectWithQuad);
|
||||||
|
face.pt[0].x = lastQ->pt[(0 + i) % 4].x;
|
||||||
|
face.pt[0].y = lastQ->pt[(0 + i) % 4].y;
|
||||||
|
face.pt[0].z = lastQ->pt[(0 + i) % 4].z;
|
||||||
|
face.pt[1].x = q.pt[(0 + i) % 4].x;
|
||||||
|
face.pt[1].y = q.pt[(0 + i) % 4].y;
|
||||||
|
face.pt[1].z = q.pt[(0 + i) % 4].z;
|
||||||
|
face.pt[2].x = q.pt[(1 + i) % 4].x;
|
||||||
|
face.pt[2].y = q.pt[(1 + i) % 4].y;
|
||||||
|
face.pt[2].z = q.pt[(1 + i) % 4].z;
|
||||||
|
face.pt[3].x = lastQ->pt[(1 + i) % 4].x;
|
||||||
|
face.pt[3].y = lastQ->pt[(1 + i) % 4].y;
|
||||||
|
face.pt[3].z = lastQ->pt[(1 + i) % 4].z;
|
||||||
|
if (-1 == bmeshAddQuad(bm, &face)) {
|
||||||
|
fprintf(stderr, "%s:meshAddQuad failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int bmeshGenerateInbetweenNodesBetween(bmesh *bm,
|
static int bmeshGenerateInbetweenNodesBetween(bmesh *bm,
|
||||||
int firstNodeIndex, int secondNodeIndex) {
|
int firstNodeIndex, int secondNodeIndex) {
|
||||||
float step = 0.5;
|
float step = 0.5;
|
||||||
float distance;
|
float distance;
|
||||||
int parentNodeIndex = firstNodeIndex;
|
int parentNodeIndex = firstNodeIndex;
|
||||||
|
float rotateAngle = 0;
|
||||||
|
vec3 rotateAround = {0, 0, 0};
|
||||||
|
vec3 p;
|
||||||
|
vec3 zAxis = {0, 0, 1};
|
||||||
|
matrix matRotate;
|
||||||
|
int lastQuadIndex = -1;
|
||||||
|
|
||||||
bmeshNode *firstNode = bmeshGetNode(bm, firstNodeIndex);
|
bmeshNode *firstNode = bmeshGetNode(bm, firstNodeIndex);
|
||||||
bmeshNode *secondNode = bmeshGetNode(bm, secondNodeIndex);
|
bmeshNode *secondNode = bmeshGetNode(bm, secondNodeIndex);
|
||||||
|
bmeshNode *newNode;
|
||||||
if (secondNode->roundColor == bm->roundColor) {
|
if (secondNode->roundColor == bm->roundColor) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
distance = vec3Distance(&firstNode->position, &secondNode->position);
|
vec3Sub(&firstNode->position, &secondNode->position, &p);
|
||||||
|
vec3CrossProduct(&zAxis, &p, &rotateAround);
|
||||||
|
vec3Normalize(&rotateAround);
|
||||||
|
|
||||||
|
distance = vec3Length(&p);
|
||||||
if (distance > 0) {
|
if (distance > 0) {
|
||||||
float offset = step;
|
float offset = step;
|
||||||
|
rotateAngle = 180 / M_PI * acos(vec3DotProduct(&zAxis, &p) / distance);
|
||||||
|
matrixRotate(&matRotate,
|
||||||
|
rotateAngle, rotateAround.x, rotateAround.y, rotateAround.z);
|
||||||
if (offset + step <= distance) {
|
if (offset + step <= distance) {
|
||||||
while (offset + step <= distance) {
|
while (offset + step <= distance) {
|
||||||
float frac = offset / distance;
|
float frac = offset / distance;
|
||||||
|
@ -166,14 +252,23 @@ static int bmeshGenerateInbetweenNodesBetween(bmesh *bm,
|
||||||
if (-1 == parentNodeIndex) {
|
if (-1 == parentNodeIndex) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
newNode = bmeshGetNode(bm, parentNodeIndex);
|
||||||
|
bmeshGenerateNodeQuad(bm, newNode, &matRotate,
|
||||||
|
lastQuadIndex);
|
||||||
|
lastQuadIndex = -1 == lastQuadIndex ? bmeshGetQuadNum(bm) - 1 :
|
||||||
|
bmeshGetQuadNum(bm) - 5;
|
||||||
offset += step;
|
offset += step;
|
||||||
}
|
}
|
||||||
} else if (distance > step) {
|
} else if (distance > step) {
|
||||||
parentNodeIndex = bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode, 0.5,
|
parentNodeIndex = bmeshAddInbetweenNodeBetween(bm, firstNode, secondNode,
|
||||||
parentNodeIndex);
|
0.5, parentNodeIndex);
|
||||||
if (-1 == parentNodeIndex) {
|
if (-1 == parentNodeIndex) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
newNode = bmeshGetNode(bm, parentNodeIndex);
|
||||||
|
bmeshGenerateNodeQuad(bm, newNode, &matRotate, lastQuadIndex);
|
||||||
|
lastQuadIndex = -1 == lastQuadIndex ? bmeshGetQuadNum(bm) - 1 :
|
||||||
|
bmeshGetQuadNum(bm) - 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (-1 == bmeshAddChildNodeRelation(bm, parentNodeIndex, secondNodeIndex)) {
|
if (-1 == bmeshAddChildNodeRelation(bm, parentNodeIndex, secondNodeIndex)) {
|
||||||
|
@ -256,3 +351,23 @@ int bmeshGenerateInbetweenNodes(bmesh *bm) {
|
||||||
bm->roundColor++;
|
bm->roundColor++;
|
||||||
return bmeshGenerateInbetweenNodesFrom(bm, bm->rootNodeIndex);
|
return bmeshGenerateInbetweenNodesFrom(bm, bm->rootNodeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bmeshGetQuadNum(bmesh *bm) {
|
||||||
|
return arrayGetLength(bm->quadArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
quad *bmeshGetQuad(bmesh *bm, int index) {
|
||||||
|
return (quad *)arrayGetItem(bm->quadArray, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmeshAddQuad(bmesh *bm, quad *q) {
|
||||||
|
int index = arrayGetLength(bm->quadArray);
|
||||||
|
if (0 != arraySetLength(bm->quadArray, index + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(arrayGetItem(bm->quadArray, index), q, sizeof(quad));
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef B_MESH_H
|
#ifndef B_MESH_H
|
||||||
#define B_MESH_H
|
#define B_MESH_H
|
||||||
#include "vector3d.h"
|
#include "vector3d.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -41,6 +42,9 @@ int bmeshAddEdge(bmesh *bm, bmeshEdge *edge);
|
||||||
int bmeshGenerateInbetweenNodes(bmesh *bm);
|
int bmeshGenerateInbetweenNodes(bmesh *bm);
|
||||||
int bmeshGetNodeNextChild(bmesh *bm, bmeshNode *node, int *childIndex);
|
int bmeshGetNodeNextChild(bmesh *bm, bmeshNode *node, int *childIndex);
|
||||||
bmeshNode *bmeshGetRootNode(bmesh *bm);
|
bmeshNode *bmeshGetRootNode(bmesh *bm);
|
||||||
|
int bmeshGetQuadNum(bmesh *bm);
|
||||||
|
quad *bmeshGetQuad(bmesh *bm, int index);
|
||||||
|
int bmeshAddQuad(bmesh *bm, quad *q);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ int drawCylinder(vec3 *topOrigin, vec3 *bottomOrigin, float radius, int slices,
|
||||||
|
|
||||||
vec3Sub(topOrigin, bottomOrigin, &p);
|
vec3Sub(topOrigin, bottomOrigin, &p);
|
||||||
vec3CrossProduct(&zAxis, &p, &t);
|
vec3CrossProduct(&zAxis, &p, &t);
|
||||||
|
vec3Normalize(&t);
|
||||||
height = vec3Length(&p);
|
height = vec3Length(&p);
|
||||||
if (height > 0) {
|
if (height > 0) {
|
||||||
angle = 180 / M_PI * acos(vec3DotProduct(&zAxis, &p) / height);
|
angle = 180 / M_PI * acos(vec3DotProduct(&zAxis, &p) / height);
|
||||||
|
|
|
@ -17,7 +17,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vec3 pt[4];
|
vec3 pt[4];
|
||||||
} quard;
|
} quad;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int npoly;
|
int npoly;
|
||||||
|
|
36
src/matrix.c
36
src/matrix.c
|
@ -21,6 +21,42 @@ matrix *matrixTranslate(matrix *mat, float x, float y, float z) {
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// matrixRotate modified from http://www.gamedev.net/topic/600537-instead-of-glrotatef-build-a-matrix/
|
||||||
|
//
|
||||||
|
|
||||||
|
matrix *matrixRotate(matrix *mat, float degree, float x, float y, float z) {
|
||||||
|
float c;
|
||||||
|
float s;
|
||||||
|
float length;
|
||||||
|
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
|
||||||
|
if (degree <= 0) {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = sqrt(x * x + y * y + z * z);
|
||||||
|
|
||||||
|
c = cos(degree * DEG2RAD);
|
||||||
|
s = sin(degree * DEG2RAD);
|
||||||
|
|
||||||
|
mat->data[0] = x * x * (1 - c) + c;
|
||||||
|
mat->data[4] = x * y * (1 - c) - z * s;
|
||||||
|
mat->data[8] = x * z * (1 - c) + y * s;
|
||||||
|
|
||||||
|
mat->data[1] = y * x * (1 - c) + z * s;
|
||||||
|
mat->data[5] = y * y * (1 - c) + c;
|
||||||
|
mat->data[9] = y * z * (1 - c) - x * s;
|
||||||
|
|
||||||
|
mat->data[2] = x * z * (1 - c) - y * s;
|
||||||
|
mat->data[6] = y * z * (1 - c) + x * s;
|
||||||
|
mat->data[10] = z * z * (1 - c) + c;
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
matrix *matrixRotateX(matrix *mat, float degree) {
|
matrix *matrixRotateX(matrix *mat, float degree) {
|
||||||
float c;
|
float c;
|
||||||
float s;
|
float s;
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#ifndef __MATRIX_H__
|
#ifndef __MATRIX_H__
|
||||||
#define __MATRIX_H__
|
#define __MATRIX_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
// Modified from http://wiki.unity3d.com/index.php?title=Matrix
|
// Modified from http://wiki.unity3d.com/index.php?title=Matrix
|
||||||
|
|
||||||
typedef struct matrix {
|
typedef struct matrix {
|
||||||
|
@ -12,8 +16,13 @@ matrix *matrixTranslate(matrix *mat, float x, float y, float z);
|
||||||
matrix *matrixRotateX(matrix *mat, float degree);
|
matrix *matrixRotateX(matrix *mat, float degree);
|
||||||
matrix *matrixRotateY(matrix *mat, float degree);
|
matrix *matrixRotateY(matrix *mat, float degree);
|
||||||
matrix *matrixRotateZ(matrix *mat, float degree);
|
matrix *matrixRotateZ(matrix *mat, float degree);
|
||||||
|
matrix *matrixRotate(matrix *mat, float degree, float x, float y, float z);
|
||||||
matrix *matrixScale(matrix *mat, float x, float y, float z);
|
matrix *matrixScale(matrix *mat, float x, float y, float z);
|
||||||
float *matrixTransformVector(matrix *mat, float *vec);
|
float *matrixTransformVector(matrix *mat, float *vec);
|
||||||
matrix *matrixAppend(matrix *mat, matrix *matB);
|
matrix *matrixAppend(matrix *mat, matrix *matB);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,6 @@ static int drawBmeshNode(bmesh *bm, bmeshNode *node) {
|
||||||
static void drawBmeshNodeRecursively(bmesh *bm, bmeshNode *node) {
|
static void drawBmeshNodeRecursively(bmesh *bm, bmeshNode *node) {
|
||||||
int childIndex = node->firstChildIndex;
|
int childIndex = node->firstChildIndex;
|
||||||
int childNodeIndex;
|
int childNodeIndex;
|
||||||
|
|
||||||
drawBmeshNode(bm, node);
|
drawBmeshNode(bm, node);
|
||||||
while (-1 != childIndex) {
|
while (-1 != childIndex) {
|
||||||
childNodeIndex = bmeshGetNodeNextChild(bm, node, &childIndex);
|
childNodeIndex = bmeshGetNodeNextChild(bm, node, &childIndex);
|
||||||
|
@ -37,6 +36,62 @@ static void drawBmeshNodeRecursively(bmesh *bm, bmeshNode *node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawBmeshNodeQuardRecursively(bmesh *bm, bmeshNode *node) {
|
||||||
|
int childIndex = node->firstChildIndex;
|
||||||
|
int childNodeIndex;
|
||||||
|
|
||||||
|
/*
|
||||||
|
matrix matTmp;
|
||||||
|
matrix matCalc;
|
||||||
|
float quad[4][3] = {
|
||||||
|
{-node->radius, +node->radius, 0},
|
||||||
|
{-node->radius, -node->radius, 0},
|
||||||
|
{+node->radius, -node->radius, 0},
|
||||||
|
{+node->radius, +node->radius, 0},
|
||||||
|
};
|
||||||
|
matrixLoadIdentity(&matCalc);
|
||||||
|
matrixAppend(&matCalc,
|
||||||
|
matrixTranslate(&matTmp, node->position.x, node->position.y,
|
||||||
|
node->position.z));
|
||||||
|
matrixAppend(&matCalc,
|
||||||
|
matrixRotate(&matTmp,
|
||||||
|
node->rotateAngle, node->rotateAround.x, node->rotateAround.y,
|
||||||
|
node->rotateAround.z));
|
||||||
|
matrixTransformVector(&matCalc, quad[0]);
|
||||||
|
matrixTransformVector(&matCalc, quad[1]);
|
||||||
|
matrixTransformVector(&matCalc, quad[2]);
|
||||||
|
matrixTransformVector(&matCalc, quad[3]);
|
||||||
|
|
||||||
|
glVertex3fv(quad[0]);
|
||||||
|
glVertex3fv(quad[1]);
|
||||||
|
glVertex3fv(quad[2]);
|
||||||
|
glVertex3fv(quad[3]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(node->position.x, node->position.y,
|
||||||
|
node->position.z);
|
||||||
|
glRotatef(node->rotateAngle, node->rotateAround.x, node->rotateAround.y,
|
||||||
|
node->rotateAround.z);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex3f(-node->radius, +node->radius, 0);
|
||||||
|
glVertex3f(-node->radius, -node->radius, 0);
|
||||||
|
glVertex3f(+node->radius, -node->radius, 0);
|
||||||
|
glVertex3f(+node->radius, +node->radius, 0);
|
||||||
|
glEnd();
|
||||||
|
glPopMatrix();
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (-1 != childIndex) {
|
||||||
|
childNodeIndex = bmeshGetNodeNextChild(bm, node, &childIndex);
|
||||||
|
if (-1 == childNodeIndex) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drawBmeshNodeQuardRecursively(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->firstNodeIndex);
|
bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNodeIndex);
|
||||||
|
@ -82,6 +137,8 @@ void Render::initializeGL() {
|
||||||
qglClearColor(QWidget::palette().color(QWidget::backgroundRole()));
|
qglClearColor(QWidget::palette().color(QWidget::backgroundRole()));
|
||||||
glClearStencil(0);
|
glClearStencil(0);
|
||||||
glClearDepth(1.0f);
|
glClearDepth(1.0f);
|
||||||
|
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
GLfloat ambientLight[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
GLfloat ambientLight[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
GLfloat diffuseLight[] = {0.9f, 0.9f, 0.9f, 1.0f};
|
GLfloat diffuseLight[] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||||
|
@ -156,6 +213,10 @@ void Render::paintGL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
drawBmeshNodeRecursively(bm, bmeshGetRootNode(bm));
|
drawBmeshNodeRecursively(bm, bmeshGetRootNode(bm));
|
||||||
|
|
||||||
|
//glBegin(GL_QUADS);
|
||||||
|
//drawBmeshNodeQuardRecursively(bm, bmeshGetRootNode(bm));
|
||||||
|
//glEnd();
|
||||||
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
@ -168,6 +229,30 @@ void Render::paintGL() {
|
||||||
bmeshEdge *edge = bmeshGetEdge(bm, index);
|
bmeshEdge *edge = bmeshGetEdge(bm, index);
|
||||||
drawBmeshEdge(bm, edge);
|
drawBmeshEdge(bm, edge);
|
||||||
}
|
}
|
||||||
|
glColor4f(1.0f, 1.0f, 1.0f, 0.5);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
for (index = 0; index < bmeshGetQuadNum(bm); ++index) {
|
||||||
|
quad *q = bmeshGetQuad(bm, index);
|
||||||
|
vec3 normal;
|
||||||
|
int j;
|
||||||
|
vec3Normal(&q->pt[0], &q->pt[1], &q->pt[2], &normal);
|
||||||
|
for (j = 0; j < 4; ++j) {
|
||||||
|
glNormal3f(normal.x, normal.y, normal.z);
|
||||||
|
glVertex3f(q->pt[j].x, q->pt[j].y, q->pt[j].z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
glColor3f(0.0f, 0.0f, 0.0f);
|
||||||
|
for (index = 0; index < bmeshGetQuadNum(bm); ++index) {
|
||||||
|
quad *q = bmeshGetQuad(bm, index);
|
||||||
|
int j;
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
for (j = 0; j < 4; ++j) {
|
||||||
|
glVertex3f(q->pt[j].x, q->pt[j].y, q->pt[j].z);
|
||||||
|
}
|
||||||
|
glVertex3f(q->pt[0].x, q->pt[0].y, q->pt[0].z);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -49,3 +49,25 @@ float vec3Distance(vec3 *a, vec3 *b) {
|
||||||
vec3Sub(a, b, &p);
|
vec3Sub(a, b, &p);
|
||||||
return vec3Length(&p);
|
return vec3Length(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vec3Normal(vec3 *a, vec3 *b, vec3 *c, vec3 *normal) {
|
||||||
|
float v1[3], v2[3], vr[3], val;
|
||||||
|
|
||||||
|
v1[0] = a->x - b->x;
|
||||||
|
v1[1] = a->y - b->y;
|
||||||
|
v1[2] = a->z - b->z;
|
||||||
|
|
||||||
|
v2[0] = a->x - c->x;
|
||||||
|
v2[1] = a->y - c->y;
|
||||||
|
v2[2] = a->z - c->z;
|
||||||
|
|
||||||
|
vr[0] = v1[1] * v2[2] - v2[1] * v1[2];
|
||||||
|
vr[1] = v2[0] * v1[2] - v1[0] * v2[2];
|
||||||
|
vr[2] = v1[0] * v2[1] - v2[0] * v1[1];
|
||||||
|
|
||||||
|
val = sqrt(vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2]);
|
||||||
|
|
||||||
|
normal->x = vr[0]/val;
|
||||||
|
normal->y = vr[1]/val;
|
||||||
|
normal->z = vr[2]/val;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ 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);
|
float vec3Distance(vec3 *a, vec3 *b);
|
||||||
|
void vec3Normal(vec3 *a, vec3 *b, vec3 *c, vec3 *normal);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue