[comp.graphics] Virtual Sphere - 3D Object Manipulator

naughton@wind.Sun.COM (Patrick Naughton) (09/14/89)

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 am playing with spinning 3D objects around using a NeWS front end under
OpenWindows while talking directly to the GX hardware on my 4/60 and don't
want to waste a lot of time rebuilding this particular wheel if it is
already out there.

I'll go ahead and do it myself if I don't hear from anyone and post it to
this group, but this is a pet project not real work, so it may be a while.

-Patrick
    ______________________________________________________________________
    Patrick J. Naughton				    ARPA: naughton@Sun.COM
    Window Systems Group			    UUCP: ...!sun!naughton
    Sun Microsystems, Inc.			    AT&T: (415) 336 - 1080

bouma@cs.purdue.EDU (William J. Bouma) (09/20/89)

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 <bouma@cs.purdue.edu>  ||  ...!purdue!bouma 
-----------------------------------------------------------
#include <math.h>

#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;
}