C Board  

Go Back   C Board > General Programming Boards > Game Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-13-2008, 04:40 PM   #1
Registered User
 
Join Date: Apr 2007
Posts: 112
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;

}
__________________
why Gaos didn't had a wife ?
http://bsh83.blogspot.com

Last edited by jabka; 06-13-2008 at 05:05 PM. Reason: no CODE elemnts
jabka is offline   Reply With Quote
Old 06-13-2008, 04:51 PM   #2
Frequently Quite Prolix
 
dwks's Avatar
 
Join Date: Apr 2005
Location: Canada
Posts: 7,629
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.

Quote:
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, etc.

New project: nort
dwks is offline   Reply With Quote
Old 06-13-2008, 05:58 PM   #3
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
To rotate around something always translate then rotate.
Bubba is offline   Reply With Quote
Old 06-14-2008, 03:41 AM   #4
Registered User
 
Join Date: Apr 2007
Posts: 112
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
jabka is offline   Reply With Quote
Old 06-14-2008, 08:06 PM   #5
Registered User
 
Join Date: Jan 2008
Posts: 65
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.
Drac is offline   Reply With Quote
Old 06-15-2008, 04:30 AM   #6
Registered User
 
Join Date: Apr 2007
Posts: 112
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
jabka is offline   Reply With Quote
Old 06-15-2008, 10:30 AM   #7
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
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.
Bubba is offline   Reply With Quote
Old 06-15-2008, 11:26 AM   #8
Registered User
 
Join Date: Oct 2006
Location: UK/Norway
Posts: 464
A bit off topic, but still within I think?

Is there any other way to rotate a mesh then using a matrix?
h3ro is offline   Reply With Quote
Old 06-15-2008, 02:52 PM   #9
Registered User
 
Join Date: Jan 2008
Posts: 65
Quote:
Is there any other way to rotate a mesh then using a matrix?
Yes. A quaternion would do, and is faster in most cases.
Quote:
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.
Drac is offline   Reply With Quote
Old 06-18-2008, 11:14 AM   #10
Registered User
 
Join Date: Apr 2007
Posts: 112
[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
jabka is offline   Reply With Quote
Old 06-18-2008, 04:29 PM   #11
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
That code will gimbal lock.
__________________
If you aim at everything you will hit something but you won't know what it is.
Bubba is offline   Reply With Quote
Old 06-18-2008, 04:36 PM   #12
Registered User
 
Join Date: Apr 2007
Posts: 112
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
jabka is offline   Reply With Quote
Old 06-18-2008, 05:01 PM   #13
Registered User
 
Join Date: Jan 2008
Posts: 65
http://en.wikipedia.org/wiki/Gimbal_Lock
Drac is offline   Reply With Quote
Old 06-18-2008, 05:02 PM   #14
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,472
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.
__________________
If you aim at everything you will hit something but you won't know what it is.

Last edited by Bubba; 06-18-2008 at 05:05 PM.
Bubba is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
using this as synchronization object George2 C# Programming 0 03-22-2008 07:49 AM
circular doubly linked list help gunnerz C++ Programming 5 04-28-2007 08:38 PM
I believe I've found an official Answer to my Problem (Object Factories) Shamino Game Programming 60 12-20-2005 11:36 PM
Question on l-values. Hulag C++ Programming 6 10-13-2005 04:33 PM
A question about constructors... Wolve C++ Programming 9 05-04-2005 04:24 PM


All times are GMT -6. The time now is 11:17 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22