Sphere in OpenGL

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

opengl_sphere

I’ve used this sphere in PA199 3D Breakout (C++/OpenGL) project.


Comments

2 responses to “Sphere in OpenGL”

  1. Max Sun

    Hi may i get the github link to this piece of code?

  2. The source is linked on the project page: https://romanluks.eu/blog/pa199_3dbreakout/

Leave a Reply

Your email address will not be published. Required fields are marked *