Chessboard in opengl - c++

I'm trying to create 5x5 chessboard in OpenGL. I have been able to design a 5x6, and 8x8 but the code just won't work for the 5x5.
Can someone look over the code and maybe point out where my mistake is as the width just wont change to 5?
Here is the part of the code i seem to have a problem with:
void drawScene()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-2.5*1.5, 0.0, 2.5*1.5);
for(double j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
for(i=0.0;i<(2.5*3.0);i+=3.0)
{
if(k%2!=0)
{
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
else
{
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
}
for(double j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
for(i=0.0;i<(2.5*3.0);i+=3.0)
{
if(k%2!=0)
{
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
else
{
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
}
}

If you have an odd number of columns, your "odd vs. even" for black vs white will go different than if you have an even number. I think the easiest way is to do one loop for all the Squares, and keep a bool white_or_black variable that is set to white_or_black = !white_or_black at the end of each loop.
There is also a large amount of duplicated code that could be made much simpler by having one loop rather than two.
[I'm not 100% sure what is going wrong in your code, so I'm not sure if this will ACTUALLY fix the problem - but I believe it's a worthwhile improvement].

Understand your problem first. You have to draw odd vs even for black vs white board that means at first row if you draw odd white board then you have to draw even black board and in next row even white board and odd black board. For completing 5*5 chessboard pattern for white and black board row wise is given below:
3*2
2*3
3*2
2*3
3*2
But code you provide is for equal number of white and black board so you have to change the logic.Here is the part of code where I used my logic to draw 5*5 chessboard and its works perfectly.
for(float j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
//for(i=0.0;i<(4*3.0);i+=3.0)
//{
if(k%2==0)
{
for(i=0.0;i<(3*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
else
{
for(i=0.0;i<(2*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_blackArea);
glPopMatrix();
}
}
//}
}
k=0;
for(float j=0.0;j>(-5*1.5);j-=1.5)
{
k++;
//for(i=0.0;i<(4*3.0);i+=3.0)
//{
if(k%2!=0)
{
for(i=0.0;i<(3*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
else
{
for(i=0.0;i<(2*3.0);i+=3.0){
glPushMatrix();
glTranslatef(i+1.5,0.0,j);
glCallList(_displayListId_whiteArea);
glPopMatrix();
}
}
}
k=0;
glutSwapBuffers();
}

I suspect that by "the width won't change to 5", you are observing a width of 4 or 6. Would that be correct? It's quite likely in that case to be an error due to double-precision arithmetic.
You see, you assume infinite precision in your loops, but it's quite conceivable that 5*1.5 is not the same as adding 1.5 five times.
What you should really do is have an integer loop from 1 to 5 (or 0 to 4), and then multiply that value by your square size to produce a co-ordinate. It's generally not a good idea to loop over doubles unless you know what you are doing and what can happen.
Another thing that you should PLEASE do is use constants instead of literals. Instead of peppering your code with the number 5, why not define:
const int BoardWidth = 5;
const int BoardHeight = 5;
Then it will be a lot easier to change.

Forget that code, it has bad potential, you should use ints as a counter to create the board. For example:
const unsigned BOARD_SIZE = 5;
for(unsigned i = 0; i < BOARD_SIZE; ++i){
for(unsigned j = 0; j < BOARD_SIZE; ++j){
drawBoardCell(i,j, (i*BOARD_SIZE + j) % 2 == 0);
}
}
void drawBoardCell(const int row, const int col, const bool isBlack){
glPushMatrix();
glTranslatef(col+1.5,0.0,row);
const int callId = isBlack ? _displayListId_blackArea : _displayListId_whiteArea;
glCallList(callId);
glPopMatrix();
}
That might not work at first try but it should give you a starting point.

Related

How do I draw a rectangular box using GL_TRIANGLE_STRIP?

I'm new to OpenGL programming and need some help wrapping my head around this issue. I found this answer detailing how to create a cube mesh using a GL_TRIANGLE_STRIP. However, I want to create a rectangular box where the one axis isn't just elongated but rather repeated, so that the geometry ends up something like this:
I can't figure out how I'm supposed to construct such a shape where the geometry gets generated correctly, with correct normals and closed ends, with the winding order to keep in mind and what-not.
How should I be thinking and defining the vertices?
The formula for the triangle strip cube does most of the work, all you have to do is extend the long faces to add more in between, which can be done with for loops.
There are two times the strip changes direction, both on the bottom face, so we just need a little manual work there. I wrote up this simple function to create vertices based on a length, and it will build a length by 1 by 1 rectangle.
void generateRect(int length, std::vector<glm::vec3>& vertices) {
std::vector<glm::vec3> vertexArray;
//Generate nescessary points
float x = length / 2.0f;
for (int i = 0; i <= length; i++) {
vertexArray.push_back(glm::vec3(x, -0.5f, 0.5f));
vertexArray.push_back(glm::vec3(x, -0.5f, -0.5f));
vertexArray.push_back(glm::vec3(x, 0.5f, 0.5f));
vertexArray.push_back(glm::vec3(x, 0.5f, -0.5f));
x -= 1.0f;
}
//+Y face
for (int i = 0; i <= length; i++) {
int index = i * 4 + 3;
vertices.push_back(vertexArray.at(index));
vertices.push_back(vertexArray.at(index - 1));
}
//Change direction (Half of -X face)
vertices.push_back(vertexArray.at(length * 4));
//+Z face
for (int i = length - 1; i >= 0; i--) {
int index = i * 4;
vertices.push_back(vertexArray.at(index + 2));
vertices.push_back(vertexArray.at(index));
}
//-Z face (+X face created as well)
for (int i = 0; i <= length; i++) {
int index = i * 4 + 3;
vertices.push_back(vertexArray.at(index));
vertices.push_back(vertexArray.at(index - 2));
}
//Change direction (Other half of -X face)
vertices.push_back(vertexArray.at(length * 4));
//-Y face
for (int i = length - 1; i >= 0; i--) {
int index = i * 4;
vertices.push_back(vertexArray.at(index + 1));
vertices.push_back(vertexArray.at(index));
}
}
From this we get our rectangle, and for texturing I just used a cubemap as I've been doing skyboxes. OpenGL is smart enough to know the winding order will be reversed every other triangle, so no need to do any fancy math. You just have to make sure it's right for the first one, in this case the first one is counter-clockwise.
For normal generation, it's a little harder as the vertices must share a normal as well, even if it's being used for a different face. I don't think there is a workaround, but I haven't done much with triangle strip so there may be, perhaps something to do with a geometry shader.

c++ Opengl handle elements drawn

I am currently working on a game and I want to know if there is any way of handling with the elements i am drawing . For example : if i draw in a loop 100 cubes , how can i show / hide the cube number 15 or 63 or n ... I thought that initializing elements in a list would work , but i didn't find any property of it that could help.
GLuint cube;
cube = glGenLists(1);
glNewList(cube,GL_COMPILE);
for(int i = -30; i < 3; i++) {
for(int j = -30; j < 3; j++) {
glPushMatrix();
glTranslatef(i*2.0,0,j * 2.0);
Dcube();
glPopMatrix();
}
}
glEndList();
//something like : glDeleteList(cube); but that only works with entire list not with individual objects..
You have a display list, very good. So now you're back to using your regular language primitives to simply call that function.
std::array<bool, 100> cubes;
std::fill(cubes.begin(), cubes.end(), true);
cubes[15] = false;
cubes[63] = false;
for (bool drawCube : cubes) {
if (drawCube) {
// move a bit, perhaps using glTranslate
glCallList(cube);
}
}
OpenGL isn't your statekeeper. It just draws what you tell it to, you're responsible for keeping your objects.

Alternative color of the box creating with POLYGON

I am to alternative box color for each polygon.
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
int evenoddcheck = 0;
int height = 50;
int width = 100;
glBegin(GL_POLYGON);
for( int a=0 ; a <= 1000 ; a=a+100 )
{
for( int b=0 ; b <= 500 ; b=b+50 )
{
if( evenoddcheck % 2 == 0 )
{
glColor3f(0.0f,0.0f,0.0f);
}
else {
glColor3f(1.0f,1.0f,1.0f);
}
glVertex2i(b,a);
glVertex2i(b,width+a);
glVertex2i(height+b,width+a);
glVertex2i(height+b,a);
evenoddcheck++;
}
}
glEnd();
glFlush();
}
work fine with single color, but when i render code it shows
http://s11.postimage.org/3ms3mmc4j/box.png
I tried your code first I also found same problem as you. I kept the glBegin() and glEnd inside the second for loop like this then it works fine because in each loop you draw ploygon and start the next so here you can use GL_POLYGON. But in you code as describe by #dantenwolf you can't get correct result by using GL_POLYGON you have to use GL_QUADS.
for( int a=0 ; a <= 100 ; a=a+10 )
{ for( int b=0 ; b <= 50 ; b=b+5 ).
{
glBegin(GL_POLYGON);
if( evenoddcheck % 2 == 0 )
{
glColor3f(0.0f,0.0f,0.0f);
}
else {
glColor3f(1.0f,1.0f,1.0f);
}
glVertex2i(b,a);
glVertex2i(b,width+a);
glVertex2i(height+b,width+a);
glVertex2i(height+b,a);
glEnd();
evenoddcheck++;
}
}
glFlush();
You're using GL_POLYGON, which only works for convex, coplanar primitives. What you're drawing is a bunch of vertices on a regular grid, connecting edges by quads: This clearly doesn't meet those constraints; also it completely messes up your topology. Simple fix: Replace GL_POLYGON with GL_QUADS.
Oh and you shouldn't use immediate mode (you know glBegin … glEnd) in the first place. It's been out of fashion for well over 15 years now (getting close to 20).

How to change a color to random in OpenGL?

I've tried countless times to try and get this to work. I've moved loads of it around but still, nothing works. When I press the M key, my lights are meant to change to random colours. However, they change just to white.
This is what i have...
float colorArray[100][3]; // Create an array for random colors
keyPressed function:
case 'm' | 'M':
updateLights(2);
break;
defined_to_openGL function:
for (int i = 0; i < 3; i++)
{
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-50*i/2,-20,0.5); // Begin the first circle at -50, -20. Then multiply by i to create a space between them.
drawLights(2.0f);
glPopMatrix();
if(i <= 3)
{
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-38,-20,0.5);
drawLights(2.0f);
glPopMatrix();
glPushMatrix();
glColor3f(colorArray[i][0],colorArray[i][1],colorArray[i][2]);
glTranslatef(-12,-20,0.5);
drawLights(2.0f);
glPopMatrix();
}
}
Update lights function:
{
cout << "update lights" << endl;
for(int i = 0; i < 3; i++)
{
colorArray[i][0] = rand() % 255;
colorArray[i][1] = rand() % 255;
colorArray[i][2] = rand() % 255;
glutPostRedisplay();
}
}
You are using glColor3f which accepts 3 float parameters in [0.0,1.0] for each color intensity while rand()%255 produces an output which is in [0,254].
You can either switch to glColor3ub( GLubyte red, GLubyte green, GLubyte blue) which accepts an unsigned byte (and change modulo to %256 since you are skipping a value with 255) or generate a value in [0.0,1.0]by changing your random generation to
rand()/((float)RAND_MAX+1)
but this mean that you will have to change the type of colorArray to GLFloat.

Shape object in Processing, translate individual shapes

I am facing difficulty with the translate() function for objects as well as objects in general in Processing. I went through the examples and tried to replicate the manners by which they instantiated the objects but cannot seem to even get the shapes to appear on the screen no less move them. I instantiate the objects into an array using a nested for loop and expect a grid of the objects to be rendered. However, nothing at all is rendered.
My nested for loop structure to instantiate the tiles:
for(int i=0; i<102; i++){
for(int j=0; j<102; j++){
tiles[i][j]=new tile(i,0,j);
tiles[i][j].display();
}
}
And the constructors for the tile class:
tile(int x, int y, int z){
this.x=x;
this.y=y;
this.z=z;
beginShape();
vertex(x,y,z);
vertex(x+1,y,z);
vertex(x+1,y,z-1);
vertex(x,y,z-1);
endShape();
}
Nothing is rendered at all when this runs. Furthermore, if this is of any concern, my translations(movements) are done in a method I wrote for the tile class called move which simply calls translate. Is this the correct way? How should one approach this? I can't seem to understand at all how to render/create/translate individual objects/shapes.
Transformations (such as translate, rotate, etc) do not work if you use beginShape() as you're simply specifying direct coordinates to draw to. If you're relying on the result of a translate to put an object into a visible location that could be why you're not having any results.
Also, depending on how you're looking at your scene, you probably have z coming towards the camera, so your objects are being drawn with you looking at them on the side, and since they are 2d objects you won't see anything, try using x/y or y/z instead of x/z which you are doing right now.
You can definitely use pushMatrix() and translate() with beginShape() and such, it may be not completely what you expect, but it will definitely move the things around from the default origin.
What is going wrong with your above example is that you are putting the drawing() code in the constructor where you should be putting it in the display function.
so:
public void display(Processing proc) {
proc.beginShape()
etc.
}
display() also needs to be called in the draw() loop, so initialize your tiles once and then display them in draw().
You should follow #Tyler's advice on drawing in a 2D plane(x/y, y/z, x/z).
Your shapes probably do not render because you might be drawing them once, and clearing the screen in the draw() method, but I'm not sure as I can't see the rest of your code.
Here's what I mean:
tile[][] tiles;
int numTiles = 51;//x and y number of tiles
void setup() {
size(400,400,P3D);
tiles = new tile[numTiles][numTiles];
for(int i=0; i<numTiles; i++)
for(int j=0; j<numTiles; j++)
tiles[i][j]=new tile(i,j,0,5);
}
void draw() {
background(255);
translate(width * .5,height * .5);
rotateY((float)mouseX/width * PI);
rotateX((float)mouseY/height * PI);
for(int i=0; i<numTiles; i++)
for(int j=0; j<numTiles; j++)
tiles[i][j].display();
}
class tile {
int x,y,z;
tile(int x, int y, int z,int s) {//s for size
this.x=x * s;
this.y=y * s;
this.z=z * s;
}
void display(){
beginShape(QUADS);
//XY plane
//*
vertex(x,y,z);
vertex(x+x,y,z);
vertex(x+x,y+y,z);
vertex(x,y+y,z);
//*/
endShape();
}
}
Since you're only drawing squares, you could use the rect() function.
int numSquares = 51,squareSize = 10;
void setup(){
size(400,400,P3D);
smooth();
}
void draw(){
background(255);
translate(width * .5, height * .5);
rotateY((float)mouseX/width * PI);
for(int j = 0 ; j < numSquares ; j++)
for(int i = 0 ; i < numSquares ; i++)
rect(i*squareSize,j*squareSize,squareSize,squareSize);
}
HTH