I am trying to create a simple function that adds openGL code into my MainLoop.
For example, using win->AddToScene("glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glEnd(); ");
I am trying to do this using Arrays, but it isn't working as far what I have.
Code:
std::vector< int > arr;
void Window::MainLoop()
{
do
{
glfwMakeContextCurrent(window);
glFlush();
glfwPollEvents();
for(int i = 0; i < arr.size(); i++)
{
arr[i];
}
glfwSwapBuffers(window);
}
while(running && !glfwWindowShouldClose(window));
}
void Window::AddToScene(char child[100]){
for(unsigned int i = 0; i < arr.size(); i++){
arr.push_back(*child);
}
}
Are the arrays a way to do it, or do I have to do something completely else?
Thanks
Props for creativity. Just FYI what you want to do wouldn't work that way in interpreted languages either. In those you'd have to use some eval statement.
It should be noted that it's perfectly possible to implement an interpreter for a small custom toy language (or rather command execution list) in C that does exactly as you envision.
However as far as adding geometry to your scene goes: You're barking up the completely wrong tree! A scene solely consists of what is drawn not how it is drawn. Your mistake in thinking is, that you mistook the glVertex calls as what is important. What's actually important are the numbers that go into it.
Think about something like this:
glBegin(…);
for(size_t i = 0; i < vertices.length(); ++i){
glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
}
glEnd();
However all these function calls are super inefficient. What you actually want to do is rather this, i.e. using Vertex Arrays:
glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
glDrawArrays(…, 0, vertices.length());
Last step would be dropping the old style OpenGL functions and transition to generic vertex attributes and vertex buffer object; but that is easy enough once you master old style vertex arrays.
Related
For the entire night, I've been looking around the internet, both stackoverflow and elsewhere, to find something to say how to print text on GLUT. While I've found places that say how, none have explained it well, saying which parts of the function is neccessary, which parts aren't. I've also tried to copy in some of the code with the closest to a success is something that made my entire screen white except for some blue pixels. So I've given up, and I'm hoping this will clear up confusion for me and the many people who are confused, like me.
So, I have found this code:
glColor3f(1.0f, 0.0f, 0.0f);
glRasterPos2f(1280, 720);
int len = menu.length();
for (int i = 0; i < len; i++) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
and I have placed it in my code:
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(-_cameraAngle, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0f, 0.0f, -9.0f + zoom);
glTranslatef(0.0f, -1.0f, 0.0f);
string menu = "Hello!";
glColor3f(1.0f, 0.0f, 0.0f);
glRasterPos2f(1280, 720);
int len = menu.length();
for (int i = 0; i < len; i++) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
} /*if I need to post the rest of drawScene(), which is the function delegated
as the Display Func, tell me. I don't want to because it's long
What I want to know is what am I doing wrong, and what do future readers in my position need to do in order to get good results.
You don't say what's specifically wrong, but I'm suspecting that your text is not showing up. The reason is likely that the raster position is being clipped, and this is causing your text to not be rendered.
The raster position is the "anchor point" of where a bitmap will be drawn. Usually, this is the lower-left corner of the bitmap (the glBitmap can change that with by setting the x and y parameters to something other than zero, but assume you're not doing that). The raster position is transformed by the model-view matrix, just like a vertex in a geometric primitive. And just like a vertex, if the transformed raster position lies outside of the viewport, it's clipped, and nothing is rendered. What's important to know here is that any rendering of a bitmap - regardless of its size - is predicated on the raster position being inside of the viewport.
In your example, you don't show the viewport you're using, nor the projection transformation (the matrix on the GL_PROJECTION stack), but you set the raster position to (1280, 720), which may well be outside of the viewport.
Let's say you want to render your text in the lower-left corner of your window (and for the sake of argument, let's say your window is 1280 x 1024). When it's time to render your text, drop the following into your rendering routine:
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
gluOrtho2D( 0, 1280, 0, 1024 );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glRasterPos2i( 10, 1014 ); // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
glPopMatrix();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
Depending on which version of OpenGL you're using, you may be able to use a simpler routine glWindowPos2i() (the 2i can be replaced with other dimension-type pairs like other OpenGL functions), which bypasses transforming the raster position by the model-view and projection matrices, and works directly in window coordinates. In that case, you'd write the above code as:
glWindowPos2i( 10, 1014 ); // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
I have a file with 3 coordinates and I can render it as points, lines, triangles , or any primitive.
I want to construct a wireframe model of this file, what should I change or add to view it as a wireframe
sample:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glOrtho(-50.0,50.0,-50.0,50.0,-50.0,50.0);
glColor4f(1.0f,1.0f,1.0f,1.0f);
glPointSize(3);
glLineWidth(3);
glColor3f(1.0f,1.0f,1.0f);
for(int i=0; i<points; i++)
{
glBegin(GL_LINES);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
glEnd();
}
}
This will never produce any output:
for(int i=0; i<points; i++)
{
glBegin(GL_LINES);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
glEnd();
}
GL_LINES requires two vertices per line, and you're only providing one between your glBegin and glEnd calls.
glBegin and glEnd should bookend particular pieces of geometry, not individual vertices.
However, simply moving the calls out of the for loop won't fix your problem:
glBegin(GL_LINES);
for(int i=0; i<points; i++)
{
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
}
glEnd();
This would almost produce what you want, but will actually show every OTHER line, because it's treating each pair you send in as one line. So it will draw a line between point 1 and 2, and then between 3 and 4. This is because GL_LINES means "interpret each pair I send in as a completely new line, unrelated to the previous vertices.
What you really want is this:
glBegin(GL_LINE_STRIP);
for(int i=0; i<points; i++)
{
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3d(vList[i][0],vList[i][1],vList[i][2]);
}
glEnd();
Using GL_LINE_STRIP instructs OpenGL that it should take the first two vertices and draw a line, and then for each new vertex, draw another line from the end of the last line.
Caveat
All this assumes your file is actually designed to produce lines like this. Most 3D file formats include both vertices and indices. The vertices tell you the 3D positions, but the indices tell you which points should be connected to which. However, since this looks like a sort of homework assignment, I'm going to assume that the file is as described, a simple list of X-Y-Z coordinates that should be connected in sequence.
I have created a function to move several cubes along the z-axis. I can get all the cubes to move at once and repeat but I am trying to get each individual cube to move independently of the other. My z-axis function is:
void moveCubes()
{
cubeZ += 0.050f;
if(cubeZ > 120)
cubeZ -= 110.0f;
glutPostRedisplay();
}
and the display function is:
void myDisplay()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
for(int i = 0; i < maxCubes; i++)
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -110);
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeZ);
glRotatef(rotateAxis, cubeOrigins[i].rotateX, cubeOrigins[i].rotateY, 0.0f);
drawCubes();
}
moveCubes();
glutSwapBuffers();
}
cubeZ is defined at the top of my code and is:
GLfloat cubeZ = 0.0;
cubeOrigins[i].x and .y are generated rands(). I can add more code if needed but I believe this is the important part. I am hoping someone can show me what I need to do. Frankly it is getting pretty frustrating. I appreciate any help.
You've hard-coded a constant Z-position for all cubes. You probably want to use cubeOrigins[i].z instead. If you don't have such a value in your struct, perhaps you should (and randomize that the same as your x- and y-values).
When you update:
void moveCubes() {
for( int i = 0; i < maxCubes; i++ ) {
cubeOrigins[i].z += 0.05f;
if( cubeOrigins[i].z > 120 )
cubeOrigins[i].z -= 110.0f;
}
glutPostRedisplay();
}
And of course:
glTranslatef(cubeOrigins[i].x, cubeOrigins[i].y, cubeOrigins[i].z);
If you want to get techy, you may also want to randomize the speed of the cubes. So you can create an array of floats to represent each cube's speed and use that instead of the constant 0.05f speed.
I have a binary file which contains the vertices and normals to make a human body graphics in opengl. The graphics are made up of small triangles. The numbers (floating points ) in the binary files are in the order, X, Y, Z of the first vertice of a triangle followed by the normals(x,y,z) to it, Similarly two more of such set completes a triangle.( thus every 18 set of floating numbers in the binary files makes a triangle) and binary files contains several thousands of such triangles.I have written a opengl code in windows form in c++ , to display the graphics, following is the rendering function.I am ignoring the normals and using only vertices
void OpenGL::RenderScene()
{
size_t file_size;
ifstream file;
file.open("male_16_do`enter code here`wn.bin",ios::binary|ios::in);
if(!file){
cout<<"Couldnt find the file"<<endl;
}
file.seekg(0,ios::end);
file_size=file.tellg();
file_size/=(sizeof(float));
file.seekg(0,ios::beg);
std::vector<float> data(file_size);
file.read(reinterpret_cast<char*>(&data[0]),file_size*sizeof(float));
for(size_t i=0;i<file_size;i++){
//cout<<fixed<<setprecision(3)<<data[i]<<endl;
}
vector<float>::iterator iter;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(1.5f,1.0f,0.0f);
for(iter=data.begin();iter!=data.end();iter++){
glBegin(GL_TRIANGLE_STRIP);
int i=0;
glColor3f(1,0.0f,0.0f);
glVertex3f( data[i], data[i+1], data[i+2]);
glColor3f(1,0.0f,0.0f);
glVertex3f(data[i+6],data[i+7], data[i+8]);
glColor3f(1,0.0f,0.0f);
glVertex3f( data[i+12],data[i+13], data[i+14]);
glEnd();
i=i+18;
}
SwapBuffers(m_hDC);
}
The code appears to be right , but on rendering there is nothing shown in the window, can anyone suggest me what could be possibly wrong here ? Viewport is set to match the width and height of window.
Your for loop with the iterator looks fishy. You're using an iterator over data as well as i:
Make it:
size_t dataLen = data.size();
for(size_t i = 0; i < dataLen; i+= 18) {
glBegin(GL_TRIANGLE_LIST); // your original code mentioned TRI_STRIP.
glColor3f(1,0.0f,0.0f);
glVertex3f( data[i], data[i+1], data[i+2]);
glColor3f(1,0.0f,0.0f);
glVertex3f(data[i+6],data[i+7], data[i+8]);
glColor3f(1,0.0f,0.0f);
glVertex3f( data[i+12],data[i+13], data[i+14]);
glEnd();
}
I'm really not sure what to do anymore. I'v made my application use VBO's and my cpu usage still goes into the 70's and 80's. My render proceedure works like this:
Set the camera transformation
if the shape has not been tesselated, tesselate it.
create it's VBO
if it has a VBO, use it.
You will notice I have display lists too, I might use these if VBO is not supported. I went and found an OpenGL demo that renders a 32000 poly mesh at 60fps on my PC and uses 4% cpu. I'm rendering about 10,000 polys # 60fps using vbos and its using 70-80%.
Here is my render proc:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
POINT hh = controls.MainGlFrame.GetMousePos();
POINTFLOAT S;
S.x = static_cast<float>(hh.x);
S.y = static_cast<float>(hh.y);
POINTFLOAT t;
t.x = 256;
t.y = 256;
POINT dimensions;
dimensions.x = 512;
dimensions.y = 512;
glDeleteTextures(1,&texName);
texName = functions.CreateGradient(col,t,S,512,512,true);
itt = true;
}
HDC hdc;
PAINTSTRUCT ps;
glEnable(GL_MULTISAMPLE_ARB);
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
hdc = BeginPaint(controls.MainGlContext.mhWnd,&ps);
//start OGL code
glClearColor( 1.0f, 1.0f, 1.0f, 0.0f );
if(!current.isdrawing)
glClear( GL_COLOR_BUFFER_BIT );
glPushMatrix();
glTranslatef(controls.MainGlFrame.GetCameraX(),
controls.MainGlFrame.GetCameraY(),0);
//glTranslatef(current.ScalePoint.x,current.ScalePoint.y,0);
glScalef(current.ScaleFactor,current.ScaleFactor,current.ScaleFactor);
//glTranslatef(-current.ScalePoint.x,-current.ScalePoint.y,0);
if(!current.isdrawing)
{
for(unsigned int currentlayer = 0; currentlayer < layer.size(); ++currentlayer)
{
PolygonTesselator.Init();
for(unsigned int i = 0; i < layer[currentlayer].Shapes.size(); i++)
{
if(layer[currentlayer].Shapes[i].DisplayListInt == -999)
{
gluTessNormal(PolygonTesselator.tobj, 0, 0, 1);
PolygonTesselator.Set_Winding_Rule(layer[currentlayer].Shapes[i].WindingRule);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName);
layer[currentlayer].Shapes[i].DisplayListInt = glGenLists(1);
glNewList(layer[currentlayer].Shapes[i].DisplayListInt,GL_COMPILE);
PolygonTesselator.SetDimensions(layer[currentlayer].Shapes[i].Dimensions,layer[currentlayer].Shapes[i].minima);
PolygonTesselator.Begin_Polygon();
for(unsigned int c = 0; c < layer[currentlayer].Shapes[i].Contour.size(); ++c)
{
if(layer[currentlayer].Shapes[i].Color.a != 0)
{
PolygonTesselator.Begin_Contour();
for(unsigned int j = 0; j < layer[currentlayer].Shapes[i].Contour[c].DrawingPoints.size(); ++j)
{
gluTessVertex(PolygonTesselator.tobj,&layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0],
&layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0]);
}
PolygonTesselator.End_Contour();
}
}
PolygonTesselator.End_Polygon();
glEndList();
PolygonTesselator.TransferVerticies(layer[currentlayer].Shapes[i].OutPoints);
glGenBuffersARB(1,&layer[currentlayer].Shapes[i].VBOInt);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,layer[currentlayer].Shapes[i].VBOInt);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,sizeof(GLfloat) * layer[currentlayer].Shapes[i].OutPoints.size(),
&layer[currentlayer].Shapes[i].OutPoints[0], GL_STATIC_DRAW_ARB);
InvalidateRect(controls.MainGlFrame.framehWnd,NULL,false);
}
else //run vbo
{
//glEnable(GL_TEXTURE_2D);
//glDisable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, texName);
glColor4f(layer[currentlayer].Shapes[i].Color.r,
layer[currentlayer].Shapes[i].Color.g,
layer[currentlayer].Shapes[i].Color.b,
layer[currentlayer].Shapes[i].Color.a);
//glColor4f(1,1,1,1);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, layer[currentlayer].Shapes[i].VBOInt);
//glCallList(layer[currentlayer].Shapes[i].DisplayListInt);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, layer[currentlayer].Shapes[i].OutPoints.size() / 2);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
glDisable(GL_TEXTURE_2D);
//Draw outlines
if(layer[currentlayer].Shapes[i].Outline.OutlinePoints.size() > 4)
{
glColor4f(layer[currentlayer].Shapes[i].Outline.OutlineColor.r
,layer[currentlayer].Shapes[i].Outline.OutlineColor.g
,layer[currentlayer].Shapes[i].Outline.OutlineColor.b
,layer[currentlayer].Shapes[i].Outline.OutlineColor.a);
}
}
PolygonTesselator.End();
}
}
glPopMatrix();
//end OGL code
glFlush();
SwapBuffers(hdc);
glDisable(GL_MULTISAMPLE_ARB);
EndPaint(controls.MainGlContext.mhWnd,&ps);
}
Why could I be getting such high cpu usage?
Under what conditions is that first bit of code run? There's a couple of suspicious-looking lines in there:
glDeleteTextures(1,&texName);
texName = functions.CreateGradient(col,t,S,512,512,true);
If you're deleting and recreating a texture every time you paint, that could get expensive. I couldn't say how expensive the OpenGL parts would be -- I'd expect uploading texture data to be reasonably efficient, even if deleting and creating texture names might be less so -- but perhaps CreateGradient is inherently slow. Or maybe you're accidentally hitting some kind of slow path for your graphics card. Or the function is creating all the mipmap levels. And so on.
Aside from that, some random ideas:
What is the present interval? If the buffer swap is set to sync with the monitor, you may incur a delay because of that. (You can use the WGL_EXT_swap_control extension to tweak this value.)
If all of this is being run in response to a WM_PAINT, check that you aren't getting unexpected extra WM_PAINTs for some reason.
Check that the polygon tesselator Init and End functions aren't doing anything, since they're being called every time, even if there's no tesselating to be done.
Based on the code snippet you have provided, you have (at one point) loops nested four layers deep. You may be seeing high CPU load due to running each of these loops an extremely large number of times. Can you give us any idea how many iterations these loops are having to run through?
Try grabbing a timestamp inside each loop iteration and compare it against the previous to see how long it is taking to run one iteration of each particular loop. This should help you determine what part of the function is taking up the bulk of your CPU time.