Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 167 additions & 31 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,53 +1,189 @@
#include <math.h>
#include<iostream>

#include "engine.hpp"

static int SCR_HEIGHT = 600;
static int SCR_WIDTH = 800;

const char *cubeSource = "/cube2.obj";
const char *catSource = "/cat.obj";
const char *benchSource = "/bench.obj";

const char *vertexShaderSource = "/vertex/standart.vshader";
const char *fragmentShaderSource = "/fragment/standart.fshader";

const char *cubeSource = "/cube.obj";

class MovingBall : public Object {
private:
float MIN_VELOCITY = 0.001;
public:
Vec3 velocity;
float bounciness = 1;
float friction = 0;

void Update(float dt) override {
transform->Translate(velocity * dt);
// transform->Rotate(length(velocity) * dt / transform->GetScale().x / 2, direction);
velocity *= pow(1 - friction, dt);
if (length(velocity) < MIN_VELOCITY) {
velocity = Vec3(0, 0, 0);
}
}

MovingBall(Vec3 position, ShaderProgram * shaderProgram,
std::string diffuseSource, std::string specularSource = "") {
this->renderData = new RenderData();
this->renderData->model = Model::GetSphere();
this->renderData->model->shader = shaderProgram;

auto images = std::vector<std::string>();
images.push_back(diffuseSource);
if (specularSource != "") {
images.push_back(specularSource);
}
this->renderData->material = {
4.f,
Texture(images),
};

bindRenderData(this->renderData);

Object* initModel();
this->collider = new Collider{Sphere{
Vec3(0.0),
1.0f,
}};

transform = new Transform(position, Vec3(1., 1., 1.), Mat4(1.0));
}
};

class GameManager : public Object {
public:
std::vector<MovingBall*> balls;
float minX = -7, maxX = 7, minZ = -7, maxZ = 7;

void Update(float dt) override {
for (int i = 0; i < balls.size(); ++i) {
auto ball = balls[i];
Vec3 pos = ball->transform->GetTranslation();
if (pos.x < minX) {
ball->transform->Translate((1 + ball->bounciness) * Vec3(minX - pos.x, 0, 0));
ball->velocity = Vec3(- ball->velocity.x, 0, ball->velocity.z) * ball->bounciness;
}
if (pos.x > maxX) {
ball->transform->Translate((1 + ball->bounciness) * Vec3(maxX - pos.x, 0, 0));
ball->velocity = Vec3(- ball->velocity.x, 0, ball->velocity.z) * ball->bounciness;
}
if (pos.z < minZ) {
ball->transform->Translate((1 + ball->bounciness) * Vec3(0, 0, minZ - pos.z));
ball->velocity = Vec3(ball->velocity.x, 0, - ball->velocity.z) * ball->bounciness;
}
if (pos.z > maxZ) {
ball->transform->Translate((1 + ball->bounciness) * Vec3(0, 0, maxZ - pos.z));
ball->velocity = Vec3(ball->velocity.x, 0, - ball->velocity.z) * ball->bounciness;
}
for (int j = i + 1; j < balls.size(); ++j) {
auto ball2 = balls[j];
if (ball->collider->Collide(*ball->transform, ball2->collider, *ball2->transform)) {
// collision
Vec3 pos2 = ball2->transform->GetTranslation();
Vec3 center = (pos + pos2) * 0.5f; // collision point
Vec3 speed = ball->velocity - ball2->velocity; // approach speed of 2 balls
Vec3 v = pos - center; // vector towards center of collision
float dotProduct = speed.x * v.x + speed.z * v.z;
float proj = dotProduct / length(v); // projection of speed vector on collision line
Vec3 impulseChange = normalize(v) * proj * (1 + ball->bounciness * ball2->bounciness);
ball->velocity -= impulseChange * 0.5f;
ball2->velocity += impulseChange * 0.5f;
ball->transform->Translate(v * (ball->transform->GetScale().x / length(v) - 1));
ball2->transform->Translate(v * (1 - ball2->transform->GetScale().x / length(v)));
}
}
}
}
explicit GameManager(std::vector<MovingBall*> balls) {
this->balls = balls;
}
};

MovingBall *newBall(Vec3 position, Vec3 velocity,
ShaderProgram *sp, std::string diffuseSource, std::string specularSource);

void initLight(Engine& engine);

int main() {
auto engine = Engine(SCR_WIDTH, SCR_HEIGHT);
Object* testObj = initModel();
engine.AddObject<>(testObj);
engine.Run(SCR_WIDTH, SCR_HEIGHT);
}

Object* initModel() {
// build and compile our shader program ------------------------------------
Shader vShader = Shader(VertexShader, vertexShaderSource);
Shader fShader = Shader(FragmentShader, fragmentShaderSource);
ShaderProgram *shaderProgram = new ShaderProgram(vShader, fShader);

initLight(engine);

std::vector<MovingBall*> balls;
int ballsCount = 5;

for (int i = 0; i < ballsCount; ++i) {
MovingBall *sphere = newBall(Vec3(i * 2 - 5, -12, -i), Vec3(3, 0, 1 + i),
shaderProgram, "/wall.png", "/wallspecular.png");
balls.push_back(sphere);
engine.AddObject<>(sphere);
}

GameManager *gameManager = new GameManager(balls);

engine.AddObject(gameManager);

engine.Run(SCR_WIDTH, SCR_HEIGHT);
}

MovingBall *newBall(Vec3 position, Vec3 velocity,
ShaderProgram *sp, std::string diffuseSource, std::string specularSource) {
MovingBall* ball = new MovingBall(position, sp, diffuseSource, specularSource);
ball->velocity = velocity;
return ball;
}


// init a model
Model * model = Model::loadFromFile(catSource);
void initLight(Engine& engine) {
// init light objects
Object* pointLight1 = new Object();
pointLight1->light = new PointLight(
Vec3(0.2f, 0.2f, 0.2f), Vec3(0.5f, 0.5f, 0.5f),
Vec3(1.0f, 1.0f, 1.0f), Vec3(-0.2, -0.5, -1.2),
1, 0.09f, 0.032f);
auto pointLight = std::get<PointLight*>(pointLight1->light);
engine.AddObject<>(pointLight1);

auto obj = new Object();
obj->renderData = new RenderData();
obj->renderData->model = model;
obj->renderData->model->shader = new ShaderProgram(vShader, fShader);
Object* pointLight2 = new Object();
pointLight2->light = new PointLight(
Vec3(0.2f, 0.2f, 0.2f), Vec3(0.5f, 0.5f, 0.5f),
Vec3(1.0f, 1.0f, 1.0f), Vec3(2.3f, -3.3f, -4.0f),
1, 0.09f, 0.032f);
pointLight = std::get<PointLight*>(pointLight2->light);
engine.AddObject<>(pointLight2);

obj->transform = new Transform(glm::vec3(0.f, -3.f, -8.f), glm::vec3(.1f, .1f, .1f), glm::mat4(1.0));
obj->transform->Rotate(1.67f, glm::vec3(-1.f, 0.f, 0.f));
auto render_data = obj->renderData;
Object* pointLight3 = new Object();
pointLight3->light = new PointLight(
Vec3(0.2f, 0.2f, 0.2f), Vec3(0.5f, 0.5f, 0.5f),
Vec3(1.0f, 1.0f, 1.0f), Vec3(0.0f, 0.0f, -3.0f),
1, 0.09f, 0.032f);
pointLight = std::get<PointLight*>(pointLight3->light);
engine.AddObject<>(pointLight3);

bindRenderData(render_data);
Object* dirLight = new Object();
dirLight->light = new DirLight(
Vec3(0.05f, 0.05f, 0.05f), Vec3(0.4f, 0.4f, 0.4f),
Vec3(0.5f, 0.5f, 0.5f), Vec3(-0.2f, -1.0f, -0.3f));

// Maybe this can be less clunky?
// Perhaps variadic functions?
auto images = std::vector<std::string>();
images.push_back("/Cat_diffuse.png");
images.push_back("/Cat_specular.png");
obj->renderData->material = {
4.f,
Texture(images),
};
auto directionLight = std::get<DirLight*>(dirLight->light);
engine.AddObject<>(dirLight);

return obj;
Object* spotLight = new Object();
spotLight->light = new SpotLight(
Vec3(0.0f, 0.0f, 0.0f), Vec3(1.0f, 1.0f, 1.0f),
Vec3(1.0f, 1.0f, 1.0f), Vec3(1.0f, 1.0f, 1.0f),
1.0f, 0.09f, 0.032f, Vec3(0),
glm::cos(glm::radians(12.5f)),
glm::cos(glm::radians(15.0f)));
auto sptLight = std::get<SpotLight*>(spotLight->light);
engine.AddObject<>(spotLight);
}