From 74c6854fd8dcbaee736ac0421805ff1e03c4a1e2 Mon Sep 17 00:00:00 2001 From: iamn1ck Date: Sun, 19 Feb 2017 07:00:34 -0600 Subject: -quadtree and opengl rendering are now in the master branch ! -using sdl_rect for location and size ended up being not so great due to it not having floats, so we reverted back to using location -much, much refractoring is now needed --- src/creature.cpp | 103 +++++++++++++++++------------ src/entity.cpp | 17 +---- src/geoshader.cpp | 115 ++++++++++++++++++++++++++++++++ src/list.cpp | 78 ++++++++++++---------- src/main.cpp | 59 +++++++++++++---- src/quadtree.cpp | 140 +++++++++++++++++++++++++++++++++++++++ src/rectdrawer.cpp | 135 ++++++++++++++++++++++++++++++++++++++ src/resource.cpp | 20 ++++-- src/spritebatch.cpp | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/window.cpp | 40 +++++++----- 10 files changed, 767 insertions(+), 125 deletions(-) create mode 100644 src/geoshader.cpp create mode 100644 src/quadtree.cpp create mode 100644 src/rectdrawer.cpp create mode 100644 src/spritebatch.cpp (limited to 'src') diff --git a/src/creature.cpp b/src/creature.cpp index bd731d2..0484fd1 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1,16 +1,19 @@ #include "creature.hpp" -Creature::Creature(Window M, SDL_Rect R, Dna D) +Creature::Creature(Location t, Dna D) { - renderer = M.getRenderer(); - rect = R; + L = t; mine = D; - if(rect.x == 0 && rect.y == 0){ - rect.x = rand()%WINDOW_X; - rect.y = rand()%WINDOW_Y; + if(L.x == 0 && L.y == 0){ + L.x = -30.0 + static_cast (rand()) / (static_cast (RAND_MAX/(30-(-30)))); + L.y = -30.0 + static_cast (rand()) / (static_cast (RAND_MAX/(30-(-30)))); } + gfxData.sides = 4.0; + gfxData.x = L.x; + gfxData.y = L.y; + type = CREATURE_TYPE; health = mine.maxHealth/2; gender = rand() % 2; @@ -19,6 +22,22 @@ Creature::Creature(Window M, SDL_Rect R, Dna D) pregnancyReady = false; pregnate = false; hasTarget = false; + + if(gender){ + gfxData.r = 1.0; + gfxData.g = 0.0; + gfxData.b = 0.0; + } + else if(pregnate){ + gfxData.r = 1.0; + gfxData.g = 0.0; + gfxData.b = 1.0; + } + else{ + gfxData.r = 0.0; + gfxData.g = 0.0; + gfxData.b = 1.0; + } } void Creature::Behavior() @@ -59,8 +78,8 @@ void Creature::Priority() void Creature::setTarget() { - std::random_shuffle(N.begin(),N.end()); - for(std::vector ::iterator it = N.begin(); it!=N.end(); it++){ + //std::random_shuffle(N.begin(),N.end()); + for(std::list ::iterator it = N.begin(); it!=N.end(); it++){ if( (*it)->getType() == RESOURCE_TYPE && hungry){ target = *it; hasTarget = true; @@ -77,14 +96,18 @@ void Creature::setTarget() if(!hasTarget&&!wander){ wander = true; - SDL_Rect r = {rand() % WINDOW_X, rand() % WINDOW_Y, 0, 0}; - wTarget = r; + float x = -30.0 + static_cast (rand()) / (static_cast (RAND_MAX/(30-(-30)))); + float y = -30.0 + static_cast (rand()) / (static_cast (RAND_MAX/(30-(-30)))); + Location tmp; + tmp.x = x; + tmp.y = y; + wTarget = tmp; } } void Creature::checkTarget() { - for(std::vector ::iterator it = N.begin(); it!=N.end(); it++) + for(std::list ::iterator it = N.begin(); it!=N.end(); it++) if( target == *it ) return; @@ -95,64 +118,64 @@ void Creature::checkTarget() void Creature::Action() { if(hasTarget){ - if( Distance(rect,target->getRect()) < mine.reach && target->getType() == RESOURCE_TYPE){ + if( Distance(L,target->getLocation()) < mine.reach && target->getType() == RESOURCE_TYPE){ target->eat(mine.bite); health+=mine.bite; amountAte++; - if(rect.w <= mine.sizeMax && mine.amountToGrow <= amountAte){ - amountAte = 0; - rect.w = rect.h = rect.w + 1; - } + //if(L.w <= mine.sizeMax && mine.amountToGrow <= amountAte){ + // amountAte = 0; + // L.w = L.h = L.w + 1; + //} if(target->getAmount()<=0) hasTarget = false; } - else if( Distance(rect,target->getRect()) < mine.reach && target->getType() == CREATURE_TYPE && target->getGender() != gender ){ + else if( Distance(L,target->getLocation()) < mine.reach && target->getType() == CREATURE_TYPE && target->getGender() != gender ){ target->impregnate(mine); hasTarget = false; } else - moveTowards(target->getRect()); + moveTowards(target->getLocation()); } else if(wander){ - if(Distance(rect,wTarget) < mine.reach) + if(Distance(L,wTarget) < mine.reach) wander = false; else moveTowards(wTarget); } } -void Creature::moveTowards(SDL_Rect R) +void Creature::moveTowards(Location t) { - if( rect.x == R.x ){ - if( rect.y < R.y ) - rect.y+=mine.speed; + if( L.x == t.x ){ + if( L.y < t.y ) + L.y+=mine.speed; else - rect.y-=mine.speed; + L.y-=mine.speed; } - else if( rect.y == R.y ){ - if( rect.x < R.x ) - rect.x+=mine.speed; + else if( L.y == t.y ){ + if( L.x < t.x ) + L.x+=mine.speed; else - rect.x-=mine.speed; + L.x-=mine.speed; } - else if( rect.x < R.x ){ - if( rect.y < R.y ){ - rect.x+=mine.speed; - rect.y+=mine.speed; + else if( L.x < t.x ){ + if( L.y < t.y ){ + L.x+=mine.speed; + L.y+=mine.speed; } else{ - rect.x+=mine.speed; - rect.y-=mine.speed; + L.x+=mine.speed; + L.y-=mine.speed; } } - else if ( rect.x > R.x ){ - if( rect.y < R.y ){ - rect.x-=mine.speed; - rect.y+=mine.speed; + else if ( L.x > t.x ){ + if( L.y < t.y ){ + L.x-=mine.speed; + L.y+=mine.speed; } else{ - rect.x-=mine.speed; - rect.y-=mine.speed; + L.x-=mine.speed; + L.y-=mine.speed; } } } diff --git a/src/entity.cpp b/src/entity.cpp index a2c2d87..13bd290 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -2,19 +2,6 @@ void Entity::Place() { - if(type == CREATURE_TYPE){ - if(gender) - SDL_SetRenderDrawColor(renderer,255,0,0,255); - else - if(pregnate) - SDL_SetRenderDrawColor(renderer,255,0,255,255); - else - SDL_SetRenderDrawColor(renderer,0,0,255,255); - } - else if (type == RESOURCE_TYPE) - SDL_SetRenderDrawColor(renderer,0,255,0,255); - - SDL_RenderFillRect(renderer, &rect); - - SDL_SetRenderDrawColor(renderer,0,0,0,0); + gfxData.x = L.x; + gfxData.y = L.y; } diff --git a/src/geoshader.cpp b/src/geoshader.cpp new file mode 100644 index 0000000..b870313 --- /dev/null +++ b/src/geoshader.cpp @@ -0,0 +1,115 @@ +#include "geoshader.hpp" +#include +#include + +GeoShader::GeoShader(const std::string& fileName) +{ + m_program = glCreateProgram(); + + /* load shader from static vars + m_shaders[0] = CreateShader(GL_VERTEX_SHADER, vertexShaderSrc); + m_shaders[1] = CreateShader(GL_FRAGMENT_SHADER, fragmentShaderSrc); + m_shaders[2] = CreateShader(GL_GEOMETRY_SHADER, geometryShaderSrc); + */ + + m_shaders[0] = CreateShader(LoadShader(fileName + ".vert"), GL_VERTEX_SHADER); + m_shaders[1] = CreateShader(LoadShader(fileName + ".frag"), GL_FRAGMENT_SHADER); + m_shaders[2] = CreateShader(LoadShader(fileName + ".geom"), GL_GEOMETRY_SHADER); + + + for(unsigned int i=0; i < NUM_SHADERS; i++) + glAttachShader(m_program, m_shaders[i]); + + glLinkProgram(m_program); + CheckShaderError(m_program, GL_LINK_STATUS, true, "error shader failed to link: "); + + glValidateProgram(m_program); + CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "error shader is invalid: "); + + glUseProgram(m_program); +} + +GeoShader::~GeoShader() +{ + for(unsigned int i=0; i< NUM_SHADERS; i++){ + glDetachShader(m_program, m_shaders[i]); + glDeleteShader(m_shaders[i]); + } +} + +void GeoShader::Bind() +{ + glUseProgram(m_program); +} + + +void GeoShader::Update(const Transform& transform, const Camera& camera) +{ + glm::mat4 MVP = transform.GetMVP(camera); + glm::mat4 Normal = transform.GetModel(); + + glUniformMatrix4fv(m_uniforms[0], 1, GL_FALSE, &MVP[0][0]); +} + +GLuint GeoShader::CreateShader(const std::string& text, GLenum shaderType) +{ + GLuint shader = glCreateShader(shaderType); + if(shader == 0) + std::cerr << "Error: Shader Creation Failed" << std::endl; + + const GLchar* shaderSource[1]; + GLint shaderSourceLengths[1]; + + shaderSource[0] = text.c_str(); + shaderSourceLengths[0] = text.length(); + + glShaderSource(shader, 1, shaderSource, shaderSourceLengths); + glCompileShader(shader); + + CheckShaderError(shader, GL_COMPILE_STATUS, false, "error shader compilation failed to link: "); + + return shader; +} + + +void GeoShader::CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string& errorMessage) +{ + GLint success = 0; + GLchar error[1024] = { 0 }; + + if(isProgram) + glGetProgramiv(shader, flag, &success); + else + glGetShaderiv(shader, flag, &success); + + if(success == GL_FALSE) + { + if(isProgram) + glGetProgramInfoLog(shader, sizeof(error), NULL, error); + else + glGetShaderInfoLog(shader, sizeof(error), NULL, error); + + std::cerr << errorMessage << ": '" << error << "'" << std::endl; + } +} + +std::string GeoShader::LoadShader(const std::string& fileName) +{ + std::ifstream file; + file.open((fileName).c_str()); + + std::string output; + std::string line; + + if(file.is_open()){ + while(file.good()){ + getline(file, line); + output.append(line + "\n"); + } + } + else{ + std::cerr << "Unable to load shader: " << fileName << std::endl; + } + + return output; +} diff --git a/src/list.cpp b/src/list.cpp index afe51a3..fab5813 100644 --- a/src/list.cpp +++ b/src/list.cpp @@ -1,30 +1,33 @@ #include "list.hpp" -List::List(Window m) +List::List() { - main = m; + int i; + Dna defaultDNA; + //SDL_Rect rect = {0,0,defaultDNA.sizeMax/5,defaultDNA.sizeMax/5}; + Location tmp; + tmp.x = tmp.y = 0; + for(i=0;i::iterator it = C.begin(); it!=C.end(); it++) if(it->getHealth()<=0){ - SDL_Rect Rect = it->getRect(); - Resource r = Resource(main,Rect); + Location tmp = it->getLocation(); + Resource r = Resource(tmp); R.push_back(r); C.erase(it--); } @@ -37,15 +40,14 @@ void List::Remove() void List::Behavior() { for(std::list::iterator it = C.begin(); it!=C.end(); it++){ - std::vector N = getNear(*it); + std::list N = getNear(*it); it->giveN(N); it->Behavior(); if(it->getPregnancyReady()){ Dna D = it->getChildDNA(); - SDL_Rect rect = it->getRect(); - rect.h = rect.w = D.sizeMax / 5; - Creature X(main,rect,D); + Location tmp = it->getLocation(); + Creature X(tmp,D); C.push_back(X); it->hadPregnancy(); } @@ -57,34 +59,38 @@ void List::Behavior() void List::Place() { - SDL_Rect rect = {0,0,RESOURCE_SIZE_START,RESOURCE_SIZE_START}; + tree.clear(); + + Location tmp; + tmp.x = tmp.y = 0; while(R.size() < MINIMUM_RESOURCES){ - Resource Y(main,rect); + Resource Y(tmp); R.push_back(Y); } - for(std::list::iterator it = C.begin(); it!=C.end(); it++) + for(std::list::iterator it = C.begin(); it!=C.end(); it++){ it->Place(); + tree.insert(&(*it));; + } - for(std::list::iterator it = R.begin(); it!=R.end(); it++) + for(std::list::iterator it = R.begin(); it!=R.end(); it++){ it->Place(); + tree.insert(&(*it));; + } } -std::vector List::getNear(Creature nC) +std::list List::getNear(Creature nC) { - std::vector N; - - for(std::list::iterator it = R.begin(); it!=R.end(); it++) - if(nC.getBestSense() > Distance(nC.getRect(),it->getRect())) - N.push_back(&(*it)); - - for(std::list::iterator it = C.begin(); it!=C.end(); it++) - if(&nC == &(*it)) - continue; - else if(nC.getBestSense() > Distance(nC.getRect(),it->getRect())) - N.push_back(&(*it)); + std::list N; + N.clear(); + N = tree.retrieve(N, nC.getGFXD()); + //std::vector x{std::begin(N),std::begin(N)}; return N; } +std::vector List::drawQuadTree(){ + return tree.Draw(); +} + diff --git a/src/main.cpp b/src/main.cpp index 5170bf3..e385f9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,16 +3,36 @@ int main() { srand(time(NULL)); - Window main; - List L(main); - Event e; - Timer fps; - int speed = 60; - bool pause = false; + Window main(WINDOW_X, WINDOW_Y, "natures"); + List L; + Event e; + + //New opengl stuff + Transform transform; + Camera camera(glm::vec3(0,0,70), 70.0f, (float)800/(float)600, 0.01f, 1000.0f); + GeoShader shader("./inc/opengl/theshader"); + GeoShader shader2("./inc/opengl/basicshader"); + Rectdrawer rectrenderer(shader2); + SpriteBatch _spriteBatch(shader); + + _spriteBatch.init(); + shader.Bind(); + + int uniModel = glGetUniformLocation(shader.m_program, "MVP"); + glUniformMatrix4fv(uniModel, 1, false, &transform.GetMVP(camera)[0][0]); + shader2.Bind(); + + int uniModel2 = glGetUniformLocation(shader2.m_program, "MPV"); + glUniformMatrix4fv(uniModel2, 1, false, &transform.GetMVP(camera)[0][0]); + int countedFrames = 0; + + Timer fps; + int speed = 60; + bool pause = false; while(e.gRun()){ - fps.Start(); + //fps.Start(); while(e.Poll()){ if(e.gEventType() == SDL_QUIT) e.off(); @@ -26,19 +46,34 @@ int main() } if(!pause){ - main.Clear(); + main.Clear(0.0f,0.0f,0.0f,1.0f); L.Remove(); L.Behavior(); L.Place(); - main.Render(); + shader.Bind(); + _spriteBatch.begin(); + for(std::list::iterator it = L.C.begin(); it != L.C.end(); it++) + _spriteBatch.draw(it->gfxData);; + + for(std::list::iterator it = L.R.begin(); it != L.R.end(); it++) + _spriteBatch.draw(it->gfxData);; + + _spriteBatch.end(); + _spriteBatch.renderBatch(); + + main.swapBuffers(); } - if(fps.getTicks() < (1000 / speed)) - SDL_Delay((1000 / speed) - fps.getTicks()); + float avgFPS = countedFrames / ( fps.getTicks() / 1000.f ); + if( avgFPS > 200000 ){ + avgFPS = 0; + } + ++countedFrames; + //if(fps.getTicks() < (1000 / speed)) + // SDL_Delay((1000 / speed) - fps.getTicks()); } - main.Destroy(); return 0; } diff --git a/src/quadtree.cpp b/src/quadtree.cpp new file mode 100644 index 0000000..e347e55 --- /dev/null +++ b/src/quadtree.cpp @@ -0,0 +1,140 @@ +#include "quadtree.hpp" + + +Quadtree::Quadtree(){} + +Quadtree::Quadtree(int pLevel, Rectangle pBounds){ + level = pLevel; + bounds = pBounds; + isNull=false; + nodes = new Quadtree[4]; + gfxDataRect.x = pBounds.x * 1.01; + gfxDataRect.y = pBounds.y * 1.05; + gfxDataRect.r = 255; + gfxDataRect.g = 0; + gfxDataRect.b = 255; + gfxDataRect.sides = pBounds.height; +} + +void Quadtree::clear(){ + objects.clear(); + + for (int i = 0; i < 4; i++) + if (!nodes[i].isNull) { + nodes[i].objects.clear(); + nodes[i].clear(); + } + + delete[] nodes; + if(level == 0) + nodes = new Quadtree[4]; + } + + void Quadtree::split(){ + float subWidth = (bounds.getWidth() / 2); + float subHeight = (bounds.getHeight() / 2); + float x = bounds.getX(); + float y = bounds.getY(); + + + Rectangle R0(x + subWidth/2, y + subHeight/2, subWidth, subHeight); + Rectangle R1(x - subWidth/2, y + subHeight/2, subWidth, subHeight); + Rectangle R2(x - subWidth/2, y - subHeight/2, subWidth, subHeight); + Rectangle R3(x + subWidth/2, y - subHeight/2, subWidth, subHeight); + + Quadtree Q0(level+1, R0); + Quadtree Q1(level+1, R1); + Quadtree Q2(level+1, R2); + Quadtree Q3(level+1, R3); + + nodes[0] = Q0; + nodes[1] = Q1; + nodes[2] = Q2; + nodes[3] = Q3; +} + + +int Quadtree::getIndex(GraphicsData object) { + int index = -1; + + bool topQuadrant = (object.getY() > bounds.getY()); + bool bottomQuadrant = (object.getY() < bounds.getY()); + + if (object.getX() < bounds.getX()) { + if (topQuadrant) + index = 1; + else if (bottomQuadrant) + index = 2; + } + else if (object.getX() > bounds.getX()) { + if (topQuadrant) + index = 0; + else if (bottomQuadrant) + index = 3; + } + + return index; +} + +void Quadtree::insert(Entity* iter){ + if (!nodes[0].isNull) { + int index = getIndex((*iter).getGFXD()); + if (index != -1) { + nodes[index].insert(iter); + return; + } + } + + objects.emplace_back(iter); + + if (objects.size() > MAX_OBJECTS && level < MAX_LEVELS) { + if (nodes[0].isNull) + split(); + + + for(std::list ::iterator it = objects.begin(); it!=objects.end();it++){ + int index = getIndex((*it)->getGFXD()); + if (index != -1) { + nodes[index].insert(*it); + objects.erase(it--); + } + } + } +} + + +std::vector Quadtree::Draw(){ + std::vector retdat; + + for (int i = 0; i < 4; i++) { + if (!nodes[i].isNull) { + std::vector temp = nodes[i].Draw(); + retdat.insert(retdat.end(), temp.begin(), temp.end()); + } + } + + if (!nodes[0].isNull) + retdat.emplace_back(nodes[0].gfxDataRect); + if (!nodes[1].isNull) + retdat.emplace_back(nodes[1].gfxDataRect); + if (!nodes[2].isNull) + retdat.emplace_back(nodes[2].gfxDataRect); + if (!nodes[3].isNull) + retdat.emplace_back(nodes[3].gfxDataRect); + + retdat.emplace_back(gfxDataRect); + + return retdat; +} + +std::list Quadtree::retrieve(std::list returnObjects, GraphicsData obj) { + int index = getIndex(obj); + if (index != -1 && !nodes[0].isNull) { + returnObjects = nodes[index].retrieve(returnObjects, obj); + } + for(std::list ::iterator it = objects.begin(); it!=objects.end(); it++){ + returnObjects.emplace_back(*it); + } + + return returnObjects; +} diff --git a/src/rectdrawer.cpp b/src/rectdrawer.cpp new file mode 100644 index 0000000..980f348 --- /dev/null +++ b/src/rectdrawer.cpp @@ -0,0 +1,135 @@ +#include "rectdrawer.hpp" + +Rectdrawer::Rectdrawer(GeoShader theshader) : _vbo(0), _vao(0), shader(theshader){ + // Generate the VAO if it isn't already generated + if (_vao == 0) { + glGenVertexArrays(1, &_vao); + } + + // Bind the VAO. All subsequent opengl calls will modify it's state. + glBindVertexArray(_vao); + + //G enerate the VBO if it isn't already generated + if (_vbo == 0) { + glGenBuffers(1, &_vbo); + } + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + + //Tell opengl what attribute arrays we need + GLint posAttrib = glGetAttribLocation(shader.m_program, "pos"); + glEnableVertexAttribArray(posAttrib); + + GLint colAttrib = glGetAttribLocation(shader.m_program, "color"); + glEnableVertexAttribArray(colAttrib); + + GLint sidesAttrib = glGetAttribLocation(shader.m_program, "sides"); + glEnableVertexAttribArray(sidesAttrib); + + // glEnableVertexAttribArray(2); + + //This is the position attribute pointer + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), 0); //This is the color attribute pointer + glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), (void*) (2 * sizeof(float))); //This is the UV attribute pointer + glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), (void*) (5 * sizeof(float))); + glBindVertexArray(0); + + +} + +Rectdrawer::~Rectdrawer() +{ +} + +void Rectdrawer::draw(const GraphicsData& gfxData) { + _gfx.emplace_back(gfxData); +} + + + +void Rectdrawer::begin() { + _renderBatches.clear(); + _gfx.clear(); +} + +void Rectdrawer::end() { + // Set up all pointers for fast sorting + _gfxPtr.resize(_gfx.size()); + for (int i = 0; i < _gfx.size(); i++) { + _gfxPtr[i] = &_gfx[i]; + } + + //sortGlyphs(); + createRenderBatches(); +} + +void Rectdrawer::renderBatch() { + + // Bind our VAO. This sets up the opengl state we need, including the + // vertex attribute pointers and it binds the VBO + glBindVertexArray(_vao); + + for (int i = 0; i < _renderBatches.size(); i++) { + glDrawArrays(GL_POINTS, _renderBatches[i].offset, _renderBatches[i].numVertices); + } + glBindVertexArray(0); +} + + +// needs edit here for rectangle instead of other geometry +void Rectdrawer::createRenderBatches() { + // This will store all the vertices that we need to upload + std::vector vertices; + // Resize the buffer to the exact size we need so we can treat + // it like an array + vertices.resize(_gfxPtr.size() * 6); + + if (_gfxPtr.empty()) { + return; + } + + int offset = 0; // current offset + int cv = 0; // current vertex + + //Add the first batch + _renderBatches.emplace_back(offset, 6); + vertices[cv++] = _gfxPtr[0]->x; + vertices[cv++] = _gfxPtr[0]->y; + vertices[cv++] = _gfxPtr[0]->r; + vertices[cv++] = _gfxPtr[0]->g; + vertices[cv++] = _gfxPtr[0]->b; + vertices[cv++] = _gfxPtr[0]->sides; + + offset += 6; + + //Add all the rest of the glyphs + //std::cout << "ptr size = " << _gfxPtr.size() << std::endl; + for (int cg = 1; cg < _gfxPtr.size(); cg++) { + + _renderBatches.back().numVertices += 6; + + vertices[cv++] = _gfxPtr[cg]->x; + vertices[cv++] = _gfxPtr[cg]->y; + vertices[cv++] = _gfxPtr[cg]->r; + vertices[cv++] = _gfxPtr[cg]->g; + vertices[cv++] = _gfxPtr[cg]->b; + vertices[cv++] = _gfxPtr[cg]->sides; + + offset += 6; + } + + + + // Bind our VBO + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + // Orphan the buffer (for speed) + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), nullptr, GL_DYNAMIC_DRAW); + // Upload the data + glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data()); + + // Unbind the VBO + glBindBuffer(GL_ARRAY_BUFFER, 0); + +} diff --git a/src/resource.cpp b/src/resource.cpp index ee9100a..31811ca 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -1,15 +1,21 @@ #include "resource.hpp" -Resource::Resource(Window M, SDL_Rect R) +Resource::Resource(Location t) { - renderer = M.getRenderer(); - rect = R; + L = t; - if(rect.x == 0 && rect.y == 0){ - rect.x = rand()%WINDOW_X; - rect.y = rand()%WINDOW_Y; + if(L.x == 0 && L.y == 0){ + L.x = -30 + static_cast (rand()) / (static_cast (RAND_MAX/(30.0-(-30.0)))); + L.y = -30 + static_cast (rand()) / (static_cast (RAND_MAX/(30.0-(-30.0)))); } + gfxData.x = L.x; + gfxData.y = L.y; + gfxData.r = 0.0; + gfxData.g = 1.0; + gfxData.b = 0.0; + gfxData.sides = 10.0; + type = RESOURCE_TYPE; amount = RESOURCE_AMOUNT_START; growAmount = RESOURCE_GROW; @@ -24,6 +30,6 @@ void Resource::grow() { if(amount < RESOURCE_AMOUNT_MAX){ amount+=growAmount; - rect.h = rect.w = map(amount,0,RESOURCE_AMOUNT_MAX,0,RESOURCE_SIZE_MAX); + L.h = L.w = map(amount,0,RESOURCE_AMOUNT_MAX,0,RESOURCE_SIZE_MAX); } } diff --git a/src/spritebatch.cpp b/src/spritebatch.cpp new file mode 100644 index 0000000..91e04ba --- /dev/null +++ b/src/spritebatch.cpp @@ -0,0 +1,185 @@ +#include "spritebatch.hpp" + +SpriteBatch::SpriteBatch(GeoShader theshader) : _vbo(0), _vao(0), shader(theshader) +{ + //shader = theshader; +} + +SpriteBatch::~SpriteBatch() +{ + +} + +void SpriteBatch::init() +{ + createVertexArray(); +} + + +void SpriteBatch::begin() { + //_sortType = sortType; + _renderBatches.clear(); + + // Makes _glpyhs.size() == 0, however it does not free internal memory. + // So when we later call emplace_back it doesn't need to internally call new. + _gfx.clear(); +} + +void SpriteBatch::end() { + // Set up all pointers for fast sorting + _gfxPtr.resize(_gfx.size()); + for (int i = 0; i < _gfx.size(); i++) { + _gfxPtr[i] = &_gfx[i]; + } + + //sortGlyphs(); + createRenderBatches(); +} + +void SpriteBatch::draw(const GraphicsData& gfxData) { + _gfx.emplace_back(gfxData); +} + +void SpriteBatch::renderBatch() { + + // Bind our VAO. This sets up the opengl state we need, including the + // vertex attribute pointers and it binds the VBO + glBindVertexArray(_vao); + + for (int i = 0; i < _renderBatches.size(); i++) { + //glBindTexture(GL_TEXTURE_2D, _renderBatches[i].texture); + + glDrawArrays(GL_POINTS, _renderBatches[i].offset, _renderBatches[i].numVertices); + } + glBindVertexArray(0); +} + +void SpriteBatch::createRenderBatches() { + // This will store all the vertices that we need to upload + std::vector vertices; + // Resize the buffer to the exact size we need so we can treat + // it like an array + vertices.resize(_gfxPtr.size() * 6); + + if (_gfxPtr.empty()) { + return; + } + + int offset = 0; // current offset + int cv = 0; // current vertex + + //Add the first batch + _renderBatches.emplace_back(offset, 6); + vertices[cv++] = _gfxPtr[0]->x; + vertices[cv++] = _gfxPtr[0]->y; + vertices[cv++] = _gfxPtr[0]->r; + vertices[cv++] = _gfxPtr[0]->g; + vertices[cv++] = _gfxPtr[0]->b; + vertices[cv++] = _gfxPtr[0]->sides; + + offset += 6; + + //Add all the rest of the glyphs + //std::cout << "ptr size = " << _gfxPtr.size() << std::endl; + for (int cg = 1; cg < _gfxPtr.size(); cg++) { + + // Check if this glyph can be part of the current batch + //if (_gfxPtr[cg]->texture != _gfxPtr[cg - 1]->texture) { + // Make a new batch + // _renderBatches.emplace_back(offset, 6); + //} else { + // If its part of the current batch, just increase numVertices + _renderBatches.back().numVertices += 6; + //} + vertices[cv++] = _gfxPtr[cg]->x; + vertices[cv++] = _gfxPtr[cg]->y; + vertices[cv++] = _gfxPtr[cg]->r; + vertices[cv++] = _gfxPtr[cg]->g; + vertices[cv++] = _gfxPtr[cg]->b; + vertices[cv++] = _gfxPtr[cg]->sides; + + offset += 6; + } + + + + // Bind our VBO + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + // Orphan the buffer (for speed) + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), nullptr, GL_DYNAMIC_DRAW); + // Upload the data + glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data()); + + // Unbind the VBO + glBindBuffer(GL_ARRAY_BUFFER, 0); + +} + +void SpriteBatch::createVertexArray() { + + // Generate the VAO if it isn't already generated + if (_vao == 0) { + glGenVertexArrays(1, &_vao); + } + + // Bind the VAO. All subsequent opengl calls will modify it's state. + glBindVertexArray(_vao); + + //G enerate the VBO if it isn't already generated + if (_vbo == 0) { + glGenBuffers(1, &_vbo); + } + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + + //Tell opengl what attribute arrays we need + GLint posAttrib = glGetAttribLocation(shader.m_program, "pos"); + glEnableVertexAttribArray(posAttrib); + + GLint colAttrib = glGetAttribLocation(shader.m_program, "color"); + glEnableVertexAttribArray(colAttrib); + + GLint sidesAttrib = glGetAttribLocation(shader.m_program, "sides"); + glEnableVertexAttribArray(sidesAttrib); + + // glEnableVertexAttribArray(2); + + //This is the position attribute pointer + glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), 0); //This is the color attribute pointer + glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), (void*) (2 * sizeof(float))); //This is the UV attribute pointer + glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, + 6 * sizeof(float), (void*) (5 * sizeof(float))); + glBindVertexArray(0); + +} + +/* +void SpriteBatch::sortGlyphs() { + + switch (_sortType) { + case GlyphSortType::BACK_TO_FRONT: + std::stable_sort(_glyphPointers.begin(), _glyphPointers.end(), compareBackToFront); + break; + case GlyphSortType::FRONT_TO_BACK: + std::stable_sort(_glyphPointers.begin(), _glyphPointers.end(), compareFrontToBack); + break; + case GlyphSortType::TEXTURE: + std::stable_sort(_glyphPointers.begin(), _glyphPointers.end(), compareTexture); + break; + } +} +bool SpriteBatch::compareFrontToBack(Glyph* a, Glyph* b) { + return (a->depth < b->depth); +} + +bool SpriteBatch::compareBackToFront(Glyph* a, Glyph* b) { + return (a->depth > b->depth); +} + +bool SpriteBatch::compareTexture(Glyph* a, Glyph* b) { + return (a->texture < b->texture); +} + +} +*/ diff --git a/src/window.cpp b/src/window.cpp index f7868a4..28af6bf 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,31 +1,41 @@ #include "window.hpp" -Window::Window() +Window::Window(int width, int height, const std::string& title) { - SDL_Init(SDL_INIT_VIDEO); - main = SDL_CreateWindow("main",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,WINDOW_X,WINDOW_Y,SDL_WINDOW_SHOWN); - renderer = SDL_CreateRenderer(main,-1,SDL_RENDERER_ACCELERATED); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); + SDL_Init(SDL_INIT_EVERYTHING); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + main = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width,height,SDL_WINDOW_OPENGL); + glContext = SDL_GL_CreateContext(main); + GLenum status = glewInit(); + closed = false; + + if(status != GLEW_OK) + std::cerr << "Failiure to init." << std::endl; + } -void Window::Destroy() +Window::~Window() { - SDL_DestroyRenderer(renderer); + SDL_GL_DeleteContext(glContext); SDL_DestroyWindow(main); SDL_Quit(); } -void Window::Clear() +void Window::swapBuffers() { - SDL_RenderClear(renderer); + SDL_GL_SwapWindow(main); } -void Window::Render() +void Window::Clear(float r, float g, float b, float a) { - SDL_RenderPresent(renderer); + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT); } -SDL_Renderer* Window::getRenderer() -{ - return renderer; -} -- cgit v1.2.3