Add Jon Leech's method to draw shpere
parent
d7b349b986
commit
a0ebc379b4
|
@ -0,0 +1,3 @@
|
||||||
|
.*
|
||||||
|
*.o
|
||||||
|
build/*
|
|
@ -8,7 +8,11 @@ INCLUDEPATH += ../src
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
mainwindow.cpp \
|
mainwindow.cpp \
|
||||||
glwidget.cpp
|
glwidget.cpp \
|
||||||
|
drawcommon.c \
|
||||||
|
drawsphere.c
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
glwidget.h
|
glwidget.h \
|
||||||
|
drawcommon.h \
|
||||||
|
drawsphere.h
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "drawcommon.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
void normalize(point *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 midpoint(point *a, point *b, point *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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef DRAW_COMMON_H
|
||||||
|
#define DRAW_COMMON_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} point;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
point pt[3];
|
||||||
|
} triangle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int npoly;
|
||||||
|
triangle *poly;
|
||||||
|
} object;
|
||||||
|
|
||||||
|
void normalize(point *p);
|
||||||
|
void midpoint(point *a, point *b, point *mid);
|
||||||
|
void drawTriangle(triangle *poly);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,106 @@
|
||||||
|
#include "drawcommon.h"
|
||||||
|
#include "drawsphere.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This 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];
|
||||||
|
point a, b, c;
|
||||||
|
|
||||||
|
midpoint(&oldt->pt[0], &oldt->pt[2], &a);
|
||||||
|
midpoint(&oldt->pt[0], &oldt->pt[1], &b);
|
||||||
|
midpoint(&oldt->pt[1], &oldt->pt[2], &c);
|
||||||
|
|
||||||
|
normalize(&a);
|
||||||
|
normalize(&b);
|
||||||
|
normalize(&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(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < newObj.npoly; ++i) {
|
||||||
|
drawTriangle(&newObj.poly[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(newObj.poly);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef DRAW_SPHERE_H
|
||||||
|
#define DRAW_SPHERE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int drawSphere(int level);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
107
src/glwidget.cpp
107
src/glwidget.cpp
|
@ -1,25 +1,35 @@
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
#include <QtOpenGL>
|
#include <QtOpenGL>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "glwidget.h"
|
#include "glwidget.h"
|
||||||
|
#include "drawcommon.h"
|
||||||
|
#include "drawsphere.h"
|
||||||
|
|
||||||
|
void drawTriangle(triangle *poly) {
|
||||||
|
int i;
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
for (i = 0; i < 3; ++i) {
|
||||||
|
point *pt = &poly->pt[i];
|
||||||
|
glNormal3f(pt->x, pt->y, pt->z);
|
||||||
|
glVertex3f(pt->x, pt->y, pt->z);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
GLWidget::GLWidget(QWidget *parent)
|
GLWidget::GLWidget(QWidget *parent)
|
||||||
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
|
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLWidget::~GLWidget()
|
GLWidget::~GLWidget() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::initializeGL()
|
void GLWidget::initializeGL() {
|
||||||
{
|
|
||||||
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
|
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
|
||||||
GLfloat mat_shininess[] = {50.0};
|
GLfloat mat_shininess[] = {50.0};
|
||||||
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
|
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
|
||||||
GLfloat light[] = {1.0, 0.2, 0.2};
|
GLfloat light[] = {1.0, 0.2, 0.2};
|
||||||
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
|
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
|
||||||
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
glShadeModel(GL_SMOOTH);
|
glShadeModel(GL_SMOOTH);
|
||||||
|
|
||||||
|
@ -36,86 +46,19 @@ void GLWidget::initializeGL()
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void normalize(float v[3])
|
void GLWidget::paintGL() {
|
||||||
{
|
|
||||||
GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
|
|
||||||
if (d == 0.0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
v[0] /= d; v[1] /= d; v[2] /= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawtriangle(float *v1, float *v2, float *v3)
|
|
||||||
{
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
glNormal3fv(v1); glVertex3fv(v1);
|
|
||||||
glNormal3fv(v2); glVertex3fv(v2);
|
|
||||||
glNormal3fv(v3); glVertex3fv(v3);
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void subdivide(float *v1, float *v2, float *v3)
|
|
||||||
{
|
|
||||||
GLfloat v12[3], v23[3], v31[3];
|
|
||||||
GLint i;
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
v12[i] = v1[i]+v2[i];
|
|
||||||
v23[i] = v2[i]+v3[i];
|
|
||||||
v31[i] = v3[i]+v1[i];
|
|
||||||
}
|
|
||||||
normalize(v12);
|
|
||||||
normalize(v23);
|
|
||||||
normalize(v31);
|
|
||||||
drawtriangle(v1, v12, v31);
|
|
||||||
drawtriangle(v2, v23, v12);
|
|
||||||
drawtriangle(v3, v31, v23);
|
|
||||||
drawtriangle(v12, v23, v31);
|
|
||||||
}
|
|
||||||
|
|
||||||
// An example come from http://www.glprogramming.com/red/chapter02.html#name8
|
|
||||||
|
|
||||||
#define X .525731112119133606
|
|
||||||
#define Z .850650808352039932
|
|
||||||
|
|
||||||
static GLfloat vdata[12][3] = {
|
|
||||||
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
|
|
||||||
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
|
|
||||||
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
|
|
||||||
};
|
|
||||||
static GLuint tindices[20][3] = {
|
|
||||||
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
|
|
||||||
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
|
|
||||||
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
|
|
||||||
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
|
|
||||||
};
|
|
||||||
|
|
||||||
void GLWidget::paintGL()
|
|
||||||
{
|
|
||||||
GLint i;
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
for (i = 0; i < 20; i++)
|
drawSphere(3);
|
||||||
{
|
|
||||||
subdivide(&vdata[tindices[i][0]][0],
|
|
||||||
&vdata[tindices[i][1]][0],
|
|
||||||
&vdata[tindices[i][2]][0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::resizeGL(int w, int h)
|
void GLWidget::resizeGL(int w, int h) {
|
||||||
{
|
|
||||||
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
|
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
if (w <= h)
|
if (w <= h) {
|
||||||
{
|
|
||||||
glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
|
glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
|
||||||
1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
|
1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
|
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
|
||||||
1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
|
1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
|
||||||
}
|
}
|
||||||
|
@ -123,10 +66,8 @@ void GLWidget::resizeGL(int w, int h)
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::mousePressEvent(QMouseEvent *event)
|
void GLWidget::mousePressEvent(QMouseEvent *event) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::mouseMoveEvent(QMouseEvent *event)
|
void GLWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
|
|
||||||
|
assert(0 != freopen((a.applicationDirPath() +
|
||||||
|
"/dust3d.log").toUtf8(), "w", stdout));
|
||||||
|
assert(0 != freopen((a.applicationDirPath() +
|
||||||
|
"/dust3d_error.log").toUtf8(), "w", stderr));
|
||||||
|
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
|
|
Loading…
Reference in New Issue