PDA

View Full Version : Drawing cubes properly; OpenGL c++ freeglut (windows)



nielsbwashere
03-14-2016, 03:01 PM
Hi everyone,
I have been working on some test game, where I basically make a 3D tile map and I render it.
The problem with this is, I did add checks to see what sides must be rendered, but the rendering is really weird because sometimes a side just disappears or it becomes transparent (at least part of it).
I render the cubes with quad vertexes and I use the debugging colors; orange = bottom, green = top, yellow = front, red = back, blue = left, purple = right.
I just started out with OpenGL, so please don't be to hard on me.



/*
* test.cpp
*
* Created on: Mar 12, 2016
* Author: Niels
*/

using namespace std;

#include <GL/glut.h>
#include <ctime>
#include <iostream>


//Run handler
const static int MAX_FPS = 60;
const static int FRAME_PERIOD = 1000 / MAX_FPS;
int behind, skip = 500;
bool init = false;

//Cam

double camrX=0,camrY=0,camrZ=0;

const int width=32, height=32, length=32;

unsigned char *data;

void initialize(){
glClearColor(0,0,0,0);
data = new unsigned char[width*height*length];
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
for(int k=0;k<length;k++)data[k*height*width+j*width+i] = i==0||j==0||i==width-1||j==height-1?1:rand()%2;
}
void update(){
camrX+=0.2;
camrY+=0.3;
camrZ+=0.1;
}

int disp = 5;
double dispSize = 1.0/disp;

void renderBlock(int i, int j, int k, unsigned char t, unsigned char sides){
if(t==0)return;

glBegin(GL_QUADS);

double x = (double)i/disp-1;
double y = (double)j/disp-1;
double z = (double)k/disp-1;
double e = x+dispSize;
double f = y+dispSize;
double g = z+dispSize;


if(sides&0x4){ //Front
glColor3f(1.0f,1.0f,0.0f);
glVertex3f(x, y, z);
glVertex3f(e, y, z);
glVertex3f(e, f, z);
glVertex3f(x, f, z);
}

if(sides&0x8){ //Back
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(x, y, g);
glVertex3f(e, y, g);
glVertex3f(e, f, g);
glVertex3f(x, f, g);
}

if(sides&0x2){ //Down
glColor3f(1.0f,0.5f,0.0f);
glVertex3f(x, y, z);
glVertex3f(e, y, z);
glVertex3f(e, y, g);
glVertex3f(x, y, g);
}

if(sides&0x10){ //Left
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(x, y, z);
glVertex3f(x, y, g);
glVertex3f(x, f, g);
glVertex3f(x, f, z);
}

if(sides&0x20){ //Right
glColor3f(1.0f,0.0f,1.0f);
glVertex3f(e, y, z);
glVertex3f(e, y, g);
glVertex3f(e, f, g);
glVertex3f(e, f, z);
}

if(sides&0x1){ //Up
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(x, f, z);
glVertex3f(e, f, z);
glVertex3f(e, f, g);
glVertex3f(x, f, g);
}
glEnd();
}

bool at(int i, int j, int k){
if(i<0||j<0||k<0||i>=width||j>=height||k>=length)return false;
return data[k*height*width+j*width+i]!=0;
}

unsigned char getSides(int i, int j, int k){
unsigned char result = 0;
if(!at(i,j,k-1))result|=0x8;
if(!at(i,j,k+1))result|=0x4;
if(!at(i+1,j,k))result|=0x20;
if(!at(i-1,j,k))result|=0x10;
if(!at(i,j+1,k))result|=0x1;
if(!at(i,j-1,k))result|=0x2;
return result;
}

void render(){
if(!init)return;
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0,0.0,-10.5);
glRotatef(camrX, 1.0, 0, 0);
glRotatef(camrY, 0, 1.0, 0);
glRotatef(camrZ, 0, 0, 1.0);
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
for(int k=0;k<length;k++){
unsigned char side = getSides(i,j,k);
if(side!=0){
renderBlock(i,j,k,data[k*height*width+j*width+i],side);
}
}
glRotatef(-camrX, 1.0, 0, 0);
glRotatef(-camrY, 0, 1.0, 0);
glRotatef(-camrZ, 0, 0, 1.0);
glTranslatef(0,0,10.5);
glutSwapBuffers();
}

//The thing called on an update tick of the window
void loop(){
if(!init){
init = true;
initialize();
}
long time = clock();
update();
glutPostRedisplay();
long interval = clock()-time;
if(interval>=FRAME_PERIOD){
behind+=interval-FRAME_PERIOD;
if(behind>=skip){
long ticks = (long)(0.4 * behind);
behind-=ticks;
}
}
else{
if(behind>0){
long sleep = FRAME_PERIOD-interval;
if(behind<=sleep){
sleep-=behind;
behind = 0;
}
else{
behind-=sleep;
sleep = 0;
}
Sleep(sleep);
}
else Sleep(FRAME_PERIOD-interval);
}
}
void reshape(int x, int y)
{
if(y==0||x==0)return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0,(double)x/y,0.5,20);
glMatrixMode(GL_MODELVIEW);
glViewport(0,0,x,y);
}

//Initiating the window on start
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutCreateWindow("3D cube test");
glutInitWindowSize(320, 320);
glutInitWindowPosition(50, 50);
glutReshapeFunc(reshape);
glutDisplayFunc(render);
glutIdleFunc(loop);
glutMainLoop();
return 0;
}


I would want to ask you, if you know what's wrong with this, because I tried a lot of things. Moving the 'chunk' away, so there was no way that it couldn't be rendered and even rotating the cubes themselves.
And last but not least, I would want to ask if anyone knows what is better: An array of pointers to chunks (16x512x16 blocks) or just an array of unsigned chars (= blockList). Is it right that the chunks method saves memory and the blockList type saves time?

Wanted result: In this case: a smooth cube, that is smooth from all sides. It should be that, because the blockList actually has blocks on all of the outside.
The smooth sides can be seen sometimes when the cube is turned a specific way.

Thank you for your time!
-Nielsbwashere