I have an array of cube objects initialised like so (index 0 not used here as that's for the player):
game_object[1] = new GameObject();
game_object[1]->setPosition(vec3(7.0f, 0.0f, 0.0f));
game_object[2] = new GameObject();
game_object[2]->setPosition(vec3(14.0f, 0.0f, 0.0f));
game_object[3] = new GameObject();
game_object[3]->setPosition(vec3(21.0f, 0.0f, 0.0f));
game_object[4] = new GameObject();
game_object[4]->setPosition(vec3(36.0f, 0.0f, 0.0f));
game_object[5] = new GameObject();
game_object[5]->setPosition(vec3(42.0f, 0.0f, 0.0f));
I have a render function in which they are drawn:
glDrawElements(GL_TRIANGLES, 3 * INDICES, GL_UNSIGNED_INT, NULL);
In my update they move to the left as expected. To do this I am just adding another vector to their positions:
for (int i = 1; i < MAX_CUBES; i++)
{
game_object[i]->setPosition(game_object[i]->getPosition() + vec3(-0.03, 0.0, 0.00));
}
However, I want the cubes to repeat this until the user exits the game. I made a reset function to send them back to their starting positions:
void Game::reset()
{
game_object[0]->setPosition(vec3(0.0f, 0.0f, 0.0f));
game_object[1]->setPosition(vec3(7.0f, 0.0f, 0.0f));
game_object[2]->setPosition(vec3(14.0f, 0.0f, 0.0f));
game_object[3]->setPosition(vec3(21.0f, 0.0f, 0.0f));
game_object[4]->setPosition(vec3(36.0f, 0.0f, 0.0f));
game_object[5]->setPosition(vec3(42.0f, 0.0f, 0.0f));
}
This function gets called in the update when the final cube's position is off screen to the left:
if (game_object[5]->getPosition().x <= 0.0)
{
reset();
}
However, this isn't working. Nothing resets after the last cube goes to the left.
Not sure how you are using game_object here but looks very error prone. If you have MAX_CUBES = 5 (as you do have 5 cubes), then that for-loop will miss the last one. Adding further objects (e.g. for gaps, vertical rules, hazards, etc.) will make it even more so.
for (int i = 1; i < MAX_CUBES; i++)
{
game_object[i]->setPosition(game_object[i]->getPosition() + vec3(-0.03, 0.0, 0.00));
}
If MAX_CUBES = 5, then it will move index 1, 2, 3, 4, and not 5, which is the one you check in the condition. 5 will just stay at 42 permanently (is that off-screen?).
Stepping through the code in a debugger will make a problem like this pretty clear regardless, and is an essential tool for programming. Maybe the code just never reaches the if (game_object[5]->getPosition().x <= 0.0) check in the first place? Is there any return in that update function, or is that condition inside another one of some sorts?
Because in your comment you noted that game_object[5]->getPosition().x returns a correct value, the most likely problem is with your reset() function and the setPosition function you are using.
1. Check if set position is working in the first place
Perhaps there is an error with setPosition().
After you set the position using setPosition() and then log the object's coordinates using getPosition() does it return the position you expect?
If not, something is wrong with setPosition.
If so, then...
2. You probably changed the position but failed to render it!
This is a very common problem lol
There is a very high chance you changed the position of the object BUT didn't update what's shown on the screen!
3. Side note for scalability
There is a much more efficient and scalable way of doing a reset if you have eventually have more than 5 objects, by placing their reset values in an array and looping through them:
#define MAX_CUBES 6
double resetPositions_x[MAX_CUBES] = {0.0, 7.0, 14.0, 21.0, 36.0, 42.0};
void Game::reset()
{
for(int i=0;i<MAX_CUBES;i++){
game_object[i]->setPosition(vec3(resetPositions_x[i], 0.0f, 0.0f));
}
}
(Also, it seems every x reset position is a multiple of 7 except 36.0 -> is that a mistake?)
Related
This question already exists:
OpenGL Converting from busy vertex buffer to element buffer
Closed 6 months ago.
I am having trouble merging multiple simple objects into a single mesh with OpenGL.
Before I go on I am aware of instancing and I'm certain that it's not what I want.
I'm drawing a cube with the following buffers:
float cubeVertices[] = {
-0.5f, 0.5f, 0.5f, //front top left
0.5f, 0.5f, 0.5f, //front top right
-0.5f, -0.5f, 0.5f, //front bottom left
0.5f, -0.5f, 0.5f, //front bottom right
-0.5f, 0.5f, -0.5f, //back top left
0.5f, 0.5f, -0.5f, //back top right
-0.5f, -0.5f, -0.5f, //back bottom left
0.5f, -0.5f, -0.5f //back bottom right
};
unsigned int cubeIndices[] = {
0, 2, 1, //FRONT
1, 2, 3,
0, 1, 4, //TOP
4, 1, 5,
1, 3, 5, //RIGHT
5, 3, 7,
2, 7, 3, //BOTTOM
7, 2, 6,
6, 2, 0, //LEFT
0, 4, 6,
6, 4, 5, //BACK
5, 7, 6
};
I then call glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr) which works as wanted.
Now my problem is if I want to draw multiple cubes in the same draw call (Still don't want instancing).
My current way of rendering multiple cubes is by:
for (int y = 0; y < 2; ++y)
{
for (int x = 0; x < 2; ++x)
{
for (int z = 0; z < 2; ++z)
{
model = glm::mat4{1.0f};
model = glm::translate(model, glm::vec3{x, y, z});
shader.SetMat4("uModel", model);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
}
}
}
Which is fine for a 2x2x2 cube of cubes but if I want to go larger like 32x32x32 it starts to fall apart performance wise.
So I was wondering how I can merge this 2x2x2 cube into a single mesh and call glDrawElements(GL_TRIANGLES, 36 * 8, GL_UNSIGNED_INT, nullptr) or similar.
I've tried:
std::array<glm::vec3, 8> locations{};
for (int x = 0; x < 2; ++x)
{
for (int y = 0; y < 2; ++y)
{
for (int z = 0; z < 2; ++z)
{
locations[x + 2 * (y + 2 * z)] = glm::vec3{x, y, z};
}
}
}
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO[1]);
glBufferData(GL_ARRAY_BUFFER, locations.size(), locations.data(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(1);
glBindVertexArray(0);
And using gl_Position = uProjection * uView * uModel * vec4(aPos * aLocation, 1.0f); where uModel is just a glm::mat4{1.0f}, aPos is from cubeVertices and aLocation is from the locations array.
I've got a couple ideas on why it doesn't work which I'll list.
First off: aLocation is different for every vertex instead of staying constant for the entire cube and then changing to the next location. Not sure how to do that. I could copy and paste the same location for every vertex I assume but that seems to defeat the purpose of using an element buffer in the first place.
Second: cubeIndices[] only holds enough indices for a single cube so I could also fix that by copy pasting the cubeIndices 8 times but doesn't that defeat the purpose of using an element buffer if I just have the same data 8 times?
So maybe a double element buffer could work?
I know instancing does seem like a really obvious solution but I guarantee that it's not what I am after.
I'm quite new to OpenGL so I don't have the most solid grasp of what I'm doing yet so I'm just trying to figure OpenGL out by making small projects. If someone could help it would be greatly appreciated.
It really looks like it is instancing that you want.
Do your objects moves but the geometry of each one stays the same? instancing.
Does each object move with bones animations? instancing.
Does the geometry moves every frame and not bone animated? not instancing, dynamic buffers.
One of the bottleneck of GPU is main memory=>GPU data transfers. You will struggle to update a lot of geometry at once because you need to transfer all the vertex every frame (~100 times a sec).
Your 2nd code is good. If you have performance issues its for another reason.
If you try to draw 32*32*32 cubes, that's 6*2*32*32*32=393 216 triangles. That could be a lot depending on your hardware.
If you used a big index buffer, everything would be the same, but you would use 6*3*2*32*32*32*sizeof(UINT)=4.7MB instead of 6*3*2*sizeof(UINT)=144B of memory space for your index buffer.
If the vertex positions are changing, you don't have to update the index buffer, there is probably a way to select a different start vertex. There is in Direct3D but IDK for opengl.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm learning openGL from this website https://learnopengl.com
To draw a simple triangle, the first example provided by this website is using a float array:
float triangle[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
Of course it work well. But beside this example I have tried to use a basic structur carrying glm::vec3 as follow :
struct Position {
glm::vec3 pos;
};
Then to store the same data as the float array I just did a simple array of Position as follow :
Position leTriangle[3];
leTriangle[0].pos = glm::vec3(-0.5f, -0.5f, 0.0f);
leTriangle[1].pos = glm::vec3(0.5f, -0.5f, 0.0f);
leTriangle[2].pos = glm::vec3(0.0f, 0.5f, 0.0f);
(Of course all this was just to test if it could work)
Then after having sent my array of Position to the GPU using glBufferData and glVertexAttribPointer the triangle wasn't appearing anymore. So, juste to see if the array I sent where similar to the exemple floating array, I did this :
float* test = (float*)&leTriangle;
for(int e = 0; e < ((12/4) * 3); e++,test++){
std::cout << *test << std::endl;
}
And instead of printing the same floating array, it print this :
0.0f,-0.5f,-0.5f,// left
0.0f,-0.5f,0.5f, // right
0.0f,0.5f,0.0f // top
X and Z value has been inverted. So I guessed the order of the GLM data is not what I thought.
Can someone explain me why data in GLM are ordered this way? Should I respect this order or maybe I should try to reverse it? Maybe it's not important, is it something I should have in mind when placing 3D object?
Data in the glm::vec3 struct is ordered correctly. You could easily verify this by checking up memory, pointed by your test variable:
You are getting strange results, because something in your test is wrong, you are clearly reading glm::vec3 fields backward. Code in your question does not exhibit this behavior. Perhaps you should check how you assign your data.
I want to test the spring contraint of Bullet Physics. So I created a static box hovering above the ground and a second dynamic box hanging down from it. But activating the spring behavior does nothing! The box is indeed hanging freely. I know it because it rotates freely. But it does not oscillate or anything.
btCollisionShape *boxShape = createBoxShape(0.2f, 0.2f, 0.2f);
btRigidBody *box1 = createStatic(boxShape);
btRigidBody *box2 = createDynamic(1.0f /*mass*/, boxShape);
box1->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 2.0f, 1.0f }));
box2->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 1.0f, 1.0f }));
btGeneric6DofSpring2Constraint *spring = new btGeneric6DofSpring2Constraint(
*box1, *box2,
btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
btTransform(btQuaternion::getIdentity(), { 0.0f, 0.0f, 0.0f })
);
// I thought maybe the linear movement is locked, but even using these lines do not help.
// spring->setLinearUpperLimit(btVector3(0.0f, 0.1, 0.0f));
// spring->setLinearLowerLimit(btVector3(0.0f, -0.1, 0.0f));
// Enabling the spring behavior for they y-coordinate (index = 1)
spring->enableSpring(1, true);
spring->setStiffness(1, 0.01f);
spring->setDamping (1, 0.00f);
spring->setEquilibriumPoint();
What is wrong? I played a lot with the the Stiffness and Damping parameters. But it changed nothing. Setting linear lower and upper limits makes the box movable in the y-direction, but it still not oscillates. And yes, gravity is activated.
Ok, I found a solution by checking out Bullet's provided example projects (could have come up with the idea earlier). Three things I have learned:
The spring constraint will not violate the linear limits. The problem with my former approach was that the linear movement was either locked, or limited to a too small range for the assigned spring stiffness. Now there are no more limits (by setting the lower limit above the upper one).
The stiffness was far too small, so the joined objects were acting as if they were freely movable inside the linear limits. You can check out the values in my code below, I got them from the example project.
There is a small difference in the behavior between btGeneric6DofSpringConstraint and btGeneric6DofSpring2Constraint. The former one seems to violet the non-spring-axes less (x- and z-axes in my case). The latter one seems to apply a stronger damping. But these are just first observations.
btGeneric6DofSpringConstraint *spring = new btGeneric6DofSpringConstraint(
*box1, *box2,
btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
btTransform(btQuaternion::getIdentity(), { 0.0f, 0.0f, 0.0f }),
true
);
// Removing any restrictions on the y-coordinate of the hanging box
// by setting the lower limit above the upper one.
spring->setLinearLowerLimit(btVector3(0.0f, 1.0f, 0.0f));
spring->setLinearUpperLimit(btVector3(0.0f, 0.0f, 0.0f));
// Enabling the spring behavior for they y-coordinate (index = 1)
spring->enableSpring(1, true);
spring->setStiffness(1, 35.0f);
spring->setDamping (1, 0.5f);
spring->setEquilibriumPoint();
I'm trying to rotate a cube's vertexes with a rotation matrix but whenever I run the program the cube just disappears.
I'm using a rotation matrix that was given to us in a lecture that rotates the cube's x coordinates.
double moveCubeX = 0;
float xRotationMatrix[9] = {1, 0, 0,
0, cos(moveCubeX), sin(moveCubeX),
0, -sin(moveCubeX), cos(moveCubeX)
};
I'm adding to the moveCubeX variable with the 't' key on my keyboard
case 't':
moveCubeX += 5;
break;
And to do the matrix multiplication I'm using
glMultMatrixf();
However when I add this into my code when running it the cube has just disappeared. This is where I add in the glMultMatrixf() function.
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(pan, 0, -g_fViewDistance,
pan, 0, -1,
0, 1, 0);
glRotatef(rotate_x, 1.0f, 0.0f, 0.0f); //Rotate the camera
glRotatef(rotate_y, 0.0f, 1.0f, 0.0f); //Rotate the camera
glMultMatrixf(xRotationMatrix);
I'm struggling to see where it is I have gone wrong.
OpenGL uses matrices of size 4x4. Therefore, your rotation matrix needs to be expanded to 4 rows and 4 columns, for a total of 16 elements:
float xRotationMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
0.0f, cos(moveCubeX), sin(moveCubeX), 0.0f,
0.0f, -sin(moveCubeX), cos(moveCubeX), 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
You will also need to be careful about the units for your angles. Since you add 5 to your angle every time the user presses a key, it looks like you're thinking in degrees. The standard cos() and sin() functions in C/C++ libraries expect the angle to be in radians.
In addition, it looks like your matrix is defined at a global level. If you do this, the elements will only be evaluated once at program startup. You will either have to make the matrix definition local to the display(), so that the matrix is re-evaluated each time you draw, or update the matrix every time the angle changes.
For the second option, you can update only the matrix elements that depend on the angle every time the angle changes. In the function that modifies moveCubeX, add:
xRotationMatrix[5] = cos(moveCubeX);
xRotationMatrix[6] = sin(moveCubeX);
xRotationMatrix[9] = -sin(moveCubeX);
xRotationMatrix[10] = cos(moveCubeX);
The code below is from a book. When I try to run it, it fails on the line
osg::ref_ptr geom = new osg::Geometry();
and, the output window does not seem to contain much information on why it crashes, other than telling me that it did. Any idea what I may be doing wrong in the code below? Thanks in advance.
Here is the windows error popup when I try to run this in Visual Studio 2010(windows 7 64)
Windows has triggered a breakpoint in OSGPracticeLab.exe.
This may be due to a corruption of the heap, which indicates a bug in OSGPracticeLab.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while OSGPracticeLab.exe has focus.
The output window may have more diagnostic information.
On attempting to debug the code, I was able to trace the problem to the new function call. In the code below, it seems the while loop is skipped over, and a null value is returned for p(no memory allocated, and so my Geometry object in the code below this, is not instantiated.
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{ // try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
Below is my Program to draw some shapes and display.
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osgViewer/Viewer>
int main()
{
//An octahedron is a polyhedron having eight triangle faces.
//It is really a nice example to show why primitive indexing is important
// we will sketch the octahedron structure now
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(6);
//octahedron has six vertices, each shaed by four triangles.
//withe the help of an index array and the osg::DrawElementsUInt class, we can allocate
//a vertex array with only six elements
(*vertices)[0].set( 0.0f, 0.0f, 1.0f);
(*vertices)[1].set(-0.5f,-0.5f, 0.0f);
(*vertices)[2].set( 0.5f,-0.5f, 0.0f);
(*vertices)[3].set( 0.5f, 0.5f, 0.0f);
(*vertices)[4].set(-0.5f, 0.5f, 0.0f);
(*vertices)[5].set( 0.0f, 0.0f,-1.0f);
//The osg::DrawElementsUInt accepts a size parameter besides the drawing mode parameter, too.
//After that, we will specify the indices of vertices to describe all eight triangle faces.
osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_TRIANGLES, 24);
(*indices)[0] = 0; (*indices)[1] = 1; (*indices)[2] = 2;
(*indices)[3] = 0; (*indices)[4] = 2; (*indices)[5] = 3;
(*indices)[6] = 0; (*indices)[7] = 3; (*indices)[8] = 4;
(*indices)[9] = 0; (*indices)[10]= 4; (*indices)[11]= 1;
(*indices)[12]= 5; (*indices)[13]= 2; (*indices)[14]= 1;
(*indices)[15]= 5; (*indices)[16]= 3; (*indices)[17]= 2;
(*indices)[18]= 5; (*indices)[19]= 4; (*indices)[20]= 3;
(*indices)[21]= 5; (*indices)[22]= 1; (*indices)[23]= 4;
//To create a geometry with a default white color, we only set the vertex array
//and the osg::DrawElementsUInt primitive set. The normal array is also required but is not easy
//to compute manually. We will use a smoothed normal calculator to automatically obtain it. This calculator
//will be described in the next section, Using polygonal techniques.
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
geom->setVertexArray( vertices.get() );
geom->addPrimitiveSet( indices.get() );
//osgUtil::SmoothingVisitor::smooth( *geom );
//Add the geometry to an osg::Geode object and make it the scene root
osg::ref_ptr<osg::Geode> root = new osg::Geode;
root->addDrawable( geom.get() );
osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
return viewer.run();
}
int drawShapeUsingVertices()
{
//Create the vertex array and push the four corner points to the back of the array by using vector like operations:
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back( osg::Vec3(0.0f, 0.0f, 0.0f) );
vertices->push_back( osg::Vec3(1.0f, 0.0f, 0.0f) );
vertices->push_back( osg::Vec3(1.0f, 0.0f, 1.0f) );
vertices->push_back( osg::Vec3(0.0f, 0.0f, 1.0f) );
//We have to indicate the normal of each vertex; otherwise OpenGL will use a default (0, 0, 1) normal vector
//and the lighting equation calculation may be incorrect. The four vertices actually face the same direction,
//so a single normal vector is enough. We will also set the setNormalBinding() method to BIND_OVERALL later.
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
//here We will indicate a unique color value to each vertex and make them colored. By default,
//OpenGL will use smooth coloring and blend colors at each vertex together:
colors->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
colors->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
colors->push_back( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
//Next, we create the osg::Geometry object and set the prepared vertex, normal, and color arrays to it.
//We also indicate that the single normal should be bound to the entire geometry and that the colors
//should be bound per vertex:
osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
quad->setVertexArray( vertices.get() );
quad->setNormalArray( normals.get() );
quad->setNormalBinding( osg::Geometry::BIND_OVERALL );
quad->setColorArray( colors.get() );
quad->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
//The last step required to finish a geometry and add it to the scene graph is to specify the primitive set.
//A newly allocated osg::DrawArrays instance with the drawing mode set to GL_QUADS is used here, in order to
//render the four vertices as quad corners in a counter-clockwise order:
quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );
//Add the geometry to an osg::Geode object and render it in the scene viewer:
osg::ref_ptr<osg::Geode> root = new osg::Geode;
root->addDrawable( quad.get() );
osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
return viewer.run();
}
I didn't have any problems with the code. Took it from the beginners guide and it works fine:
#include <osg/Geometry>
#include <osg/Geode>
#include <osgViewer/Viewer>
int main()
{
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back( osg::Vec3(0.0f, 0.0f, 0.0f) );
vertices->push_back( osg::Vec3(1.0f, 0.0f, 0.0f) );
vertices->push_back( osg::Vec3(1.0f, 0.0f, 1.0f) );
vertices->push_back( osg::Vec3(0.0f, 0.0f, 1.0f) );
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
colors->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
colors->push_back( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
quad->setVertexArray( vertices.get() );
quad->setNormalArray( normals.get() );
quad->setNormalBinding( osg::Geometry::BIND_OVERALL );
quad->setColorArray( colors.get() );
quad->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );
osg::ref_ptr<osg::Geode> root = new osg::Geode;
root->addDrawable( quad.get() );
osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
return viewer.run();
}
I recommend you check your project properties.
Have you included additional include directories: $(OSG_ROOT)\include;$(OSG_SOURCE)\include;$(OSG_ROOT)\include\osg;
If you're in Debug mode, do you have this in your preprocessor definitions? _DEBUG;WIN32;
Did you specify your linker additional directory: $(OSG_ROOT)\lib
Did you specify linker additional dependencies?: osgWidgetd.lib;osgVolumed.lib;osgViewerd.lib;osgUtild.lib;osgTextd.lib;osgTerraind.lib;osgSimd.lib;osgShadowd.lib;osgPresentationd.lib;osgParticled.lib;osgManipulatord.lib;osgGAd.lib;osgFXd.lib;osgDBd.lib;osgd.lib;osgAnimationd.lib;OpenThreadsd.lib;;;;;;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
Have you specified Configuration properties > debugging > Working directory as: $(OSG_ROOT)\bin
If an extreme case, it may be because your Visual Studio installation is corrupted. Try reinstalling Visual Studio and if the OSG installation was corrupted, then reinstall OSG (build from source). Mentioning this because a friend of mine had problems running OSG because his Visual Studio was corrupted. Reinstalling fixed it.
Does osg build? Did you run the "Install" project from within OSG? Even if you did, the permissions can be borked in Win7 - you might have to manually install to Program Files.
Your sample posted above compiled perfectly for me on Win7 / VS 2008 / Win32-Release build config, built against version 3.1.0 of OSG. I just replaced the main from one of the Example Projects in the OSG solution with the code you pasted above, it builds and runs without the error you listed.
I am using OSG from the trunk - probably at least a minor version ahead of any of the prebuilds, but it should work from the prebuilds if you have your paths, etc., set right. You could, of course, also try starting from the authors' download of the examples: http://www.skew-matrix.com/OSGQSG/ - they already have the project files, etc., set up correctly.
You don't define the osg::Geometry class in your code, so the most likely problem is that you aren't properly linking to the object or library where it is defined.