#ifndef GLAD #define GLAD #include #endif #include #include #include #include #include #include #include "block.hpp" #include "chunk.hpp" //Sets the type of each block in the same order as the enumeration BlockID BlockType blockTypes[] = { BlockType(GRASS_TOP,DIRT,GRASS_SIDE,Color(0x7cbd6b),WHITE,WHITE), BlockType(DIRT), BlockType(COBBLESTONE), BlockType(OAK_PLANKS), BlockType(OAK_LOG_TOP,OAK_LOG_TOP,OAK_LOG), BlockType(STONE), BlockType(OAK_LEAVES,Color(0x48b518)), BlockType(GLASS), BlockType(WATER,Color(0x3F76E4)) }; void Chunk::setBlock(int x,int y,int z,BlockID block){ blocks[16*16*x+16*y+z]=block; } BlockID Chunk::getBlock(int x,int y,int z){ return (BlockID)blocks[16*16*x+16*y+z]; } void Chunk::Generate(){ if(index.y>=0) for(int y=0;y<16;y++) for(int z=0;z<16;z++) for(int x=0;x<16;x++) setBlock(x,y,z, AIR); if(index.y<0) for(int y=0;y<16;y++) for(int z=0;z<16;z++) for(int x=0;x<16;x++) setBlock(x,y,z, DIRT_BLOCK); if(index.y==-1) for(int z=0;z<16;z++) for(int x=0;x<16;x++) setBlock(x,15,z,GRASS_BLOCK); } void Chunk::Draw(int texture){ glBindTexture(GL_TEXTURE_2D,texture); glBindVertexArray(VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSIGNED_INT,0); } Chunk::Chunk(){ } bool Chunk::checkInvalid(){ bool valid =true; for(int i=0;i<16*16*16;i++){ if(blocks[i]>8||blocks[i]<-1)valid=false; } return(valid); } void addFaceIndicesAndVertices(int block,int face, Vector3f pos, std::vector &indices,std::vector &vertices){ float s1=(float)(blockTypes[block].t[face])/(float)AM_TEXTURES; float s2=(float)(blockTypes[block].t[face]+1)/(float)AM_TEXTURES; float r = blockTypes[block].c[face].r; float g = blockTypes[block].c[face].g; float b = blockTypes[block].c[face].b; vertices.insert(vertices.end(), { #define x(index) pos.x+blockCoords[face][index] #define y(index) pos.y+blockCoords[face][index] #define z(index) pos.z+blockCoords[face][index] // positions //Color // texture coords x(0),y(1), z(2), r,g,b, s2,1.0, x(3),y(4), z(5), r,g,b, s1,1.0, x(6),y(7), z(8), r,g,b, s1,0.0, x(9),y(10),z(11), r,g,b, s2,0.0 }); int s = vertices.size()/8-4; indices.insert(indices.end(), { s+1,s+2,s+3, s,s+1,s+3, } ); } void Chunk::createMesh(){ glGenVertexArrays(1,&VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER,VBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); glVertexAttribPointer(0,3, GL_FLOAT, GL_FALSE,8*sizeof(float),NULL); glEnableVertexAttribArray(0); glVertexAttribPointer(1,3, GL_FLOAT, GL_FALSE,8*sizeof(float),(void*)(3*sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2,2, GL_FLOAT, GL_FALSE,8*sizeof(float),(void*)(6*sizeof(float))); glEnableVertexAttribArray(2); //Delete the mesh that was made earlier vertices.clear(); indices.clear(); for(int x=0;x<16;x++){ for(int y=0;y<16;y++){ for(int z=0;z<16;z++){ int block = getBlock(x,y,z); if(block==-1)continue; for(int face=0;face<6;face++){ switch(face){ //If the face next to a different block there is no //point to add it to the mesh, because the player //will not see it anyway case 0://TOP if(y!=15&&getBlock(x,y+1,z)!=-1)continue; break; case 1://SOUTH if(y!=0&&getBlock(x,y-1,z)!=-1)continue; break; case 2://NORTH if(z!=15&&getBlock(x,y,z+1)!=-1)continue; break; case 3://SOUTH if(z!=0&&getBlock(x,y,z-1)!=-1)continue; break; case 4://WEST if(x!=0&&getBlock(x-1,y,z)!=-1)continue; break; case 5://EAST if(x!=15&&getBlock(x+1,y,z)!=-1)continue; break; } addFaceIndicesAndVertices(block,face, Vector3f((float)x + 16.0*(float)index.x, (float)y + 16.0*(float)index.y, (float)z + 16.0*(float)index.z), indices,vertices ); }}}} glBindBuffer(GL_ARRAY_BUFFER,VBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); //Send the vertex data to the GPU glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(float), &vertices[0], GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size()*sizeof(int),&indices[0], GL_STATIC_DRAW); } void Chunk::deleteMesh(){ glDeleteVertexArrays(1,&VAO); glDeleteBuffers(1,&VBO); glDeleteBuffers(1,&EBO); } ChunkIndex::ChunkIndex(){} ChunkIndex::ChunkIndex(int _x, int _y, int _z){ x=_x; y=_y; z=_z; } ChunkIndex::ChunkIndex(Vector3f pos){ x=(int)floorf(pos.x/16.0); y=(int)floorf(pos.y/16.0); z=(int)floorf(pos.z/16.0); } ChunkIndex::ChunkIndex(Vector3i pos){ x=(int)floorf(pos.x/16.0); y=(int)floorf(pos.y/16.0); z=(int)floorf(pos.z/16.0); } bool ChunkIndex::operator!=(ChunkIndex c){ return(x!=c.x || y!=c.y || z!=c.z); } void ChunkIndex::Write(FILE* f){ fwrite(&x,1,sizeof(int),f); fwrite(&y,1,sizeof(int),f); fwrite(&z,1,sizeof(int),f); } void ChunkIndex::Read(FILE* f){ fread(&x,1,sizeof(int),f); fread(&y,1,sizeof(int),f); fread(&z,1,sizeof(int),f); } std::ostream& ChunkIndex::operator<<(std::ostream &out){ out << "(" << x <<", " << y <<", "<< z <<")" <