Global Variables Not Truly Global?

I'm working on this graphics application (DirectX Direct3D Ratained-Mode). My goal at this point is to make it possible to use the numeric keypad keys to move the "camera" around the scene and to retate the "camera" as needed.

First, I added to the WindowProc() function to have it read the numeric keypad keys via a switch case method.

First, I tried to declare (near the top of the program outside of any function blocks) nine variables to store the x, y, z vectors for the camera frame position rotation and vertical orientation. Then, in the switch case, I tried to adjust these variables according to which numpad key ( 0-9 ) was pressed.

Please bear in mind that this code segment is only oneout of nine cases I attempted to program. Assuming that global variables could be read by any function, I then placed the following lines in the function that sets the positions of the frames.

Now, assuming that the campos, camrot, and camvrt variables are truly global, this method should have worked, but it didn't.

My second attempted method was trying to define a global variable (again, near the top of the program outside any functions) named "keyindex" which was supposed to be assigned an integer value corrosponding to which numpad key ( 0-9 ) was pressed.

I added the appropriate code to the same switch-case statements in the WindowProc() and added some statements in the SetPositions function to adjust the nine camera movement variables mentioned above according to the value of keyindex. However, this method, too, failed.

My third attempted method was to try to globally define and then use a pointer (*p_keyindex) to point to the keyvalue. No good.

My fourth attempted method was to try to define a character variable and use it. Again, no good.

My fifth attempted method was to try to "tap" into the message queue and have the message copied into a MSG structure named keypress and go from there, having the SetPosition function then read the values in that keypress structure. No success here, either.

My sixth attempted method was to try to add the keyindex and/or keypress MSG structure member or two to the function prototype and the function definition to show that these were supposed to be passed among these functions from one to the other as appropriate. No dice.

In desparation, I also added memset calls to the InitApp function to initialize these global variables and the structure.

So far, I've spent three to four days and nights trying to figure out and/or research in the documentation a way out of this difficulty.

Bottom line? Unless I'm missing something, one would think that if a variable(s) is(are) defined globally, they are supposed to be able to be used and updated anywhere in the file in which they appear after their declaration. And you're supposed to be able to "see" and use the values regardless of what function your program is in at any given time.

I tested to see if the keys were being read by placine a call to the CleanUp() function which releases all objects and variables and causes the application to terminate. In each tested case, this worked. So, the keys DO appear to be being scanned okay.

Also, I deliberately set the index variable to a value in the SetPositions() function to see if the adjustments would work there. Again, success to some degree. Having eliminated these two steps, the only one left is the middle step, "copying" the value called for from the WindowProc function to the SetPositions() function so as to be able to move the camera with the keypad keys.

This is maddening to me because (at least from my perspective and unless I'm missing something) global variables are supposed to be visible in the file.

Thank you very much in advance for any help you may be able to offer.

Mike

PS. Also, I'm not sure (and this may have some bearing on what I'm trying to do) whether the program cycles through the whole program for every frame update or whether it starts at Winmain(), then calls InitApp, and then cyles through the various rendering functions over and over again until the application is shut down.

Also, I'm not sure if DirectInput is the answer. This particular version of DirectInput appears to be only for joystick input.

Comments

: I'm working on this graphics application (DirectX Direct3D Ratained-Mode). My goal at this point is to make it possible to use the numeric keypad keys to move the "camera" around the scene and to retate the "camera" as needed.: : First, I added to the WindowProc() function to have it read the numeric keypad keys via a switch case method. : : First, I tried to declare (near the top of the program outside of any function blocks) nine variables to store the x, y, z vectors for the camera frame position rotation and vertical orientation. Then, in the switch case, I tried to adjust these variables according to which numpad key ( 0-9 ) was pressed. : : switch(msg): {: case WM_KEYDOWN:: {: switch(wparam): {: VK_NUMPAD4:: campos_x = campos_X - 0.1;: break;: }: }: : Please bear in mind that this code segment is only one: out of nine cases I attempted to program. Assuming that global variables could be read by any function, I then placed the following lines in the function that sets the positions of the frames.: : lpCamera->SetPosition(lpScene, D3DVAL(campos_x), D3DVAL(campos_y), : D3DVAL(campos_z));: : lpCamera->SetOrientation(lpScene, D3DVAL(camrot_x), : D3DVAL(camrot_y), D3DVAL(camrot_z), D3DVAL(camvrt_x), : D3DVAL(camvrt_y, camvrt_z));: : Now, assuming that the campos, camrot, and camvrt variables are truly global, this method should have worked, but it didn't.: : My second attempted method was trying to define a global variable (again, near the top of the program outside any functions) named "keyindex" which was supposed to be assigned an integer value corrosponding to which numpad key ( 0-9 ) was pressed.: : I added the appropriate code to the same switch-case statements in the WindowProc() and added some statements in the SetPositions function to adjust the nine camera movement variables mentioned above according to the value of keyindex. However, this method, too, failed.: : My third attempted method was to try to globally define and then use a pointer (*p_keyindex) to point to the keyvalue. No good.: : My fourth attempted method was to try to define a character variable and use it. Again, no good.: : My fifth attempted method was to try to "tap" into the message queue and have the message copied into a MSG structure named keypress and go from there, having the SetPosition function then read the values in that keypress structure. No success here, either.: : My sixth attempted method was to try to add the keyindex and/or keypress MSG structure member or two to the function prototype and the function definition to show that these were supposed to be passed among these functions from one to the other as appropriate. No dice.: : In desparation, I also added memset calls to the InitApp function to initialize these global variables and the structure.: : So far, I've spent three to four days and nights trying to figure out and/or research in the documentation a way out of this difficulty.: : Bottom line? Unless I'm missing something, one would think that if a variable(s) is(are) defined globally, they are supposed to be able to be used and updated anywhere in the file in which they appear after their declaration. And you're supposed to be able to "see" and use the values regardless of what function your program is in at any given time.: : I tested to see if the keys were being read by placine a call to the CleanUp() function which releases all objects and variables and causes the application to terminate. In each tested case, this worked. So, the keys DO appear to be being scanned okay.: : Also, I deliberately set the index variable to a value in the SetPositions() function to see if the adjustments would work there. Again, success to some degree. Having eliminated these two steps, the only one left is the middle step, "copying" the value called for from the WindowProc function to the SetPositions() function so as to be able to move the camera with the keypad keys.: : This is maddening to me because (at least from my perspective and unless I'm missing something) global variables are supposed to be visible in the file.: : Thank you very much in advance for any help you may be able to offer.: : Mike: : PS. Also, I'm not sure (and this may have some bearing on what I'm trying to do) whether the program cycles through the whole program for every frame update or whether it starts at Winmain(), then calls InitApp, and then cyles through the various rendering functions over and over again until the application is shut down.: : Also, I'm not sure if DirectInput is the answer. This particular version of DirectInput appears to be only for joystick input.: : By the way, I'm using Microsoft's Developer Studio '97 Visual C++ 5.0 development environment.: : Thanks again.:

It is really not clear what is happening here; you say "it fails", "it is no good" etc. What fails, what is not good?

And yes, global variables can be from accessed anywhere in the program. The only time you will have problems with their access is when you are doing multithreading and need to protect them with semaphores.

I assume you have tested the program in a debugger and checked the values of those globals before the function call? And that the globals are assigned values from the WM_KEYDOWN in the first place?

One thing that I think that you should look over your code very carefully for is multiple definitions of the same variable. I noticed that in the code you posted you have campos_x and campos_X. C/C++ is case sensitive.

Also are you sure that the code that is supposed to move the camera around is correct and works?

: One thing that I think that you should look over your code very carefully for is multiple definitions of the same variable. I noticed that in the code you posted you have campos_x and campos_X. C/C++ is case sensitive.: : Also are you sure that the code that is supposed to move the camera around is correct and works?:

Hi, Frank:

Thank you very much for taking the time and trying to lend me a hand on this. I truly appreciate it.

To be quite honest, the typo in the code was due to the fact that I vas extremely tired and fighting the "heavy eyelids" when I posted my original message. Thus, I'm not surprised I missed the uppercase X to which you referred.

In answer to your other question about whether the code works, I'm still experimenting around with it to see just how it works. However, I believe that I can say with a fair degree of certainty that the answer is "yes." I say that because, in order to see if this part of it was indeed working, I deliberately assigned a high value to the adjustment in order to cause the SetPosition function to move the camera to the left ( "campos_x = campos_x - 50.0; ). This worked. The funny thing is, though, that it only moved the camera once and did not keep moving it, which in part led to one of the postscripts of my original message about just how the flow control in this application works. The more I think about it, it could be that it only positions the objects in the scene once. I don't know for sure -- I'm kind of "grasping at straws" at the moment.

As far as the multiple definitions go, it has been my experience that if you redefine a variable, the compiler will generate an error message. Also, in the documentation, I think (I'm not sure, though) I read something about "referencing declarations" which simply help to make a variable visible in more than one area. It could be, though, that somehow the variables are being reset to zero somehow upon entry of the SetPosition function. In any case, for some reason, the values set in the WinProc function by the keypresses are not being transmitted to the SetPositions function.

I'll look over my code again and see if there are any obvious errors that I'm missing.

Thank you again for taking the time to read and answer my original message.

: : : It is really not clear what is happening here; you say "it fails", "it is no good" etc. What fails, what is not good?: : And yes, global variables can be from accessed anywhere in the program. The only time you will have problems with their access is when you are doing multithreading and need to protect them with semaphores. : : I assume you have tested the program in a debugger and checked the values of those globals before the function call? And that the globals are assigned values from the WM_KEYDOWN in the first place?:

Hi, Lundin:

Thank you very much for taking the time to try to assist me in this difficulty. I appreciate it a lot.

I think the best way to answer your question regarding what is supposed to be happening is to try to explain it a little better. When I wrote my original message I was extremely tired and therefore I did not explain the situation well enough. Now that I'm not fighting the "heavy eyelids" so bad, maybe I can do better this time.

As I stated in my original message, the application in question is a DirectX Direct3D Retained Mode application which draws 3-dimensional objects. The particular task that I'm trying to accomplish is that of being able to move and rotate the camera around the scene and any objects therein. My eventual goal is to be able to program various items such as buildings, etc. and being able to virtually "walk" around and inside of them.

Once I get these modes working, I'll add modes to move the camera up and down vertically along the Y axis.

The intended design is to press the numpad keys (0-9) and adjust the values of the camera movement variables in order to accomplish the task. For this to happen, the following must occur:

1) User presses desired key.

2) Appropriate values are assigned to keyindex variable(s) depending on which key is pressed. (case VK_NUMPAD_1 - case VK_NUMPAD9 -- value assinged according to which key is pressed. (1-9)

3) Values in keyindex variables are then accessed from SetPositions function. Have tried to use if and switch-case statements here.

4) Adjustments are made to camera movement/rotation variables according to the value of the keypress variable updated in the WinProc function.

5) The camera is repositioned according to the adjusted and updated values of the camera position/rotation variables.

Somewhere along this chain of events, the values stored in the key index variable(s) according to the keypresses in the WinProc() function are not able to be accessed by the SetPositions() function.

I hope this better answers your question about what is supposed to happen and is not happening. I apologize for not providing sufficient detail in my original message.

As far as the debugger goes, yes I have tried running the debugger. Part of the problem is, though, that I'm not sure yet just when to press the numpad keys to cause an adjustment to the key index variable and thus to monitor whether that adjustment is being performed. I'll try to step through the program again and see if I can learn anything that way.

I will also research the matter of "multithreading" and "semaphores" to see what they are and whether they have any bearing on what I'm trying to do.

Again, thank you very much for taking the time to read and answer my original message.

: : : It is really not clear what is happening here; you say "it fails", "it is no good" etc. What fails, what is not good?: : And yes, global variables can be from accessed anywhere in the program. The only time you will have problems with their access is when you are doing multithreading and need to protect them with semaphores. : : I assume you have tested the program in a debugger and checked the values of those globals before the function call? And that the globals are assigned values from the WM_KEYDOWN in the first place?:

Hi, Lundin:

Thank you very much for taking the time to try to assist me in this difficulty. I appreciate it a lot.

I think the best way to answer your question regarding what is supposed to be happening is to try to explain it a little better. When I wrote my original message I was extremely tired and therefore I did not explain the situation well enough. Now that I'm not fighting the "heavy eyelids" so bad, maybe I can do better this time.

As I stated in my original message, the application in question is a DirectX Direct3D Retained Mode application which draws 3-dimensional objects. The particular task that I'm trying to accomplish is that of being able to move and rotate the camera around the scene and any objects therein. My eventual goal is to be able to program various items such as buildings, etc. and being able to virtually "walk" around and inside of them.

Once I get these modes working, I'll add modes to move the camera up and down vertically along the Y axis.

The intended design is to press the numpad keys (0-9) and adjust the values of the camera movement variables in order to accomplish the task. For this to happen, the following must occur:

1) User presses desired key.

2) Appropriate values are assigned to keyindex variable(s) depending on which key is pressed. (case VK_NUMPAD_1 - case VK_NUMPAD9 -- value assinged according to which key is pressed. (1-9)

3) Values in keyindex variables are then accessed from SetPositions function. Have tried to use if and switch-case statements here.

4) Adjustments are made to camera movement/rotation variables according to the value of the keypress variable updated in the WinProc function.

5) The camera is repositioned according to the adjusted and updated values of the camera position/rotation variables.

Somewhere along this chain of events, the values stored in the key index variable(s) according to the keypresses in the WinProc() function are not able to be accessed by the SetPositions() function.

I hope this better answers your question about what is supposed to happen and is not happening. I apologize for not providing sufficient detail in my original message.

As far as the debugger goes, yes I have tried running the debugger. Part of the problem is, though, that I'm not sure yet just when to press the numpad keys to cause an adjustment to the key index variable and thus to monitor whether that adjustment is being performed. I'll try to step through the program again and see if I can learn anything that way.

I will also research the matter of "multithreading" and "semaphores" to see what they are and whether they have any bearing on what I'm trying to do.

Again, thank you very much for taking the time to read and answer my original message.

In addition to your reply, I also read one from Lundin. In my reply to him, I provided more detail about what it is I'm trying to do. Perhaps reading that reply will assist you as well. I intended to copy some of that same information into this message to you but something went amiss and the data disappeared from my clipboard.

: [blue]: Maybe, you should show more of your code?: : 1. How did you call the functions using the positions set in WM_KEYDOWN?: 2. If these functions are in different file, then you need to use 'extern' keyword before your global variables.: : [/blue]:

Hello:

Thank you for taking the time to read and reply to my original message. I appreciate that very much.

The global variables I'm attempting to use are defined near the top of the file (There's only one file, by the way) outside of any function blocks.

int keyindex = 0;

The key presses are taken as part of the WindowProc() function via the switch case method. The WindowProc() function is called (I'm assuming) by the WinMain() function as this is a Win32-based application.

This switch case appears among the other cases in the WindowProc() function, including WM_ACTIVATE, WM_DESTROY, WM_PAINT, etc.

The SetPositions() function is called as one of a series of functions called by the MyScene() function to set up the frames, set up the lights, set the positions, set up the meshes (the visual objects), set up the wraps, and finally to set the textures. Within, the SetPositions function, the code at one point (when I was trying to use the keyindex variable) went like this:

SetPosition and SetOrientation commands follow, using the variable names within the parenthese of the D3DVAL value entries. In this way, it is possible to adjust the D3DVAL's with variables. The problem is that, even though keyindex is defined as a global variable and it set according to the switch cases within the WinProc function, the keyindex variable is appearently not accessible to the SetPositions() function. Thus keyselect stays equal to 0 and thus the adjustments to the cam variables are not made.

I hope that answers your questions. Again, all of this is in just one file.

: Hi, Frank.: : In addition to your reply, I also read one from Lundin. In my reply to him, I provided more detail about what it is I'm trying to do. Perhaps reading that reply will assist you as well. I intended to copy some of that same information into this message to you but something went amiss and the data disappeared from my clipboard.: : Thanks again for your reply.: : Mike: : If I remember correctly the following code will compile correctly, but it will be impossible to access the global variable from within the function:[code]// the global variableint some_var;

int some_func( void ){ // the following line will not change the global some_var at all // it will just create a local variable of name some_var and // assign it a value of 5 int some_var = 5;

// also this will only modify the local variable and not the // global one some_var++;

} // end some_func[/code]I can't test that right now though. If you sent me the code I could look over it better [email protected]

I think, your problem is in a fact that you do not call the functions which USE the variables in a continuous loop. Only continuous loop will provide a sense of a feedback.

As I see it - you want to press a key and right away (from human point of view) to see the result of that key acting as a modifier for the camera(s) location and angle, etc.

Do you call these functions in a loop or not? Because if you call them once, then your keys will not be noticed by the function unless you actually call it.

Usually, to interactively control hardware in Win32 you need to use a timer. For example, you can set up a timer to be called every 100 milliseconds. In response to timer - you call your functions, which are using these variables. This way, max. interval between a key press and reaction on it will be 100 ms or less.[/blue]

: If I remember correctly the following code will compile correctly, but it will be impossible to access the global variable from within the function:: [code]: // the global variable: int some_var;: : int some_func( void ): {: // the following line will not change the global some_var at all: // it will just create a local variable of name some_var and : // assign it a value of 5: int some_var = 5;: : // also this will only modify the local variable and not the: // global one: some_var++;: : } // end some_func: [/code]: I can't test that right now though. If you sent me the code I could look over it better [email protected]:

Hi, Frank:

Thanks for your second reply. If you are correct, this would certainly explain why I'm experiencing the difficulties that I am. I will do some more research and see if I can determine why this is so. I'll let you know what I find out.

: [blue]Mike,: : I think, your problem is in a fact that you do not call the functions which USE the variables in a continuous loop. Only continuous loop will provide a sense of a feedback.: : As I see it - you want to press a key and right away (from human point of view) to see the result of that key acting as a modifier for the camera(s) location and angle, etc.: : Do you call these functions in a loop or not? Because if you call them once, then your keys will not be noticed by the function unless you actually call it.: : Usually, to interactively control hardware in Win32 you need to use a timer. For example, you can set up a timer to be called every 100 milliseconds. In response to timer - you call your functions, which are using these variables. This way, max. interval between a key press and reaction on it will be 100 ms or less.: [/blue]:

Hello again:

Thanks for your second reply.

I believe that you might be correct about both the loop and the timer. I'm still trying to determine the flow of this particular program. Does the program:

Scenario A:

1) Enter at Winmain() function2) Cycle through InitApp, calling the other initializing functions3) cycle repeatedly through the drawing functions over and over again?

- or -

Scenario B:

Cycle through everything once?

I had assumed that a C++ Win32 program enters at the Winmain function and then, after carrying out all initialization functions (until initialization flag = TRUE) and then cycles through the WinProc or WindowProc loop over and over again until termination. It is possible, however, that my assumption could be in error.

I'll have to do some more testing and try to determine that further. I used to program pretty extensively in BASIC and am relatively new to C. I'm still in the process of learning just how C works from a flow control and variable accessing standpoint.

Your thoughts about the timer are interesting, also. Could it be that the timer is neccessary in order to slow things down just a bit so that the system will have a chance to read the keys? It's certainly worth some thought. One interesting thing, though, is that the system does read the escape key when I press it and does shut down the application. The case VK_ESCAPE is within the switch(wparam) case WM_KEYDOWN within the WindowProc() function. The program does have one call to the Direct3DRM::Tick function to tick the scene, but if that runs only once that would certainly explain why the camera only moves once when I deliberately set the keyselect variable within the SetPositions() function.

I'll look into both the loop and timer and let you know what I find out.

The WndProc is a message receiver from Windows (and from other sources as your own code or other applications). Windows will call your WndProc function only when needed. But if you use a timer - Windows will send you a message WM_TIMER with an interval you specify.

The drawing in Windows is not cyclical and all the time, but only when needed: window resized, window minimized and restored, maximized and restored, or other window was closing yours and been moved out uncovering your window... etc.[/blue]

I don't know if this counts for when using Direct3D to draw...Probably not, but:

I was messing around with printing text on a window and I noticed it didn't draw until I 'triggered' the repaint code.So I thought I would be smart and send a WM_PAINT with PostMessage.However, then still the program wouldn't draw until I resized.

I found out this is because Windows doesn't really draw it. It just 'remembers' what the code run by WM_PAINT did and then when it is need of a refresh it draws.What I needed to do is mark the client area of my window as 'invalidated'. I had to tell Windows it was in need of an actual repaint (I did this with InvalidateRect API). And THEN I posted the WM_PAINT message.

But like I said, I don't know if it's the same when using Direct3D (I would expect it to redraw automatically).