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.
Related
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?)
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();
Introduction
Let's say I have the following vertices:
const VERTEX World::vertices[ 4 ] = {
{ -960.0f, -600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f }, // side 1 screen coordinates centred
{ 960.0f, -600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f },
{ -960.0f, 600.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f },
{ 960.0f, 960.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f }
};
You may have guessed that 960 * 2 is 1920.. which is the width of my screen and same goes for 600 * 2 being 1200.
These vertices represent a rectangle that will fill up my ENTIRE screen where the origin is in the centre of my screen.
Issue
So up until now, I have been using an Orthographic view without a projection:
matView = XMMatrixOrthographicLH( Window::width, Window::height, -1.0, 1.0 );
Any matrix that was being sent to the screen was multiplied by matView and it seemed to work great. More specifically, my image; using the above vertices array, fit snugly in my screen and was 1:1 pixels to its original form.
Unfortunately, I need 3D now... and I just realised i'm going to need some projection... so I prepared this little puppy:
XMVECTOR vecCamPosition = XMVectorSet( 0.0f, 0.0f, -1.0f, 0 ); // I did try setting z to -100.0f but that didn't work well as I can't scale it back any more... and it's not accurate to the 1:1 pixel I want
XMVECTOR vecCamLookAt = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f );
XMVECTOR vecCamUp = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
matView = XMMatrixLookAtLH( vecCamPosition, vecCamLookAt, vecCamUp );
matProjection = XMMatrixPerspectiveFovLH(
XMConvertToRadians( 45 ), // the field of view
Window::width / Window::height, // aspect ratio
1.0f, // the near view-plane
100.0f ); // the far view-plan
You may already know what the problem is... but if not, I have just set my field of view to 45 degrees.. this'll make a nice perspective and do 3d stuff great, but my vertices array is no longer going to cut the mustard... because the fov and screen aspect have been greatly reduced (or increased ) so the vertices are going to be far too huge for the current view I am looking at (see image)
I was thinking that I need to do some scaling to the output matrix to scale the huge coordinates back down to the respective size my fov and screen aspect is now asking for.
What must I do to use the vertices array as it is (1:1 pixel ratio to the original image size) while still allowing 3d stuff to happen like have a fly fly around the screen and rotate and go closer and further into the frustrum etc...
Goal
I'm trying to avoid changing every single objects vertices array to a rough scaled prediction of what the original image would look like in world space.
Some extra info
I just wanted to clarify what kind of matrix operations I am currently doing to the world and then how I render using those changes... so this is me doing some translations on my big old background image:
// flipY just turns the textures back around
// worldTranslation is actually the position for the background, so always 0,0,0... as you can see 0.5 was there to make sure I ordered things that were drawn correctly when using orthographic
XMMATRIX worldTranslation = XMMatrixTranslation( 0.0f, 0.0f, 0.5f );
world->constantBuffer.Final = flipY * worldTranslation * matView;
// My thoughts are on this that somehow I need to add a scaling to this matrix...
// but if I add scaling here... it's going to mean every other game object
// (players, enemies, pickups) are going to need to be scaled... and really I just want to
// have to scale the whole lot the once.. right?
And finally this Is where it is drawn to the screen:
// Background
d3dDeviceContext->PSSetShaderResources( 0, 1, world->textures[ 0 ].GetAddressOf( ) ); // Set up texture of background
d3dDeviceContext->IASetVertexBuffers( 0, 1, world->vertexbuffer.GetAddressOf( ), &stride, &offset ); // Set up vertex buffer (do I need the scaling here?)
d3dDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // How the vertices be drawn
d3dDeviceContext->IASetIndexBuffer( world->indexbuffer.Get( ), DXGI_FORMAT_R16_UINT, 0 ); // Set up index buffer
d3dDeviceContext->UpdateSubresource( constantbuffer.Get( ), 0, 0, &world->constantBuffer, 0, 0 ); // set the new values for the constant buffer
d3dDeviceContext->OMSetBlendState( blendstate.Get( ), 0, 0xffffffff ); // DONT FORGET IF YOU DISABLE THIS AND YOU WANT COLOUR, * BY Color.a!!!
d3dDeviceContext->DrawIndexed( ARRAYSIZE( world->indices ), 0, 0 ); // draw
and then what I have done to apply my matProjection which has supersized all my vertices
world->constantBuffer.Final = flipY * worldTranslation * matView * matProjection; // My new lovely projection and view that make everything hugeeeee... I literally see like 1 pixel of the background brah!
Please feel free to take a copy of my game and run it as is (Windows 8 application Visual studio 2013 express project) in the hopes that you can help me out with putting this all into 3D: https://github.com/jimmyt1988/FlyGame/tree/LeanerFramework/Game
its me again. Let me try to clear a few things up
1
Here is a little screenshot from an editor of mine:
I have edited in little black boxes to illustrate something. The axis circles you see around the objects are rendered at exactly the same size. However, they are rendered through a perspective projection. As you can see, the one on the far left is something like twice as large as the one in the center. This is due purely to the nature of a projection like that. If this is unacceptable, you must use a non-perspective projection.
2
The only way it is possible to maintain a 1:1 ratio of screenspace to uv space is to have the object rendered at 1 pixel on screen per 1 pixel on texture. There is nothing more to it than that. However, what you can do is change your texture filter options. Filter options are designs specifically for rendering non 1:1 ratios. For example, the code:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Tells opengl: "If you are told to sample a pixel, don't interpolate anything. Just take the nearest value on the texture and paste it on the screen.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
This code, however, does something much better: it interpolates between pixels. I think this may be what you want, if you aren't already doing it.
These pictures (taken from http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/) show this:
Nearest:
Linear:
Here is what it comes down to. You request that:
What must I do to use the vertices array as it is (1:1 pixel ratio to the original image size) while still allowing 3d stuff to happen like have a fly fly around the screen and rotate and go closer and further into the frustrum etc...
What you are requesting is by definition not possible, so you have to look for alternative solutions. I hope that helps somewhat.
So I have begun learning OpenGL, reading from the book "OpenGL Super Bible 5 ed.". It's explains things really well, and I have been able to create my first gl program myself! Just something simple, a rotating 3d pyramid.
Now for some reason one of the faces are not rendering. I checked the vertecies (plotted it on paper first) and it seemed to be right. Found out if I changed the shader to draw a line loop, it would render. However it would not render a triangle. Can anyone explain why?
void setupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
M3DVector3f vVerts1[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
M3DVector3f vVerts2[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,-0.5f,0.0f,0.5f};
M3DVector3f vVerts3[] = {-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f};
M3DVector3f vVerts4[] = {0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
triangleBatch1.Begin(GL_LINE_LOOP, 3);
triangleBatch1.CopyVertexData3f(vVerts1);
triangleBatch1.End();
triangleBatch2.Begin(GL_TRIANGLES, 3);
triangleBatch2.CopyVertexData3f(vVerts2);
triangleBatch2.End();
triangleBatch3.Begin(GL_TRIANGLES, 3);
triangleBatch3.CopyVertexData3f(vVerts3);
triangleBatch3.End();
triangleBatch4.Begin(GL_TRIANGLES, 3);
triangleBatch4.CopyVertexData3f(vVerts4);
triangleBatch4.End();
glEnable(GL_CULL_FACE);
}
float rot = 1;
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
GLfloat vBlue[] = {0.0f, 1.0f, 0.0f, 0.5f};
GLfloat vGreen[] = {0.0f, 0.0f, 1.0f, 0.5f};
GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 0.5f};
M3DMatrix44f transformMatrix;
if (rot >= 360)
rot = 0;
else
rot = rot + 1;
m3dRotationMatrix44(transformMatrix,m3dDegToRad(rot),0.0f,1.0f,0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vRed);
triangleBatch1.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vBlue);
triangleBatch2.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vGreen);
triangleBatch3.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vWhite);
triangleBatch4.Draw();
glutSwapBuffers();
glutPostRedisplay();
Sleep(10);
}
You've most likely defined the vertices in clockwise order for the triangle that isn't showing, and in counterclockwise order (normally the default) for those that are. Clockwise winding essentially creates an inward facing normal and thus OpenGL won't bother to render it when culling is enabled.
The easiest way to check this is to set glCullFace(GL_FRONT)--that should toggle it so you see the missing triangle and no longer see the other three.
The only thing I see that affects polygons here is glEnable(GL_CULL_FACE);.
You shouldn't have that, because if you plot your vertices backwards, the polygon won't render.
Remove it or actually call glDisable(GL_CULL_FACE); to be sure.
In your case, it's not likely that you want to draw a polygon that you can see from one side only.
This is a simple issue that I'm somewhat ashamed to ask for help on.
I'm making a simple call to gluSphere to render a sphere, however, it does not light properly even though I'm pretty sure I added the normals and lighting correctly. If, however, I add a texture, the model lights normally, except it seems to be always SMOOTH, and I cannot change it to flat.
This is the lighting code in my init() function:
gl.glLightfv( GL.GL_LIGHT0, GL.GL_AMBIENT , AMBIENT_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_DIFFUSE , DIFFUSE_LIGHT, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_POSITION, light_pos , 0 );
gl.glEnable ( GL.GL_LIGHT0 );
gl.glEnable ( GL.GL_LIGHTING );
this is my sphere code in my display() function:
gl.glColor3d(1.0, 1.0, 1.0);
glu.gluQuadricDrawStyle (quad, GLU.GLU_FILL);
glu.gluQuadricNormals (quad, GLU.GLU_FLAT);
glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE);
glu.gluSphere(quad, 1.0, lat, lon);
Please advise.
EDIT:
light values:
public final static float[] DIFFUSE_LIGHT = { 1.0f, 1.0f, 1.0f, 1.0f };
public final static float[] AMBIENT_LIGHT = { 0.3f, 0.3f, 0.3f, 1.0f };
public float[] light_pos = { -2.0f, 2.0f, 10.0f, 0.0f };
added materials, no change:
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT , new float[]{0.5f, 0.5f, 0.5f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE , new float[]{1.0f, 1.0f, 1.0f, 1.0f}, 0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, new float[]{0.7f, 0.7f, 0.7f, 1.0f}, 0);
gl.glMaterialf (GL.GL_FRONT, GL.GL_SHININESS, 0.5f);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, new float[]{0.3f, 0.3f, 0.3f, 0.0f}, 0);
EDIT2:
Blah, I figured i had a:
gl.glEnable(GL.GL_TEXTURE_2D);
active somewhere and it was causing my model not to have shading if there was no texture associated with it. -_- carry on good people, carry on.
I encountered lighting problem too and figured out that i need to add glEnable(GL_NORMALIZE).
What kind of lighting are you expecting? The third parameter to glLightfv is supposed to be the values of the light you are setting.
Are there any translations/rotations you do that may affect the position of the light?
Is GL_COLOR_MATERIAL enabled or disabled? It may overwrite your material settings if it is.
Even if your code is not enabling GL_TEXTURE_2D, you should try disabling it manually right before the line is reached, just in case.
If you wish to ignore gluSphere completely, there's some code in this thread that you can use.