gears scene working with the sheer power of iman
This commit is contained in:
parent
5a90c96615
commit
524dcab7be
@ -5,4 +5,4 @@ SortIncludes: false
|
||||
Language: Cpp
|
||||
# Force pointers to the type for C++.
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
PointerAlignment: Left
|
||||
|
3
.clangd
3
.clangd
@ -11,7 +11,8 @@ Diagnostics:
|
||||
modernize-avoid-c-arrays,
|
||||
readability-magic-numbers,
|
||||
readability-implicit-bool-conversion,
|
||||
readability-identifier-length
|
||||
readability-identifier-length,
|
||||
bugprone-easily-swappable-parameters
|
||||
]
|
||||
|
||||
Completion:
|
||||
|
@ -67,11 +67,11 @@ SET(CMAKE_CXX_FLAGS
|
||||
SET(SOURCE_FILES
|
||||
src/game/game.cpp
|
||||
|
||||
src/graphics/opengl/opengl.cpp
|
||||
src/graphics/graphics.cpp
|
||||
|
||||
src/input/input.cpp
|
||||
|
||||
src/scene/example/example.cpp
|
||||
src/scene/gears/gears.cpp
|
||||
|
||||
src/window/window.cpp
|
||||
|
||||
@ -114,8 +114,8 @@ ENDIF()
|
||||
|
||||
TARGET_LINK_LIBRARIES(HomdEngine
|
||||
sdl2
|
||||
glew32
|
||||
opengl32
|
||||
glew32
|
||||
${win32_link}
|
||||
)
|
||||
|
||||
|
@ -4,14 +4,14 @@
|
||||
*/
|
||||
|
||||
#include <game/game.h>
|
||||
#include <scene/example/example.h>
|
||||
#include <graphics/opengl/opengl.h>
|
||||
#include <graphics/graphics.h>
|
||||
#include <scene/gears/gears.h>
|
||||
|
||||
Game::Game() {
|
||||
this->pWindow = new Window(this);
|
||||
this->pRenderer = new OpenGL(this);
|
||||
this->pRenderer = new Graphics(this);
|
||||
this->pInput = new Input(this);
|
||||
this->scenes.push(new Example(this));
|
||||
this->scenes.push(new GearsScene(this));
|
||||
}
|
||||
|
||||
void Game::loop() {
|
||||
|
178
src/graphics/graphics.cpp
Normal file
178
src/graphics/graphics.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GL/glew.h>
|
||||
#include <SDL2/SDL_video.h>
|
||||
|
||||
#include <game/game.h>
|
||||
#include <graphics/graphics.h>
|
||||
#include <window/window.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
void GLAPIENTRY MessageCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
const void* userParam) {
|
||||
fprintf(stderr,
|
||||
"GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
|
||||
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type,
|
||||
severity, message);
|
||||
}
|
||||
|
||||
Graphics::Graphics(Game* game) {
|
||||
this->pGame = game;
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
|
||||
this->context = SDL_GL_CreateContext(this->pGame->pWindow->window);
|
||||
|
||||
glewExperimental = GL_TRUE;
|
||||
glewInit();
|
||||
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(MessageCallback, nullptr);
|
||||
}
|
||||
|
||||
void Graphics::storeVertexBufObj(GLuint& dest, GLsizeiptr size, int* target) {
|
||||
// Store the vertices in a vertex buffer object
|
||||
glGenBuffers(1, &dest);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, dest);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, target, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void Graphics::multiply4x4Matrices(GLfloat* m, const GLfloat* n) {
|
||||
GLfloat tmp[16];
|
||||
const GLfloat* row;
|
||||
const GLfloat* column;
|
||||
div_t d;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
tmp[i] = 0;
|
||||
d = div(i, 4);
|
||||
row = n + d.quot * 4;
|
||||
column = m + d.rem;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
tmp[i] += row[j] * column[j * 4];
|
||||
}
|
||||
}
|
||||
memcpy(m, &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
void Graphics::rotate4x4Matrix(GLfloat* m,
|
||||
GLfloat angle,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat z) {
|
||||
double sin;
|
||||
double cos;
|
||||
|
||||
sincos(angle, &sin, &cos);
|
||||
GLfloat r[16] = {(GLfloat)(x * x * (1 - cos) + cos),
|
||||
(GLfloat)(y * x * (1 - cos) + z * sin),
|
||||
(GLfloat)(x * z * (1 - cos) - y * sin),
|
||||
0,
|
||||
(GLfloat)(x * y * (1 - cos) - z * sin),
|
||||
(GLfloat)(y * y * (1 - cos) + cos),
|
||||
(GLfloat)(y * z * (1 - cos) + x * sin),
|
||||
0,
|
||||
(GLfloat)(x * z * (1 - cos) + y * sin),
|
||||
(GLfloat)(y * z * (1 - cos) - x * sin),
|
||||
(GLfloat)(z * z * (1 - cos) + cos),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1};
|
||||
|
||||
multiply4x4Matrices(m, r);
|
||||
}
|
||||
|
||||
void Graphics::translate4x4Matrix(GLfloat* m, GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat t[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
|
||||
|
||||
multiply4x4Matrices(m, t);
|
||||
}
|
||||
|
||||
void Graphics::create4x4IdentityMatrix(GLfloat* m) {
|
||||
GLfloat t[16] = {
|
||||
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
memcpy(m, t, sizeof(t));
|
||||
}
|
||||
|
||||
void Graphics::transpose4x4Matrix(GLfloat* m) {
|
||||
GLfloat t[16] = {m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13],
|
||||
m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]};
|
||||
|
||||
memcpy(m, t, sizeof(t));
|
||||
}
|
||||
|
||||
void Graphics::invert4x4Matrix(GLfloat* m) {
|
||||
GLfloat t[16];
|
||||
create4x4IdentityMatrix(t);
|
||||
|
||||
// Extract and invert the translation part 't'. The inverse of a
|
||||
// translation matrix can be calculated by negating the translation
|
||||
// coordinates.
|
||||
t[12] = -m[12];
|
||||
t[13] = -m[13];
|
||||
t[14] = -m[14];
|
||||
|
||||
// Invert the rotation part 'r'. The inverse of a rotation matrix is
|
||||
// equal to its transpose.
|
||||
m[12] = m[13] = m[14] = 0;
|
||||
transpose4x4Matrix(m);
|
||||
|
||||
// inv(m) = inv(r) * inv(t)
|
||||
multiply4x4Matrices(m, t);
|
||||
}
|
||||
|
||||
void Graphics::calcPerspectiveProjectTransformation(GLfloat* m,
|
||||
GLfloat yFOV,
|
||||
GLfloat aspect,
|
||||
GLfloat zNear,
|
||||
GLfloat zFar) {
|
||||
GLfloat tmp[16];
|
||||
create4x4IdentityMatrix(tmp);
|
||||
|
||||
double sine;
|
||||
double cosine;
|
||||
double cotangent;
|
||||
double deltaZ;
|
||||
GLfloat radians = yFOV / 2.0F * (float)M_PI / 180.0F;
|
||||
|
||||
deltaZ = zFar - zNear;
|
||||
sincos(radians, &sine, &cosine);
|
||||
|
||||
if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cotangent = cosine / sine;
|
||||
|
||||
tmp[0] = (float)cotangent / aspect;
|
||||
tmp[5] = (float)cotangent;
|
||||
tmp[10] = -(zFar + zNear) / (float)deltaZ;
|
||||
tmp[11] = -1;
|
||||
tmp[14] = -2 * zNear * zFar / (float)deltaZ;
|
||||
tmp[15] = 0;
|
||||
|
||||
memcpy(m, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
void Graphics::draw() {
|
||||
SDL_GL_SwapWindow(this->pGame->pWindow->window);
|
||||
}
|
@ -3,17 +3,98 @@
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef _HOMD_GRAPHICS
|
||||
#define _HOMD_GRAPHICS
|
||||
#ifndef _HOMD_GRAPHICS_GL
|
||||
#define _HOMD_GRAPHICS_GL
|
||||
|
||||
#define GLEW_STATIC
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GL/glew.h>
|
||||
#include <SDL2/SDL_video.h>
|
||||
|
||||
class Game;
|
||||
class Window;
|
||||
|
||||
class Graphics {
|
||||
Game* pGame;
|
||||
SDL_GLContext context = nullptr;
|
||||
|
||||
public:
|
||||
Game* game;
|
||||
Graphics() = default;
|
||||
virtual ~Graphics() = default;
|
||||
virtual void drawSomething() = 0;
|
||||
Graphics(Game*);
|
||||
~Graphics() = default;
|
||||
|
||||
void setGLContext();
|
||||
|
||||
void draw();
|
||||
|
||||
static void storeVertexBufObj(GLuint&, GLsizeiptr, int*);
|
||||
|
||||
/**
|
||||
* Multiplies two 4x4 matrices
|
||||
*
|
||||
* The result is stored in matrix m.
|
||||
*
|
||||
* @param m first matrix
|
||||
* @param n second matrix
|
||||
*/
|
||||
static void multiply4x4Matrices(GLfloat*, const GLfloat*);
|
||||
|
||||
/**
|
||||
* Rotates a 4x4 matrix
|
||||
*
|
||||
* @param[in,out] m the matrix to rotate
|
||||
* @param angle the angle to rotate
|
||||
* @param x the x component of the direction to rotate to
|
||||
* @param y the y component of the direction to rotate to
|
||||
* @param z the z component of the direction to rotate to
|
||||
*/
|
||||
static void rotate4x4Matrix(GLfloat*, GLfloat, GLfloat, GLfloat, GLfloat);
|
||||
|
||||
/**
|
||||
* Translates a 4x4 matrix
|
||||
*
|
||||
* @param[in,out] m the matrix to translate
|
||||
* @param x the x component of the direction to translate to
|
||||
* @param y the y component of the direction to translate to
|
||||
* @param z the z component of the direction to translate to
|
||||
*/
|
||||
static void translate4x4Matrix(GLfloat*, GLfloat, GLfloat, GLfloat);
|
||||
|
||||
/**
|
||||
* Creates a 4x4 identity matrix
|
||||
*
|
||||
* @param m the matrix to convert to an identity matrix
|
||||
*/
|
||||
static void create4x4IdentityMatrix(GLfloat*);
|
||||
|
||||
/**
|
||||
* Transposes a 4x4 matrix.
|
||||
*
|
||||
* @param m the matrix to transpose
|
||||
*/
|
||||
static void transpose4x4Matrix(GLfloat*);
|
||||
|
||||
/**
|
||||
* Inverts a 4x4 matrix.
|
||||
*
|
||||
* @param m the matrix to invert
|
||||
*/
|
||||
static void invert4x4Matrix(GLfloat*);
|
||||
|
||||
/**
|
||||
* Calculate a perspective projection transformation.
|
||||
*
|
||||
* @param m the matrix to save the transformation in
|
||||
* @param yFOV the field of view in the y direction
|
||||
* @param aspect the view aspect ratio
|
||||
* @param zNear the near clipping plane
|
||||
* @param zFar the far clipping plane
|
||||
*/
|
||||
static void calcPerspectiveProjectTransformation(GLfloat*,
|
||||
GLfloat,
|
||||
GLfloat,
|
||||
GLfloat,
|
||||
GLfloat);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#define GLEW_STATIC
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <graphics/opengl/opengl.h>
|
||||
#include <game/game.h>
|
||||
#include <window/window.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
static const GLchar* vertexShaderSrc = R"(
|
||||
attribute vec4 position;
|
||||
void main() {
|
||||
gl_Position = vec4(position.xyz, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
static const GLchar* fragmentShaderSrc = R"(
|
||||
precision mediump float;
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
static GLfloat vertices[] = {0.0, 0.8, -0.8, -0.8, 0.8, -0.8};
|
||||
|
||||
OpenGL::OpenGL(Game* pGame) {
|
||||
glewExperimental = GL_TRUE;
|
||||
this->game = pGame;
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
|
||||
this->context = SDL_GL_CreateContext(this->game->pWindow->window);
|
||||
|
||||
GLenum err = glewInit();
|
||||
std::cout << glewGetErrorString(err);
|
||||
|
||||
GLuint vertexArrObj;
|
||||
glGenVertexArrays(1, &vertexArrObj);
|
||||
glBindVertexArray(vertexArrObj);
|
||||
|
||||
GLuint vertexBufObj;
|
||||
glGenBuffers(1, &vertexBufObj);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBufObj);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
GLint posAttribute = glGetAttribLocation(shaderProgram, "position");
|
||||
glEnableVertexAttribArray(posAttribute);
|
||||
glVertexAttribPointer(posAttribute, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
}
|
||||
|
||||
void OpenGL::drawSomething() {
|
||||
glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
SDL_GL_SwapWindow(this->game->pWindow->window);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef _HOMD_GRAPHICS_GL
|
||||
#define _HOMD_GRAPHICS_GL
|
||||
|
||||
#include <SDL2/SDL_video.h>
|
||||
#include <graphics/graphics.h>
|
||||
|
||||
class Window;
|
||||
|
||||
class OpenGL : public Graphics {
|
||||
SDL_GLContext context = nullptr;
|
||||
|
||||
public:
|
||||
OpenGL(Game*);
|
||||
~OpenGL() override = default;
|
||||
|
||||
void setGLContext();
|
||||
void drawSomething() override;
|
||||
};
|
||||
|
||||
#endif
|
@ -3,8 +3,8 @@
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <input/input.h>
|
||||
#include <game/game.h>
|
||||
#include <input/input.h>
|
||||
|
||||
Input::Input(Game* pGame) {
|
||||
this->game = pGame;
|
||||
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <game/game.h>
|
||||
#include <graphics/graphics.h>
|
||||
#include <scene/example/example.h>
|
||||
|
||||
Example::Example(Game* pGame) {
|
||||
this->game = pGame;
|
||||
}
|
||||
|
||||
void Example::draw() {
|
||||
this->game->pRenderer->drawSomething();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <scene/scene.h>
|
||||
|
||||
class Example : public Scene {
|
||||
public:
|
||||
Example(Game*);
|
||||
void draw() override;
|
||||
};
|
411
src/scene/gears/gears.cpp
Normal file
411
src/scene/gears/gears.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GL/glew.h>
|
||||
#include <game/game.h>
|
||||
#include <graphics/graphics.h>
|
||||
#include <scene/gears/gears.h>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
static const char* vertexShader = R"(
|
||||
attribute vec3 position;
|
||||
attribute vec3 normal;
|
||||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
uniform mat4 NormalMatrix;
|
||||
uniform vec4 LightSourcePosition;
|
||||
uniform vec4 MaterialColor;
|
||||
|
||||
varying vec4 Color;
|
||||
|
||||
void main(void) {
|
||||
// Transform the normal to eye coordinates
|
||||
vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));
|
||||
|
||||
// The LightSourcePosition is the direction for directional light
|
||||
vec3 L = normalize(LightSourcePosition.xyz);
|
||||
|
||||
float diffuse = max(dot(N, L), 0.0);
|
||||
float ambient = 0.2;
|
||||
|
||||
// Multiply the diffuse value by the vertex color
|
||||
// to get the actual color that will be used to draw the vertex with
|
||||
|
||||
// Color = diffuse * MaterialColor;
|
||||
Color = vec4((ambient + diffuse) * MaterialColor.xyz, MaterialColor.a);
|
||||
|
||||
gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
static const char* fragmentShader = R"(
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
varying vec4 Color;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = Color;
|
||||
}
|
||||
)";
|
||||
|
||||
GearsScene::GearsScene(Game* pGame) {
|
||||
this->pGame = pGame;
|
||||
char msg[512];
|
||||
const char* p;
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
GLuint vertex;
|
||||
GLuint fragment;
|
||||
GLuint program;
|
||||
|
||||
p = vertexShader;
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &p, nullptr);
|
||||
glCompileShader(vertex);
|
||||
glGetShaderInfoLog(vertex, sizeof msg, nullptr, msg);
|
||||
std::cout << "Vertex shader info: " << msg << "\n";
|
||||
|
||||
p = fragmentShader;
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment, 1, &p, nullptr);
|
||||
glCompileShader(fragment);
|
||||
glGetShaderInfoLog(fragment, sizeof msg, nullptr, msg);
|
||||
std::cout << "Fragment shader info: " << msg << "\n";
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex);
|
||||
glAttachShader(program, fragment);
|
||||
glBindAttribLocation(program, 0, "position");
|
||||
glBindAttribLocation(program, 1, "normal");
|
||||
|
||||
glLinkProgram(program);
|
||||
glGetProgramInfoLog(program, sizeof msg, nullptr, msg);
|
||||
std::cout << "Program info: " << msg << "\n";
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
this->modelViewProjectionMatrixLoc =
|
||||
glGetUniformLocation(program, "ModelViewProjectionMatrix");
|
||||
this->normalMatrixLoc = glGetUniformLocation(program, "NormalMatrix");
|
||||
this->lightSrcPosLoc = glGetUniformLocation(program, "LightSourcePosition");
|
||||
this->materialColorLoc = glGetUniformLocation(program, "MaterialColor");
|
||||
|
||||
glUniform4fv((GLint)this->lightSrcPosLoc, 1, lightSourcePos);
|
||||
|
||||
gears[0] = createGear(1.0, 4.0, 1.0, 20, 0.7);
|
||||
gears[1] = createGear(0.5, 2.0, 2.0, 10, 0.7);
|
||||
gears[2] = createGear(1.3, 2.0, 0.5, 10, 0.7);
|
||||
}
|
||||
|
||||
GearVertex* GearsScene::fillGearVertex(GearVertex* gearVertex,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat z,
|
||||
const GLfloat n[3]) {
|
||||
gearVertex[0][0] = x;
|
||||
gearVertex[0][1] = y;
|
||||
gearVertex[0][2] = z;
|
||||
gearVertex[0][3] = n[0];
|
||||
gearVertex[0][4] = n[1];
|
||||
gearVertex[0][5] = n[2];
|
||||
|
||||
return gearVertex + 1;
|
||||
}
|
||||
|
||||
Gear* GearsScene::createGear(GLfloat innerRad,
|
||||
GLfloat outerRad,
|
||||
GLfloat width,
|
||||
GLfloat teeth,
|
||||
GLfloat toothDepth) {
|
||||
GLfloat rad0;
|
||||
GLfloat rad1;
|
||||
GLfloat rad2;
|
||||
GLfloat diameter;
|
||||
|
||||
GearVertex* vertex;
|
||||
Gear* gear;
|
||||
|
||||
double sinArr[5];
|
||||
double cosArr[5];
|
||||
GLfloat normal[3];
|
||||
|
||||
int currentStrip = 0;
|
||||
|
||||
gear = (Gear*)malloc(sizeof *gear);
|
||||
|
||||
// Calculate the radii used in the gear
|
||||
rad0 = innerRad;
|
||||
rad1 = outerRad - toothDepth / 2.0F;
|
||||
rad2 = outerRad + toothDepth / 2.0F;
|
||||
|
||||
diameter = 2.0F * (float)M_PI / teeth / 4.0F;
|
||||
|
||||
// Allocate triangle strip information
|
||||
gear->nStrips = STRIPS_PER_TOOTH * teeth;
|
||||
gear->strips = (VertexStrip*)calloc(gear->nStrips, sizeof(*gear->vertices));
|
||||
|
||||
// Allocate the vertices
|
||||
gear->vertices = (GearVertex*)calloc(VERTICES_PER_TOOTH * teeth,
|
||||
sizeof(*gear->vertices));
|
||||
vertex = gear->vertices;
|
||||
|
||||
// Calculate needed sin/cos for various angles
|
||||
for (int i = 0; i < (int)teeth; ++i) {
|
||||
sincos((float)i * 2.0F * M_PI / teeth, &sinArr[0], &cosArr[0]);
|
||||
sincos((float)i * 2.0F * M_PI / teeth + diameter, &sinArr[1],
|
||||
&cosArr[1]);
|
||||
sincos((float)i * 2.0F * M_PI / teeth + diameter * 2, &sinArr[2],
|
||||
&cosArr[2]);
|
||||
sincos((float)i * 2.0F * M_PI / teeth + diameter * 3, &sinArr[3],
|
||||
&cosArr[3]);
|
||||
sincos((float)i * 2.0F * M_PI / teeth + diameter * 4, &sinArr[4],
|
||||
&cosArr[4]);
|
||||
|
||||
// Macros that do shit idk
|
||||
#define GEAR_POINT(r, da) \
|
||||
{ (float)((r)*cosArr[(da)]), (float)((r)*sinArr[(da)]) }
|
||||
#define SET_NORMAL(x, y, z) \
|
||||
do { \
|
||||
normal[0] = (x); \
|
||||
normal[1] = (y); \
|
||||
normal[2] = (z); \
|
||||
} while (0)
|
||||
|
||||
#define GEAR_VERT(v, point, sign) \
|
||||
fillGearVertex((v), points[(point)].x, points[(point)].y, \
|
||||
(sign)*width * 0.5, normal)
|
||||
|
||||
#define START_STRIP \
|
||||
do { \
|
||||
gear->strips[currentStrip].first = vertex - gear->vertices; \
|
||||
} while (0);
|
||||
|
||||
#define END_STRIP \
|
||||
do { \
|
||||
int _tmp = (vertex - gear->vertices); \
|
||||
gear->strips[currentStrip].count = \
|
||||
_tmp - gear->strips[currentStrip].first; \
|
||||
currentStrip++; \
|
||||
} while (0)
|
||||
|
||||
#define QUAD_WITH_NORMAL(p1, p2) \
|
||||
do { \
|
||||
SET_NORMAL((points[(p1)].y - points[(p2)].y), \
|
||||
-(points[(p1)].x - points[(p2)].x), 0); \
|
||||
vertex = GEAR_VERT(vertex, (p1), -1); \
|
||||
vertex = GEAR_VERT(vertex, (p1), 1); \
|
||||
vertex = GEAR_VERT(vertex, (p2), -1); \
|
||||
vertex = GEAR_VERT(vertex, (p2), 1); \
|
||||
} while (0)
|
||||
|
||||
using Point = struct {
|
||||
GLfloat x;
|
||||
GLfloat y;
|
||||
};
|
||||
|
||||
// Create 7 points (x,y coords) that make up a tooth
|
||||
Point points[7] = {
|
||||
GEAR_POINT(rad2, 1), GEAR_POINT(rad2, 2), GEAR_POINT(rad1, 0),
|
||||
GEAR_POINT(rad1, 3), GEAR_POINT(rad0, 0), GEAR_POINT(rad1, 4),
|
||||
GEAR_POINT(rad0, 4),
|
||||
};
|
||||
|
||||
// Front face
|
||||
START_STRIP;
|
||||
SET_NORMAL(0, 0, 1.0);
|
||||
vertex = GEAR_VERT(vertex, 0, +1);
|
||||
vertex = GEAR_VERT(vertex, 1, +1);
|
||||
vertex = GEAR_VERT(vertex, 2, +1);
|
||||
vertex = GEAR_VERT(vertex, 3, +1);
|
||||
vertex = GEAR_VERT(vertex, 4, +1);
|
||||
vertex = GEAR_VERT(vertex, 5, +1);
|
||||
vertex = GEAR_VERT(vertex, 6, +1);
|
||||
END_STRIP;
|
||||
|
||||
// Inner face
|
||||
START_STRIP;
|
||||
QUAD_WITH_NORMAL(4, 6);
|
||||
END_STRIP;
|
||||
|
||||
// Back face
|
||||
START_STRIP;
|
||||
SET_NORMAL(0, 0, -1.0);
|
||||
vertex = GEAR_VERT(vertex, 6, -1);
|
||||
vertex = GEAR_VERT(vertex, 5, -1);
|
||||
vertex = GEAR_VERT(vertex, 4, -1);
|
||||
vertex = GEAR_VERT(vertex, 3, -1);
|
||||
vertex = GEAR_VERT(vertex, 2, -1);
|
||||
vertex = GEAR_VERT(vertex, 1, -1);
|
||||
vertex = GEAR_VERT(vertex, 0, -1);
|
||||
END_STRIP;
|
||||
|
||||
// Outer face
|
||||
START_STRIP;
|
||||
QUAD_WITH_NORMAL(0, 2);
|
||||
END_STRIP;
|
||||
|
||||
START_STRIP;
|
||||
QUAD_WITH_NORMAL(1, 0);
|
||||
END_STRIP;
|
||||
|
||||
START_STRIP;
|
||||
QUAD_WITH_NORMAL(3, 1);
|
||||
END_STRIP;
|
||||
|
||||
START_STRIP;
|
||||
QUAD_WITH_NORMAL(5, 3);
|
||||
END_STRIP;
|
||||
}
|
||||
|
||||
gear->nVertices = (int)(vertex - gear->vertices);
|
||||
glGenBuffers(1, &gear->vertexBufObj);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, gear->vertexBufObj);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
(GLsizeiptr)(gear->nVertices * sizeof(GearVertex)),
|
||||
gear->vertices, GL_STATIC_DRAW);
|
||||
|
||||
return gear;
|
||||
}
|
||||
|
||||
void GearsScene::drawGear(Gear* gear,
|
||||
GLfloat* transform,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat angle,
|
||||
const GLfloat color[4]) {
|
||||
GLfloat modelView[16];
|
||||
GLfloat normalMatrix[16];
|
||||
GLfloat modelViewProjection[16];
|
||||
|
||||
// Translate and rotate the gear
|
||||
memcpy(modelView, transform, sizeof(modelView));
|
||||
Graphics::translate4x4Matrix(modelView, x, y, 0);
|
||||
Graphics::rotate4x4Matrix(modelView, 2.0F * (float)M_PI * angle / 360.0F, 0,
|
||||
0, 1);
|
||||
|
||||
/* Create and set the ModelViewProjectionMatrix */
|
||||
memcpy(modelViewProjection, this->projectionMatrix,
|
||||
sizeof(modelViewProjection));
|
||||
Graphics::multiply4x4Matrices(modelViewProjection, modelView);
|
||||
|
||||
glUniformMatrix4fv((GLint)this->modelViewProjectionMatrixLoc, 1, GL_FALSE,
|
||||
modelViewProjection);
|
||||
|
||||
/*
|
||||
* Create and set the NormalMatrix. It's the inverse transpose of the
|
||||
* ModelView matrix.
|
||||
*/
|
||||
memcpy(normalMatrix, modelView, sizeof(normalMatrix));
|
||||
Graphics::invert4x4Matrix(normalMatrix);
|
||||
Graphics::transpose4x4Matrix(normalMatrix);
|
||||
glUniformMatrix4fv((GLint)this->normalMatrixLoc, 1, GL_FALSE, normalMatrix);
|
||||
|
||||
/* Set the gear color */
|
||||
glUniform4fv((GLint)this->materialColorLoc, 1, color);
|
||||
|
||||
/* Set the vertex buffer object to use */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, gear->vertexBufObj);
|
||||
|
||||
/* Set up the position of the attributes in the vertex buffer object */
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
|
||||
nullptr);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
|
||||
(GLfloat*)(sizeof(GLfloat) * 3));
|
||||
|
||||
/* Enable the attributes */
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
/* Draw the triangle strips that comprise the gear */
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->nVertices);
|
||||
|
||||
/* Disable the attributes */
|
||||
glDisableVertexAttribArray(1);
|
||||
glDisableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
void GearsScene::reshape() {
|
||||
if (this->width != this->pGame->pWindow->getWidth() ||
|
||||
this->height != this->pGame->pWindow->getHeight()) {
|
||||
this->width = this->pGame->pWindow->getWidth();
|
||||
this->height = this->pGame->pWindow->getHeight();
|
||||
|
||||
Graphics::calcPerspectiveProjectTransformation(
|
||||
this->projectionMatrix, 60.0,
|
||||
(float)this->width / (float)this->height, 1.0, 1024.0);
|
||||
glViewport(0, 0, (GLint)this->width, (GLint)this->height);
|
||||
}
|
||||
}
|
||||
|
||||
void GearsScene::idle() {
|
||||
static int frames = 0;
|
||||
static double tRot0 = -1.0;
|
||||
static double tRate0 = -1.0;
|
||||
double dt;
|
||||
double t = SDL_GetTicks() / 1000.0;
|
||||
|
||||
if (tRot0 < 0.0) {
|
||||
tRot0 = t;
|
||||
}
|
||||
dt = t - tRot0;
|
||||
tRot0 = t;
|
||||
|
||||
/* advance rotation for next frame */
|
||||
this->currentAngle += 70.0 * dt; /* 70 degrees per second */
|
||||
if (this->currentAngle > 3600.0) {
|
||||
this->currentAngle -= 3600.0;
|
||||
}
|
||||
|
||||
this->pGame->pRenderer->draw();
|
||||
frames++;
|
||||
|
||||
if (tRate0 < 0.0) {
|
||||
tRate0 = t;
|
||||
}
|
||||
if (t - tRate0 >= 5.0) {
|
||||
GLfloat seconds = t - tRate0;
|
||||
GLfloat fps = frames / seconds;
|
||||
printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
|
||||
fps);
|
||||
tRate0 = t;
|
||||
frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GearsScene::draw() {
|
||||
const static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
|
||||
const static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
|
||||
const static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
|
||||
GLfloat transform[16];
|
||||
Graphics::create4x4IdentityMatrix(transform);
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/* Translate and rotate the view */
|
||||
Graphics::translate4x4Matrix(transform, 0, 0, -20);
|
||||
Graphics::rotate4x4Matrix(
|
||||
transform, 2.0F * (float)M_PI * viewRotation[0] / 360.0F, 1, 0, 0);
|
||||
Graphics::rotate4x4Matrix(
|
||||
transform, 2.0F * (float)M_PI * viewRotation[1] / 360.0F, 0, 1, 0);
|
||||
Graphics::rotate4x4Matrix(
|
||||
transform, 2.0F * (float)M_PI * viewRotation[2] / 360.0F, 0, 0, 1);
|
||||
|
||||
/* Draw the gears */
|
||||
drawGear(gears[0], transform, -3.0, -2.0, currentAngle, red);
|
||||
drawGear(gears[1], transform, 3.1, -2.0, (float)-2 * currentAngle - 9.0F,
|
||||
green);
|
||||
drawGear(gears[2], transform, -3.1, 4.2, (float)-2 * currentAngle - 25.0F,
|
||||
blue);
|
||||
|
||||
reshape();
|
||||
idle();
|
||||
}
|
114
src/scene/gears/gears.h
Normal file
114
src/scene/gears/gears.h
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2023, Furkan Mudanyali <fmudanyali@icloud.com>
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GL/glew.h>
|
||||
#include <scene/scene.h>
|
||||
|
||||
#define STRIPS_PER_TOOTH 7
|
||||
#define VERTICES_PER_TOOTH 35
|
||||
#define GEAR_VERTEX_STRIDE 6
|
||||
|
||||
// Class describing the vertices in triangle strip
|
||||
using VertexStrip = struct {
|
||||
// First vertex in the strip
|
||||
GLint first;
|
||||
// Number of consecutive verices in the strip after the first
|
||||
GLint count;
|
||||
};
|
||||
|
||||
// Each vertex consists of GEAR_VERTEX_STRIDE GLfloat attributes
|
||||
using GearVertex = GLfloat[GEAR_VERTEX_STRIDE];
|
||||
|
||||
// Class representing a gear
|
||||
using Gear = struct {
|
||||
// Array of vertices comprising the gear
|
||||
GearVertex* vertices;
|
||||
// Number of vertices comprising the gear
|
||||
int nVertices;
|
||||
// Array of triangle strips comprising the gear
|
||||
VertexStrip* strips;
|
||||
// Number of triangle strips comprising the gear
|
||||
int nStrips;
|
||||
// Vertex buffer object holding the vertices in the GPU
|
||||
GLuint vertexBufObj;
|
||||
};
|
||||
|
||||
class GearsScene : public Scene {
|
||||
// The view rotation [x, y, z]
|
||||
GLfloat viewRotation[3] = {20.0, 30.0, 0.0};
|
||||
// The gears
|
||||
Gear* gears[3];
|
||||
// The current gear rotation angle
|
||||
GLfloat currentAngle = 0.0;
|
||||
// The location of the shader uniforms
|
||||
GLuint modelViewProjectionMatrixLoc;
|
||||
GLuint normalMatrixLoc;
|
||||
GLuint lightSrcPosLoc;
|
||||
GLuint materialColorLoc;
|
||||
// The projection matrix
|
||||
GLfloat projectionMatrix[16];
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
void idle();
|
||||
void reshape();
|
||||
// The direction of the directional light for the scene
|
||||
const GLfloat lightSourcePos[4] = {5.0, 5.0, 10.0, 1.0};
|
||||
|
||||
/**
|
||||
* Fills a gear vertex.
|
||||
*
|
||||
* @param gearVertex the vertex to fill
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param z the z coordinate
|
||||
* @param n pointer to the normal table
|
||||
*
|
||||
* @return the operation error code
|
||||
*/
|
||||
static GearVertex* fillGearVertex(GearVertex* gearVertex,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat z,
|
||||
const GLfloat n[3]);
|
||||
|
||||
/**
|
||||
* Create a gear wheel.
|
||||
*
|
||||
* @param innerRad radius of the hole at the center
|
||||
* @param outerRad radius at the center of the teth
|
||||
* @param width width of the gear
|
||||
* @param teeth the number of teeth
|
||||
* @param toothDepth the depth of the teeth
|
||||
*
|
||||
* @return the pointer to the constructed gear struct
|
||||
*/
|
||||
static Gear* createGear(GLfloat innerRad,
|
||||
GLfloat outerRad,
|
||||
GLfloat width,
|
||||
GLfloat teeth,
|
||||
GLfloat toothDepth);
|
||||
|
||||
/**
|
||||
* Draws a gear
|
||||
*
|
||||
* @param gear the gear to draw
|
||||
* @param transform the current transformation matrix
|
||||
* @param x the x pos to draw the gear at
|
||||
* @param y the y pos to draw the gear at
|
||||
* @param angle the rotation angle of the gear
|
||||
* @param color the color of the gear
|
||||
*/
|
||||
void drawGear(Gear*, GLfloat*, GLfloat, GLfloat, GLfloat, const GLfloat[4]);
|
||||
|
||||
// Draws all gears
|
||||
void drawAllGears();
|
||||
|
||||
public:
|
||||
GearsScene(Game*);
|
||||
void draw() override;
|
||||
};
|
@ -10,7 +10,7 @@ class Game;
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Game* game;
|
||||
Game* pGame;
|
||||
|
||||
bool destroy = false;
|
||||
Scene() = default;
|
||||
|
Reference in New Issue
Block a user