Add array data struct
Add bmesh define Add vec3 Add camera control Add draw x,z axismaster
parent
d7ef7d6d08
commit
a074a8d846
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
|
@ -0,0 +1,54 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
struct array {
|
||||||
|
int nodeSize;
|
||||||
|
int capacity;
|
||||||
|
int length;
|
||||||
|
char *nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
array *arrayCreate(int nodeSize) {
|
||||||
|
array *arr = (array *)calloc(1, sizeof(array));
|
||||||
|
if (!arr) {
|
||||||
|
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arr->nodeSize = nodeSize;
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arraySetLength(array *arr, int length) {
|
||||||
|
if (length > arr->capacity) {
|
||||||
|
int newCapacity = (arr->capacity + 1) * 2;
|
||||||
|
char *newNodes = (char *)realloc(arr->nodes, arr->nodeSize * newCapacity);
|
||||||
|
if (!newNodes) {
|
||||||
|
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
arr->capacity = newCapacity;
|
||||||
|
arr->nodes = newNodes;
|
||||||
|
}
|
||||||
|
arr->length = length;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *arrayGetItem(array *arr, int index) {
|
||||||
|
if (index >= arr->length) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return arr->nodes + arr->nodeSize * index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arrayGetLength(array *arr) {
|
||||||
|
return arr->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arrayDestroy(array *arr) {
|
||||||
|
if (arr) {
|
||||||
|
free(arr->nodes);
|
||||||
|
free(arr);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef ARRAY_H
|
||||||
|
#define ARRAY_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct array array;
|
||||||
|
|
||||||
|
array *arrayCreate(int nodeSize);
|
||||||
|
void *arrayGetItem(array *arr, int index);
|
||||||
|
int arrayGetLength(array *arr);
|
||||||
|
int arraySetLength(array *arr, int length);
|
||||||
|
void arrayDestroy(array *arr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "bmesh.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
struct bmesh {
|
||||||
|
array *nodeArray;
|
||||||
|
array *edgeArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
bmesh *bmeshCreate(void) {
|
||||||
|
bmesh *bm = (bmesh *)calloc(1, sizeof(bmesh));
|
||||||
|
if (!bm) {
|
||||||
|
fprintf(stderr, "%s:Insufficient memory.\n", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bm->nodeArray = arrayCreate(sizeof(bmeshNode));
|
||||||
|
if (!bm->nodeArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate bmeshNode failed.\n", __FUNCTION__);
|
||||||
|
bmeshDestroy(bm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bm->edgeArray = arrayCreate(sizeof(bmeshEdge));
|
||||||
|
if (!bm->edgeArray) {
|
||||||
|
fprintf(stderr, "%s:arrayCreate bmeshEdge failed.\n", __FUNCTION__);
|
||||||
|
bmeshDestroy(bm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bmeshDestroy(bmesh *bm) {
|
||||||
|
arrayDestroy(bm->nodeArray);
|
||||||
|
arrayDestroy(bm->edgeArray);
|
||||||
|
free(bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmeshGetNodeNum(bmesh *bm) {
|
||||||
|
return arrayGetLength(bm->nodeArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmeshGetEdgeNum(bmesh *bm) {
|
||||||
|
return arrayGetLength(bm->edgeArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
bmeshNode *bmeshGetNode(bmesh *bm, int index) {
|
||||||
|
return (bmeshNode *)arrayGetItem(bm->nodeArray, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bmeshEdge *bmeshGetEdge(bmesh *bm, int index) {
|
||||||
|
return (bmeshEdge *)arrayGetItem(bm->edgeArray, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmeshAddNode(bmesh *bm, bmeshNode *node) {
|
||||||
|
int index = arrayGetLength(bm->nodeArray);
|
||||||
|
node->index = index;
|
||||||
|
if (0 != arraySetLength(bm->nodeArray, index + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(arrayGetItem(bm->nodeArray, index), node, sizeof(bmeshNode));
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmeshAddEdge(bmesh *bm, bmeshEdge *edge) {
|
||||||
|
int index = arrayGetLength(bm->edgeArray);
|
||||||
|
edge->index = index;
|
||||||
|
if (0 != arraySetLength(bm->edgeArray, index + 1)) {
|
||||||
|
fprintf(stderr, "%s:arraySetLength failed.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(arrayGetItem(bm->edgeArray, index), edge, sizeof(bmeshEdge));
|
||||||
|
return index;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef B_MESH_H
|
||||||
|
#define B_MESH_H
|
||||||
|
#include "vector3d.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BMESH_NODE_FLAG_KEY = 0x00000001,
|
||||||
|
BMESH_NODE_FLAG_INBETWEEN = 0x00000002,
|
||||||
|
BMESH_NODE_FLAG_ROOT = 0x00000010,
|
||||||
|
} bmeshNodeFlag;
|
||||||
|
|
||||||
|
typedef struct bmesh bmesh;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int index;
|
||||||
|
vec3 position;
|
||||||
|
float radius;
|
||||||
|
unsigned int flag;
|
||||||
|
} bmeshNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int index;
|
||||||
|
int firstNode;
|
||||||
|
int secondNode;
|
||||||
|
} bmeshEdge;
|
||||||
|
|
||||||
|
bmesh *bmeshCreate(void);
|
||||||
|
void bmeshDestroy(bmesh *bm);
|
||||||
|
int bmeshGetNodeNum(bmesh *bm);
|
||||||
|
int bmeshGetEdgeNum(bmesh *bm);
|
||||||
|
bmeshNode *bmeshGetNode(bmesh *bm, int index);
|
||||||
|
bmeshEdge *bmeshGetEdge(bmesh *bm, int index);
|
||||||
|
int bmeshAddNode(bmesh *bm, bmeshNode *node);
|
||||||
|
int bmeshAddEdge(bmesh *bm, bmeshEdge *edge);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,223 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtOpenGL>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This drawSphere function modified from [Jon Leech's implementation of sphere](ftp://ftp.ee.lbl.gov/sphere.c)
|
||||||
|
* Jeremy HU (huxingyi@msn.com) 2016/12/16
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XPLUS { 1, 0, 0 } /* X */
|
||||||
|
#define XMIN { -1, 0, 0 } /* -X */
|
||||||
|
#define YPLUS { 0, 1, 0 } /* Y */
|
||||||
|
#define YMIN { 0, -1, 0 } /* -Y */
|
||||||
|
#define ZPLUS { 0, 0, 1 } /* Z */
|
||||||
|
#define ZMIN { 0, 0, -1 } /* -Z */
|
||||||
|
|
||||||
|
static const triangle octahedron[] = {
|
||||||
|
{{XPLUS, ZPLUS, YPLUS}},
|
||||||
|
{{YPLUS, ZPLUS, XMIN}},
|
||||||
|
{{XMIN, ZPLUS, YMIN}},
|
||||||
|
{{YMIN, ZPLUS, XPLUS}},
|
||||||
|
{{XPLUS, YPLUS, ZMIN}},
|
||||||
|
{{YPLUS, XMIN, ZMIN}},
|
||||||
|
{{XMIN, YMIN, ZMIN}},
|
||||||
|
{{YMIN, XPLUS, ZMIN}},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void subdivide(object *old, object *subdivided) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < old->npoly; ++i) {
|
||||||
|
triangle *oldt = &old->poly[i];
|
||||||
|
triangle *newt = &subdivided->poly[i * 4];
|
||||||
|
vec3 a, b, c;
|
||||||
|
|
||||||
|
vec3Midpoint(&oldt->pt[0], &oldt->pt[2], &a);
|
||||||
|
vec3Midpoint(&oldt->pt[0], &oldt->pt[1], &b);
|
||||||
|
vec3Midpoint(&oldt->pt[1], &oldt->pt[2], &c);
|
||||||
|
|
||||||
|
vec3Normalize(&a);
|
||||||
|
vec3Normalize(&b);
|
||||||
|
vec3Normalize(&c);
|
||||||
|
|
||||||
|
newt->pt[0] = oldt->pt[0];
|
||||||
|
newt->pt[1] = b;
|
||||||
|
newt->pt[2] = a;
|
||||||
|
newt++;
|
||||||
|
|
||||||
|
newt->pt[0] = b;
|
||||||
|
newt->pt[1] = oldt->pt[1];
|
||||||
|
newt->pt[2] = c;
|
||||||
|
newt++;
|
||||||
|
|
||||||
|
newt->pt[0] = a;
|
||||||
|
newt->pt[1] = b;
|
||||||
|
newt->pt[2] = c;
|
||||||
|
newt++;
|
||||||
|
|
||||||
|
newt->pt[0] = a;
|
||||||
|
newt->pt[1] = c;
|
||||||
|
newt->pt[2] = oldt->pt[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawSphere(vec3 *origin, float radius, int level) {
|
||||||
|
int lv, i;
|
||||||
|
object oldObj, newObj;
|
||||||
|
|
||||||
|
if (level < 1) {
|
||||||
|
fprintf(stderr, "%s:level max greater than 0.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldObj.npoly = sizeof(octahedron) / sizeof(octahedron[0]);
|
||||||
|
oldObj.poly = (triangle *)malloc(oldObj.npoly * sizeof(triangle));
|
||||||
|
if (!oldObj.poly) {
|
||||||
|
fprintf(stderr, "%s:insufficient memory.\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(oldObj.poly, octahedron, oldObj.npoly * sizeof(triangle));
|
||||||
|
|
||||||
|
for (lv = 0; lv < level; lv++) {
|
||||||
|
newObj.npoly = oldObj.npoly * 4;
|
||||||
|
newObj.poly = (triangle *)malloc(newObj.npoly * sizeof(triangle));
|
||||||
|
if (!newObj.poly) {
|
||||||
|
fprintf(stderr, "%s:insufficient memory(levelLoop:%d).\n",
|
||||||
|
__FUNCTION__, lv);
|
||||||
|
free(oldObj.poly);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
subdivide(&oldObj, &newObj);
|
||||||
|
|
||||||
|
free(oldObj.poly);
|
||||||
|
oldObj = newObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(origin->x, origin->y, origin->z);
|
||||||
|
glScalef(radius, radius, radius);
|
||||||
|
for (i = 0; i < newObj.npoly; ++i) {
|
||||||
|
drawTriangle(&newObj.poly[i]);
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
free(newObj.poly);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTriangle(triangle *poly) {
|
||||||
|
int i;
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
for (i = 0; i < 3; ++i) {
|
||||||
|
vec3 *pt = &poly->pt[i];
|
||||||
|
glNormal3f(pt->x, pt->y, pt->z);
|
||||||
|
glVertex3f(pt->x, pt->y, pt->z);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawCylinder(vec3 *topOrigin, vec3 *bottomOrigin, float radius, int slices) {
|
||||||
|
float theta = (2.0 * M_PI) / (float)slices;
|
||||||
|
float a = 0.0f;
|
||||||
|
int lv;
|
||||||
|
float x, y, z;
|
||||||
|
vec3 zAxis = {0, 0, 1};
|
||||||
|
vec3 p, t;
|
||||||
|
float height = 0;
|
||||||
|
float angle = 0;
|
||||||
|
|
||||||
|
if (slices <= 0) {
|
||||||
|
fprintf(stderr, "%s:Invalid parameter(slices:%d).\n", __FUNCTION__, slices);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3Sub(topOrigin, bottomOrigin, &p);
|
||||||
|
vec3CrossProduct(&zAxis, &p, &t);
|
||||||
|
height = vec3Length(&p);
|
||||||
|
if (height > 0) {
|
||||||
|
angle = 180 / M_PI * acos(vec3DotProduct(&zAxis, &p) / height);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glTranslatef(bottomOrigin->x, bottomOrigin->y,
|
||||||
|
bottomOrigin->z);
|
||||||
|
glRotatef(angle, t.x, t.y, t.z);
|
||||||
|
|
||||||
|
// strips
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
for (a = 0, lv = 0; lv <= slices; ++lv) {
|
||||||
|
float cosa = cos(a);
|
||||||
|
float sina = sin(a);
|
||||||
|
x = cosa * radius;
|
||||||
|
y = sina * radius;
|
||||||
|
z = 0;
|
||||||
|
glNormal3f(cosa, sina, 0);
|
||||||
|
glVertex3f(x, y, z);
|
||||||
|
z = height;
|
||||||
|
glNormal3f(cosa, sina, 0);
|
||||||
|
glVertex3f(x, y, z);
|
||||||
|
a += theta;
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// bottom cap
|
||||||
|
z = 0;
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
glNormal3f(0, 0, -1);
|
||||||
|
glVertex3f(0, 0, z);
|
||||||
|
for (a = 0, lv = 0; lv <= slices; ++lv) {
|
||||||
|
x = cos(a) * radius;
|
||||||
|
y = sin(a) * radius;
|
||||||
|
glNormal3f(0, 0, -1);
|
||||||
|
glVertex3f(x, y, z);
|
||||||
|
a += theta;
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
// top cap
|
||||||
|
z = height;
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
glNormal3f(0, 0, 1);
|
||||||
|
glVertex3f(0, 0, z);
|
||||||
|
for (a = 0, lv = 0; lv <= slices; ++lv) {
|
||||||
|
x = cos(a) * radius;
|
||||||
|
y = sin(a) * radius;
|
||||||
|
glNormal3f(0, 0, 1);
|
||||||
|
glVertex3f(x, y, z);
|
||||||
|
a += theta;
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawGrid(float size, float step) {
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
// x z plane
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
for (GLfloat i = -size; i <= size; i += step) {
|
||||||
|
if (0 == i) {
|
||||||
|
glColor3f(0.0, 0.0, 1.0);
|
||||||
|
glVertex3f(i, 0, size); glVertex3f(i, 0, -size);
|
||||||
|
glColor3f(1.0, 0.0, 0.0);
|
||||||
|
glVertex3f(size, 0, i); glVertex3f(-size, 0, i);
|
||||||
|
} else {
|
||||||
|
glColor3f(0.39, 0.39, 0.39);
|
||||||
|
glVertex3f(i, 0, size); glVertex3f(i, 0, -size);
|
||||||
|
glVertex3f(size, 0, i); glVertex3f(-size, 0, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef DRAW_SPHERE_H
|
||||||
|
#define DRAW_SPHERE_H
|
||||||
|
#include "vector3d.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3 pt[3];
|
||||||
|
} triangle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int npoly;
|
||||||
|
triangle *poly;
|
||||||
|
} object;
|
||||||
|
|
||||||
|
int drawSphere(vec3 *origin, float radius, int level);
|
||||||
|
void drawTriangle(triangle *poly);
|
||||||
|
int drawCylinder(vec3 *topOrigin, vec3 *bottomOrigin, float radius, int slices);
|
||||||
|
int drawGrid(float size, float step);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,18 +1,13 @@
|
||||||
#ifndef DRAW_COMMON_H
|
#ifndef DRAW_COMMON_H
|
||||||
#define DRAW_COMMON_H
|
#define DRAW_COMMON_H
|
||||||
|
#include "vector3d.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
vec3 pt[3];
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
} point;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
point pt[3];
|
|
||||||
} triangle;
|
} triangle;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -20,8 +15,6 @@ typedef struct {
|
||||||
triangle *poly;
|
triangle *poly;
|
||||||
} object;
|
} object;
|
||||||
|
|
||||||
void normalize(point *p);
|
|
||||||
void midpoint(point *a, point *b, point *mid);
|
|
||||||
void drawTriangle(triangle *poly);
|
void drawTriangle(triangle *poly);
|
||||||
int drawCylinder(int slices, float radius, float height);
|
int drawCylinder(int slices, float radius, float height);
|
||||||
|
|
||||||
|
|
|
@ -2,29 +2,21 @@
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(void)
|
MainWindow::MainWindow(void) {
|
||||||
{
|
render = new Render;
|
||||||
glWidget = new GLWidget;
|
|
||||||
|
|
||||||
resize(QDesktopWidget().availableGeometry(this).size() * 0.7);
|
resize(QDesktopWidget().availableGeometry(this).size() * 0.7);
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
mainLayout->addWidget(glWidget);
|
mainLayout->addWidget(render);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
setWindowTitle(tr("Dust3D Experiment"));
|
||||||
setWindowTitle(tr("DUST3D"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::keyPressEvent(QKeyEvent *e)
|
void MainWindow::keyPressEvent(QKeyEvent *e) {
|
||||||
{
|
if (e->key() == Qt::Key_Escape) {
|
||||||
if (e->key() == Qt::Key_Escape)
|
|
||||||
{
|
|
||||||
close();
|
close();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QWidget::keyPressEvent(e);
|
QWidget::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#define MAINWINDOW_H
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "glwidget.h"
|
|
||||||
|
|
||||||
class MainWindow : public QWidget
|
class Render;
|
||||||
{
|
|
||||||
|
class MainWindow : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -15,7 +15,7 @@ protected:
|
||||||
void keyPressEvent(QKeyEvent *event);
|
void keyPressEvent(QKeyEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLWidget *glWidget;
|
Render *render;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
#include "matrix.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define DEG2RAD (M_PI / 180.0)
|
||||||
|
|
||||||
|
matrix *matrixLoadIdentity(matrix *mat) {
|
||||||
|
memset(mat->data, 0, sizeof(mat->data));
|
||||||
|
mat->data[0] = 1;
|
||||||
|
mat->data[5] = 1;
|
||||||
|
mat->data[10] = 1;
|
||||||
|
mat->data[15] = 1;
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixTranslate(matrix *mat, float x, float y, float z) {
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
mat->data[12] = x;
|
||||||
|
mat->data[13] = y;
|
||||||
|
mat->data[14] = z;
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixRotateX(matrix *mat, float degree) {
|
||||||
|
float c;
|
||||||
|
float s;
|
||||||
|
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
|
||||||
|
if (degree <= 0) {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = cos(degree * DEG2RAD);
|
||||||
|
s = sin(degree * DEG2RAD);
|
||||||
|
|
||||||
|
mat->data[5] = c;
|
||||||
|
mat->data[6] = s;
|
||||||
|
mat->data[9] = -s;
|
||||||
|
mat->data[10] = c;
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixRotateY(matrix *mat, float degree) {
|
||||||
|
float c;
|
||||||
|
float s;
|
||||||
|
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
|
||||||
|
if (degree <= 0) {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = cos(degree * DEG2RAD);
|
||||||
|
s = sin(degree * DEG2RAD);
|
||||||
|
|
||||||
|
mat->data[0] = c;
|
||||||
|
mat->data[2] = -s;
|
||||||
|
mat->data[8] = s;
|
||||||
|
mat->data[10] = c;
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixRotateZ(matrix *mat, float degree) {
|
||||||
|
float c;
|
||||||
|
float s;
|
||||||
|
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
|
||||||
|
if (degree <= 0) {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = cos(degree * DEG2RAD);
|
||||||
|
s = sin(degree * DEG2RAD);
|
||||||
|
|
||||||
|
mat->data[0] = c;
|
||||||
|
mat->data[1] = s;
|
||||||
|
mat->data[4] = -s;
|
||||||
|
mat->data[5] = c;
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixScale(matrix *mat, float x, float y, float z) {
|
||||||
|
matrixLoadIdentity(mat);
|
||||||
|
mat->data[0] = x;
|
||||||
|
mat->data[5] = y;
|
||||||
|
mat->data[10] = z;
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *matrixTransformVector(matrix *mat, float *vec) {
|
||||||
|
float x = (vec[0] * mat->data[0]) +
|
||||||
|
(vec[1] * mat->data[4]) + (vec[2] * mat->data[8]) + mat->data[12];
|
||||||
|
float y = (vec[0] * mat->data[1]) +
|
||||||
|
(vec[1] * mat->data[5]) + (vec[2] * mat->data[9]) + mat->data[13];
|
||||||
|
float z = (vec[0] * mat->data[2]) +
|
||||||
|
(vec[1] * mat->data[6]) + (vec[2] * mat->data[10]) + mat->data[14];
|
||||||
|
vec[0] = x;
|
||||||
|
vec[1] = y;
|
||||||
|
vec[2] = z;
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix *matrixAppend(matrix *mat, matrix *matB) {
|
||||||
|
matrix structMatA;
|
||||||
|
matrix *matA = &structMatA;
|
||||||
|
|
||||||
|
memcpy(matA, mat, sizeof(matrix));
|
||||||
|
|
||||||
|
mat->data[0] = matA->data[0] * matB->data[0] +
|
||||||
|
matA->data[4] * matB->data[1] +
|
||||||
|
matA->data[8] * matB->data[2] +
|
||||||
|
matA->data[12] * matB->data[3];
|
||||||
|
mat->data[4] = matA->data[0] * matB->data[4] +
|
||||||
|
matA->data[4] * matB->data[5] +
|
||||||
|
matA->data[8] * matB->data[6] +
|
||||||
|
matA->data[12] * matB->data[7];
|
||||||
|
mat->data[8] = matA->data[0] * matB->data[8] +
|
||||||
|
matA->data[4] * matB->data[9] +
|
||||||
|
matA->data[8] * matB->data[10] +
|
||||||
|
matA->data[12] * matB->data[11];
|
||||||
|
mat->data[12] = matA->data[0] * matB->data[12] +
|
||||||
|
matA->data[4] * matB->data[13] +
|
||||||
|
matA->data[8] * matB->data[14] +
|
||||||
|
matA->data[12] * matB->data[15];
|
||||||
|
|
||||||
|
mat->data[1] = matA->data[1] * matB->data[0] +
|
||||||
|
matA->data[5] * matB->data[1] +
|
||||||
|
matA->data[9] * matB->data[2] +
|
||||||
|
matA->data[13] * matB->data[3];
|
||||||
|
mat->data[5] = matA->data[1] * matB->data[4] +
|
||||||
|
matA->data[5] * matB->data[5] +
|
||||||
|
matA->data[9] * matB->data[6] +
|
||||||
|
matA->data[13] * matB->data[7];
|
||||||
|
mat->data[9] = matA->data[1] * matB->data[8] +
|
||||||
|
matA->data[5] * matB->data[9] +
|
||||||
|
matA->data[9] * matB->data[10] +
|
||||||
|
matA->data[13] * matB->data[11];
|
||||||
|
mat->data[13] = matA->data[1] * matB->data[12] +
|
||||||
|
matA->data[5] * matB->data[13] +
|
||||||
|
matA->data[9] * matB->data[14] +
|
||||||
|
matA->data[13] * matB->data[15];
|
||||||
|
|
||||||
|
mat->data[2] = matA->data[2] * matB->data[0] +
|
||||||
|
matA->data[6] * matB->data[1] +
|
||||||
|
matA->data[10] * matB->data[2] +
|
||||||
|
matA->data[14] * matB->data[3];
|
||||||
|
mat->data[6] = matA->data[2] * matB->data[4] +
|
||||||
|
matA->data[6] * matB->data[5] +
|
||||||
|
matA->data[10] * matB->data[6] +
|
||||||
|
matA->data[14] * matB->data[7];
|
||||||
|
mat->data[10] = matA->data[2] * matB->data[8] +
|
||||||
|
matA->data[6] * matB->data[9] +
|
||||||
|
matA->data[10] * matB->data[10] +
|
||||||
|
matA->data[14] * matB->data[11];
|
||||||
|
mat->data[14] = matA->data[2] * matB->data[12] +
|
||||||
|
matA->data[6] * matB->data[13] +
|
||||||
|
matA->data[10] * matB->data[14] +
|
||||||
|
matA->data[14] * matB->data[15];
|
||||||
|
|
||||||
|
mat->data[3] = matA->data[3] * matB->data[0] +
|
||||||
|
matA->data[7] * matB->data[1] +
|
||||||
|
matA->data[11] * matB->data[2] +
|
||||||
|
matA->data[15] * matB->data[3];
|
||||||
|
mat->data[7] = matA->data[3] * matB->data[4] +
|
||||||
|
matA->data[7] * matB->data[5] +
|
||||||
|
matA->data[11] * matB->data[6] +
|
||||||
|
matA->data[15] * matB->data[7];
|
||||||
|
mat->data[11] = matA->data[3] * matB->data[8] +
|
||||||
|
matA->data[7] * matB->data[9] +
|
||||||
|
matA->data[11] * matB->data[10] +
|
||||||
|
matA->data[15] * matB->data[11];
|
||||||
|
mat->data[15] = matA->data[3] * matB->data[12] +
|
||||||
|
matA->data[7] * matB->data[13] +
|
||||||
|
matA->data[11] * matB->data[14] +
|
||||||
|
matA->data[15] * matB->data[15];
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef __MATRIX_H__
|
||||||
|
#define __MATRIX_H__
|
||||||
|
|
||||||
|
// Modified from http://wiki.unity3d.com/index.php?title=Matrix
|
||||||
|
|
||||||
|
typedef struct matrix {
|
||||||
|
float data[16];
|
||||||
|
} matrix;
|
||||||
|
|
||||||
|
matrix *matrixLoadIdentity(matrix *mat);
|
||||||
|
matrix *matrixTranslate(matrix *mat, float x, float y, float z);
|
||||||
|
matrix *matrixRotateX(matrix *mat, float degree);
|
||||||
|
matrix *matrixRotateY(matrix *mat, float degree);
|
||||||
|
matrix *matrixRotateZ(matrix *mat, float degree);
|
||||||
|
matrix *matrixScale(matrix *mat, float x, float y, float z);
|
||||||
|
float *matrixTransformVector(matrix *mat, float *vec);
|
||||||
|
matrix *matrixAppend(matrix *mat, matrix *matB);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QtOpenGL>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "render.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "bmesh.h"
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
static int drawBmeshNode(bmesh *bm, bmeshNode *node) {
|
||||||
|
float color1[3] = {1, 0, 0};
|
||||||
|
glColor3fv(color1);
|
||||||
|
drawSphere(&node->position, node->radius, 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drawBmeshEdge(bmesh *bm, bmeshEdge *edge) {
|
||||||
|
float color2[3] = {0, 0, 1};
|
||||||
|
glColor3fv(color2);
|
||||||
|
bmeshNode *firstNode = bmeshGetNode(bm, edge->firstNode);
|
||||||
|
bmeshNode *secondNode = bmeshGetNode(bm, edge->secondNode);
|
||||||
|
drawCylinder(&firstNode->position, &secondNode->position, 0.04, 40);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Render::Render(QWidget *parent)
|
||||||
|
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent) {
|
||||||
|
QTimer *timer = new QTimer(this);
|
||||||
|
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
|
||||||
|
timer->start(100);
|
||||||
|
|
||||||
|
mouseX = 0;
|
||||||
|
mouseY = 0;
|
||||||
|
cameraAngleX = 50;
|
||||||
|
cameraAngleY = 70;
|
||||||
|
cameraDistance = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Render::~Render(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::initializeGL() {
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
qglClearColor(QWidget::palette().color(QWidget::backgroundRole()));
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
|
||||||
|
GLfloat ambientLight[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
GLfloat diffuseLight[] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||||
|
GLfloat specularLight[] = {1, 1, 1, 1};
|
||||||
|
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
|
||||||
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
|
||||||
|
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
|
||||||
|
|
||||||
|
float lightDirection[4] = {0, 0, 1, 0};
|
||||||
|
glLightfv(GL_LIGHT0, GL_POSITION, lightDirection);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
|
||||||
|
float shininess = 64.0f;
|
||||||
|
float specularColor[] = {1.0, 1.0f, 1.0f, 1.0f};
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); // range 0 ~ 128
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
|
||||||
|
|
||||||
|
glClearStencil(0);
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||||
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::paintGL() {
|
||||||
|
static bmesh *bm = 0;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glTranslatef(0, 0, -cameraDistance);
|
||||||
|
glRotatef(cameraAngleX, 1, 0, 0);
|
||||||
|
glRotatef(cameraAngleY, 0, 1, 0);
|
||||||
|
|
||||||
|
drawGrid(10, 1);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
if (0 == bm) {
|
||||||
|
bmeshNode node;
|
||||||
|
bmeshEdge edge;
|
||||||
|
bm = bmeshCreate();
|
||||||
|
|
||||||
|
memset(&node, 0, sizeof(node));
|
||||||
|
node.position.x = -1.0;
|
||||||
|
node.position.y = 0.3;
|
||||||
|
node.position.z = 1.0;
|
||||||
|
node.radius = 0.45;
|
||||||
|
bmeshAddNode(bm, &node);
|
||||||
|
|
||||||
|
memset(&node, 0, sizeof(node));
|
||||||
|
node.position.x = -0.5;
|
||||||
|
node.position.y = 0.2;
|
||||||
|
node.position.z = 0.5;
|
||||||
|
node.radius = 0.1;
|
||||||
|
bmeshAddNode(bm, &node);
|
||||||
|
|
||||||
|
memset(&edge, 0, sizeof(edge));
|
||||||
|
edge.firstNode = 1;
|
||||||
|
edge.secondNode = 0;
|
||||||
|
bmeshAddEdge(bm, &edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < bmeshGetNodeNum(bm); ++index) {
|
||||||
|
bmeshNode *node = bmeshGetNode(bm, index);
|
||||||
|
drawBmeshNode(bm, node);
|
||||||
|
}
|
||||||
|
for (index = 0; index < bmeshGetEdgeNum(bm); ++index) {
|
||||||
|
bmeshEdge *edge = bmeshGetEdge(bm, index);
|
||||||
|
drawBmeshEdge(bm, edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::resizeGL(int w, int h) {
|
||||||
|
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glFrustum(-2, 2, -1.5, 1.5, 1, 1000);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::mousePressEvent(QMouseEvent *event) {
|
||||||
|
mouseX = event->x();
|
||||||
|
mouseY = event->y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::mouseMoveEvent(QMouseEvent *event) {
|
||||||
|
cameraAngleY += (event->x() - mouseX);
|
||||||
|
cameraAngleX += (event->y() - mouseY);
|
||||||
|
update();
|
||||||
|
mouseX = event->x();
|
||||||
|
mouseY = event->y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::wheelEvent(QWheelEvent * event) {
|
||||||
|
cameraDistance -= event->delta() * 0.01f;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef RENDER_H
|
||||||
|
#define RENDER_H
|
||||||
|
|
||||||
|
#include <QGLWidget>
|
||||||
|
|
||||||
|
class Render : public QGLWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Render(QWidget *parent = 0);
|
||||||
|
~Render(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initializeGL(void);
|
||||||
|
void paintGL(void);
|
||||||
|
void resizeGL(int width, int height);
|
||||||
|
void mousePressEvent(QMouseEvent *event);
|
||||||
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
void wheelEvent(QWheelEvent * event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mouseX;
|
||||||
|
int mouseY;
|
||||||
|
float cameraAngleX;
|
||||||
|
float cameraAngleY;
|
||||||
|
float cameraDistance;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "vector3d.h"
|
||||||
|
|
||||||
|
float vec3Length(vec3 *p) {
|
||||||
|
double mag;
|
||||||
|
mag = p->x * p->x + p->y * p->y + p->z * p->z;
|
||||||
|
return sqrt(mag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec3Normalize(vec3 *p) {
|
||||||
|
double mag;
|
||||||
|
mag = p->x * p->x + p->y * p->y + p->z * p->z;
|
||||||
|
if (mag != 0.0) {
|
||||||
|
mag = 1.0 / sqrt(mag);
|
||||||
|
p->x *= mag;
|
||||||
|
p->y *= mag;
|
||||||
|
p->z *= mag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec3Sub(vec3 *a, vec3 *b, vec3 *result) {
|
||||||
|
result->x = a->x - b->x;
|
||||||
|
result->y = a->y - b->y;
|
||||||
|
result->z = a->z - b->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec3CrossProduct(vec3 *a, vec3 *b, vec3 *result) {
|
||||||
|
result->x = a->y * b->z - a->z * b->y;
|
||||||
|
result->y = a->z * b->x - a->x * b->z;
|
||||||
|
result->z = a->x * b->y - a->y * b->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float vec3DotProduct(vec3 *a, vec3 *b) {
|
||||||
|
return a->x * b->x + a->y * b->y + a->z * b->z;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef VECTOR_3D_H
|
||||||
|
#define VECTOR_3D_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} vec3;
|
||||||
|
|
||||||
|
void vec3Normalize(vec3 *p);
|
||||||
|
void vec3Midpoint(vec3 *a, vec3 *b, vec3 *mid);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue