Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!iuvax!purdue!bouma From: bouma@cs.purdue.EDU (William J. Bouma) Newsgroups: comp.graphics Subject: Re: Virtual Sphere - 3D Object Manipulator Keywords: virtual sphere 3D rotation Message-ID: <8025@medusa.cs.purdue.edu> Date: 19 Sep 89 19:32:00 GMT References: <124673@sun.Eng.Sun.COM> Distribution: na Organization: Department of Computer Science, Purdue University Lines: 94 In article <124673@sun.Eng.Sun.COM> naughton@sun.com (Patrick Naughton) writes: >The August '88 SIGGRAPH proceedings describe an algorithm for manipulating >3D objects in an intuitive manner with a 'virtual controller'. > > Chen, Mountford and Sellen, "A Study in Interactive 3-D Rotation Using > 2-D Control Devices", Computer Graphics, Vol 22, No 4, August 1988. > >It basically describes the transforms required to turn the 2-D delta motion >from a mouse dragged over the window displaying the object into the 3-D >rotation about an arbitrary axis in 3-D space. It models this as a virtual >sphere or track-ball centered at the center of the object to be manipulated. > >I am looking for someone who has already coded this from the algorithm to >C or some other reasonable language in any form of a window system. I think this hacked up code here does what you want. People actually get papers published on this junk? Bill || ...!purdue!bouma ----------------------------------------------------------- #include #define PI 3.14159265358979 #define dot_product(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) #define length(a) (float) (sqrt((double) dot_product(a,a))) #define copyvec(a,b) (b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2] #define cross_product(a,b,c) (c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1];\ (c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2];\ (c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0] #define normalize(vec) temp = length(vec);\ vec[0]/=temp;\ vec[1]/=temp;\ vec[2]/=temp #define negate(v) v[0] = -v[0]; v[1] = -v[1]; v[2] = - v[2] #define subvec(a,b,c) c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2] float eye[3], center[3], up[3]; /* * rotate changes eye according to horizontal and vertical movements * about a sphere at center. up should be normalized upon entry. * idx, idy are amount in pixels your mouse has moved. * xsize, ysize are the size in pixels of your window. */ rotate(dx, dy, xsize, ysize) int idx, idy; int xsize, ysize; { int i; float enew[3], eold[3]; float rt[3], radius, temp, dx, dy; subvec(eye, center, eold); radius = length(eold); enew[0] = eold[0] /= radius; enew[1] = eold[1] /= radius; enew[2] = eold[2] /= radius; if (idy != 0) { dy = idy * 2 * PI / ysize; for (i=0; i<3; i++) enew[i] = eold[i]*cos(dy) + up[i]*sin(dy); normalize(enew); subvec(enew, eold, up); if (dy < 0) { /* moving down */ negate(up); } normalize(up); cross_product(enew, up, rt); normalize(rt); copyvec(enew, eold); } else { rt[0] = 1.0; rt[1] = 0.0; rt[2] = 0.0; } if (idx != 0) { dx = idx * 2 * PI / xsize; for (i=0; i<3; i++) enew[i] = eold[i]*cos(dx) + rt[i]*sin(dx); normalize(enew); subvec(enew, eold, rt); if (dx < 0) { /* moving left */ negate(rt); } normalize(rt); cross_product(rt, enew, up); normalize(up); } eye[0] = center[0] + enew[0]*radius; eye[1] = center[1] + enew[1]*radius; eye[2] = center[2] + enew[2]*radius; }