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();
}
Related
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.
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 am given a constantly changing/updated buffer and I need to blit this buffer's pixels to the screen.
For my test code, I read a bitmap and stored it into a buffer.
The thing is, I want to ignore a specific colour when blitting it to the screen using OpenGL.
Currently I use:
glPushMatrix();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
unsigned char* Data = (unsigned char*)Buffer;
for (int I = Bmp.Height(); I > 0; --I)
{
for (int J = 0; J < Bmp.Width(); ++J)
{
if (Data[0] != 0 && Data[1] != 0 && Data[2] != 0) //If the colour is black, we don't draw it..
{
glRasterPos2i(J, I);
glDrawPixels(1, 1, GL_BGR, GL_UNSIGNED_BYTE, Data);
}
Data += Bmp.Bits() == 32 ? 4 : 3;
if(Bmp.Bits() == 24)
Data += (-Bmp.Width() * 3) & 3;
}
}
glPopMatrix();
SwapBuffers(DC);
Sleep(1);
So in the above, what I have is some Buffer pointer called Data. I then loop through it given a height and width. If the colour is black, I don't draw it.. Otherwise I use glDrawPixels in combination with glRasterPos2i to draw it to the screen one pixel at a time. Is there a more efficient way I can make it draw all pixels except a specific colour? It is a buffer not a texture. I used Bmp as an example.
You can use the Stencil buffer. There are also some ways to do chroma key by using the pixel shader.