PDA

View Full Version : Fast Spinning Objects, and Shading



Durandal
12-09-2003, 05:10 AM
Hi.

For my final year Computer Science project I need to produce a simulator for a new kind of 3d display. I'm doing this using OpenGL (obviously http://www.opengl.org/discussion_boards/ubb/wink.gif). I have a few questions.

1. I need to animate accurately a square/circular screen spinning at 30hz inside the display. Now I can do so, with incrementing the rotation angle with each idle call of the function, but this either doesn't get the speeds I require, or if I rotate by 150 degrees each frame(which I figured out would get me roughly 30hz at 72 fps)the rotation is anything but smooth. Is there any way to make objects spin very fast and smoothly? (or is there any way I can fake it? It is very important that the screen not only appears to spin smoothly, but actually does go through every degree.)

2. Currently, the OpenGL output consists of the spinning screen, a central glass sphere, and some cones around the sphere representing the beam sources. I've set up lights that light up half the sphere, and leave the other half semi-unlit - however, the cones aren't affected at all by the light. They're flat shaded (not GL_FLAT) without the proper shading. I do have webspace somewhere, but I'm in uni now and I don't have the details to upload any pics at the moment.


The code for the objects and lighting is below.




void draw_cones(float srad, float rotang, int no_cones){ //draws all beam sources at specified angles
float rrotang = 0.0; //(remember specified distances/size)
while (no_cones != 0){
glPushMatrix();
glRotatef(rrotang, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, srad-0.1);
glColor4f(1, 1, 1, 0.5);
glutSolidCone(0.25, 0.6, 20.0, 10.0);
glPopMatrix();

rrotang = rrotang + rotang;
no_cones--;
}
}


void draw_screen(){
glPushMatrix();
glRotatef(axis_rot, 0, 1, 0);

glPushMatrix(); //currently fixed screen size
glColor4f(0.5, 0.5, 0.5, 0.2);
glScalef(1, 1, 0.02);
glutSolidCube(0.5);
glPopMatrix();

glPushMatrix(); //screen shaft (distorted cube)
glColor4f(0.5, 0.5, 0.5, 1);
glScalef(1, 50, 0.5);
glTranslatef(0, 0.002, 0);
glutSolidCube(0.015);
glPopMatrix();
glPopMatrix();

axis_rot += 150;
}


void display(void){
float srad = 0.4; //main sphere radius
float rotang = 90.0; //rotation angle between beam sources
int no_cones = 2; //number of beam source cones

fps();

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

camerapos(srad);

glLoadIdentity();
gluLookAt(0.0,0.0,0.0, //camera direction
cx,cy,cz, //camera position
0.0,1.0,0.0); //up vector

draw_screen();

glColor4f(1, 1, 1, 0.2);
glutSolidSphere(srad, 40.0, 40.0);
glColor4f(1, 1, 1, 0.2);
glutSolidSphere(srad-wall_thickness, 40.0, 40.0);


draw_cones(srad, rotang, no_cones);
glTranslatef(0.0, 0.0, 5.0);

glFlush();

glPopMatrix();

glutSwapBuffers();
}


void lighting(){
GLfloat light_pos[] = {0.0, 0.0, -1.0, 0.5};
GLfloat light_amb[] = {0.2, 0.2, 0.2, 0.2};

glLightfv(GL_LIGHT0,GL_POSITION, light_pos);
glLightfv(GL_LIGHT0,GL_AMBIENT, light_amb);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}


void init(){
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}


Thanks.

[This message has been edited by Durandal (edited 12-09-2003).]

tku
12-09-2003, 10:03 AM
Hi, don't really understand what you are doing but anyway. http://www.opengl.org/discussion_boards/ubb/smile.gif
So you got an object witch spins in your scene with really fast speed. You needed a spin rate of 30Hz and that would make 30*360Degrees. If you turn your object 1 degree/frame you would need to have 10800 frames/second and that would not be nothing you would get.
So you need something else to make it look like it is spinning very fast. Motion blur would be solution if you were making animation, but i guess it needs to be realtime.
You could start with lower spin rates as eye isn't best thing to say how fast something spins and you could fake it with some kind of blurring.

And you had some problem with your lights. You have only enabled ambient lighting and you wanted pointlight. Use glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); to get spotlight.

Durandal
12-09-2003, 11:05 AM
Hi, thanks for your reply.

You've got the gist of it http://www.opengl.org/discussion_boards/ubb/smile.gif. The problem is, is that I have to make a 'scientific' simulation of one of these displays, that will allow the user to adjust dimensions/attributes of the display, then various things would be calculated realistically for the new configuration. This involves the simulation of firing electron beams onto the spinning screen at all addressable points, making a note of it's angle, and colouring that pixel accordingly (as well as more things). Maybe actually spinning it that fast won't be necessary, maybe motion blurring would produce the correct output. Something to have a play with I suppose http://www.opengl.org/discussion_boards/ubb/wink.gif

Regarding the lighting, I've added the diffuse line (with a set of values for light_diffuse), however it only makes the general scene darker without fixing the problem. This (http://cerby.no-ip.com/~durandal/GLOutput.gif) is a screenshot of my basic output looking down on the display, using simple ambient lighting as it's brighter (no real difference in shading though). You can see how the cones should be shaded, but are not.

Durandal
12-10-2003, 02:44 AM
Another thing - what would be the best way of achieving the motion blur? I've read techniques that use glAccum (slow), and methods that essentially take screenshots and use them as the motion trail textures (fast), but I cannot see how that can be applied to only a single object in a scene. Got any ideas?

Edit - realised I should've searched these boards first... Got some ideas.... kinda...

[This message has been edited by Durandal (edited 12-10-2003).]

tku
12-10-2003, 07:54 AM
I think lighting problem is caused by blending. .. if you render cone with front and back faces and look cone from side it would look flat shaded because it's basicly round object and lighting affect both front and back faces result looks flat.
Try if glPolygonMode(GL_FRONT,GL_FILL); affects rendering... worked in my test.

To motionblurring problem i don't have any clever ideas, but if that plane inside sphere is the only object rotating you could render 10 planes with different rotations and 10% visibility.

Durandal
12-10-2003, 09:37 AM
Interesting idea. the multiple planes does looks better, and motion blurring would make it look even more so - it'd be interesting to see what effect that would have on the simulation side of things.

I tried putting that glPolygonMode in several places, my init function, and the main render function, with no effect. I've solidified the cones to test (i.e. alpha of 1) and it looks exactly like it would if there were no lights in the scene. Ok, has anyone done any VRML coding? (we've just finished a coursework using it http://www.opengl.org/discussion_boards/ubb/rolleyes.gif ) For 'lighting' you have to group all the objects you'd like to be affected by the lighting together. Do you have to do something similar in OpenGL?

Thanks for your help guys.

[This message has been edited by Durandal (edited 12-10-2003).]

ZbuffeR
12-10-2003, 10:00 AM
For 'lighting' you have to group all the objects you'd like to be affected by the lighting together. Do you have to do something similar in OpenGL?
Not exactly the same, but sort of (taken from the html man pages) :

Lighting calculation is enabled and disabled using glEnable and glDisable
with argument GL_LIGHTING. When lighting is enabled, light sources that
are enabled contribute to the lighting calculation. Light source i is
enabled and disabled using glEnable and glDisable with argument GL_LIGHTi.

So you can :
glEnable(GL_LIGHTING);
glEnable(Gl_LIGHT0);
<draw polygons affected only by light0>
glEnable(Gl_LIGHT1);
<draw polygons affected by both light0 and light1>
glDisable(Gl_LIGHT0);
<draw polygons affected only by light1>

etc...

For motion blurring, the method you use is probably the simpler for your case. You may check my webpage, with my tries to do that in fullscreen (a bit slower though) : http://www.chez.com/dedebuffer/
To blur more, either you draw more samples until you can't see the individual quads (but you will have a lower framerate), or you may draw an 'time-extruded' screen, see it like two opposite 3D piecharts. Well its hard to describe, i will try to do a picture later. Depending on your scene (i.e. if you have a texture on the screen), it may not look good.

Your screenshot helped me a lot to understant what you need, can you post more pictures and schematics, even if handdrawn ?

For your lighting problem, though, I don't understand if the screeshot you gave is only with ambient or with diffuse too.

[This message has been edited by ZbuffeR (edited 12-10-2003).]

Durandal
12-10-2003, 10:17 AM
Ok, I'll have a look at your code, thanks http://www.opengl.org/discussion_boards/ubb/smile.gif

As for the lighting, I had it enclosed within glEnable functions. I tried adding a new light source specifically for the cones, and even disabling all light sources for them. The actual code I've saved is almost identical to the lighting code I've posted above, with an added GL_DIFFUSE for light0.

Disabling the lightsources resulted in the cones getting darker, so it shows that the light is reaching the cones, it's just not shading them. How annoying...

Regarding the motion blur, I currently don't plan to have any texturing, so that should be ok. As for pies, well, I don't really follow you!

Durandal
12-10-2003, 10:24 AM
The above screenshot was just ambient lighting.

Here's a screenshot using diffuse lighting: Diffuse (http://cerby.no-ip.com/~durandal/diffuse.jpg)

Both is hardly different: Ambient and Diffuse (http://cerby.no-ip.com/~durandal/amb&diff.jpg)


It doesn't really matter (yet) about lighting the spinning plane, but the cones need to be lit properly. Eventually I'd like to get the effect of glass on the sphere and cones (I currently have two spheres, one slightly smaller than the other, to simulate thickness).

As for schematics, what exactly do you mean?

[This message has been edited by Durandal (edited 12-10-2003).]

ZbuffeR
12-10-2003, 12:45 PM
The above screenshot was just ambient lighting.
On GLOutput.gif, how come the sphere apears lit then ??

To display the glass sphere better, try to draw the inner sphere with reversed normals ('inside out'). You can do that easily by putting a glScalef(-1.0,-1.0,-1.0);
before you draw it. Maybe you will need to mess with glCullFace() and glFrontFace() as well.

Forget 'schematics', probably a french false friend.

Here is a picture of what I meant by "piecharts", actually more described as time extrusion. I does not appear on the picture, but the smaller face is indeed a part of the cylinder of revolution created by the rotaion. Gee, it's hard to describe ;D
http://www.chez.com/dedebuffer/time_extruded_screen.jpg

For your lighing problems, it may have something to do with normals, try to do glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMALS);
at the very begining of your prog.
And try to find out why the sphere apears lit, there may be something there. Or put you whole source code on the web...

[This message has been edited by ZbuffeR (edited 12-10-2003).]

Durandal
12-10-2003, 03:13 PM
Regarding GLOutput.gif.... I honestly don't know! I'm sure I was using ambient lighting! (i.e. I used GL_POSITION and GL_AMBIENT and that was it)

I've given that inner sphere idea a go, which is quite nice! Eventually I aught to put on specular effects, but that can wait for the time being.

It took a few goes, but I now thing I understand what you mean with the whole 'pie' thing. If the screen was 'time extruded' 90 degrees, it would look like one of those Diablo juggling-ball-like toy things, and if it were extruded 180 degrees it would form a solid cylinder. While that would result in a smoother animation, it wouldn't quite be applicable for my project.

I thought the lighting problem would be down to normals, although glEnable(GL_AUTO_NORMALS) doesn't work, but apparently glEnable(GL_NORMALIZE) does the same thing. I can't figure it out, so I present the whole code for the world to see http://www.opengl.org/discussion_boards/ubb/smile.gif.

My Code in Text file form! (http://cerby.no-ip.com/~durandal/whole_code.txt)

Thanks again for your help.

ZbuffeR
12-10-2003, 04:17 PM
Just put this line right after your glutSolidCone() :



glutSolidSphere(0.1, 40.0, 40.0); // lit correctly !!


You will see that your light apear to stick to each of your objects. You have a projection/modelview matrix problem. Try to set glMatrixMode(GL_PROJECTION); before setting the camera, then place your light and glMatrixMode(GL_MODELVIEW); then place your objects.
I think that you should find yourself the right solution now (hint : http://www.opengl.org/discussion_boards/ubb/Forum2/HTML/014805.html ).

By the way, it is GL_AUTO_NORMAL (no 'S'), but by reading the glut doc, the normals are always set by the glutSolid* commands.


[This message has been edited by ZbuffeR (edited 12-10-2003).]

Durandal
12-14-2003, 05:59 AM
Hi.

Sorry about the delay - I've now gone home for the Christmas 'holidays'.

I've given the lighting idea of yours a go - and it's now sorted http://www.opengl.org/discussion_boards/ubb/biggrin.gif

The lighting seems to come from a different direction, but at least they're shaded!

Thanks for your help. I'll try to implement the motion blurring in a few days - time for a well-earned rest after over 3 months of Uni hell! http://www.opengl.org/discussion_boards/ubb/wink.gif