glScale and glTranslate

I have a problem with glScale. The code is below, what I basically want to do is to construct some ellipsoids by using glScale on spheres. This is just a test code to learn glScale, but I cant get it done right. I have put glScale in between pushMatrix and popMatrix so that glScale’s scaling ratio does not increase with the loop. But that doesn’t help because glTranslate also interferes with the scaling for some reason, so I tried putting them in push and popmatrix as below. But now my spheres aren’t being translated but they are built on top of each other. If I take glTranslate out of push and pop, then it interferes with glScale. What should really happen here is there should be 4 constructed sphere translated from each other in the x axis by 1.4 and their radii increased to 1.4 of their scale.

The code is in perl language where $ stands for declaration of variable type like int.

Thanks alot


sub DrawGLScene {

    my $newQuad;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
    glLoadIdentity();
	
    glTranslatef(-1.5, 0.0, -6.0); 
    	
	for (1..5){
		
		glPushMatrix();	
		glScaled(1.1, 1.1, 1.1);
		
		glBegin (GL_QUADS);	
			$newQuad = gluNewQuadric ();		
			gluSphere($newQuad,0.5, 32, 16);
		glEnd ;
		
		glPopMatrix();
		
		
		glPushMatrix();	
		glTranslatef(1.4,1.4,1.4);
		glPopMatrix();
		
		
		}

If you don’t want the scale being applied at each loop iteration, why don’t you put it outside of the loop?


		glPushMatrix();	
		glTranslatef(1.4,1.4,1.4);
		glPopMatrix();


when you do that, it has no effects because you save the current modelview matrix pushing it in the matrix stack, then affect this matrix by a translation and finally pop the saved matrix which overwrites the current matrix.

I don’t really understand how you want to transform your scene, maybe you can explain it to us without an opengl code so that we can understand well your problem.

My exact plan is not to use the same scale each time. Suppose that you have a set of ellipsoids with different ratios at different center coordinates. I have all these as an array, I will read them from the array and plot them on openGl to see their positions and sizes. So what is really going to happen is I am going to read ratios $x, $y, $z each time for each ellipsoid. So in that loop glScaled($x, $y, $z) and glTranslatef($x_dir,$y_dir,$z_dir). With each cycle the ellipsoid I am plotting will change and so will these values. That is why I need them in the loop…

Background is, I am writing a molecular modelling program with perl. Up to now I was only planning to give output to known molecular viewer programs but the way I have chosen to represent my molecules are different from those programs so I have decided to do my own simple openGL extension. However I have no what so ever openGL experience and not really the time to go extensively through a book, so I am stringing together pieces of codes I see around. Right now, all I need is to plot some ellipsoids on a space whose coordinates and radii directions, values I know. I will later also need to apply rotations, though first I have to fix this glScaled problem.

And when I don’t do that, it somehow interferes with the scaling, and spheres are scaled more on the x axis. I cant see how glTranslate interferes with glRotate though, I hope openGL is not just progressively multplying matrices. I was hoping that it is not that low-level :stuck_out_tongue:

First if you wanna translate on the x axis, you should do

glTranslatef(1.4, 0, 0); not glTranslatef(1.4, 1.4, 1.4);

Then, what you can do is the following


for (1..5)
  {
    glPushMatrix();
    glScaled(1.1, 1.1, 1.1);
    glBegin(GL_QUADS);
    $newQuad = gluNewQuadric ();
    gluSphere($newQuad,0.5, 32, 16);
    glEnd();
    glTranslatef(1.4, 0.0, 0.0);
    glPopMatrix();
  }


But are you sure you should translate on X axis and not another axis ?

BTW : the code i wrote above is equivalent to your code in the exception of the translate function.

Okay I think I figured how, I of course need to put in the same push, pop block as the scale

for (my $i=0; $i<5; $i++){

	glPushMatrix();	
	
	glScaled(1.1, 1.1, 1.1);
	glTranslatef(0.5*$i,0,0);
	
	glBegin (GL_QUADS);	
		$newQuad = gluNewQuadric ();		
		gluSphere($newQuad,1, 32, 16);
	glEnd ;
	
	glPopMatrix();
	

	
	}

Yup, but i think that doing

push
draw
pop

push
translate
pop

Is the same as

push
draw
translate
pop

(but i might be wrong)

NekoChan, it’s only the same in the sense that both cases are pretty much equivalent to just

draw.

Any matrix operation immediately followed by glPopMatrix is just wasteful.

Instead of hoping and guessing, why don’t you just read the documentation.

Because it was not my intention to add graphic capability to the program but I was going to distribute it as side mathlab script for those who have matlab. I decided to be nice and try to add it to my perl script but I really dont have time to go through extensive openGL documentation, because I also need to keep up with the main parts of program like monte carlo simulations and potential energy calculations. I can only do this part at my free times, I am also reading opengl when ever I have time. Here comes my second question, suppose I denoted the page up key so that when it is pressed the camera zooms out. I am doing it like this:

glutSpecialFunc(&cbSpecialKeyPressed);

is the part for calling key pressed function. And in that function page up is like


sub cbSpecialKeyPressed
{
  my $key = shift;

  if ($key == GLUT_KEY_PAGE_UP)
  {
   $Z_Off -= 1;
   DrawGLScene();
  }
....
}

And I added a seperate glTranslate function that translates in the z axis $Z_off. So each time someone presses (or keeps pressing) page up, the scene is redrawn with a rotated model. That rather seems cumbersome. Although my model is going to be very simple, I wonder if there is a more elegant way of doing it. Also what is the call if I want to change GLUT_KEY_PAGE_UP to mouse buttons or mouse movements? Is it done in the same way?

Thanks

iSina, ust a hint. Don’t do $newQuad = gluNewQuadric () on each loop iteration. As some memory is reserved by the library each time you call it (the garbage collector won’t be able to collect it!), you will run out of memory on some point. It is suficient to declare one global variable for all your quadrics, allocated just once.

Thanks for the hint, you are right. I carried it out of the loop to the top. I also have a question about lighting:

And one more, I have set the color

glColor4f(0.2,0.8,0.6,.95);

and the light as

glLightfv_p(GL_LIGHT1, GL_POSITION, @Light_Position);
glLightfv_p(GL_LIGHT1, GL_AMBIENT, @Light_Ambient);
glLightfv_p(GL_LIGHT1, GL_DIFFUSE, @Light_Diffuse);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);

glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

where arrays are (those starting with @)

my @Light_Ambient = ( 0.1,0.5,0.9,-0.35 );
my @Light_Diffuse = ( 0.7,0.7,0.7,-0.35 );
my @Light_Position = ( 0.0, 0.0, 1.0, 0.0 );

But no light seems to be set. Do I need to put a texture on these ellipsoids? Here is a screen shot: