opengl not drawing some triangles [closed] - c++

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 1 year ago.
Improve this question
In opengl, I was attempting to write a program that would be able to draw multiple rectangles across the screen using triangles. Instead of writing down all of the vertices by hand, I wrote a nested for loop to generate the vertices. However, instead of drawing all the triangles, this program only outputs the last two triangles as a rectangle(see the pictures below). I'm sure that this way of generating triangles is hilariously bad and inefficient but that's not my main gripe with the output of this code.
Below is the nested for loop that adds the vertices to the array(be warned this code is absolutely disgusting)
float initTri1[] = { -1.5f, 0.5f, 0.0f, -1.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f };
float initTri2[] = { -1.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.5f, 0.0f };
float vertices[18*4];
float increment =0.0f;
// draws an amount of rectangles equal to the number after 18 in vertices
for (int j = 0; j < sizeof(vertices)/sizeof(vertices[0])/18; j++)
{
increment += 0.5f;
// draws triangle with hypotenuse on right side
for (int i = 0; i < 9; i++)
{
// shifts the value of the initial triangles x verticies by 0.5
if ((i + 1) % 3 != 1)
{
vertices[i+j*9] = initTri1[i];
}
// keeps the y and z values the same as the initial triangle.
else
{
vertices[i+j*9] = initTri1[i] + increment;
}
}
// sometimes draws the triangle with the hypotenuse on the left side
for (int i = 9; i < 18; i++)
{
// shifts the value of the initial triangles x verticies by 0.5
if ((i + 1) % 3 != 1)
{
vertices[i+j*9] = initTri2[i - 9];
}
// keeps the y and z values the same as the initial triangle.
else
{
vertices[i+j*9] = initTri2[i - 9] + increment;
}
}
}
Below are images of the outcome of generating: 2 triangles, 4 triangles, and 8 triangles respectively.

I didn't feel able to follow the index computations of OP. It was easier to try it out. The result looks wrong:
vertices[0]: -1, 0.5, 0
vertices[3]: -1, 0, 0
vertices[6]: -0.5, 0, 0
vertices[9]: -0.5, 0.5, 0
vertices[12]: -0.5, 0, 0
vertices[15]: 0, 0, 0
vertices[18]: 0, 0.5, 0
vertices[21]: 0, 0, 0
vertices[24]: 0.5, 0, 0
vertices[27]: 0.5, 0.5, 0
vertices[30]: 0.5, 0, 0
vertices[33]: 1, 0, 0
vertices[36]: 0.5, 0.5, 0
vertices[39]: 1, 0, 0
vertices[42]: 1, 0.5, 0
vertices[45]: 0, 8.40779e-45, 0
vertices[48]: 8.82286e-39, 0, 8.82332e-39
vertices[51]: 0, 5.87998e-39, 0
vertices[54]: 5.87998e-39, 0, 8.82286e-39
vertices[57]: 0, -4.13785e+09, 4.58841e-41
vertices[60]: 1.4013e-45, 0, 2.8026e-45
vertices[63]: 0, 8.82195e-39, 0
vertices[66]: 5.88135e-39, 0, 0
vertices[69]: 0, 0, 0
Demo on coliru
So, I just rewrote the loops instead of tediously debugging it. (That appeared the lesser evil to me.)
#include <iostream>
int main()
{
float initTri1[] = { -1.5f, 0.5f, 0.0f, -1.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f };
const size_t nTri1 = std::size(initTri1);
float initTri2[] = { -1.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.5f, 0.0f };
const size_t nTri2 = std::size(initTri2);
const size_t nRect = 4;
const size_t nVtcs = (nTri1 + nTri2) * nRect;
float vertices[nVtcs];
float increment = 0.0f;
for (size_t j = 0, k = 0; j < nRect; ++j) {
for (size_t i = 2; i < nTri1; i += 3) {
vertices[k++] = initTri1[i - 2] + increment;
vertices[k++] = initTri1[i - 1];
vertices[k++] = initTri1[i - 0];
}
for (size_t i = 2; i < nTri2; i += 3) {
vertices[k++] = initTri2[i - 2] + increment;
vertices[k++] = initTri2[i - 1];
vertices[k++] = initTri2[i - 0];
}
increment += 0.5f;
}
for (size_t k = 0; k < nVtcs; ++k) {
if (k % (nTri1 + nTri2) == 0) std::cout << '\n';
if (k % 3 == 0) {
std::cout << "vertices[" << k << "]: ";
}
std::cout << vertices[k];
std::cout << (k % 3 < 2 ? ", " : "\n");
}
}
Output:
vertices[0]: -1.5, 0.5, 0
vertices[3]: -1.5, 0, 0
vertices[6]: -1, 0, 0
vertices[9]: -1.5, 0.5, 0
vertices[12]: -1, 0, 0
vertices[15]: -1, 0.5, 0
vertices[18]: -1, 0.5, 0
vertices[21]: -1, 0, 0
vertices[24]: -0.5, 0, 0
vertices[27]: -1, 0.5, 0
vertices[30]: -0.5, 0, 0
vertices[33]: -0.5, 0.5, 0
vertices[36]: -0.5, 0.5, 0
vertices[39]: -0.5, 0, 0
vertices[42]: 0, 0, 0
vertices[45]: -0.5, 0.5, 0
vertices[48]: 0, 0, 0
vertices[51]: 0, 0.5, 0
vertices[54]: 0, 0.5, 0
vertices[57]: 0, 0, 0
vertices[60]: 0.5, 0, 0
vertices[63]: 0, 0.5, 0
vertices[66]: 0.5, 0, 0
vertices[69]: 0.5, 0.5, 0
Demo on coliru
The moral of the story:
Simpler code is faster to write.
Simpler code is running sooner.
Simpler code is maintenance friendly.
Profiling it, you might be surprised that simpler code might be even faster.

Related

How to draw a rotated texture including text on top of output texture buffer using OpenGL

I have developed an opengl application where we draw strings of text using freetype and opengl.
I want to achieve rotation capability for the text that I put on OpenGL window.
For instance, "This is a text" string should be calculated and put into a buffer on a plain background and then refactored with a rotation value, so that the text will be visible as such below
I also have a text background that is just a regular texture with a buffer. I manually fill this background with a uint8_t buffer which can contain anything ranging from a single colour to an image buffer.
struct Background{
Color color;
Texture* bg_texture;
int x, y;
int w, h;
uint8_t* buffer;
explicit Background(int x, int y):x(x), y(y)
{
};
void create_bg_buffer();
~Background()
{
free(buffer);
}
};
void Background::create_bg_buffer()
{
int w = this->w;
int h = this->h;
if (posix_memalign((void**)&this->buffer, 128, w * h * 4) != 0)
{
VI_ERROR("ERROR::FREETYTPE: Couldn't allocate frame buffer ");
}
int c = 0;
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
this->buffer[ c + 0 ] = this->color.get_color_char(Utils::RED);
this->buffer[ c + 1 ] = this->color.get_color_char(Utils::GREEN);
this->buffer[ c + 2 ] = this->color.get_color_char(Utils::BLUE);
this->buffer[ c + 3 ] = 0xFF;
c += 4;
}
}
}
I want users to be able to rotate this text with it's background with a given angle. In on itself, rotating this is a tedious task. So I want to draw the text inside the backgrounds buffer itself, and then rotate it.
Please note that the way I rotate a background, for different reasons is not using an opengl function but rather taking the rectangle's middle point and rotating each point manually and passing those points to opengl with this code:
cpp
...
GLfloat vertices[32] = {
// positions // colors // texture coords
pos.TR_x, pos.TR_y, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top right
pos.BR_x, pos.BR_y, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom right
pos.BL_x, pos.BL_y, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom left
pos.TL_x, pos.TL_y, 1.0f, 0.1f, 0.1f, 0.1f, 0.0f, 0.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
...
Every pos stands for a rotated position, with labels indicating positions such as TR stands for top-right.
We want to use a Framebuffer for the output buffer. Then we want to use this framebuffer to be used for actual OpenGL output.
How should we alter the render_text function so that it will use the framebuffer to prepare the string from each individual character.
void Text::render_text(float angle_rad, bool has_bg)
{
if(has_bg) background->bg_texture->render(background->w, background->h, background->buffer, 1);
int start_y = ty + background->h;
start_y = ( std::abs(start_y - SCR_HEIGHT) / 2);
int total_h_index = 0;
for(auto& line: lines)
{
line.y = start_y;
line.x = tx;
total_h_index += line.total_height + LINE_GAP;
calc_pos(line.x, line.y, line.total_width, line.total_height, total_h_index);
for (c = line.text.begin(); c != line.text.end(); c++)
{
Character ch = Characters[*c];
line.char_h.push_back(ch.Size.y);
line.chars_y.push_back( line.y - (ch.Size.y - ch.Bearing.y) );
}
}
// glEnable(GL_CULL_FACE);
// glDisable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader.use();
glUniform3f(glGetUniformLocation(shader.ID, "textColor"), color.r, color.g, color.b);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
GLfloat vertices[6][4] = {
{ 0.0, 1.0, 0.0, 0.0 },
{ 0.0, 0.0, 0.0, 1.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 0.0, 1.0, 0.0, 0.0 },
{ 1.0, 0.0, 1.0, 1.0 },
{ 1.0, 1.0, 1.0, 0.0 }
};
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
GLint transition_loc = glGetUniformLocation(shader.ID, "transparency");
glUniform1f(transition_loc, 1.0f);
for(auto& line: lines)
{
GLfloat char_x = 0.0f;
std::string str = line.text;
glm::mat4 transOriginM = glm::translate(glm::mat4(1.0f), glm::vec3(line.x, line.y, 0));
glm::mat4 rotateM = glm::rotate(glm::mat4(1.0f), glm::radians(-angle_rad), glm::vec3(0.0f, 0.0f, 1.0f));
int e = 0;
std::vector<glm::vec2> rotated_pos = calc_rotation(line.chars_x, line.chars_y, -angle_rad, line.total_width);
for (c = str.begin(); c != str.end(); c++)
{
Character ch = Characters[*c];
GLfloat w = ch.Size.x;
GLfloat h = ch.Size.y;
GLfloat xrel = rotated_pos[e].x ; // char_x
GLfloat yrel = rotated_pos[e].y;
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
e++; // Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
glm::mat4 transRelM = glm::translate(glm::mat4(1.0f), glm::vec3(xrel, yrel, 0));
glm::mat4 scaleM = glm::scale(glm::mat4(1.0f), glm::vec3(w, h, 1.0f));
// Keep the translation matrix that sets the position of the text before the rotation matrix
glm::mat4 modelM = transOriginM * transRelM * rotateM * scaleM;
GLint model_loc = glGetUniformLocation(shader.ID, "model");
glUniformMatrix4fv(model_loc, 1, GL_FALSE, glm::value_ptr(modelM));
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
}
}
As of now, "Adding a character or text" is completely independent from the background operation.
They are just positioned in a way, so it looks like it has a background.
Our aim is to use a single output buffer that will hold both background color and freetype text data.
Following is how we handle the texture and texture rotation mechanism :
#define _VERTICIZE_X(number, global) _VERTICIZE(number, global) - 1
#define _VERTICIZE_Y(number, global) _VERTICIZE(number, global) + 1
namespace OpenGL
{
Texture::Texture(int x, int y, int w, int h, int gw, int gh, float angle)
{
Utils::Point rotatedPoints[4] = {
{x, y},
{x + w, y},
{x, y + h},
{x + w, y + h},
};
Utils::RotateRectangle(rotatedPoints, angle);
pos.TL_x = _VERTICIZE_X(rotatedPoints[0].x, gw); pos.TL_y = -_VERTICIZE_Y(rotatedPoints[0].y, gh);
pos.TR_x = _VERTICIZE_X(rotatedPoints[1].x, gw); pos.TR_y = -_VERTICIZE_Y(rotatedPoints[1].y, gh);
pos.BL_x = _VERTICIZE_X(rotatedPoints[2].x, gw); pos.BL_y = -_VERTICIZE_Y(rotatedPoints[2].y, gh);
pos.BR_x = _VERTICIZE_X(rotatedPoints[3].x, gw); pos.BR_y = -_VERTICIZE_Y(rotatedPoints[3].y, gh);
}
int Texture::init(float alpha, std::string* filter, Utils::Color proj_filt)
{
shader = Shader("./src/opengl/shaders/texture_shaders/texture.vs", "./src/opengl/shaders/texture_shaders/texture.fs");
void RotateRectangle(Point (&points)[4], float angle) {
// Calculate the center point
Point center = { 0 };
for (int i = 0; i < 4; i++) {
center.x += points[i].x;
center.y += points[i].y;
}
center.x /= 4;
center.y /= 4;
// Rotate each point
float angleRadians = angle * M_PI / 180.0f;
float s = sin(angleRadians);
float c = cos(angleRadians);
for (int i = 0; i < 4; i++) {
// Subtract the center point to get a vector from the center to the point
Point vector = { points[i].x - center.x, points[i].y - center.y };
// Rotate the vector
float x = vector.x;
float y = vector.y;
vector.x = x * c - y * s;
vector.y = x * s + y * c;
// Add the center point back to the rotated vector to get the new point
points[i].x = vector.x + center.x;
points[i].y = vector.y + center.y;
}
}
How can we use a framebuffer so that all OpenGL and FreeType operation are going to be executed in a single output space, and following that depending our way we can rotate the whole text using this single output framebuffer ?

Performing multiple reflections in OpenGL

My assignment is to perform transformations (reflections) on a 2D object.
Lets say my original object is a circle:
o
I want to reflect it across a line y = 5 for example.
o | o
Then I want to reflect the two objects across a line x = 5 for example.
o o
__
o o
Then finally I want to reflect the four objects across a line y = 10 for example.
o o | o o
o o | o o
So ultimately I want the end result to include 8 circles.
My question is, how would I go about implementing that into my code?
This is the code for my project:
#include <glut.h>
GLfloat square[4][3] = {{5, 0,0}, {5,20,0},{-5,20,0}, {-5,0,0}};
GLfloat square2[4][3] = { { 10, -5,0 },{ 10,25,0 },{ 0,25,0 },{ 0,-5,0 } };
GLfloat square3[4][3] = { { 0, -5,0 },{ 0,25,0 },{ -10,25,0 },{ -10,-5,0 } };
GLfloat colors[3][3] = {{0,0,1},{1,1,1},{0,0,0}};
void draw_square(void){
glBegin(GL_POLYGON);
for(int i = 0; i < 4; i++){
glVertex3fv(square[i]);
}
glEnd();
}
void draw_square2(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square2[i]);
}
glEnd();
}
void draw_square3(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square3[i]);
}
glEnd();
}
void draw_ring(void){
for(int r =0; r < 360;r+=45){
glPushMatrix();
glRotated(r, 0,0,1);
glTranslated(0,50,0);
draw_square();
glPopMatrix();
}
}
void draw_ring2(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square2();
glPopMatrix();
}
}
void draw_ring3(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square3();
glPopMatrix();
}
}
The display function below creates the set of overlapping rings that I want to reflect. The way it is now, I only get one set of overlapping rings at the bottom left corner. I want the output to be 8 sets of overlapping rings. Ive been trying to find a way to create the reflections I need, but i cant seem to figure it out.
void display(void){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
glFlush();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(1000,600);
glutInitWindowPosition(200,100);
glutCreateWindow("Project 2");
glClearColor(1.0,1.0,0.0,1.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-100.0, 1000.0, -100.0,600.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutDisplayFunc(display);
glutMainLoop();
}
Any help would be greatly appreciated.
Note, that drawing by glBegin/glEnd sequences and the fixed function pipeline matrix stack is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
Anyway, if you want to tile the objects, then you can do this by nested loops:
void draw_object( void )
{
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int tile_x = 4;
int tile_y = 2;
float tile_dist = 200.0f;
for ( int x = 0; x < tile_x; ++ x )
{
for (int y = 0; y < tile_y; ++ y )
{
glPushMatrix();
glTranslatef( (float)x * tile_dist, (float)y * tile_dist, 0.0f );
draw_object();
glPopMatrix();
}
}
glFlush();
}
The same tile effect can be achieved by a recursive function:
void display_tiles_recursive( int level, float dist )
{
if ( level == 0 )
{
draw_object();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_tiles_recursive( level - 1, dist );
glTranslatef( offset_x, offset_y, 0.0f );
display_tiles_recursive( level - 1, dist );
glPopMatrix();
}
void display_mirror(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_tiles_recursive( 3, 200.0f );
glFlush();
}
If you want to achieve a repeated mirror effect, then have to mirror the even tiles along the x and y axis. The mirroring can be achieved by glScale. glScalef( -1.0f, 1.0f, 1.0f ); to mirror along the x-axis and glScalef( 1.0f, -1.0f, 1.0f ); to mirror along the y axis. You can extend the recursive tiling function to get this effect:
void display_mirror_recursive( int level, float dist, bool even_x, bool even_y )
{
if ( level == 0 )
{
glPushMatrix();
if ( even_x )
glScalef( -1.0f, 1.0f, 1.0f );
if ( even_y )
glScalef( 1.0f, -1.0f, 1.0f );
draw_object();
glPopMatrix();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_mirror_recursive( level - 1, dist, even_x, even_y );
glTranslatef( offset_x, offset_y, 0.0f );
if ( level == 1 )
even_y = !even_y;
if ( level == 2)
even_x = !even_x;
display_mirror_recursive( level - 1, dist, even_x, even_y );
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_mirror_recursive( 3, 200.0f, false, false );
glFlush();
}

creating cubes with for loop in opengl

I'm trying to create cubes in OpenGL/glut using a for loop but as yet I only get an overflow.
here's the code to create the cube with textures:
void Cubes1Class::render()
{
for (int face = 0; face < 6; face++)
{
if (face < 1)
{
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glVertex3fv(VertsZ[FacesZ[face][vert]]);
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glVertex3fv(VertsZ[FacesZ[face][vert]]);
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
}
}
glEnd();
}
}
and this is where I try to render it with a for loop:
CubesClass::CubesClass(int num) // constructor
{
numOfCubes = 3;
for (int i=0; i<numOfCubes; i++)
{
lst[i]=new Cubes1Class();
}
}
void CubesClass::render()
{
int x = 0;
numOfCubes = 3;
for (x = 0; x < numOfCubes; x++)
{
glPushMatrix();
glTranslatef(0.0, x, 0.0);
lst[x]->render();
glPopMatrix();
}
}
I can't figure out where I've gone wrong.
Any idea?
EDIT:
The cubes render fine without the for loop if I just render then translate then render then translate etc.
These are the arrays:
static GLfloat VertsZ[8][3] = {
{ -0.5, 0.5, -0.5 }, /* 0 left top rear */
{ 0.5, 0.5, -0.5 }, /* 1 right top rear */
{ 0.5, -0.5, -0.5 }, /* 2 right bottom rear */
{ -0.5, -0.5, -0.5 }, /* 3 left bottom rear */
{ -0.5, 0.5, 0.5 }, /* 4 left top front */
{ 0.5, 0.5, 0.5 }, /* 5 right top front */
{ 0.5, -0.5, 0.5 }, /* 6 right bottom front */
{ -0.5, -0.5, 0.5 } /* 7 left bottom front */
};
static GLuint FacesZ[6][4] = {
7, 6, 5, 4, /* front */
6, 2, 1, 5, /* right */
3, 7, 4, 0, /* left */
5, 1, 0, 4, /* top */
7, 6, 2, 3, /* bottom */
2, 3, 0, 1 /* rear */
};
static GLfloat TexZ[4][2] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
};
the cubes1Class is empty currently
It works now not sure why it just didn't
sorry if I wasted time :/
here's the end code:
#include "Cubes.h"
#include "bitmap.h"
static GLfloat VertsZ[8][3] = {
{ -0.5, 0.5, -0.5 }, /* 0 left top rear */
{ 0.5, 0.5, -0.5 }, /* 1 right top rear */
{ 0.5, -0.5, -0.5 }, /* 2 right bottom rear */
{ -0.5, -0.5, -0.5 }, /* 3 left bottom rear */
{ -0.5, 0.5, 0.5 }, /* 4 left top front */
{ 0.5, 0.5, 0.5 }, /* 5 right top front */
{ 0.5, -0.5, 0.5 }, /* 6 right bottom front */
{ -0.5, -0.5, 0.5 } /* 7 left bottom front */
};
static GLuint FacesZ[6][4] = {
7, 6, 5, 4, /* front */
6, 2, 1, 5, /* right */
3, 7, 4, 0, /* left */
5, 1, 0, 4, /* top */
7, 6, 2, 3, /* bottom */
2, 3, 0, 1 /* rear */
};
static GLfloat NormalsZ[6][3] = {
0, 0, 1, /* front */
1, 0, 0, /* right */
-1, 0, 0, /* left */
0, 1, 0, /* top */
0, -1, 0, /* bottom */
0, 0, -1 /* rear */
};
static GLfloat TexZ[4][2] = {
{0.0, 0.0 },
{0.0, 1.0 },
{1.0, 1.0 },
{1.0, 0.0 }
};
static CBitmap *bmp0; // the texture
static CBitmap *bmp1; // the texture
static GLuint texHandle[2]; // the open gl texture handle
void readTextureFile()
{
bmp0= new CBitmap("metal.bmp");
printf("bmp size %d %d\n",bmp0->GetWidth(),bmp0->GetHeight());
bmp1= new CBitmap("starTexture3.bmp");
printf("bmp size %d %d\n",bmp1->GetWidth(),bmp1->GetHeight());
glGenTextures(2, &texHandle[0]);
// Texture handle will be bound to the BMP bitmap data just
// as it was read in...
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glTexImage2D(GL_TEXTURE_2D,
0, // Mipmap level 0
3, // 3 bytes [R,G,B] per pixel
bmp0->GetWidth(), // width of bitmap
bmp0->GetHeight(), // height of bitmap
0, // no border pixels
GL_RGBA, // bitmap pixel format
GL_UNSIGNED_BYTE, // format for GL to store it
bmp0->GetBits() // pointer to the pixel data
);
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glTexImage2D(GL_TEXTURE_2D,
0, // Mipmap level 0
3, // 3 bytes [R,G,B] per pixel
bmp1->GetWidth(), // width of bitmap
bmp1->GetHeight(), // height of bitmap
0, // no border pixels
GL_RGBA, // bitmap pixel format
GL_UNSIGNED_BYTE, // format for GL to store it
bmp1->GetBits() // pointer to the pixel data
);
}
// ------------------------- Cubes1Class -----------------------------
Cubes1Class::Cubes1Class() // constructor
{
}
void Cubes1Class::render()
{
for (int face = 0; face < 6; face++)
{
if (face < 1)
{
glBindTexture(GL_TEXTURE_2D, texHandle[1]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
glVertex3fv(VertsZ[FacesZ[face][vert]]);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glBegin(GL_QUADS);
for (int vert = 0; vert <= 4; vert++)
{
glTexCoord2f(TexZ[vert][0], TexZ[vert][1]);
glVertex3fv(VertsZ[FacesZ[face][vert]]);
}
}
glEnd();
}
}
// ------------------------- CubesClass -----------------------------
//Cubes1Class *lst[MAX_NUM_CUBES]; // the cubes
//GLfloat angle[MAX_NUM_CUBES]; // the cubes rotations
CubesClass::CubesClass(int num) // constructor
{
numOfCubes = 4;
for (int i=0; i<numOfCubes; i++)
{
lst[i]=new Cubes1Class();
}
}
void CubesClass::render() // draw it
{
for (int i=0; i<numOfCubes; i++)
{
glPushMatrix();
glTranslatef(0.0, i, 0.0);
lst[i]->render();
glPopMatrix();
}
}

Picking in OpenGL using glRenderMode(GL_SELECT) and glReadPixels

I'm trying to do selection in opengl but it is not working.
I draw objects I receive from a .obj file (v, vn, f, o and such indices). Each object consists from "groups" and each group is a group of GL_POLYGON.
Here is the draw function:
void draw(GLenum mode) {
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0, 0, 1);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glColor3f(0, 1, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 100.0);
glEnd();
glColor4f(1.0, 1.0, 1.0, 1.0);
if (changeFOV) {
fovAngle += fovScale;
changeFOV = false;
setTransformations();
}
for (unsigned int i = 0; i < objects.size(); i++) {
objectItem currObject = objects[i];
for (unsigned int j = 0; j < currObject.getGroups().size(); j++) {
group currGroup = currObject.getGroups().at(j);
for (unsigned int k = 0; k < currGroup.getFs().size(); k++) {
if (mode == GL_SELECT)
glPushName(currGroup.getName());
glPushMatrix();
vector<pair<int, int> > currF = currGroup.getFs()[k];
glBegin(GL_POLYGON);
for (unsigned int kk = 0; kk < currF.size(); kk++) {
Vector3f currVertex = vertexes.at(
(currF.at(kk).first - 1 >= 0) ?
currF.at(kk).first - 1 : 0);
Vector3f currNormal = vertexesNormal.at(
(currF.at(kk).second - 1 >= 0) ?
currF.at(kk).second - 1 : 0);
glNormal3f(currNormal.x, currNormal.y, currNormal.z);
glVertex3f(currVertex.x / 1, currVertex.y / 1,
currVertex.z / 1);
}
glEnd();
glPopMatrix();
}
}
}
}
The drawing works ok and I see the object on the screen.
This is all the picking procedure
/* PICKING */
void processHits(GLint hits, GLuint *buffer) {
float z1, z2;
for (int i = 0; buffer[i] > 0; i += 5) {
z1 = buffer[i + 1] / 4294967295.0;
z2 = buffer[i + 2] / 4294967295.0;
printf("z1 = %f ,z2 = %f zValue = %f\n", z1, z2, zValue[0]);
if ((zValue[0] <= z1 + 0.0001 && zValue[0] >= z2 - 0.0001)
|| (zValue[0] >= z1 - 0.0001 && zValue[0] <= z2 + 0.0001)) { //try to locate which name is correlated with the pressed pixel according to z value
ii = buffer[i + 3];
jj = buffer[i + 4];
}
}
}
void startPicking(GLuint *selectionBuf) {
glSelectBuffer(bufSize, selectionBuf); //declare buffer for input in selection mode
glRenderMode(GL_SELECT); //change to selecting mode
glInitNames(); //initialize names stack
glPushName(-1); //push name
}
void pick(int button, int x, int y) {
//use selection mode to pick
glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_FLOAT, pix);
//printf("depth = %f, x = %d, y = %d\n",pixels[(viewport[3]-y)*512+x],x,viewport[3]-y);
glMatrixMode(GL_PROJECTION);
glReadPixels((GLdouble) x, (GLdouble) viewport[3] - y, 2, 2,
GL_DEPTH_COMPONENT, GL_FLOAT, zValue);
glPushMatrix(); //saves current projection matrix
startPicking(selectionBuf); //preper selection mode
glLoadIdentity();
gluPickMatrix((GLdouble) x, (GLdouble) viewport[3] - y, 1, 1, viewport); //change matrices so only the area of the picking pixel can be seen.
gluPerspective(fovAngle, 1, near, far); //return to perspective state
glMatrixMode(GL_MODELVIEW);
draw(GL_SELECT); //draws board on background
hits = glRenderMode(GL_RENDER); //gets hits number
glMatrixMode(GL_PROJECTION);
glPopMatrix(); //restores projection matrix
glMatrixMode(GL_MODELVIEW);
processHits(hits, selectionBuf); //check hits
if(hits > 0)
printf("touched: %d\n",selectionBuf[3]);
//printf("depth %f hits: %d\n\n",pixels[(viewport[3]-y)*512+x], hits);
if (zValue[0] < 1.0) {
isPick = true;
xx = x;
yy = y;
if (button == GLUT_RIGHT_BUTTON)
zMove = true;
else
zMove = false;
}
}
the pick function is called when the mouse is clicked (using opengl mouse function).
The error I'm receiving is that no objects appears to be hit when clicking on an object.
I'm using Ubuntu 14.04 LTS with Opengl 3.0
I don't know how to ask or what specifically ask, I would appreciate some inputs on the code if you see something wrong..
You seemed to have missed using glPopName()
GLNames used in the selection buffer are pushed on a stack. So unless you call glPopName() the stack would never unwind. The working of this is similar to the calls glPushMatrix() and glPopMatrix().
Typically this is what the code flow looks like.
//Push the name of the primitives on top of selection stack
glPushName(...)
//Set Transformations / Draw the primitives
..
..
//Pop the name (Clear the stack for pushing another name)
glPopName();

C++ Directx 11 Trying to XMMatrixTranslation a cube

Trying to modify the cube position with the XMMatrixTranslation function. Attached is the code...
// Rotate and modify position of cube around the origin
g_World = XMMatrixRotationY( t );
g_World = XMMatrixMultiply(g_World, XMMatrixTranslation(0, yDirection, 0));
// Modify the color
g_vMeshColor.x = ( sinf( t * 1.0f ) + 1.0f ) * 0.5f;
g_vMeshColor.y = ( cosf( t * 3.0f ) + 1.0f ) * 0.5f;
g_vMeshColor.z = ( sinf( t * 5.0f ) + 1.0f ) * 0.5f;
//
// Clear the back buffer
//
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
//
// Clear the depth buffer to 1.0 (max depth)
//
g_pImmediateContext->ClearDepthStencilView( g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0 );
//
// Update variables that change once per frame
//
CBChangesEveryFrame cb;
cb.mWorld = XMMatrixTranspose( g_World );
cb.vMeshColor = g_vMeshColor;
g_pImmediateContext->UpdateSubresource( g_pCBChangesEveryFrame, 0, NULL, &cb, 0, 0 );
//
// Render the cube
//
g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
g_pImmediateContext->VSSetConstantBuffers( 0, 1, &g_pCBNeverChanges );
g_pImmediateContext->VSSetConstantBuffers( 1, 1, &g_pCBChangeOnResize );
g_pImmediateContext->VSSetConstantBuffers( 2, 1, &g_pCBChangesEveryFrame );
g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
g_pImmediateContext->PSSetConstantBuffers( 2, 1, &g_pCBChangesEveryFrame );
g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV );
g_pImmediateContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );
g_pImmediateContext->DrawIndexed( 36, 0, 0 );
//
// Present our back buffer to our front buffer
//
g_pSwapChain->Present( 0, 0 );
When I press the down button the position of the cube is supposed to change in the negative y direction. The cube disappears when the I press the key.
Thanks,
Scott