Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: Jim on April 07, 2008

Title: Transition demo source code
Post 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
Title: Re: Transition demo source code
Post by: ninogenio on April 08, 2008
there was far more to this than i first thought,

as always cheers jim for an insight into your code very handy k+.
Title: Re: Transition demo source code
Post by: kypho on January 22, 2009
 :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):

Code: [Select]
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
Title: Re: Transition demo source code
Post by: Jim on January 22, 2009
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.
Code: [Select]
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
Title: Re: Transition demo source code
Post by: kypho on January 25, 2009
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 :/

Code: [Select]
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

Code: [Select]
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.

Quote
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
Title: Re: Transition demo source code
Post by: Jim on January 26, 2009
Quote
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.

Code: [Select]
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.

Quote
Quote
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:

Code: [Select]
//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);

Code: [Select]
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
Code: [Select]
for (j=0.999; j>0.0;j-=0.001)
{
float scaleamount = j;
ogl_draw(true);
}
and then inside ogl_draw() you had this
Code: [Select]
glScalef(scaleamount,scaleamount,scaleamount);
I guess you must also have added a global variable line at the top of the code like this
Code: [Select]
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



Title: Re: Transition demo source code
Post by: kypho on January 26, 2009
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
Title: Re: Transition demo source code
Post by: Jim on January 26, 2009
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

Title: Re: Transition demo source code
Post by: kypho on January 27, 2009
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 :(

Code: [Select]
///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
 
Code: [Select]
 
if (state == FINISHED)
  {
  DrawGLScene();
  }


.-Kypho the beginner
Title: Re: Transition demo source code
Post by: Jim on January 27, 2009
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

Title: Re: Transition demo source code
Post by: kypho on January 29, 2009
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
Title: Re: Transition demo source code
Post by: Jim on January 29, 2009
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
Title: Re: Transition demo source code
Post by: kypho on January 30, 2009
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