Dark Bit Factory & Gravity
PROGRAMMING => C / C++ /C# => Topic started by: Jim on April 07, 2008
-
Here's the source of my transition demo. Project file is for VS2008, but it should build pretty much anywhere.
Enjoy,
Jim
-
there was far more to this than i first thought,
as always cheers jim for an insight into your code very handy k+.
-
:bfuck2:
Hi guys. I started to play with this code little bit and added mp3 playback and tried to to control the drawing like this (check the two for loops):
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg )
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
break;
case WM_ERASEBKGND:
return 1;
case WM_CLOSE:
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
return 0;
}
/*void ogl_scale(void)
{
HDC dc;
GLenum err;
err = glGetError();
if (err != GL_NO_ERROR)
{
char tmp[256];
sprintf(tmp, "GLERROR %08X %d\n", err, err);
OutputDebugString(tmp);
}
glScalef(0.1f,0.1f,0.1f);
ogl_draw();
}
*/
//-----------------------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------------------------------------------
static char GLSampleClass[32] = "GLHelixTransitionClass";
int WINAPI WinMain(HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline, int cmdshow)
{
WNDCLASS wc;
int style, exstyle;
RECT rect;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = this_inst;
wc.hIcon = LoadIcon(NULL, (LPCSTR)IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = GLSampleClass;
RegisterClass(&wc);
style = WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION;
exstyle = WS_EX_APPWINDOW;
gameWindow = CreateWindowEx(
0,
GLSampleClass, // class
"Helix",
style,
CW_USEDEFAULT,CW_USEDEFAULT, // init. x,y pos
SCREEN_WIDTH,SCREEN_HEIGHT,
NULL, // parent window
NULL, // menu handle
this_inst, // program handle
NULL // create parms
);
GetWindowRect(gameWindow, &rect);
AdjustWindowRectEx(&rect, style, FALSE, exstyle);
SetWindowPos(gameWindow, NULL, 0,0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE);
ShowWindow(gameWindow, cmdshow);
UpdateWindow(gameWindow);
if (ogl_init() == 0)
{
MessageBox(gameWindow, "Failed Initialising OpenGL", "Failed", MB_OK);
return 0;
}
init_sprite_engine(gameWindow);
init();
quit = 0;
do
{
MSG msg;
while (PeekMessage(&msg,NULL,0,0, PM_NOREMOVE))
{
if (GetMessage(&msg,NULL,0,0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
quit = 1;
break;
}
}
if (!IsPlaying)
{
playmusic();
}
int i;
for (i=0; i<181; i++)
{
ogl_draw();
ogl_flip();
}
GLfloat j;
for (j=0.999f; j>0.0f;j-=0.001f)
{
glScalef(j,j,j);
ogl_draw();
}
} while (!quit);
ogl_shutdown();
return 0;
}
So, there is a problem that the picture doesn't scale to smaller :/ I tried to make decreasing for loop and put that value to glScalef's attributes, but nothing happens...when I put scaling to first for loop, it scaled nicely and showed me smaller picture. So what I want to do is: Spin the the picture 1 time and then stop it (I tweaked the for loop to make it stop nicely after flipping) and when the image is halted, scale it to eternity :D...but something is bugging this code and I don't know what it is. If somebody could give me hint I would be glad :)
- Kypho the beginner
-
Yes, the problem is that glScale/glRotate/glTranslate don't work just on their own. What they do is update the currently active transformation matrix (the one set active by glMatrixMode). After you've set the glScale, ogl_draw comes along and overwrites its effects.
The bit you want to change is at the start of ogl_draw.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0,0,-5000);
glRotatef(c,0,0,1);
You should add your glScale after the glRotate.
btw, since you're not calling ogl_draw/ogl_flip inside the GetMessage loop any more, your app will eventually become unresponsive and crash. You need to pump (Get/Dispatch) messages.
One way you might fix this is to add a parameter to ogl_draw which is the scale, and have two states. One state is called 'rotating' the other called 'scaling'.
Jim
-
Huh, I cannot get working still :(
I made the draw function have a parameter fxType and then some IF things to check what to do :/
bool ogl_draw(bool fxType)
{
static float a=0.0f, b=0.0f,binc=0.86f;
static float c=0;
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
start:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0,0,-5000);
//rotation
if (fxType == false)
{
glRotatef(c,0,0,1);
}
//scale
if (fxType == true)
{
glScalef(scaleamount,scaleamount,scaleamount);
}
c+=0.5;
if (c > 90)
{c = 90, binc=0;
Sprite *img = images[0];
images[0] = images[1];
images[1] = img;
images[0]->flipx();
images[1]->flipx();
images[0]->dirty();
images[1]->dirty();
c=0,b=0,binc=0.86f;
goto start;
}
//glRotatef(a,axis.x,axis.y,0.0);
//a += 1.0f;
glPushMatrix();
a=0;
images[0]->settexture();
glCullFace(GL_FRONT);
for (int x = 0; x < HSEGS; x++)
{
glPushMatrix();
a = b+(b*x)/HSEGS;
if (a>180)a=180;
glRotatef(a,axis.x,axis.y,0.0);
segs[x]->draw();
glPopMatrix();
}
glPopMatrix();
a=0;
images[1]->settexture();
glCullFace(GL_BACK);
for (int x = 0; x < HSEGS; x++)
{
glPushMatrix();
a = b+(b*x)/HSEGS;
if (a>180)a=180;
glRotatef(a,axis.x,axis.y,0.0);
segs[x]->draw();
glPopMatrix();
}
b=b+binc;
return fxType;
}
and then in the while
do
{
MSG msg;
while (PeekMessage(&msg,NULL,0,0, PM_NOREMOVE))
{
if (GetMessage(&msg,NULL,0,0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
quit = 1;
break;
}
}
if (!IsPlaying)
{
playmusic();
}
int i;
for (i=0; i<181; i++)
{
ogl_draw(false);
ogl_flip();
}
float j;
for (j=0.999; j>0.0;j-=0.001)
{
float scaleamount = j;
ogl_draw(true);
}
} while (!quit);
so it should have scaleamount from here and also the bool parameter for scale/rotate choosing.
Jim wrote: btw, since you're not calling ogl_draw/ogl_flip inside the GetMessage loop any more, your app will eventually become unresponsive and crash. You need to pump (Get/Dispatch) messages.
I don't understand this...those for loops are on the place where was earlier the ogl_draw() function and flip function too :P How this is not inside GetMessage loop? I understand the for loop is making this problem but I don't see any way to fix it. Cos I need some way to control the lenght of that flipping and as I see it the only way is with for loop(=?)
I also heard from my sister's husband that it would be wise to make a new Draw class for this and then make two "virtual" functions that have same name for example effect, one for scaling and one for rotating which you would use in the draw function by calling the effect function of wanted type...(but as you might know already, this was way beyond my skill level now, and I didn't quite understand it :P)...
-Kypho the beginner
-
I also heard from my sister's husband that it would be wise to make a new Draw class for this and then make two "virtual" functions that have same name for example effect, one for scaling and one for rotating which you would use in the draw function by calling the effect function of wanted type
That can be a good solution for some problems, but this isn't one of them. virtual functions are part of C++ that let you implement the same thing for objects that have the same base class, for instance.
class shape
{
protected virtual void draw();
}
class square : shape
{
protected virtual draw()
{
//code to draw a square
}
}
class triangle : shape
{
protected virtual draw()
{
//code to draw a triangle
}
}
Then, any time someone hands you a 'shape' object, you can call shape->draw() and it will know how to draw that shape whether it's a triangle or a square.
btw, since you're not calling ogl_draw/ogl_flip inside the GetMessage loop any more, your app will eventually become unresponsive and crash. You need to pump (Get/Dispatch) messages.
I don't understand this...those for loops are on the place where was earlier the ogl_draw() function and flip function too How this is not inside GetMessage loop? I understand the for loop is making this problem but I don't see any way to fix it. Cos I need some way to control the lenght of that flipping and as I see it the only way is with for loop(=?)
OK, they were inside the loop, but if you draw 1180 frames, that's over 20seconds you are not responding to messages, and Windows will complain.
Here is roughly how I would do it:
//setup
#define ROTATING 1
#define SCALING 2
#define FINISHED 3
int state = ROTATING;
float scale = 1.0f;
float angle = 0.0f;
int frame = 0;
...
...
do
{
MSG msg;
while (PeekMessage(&msg,NULL,0,0, PM_NOREMOVE))
{
if (GetMessage(&msg,NULL,0,0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
quit = 1;
break;
}
}
if (state == ROTATING)
{
angle += 0.5f;
frame++;
if (frame > 180)
state = SCALING;
}
else if (state == SCALING)
{
scale -= 0.001f;
frame++;
if (frame > 180 + 1000)
state = FINISHED;
}
ogl_draw(angle, scale);
ogl_flip();
} while (!quit);
bool ogl_draw(float angle, float scale)
{
...
glTranslatef(0,0,-5000);
glRotatef(angle,0,0,1);
glScalef(scale,scale,scale);
}
I think that will work.
On a separate note, you wrote this
for (j=0.999; j>0.0;j-=0.001)
{
float scaleamount = j;
ogl_draw(true);
}
and then inside ogl_draw() you had this
glScalef(scaleamount,scaleamount,scaleamount);
I guess you must also have added a global variable line at the top of the code like this
float scaleamount;
The problem is these two scale amounts are not the same scaleamount. The one in the for loop only lives inside the for loop. The other one would be unaffected. This is called 'scoping'. If you'd like to understand that more then give me a shout. :)
Jim
-
Hi Jim.
Thanks for your quick response and help :) I really appreciate you're willing to help beginner like me. I will try that kind of code later tonight or tomorrow :) and I would of course like to hear about that scaleamount variable difference (scoping it was) more...always willing to learn more.
One thing, is it easy to build some kind of timer thing to this program, for example I would like to rotate for 2 sec (and in 2sec the pic flips 1 time) and then use 3 secs for scale (and in 3 secs the pic scales away)? It could be cool to keep in "the rhythm" somehow :P but anyway, thanks and I will be back ;)
- Kypho the beginner
-
The timing is easy. Every frame is 1/60th of a second. So if you keep a counter of frames (frame++ in my example) then every 60 counts is 1 second.
Jim
-
This some APRON/NEHE example code
I wonder how I could put this code to the transition code, cos simply putting this function to the program and then call it doesn't do the trick :(
///NEW CUBE
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();
//NEW//////////////////NEW//////////////////NEW//////////////////NEW/////////////
glTranslatef(0.0f, 0.0f,-7.0f); // Translate Into The Screen 7.0 Units
glRotatef(rotqube,0.0f,1.0f,0.0f); // Rotate The cube around the Y axis
glRotatef(rotqube,1.0f,1.0f,1.0f);
glBegin(GL_QUADS); // Draw The Cube Using quads
glColor3f(0.0f,1.0f,0.0f); // Color Blue
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)
glColor3f(1.0f,0.5f,0.0f); // Color Orange
glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)
glColor3f(1.0f,0.0f,0.0f); // Color Red
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)
glColor3f(1.0f,1.0f,0.0f); // Color Yellow
glVertex3f( 1.0f,-1.0f,-1.0f); // Top Right Of The Quad (Back)
glVertex3f(-1.0f,-1.0f,-1.0f); // Top Left Of The Quad (Back)
glVertex3f(-1.0f, 1.0f,-1.0f); // Bottom Left Of The Quad (Back)
glVertex3f( 1.0f, 1.0f,-1.0f); // Bottom Right Of The Quad (Back)
glColor3f(0.0f,0.0f,1.0f); // Color Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)
glColor3f(1.0f,0.0f,1.0f); // Color Violet
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)
glEnd(); // End Drawing The Cube
rotqube +=0.9f; // Increase Angle
//NEW//////////////////NEW//////////////////NEW//////////////////NEW/////////////
return TRUE; // Keep Going
}
/////END OF NEW CUBE
Then I have the following in my main
if (state == FINISHED)
{
DrawGLScene();
}
.-Kypho the beginner
-
You haven't set up any model or view matrix so the object will be about 2 pixels in size.
Try adding
glScale(100,100,1) after the glRotates.
Jim
-
Hi.
I put now glMatrixMode(GL_MODELVIEW); and glPushMatrix(); and something happened, it seems that it draws my earlier texture (the picture which kept flipping) but colored it with purple :P It rotates that picture somehow, but I cannot see the cube yet there. I wonder how could I set the texture and get that thing more cubish, cos now it seems that it makes the flipping picture there and uses that old data (rotates it then and so on)...I would like to "clear" all the old data away or something :)
- Kypho the beginner
-
You most certainly don't want a glPushMatrix call unless you have a glPopMatrix call to match it. Each Push stores the current matrix on a stack, so you can then change it, draw something with the new matrix, and 'Pop' back to the original one. The stack is usually only 8 deep, so you will get errors very quickly if your Push and Pops don't match.
Have you read any OpenGL documentation? There's some great stuff here
http://www.sgi.com/products/software/opengl/tech_info.html (http://www.sgi.com/products/software/opengl/tech_info.html)
You won't fund a 'reset' function. OpenGL works as a state based system. ie. There is a current value of everything in the system - the current texture, the current uv, the current 3d position, the current colour, the current zbuffer culling method, etc, etc. Each command in OpenGL affects one of these states. If you want to reset, you have to re-write lots of states back to the way you want them. That's why it can be hard to combine two people's OpenGL codes - they rely on having a different state set at the start.
Jim
-
hmm, seems to be complicated-..I take closer look of this later when I have free time :) that document will come handy for sure.
- Kypho the beginner