Thread: rotating around object (looat)

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    111

    rotating around object (looat)

    I need to rotate an object (bezier surface).
    I wish to use glLookAt instead of rotatef.

    i started with :

    Code:
    // clear the screen & depth buffer
    	glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
    	// clear the previous transform
    	glLoadIdentity();
    	// set the camera position
    	gluLookAt(	xLookAt,yLookAt,zLookAt,	//	eye pos
    				0,0,0,	//	aim point
    				0,1,0);	//	up direction
    and :
    Code:
    		if ((x < -6.28) || (x > 6.28))
    		{
    			x=0;
    			xLookAt = 0;
    			break;
    		}
    		x -= 0.1;
    		xLookAt = cos(x) * sin (z);
    		break;
    I'm using 6.28 as 2 PI and i wish to go around an object.
    the problem is that it changes the direction of movment instead continue move.

    i used the next code :
    Code:
    //------------------------------------------------------------
    /// \file	Main.cpp
    /// \author	Rob Bateman
    /// \date	9-feb-2005
    /// \brief	This is a very simple example of a bezier patch
    //------------------------------------------------------------
    #include <stdlib.h>
    #include <GL/glut.h>
    #include <math.h>
    #include <stdio.h>
    
    struct Point {
    	float x;
    	float y;
    	float z;
    };
    
    /// 4x4 grid of points.
    Point Points[4][4] = { 
    	{
    		{ 10,0,10 },
    		{  5,0,10 },
    		{ -5,0,10 },
    		{-10,0,10 }
    	},
    
    	{
    		{ 10,0,5 },
    		{  5,6,5 },
    		{ -5,6,5 },
    		{-10,0,5 }
    	},
    
    	{
    		{ 10,0,-5 },
    		{  5,6,-5 },
    		{ -5,6,-5 },
    		{-10,0,-5 }
    	},
    
    	{
    		{ 10,0,-10 },
    		{  5,0,-10 },
    		{ -5,0,-10 },
    		{-10,0,-10 }
    	}
    
    };
    
    unsigned int num_knots_u=8;
    unsigned int num_knots_v=8;
    unsigned int num_cvs_u=4;
    unsigned int num_cvs_v=4;
    unsigned int degree_u=3;
    unsigned int degree_v=3;
    unsigned int order_u=degree_u+1;
    unsigned int order_v=degree_v+1;
    
    float knots_u[] = {0,0,0,0,1,1,1,1};
    float knots_v[] = {0,0,0,0,1,1,1,1};
    
    unsigned int LOD=20;
    
    float MinU() {
    	return knots_u[degree_u];
    }
    
    float MinV() {
    	return knots_v[degree_v];
    }
    
    float MaxU() {
    	return knots_v[num_knots_u-degree_u];
    }
    
    float MaxV() {
    	return knots_v[num_knots_v-degree_v];
    }
    
    
    //------------------------------------------------------------	CoxDeBoor()
    //
    
    float CoxDeBoor(float u,int i,int k,const float* Knots) {
    	if(k==1)
    	{
    		if( Knots[i] <= u && u <= Knots[i+1] ) {
    			return 1.0f;
    		}
    		return 0.0f;
    	}
    
    	float Den1 = Knots[i+k-1] - Knots[i];
    	float Den2 = Knots[i+k] - Knots[i+1];
    	float Eq1=0,Eq2=0;
    	if(Den1>0) {
    		Eq1 = ((u-Knots[i]) / Den1) * CoxDeBoor(u,i,k-1,Knots);
    	}
    
    	if(Den2>0) {
    		Eq2 = (Knots[i+k]-u) / Den2 * CoxDeBoor(u,i+1,k-1,Knots);
    	}
    	return Eq1+Eq2;
    }
    
    
    
    //------------------------------------------------------------	CalculateU()
    //
    
    Point CalculateU(float t,int row) {
    	Point p = {0,0,0};
    		// sum the effect of all CV's on the curve at this point to 
    		// get the evaluated curve point
    		// 
    		for(unsigned int i=0;i!=num_cvs_u;++i) {
    			// calculate the effect of this point on the curve
    			float Val = CoxDeBoor(t,i,order_u,knots_u);
    			if(Val>0.001f) {
    				// sum effect of CV on this part of the curve
    				p.x += Val * Points[row][i].x;
    
    				p.y += Val * Points[row][i].y;
    
    				p.z += Val * Points[row][i].z;
    
    			}
    
    		}
    
    
    
    	return p;
    
    }
    
    
    
    //------------------------------------------------------------	CalculateV()
    
    //
    
    Point CalculateV(float t,Point* pnts) {
    
    
    
    	Point p = {0,0,0};
    
    
    
    	// sum the effect of all CV's on the curve at this point to 
    
    	// get the evaluated curve point
    
    	// 
    
    	for(unsigned int i=0;i!=num_cvs_v;++i) {
    
    
    
    		// calculate the effect of this point on the curve
    
    		float Val = CoxDeBoor(t,i,order_v,knots_v);
    
    
    
    		if(Val>0.001f) {
    
    
    
    			// sum effect of CV on this part of the curve
    
    			p.x += Val * pnts[i].x;
    
    			p.y += Val * pnts[i].y;
    
    			p.z += Val * pnts[i].z;
    
    		}
    
    	}
    
    
    
    	return p;
    
    }
    
    
    
    //------------------------------------------------------------	Calculate()
    
    //
    
    Point Calculate(float u,float v) {
    
    
    
    
    
    	Point* temp = new Point[num_cvs_v];
    
    	for(unsigned int i=0;i!=num_cvs_v;++i) {
    
    	
    
    		// first treat the surface as a set of 4 curves. Calculate 
    
    		// a point on each of the curves and store the result.
    
    		//
    
    		temp[i] = CalculateU(u,i);
    
    	}
    
    
    
    	// having got 4 points, we can use it as a bezier curve
    
    	// to calculate the v direction
    
    	//
    
    	Point p = CalculateV(v,temp);
    
    
    
    	delete [] temp;
    
    
    
    	return p;
    
    }
    
    
    
    //------------------------------------------------------------	OnReshape()
    
    //
    
    void OnReshape(int w, int h)
    
    {
    
    	if (h==0) {
    
    		h=1;
    
    	}
    
    
    
    	// set the drawable region of the window
    
    	glViewport(0,0,w,h);
    
    
    
    	// set up the projection matrix 
    
    	glMatrixMode(GL_PROJECTION);
    
    	glLoadIdentity();
    
    
    
    	// just use a perspective projection
    
    	gluPerspective(45,(float)w/h,0.1,100);
    
    
    
    	// go back to modelview matrix so we can move the objects about
    
    	glMatrixMode(GL_MODELVIEW);
    
    	glLoadIdentity();
    
    }
    
    
    
    //------------------------------------------------------------	Draw()
    
    //
    
    
    
    float x = 5;
    
    float alpha = 0;
    
    float y = 16;
    
    float z = 20 ;
    float xLookAt = x;
    float yLookAt = y;
    float zLookAt = z;
    
    void OnDraw() {
    
    
    
    	// clear the screen & depth buffer
    
    	glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
    
    
    
    	// clear the previous transform
    
    	glLoadIdentity();
    
    
    
    	// set the camera position
    
    	gluLookAt(	xLookAt,yLookAt,zLookAt,	//	eye pos
    
    				0,0,0,	//	aim point
    
    				0,1,0);	//	up direction
    
    
    
    	glColor3f(1,0,1);
    
    	glPointSize(2);
    
    	glBegin(GL_POINTS);
    
    
    
    	// use the parametric time value 0 to 1
    
    	for(int i=0;i!=LOD;++i) {
    
    
    
    		// calculate the parametric u value
    
    		float u = (MaxU()-MinU())*(float)i/(LOD-1) + MinU();
    
    
    
    		for(int j=0;j!=LOD;++j) {
    
    
    
    			// calculate the parametric v value
    
    			float v = (MaxV()-MinV())*(float)j/(LOD-1) + MinV();
    
    
    
    			// calculate the point on the surface
    
    			Point p = Calculate(u,v);
    
    
    
    			// draw point
    
    			glVertex3f(p.x,p.y,p.z);
    
    		}
    
    	}
    
    
    
    	glEnd();
    
    
    
    	// currently we've been drawing to the back buffer, we need
    
    	// to swap the back buffer with the front one to make the image visible
    
    	glutSwapBuffers();
    
    }
    
    
    
    //------------------------------------------------------------	OnInit()
    
    //
    
    void OnInit() {
    
    	// enable depth testing
    
    	glEnable(GL_DEPTH_TEST);
    
    }
    
    
    
    //------------------------------------------------------------	OnExit()
    
    //
    
    void OnExit() {
    
    }
    
    
    
    //------------------------------------------------------------	OnKeyPress()
    
    //
    
    void OnKeyPress(unsigned char key,int,int) {
    
    	switch(key) {
    
    
    
    	// increase the LOD
    
    	case '+':
    
    		++LOD;
    
    		break;
    
    
    
    	// decrease the LOD
    
    	case '-':
    
    		--LOD;
    
    
    
    		// have a minimum LOD value
    
    		if (LOD<3) 
    
    			LOD=3;
    
    		break;
    
    	case 'a':
    
    //		glPop
    
    
    
    
    
    		
    
    		break;
    
    	case 'b':
    		if ((x < -6.28) || (x > 6.28))
    		{
    			x=0;
    			xLookAt = 0;
    			break;
    		}
    		x -= 0.1;
    		xLookAt = cos(x) * sin (z);
    		break;	
    
    	
    
    default:
    
    		break;
    
    	}
    
    	// ask glut to redraw the screen for us... 
    	//x = cos(y) * sin(z);
    
    	glutPostRedisplay();
    
    }
    
    
    
    //------------------------------------------------------------	main()
    
    //
    
    int main(int argc,char** argv) {
    
    
    
    	// initialise glut
    
    	glutInit(&argc,argv);
    
    
    
    	// request a depth buffer, RGBA display mode, and we want double buffering
    
    	glutInitDisplayMode(GLUT_DEPTH|GLUT_RGBA|GLUT_DOUBLE);
    
    
    
    	// set the initial window size
    
    	glutInitWindowSize(640,480);
    
    
    
    	// create the window
    
    	glutCreateWindow("Bezier Curve: +/- to Change Level of Detail");
    
    
    
    	// set the function to use to draw our scene
    
    	glutDisplayFunc(OnDraw);
    
    
    
    	// set the function to handle changes in screen size
    
    	glutReshapeFunc(OnReshape);
    
    
    
    	// set the function for the key presses
    
    	glutKeyboardFunc(OnKeyPress);
    
    	
    
    	// run our custom initialisation
    
    	OnInit();
    
    
    
    	// set the function to be called when we exit
    
    	atexit(OnExit);
    
    
    
    	// this function runs a while loop to keep the program running.
    
    	glutMainLoop();
    
    	return 0;
    
    }
    Last edited by jabka; 06-13-2008 at 05:05 PM. Reason: no CODE elemnts
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    That double spaced code is just hard to read. Whitespace is good, but you can have too much of a good thing.

    A suggestion: don't create global variables with short names like "x" and "y". You might use them by accident.

    I'm using 6.28 as 2 PI
    You could use the semi-non-standard M_PI from <math.h> or define PI yourself if you wanted to. For example, I like to use
    Code:
    #ifdef PI
    #define CONSTANT_PI PI
    #elif defined(M_PI)
    #define CONSTANT_PI M_PI
    #else
    #define CONSTANT_PI 3.14159265358979323846264338327950288419716939937510582097
    #endif
    Or you could calculate PI dynamically with something like
    Code:
    double PI = atan(1) * 4;
    As for your question . . . sorry, but I have no idea.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    To rotate around something always translate then rotate.

  4. #4
    Registered User
    Join Date
    Apr 2007
    Posts
    111

    So not to use glLookAt ?

    moment i didn't understant :
    if i use glRotate then i rotate the object while i wish to rotate only the camera.
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  5. #5
    Registered User
    Join Date
    Jan 2008
    Posts
    70
    What are you trying to do? Bubba is recommending you make a translation matrix and then multiply it by a rotation matrix, as that is how you would rotate one object about another. But for a camera, glLookAt, or more technically a view matrix will do the trick.

    edit:

    Was just looking at your code, it doesn't seem quite right.

    Code:
    if ((x < -6.28) || (x > 6.28))
    		{
    			x=0;
    			xLookAt = 0;
    			break;
    		}
    		x -= 0.1;
    		xLookAt = cos(x) * sin (z);
    		break;
    You're not setting yLookAt, only x. I would write my code like this.

    Code:
       angle-=0.1;
       if(angle<0)
          angle+=6.28;
       xLookAt = cos(angle) * radius;
       yLookAt = sin(angle) * radius;
    I added a radius variable in there, and changed 'x' to the more accurate 'angle', because my programmer conscience was hurting.
    Last edited by Drac; 06-14-2008 at 08:16 PM.

  6. #6
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    Still same effect back and forth .
    Also why do you change the y factor ?

    i wish to rotate around opengl y axis (math z axis).

    I think that it has connection to the fact cos is a par function ( same value for x and -x) .
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Perhaps a little bit of a math primer might help. I recommend buying a book on 3D mathematics from www.amazon.com. www.gamedev.net has several recommendations in their articles and books section that will guide you through the maze of books that are available.

    Given what I've seen here I don't think diving into rotations and translations would even help you at this point.

  8. #8
    Registered User
    Join Date
    Oct 2006
    Location
    UK/Norway
    Posts
    485
    A bit off topic, but still within I think?

    Is there any other way to rotate a mesh then using a matrix?

  9. #9
    Registered User
    Join Date
    Jan 2008
    Posts
    70
    Is there any other way to rotate a mesh then using a matrix?
    Yes. A quaternion would do, and is faster in most cases.
    Still same effect back and forth .
    I'm not too sure what that means, the code I wrote would make the camera rotate in a circle. Given, I haven't read the large amount of code on the lower end of your post.

  10. #10
    Registered User
    Join Date
    Apr 2007
    Posts
    111

    [Fixed] or i hate typos

    First of all thnx for all the great help and special thanks to dimtrios5000 and Jarik D

    The fixed code (the new parts are ):

    Code:
    	xLookAt = z * cos(y) * sin(x);
    	yLookAt = z * sin(y);
            zLookAt = -1 * z * cos(y) * cos(x);
    By that you fix the back and forth rotation
    next for some reason i didn't noticed that i use 6.8 instead of 6.28 (the "glitch" source).
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    That code will gimbal lock.

  12. #12
    Registered User
    Join Date
    Apr 2007
    Posts
    111
    Sorry for asking (not native English speaker ) what is a "gimbal lock " ?

    I tried to google and understand that it has to do with Gyroscopes.
    In this code i had a problem to rotate around and object but to keep the angle to the base the same .
    why Gaos didn't had a wife ?
    http://bsh83.blogspot.com

  13. #13

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Gimbal lock is when one or more axes are mapped onto each other. If you think of 3D rotations as 3 concentric rings, gimbal lock is when two or more of those rings line up. At this point a rotation on one axis will also yield a rotation on another axis. With Euler angles there is no way to avoid gimbal lock.

    In order to correct this you can use quaternions or you can perform axis-angle rotations. Both of these operate on the principle of rotating around an arbitrary axis as opposed to rotating around one of the three cardinal axes.

    Here is Direct3D code to rotate around the x axis. Perhaps others here could convert this to OpenGL code for you.
    Code:
    D3DXVECTOR3 g_vecRight;
    D3DXVECTOR3 g_vecUp;
    D3DXVECTOR3 g_vecLook;
    D3DXVECTOR3 g_vecPos;
    
    //Reset all vectors
    void ResetVectors()
    {
       g_vecRight = D3DXVECTOR3(1.0f,0.0f,0.0f);
       g_vecUp = D3DXVECTOR3(0.0f,1.0f,0.0f);
       g_vecLook = D3DXVECTOR3(0.0f,0.0f,1.0f);
       g_vecPos = D3DXVECTOR3(0.0f,0.0f,0.0f);
    }
    
    //Make all vectors orthonormal to each other - 90 degrees to each other
    void MakeOrtho()
    {
        D3DXVec3Normalize(&g_vecLook,&g_vecLook);
    
        D3DXVec3Cross(&g_vecUp,&g_vecLook,&g_vecRight);
        D3DXVec3Normalize(&g_vecUp,&g_vecUp);
    
        D3DXVec3Cross(&Right,&Up,&Look);
        D3DXVec3Normalize(&Right,&Right);
    }
    
    //Pitch - rotate about the x or right axis
    void Pitch(float radians)
    {
       MakeOrtho();
    
       //Rotation about x is a rotation about the right vector
       D3DXMATRIX matRotX;
       D3DXMatrixRotationAxis(&matRotX,&g_vecRight,radians);
    
       D3DXVec3TransformCoord(&g_vecUp,&g_vecUp,&matRotX);
       D3DXVec3TransformCoord(&g_vecLook,&g_vecLook,&matRotX);
    }
    
    //Get the camera view matrix
    void getViewMatrix(D3DXMATRIX *outMat)
    {
        MakeOrtho();
    
        float x = -D3DXVec3Dot(&g_vecPos, &g_vecRight);
        float y = -D3DXVec3Dot(&g_vecPos, &g_vecUp);
        float z = -D3DXVec3Dot(&g_vecPos, &g_vecLook);
        
        (*outMat)(0,0) = g_vecRight.x;
        (*outMat)(1,0) = g_vecRight.y;
        (*outMat)(2,0) = g_vecRight.z;
        (*outMat)(3,0) = x;
    
        (*outMat)(0,1) = g_vecUp.x;
        (*outMat)(1,1) = g_vecUp.y;
        (*outMat)(2,1) = g_vecUp.z;
        (*outMat)(3,1) = y;
    
        (*outMat)(0,2) = g_vecLook.x;
        (*outMat)(1,2) = g_vecLook.y;
        (*outMat)(2,2) = g_vecLook.z;
        (*outMat)(3,2) = z;
    
        (*outMat)(0,3) = 0.0f;
        (*outMat)(1,3) = 0.0f;
        (*outMat)(2,3) = 0.0f;
        (*outMat)(3,3) = 1.0f;
    }
    
    //Get the object view matrix (transpose of the camera view matrix)
    void getObjectMatrix(D3DXMATRIX *outMat)
    {
        MakeOrtho();
          
        (*outMatrix)(0,0) = g_vecRight.x;
        (*outMatrix)(1,0) = g_vecUp.x;
        (*outMatrix)(2,0) = g_vecLook.x;
        (*outMatrix)(3,0) = g_vecPos.x;//x;
    
        (*outMatrix)(0,1) = g_vecRight.y;
        (*outMatrix)(1,1) = g_vecUp.y;
        (*outMatrix)(2,1) = g_vecLook.y;
        (*outMatrix)(3,1) = g_vecPos.y;//y;
    
        (*outMatrix)(0,2) = g_vecRight.z;
        (*outMatrix)(1,2) = g_vecUp.z;
        (*outMatrix)(2,2) = g_vecLook.z;
        (*outMatrix)(3,2) = g_vecPos.z;//z;
    
        (*outMatrix)(0,3) = 0.0f;
        (*outMatrix)(1,3) = 0.0f;
        (*outMatrix)(2,3) = 0.0f;
        (*outMatrix)(3,3) = 1.0f;
    }
    MakeOrtho() is used because the vectors will become skewed due to floating point imprecision.
    Last edited by VirtualAce; 06-18-2008 at 05:05 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using this as synchronization object
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 03-22-2008, 07:49 AM
  2. circular doubly linked list help
    By gunnerz in forum C++ Programming
    Replies: 5
    Last Post: 04-28-2007, 08:38 PM
  3. Replies: 60
    Last Post: 12-20-2005, 11:36 PM
  4. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  5. A question about constructors...
    By Wolve in forum C++ Programming
    Replies: 9
    Last Post: 05-04-2005, 04:24 PM