/* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { float a[3]; /* Axis of rotation */ float phi; /* how much to rotate about axis */ float p1[3], p2[3], d[3]; float t; if (p1x == p2x && p1y == p2y) { /* Zero rotation */ vzero(q); q[3] = 1.0; return; } /* * First, figure out z-coordinates for projection of P1 and P2 to * deformed sphere */ vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y)); vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y)); /* * Now, we want the cross product of P1 and P2 */ vcross(p2,p1,a); /* * Figure out how much to rotate around that axis. */ vsub(p1, p2, d); t = vlength(d) / (2.0f*TRACKBALLSIZE); /* * Avoid problems with out-of-control values... */ if (t > 1.0) t = 1.0; if (t < -1.0) t = -1.0; phi = 2.0f * (float) asin(t); axis_to_quat(a,phi,q); }
/* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ quat & trackball(quat& q, vec2& pt1, vec2& pt2, nv_scalar trackballsize) { vec3 a; // Axis of rotation nv_scalar phi; // how much to rotate about axis vec3 d; nv_scalar t; if (pt1.x == pt2.x && pt1.y == pt2.y) { // Zero rotation q = quat_id; return q; } // First, figure out z-coordinates for projection of P1 and P2 to // deformed sphere vec3 p1(pt1.x,pt1.y,tb_project_to_sphere(trackballsize,pt1.x,pt1.y)); vec3 p2(pt2.x,pt2.y,tb_project_to_sphere(trackballsize,pt2.x,pt2.y)); // Now, we want the cross product of P1 and P2 cross(a,p1,p2); // Figure out how much to rotate around that axis. d.x = p1.x - p2.x; d.y = p1.y - p2.y; d.z = p1.z - p2.z; t = _sqrt(d.x * d.x + d.y * d.y + d.z * d.z) / (trackballsize); // Avoid problems with out-of-control values... if (t > nv_one) t = nv_one; if (t < -nv_one) t = -nv_one; phi = nv_two * nv_scalar(asin(t)); axis_to_quat(q,a,phi); return q; }
void rotate(int by, float axis[3][3], int phi) { GLfloat m[4][4]; float q[4] = {0}; int i; for (i=0; i<4; i++) { q[i] = 0; } axis_to_quat(axis[by],RAD(phi), q); build_rotmatrix(m, q); for (i=0; i<3; i++) { if (i != by) { multiply(m, axis[i], axis[i]); } } for (i=0; i<NV; i++) { multiply(m, vertexes[i], vertexes[i]); } for (i=0; i<4; i++) { multiply(m, originalVertex[i], originalVertex[i]); } }
/* Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void trackball(double q[4], double p1x, double p1y, double p2x, double p2y){ double axis[3]; /* Axis of rotation */ double phi; /* how much to rotate about axis */ double p1[3], p2[3], d[3]; double t; /* if zero rotation */ if(p1x == p2x && p1y == p2y){ vset(q, 0.0, 0.0, 0.0); q[3] = 1.0; return; } /* First, figure out z-coordinates for projection of P1 and P2 to */ /* the deformed sphere */ p1[0] = p1x; p1[1] = p1y; p1[2] = tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y); p2[0] = p2x; p2[1] = p2y; p2[2] = tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y); /* Now, we want the cross product of P1 and P2 */ vcross(axis, p2, p1); /* Figure out how much to rotate around that axis. */ vsub(d, p1, p2); t = vlength(d)/(2.0*TRACKBALLSIZE); /* Avoid problems with out-of-control values. */ if(t > 1.0){ t = 1.0; } if(t < -1.0){ t = -1.0; } phi = 2.0 * asin(t); axis_to_quat(axis, phi, q); }
/* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y, float tbSize) { float a[3]; // Axis of rotation float phi; // how much to rotate about axis float p1[3], p2[3], d[3]; float t; if( p1x == p2x && p1y == p2y ) { /* Zero rotation */ vzero(q); q[3] = 1.0; return; } // First, figure out z-coordinates for projection of P1 and P2 to deformed sphere vset( p1, p1x, p1y, tb_project_to_sphere(tbSize, p1x, p1y) ); vset( p2, p2x, p2y, tb_project_to_sphere(tbSize, p2x, p2y) ); // Now, we want the cross product of P1 and P2 vcross( p2, p1, a); // Figure out how much to rotate around that axis vsub( p1, p2, d); t = vlength(d) / ( 2.0f * tbSize ); // Avoid problems with out-of-control values if (t > 1.0) { t = 1.0; } if (t < -1.0) { t = -1.0; } phi = 2.0f * (float)asin(t); axis_to_quat( a, phi, q ); }
Rubik::Rubik(Level lv,int sz){/* Up[0] = v[0]; Up[1] = v[1]; Up[2] = v[2]; Up[3] = v[3]; Down[0] = v[7]; Down[1] = v[6]; Down[2] = v[5]; Down[3] = v[4]; Front[0] = v[3]; Front[1] = v[2]; Front[2] = v[6]; Front[3] = v[7]; Back[0] = v[1]; Back[1] = v[0]; Back[2] = v[4]; Back[3] = v[5]; Left[0] = v[0]; Left[1] = v[3]; Left[2] = v[7]; Left[3] = v[4]; Right[0] = v[2]; Right[1] = v[1]; Right[2] = v[5]; Right[3] = v[6]; */ p[0] = Vec3f(1.5*edge_length, -1.5*edge_length, 1.5*edge_length); p[1] = Vec3f(1.5*edge_length, 1.5*edge_length, 1.5*edge_length); p[2] = Vec3f(-1.5*edge_length, 1.5*edge_length, 1.5*edge_length); p[3] = Vec3f(-1.5*edge_length, -1.5*edge_length, 1.5*edge_length); for (int i = 0; i < 3; ++i) for (int j=0; j<3; ++j) for(int k=0; k<3; ++k){ int p = k+j*3+i*3*3; blocks[p].pos = Vec3i(k,j,i); switch(i){ case 0: blocks[p].sf.push_back(Surface(DOWN,DOWN,1)); break; case 2: blocks[p].sf.push_back(Surface(UP,UP,2)); break; default: break; } switch(j){ case 0: blocks[p].sf.push_back(Surface(LEFT,LEFT,3)); break; case 2: blocks[p].sf.push_back(Surface(RIGHT,RIGHT,4)); break; default: break; } switch(k){ case 0: blocks[p].sf.push_back(Surface(BACK,BACK,5)); break; case 2: blocks[p].sf.push_back(Surface(FRONT,FRONT,6)); break; default: break; } } shuffle(lv); std::cout << "Selected level is: " << lv << std::endl; angle=0; trackball(0,0,curPos); trackball(0,0,lastPos); //std::cout << curPos << std::endl; //std::cout << lastPos << std::endl; calRotation(); //std::cout << axis[0] << "," << axis[1] << ","<< axis[2] << "," << angle<< std::endl; axis_to_quat(axis,angle,curquat); std::printf("curquat = %f %f %f %f\n", curquat[0], curquat[1], curquat[2], curquat[3]); }
int tachyon_spaceball_update(sbHandle * bh, SceneHandle scene) { int tx, ty, tz, rx, ry, rz, buttons; float qq[4]; float xx[3]={1.0, 0.0, 0.0}; float yy[3]={0.0, 1.0, 0.0}; float zz[3]={0.0, 0.0, 1.0}; float m[4][4]; float t[3]; static float transdivisor = 5000.0; static float angdivisor = 20000.0; if (bh->sball == NULL) return -1; if (sball_getstatus(bh->sball, &tx, &ty, &tz, &rx, &ry, &rz, &buttons)) { /* negate rotations given by spaceball */ rx = -rx; ry = -ry; rz = -rz; if (buttons) { if (buttons & SBALL_BUTTON_PICK) { bh->curtrans[0] = 0.0; bh->curtrans[1] = 0.0; bh->curtrans[2] = 0.0; trackball(bh->curquat, 0.0, 0.0, 0.0, 0.0); transdivisor = 5000.0; angdivisor = 20000.0; bh->camviewvec = bh->orig_camviewvec; bh->camupvec = bh->orig_camupvec; bh->camcent = bh->orig_camcent; } if (buttons & SBALL_BUTTON_1) { transdivisor /= 1.2; angdivisor /= 1.2; } else if (buttons & SBALL_BUTTON_2) { transdivisor *= 1.2; angdivisor *= 1.2; } if (buttons & SBALL_BUTTON_3) transdivisor /= 1.2; else if (buttons & SBALL_BUTTON_4) transdivisor *= 1.2; if (buttons & SBALL_BUTTON_5) angdivisor *= 1.2; else if (buttons & SBALL_BUTTON_6) angdivisor /= 1.2; if (buttons & SBALL_BUTTON_7) { return 1; /* quit the fly through */ } } /* end of button handling */ t[0] = tx / transdivisor; t[1] = ty / transdivisor; t[2] = tz / transdivisor; /* * convert rotations and translations from the * spaceball's coordinate frame into the camera's frame. */ bh->newtrans[0] = t[0] * bh->orig_camrightvec.x + t[1] * bh->orig_camupvec.x + t[2] * bh->orig_camviewvec.x; bh->newtrans[1] = t[0] * bh->orig_camrightvec.y + t[1] * bh->orig_camupvec.y + t[2] * bh->orig_camviewvec.y; bh->newtrans[2] = t[0] * bh->orig_camrightvec.z + t[1] * bh->orig_camupvec.z + t[2] * bh->orig_camviewvec.z; /* * rotate around camera's coordinate frame */ xx[0] = bh->orig_camrightvec.x; xx[1] = bh->orig_camrightvec.y; xx[2] = bh->orig_camrightvec.z; yy[0] = bh->orig_camupvec.x; yy[1] = bh->orig_camupvec.y; yy[2] = bh->orig_camupvec.z; zz[0] = bh->orig_camviewvec.x; zz[1] = bh->orig_camviewvec.y; zz[2] = bh->orig_camviewvec.z; /* do rotations */ axis_to_quat(xx, rx / angdivisor, bh->lastquat); axis_to_quat(yy, ry / angdivisor, qq); add_quats(qq, bh->lastquat, bh->lastquat); axis_to_quat(zz, rz / angdivisor, qq); add_quats(qq, bh->lastquat, bh->lastquat); add_quats(bh->lastquat, bh->curquat, bh->curquat); } else { usleep(5); /* if no movement then sleep for a tiny bit.. */ } build_rotmatrix(m, bh->curquat); /* * translate along the new axes */ t[0] = m[0][0] * bh->newtrans[0] + m[0][1] * bh->newtrans[1] + m[0][2] * bh->newtrans[2]; t[1] = m[1][0] * bh->newtrans[0] + m[1][1] * bh->newtrans[1] + m[1][2] * bh->newtrans[2]; t[2] = m[2][0] * bh->newtrans[0] + m[2][1] * bh->newtrans[1] + m[2][2] * bh->newtrans[2]; bh->camcent.x += t[0]; bh->camcent.y += t[1]; bh->camcent.z += t[2]; /* * rotate view system with spaceball */ bh->camviewvec.x = m[0][0] * bh->orig_camviewvec.x + m[0][1] * bh->orig_camviewvec.y + m[0][2] * bh->orig_camviewvec.z; bh->camviewvec.y = m[1][0] * bh->orig_camviewvec.x + m[1][1] * bh->orig_camviewvec.y + m[1][2] * bh->orig_camviewvec.z; bh->camviewvec.z = m[2][0] * bh->orig_camviewvec.x + m[2][1] * bh->orig_camviewvec.y + m[2][2] * bh->orig_camviewvec.z; bh->camupvec.x = m[0][0] * bh->orig_camupvec.x + m[0][1] * bh->orig_camupvec.y + m[0][2] * bh->orig_camupvec.z; bh->camupvec.y = m[1][0] * bh->orig_camupvec.x + m[1][1] * bh->orig_camupvec.y + m[1][2] * bh->orig_camupvec.z; bh->camupvec.z = m[2][0] * bh->orig_camupvec.x + m[2][1] * bh->orig_camupvec.y + m[2][2] * bh->orig_camupvec.z; /* * update camera parameters before we render again */ rt_camera_position(scene, bh->camcent, bh->camviewvec, bh->camupvec); return 0; }
void drawContext::eventHandler(int event, float x, float y) { int width = _width, height = _height; if(_retina){ // x,y for retina are still the same as for non-retina width /= 2; height /= 2; } _current.set(_scale, _translate, _right, _left, _bottom, _top, width, height, x, y); double xx[3] = {1.,0.,0.}; double yy[3] = {0.,1.,0.}; double q[4]; switch(event){ case 0: // finger(s) press the screen // in this case x and y represent the start point _start.set(_scale, _translate, _right, _left, _bottom, _top, width, height, x, y); _previous.set(_scale, _translate, _right, _left, _bottom, _top, width, height, x, y); break; case 1: // finger move (translate) // in this case x and y represent the current point _translate[0] += (_current.wnr[0] - _previous.wnr[0]); _translate[1] += (_current.wnr[1] - _previous.wnr[1]); _translate[2] = 0.; break; case 2: // fingers move (scale) // in this case we don't care about previous and current position, x // represent the scale _scale[0] = _scale[1] = _scale[2] = x; _start.recenter(_scale, _translate); break; case 3: // fingers move (rotate) addQuaternion((2. * _previous.win[0] - width) / width, (height - 2. * _previous.win[1]) / height, (2. * _current.win[0] - width) / width, (height - 2. * _current.win[1]) / height); break; case 4: // release the finger(s) // Do nothing ? break; case 5: // X view axis_to_quat(xx, M_PI/2, q); setQuaternion(q[0], q[1], q[2], q[3]); break; case 6: // Y view axis_to_quat(yy, M_PI/2, q); setQuaternion(q[0], q[1], q[2], q[3]); break; case 7: // Z view setQuaternion(0., 0., 0., 1.); break; default: // all other reset the position setQuaternion(0., 0., 0., 1.); for(int i = 0; i < 3; i++){ _translate[i] = 0.; _scale[i] = 1.; } break; } _previous.set(_scale, _translate, _right, _left, _bottom, _top, width, height, x, y); }
static gboolean expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { GdkGLContext *glcontext = gtk_widget_get_gl_context (widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget); float d_quat[4]; float m[4][4]; if (animate) { if (counter == rot_count) { if (rot_mode[++mode].axis == NULL) mode = 0; counter = 0; } axis_to_quat (rot_mode[mode].axis, rot_mode[mode].sign * G_PI_2 / rot_count, d_quat); add_quats (d_quat, logo_quat, logo_quat); counter++; } /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return FALSE; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); /* View transformation. */ glTranslatef (0.0, 0.0, -30.0); glScalef (view_scale, view_scale, view_scale); build_rotmatrix (m, view_quat); glMultMatrixf (&m[0][0]); /* Logo model. */ glPushMatrix (); build_rotmatrix (m, logo_quat); glMultMatrixf (&m[0][0]); glRotatef (90.0, 1.0, 0.0, 0.0); glCallList (LOGO_CUBE); glCallList (LOGO_G_FORWARD); glCallList (LOGO_G_BACKWARD); glCallList (LOGO_T_FORWARD); glCallList (LOGO_T_BACKWARD); glCallList (LOGO_K_FORWARD); glCallList (LOGO_K_BACKWARD); glPopMatrix (); /* Swap buffers. */ if (gdk_gl_drawable_is_double_buffered (gldrawable)) gdk_gl_drawable_swap_buffers (gldrawable); else glFlush (); gdk_gl_drawable_gl_end (gldrawable); /*** OpenGL END ***/ return TRUE; }