Fix ball selection.

master
Jeremy Hu 2017-01-18 22:14:28 +09:30
parent feac7aea69
commit e4fc03e848
3 changed files with 104 additions and 30 deletions

View File

@ -65,13 +65,15 @@ I follow the B-Mesh paper, made another test module inside Blender, and created
<img src="screenshot/dust3d_subdivide_catmull_clark.png" width="124" height="128"> <img src="screenshot/dust3d_bmesh_subdivide_2.png" width="124" height="128"> <img src="screenshot/dust3d_subdivide_catmull_clark.png" width="124" height="128"> <img src="screenshot/dust3d_bmesh_subdivide_2.png" width="124" height="128">
There is a implementation of Catmull-Clark Subdivision algorithm on [rosettacode](https://rosettacode.org/wiki/Catmull%E2%80%93Clark_subdivision_surface/C), the code is very simple and beautiful, just lack of some memory alloc fail check. I translated the algorithm to use my own array implementation. There is a implementation of Catmull-Clark Subdivision algorithm on [rosettacode](https://rosettacode.org/wiki/Catmull%E2%80%93Clark_subdivision_surface/C), the code is very simple and beautiful, just lack of some memory alloc fail check. I translated the algorithm to use my own array implementation.
Now, the render result looks not bad after 2 times of subdivisions. I would like to mark this todo as done, though there are more polish steps on the original paper, I just leave it as to be done in the future. Now, the render result looks not bad after 2 times of subdivisions. I would like to mark this todo as done, though there are more polish steps on the original paper, I just leave it as to be done in the future.
- [ ] Export Wavefront .obj
- [x] Render B-Mesh result - [x] Render B-Mesh result
This todo already done in the B-Mesh algorithm implementation. This todo already done in the B-Mesh algorithm implementation.
- [ ] Design UI for monster parts configuration - [ ] Design UI for monster parts configuration (Jan 17, 2017 ~ Jan 18, 2017)
- [ ] Test B-Mesh realtime generation with UI *Skeleton Editor*
There is good tutorial introduced how to implement object selection by mouse in OpenGL, written by [Bartek](http://www.bfilipek.com/2012/06/select-mouse-opengl.html).
But there is a big pain in the progress of implement the object selection logic, because of resizeGL, the width and height which passed in as parameters of this function is not equal to the size of the window.
- [ ] Render rigid animation - [ ] Render rigid animation
- [ ] png exporter for isometric 2.5D game - [ ] png exporter for isometric 2.5D game
- [ ] Version 0.01 release - [ ] Export Wavefront .obj
- [ ] Materials merge of different parts - [ ] Materials merge of different parts
- [ ] Version 0.01 release
- [ ] Implement [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf) - [ ] Implement [the Skeleton of a Closed 3D Shape](http://www1.idc.ac.il/icgf/GraphicsSeminar2006/DCGskeleton06.pdf)

View File

@ -28,20 +28,42 @@ int drawDebugPrintf(const char *fmt, ...) {
va_start(args, fmt); va_start(args, fmt);
vsnprintf(text, sizeof(text), fmt, args); vsnprintf(text, sizeof(text), fmt, args);
debugOutputTop += 9; debugOutputTop += 9;
if (debugOutputTop > 200) { if (debugOutputTop > 400) {
debugOutputTop = 0; debugOutputTop = 0;
} }
glColor3f(0, 0, 0);
return drawText(x, y, text); return drawText(x, y, text);
} }
static int drawBmeshBall(bmesh *bm, bmeshBall *ball) { static int drawBmeshBall(bmesh *bm, bmeshBall *ball) {
float color[4]; float color[4];
memcpy(color, bmeshBallColors[ball->type], sizeof(color)); memcpy(color, bmeshBallColors[ball->type], sizeof(color));
vec3 mousePos[] = {{_this->mouseWorldX, _this->mouseWorldY, if (BMESH_BALL_TYPE_ROOT == ball->type || BMESH_BALL_TYPE_KEY == ball->type) {
_this->mouseWorldZ}}; vec3 a = {_this->mouseWorldNearX, _this->mouseWorldNearY,
if (vec3Distance(&ball->position, mousePos) <= ball->radius * 5) { _this->mouseWorldNearZ};
vec3 b = {_this->mouseWorldFarX, _this->mouseWorldFarY,
_this->mouseWorldFarZ};
vec3 ab, ap, q;
float abDotAb;
float apDotAb;
float t;
vec3Sub(&b, &a, &ab);
vec3Sub(&ball->position, &a, &ap);
abDotAb = vec3DotProduct(&ab, &ab);
apDotAb = vec3DotProduct(&ap, &ab);
t = apDotAb / abDotAb;
if (t < 0.0f) {
t = 0.0f;
} else if (t > 1.0f) {
t = 1.0f;
}
vec3Scale(&ab, t, &q);
vec3Add(&a, &q, &q);
//drawDebugPrintf("q: %f,%f,%f t:%f", q.x, q.y, q.z, t);
if (vec3Distance(&ball->position, &q) <= ball->radius) {
color[3] = 1; color[3] = 1;
} }
}
glColor4fv(color); glColor4fv(color);
drawSphere(&ball->position, ball->radius, 36, 24); drawSphere(&ball->position, ball->radius, 36, 24);
return 0; return 0;
@ -176,6 +198,12 @@ Render::Render(QWidget *parent)
cameraAngleX = 30; cameraAngleX = 30;
cameraAngleY = -312; cameraAngleY = -312;
cameraDistance = 14.4; cameraDistance = 14.4;
//cameraAngleX = 0;
//cameraAngleY = 0;
//cameraDistance = 0;
mouseScaleX = 1;
mouseScaleY = 1;
} }
Render::~Render(void) { Render::~Render(void) {
@ -221,7 +249,8 @@ void Render::initializeGL() {
} }
void screenCoordsToWorld(float winX, float winY, void screenCoordsToWorld(float winX, float winY,
float *worldX, float *worldY, float *worldZ){ float *worldNearX, float *worldNearY, float *worldNearZ,
float *worldFarX, float *worldFarY, float *worldFarZ){
GLint viewport[4]; GLint viewport[4];
GLdouble modelview[16]; GLdouble modelview[16];
GLdouble projection[16]; GLdouble projection[16];
@ -234,15 +263,46 @@ void screenCoordsToWorld(float winX, float winY,
winX = (float)winX; winX = (float)winX;
winY = (float)viewport[3] - (float)winY; winY = (float)viewport[3] - (float)winY;
winZ = 0;
winZ = 0;
gluUnProject((GLdouble)winX, (GLdouble)winY, (GLdouble)winZ, gluUnProject((GLdouble)winX, (GLdouble)winY, (GLdouble)winZ,
(const GLdouble *)modelview, (const GLdouble *)projection, viewport, (const GLdouble *)modelview, (const GLdouble *)projection, viewport,
&x, &y, &z); &x, &y, &z);
*worldNearX = (float)x;
*worldNearY = (float)y;
*worldNearZ = (float)z;
{
vec3 origin = {(float)x, (float)y, (float)z};
drawDebugPoint(&origin, 0);
}
*worldX = (float)x; winZ = 1;
*worldY = (float)y; gluUnProject((GLdouble)winX, (GLdouble)winY, (GLdouble)winZ,
*worldZ = (float)z; (const GLdouble *)modelview, (const GLdouble *)projection, viewport,
&x, &y, &z);
*worldFarX = (float)x;
*worldFarY = (float)y;
*worldFarZ = (float)z;
{
vec3 origin = {(float)x, (float)y, (float)z};
drawDebugPoint(&origin, 1);
}
{
vec3 topOrigin = {*worldNearX, *worldNearY, *worldNearZ};
vec3 bottomOrigin = {*worldFarX, *worldFarY, *worldFarZ};
glDisable(GL_LIGHTING);
// x z plane
glBegin(GL_LINES);
glColor3f(0.0, 0.0, 0.0);
glVertex3f(topOrigin.x, topOrigin.y, topOrigin.z);
glVertex3f(bottomOrigin.x, bottomOrigin.y, bottomOrigin.z);
glEnd();
glEnable(GL_LIGHTING);
//drawCylinder(&topOrigin, &bottomOrigin, 0.1, 36, 24);
}
} }
#include "../data/bmesh_test_2.h" #include "../data/bmesh_test_2.h"
@ -265,16 +325,18 @@ void Render::paintGL() {
drawDebugPrintf("cameraAngleX:%f cameraAngleY:%f cameraDistance:%f", drawDebugPrintf("cameraAngleX:%f cameraAngleY:%f cameraDistance:%f",
cameraAngleX, cameraAngleY, cameraDistance); cameraAngleX, cameraAngleY, cameraDistance);
screenCoordsToWorld(_this->mouseX, _this->mouseY,
&_this->mouseWorldNearX, &_this->mouseWorldNearY, &_this->mouseWorldNearZ,
&_this->mouseWorldFarX, &_this->mouseWorldFarY, &_this->mouseWorldFarZ);
glColor3f(0.0f, 0.0f, 0.0f);
drawDebugPrintf("%d,%d -> %f,%f,%f %f,%f,%f", _this->mouseX, _this->mouseY,
_this->mouseWorldNearX, _this->mouseWorldNearY, _this->mouseWorldNearZ,
_this->mouseWorldFarX, _this->mouseWorldFarY, _this->mouseWorldFarZ);
drawGrid(10, 1); drawGrid(10, 1);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
screenCoordsToWorld(_this->mouseX, _this->mouseY,
&_this->mouseWorldX, &_this->mouseWorldY, &_this->mouseWorldZ);
glColor3f(0.0f, 0.0f, 0.0f);
drawDebugPrintf("%d,%d -> %f,%f,%f", _this->mouseX, _this->mouseY,
_this->mouseWorldX, _this->mouseWorldY, _this->mouseWorldZ);
if (0 == bm) { if (0 == bm) {
bmeshBall ball; bmeshBall ball;
bmeshBone bone; bmeshBone bone;
@ -363,6 +425,9 @@ void Render::paintGL() {
} }
void Render::resizeGL(int w, int h) { void Render::resizeGL(int w, int h) {
mouseScaleX = w / width();
mouseScaleY = h / height();
glViewport(0, 0, (GLsizei)w, (GLsizei)h); glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -385,16 +450,18 @@ void drawTestUnproject(void) {
}*/ }*/
void Render::mousePressEvent(QMouseEvent *event) { void Render::mousePressEvent(QMouseEvent *event) {
mouseX = event->x(); mouseX = event->x() * mouseScaleX;
mouseY = event->y(); mouseY = event->y() * mouseScaleY;
} }
void Render::mouseMoveEvent(QMouseEvent *event) { void Render::mouseMoveEvent(QMouseEvent *event) {
cameraAngleY += (event->x() - mouseX); int x = event->x() * mouseScaleX;
cameraAngleX += (event->y() - mouseY); int y = event->y() * mouseScaleY;
cameraAngleY += (x - mouseX);
cameraAngleX += (y - mouseY);
update(); update();
mouseX = event->x(); mouseX = x;
mouseY = event->y(); mouseY = y;
} }
void Render::wheelEvent(QWheelEvent * event) { void Render::wheelEvent(QWheelEvent * event) {

View File

@ -21,9 +21,14 @@ protected:
public: public:
int mouseX; int mouseX;
int mouseY; int mouseY;
float mouseWorldX; float mouseScaleX;
float mouseWorldY; float mouseScaleY;
float mouseWorldZ; float mouseWorldNearX;
float mouseWorldNearY;
float mouseWorldNearZ;
float mouseWorldFarX;
float mouseWorldFarY;
float mouseWorldFarZ;
float cameraAngleX; float cameraAngleX;
float cameraAngleY; float cameraAngleY;
float cameraDistance; float cameraDistance;