ok

img

Freeglut

Definiamo prima i file per gli shaders:
//
// shader.h
//
#ifndef zxShader_h
#define zxShader_h

#include <gl/glew.h>
#include <gl/freeglut.h>
#include <string>
  

class zxShader
{
private:
	GLuint						program;
	GLuint						vertexShader;
	GLuint						geometryShader;
	GLuint						fragmentShader;
	char 						*open(std::string filename);
	GLuint						shader(int type, std::string filename);
	bool						link();
	bool						init();

public:
	zxShader();
	~zxShader();
	
	bool						load(std::string vert, std::string geom, std::string frag);
	void						start();
	void						end();
	GLint						attributeVariable(const char *var);
	void						attribute(const char *var, float *a);
	void						uniform1f(const char *var, float a);
	void						uniform2f(const char *var, float a, float b);
	void						uniform3f(const char *var, float a, float b, float c);
	void						uniform4f(const char *var, float a, float b, float c, float d);
	void						uniform1fv(const char *var, int size, float *a);
	void						uniform2fv(const char *var, int size, float *a);
	void						uniform3fv(const char *var, int size, float *a);
	void						uniform4fv(const char *var, int size, float *a);
	void						uniform1i(const char *var, int a);
	void						uniform2i(const char *var, int a, int b);
	void						uniform3i(const char *var, int a, int b, int c);
	void						uniform4i(const char *var, int a, int b, int c, int d);
	void						uniform1iv(const char *var, int size, int *a);
	void						uniform2iv(const char *var, int size, int *a);
	void						uniform3iv(const char *var, int size, int *a);
	void						uniform4iv(const char *var, int size, int *a);
	void						uniformMatrix(const char *var, unsigned short size, bool p, float *m);
	GLint						uniformVariable(const char *var);
};
  
#endif

//
// shader.cpp
//
#include <iostream>
#include "zxShader.h"
#include <fstream>

zxShader::zxShader()
{
}

zxShader::~zxShader()
{
	glDeleteShader(this->vertexShader);
	glDeleteShader(this->geometryShader);
	glDeleteShader(this->fragmentShader);
	glDeleteProgram(this->program);
}

char *zxShader::open(std::string filename)
{
	FILE *file;
	char *content = NULL;
	int count = 0;
	if(filename != "")
	{
		file = fopen(filename.c_str(), "rt");
		if(file != NULL) 
		{
			fseek(file, 0, SEEK_END);
			count = ftell(file);
			rewind(file);
			if(count > 0)
			{
				content = new char[count + 1];
				count = fread(content, sizeof(char), count, file);
				content[count] = '\0';
			}
			fclose(file);
		}
	}
	return content;
}

bool zxShader::init()
{
	if(glewInit() != GLEW_OK)
	{
		fprintf(stderr, "glew not initialized\n");
		return false;
	}
	else
	{
		this->vertexShader = 0;
		this->geometryShader = 0;
		this->fragmentShader = 0;
		return true;
	}
}

GLuint zxShader::shader(int type, std::string filename)
{
	if(filename != "")
	{
		GLuint s[3] = {GL_VERTEX_SHADER, GL_GEOMETRY_SHADER, GL_FRAGMENT_SHADER};
		int success;
		char infoLog[512];
		GLuint shader = glCreateShader(s[type]);
		char *script = this->open(filename);
		glShaderSource(shader, 1, (const GLchar **)&script, NULL);
		delete [] script;
		glCompileShader(shader);
		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
		if(success)
		{
			return shader;
		}
		else
		{
			std::string w[3] = {"VERTEX", "GEOMETRY", "FRAGMENT"};
			glGetShaderInfoLog(shader, 512, NULL, infoLog);
			std::cout << "ERROR::" << w[type] << "::COMPILATION_FAILED\n" << infoLog << std::endl;
			return 0;
		}
	}
	else
	{
		return 0;
	}
}

bool zxShader::link()
{
	int success;
	char infoLog[512];
	this->program = glCreateProgram();
	if(this->vertexShader != 0){glAttachShader(this->program, this->vertexShader);}
	if(this->geometryShader != 0){glAttachShader(this->program, this->geometryShader);}
	if(this->fragmentShader != 0){glAttachShader(this->program, this->fragmentShader);}
	glLinkProgram(this->program);
	glGetProgramiv(this->program, GL_LINK_STATUS, &success);
	if(!success)
	{
        	glGetProgramInfoLog(this->program, 512, NULL, infoLog);
        	std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
}

bool zxShader::load(std::string vert, std::string geom, std::string frag)
{
	bool r = false;
	if(this->init())
	{
		this->vertexShader = this->shader(0, vert);
		this->geometryShader = this->shader(1, geom);
		this->fragmentShader = this->shader(2, frag);
		if(this->link())
		{
			r = true;
		}
	}
	return r;
}

void zxShader::start()
{
	glUseProgram(this->program);
}

void zxShader::end()
{
	glUseProgram(0);
}

void zxShader::uniform1f(const char *var, float a)
{
	glUniform1f(glGetUniformLocation(this->program, var), a);
}

void zxShader::uniform2f(const char *var, float a, float b)
{
	glUniform2f(glGetUniformLocation(this->program, var), a, b);
}

void zxShader::uniform3f(const char *var, float a, float b, float c)
{
	glUniform3f(glGetUniformLocation(this->program, var), a, b, c);
}

void zxShader::uniform4f(const char *var, float a, float b, float c, float d)
{
	glUniform4f(glGetUniformLocation(this->program, var), a, b, c, d);
} 

void zxShader::uniform1fv(const char *var, int size, float *a)
{
	glUniform1fv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform2fv(const char *var, int size, float *a)
{
	glUniform2fv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform3fv(const char *var, int size, float *a)
{
	glUniform3fv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform4fv(const char *var, int size, float *a)
{
	glUniform4fv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform1i(const char *var, int a)
{
	glUniform1i(glGetUniformLocation(this->program, var), a);
}

void zxShader::uniform2i(const char *var, int a, int b)
{
	glUniform2i(glGetUniformLocation(this->program, var), a, b);
}

void zxShader::uniform3i(const char *var, int a, int b, int c)
{
	glUniform3i(glGetUniformLocation(this->program, var), a, b, c);
}

void zxShader::uniform4i(const char *var, int a, int b, int c, int d)
{
	glUniform4i(glGetUniformLocation(this->program, var), a, b, c, d);
}

void zxShader::uniform1iv(const char *var, int size, int *a)
{
	glUniform1iv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform2iv(const char *var, int size, int *a)
{
	glUniform2iv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform3iv(const char *var, int size, int *a)
{
	glUniform3iv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::uniform4iv(const char *var, int size, int *a)
{
	glUniform4iv(glGetUniformLocation(this->program, var), size, a);
}

void zxShader::attribute(const char *var, float *a)
{
	glVertexAttrib1fv(glGetAttribLocation(this->program, var), a);
}

void zxShader::uniformMatrix(const char *var, unsigned short size, bool p, float *m)
{
	glUniformMatrix4fv(glGetUniformLocation(this->program, var), size, p, m);
}

GLint zxShader::uniformVariable(const char *var)
{
	return glGetUniformLocation(this->program, var);
}

GLint zxShader::attributeVariable(const char *var)
{
	return glGetAttribLocation(this->program, var);
}
nella cartella shaders inseriamo due file txt con gli script GLSL.
//
// vert.txt
//
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 color;
uniform mat4 mvp;
void main()
{
	color = aColor;
	gl_Position = mvp * vec4(aPos, 1.0);
}

//
//
//
#version 330 core
out vec4 FragColor;
in vec3 color;
void main()
{
	FragColor = vec4(color, 1.0f);
}
Aggiungiamo anche delle classi per il calcolo delle matrici (visto che non si usano più le funzioni proprie a opengl) e due files per la definizione di variabili globali.
//
// zxMath.h
//
#ifndef zxMath_h
#define zxMath_h
#include <math.h>

namespace zxMath
{
	float									abs(float x);
	class vec2
	{
		public:
		float								x, y;
										vec2();
										vec2(float x, float y);
		void								set(float x, float y);
		void								show();
	};

	class vec3
	{
		public:
		float								x, y, z;
										vec3();
										vec3(float x, float y, float z);
		void								set(float x, float y, float z);
		void								show();
	};

	class vec4
	{
		public:
		float								x, y, z, a;
										vec4();
										vec4(float x, float y, float z, float a);
		void								set(float x, float y, float z, float a);
		void								show();
	};
	
	class mat2
	{
		public:
		float								m[4];
										mat2();
										mat2(float a, float b, float c, float d);
										mat2(vec2 A, vec2 B);
		void								set(float a, float b, float c, float d);
		void								set(vec2 A, vec2 B);
		void								show();
	};
	
	class mat3
	{
		public:
		float								m[9];
										mat3();
										mat3(float a, float b, float c, float d, float e, float f, float g, float h, float i);
										mat3(vec3 A, vec3 B, vec3 C);
		void								set(float a, float b, float c, float d, float e, float f, float g, float h, float i);
		void								set(vec3 A, vec3 B, vec3 C);
		void								show();
	};

	class mat4
	{
		public:
		float 								m[16];
										mat4();
										mat4(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p);
										mat4(vec4 A, vec4 B, vec4 C, vec4 D);
		void								set(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p);
		void								set(vec4 A, vec4 B, vec4 C, vec4 D);
		void								show();
	};
	
	vec2									cross(vec2 A, vec2 B);
	vec3									cross(vec3 A, vec3 B);
	vec4									cross(vec4 A, vec4 B);
	float									det(mat2 A);
	float									det(mat3 A);
	float									det(mat4 A);
	float									dot(vec2 A, vec2 B);
	float									dot(vec3 A, vec3 B);
	float									dot(vec4 A, vec4 B);
	float									magnitude(vec2 A);
	float									magnitude(vec3 A);
	float									magnitude(vec4 A);
	vec2									normalize(vec2 A);
	vec3									normalize(vec3 A);
	vec4									normalize(vec4 A);
	mat3									product(mat3 A, mat3 B);
	mat4									product(mat4 A, mat4 B);
	mat4									transpose(mat4 A);
	mat4									inverse(mat4 A);
	mat4									perspective(float fovy, float aspect, float near, float far);
	mat4									lookAt(vec3 E, vec3 C, vec3 U);
	mat4									defaultCamera(vec3 E, vec3 C);
	mat4									modelViewProjection(mat4 M, mat4 V, mat4 P);
	mat4									ortho(float left, float right, float bottom, float top);
	mat4									ortho(float left, float right, float bottom, float top, float near, float far);
	mat3									rotate(mat3 M, float a);
	mat4									rotate(mat4 M, float a, zxMath::vec3 b);
	mat3									translate(mat3 M, zxMath::vec2 t);
	mat4									translate(mat4 M, zxMath::vec3 t);
	mat2									toMat2(mat3 A);
	mat2									toMat2(mat4 A);
	mat3									toMat3(mat2 A);
	mat3									toMat3(mat4 A);
	mat4									toMat4(mat2 A);
	mat4									toMat4(mat3 A);
};

#endif

//
// zxMath.cpp
//
#include "zxMath.h"
#include <iostream>

float zxMath::abs(float x)
{
	if(x < 0)
	{
		x *= -1.0f;
	}
	return x;
}

zxMath::vec2::vec2()
{
	this->set(0.0f, 0.0f);
}

zxMath::vec2::vec2(float x, float y)
{
	this->set(x, y);
}

void zxMath::vec2::set(float x, float y)
{
	this->x = x;
	this->y = y;
}

void zxMath::vec2::show()
{
	std::cout << this->x << "\t" << this->y << "\n";
}

zxMath::vec3::vec3()
{
	this->set(0.0f, 0.0f, 0.0f);
}

zxMath::vec3::vec3(float x, float y, float z)
{
	this->set(x, y, z);
}

void zxMath::vec3::set(float x, float y, float z)
{
	this->x = x;
	this->y = y;
	this->z = z;
}

void zxMath::vec3::show()
{
	std::cout << this->x << "\t" << this->y << "\t" << this->z << "\n";
}

zxMath::vec4::vec4()
{
	this->set(0.0f, 0.0f, 0.0f, 0.0f);
}

zxMath::vec4::vec4(float x, float y, float z, float a)
{
	this->set(x, y, z, a);
}

void zxMath::vec4::set(float x, float y, float z, float a)
{
	this->x = x;
	this->y = y;
	this->z = z;
	this->a = a;
}

void zxMath::vec4::show()
{
	std::cout << this->x << "\t" << this->y << "\t" << this->z << "\t" << a << "\n";
}

zxMath::mat2::mat2()
{
	this->set(1.0f, 0.0f, 0.0f, 1.0f);
}

zxMath::mat2::mat2(float a, float b, float c, float d)
{
	this->set(a, b, c, d);
}

zxMath::mat2::mat2(zxMath::vec2 A, zxMath::vec2 B)
{
	this->set(A, B);
}

void zxMath::mat2::set(float a, float b, float c, float d)
{
	this->m[0] = a; this->m[1] = b;
	this->m[2] = c; this->m[3] = d;
}

void zxMath::mat2::set(zxMath::vec2 A, zxMath::vec2 B)
{
	this->m[0] = A.x; this->m[1] = A.y;
	this->m[2] = B.x; this->m[3] = B.y;
}

void zxMath::mat2::show()
{
	std::cout << this->m[0] << "\t" << this->m[1] << "\n";
	std::cout << this->m[2] << "\t" << this->m[3] << "\n";
}

zxMath::mat3::mat3()
{
	this->set(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
}

zxMath::mat3::mat3(float a, float b, float c, float d, float e, float f, float g, float h, float i)
{
	this->set(a, b, c, d, e, f, g, h, i);
}

zxMath::mat3::mat3(zxMath::vec3 A, zxMath::vec3 B, zxMath::vec3 C)
{
	this->set(A, B, C);
}

void zxMath::mat3::set(float a, float b, float c, float d, float e, float f, float g, float h, float i)
{
	this->m[0] = a; this->m[1] = b; this->m[2] = c;
	this->m[3] = d; this->m[4] = e; this->m[5] = f;
	this->m[6] = g; this->m[7] = h; this->m[8] = i;
}

void zxMath::mat3::set(zxMath::vec3 A, zxMath::vec3 B, zxMath::vec3 C)
{
	this->m[0] = A.x; this->m[1] = A.y; this->m[2] = A.z;
	this->m[3] = B.x; this->m[4] = B.y; this->m[5] = B.z;
	this->m[6] = C.x; this->m[7] = C.y; this->m[8] = C.z;
}

void zxMath::mat3::show()
{
	std::cout << this->m[0] << "\t" << this->m[1] << "\t" <<this->m[2] << "\t" << "\n";
	std::cout << this->m[3] << "\t" << this->m[4] << "\t" <<this->m[5] << "\t" << "\n";
	std::cout << this->m[6] << "\t" << this->m[7] << "\t" <<this->m[8] << "\t" << "\n";
}

zxMath::mat4::mat4()
{
	this->set(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
}

zxMath::mat4::mat4(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p)
{
	this->set(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
}

zxMath::mat4::mat4(zxMath::vec4 A, zxMath::vec4 B, zxMath::vec4 C, zxMath::vec4 D)
{
	this->set(A, B, C, D);
}

void zxMath::mat4::set(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p)
{
	this->m[ 0] = a; this->m[ 1] = b; this->m[ 2] = c; this->m[ 3] = d;
	this->m[ 4] = e; this->m[ 5] = f; this->m[ 6] = g; this->m[ 7] = h;
	this->m[ 8] = i; this->m[ 9] = j; this->m[10] = k; this->m[11] = l;
	this->m[12] = m; this->m[13] = n; this->m[14] = o; this->m[15] = p;
}

void zxMath::mat4::set(zxMath::vec4 A, zxMath::vec4 B, zxMath::vec4 C, zxMath::vec4 D)
{
	this->m[ 0] = A.x; this->m[ 1] = A.y; this->m[ 2] = A.z; this->m[ 3] = A.a;
	this->m[ 4] = B.x; this->m[ 5] = B.y; this->m[ 6] = B.z; this->m[ 7] = B.a;
	this->m[ 8] = C.x; this->m[ 9] = C.y; this->m[10] = C.z; this->m[11] = C.a;
	this->m[12] = D.x; this->m[13] = D.y; this->m[14] = D.z; this->m[15] = D.a;
}

void zxMath::mat4::show()
{
	std::cout << this->m[ 0] << "\t" << this->m[ 1] << "\t" << this->m[ 2] << "\t" << this->m[ 3] << "\n";
	std::cout << this->m[ 4] << "\t" << this->m[ 5] << "\t" << this->m[ 6] << "\t" << this->m[ 7] << "\n";
	std::cout << this->m[ 8] << "\t" << this->m[ 9] << "\t" << this->m[10] << "\t" << this->m[11] << "\n";
	std::cout << this->m[12] << "\t" << this->m[13] << "\t" << this->m[14] << "\t" << this->m[15] << "\n";
}

zxMath::vec2 zxMath::cross(zxMath::vec2 A, zxMath::vec2 B)
{
	zxMath::vec2 R(A.x * B.y - A.y * B.x, 0.0f);
	return R;
}

zxMath::vec3 zxMath::cross(zxMath::vec3 A, zxMath::vec3 B)
{
	zxMath::vec3 R(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);
	return R;
}

zxMath::vec4 zxMath::cross(zxMath::vec4 A, zxMath::vec4 B)
{
	vec4 R(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x, 0.0f);
	return R;
}

float zxMath::det(zxMath::mat2 A)
{
	float r = A.m[0] * A.m[3] - A.m[1] * A.m[2];
	return r;
}

float zxMath::det(zxMath::mat3 A)
{
	float r = 
	A.m[ 0] * A.m[ 4] * A.m[ 8] +
	A.m[ 1] * A.m[ 5] * A.m[ 6] +
	A.m[ 2] * A.m[ 3] * A.m[ 7] -
	A.m[ 6] * A.m[ 4] * A.m[ 2] -
	A.m[ 7] * A.m[ 5] * A.m[ 0] -
	A.m[ 8] * A.m[ 3] * A.m[ 1];
	return r;
}

float zxMath::det(zxMath::mat4 A)
{
	zxMath::mat3 J(A.m[ 1], A.m[ 2], A.m[ 3], A.m[ 5], A.m[ 6], A.m[ 7], A.m[ 9], A.m[10], A.m[11]);
	zxMath::mat3 K(A.m[ 0], A.m[ 2], A.m[ 3], A.m[ 4], A.m[ 6], A.m[ 7], A.m[ 8], A.m[10], A.m[11]);
	zxMath::mat3 L(A.m[ 0], A.m[ 1], A.m[ 3], A.m[ 4], A.m[ 5], A.m[ 7], A.m[ 8], A.m[ 9], A.m[11]);
	zxMath::mat3 M(A.m[ 0], A.m[ 1], A.m[ 2], A.m[ 4], A.m[ 5], A.m[ 6], A.m[ 8], A.m[ 9], A.m[10]);
	float d = 
	- A.m[12] * zxMath::det(J)
	+ A.m[13] * zxMath::det(K)
	- A.m[14] * zxMath::det(L)
	+ A.m[15] * zxMath::det(M);
	return d;
}

float zxMath::dot(zxMath::vec2 A, zxMath::vec2 B)
{
	return A.x * B.x + A.y * B.y;
}

float zxMath::dot(zxMath::vec3 A, zxMath::vec3 B)
{
	return A.x * B.x + A.y * B.y + A.z * B.z;
}

float zxMath::dot(zxMath::vec4 A, zxMath::vec4 B)
{
	return A.x * B.x + A.y * B.y + A.z * B.z + A.a * B.a;
}

float zxMath::magnitude(zxMath::vec2 A)
{
	return sqrt(A.x * A.x + A.y * A.y);
}

float zxMath::magnitude(zxMath::vec3 A)
{
	return sqrt(A.x * A.x + A.y * A.y + A.z * A.z);
}

float zxMath::magnitude(zxMath::vec4 A)
{
	float r = sqrt(A.x * A.x + A.y * A.y + A.z * A.z);
	return r;
}

zxMath::vec2 zxMath::normalize(zxMath::vec2 A)
{
	float d = zxMath::magnitude(A);
	zxMath::vec2 R(A.x / d, A.y / d);
	return R;
}

zxMath::vec3 zxMath::normalize(zxMath::vec3 A)
{
	float d = zxMath::magnitude(A);
	zxMath::vec3 R(A.x / d, A.y / d, A.z / d);
	return R;
}

zxMath::vec4 zxMath::normalize(zxMath::vec4 A)
{
	float d = zxMath::magnitude(A);
	zxMath::vec4 R(A.x / d, A.y / d, A.z / d, 0);
	return R;
}

zxMath::mat3 zxMath::product(zxMath::mat3 A, zxMath::mat3 B)
{
	zxMath::mat3 R(
	A.m[0] * B.m[0] + A.m[1] * B.m[3] + A.m[2] * B.m[6],
	A.m[0] * B.m[1] + A.m[1] * B.m[4] + A.m[2] * B.m[7],
	A.m[0] * B.m[2] + A.m[1] * B.m[5] + A.m[2] * B.m[8],
	A.m[3] * B.m[0] + A.m[4] * B.m[3] + A.m[5] * B.m[6],
	A.m[3] * B.m[1] + A.m[4] * B.m[4] + A.m[5] * B.m[7],
	A.m[3] * B.m[2] + A.m[4] * B.m[5] + A.m[5] * B.m[8],
	A.m[6] * B.m[0] + A.m[7] * B.m[3] + A.m[8] * B.m[6],
	A.m[6] * B.m[1] + A.m[7] * B.m[4] + A.m[8] * B.m[7],
	A.m[6] * B.m[2] + A.m[7] * B.m[5] + A.m[8] * B.m[8]
	);
	return R;
}

zxMath::mat4 zxMath::product(zxMath::mat4 A, zxMath::mat4 B)
{
	zxMath::mat4 R(
	A.m[ 0] * B.m[ 0] + A.m[ 1] * B.m[ 4] + A.m[ 2] * B.m[ 8] + A.m[ 3] * B.m[12],
	A.m[ 0] * B.m[ 1] + A.m[ 1] * B.m[ 5] + A.m[ 2] * B.m[ 9] + A.m[ 3] * B.m[13],
	A.m[ 0] * B.m[ 2] + A.m[ 1] * B.m[ 6] + A.m[ 2] * B.m[10] + A.m[ 3] * B.m[14],
	A.m[ 0] * B.m[ 3] + A.m[ 1] * B.m[ 7] + A.m[ 2] * B.m[11] + A.m[ 3] * B.m[15],
	A.m[ 4] * B.m[ 0] + A.m[ 5] * B.m[ 4] + A.m[ 6] * B.m[ 8] + A.m[ 7] * B.m[12],
	A.m[ 4] * B.m[ 1] + A.m[ 5] * B.m[ 5] + A.m[ 6] * B.m[ 9] + A.m[ 7] * B.m[13],
	A.m[ 4] * B.m[ 2] + A.m[ 5] * B.m[ 6] + A.m[ 6] * B.m[10] + A.m[ 7] * B.m[14],
	A.m[ 4] * B.m[ 3] + A.m[ 5] * B.m[ 7] + A.m[ 6] * B.m[11] + A.m[ 7] * B.m[15],
	A.m[ 8] * B.m[ 0] + A.m[ 9] * B.m[ 4] + A.m[10] * B.m[ 8] + A.m[11] * B.m[12],
	A.m[ 8] * B.m[ 1] + A.m[ 9] * B.m[ 5] + A.m[10] * B.m[ 9] + A.m[11] * B.m[13],
	A.m[ 8] * B.m[ 2] + A.m[ 9] * B.m[ 6] + A.m[10] * B.m[10] + A.m[11] * B.m[14],
	A.m[ 8] * B.m[ 3] + A.m[ 9] * B.m[ 7] + A.m[10] * B.m[11] + A.m[11] * B.m[15],
	A.m[12] * B.m[ 0] + A.m[13] * B.m[ 4] + A.m[14] * B.m[ 8] + A.m[15] * B.m[12],
	A.m[12] * B.m[ 1] + A.m[13] * B.m[ 5] + A.m[14] * B.m[ 9] + A.m[15] * B.m[13],
	A.m[12] * B.m[ 2] + A.m[13] * B.m[ 6] + A.m[14] * B.m[10] + A.m[15] * B.m[14],
	A.m[12] * B.m[ 3] + A.m[13] * B.m[ 7] + A.m[14] * B.m[11] + A.m[15] * B.m[15]
	);
	return R;
}

zxMath::mat4 zxMath::transpose(zxMath::mat4 A)
{
	mat4 R(
	A.m[ 0], A.m[ 4], A.m[ 8], A.m[12],
	A.m[ 1], A.m[ 5], A.m[ 9], A.m[13],
	A.m[ 2], A.m[ 6], A.m[10], A.m[14],
	A.m[ 3], A.m[ 7], A.m[11], A.m[15]);
	return R;
}

zxMath::mat4 zxMath::inverse(zxMath::mat4 A)
{
	float det = zxMath::det(A), d[16];
	zxMath::mat4 R;
	if(det != 0.0f)
	{
		for(unsigned short n = 0; n < 16; n++)
		{
			zxMath::mat3 B;
			unsigned short p = n % 4, q = n / 4, i = 0;
			for(unsigned short j = 0; j < 16; j++)
			{
				if(j % 4 != p && j / 4 != q)
				{
					B.m[i] = A.m[j];
					i++;
				}
			}
			d[n] = pow(-1.0f, p + q + 2.0f) * zxMath::det(B) / det;
		}
		R.set(d[0], d[4], d[8], d[12], d[1], d[5], d[9], d[13], d[2], d[6], d[10], d[14], d[3], d[7], d[11], d[15]);
	}
	else
	{
		std::cout << "matrix does not have an inverse. Determinant is zero.\n";
	}
	return R;
}

zxMath::mat4 zxMath::perspective(float fovy, float aspect, float near, float far)
{
	float f = 1.0f / tan(fovy * .0174533f / 2.0f);
	zxMath::mat4 R(
	f / aspect, 0.0f, 0.0f, 0.0f,
	0.0f, f, 0.0f, 0.0f,
	0.0f, 0.0f, (far + near) / (near - far), -1.0f,
	0.0f, 0.0f, (2.0f * far * near) / (near - far), 0.0f);
	return R;
}

zxMath::mat4 zxMath::ortho(float left, float right, float bottom, float top)
{
	return zxMath::ortho(left, right, bottom, top, -1.0f, 1.0f);
}

zxMath::mat4 zxMath::ortho(float left, float right, float bottom, float top, float near, float far)
{
	zxMath::mat4 R(
	2.0f / (right - left), 0.0f, 0.0f, 0.0f,
	0.0f, 2.0f / (top - bottom), 0.0f, 0.0f,
	0.0f, 0.0f, -2.0f / (far - near), 0.0f,
	-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1.0f
	);
	return R;
}

zxMath::mat4 zxMath::lookAt(zxMath::vec3 E, zxMath::vec3 C, zxMath::vec3 U)
{
	zxMath::vec3 L = zxMath::normalize(zxMath::vec3(C.x - E.x, C.y - E.y, C.z - E.z));
	zxMath::vec3 S = zxMath::normalize(zxMath::cross(L, U));
	zxMath::vec3 V = zxMath::cross(S, L);
	L.x *= -1.0f; L.y *= -1.0f; L.z *= -1.0f;
	zxMath::mat4 R(
	vec4(S.x, V.x, L.x, 0.0f),
	vec4(S.y, V.y, L.y, 0.0f),
	vec4(S.z, V.z, L.z, 0.0f),
	vec4(-dot(S, E), -dot(V, E), -dot(L, E), 1.0f));
	return R;
}

zxMath::mat3 zxMath::rotate(zxMath::mat3 M, float a)
{
	float c = cos(a * .0174533f);
	float s = sin(a * .0174533f);
	zxMath::mat3 R(
	c, -s, 0.0f,
	s, c, 0.0f,
	0.0f, 0.0f, 1.0f
	);
	return zxMath::product(M, R);
}

zxMath::mat3 zxMath::translate(zxMath::mat3 M, zxMath::vec2 t)
{
	zxMath::mat3 R(
	1.0f, 0.0f, t.x,
	0.0f, 1.0f, t.y,
	0.0f, 0.0f, 1.0f
	);
	return zxMath::product(M, R);
}

zxMath::mat4 zxMath::rotate(zxMath::mat4 M, float a, zxMath::vec3 b)
{
	float c = cos(a * .0174533f);
	float s = sin(a * .0174533f);
	zxMath::mat4 R(
	c + b.x * b.x * (1.0f - c), b.x * b.y * (1.0f - c) - b.z * s, b.x * b.z * (1.0f - c) + b.y * s, 0.0f,
	b.x * b.y * (1.0f - c) + b.z * s, c + b.y * b.y * (1.0f - c), b.y * b.z * (1.0f - c) - b.x * s, 0.0f,
	b.x * b.z * (1.0f - c) - b.y * s, b.y * b.z * (1.0f - c) + b.x * s, c + b.z * b.z * (1.0f - c), 0.0f,
	0.0f, 0.0f, 0.0f, 1.0f);
	return zxMath::product(M, R);
}

zxMath::mat4 zxMath::translate(zxMath::mat4 M, zxMath::vec3 t)
{
	M.m[ 3] = t.x;
	M.m[ 7] = t.y;
	M.m[11] = t.z;
	return M;
}

zxMath::mat4 zxMath::modelViewProjection(zxMath::mat4 M, zxMath::mat4 V, zxMath::mat4 P)
{
	return zxMath::product(zxMath::product(M, V), P);
}

zxMath::mat4 zxMath::defaultCamera(zxMath::vec3 E, zxMath::vec3 C)
{
	zxMath::vec3 U(0.0f, 0.0f, 1.0f);
	return zxMath::lookAt(E, C, U);
}

zxMath::mat2 zxMath::toMat2(zxMath::mat3 A)
{
	return zxMath::mat2(A.m[0], A.m[1], A.m[3], A.m[4]);
}

zxMath::mat2 zxMath::toMat2(zxMath::mat4 A)
{
	return zxMath::mat2(A.m[0], A.m[1], A.m[4], A.m[5]);
}

zxMath::mat3 zxMath::toMat3(zxMath::mat2 A)
{
	return zxMath::mat3(A.m[0], A.m[1], 0.0f, A.m[2], A.m[3], 0.0f, 0.0f, 0.0f, 1.0f);
}

zxMath::mat3 zxMath::toMat3(zxMath::mat4 A)
{
	return zxMath::mat3(A.m[0], A.m[1], A.m[2], A.m[4], A.m[5], A.m[6], A.m[8], A.m[9], A.m[10]);
}

zxMath::mat4 zxMath::toMat4(zxMath::mat2 A)
{
	return zxMath::mat4(A.m[0], A.m[1], 0.0f, 0.0f, A.m[2], A.m[3], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
}

zxMath::mat4 zxMath::toMat4(zxMath::mat3 A)
{
	return zxMath::mat4(A.m[0], A.m[1], A.m[2], 0.0f, A.m[3], A.m[4], A.m[5], 0.0f, A.m[6], A.m[7], A.m[8], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
}

//
// zxGlobal.h
//
#ifndef zxGlobal_h
#define zxGlobal_h
#include "zxWindow.h"
#include <vector>

struct mouse
{
	int button;
	int state;
	int x, y;
};

extern std::vector <zxWindow*> WINDOW;
extern mouse MOUSE;
extern float TIME;

#endif

//
// zxGlobal.cpp
//
#include "zxGlobal.h"

std::vector <zxWindow*> WINDOW;
mouse MOUSE;
float TIME;
La classe zxContent costituisce una classe vuota. I suoi metodi possono essere ridefiniti per passare contenuti grafici alla finestra.
//
// zxContent
//
#ifndef zxContent_h
#define zxContent_h

class zxContent
{
	public:
	zxContent();
	~zxContent();
	virtual void			init();
	virtual void			display();
};

#endif

//
// zxContent.cpp
//
#include "zxContent.h"

zxContent::zxContent()
{
}

zxContent::~zxContent()
{
}

void zxContent::init()
{
}

void zxContent::display()
{
}
Quindi la classe che gestisce la finestra vera e propria.
//
// zxWindow.h
//
#ifndef zxWindow_h
#define zxWindow_h
#include <string>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include "zxContent.h"

class zxWindow
{
    private:
    static bool ini;
    static unsigned int ID;
    unsigned int id;
    std::string title;
    zxContent *content;
    static void display();
    static void mouse(int button, int state, int x, int y);
    static void motion(int x, int y);
    static void passive(int x, int y);
    void create(int x, int y, unsigned int width, unsigned int height, std::string title, zxContent *content);
    static void init();

    public:
    zxWindow(zxContent *content);
    zxWindow(int x, int y, unsigned int width, unsigned int height, std::string title, zxContent *content);
    zxWindow(unsigned int width, unsigned int height, zxContent *content);
    ~zxWindow();

    unsigned int getId();
    int getX();
    int getY();
    unsigned int getWidth();
    unsigned int getHeight();
    void getPosition(int (&position)[2]);
    void getSize(unsigned int (&size)[2]);
    std::string getTitle();
    unsigned int getScreenWidth();
    unsigned int getScreenHeight();
    void getScreenSize(unsigned int (&screen)[2]);

    void setX(int x);
    void setY(int y);
    void setWidth(unsigned int width);
    void setHeight(unsigned int height);
    void setPosition(int x, int y);
    void setSize(unsigned int width, unsigned int height);
    void setTitle(std::string title);
    void setContent(zxContent *content);

    static void timer(int id);
    static void mainLoop();
};

#endif

//
// zxWindow.cpp
//
#include <iostream>
#include "zxWindow.h"
#include "zxGlobal.h"

bool zxWindow::ini = false;

zxWindow::zxWindow(zxContent *content)
{
    this->create(0, 0, 200, 200, "window", content);
}

zxWindow::zxWindow(int x, int y, unsigned int width, unsigned int height, std::string title, zxContent *content)
{
    this->create(x, y, width, height, title, content);
}

zxWindow::zxWindow(unsigned int width, unsigned int height, zxContent *content)
{
    this->create(0, 0, width, height, "window", content);
}

zxWindow::~zxWindow()
{

}

void zxWindow::create(int x, int y, unsigned int width, unsigned int height, std::string title, zxContent *content)
{
    zxWindow::init();
    this->content = content;
    WINDOW.push_back(this);
    this->title = title;
    glutInitWindowPosition(x, y);
    glutInitWindowSize(width, height);
    this->id = glutCreateWindow(title.c_str());
    if(glewInit() != GLEW_OK)
    {
        std::cout << "GLEW not initialized\n";
    }
    glutDisplayFunc(zxWindow::display);
    //glutIdleFunc(zxWindow::display);
    glutMouseFunc(zxWindow::mouse);
    glutMotionFunc(zxWindow::motion);
    glutPassiveMotionFunc(zxWindow::passive);
    this->content->init();
    glutTimerFunc(30, this->timer, 0);
}

void zxWindow::init()
{
    if(!zxWindow::ini)
    {
        int argc = 0; char **argv;
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
        zxWindow::ini = true;
        //glutLeaveMainLoop();
    }
}

void zxWindow::display()
{
    int id = glutGetWindow();
    WINDOW[id - 1]->content->display();
}

void zxWindow::mouse(int button, int state, int x, int y)
{
    MOUSE.button = button;
    MOUSE.state = state;
    MOUSE.x = x;
    MOUSE.y = y;
    glutPostRedisplay();
}

void zxWindow::motion(int x, int y)
{
    MOUSE.x = x;
    MOUSE.y = y;
    glutPostRedisplay();
}

void zxWindow::passive(int x, int y)
{
    MOUSE.x = x;
    MOUSE.y = y;
    glutPostRedisplay();
}

unsigned int zxWindow::getId()
{
    return this->id;
}

int zxWindow::getX()
{
    return glutGet(GLUT_WINDOW_X);
}

int zxWindow::getY()
{
    return glutGet(GLUT_WINDOW_Y);
}

unsigned int zxWindow::getWidth()
{
    return glutGet(GLUT_WINDOW_WIDTH);
}

unsigned int zxWindow::getHeight()
{
    return glutGet(GLUT_WINDOW_HEIGHT);
}

void zxWindow::getPosition(int (&position)[2])
{
    position[0] = glutGet(GLUT_WINDOW_X);
    position[1] = glutGet(GLUT_WINDOW_Y);
}

void zxWindow::getSize(unsigned int (&size)[2])
{
    size[0] = glutGet(GLUT_WINDOW_WIDTH);
    size[1] = glutGet(GLUT_WINDOW_HEIGHT);
}

std::string zxWindow::getTitle()
{
    return this->title;
}

unsigned int zxWindow::getScreenWidth()
{
    return glutGet(GLUT_SCREEN_WIDTH);
}

unsigned int zxWindow::getScreenHeight()
{
    return glutGet(GLUT_SCREEN_HEIGHT);
}

void zxWindow::getScreenSize(unsigned int (&screen)[2])
{
    screen[0] = glutGet(GLUT_SCREEN_WIDTH);
    screen[1] = glutGet(GLUT_SCREEN_HEIGHT);
}

void zxWindow::setX(int x)
{

}

void zxWindow::setY(int y)
{

}

void zxWindow::setWidth(unsigned int width)
{

}

void zxWindow::setHeight(unsigned int height)
{

}

void zxWindow::setPosition(int x, int y)
{

}

void zxWindow::setSize(unsigned int width, unsigned int height)
{

}

void zxWindow::setTitle(std::string title)
{
    this->title = title;
    glutSetWindowTitle(title.c_str());
}

void zxWindow::setContent(zxContent *content)
{
    this->content = content;
}

void zxWindow::mainLoop()
{
    glutMainLoop();
}

void zxWindow::timer(int id)
{
    glutPostRedisplay();
    glutTimerFunc(30, zxWindow::timer, 0);
}
Infine il file main.cpp che disegna la shape.
Nello script è esemplificato come si usano VAO, VBO, glDrawElements e attributi.
Il VAO è una sorta di contenitore generale che permette di raggruppare vari VBO e inviarli al vertex shader.
Gli attributi permettono di distinguere i vari gruppi di dati (vertici, colori, texture, normali, ecc) e identificarli nel vertex shader.
//
// main.cpp
//
#include <iostream>
#include "zxWindow.h"
#include "zxShader.h"
#include "zxMath.h"
#include "zxGlobal.h"

zxShader *shader;
GLuint VAO, VBO, EBO;
float rad = .0174533;

class myContent:public zxContent
{
	public:

	void init()
	{
		TIME = 0;
		// definizione dei vertici di un pentagono regolare
		float ver[] = { // 3 valori per il vertice e 3 per il colore
			cos(0.0f * rad) * 30.0f+100, sin(0.0f * rad) * 30.0f+100, 0, 1,0,1,
			cos(72.0f * rad) * 30.0f+100, sin(72.0f * rad) * 30.0f+100, 0, 1,1,0,
			cos(144.0f * rad) * 30.0f+100, sin(144.0f * rad) * 30.0f+100, 0, 0,1,1,
			cos(216.0f * rad) * 30.0f+100, sin(216.0f * rad) * 30.0f+100, 0, 0,1,0,
			cos(288.0f * rad) * 30.0f+100, sin(288.0f * rad) * 30.0f+100, 0, 1,0,0
		};

		unsigned int ind[] = {
			0, 1, 3, 1, 2, 3, 4, 0, 3
		};
		
		glGenVertexArrays(1, &VAO);
		glGenBuffers(1, &VBO);
		glGenBuffers(1, &EBO);

		glBindVertexArray(VAO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 30, ver, GL_STATIC_DRAW); // dimensioni dell'array ver
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 9, ind, GL_STATIC_DRAW); // dimensioni dell'array ind 

		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // i primi 3 valori su 6 sono il vertice
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); // i secondi 3 valori rappresentano il colore
		glEnableVertexAttribArray(1);

		shader = new zxShader();
    		shader->load("shaders/vert.txt", "", "shaders/frag.txt");
	}

	void display()
	{
		unsigned int W = WINDOW[0]->getWidth(), H = WINDOW[0]->getHeight();
		glViewport(0, 0, W, H);
		zxMath::mat4 P = zxMath::ortho(0.0f, (float)W, (float)H, 0.0f, 0.0f, 1.0f);
		//zxMath::mat4 P = zxMath::perspective(45.0f, (float)W / (float)H, .1f, 100.0f);
		//zxMath::mat4 V = zxMath::lookAt(zxMath::vec3(0,-10,0), zxMath::vec3(0,0,0), zxMath::vec3(0,0,1));
		zxMath::mat4 V = zxMath::mat4();
		zxMath::mat4 M = zxMath::mat4();
		M = zxMath::rotate(M, TIME, zxMath::vec3(0,0,1));
		zxMath::mat4 MVP = zxMath::modelViewProjection(M, V, P);
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		//
		shader->start();
		shader->uniformMatrix("MVP", 1, false, MVP.m);
		glBindVertexArray(VAO);
		glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0); // 3 vertici * 3 triangoli
		shader->stop();
		//
		TIME++;
		glutSwapBuffers();
	}
};

int main()
{
	zxContent *content = new myContent();
	zxWindow *win1 = new zxWindow(100, 100, 500, 500, "prova1", content);
	zxWindow *win2 = new zxWindow(150, 150, 200, 200, "prova2", content); // nelle due finestre (indipendenti) gira la stessa routine content->display
	zxWindow::mainLoop();
}
E' possibile scaricare tutto il pacchetto dal seguente link:
freeglut.zip

Biografia

Mi chiamo Cosimo Saccone e sono un programmatore napoletano di 44 anni con oltre 35 anni di esperienza nella programmazione (BASIC, Assembly). Realizzo progetti e programmi utilizzando i principali e più diffusi linguaggi (C, C++, PHP, Javascript, HTML) e software per la grafica (Photoshop, Illustrator, 3dsMax). Anche se la grafica rappresenta il mio principale settore di interesse, non disdegno il lavoro di back-end e di organizzazione dati e sono attento agli aspetti di efficienza e di risparmio delle risorse tipica della programmazione di basso livello (specie nel settore della grafica 3d). Realizzo siti internet, applicativi desktop e servizi di vario tipo. Ho una buona conoscenza della libreria OpenGL per lo sviluppo di applicazioni 3d interattive in C/C++. Cerco di adottare uno stile di programmazione fortemente ordinato e modulare. Possiedo, inoltre, una buona capacità di elaborazione della documentazione. Ho vari hobbies tra cui la pittura, la ginnastica e le lunghe passeggiate in solitudine.

facebook instagram youtube
HTML5 Template create by Cosimo Saccone 2022

Al fine di migliorare l’esperienza di navigazione sul nostro sito noi di cosimosaccone.com e i nostri partner selezionati elaboriamo i dati personali, compreso l’indirizzo IP e le pagine visitate, in relazione alla tua navigazione nei contenuti del sito, per i seguenti scopi:

Accesso alle informazioni
Dati precisi di geolocalizzazione
Misurazione del pubblico
Pubblicità e contenuti personalizzati
Ti ricordiamo che il termine cookie si riferisce a una porzione di dati inviati al tuo browser da un web server. Il cookie viene memorizzato sul tuo dispositivo e riconosciuto dal sito web che lo ha inviato in ogni navigazione successiva. Se vuoi saperne di più e compiere una scelta diversa, come il rifiuto del trattamento dei tuoi dati personali, clicca qui sulla nostra privacy policy. Potrai sempre modificare le tue scelte e impostare i singolo cookies selezionando il bottone qui sotto.
OK