Rewritten code from http://stackoverflow.com/questions/5988686/creating-a-3d-sphere-in-opengl-using-visual-c/5989676#5989676
Texture loading is done with:
stb_image.h
by Sean Barrett
https://github.com/nothings/stb
and
tdogl::Texture (requires few additional tdogl headers)
by Thomas Dalling
https://github.com/tomdalling/opengl-series
#include "Sphere.h" using namespace Rendering; using namespace Models; float dxR; std::vector<GLushort> indices; GLuint ibo;//Index Buffer Object for indices Sphere::Sphere() { dxR = 0.0f; } Sphere::~Sphere() {} void Sphere::Create() { GLuint vao; GLuint vbo; tdogl::Bitmap bmp = tdogl::Bitmap::bitmapFromFile("Textures/ball.png"); gTexture = new tdogl::Texture(bmp); glGenVertexArrays(1, &vao); glBindVertexArray(vao); std::vector<VertexFormat> vertices; glm::vec4 blue = glm::vec4(0, 0, 1, 1); int n = 1; unsigned int rings = 24*n; unsigned int sectors = 48*n; float const R = 1.0f / (float)(rings - 1); float const S = 1.0f / (float)(sectors - 1); float pi = 3.14159265358979323846f; for (unsigned int r = 0; r < rings; r++) { for (unsigned int s = 0; s < sectors; s++) { float const y = sin(-pi / 2.0f + pi * r * R); float const x = cos(2 * pi * s * S) * sin(pi * r * R); float const z = sin(2 * pi * s * S) * sin(pi * r * R); glm::vec2 texCoord = glm::vec2(s*S, r*R); glm::vec3 vxs = glm::vec3(x, y, z); vertices.push_back(VertexFormat(vxs, blue, texCoord)); } } indices.resize(rings * sectors * 6); std::vector<GLushort>::iterator i = indices.begin(); for (unsigned int r = 0; r < rings - 1; r++) { for (unsigned int s = 0; s < sectors - 1; s++) { *i++ = r * sectors + s; *i++ = r * sectors + (s + 1); *i++ = (r + 1) * sectors + (s + 1); *i++ = (r + 1) * sectors + (s + 1); *i++ = (r + 1) * sectors + s; *i++ = r * sectors + s; } } verticesSize = vertices.size(); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * verticesSize, &vertices[0], GL_STATIC_DRAW); glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), &indices[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(offsetof(VertexFormat, VertexFormat::color))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_TRUE, sizeof(VertexFormat), (void*)(offsetof(VertexFormat, VertexFormat::texture))); glBindVertexArray(0); this->vao = vao; this->vbos.push_back(vbo); } void Sphere::Update() { dxR += 1.0f; if (dxR > 360.0f) dxR = 0.0f; } void Sphere::Draw() { glUseProgram(program); GLuint camera = glGetUniformLocation(program, "camera"); GLuint projection = glGetUniformLocation(program, "projection"); GLuint model = glGetUniformLocation(program, "model"); GLuint texture2d = glGetUniformLocation(program, "tex"); glm::vec3 topView = glm::vec3(0, 4, 0.1); glm::vec3 perspectiveView = glm::vec3(0, 3, 3); glm::vec3 selectedView = perspectiveView; //eye - position of the camera's viewpoint, //center - where are you looking, up = up is Y+ glm::mat4 cameraMatrix = glm::lookAt(selectedView, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); glm::mat4 identityMx = glm::mat4(glm::vec4(-1, 0, 0, 0), glm::vec4(0, 1, 0, 0), glm::vec4(0, 0, 1, 0), glm::vec4(0, 0, 0, 1)); glm::mat4 rotated = glm::rotate(identityMx, glm::radians(dxR), glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(camera, 1, GL_FALSE, glm::value_ptr(cameraMatrix)); glUniformMatrix4fv(projection, 1, GL_FALSE, glm::value_ptr(projectionMatrix)); glUniformMatrix4fv(model, 1, GL_FALSE, glm::value_ptr(rotated)); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gTexture->object()); glUniform1i(texture2d, 0); glBindVertexArray(vao); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]); }
#pragma once #include "Model.h" #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/matrix_transform.hpp> #include <cmath> namespace Rendering { namespace Models { class Sphere : public Models::Model { public: Sphere(); ~Sphere(); void Create(); virtual void Draw() override final; virtual void Update() override final; }; } }
Sphere class inherits from Models class. It is partly rewritten from tutorial http://in2gpu.com/opengl-3/.
#pragma once #include <vector> #include "../IGameObject.h" #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/matrix_transform.hpp> #include "../tdogl/Texture.h" namespace Rendering { namespace Models //create another namespace { class Model :public IGameObject { public: Model(); virtual ~Model(); // methods from interface virtual void Draw() override; virtual void Update() override; virtual void SetProgram(GLuint shaderName) override; virtual void Destroy() override; virtual GLuint GetVao() const override; virtual const std::vector<GLuint>& GetVbos() const override; protected: GLuint vao; GLuint program; std::vector<GLuint> vbos; unsigned int verticesSize; tdogl::Texture* gTexture; static glm::mat4 projectionMatrix; }; } }
#include "Model.h" using namespace Rendering; using namespace Models; glm::mat4 Model::projectionMatrix = glm::perspective(glm::radians(35.0f), 800.0f / 600.0f, 0.1f, 10.0f); Model::Model() { verticesSize = 0; gTexture = NULL; } Model::~Model() { Destroy(); } void Model::Draw() { //this will be again overridden } void Model::Update() { //this will be again overridden } void Model::SetProgram(GLuint program) { this->program = program; } GLuint Model::GetVao() const { return vao; } const std::vector<GLuint>& Model::GetVbos() const { return vbos; } void Model::Destroy() { glDeleteVertexArrays(1, &vao); glDeleteBuffers(vbos.size(), &vbos[0]); vbos.clear(); }
And IGameObject is…
#pragma once #include <vector> #include <iostream> #include "..\..\packages\nupengl.core.0.0.0.1\build\native\include\GL\glew.h" #include "..\..\packages\nupengl.core.0.0.0.1\build\native\include\GL\freeglut.h" #include "VertexFormat.h" namespace Rendering { class IGameObject { public: virtual ~IGameObject() = 0; virtual void Draw() = 0; virtual void Update() = 0; virtual void SetProgram(GLuint shaderName) = 0; virtual void Destroy() = 0; virtual GLuint GetVao() const = 0; virtual const std::vector<GLuint>& GetVbos() const = 0; }; inline IGameObject::~IGameObject() {//blank } }
VertexFormat is defined as:
#pragma once #include "glm\glm.hpp" //installed with NuGet namespace Rendering { struct VertexFormat { glm::vec3 position; glm::vec4 color; glm::vec2 texture; VertexFormat(const glm::vec3 &iPos, const glm::vec4 &iColor, const glm::vec2 &iTex) { position = iPos; color = iColor; texture = iTex; } }; }
Result
I’ve used this sphere in PA199 3D Breakout (C++/OpenGL) project.
2 responses to “Sphere in OpenGL”
Hi may i get the github link to this piece of code?
The source is linked on the project page: https://romanluks.eu/blog/pa199_3dbreakout/