rotate about the mouse clicked point

Started by
3 comments, last by thinhare 14 years, 8 months ago
rotate about the mouse clicked point Hi, all I am making a 3d scene, with an area that contains many geometris, and centered on the screen, when rotating, it is for now always going about the center. What I want to do next is: I want it to rotate about the point mouse clicked, instead of the center of the screen, but my code seems odd: 1) I used UnProject to find the spot that I clicked, but the result seems not really accurate, if not entirely incorrect.

public void getClickedPositionCoordinate(GL aGL) {
	double[] l_Coordinate = new double[4];
	double[] l_ModelViewMatrix = new double[16];
	double[] l_ProjectionMatrix = new double[16];
	aGL.glGetDoublev(GL.GL_MODELVIEW_MATRIX, l_ModelViewMatrix, 0);
	aGL.glGetDoublev(GL.GL_PROJECTION_MATRIX, l_ProjectionMatrix, 0);
	int l_X = fPickPoint.x;
	int l_Y = fViewport[3] - fPickPoint.y - 1;
	FloatBuffer l_ZFloatBuffer = FloatBuffer.allocate(1); 
	aGL.glReadPixels(l_X, l_Y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_DOUBLE, l_ZFloatBuffer);
	fGlu.gluUnProject((double) l_X, (double) l_Y, l_ZFloatBuffer.get(0),
		l_ModelViewMatrix, 0, l_ProjectionMatrix, 0, fViewport, 0, l_Coordinate, 0);
	double fClickedPositionX = l_Coordinate[0];
	double fClickedPositionZ = l_Coordinate[2];
}

2) I tried to do the non-center rotating using all the maths I know, but it is always like rotating about some spot other that the place I clicked.

double l_XDisplacement = 0.0;
double l_ZDisplacement = 0.0;
double l_AzimuthInRadians = fAzimuth/180.0*Math.PI;
double l_OldX = 0.0;
double l_OldZ = 0.0;
double l_NewX = 0.0;
double l_NewZ = 0.0;
if (fClickedPositionX != 0 || fClickedPositionZ != 0) {
	l_AzimuthInRadians = fAzimuth/180.0*Math.PI;
	l_OldX = fClickedPositionX - fRotationCenterX;
	l_OldZ = fClickedPositionZ - fRotationCenterZ;
	l_NewX = l_OldX*Math.cos(l_AzimuthInRadians) - l_OldZ*Math.sin(l_AzimuthInRadians);
	l_NewZ = l_OldX*Math.sin(l_AzimuthInRadians) + l_OldZ*Math.cos(l_AzimuthInRadians);
	l_XDisplacement = l_NewX - l_OldX;
	l_ZDisplacement = l_NewZ - l_OldZ;
}

A snipt of the code is included above, and any help are welcome. Thx!! [Edited by - thinhare on August 21, 2009 4:43:50 PM]
Advertisement
pos is the position to rotate around, x,y,z the rotation axis, Transform the cameras transformation matrix and Right/Up/Forward/Position are pointers into Transform for convenience.

All you do is calculate the clicked points position in camera space, do the rotation and apply a translation that compensates for the movement

void CameraGL::rotateAround(float deg, float x, float y, float z, bool global, float* pos) {	float tx,ty,tz;	if (pos) {		float d[3]={pos[0]-Position[0], pos[1]-Position[1], pos[2]-Position[2]};		tx=d[0]*Right[0] + d[1]*Right[1] + d[2]*Right[2];		ty=d[0]*Up[0] + d[1]*Up[1] + d[2]*Up[2];		tz=d[0]*Forward[0] + d[1]*Forward[1] + d[2]*Forward[2];	}	rotate(deg, x,y,z,global);	if (pos) {		Transform[12]=pos[0] - (tx*Right[0] + ty*Up[0] + tz*Forward[0]);		Transform[13]=pos[1] - (tx*Right[1] + ty*Up[1] + tz*Forward[1]);		Transform[14]=pos[2] - (tx*Right[2] + ty*Up[2] + tz*Forward[2]);	}}
f@dzhttp://festini.device-zero.de
Hello, Trienco, thanks for reply.

I tried to use your matrix method in my code, but could not see the result I expected, maybe I am just not doing it right, here is the code, woule you please help me out. Thanks!!

	protected void transform(GL gl) {		gl.glTranslated(0, 0, -distance);		double[] model = new double[16];		gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, model, 0);		double[] pos = {mark.getX(), mark.getY(), mark.getZ()};		double[] d = {pos[0] - model[12], pos[1] - model[13], pos[2] - model[14]};		double tx = d[0]*model[0] + d[1]*model[4] + d[2]*model[8];		double ty = d[0]*model[1] + d[1]*model[5] + d[2]*model[9];		double tz = d[0]*model[2] + d[1]*model[6] + d[2]*model[10];		gl.glRotated(angleVer, 1, 0, 0);		gl.glRotated(angleHor, 0, 1, 0);		gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, model, 0);		model[12] = pos[0] - (tx*model[0] + ty*model[1] + tz*model[2]);		model[13] = pos[1] - (tx*model[4] + ty*model[5] + tz*model[6]);		model[14] = pos[2] - (tx*model[8] + ty*model[9] + tz*model[10]);		gl.glLoadMatrixd(model, 0);		gl.glTranslated(-center_x, 0, -center_z);	}


[Edited by - thinhare on August 16, 2009 4:32:16 PM]
At first glance it seems you're mixing up the matrices. Transform pretends the camera is just like any other object. So the adjusted version should begin with the identity matrix, apply the transformations for the camera (in your case it's probably just the offset as translation). You could of course just fill out the matrix yourself if there is no rotation anyway.

Then you calculate mark in camera coords as you already do (if you happen to have a matrix library you can just multiply it to keep the code less messy).

I'm noticing that you transposed the rotation part, so maybe you already try to "reinvert" the viewmatrix, but in that case you seem to forget adjusting the position part. Also not sure about doing the offset translation last.

Back to the "camera-as-object" matrix what you should put into loadmatrix is the inverse of the matrix you have.

I don't seem to have this feature in the standalone class, but maybe you can piece it together from the two camera source files in the project (scroll down to SW D6 tool)
f@dzhttp://festini.device-zero.de
Hello, Trienco,

To avoid misunderstanding (on my side), I'd like to get confirmed from you with a few things:

1) The Right/Up/Forward/Position correspond to the elements in the matrix:

R_0 R_1 R_2 P_X
U_0 U_1 U_2 P_Y
F_0 F_1 F_2 P_Z
0.0 0.0 0.0 1.0

2) What are the meanings of tx, ty, tz in this matrix operation?

	float tx,ty,tz;	float d[3]={pos[0]-Position[0], pos[1]-Position[1], pos[2]-Position[2]};	tx=d[0]*Right[0] + d[1]*Right[1] + d[2]*Right[2];	ty=d[0]*Up[0] + d[1]*Up[1] + d[2]*Up[2];	tz=d[0]*Forward[0] + d[1]*Forward[1] + d[2]*Forward[2];


3) For the elements of Right/Up/Forward, they now contain new values, or the same values as the one above? Transform is transform matrix, am I right?

	Transform[12]=pos[0] - (tx*Right[0] + ty*Up[0] + tz*Forward[0]);	Transform[13]=pos[1] - (tx*Right[1] + ty*Up[1] + tz*Forward[1]);	Transform[14]=pos[2] - (tx*Right[2] + ty*Up[2] + tz*Forward[2]);


4) I tried some simpler method, but there's a shortcoming in this method, it now can rotate about the given point, but the location of the object has been lifted up some distance, how do I fix this?

protected void transform(GL gl) {	double[] d = {mark.getX() - center_x, mark.getY() - center_y, mark.getZ() - center_z};	gl.glTranslated(0, 0, -distance);	gl.glTranslated(d[0], d[1], d[2]);	gl.glRotated(angleVer, 1, 0, 0);	gl.glRotated(angleHor, 0, 1, 0);	gl.glTranslated(-d[0], -d[1], -d[2]);	gl.glTranslated(-center_x, -center_y, -center_z);}


Image and video hosting by TinyPic

Image and video hosting by TinyPic

This topic is closed to new replies.

Advertisement