13 Commits

Author SHA1 Message Date
Pc
fa824192b7 To co w nazwie brancha + konsola w vsc 2025-01-07 23:16:46 +01:00
Pc
79c6a1e144 Klasa do fps + Limit Fps 2025-01-07 23:01:34 +01:00
Pc
01d7766b6a Sterowanie 5.0 + Klasa do fps 2025-01-07 22:20:22 +01:00
Pc
3171ebe504 Sterowanie 5.0 ? 2025-01-07 21:32:32 +01:00
Pc
039435ed73 Sterowanie na ocene chyba 5.0 ? 2025-01-07 21:25:14 +01:00
Pc
2afc119bb9 Sterowanie na ocene chyba 4.0 2025-01-07 20:49:20 +01:00
Pc
4956d74c1a Sterowanie na 3.0 2025-01-06 21:12:35 +01:00
495ec2e6ab nowa mapka (mapk2.obj) 2024-12-09 12:25:08 +01:00
633be80ec4 lekko poprawiona mapka, dodane nowe klasy do projektu w visual studio, oddzielny kolor dla mapki i łazika 2024-12-08 16:00:25 +01:00
2b51e31307 próba modularyzacji kodu, dodane klasy lazik oraz plane
- Makefile uwzględnia glfw
- projekt w visual studio także powinien linkować glfw
- dodano plik .gitignore
- klasa lazik stworzona z myślą o łaziku
- bliźniaczo podobna klasa plane stworzona z myślą o mapie
- dodano surowy projekt mapy (res/models/mapka.obj)
- usunięto zbędną klasę sześcian oraz plik wykonywalny .exe
- funkcja timestampedCout() przeniesiona do plików timeh.cpp/.hpp, co pozwala na używanie jej wszędzie
- w main.cpp:
	- zakomentowano masę (niepotrzebnego)/przeniesionego kodu
	- tryb monitorowania wydajności wyłącza ValidateRect(), co wymusza ciągłe renderowanie nowych klatek. pozwala to oszacować wpływ zmian na wydajność programu.
2024-12-07 03:47:17 +01:00
ef1a8b225b poprawiony model łazika (lazik4.obj, stoi tyłem), prymitywany licznik fps 2024-11-29 01:50:22 +01:00
1f00df1842 Merge branch 'master' of ssh://gitea.7o7.cx:2223/sherl/grafikaKBT 2024-11-28 02:20:10 +01:00
2f8f14d279 poprawiona wydajność, zużycie RAMu 2024-11-28 02:19:26 +01:00
21 changed files with 2283594 additions and 519 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
# Czarna lista plików przy commitowaniu
# (pliki do zignorowania przy udostępnianiu)
# folder z rzeczami z visual studio
.vs
# pliki wykonywalne, binarne
grafikaKBT
x64
output.exe
output2.exe
# obiekty testowe
res/models/lazik.obj
res/models/lazik2.obj
res/models/lazik4,5.obj

24
FPSCounter.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include <iostream>
#include <chrono>
class FPSCounter {
public:
FPSCounter() : frameCount(0), lastTime(std::chrono::high_resolution_clock::now()) {}
void update() {
frameCount++;
auto currentTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = currentTime - lastTime;
if (elapsed.count() >= 1.0) {
double fps = frameCount / elapsed.count();
std::cout << "FPS: " << fps << std::endl;
frameCount = 0;
lastTime = currentTime;
}
}
private:
int frameCount;
std::chrono::time_point<std::chrono::high_resolution_clock> lastTime;
};

View File

@@ -1,12 +1,13 @@
# mingw-w64-x86_64-gcc-14.1.0-3 to ostatnia wspierana wersja gcc, w której można stosować wildcard'y "*.cpp"
CC = "C:\\msys64\\mingw64\\bin\\g++.exe"
CFLAGS = -I.
DEPS = -lglew32 -lopengl32 -lglu32 -lgdi32
DEPS = -lglew32 -lglfw3 -lopengl32 -lglu32 -lgdi32
LINK = -L. -DGLEW_STATIC
OUTPUT = output.exe
CPPSTD = c++17
default:
$(CC) -g *.cpp $(CFLAGS) $(DEPS) $(LINK) -static -static-libgcc -fno-keep-inline-dllexport -o $(OUTPUT)
$(CC) -g *.cpp $(CFLAGS) $(DEPS) $(LINK) -std=$(CPPSTD) -static -static-libgcc -fno-keep-inline-dllexport -o $(OUTPUT)
run: default
$(OUTPUT)

BIN
glfw3.dll Normal file

Binary file not shown.

View File

@@ -92,6 +92,7 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -116,18 +117,27 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="FPSCounter.cpp" />
<ClCompile Include="glew.c" />
<ClCompile Include="lazik.cpp" />
<ClCompile Include="loadOBJ.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="szescian.cpp" />
<ClCompile Include="plane.cpp" />
<ClCompile Include="timeh.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="lazik.hpp" />
<ClInclude Include="loadOBJ.h" />
<ClInclude Include="plane.hpp" />
<ClInclude Include="RESOURCE.H" />
<ClInclude Include="szescian.h" />
<ClInclude Include="timeh.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="glfw3.dll" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -21,7 +21,19 @@
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="szescian.cpp">
<ClCompile Include="glew.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lazik.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="timeh.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="plane.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FPSCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -32,8 +44,19 @@
<ClInclude Include="RESOURCE.H">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="szescian.h">
<ClInclude Include="plane.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lazik.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="timeh.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="glfw3.dll">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

81
lazik.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include "lazik.hpp"
lazik::lazik(float x, float y, float z, const char* modelpath){
this->c_x = x;
this->c_y = y;
this->c_z = z;
this->modelpath = modelpath;
timestampedCout("lazik.cpp: Zaladowano dane w konstruktorze.")
}
void lazik::loadModel() {
timestampedCout("lazik.cpp:");
std::cout << " Ladowanie modelu ze sciezki " << this->modelpath << "...\n";
bool res = loadOBJ(this->modelpath, this->vertices, this->uvs, this->normals);
if (res) timestampedCout("Pomyslnie zaladowano model lazika.")
else timestampedCout("Nie udalo sie zaladowac modelu lazika.");
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, this->uvbuffer);
glBufferData(GL_ARRAY_BUFFER, this->uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
}
void lazik::draw() {
// 1st attribute buffer: vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer: UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, this->uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw vertices
glDrawArrays(GL_TRIANGLES, 0, this->vertices.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
void lazik::moveX(float x){
// TODO: dodać timer do poniższych funkcji, aby czas przejścia z punktu A do B był uniezależniony od FPSów
timestampedCout("dummy moveX");
}
void lazik::moveY(float y){
timestampedCout("dummy moveY");
}
void lazik::moveZ(float z){
timestampedCout("dummy moveZ");
}
void lazik::moveXYZ(float x, float y, float z){
// TODO: modyfikować wektor z koordynatami oraz c_x, c_y, c_z
timestampedCout("dummy moveXYZ");
}

34
lazik.hpp Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <windows.h>
#include "GL/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include <vector>
#include <iostream>
#include "timeh.hpp"
#include "GL/glm/glm.hpp"
#include "loadOBJ.h"
class lazik {
private:
float c_x{0};
float c_y{0};
float c_z{0};
float rot_x{0};
float rot_y{0};
float rot_z{0};
std::vector <glm::vec3> vertices;
std::vector <glm::vec2> uvs;
std::vector <glm::vec3> normals; // Won't be used at the moment.
GLuint vertexbuffer;
GLuint uvbuffer;
const char* modelpath;
public:
lazik(float x, float y, float z, const char* modelpath);
void loadModel();
void draw();
void moveX(float x);
void moveY(float y);
void moveZ(float z);
void moveXYZ(float x, float y, float z);
};

View File

@@ -15,11 +15,15 @@ bool loadOBJ(const char* path, std::vector <glm::vec3>& out_vertices, std::vecto
return false;
}
int line = 0;
unsigned int line = 0;
unsigned int vs = 0;
unsigned int vts = 0;
unsigned int vns = 0;
unsigned int fs = 0;
char lineHeader[128];
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF) break; // EOF = End Of File. Quit the loop.
@@ -30,23 +34,27 @@ bool loadOBJ(const char* path, std::vector <glm::vec3>& out_vertices, std::vecto
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
vs++;
} else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
temp_uvs.push_back(uv);
vts++;
} else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
vns++;
} else if (strcmp(lineHeader, "f") == 0) {
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
fs++;
if (matches != 9){
printf("File can't be read by our simple parser. Try exporting with other options (%d matches on line %d)\n", matches, line);
@@ -64,6 +72,9 @@ bool loadOBJ(const char* path, std::vector <glm::vec3>& out_vertices, std::vecto
normalIndices.push_back(normalIndex[2]);
}
line++;
}
// For each vertex of each triangle
for (unsigned int i = 0; i < vertexIndices.size(); i++) {
unsigned int vertexIndex = vertexIndices[i];
@@ -74,14 +85,14 @@ bool loadOBJ(const char* path, std::vector <glm::vec3>& out_vertices, std::vecto
glm::vec2 vertex2 = temp_uvs[uvIndex - 1];
glm::vec3 vertex3 = temp_normals[normalIndex - 1];
out_vertices .push_back(vertex1);
out_uvs .push_back(vertex2);
out_normals .push_back(vertex3);
out_vertices.push_back(vertex1);
out_uvs.push_back(vertex2);
out_normals.push_back(vertex3);
}
line++;
fclose(file);
}
printf("(loadOBJ.cpp) Loaded file with %d v, %d vt, %d vn, %d f. %d lines total.\n", vs, vts, vns, fs, line);
return true;
}

497
main.cpp
View File

@@ -23,20 +23,24 @@
//#include <stdio.h>
#include <iostream>
#include "RESOURCE.H" // About box resource identifiers.
#include "szescian.h"
#include "loadOBJ.h"
#include "lazik.hpp"
#include "plane.hpp"
//#include <vector>
#include "GL/glm/glm.hpp"
//#include "GL/glfw3.h"
#include "GL/glfw3.h"
#include <ctime>
#include "timeh.hpp"
#include "FPSCounter.cpp"
#include <thread>
using namespace glm;
#define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z)
#define BITMAP_ID 0x4D42 // identyfikator formatu BMP
#define GL_PI 3.1415
#define getTime lastTime = std::time(nullptr);
#define timestampedCout(msg) {getTime; std::cout << "( " << lastTime << ") " << msg << "\n";}
//#define getTime lastTime = std::time(nullptr);
//#define timestampedCout(msg) {getTime; std::cout << "( " << lastTime << ") " << msg << "\n";}
//using namespace std;
@@ -45,6 +49,7 @@ HPALETTE hPalette = NULL;
// Application name and instance storeage
static LPCTSTR lpszAppName = "grafikaKBT";
static HINSTANCE hInstance;
GLFWwindow* window;
// Rotation amounts
static GLfloat xRot = 0.0f;
@@ -67,19 +72,149 @@ BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam);
void SetDCPixelFormat(HDC hDC);
int polygonmode = 0;
char loadCount = 0;
std::time_t lastTime = std::time(nullptr);
int monitormode = 1;
int monitormodecounter = 0;
std::time_t monitormodehelper;
//Zmienne do ruchu ##############################################^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FPSCounter fpsCounter;
static const int targetFPS = 144; // Celowany FPS
//Fps counter
void LimitFPS(int targetFPS) {
static auto lastTime = std::chrono::high_resolution_clock::now();
auto currentTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = currentTime - lastTime;
// Jeśli upłynęło za mało czasu, aby osiągnąć target FPS, czekamy
double frameTime = 1.0 / targetFPS; // Czas na jedną klatkę w sekundach
if (elapsed.count() < frameTime) {
std::this_thread::sleep_for(std::chrono::duration<double>(frameTime - elapsed.count()));
}
lastTime = std::chrono::high_resolution_clock::now();
}
bool keyWPressed = false;
bool keySPressed = false;
bool keyAPressed = false;
bool keyDPressed = false;
float Foward = 0.0f; // Pozycja łazika w przód/tył
float Sides = 0.0f; // Pozycja łazika w lewo/prawo
float Rotation = 0.0f; // Rotacja łazika (w stopniach)
float CameraHeight = 50.0f; // Wysokość kamery
float MoveSpeed = 1.0f; // Prędkość poruszania się
float velocity = 0.0f; // Aktualna prędkość łazika
const float friction = 0.05f; // Współczynnik tarcia (μ)
const float maxSpeed = 3.0f; // Maksymalna prędkość łazika
const float acceleration = 0.2f;
float rotationVelocity = 0.0f; // Prędkość obrotu łazika
const float rotationAcceleration = 0.1f; // Przyspieszenie obrotu
const float rotationFriction = 0.05f; // Współczynnik tarcia obrotu
const float maxRotationSpeed = 3.0f; // Maksymalna prędkość obrotu
// Funkcja do poruszania łazikiem
void MoveRover(bool forward) {
// Zamieniamy kąt na radiany
float radRotation = Rotation * GL_PI / 180.0f;
// Wektor ruchu w kierunku przód/tył (kierunek łazika)
float moveX = cos(radRotation);
float moveZ = sin(radRotation);
// Ruch w przód
if (forward) {
Sides -= MoveSpeed * moveX;
Foward -= MoveSpeed * moveZ;
}
// Ruch w tył
else {
Sides += MoveSpeed * moveX;
Foward += MoveSpeed * moveZ;
}
}
// Funkcja do obracania łazika wokół osi Y
void RotateRoverAndCamera(float angle) {
Rotation += angle;
if (Rotation >= 360.0f) Rotation -= 360.0f;
if (Rotation < 0.0f) Rotation += 360.0f;
}
void UpdateRover() {
// Przyspieszanie w przód
if (keyWPressed) {
velocity += acceleration;
if (velocity > maxSpeed) velocity = maxSpeed;
}
// Przyspieszanie w tył
else if (keySPressed) {
velocity -= acceleration;
if (velocity < -maxSpeed) velocity = -maxSpeed;
}
// Hamowanie (wytracanie prędkości z powodu tarcia)
else {
if (velocity > 0) {
velocity -= friction;
if (velocity < 0) velocity = 0;
}
else if (velocity < 0) {
velocity += friction;
if (velocity > 0) velocity = 0;
}
}
// Obracanie
if (keyAPressed) {
rotationVelocity += rotationAcceleration;
if (rotationVelocity > maxRotationSpeed) rotationVelocity = maxRotationSpeed;
}
else if (keyDPressed) {
rotationVelocity -= rotationAcceleration;
if (rotationVelocity < -maxRotationSpeed) rotationVelocity = -maxRotationSpeed;
}
else {
// Hamowanie obrotu (wytracanie prędkości z powodu tarcia)
if (rotationVelocity > 0) {
rotationVelocity -= rotationFriction;
if (rotationVelocity < 0) rotationVelocity = 0;
}
else if (rotationVelocity < 0) {
rotationVelocity += rotationFriction;
if (rotationVelocity > 0) rotationVelocity = 0;
}
}
// Aktualizacja pozycji na podstawie prędkości
float radRotation = Rotation * GL_PI / 180.0f;
Sides -= velocity * cos(radRotation);
Foward -= velocity * sin(radRotation);
// Aktualizacja kąta obrotu
Rotation += rotationVelocity;
if (Rotation >= 360.0f) Rotation -= 360.0f;
if (Rotation < 0.0f) Rotation += 360.0f;
}
// Change viewing volume and viewport. Called when window is resized
void ChangeSize(GLsizei w, GLsizei h) {
GLfloat nRange = 100.0f;
GLfloat fAspect;
//GLfloat fAspect;
// Prevent a divide by zero
if (h == 0) h = 1;
lastWidth = w;
lastHeight = h;
fAspect = (GLfloat)w / (GLfloat)h;
//fAspect = (GLfloat)w / (GLfloat)h;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
@@ -87,9 +222,13 @@ void ChangeSize(GLsizei w, GLsizei h) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// // Establish clipping volume (left, right, bottom, top, near, far)
// if (w <= h) glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -nRange, nRange);
// else glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -nRange, nRange);
// Establish clipping volume (left, right, bottom, top, near, far)
if (w <= h) glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -nRange, nRange);
else glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -nRange, nRange);
if (w <= h) glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -20 * nRange, 20 * nRange);
else glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -20 * nRange, 20 * nRange);
// Establish perspective:
/*
@@ -100,47 +239,6 @@ void ChangeSize(GLsizei w, GLsizei h) {
glLoadIdentity();
}
void SetupRC() {
// Light values and coordinates
//GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
//GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
//GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
//GLfloat lightPos[] = { 0.0f, 150.0f, 150.0f, 1.0f };
//GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
//glEnable(GL_CULL_FACE); // Do not calculate inside of jet
// Enable lighting
//glEnable(GL_LIGHTING);
// Setup and enable light 0
//glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
//glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
//glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
//glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//glEnable(GL_LIGHT0);
// Enable color tracking
//glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
//glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
//glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
//glMateriali(GL_FRONT, GL_SHININESS, 128);
// White background
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Black brush
glColor3f(0.0, 0.0, 0.0);
}
// LoadBitmapFile
// opis: ładuje mapę bitową z pliku i zwraca jej adres.
// Wypełnia strukturę nagłówka.
@@ -232,108 +330,110 @@ void SetDCPixelFormat(HDC hDC) {
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
std::vector <glm::vec3> vertices;
std::vector <glm::vec2> uvs;
std::vector <glm::vec3> normals; // Won't be used at the moment.
GLuint vertexbuffer;
GLuint uvbuffer;
std::time_t lastTime = std::time(nullptr);
lazik user(10.0f, 0.0f, 0.0f, "res/models/lazik4.obj");
plane mapa(0.0f, 0.0f, 0.0f, "res/models/mapka2.obj");
void setup(){
// załaduj model
void SetupRC() {
// Light values and coordinates
//GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
//GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
//GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
//GLfloat lightPos[] = { 0.0f, 150.0f, 150.0f, 1.0f };
//GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// if(!glfwInit()) {
// fprintf(stderr, "Failed to initialize GLFW\n");
// getchar();
// return;
// }
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate inside of jet // !!! znacząco poprawia wydajność
// Enable lighting
//glEnable(GL_LIGHTING);
// Setup and enable light 0
//glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
//glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
//glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
//glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//glEnable(GL_LIGHT0);
// Enable color tracking
//glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
//glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
//glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
//glMateriali(GL_FRONT, GL_SHININESS, 128);
// White background
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Black brush
glColor3f(0.0, 0.0, 0.0);
// Initialize GLEW
timestampedCout("Inicjalizowanie GLEW...");
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
// glfwTerminate();
timestampedCout("Failed to initialize GLEW");
return;
}
timestampedCout("Zainicjalizowano GLEW.");
/* */
// Read our .obj file
// TODO: zmierzyć czas ładowania łazika w cyklach procesora/mikrosekundach
timestampedCout("Ladowanie lazika...");
bool res = loadOBJ("res/models/lazik3.obj", vertices, uvs, normals);
// bool res = loadOBJ("res/models/suzanne.obj", vertices, uvs, normals);
if (res) {
timestampedCout("Pomyslnie zaladowano model lazika.");
// glfw3 jest w teorii niepotrzebny, ale może się przydać
// do przepisania kodu na podobny do tego stąd:
// https://github.com/opengl-tutorials/ogl/blob/master/tutorial07_model_loading/tutorial07.cpp
timestampedCout("Inicjalizowanie GLFW3...");
if (!glfwInit()) {
timestampedCout("Failed to initialize GLFW");
}
else timestampedCout("Nie udalo sie zaladowac modelu lazika.");
timestampedCout("Zainicjalizowano GLFW3.");
/* */
// Załaduj model z pliku .obj
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
timestampedCout("Ladowanie modelu lazika...");
user.loadModel();
timestampedCout("Ladowanie modelu mapki...");
mapa.loadModel();
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
loadCount++;
glfwSwapInterval(1);
//glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
}
void RenderScene(void) {
if (loadCount == 0) setup();
//float normal[3]; // Storage for calculated surface normal
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
// gluLookAt(
// 0, 0, 0, // the position of your camera, in world space
// 0, 0, 0, // where you want to look at, in world space
// 0, 1, 0 // probably glm::vec3(0,1,0), but (0,-1,0) would make you looking upside-down, which can be great too
// );
/////////////////////////////////////////////////////////////////
// MIEJSCE NA KOD OPENGL DO TWORZENIA WLASNYCH SCEN: //
/////////////////////////////////////////////////////////////////
//szescian();
//Sposób na odróżnienie "przedniej" i "tylniej" ściany wielokąta:
//glPolygonMode(GL_BACK,GL_LINE);
//walec(40, 40);
//szescian();
switch (polygonmode) {
case 0:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case 1:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
default:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -345,71 +445,51 @@ void RenderScene(void) {
// glBindTexture(GL_TEXTURE_2D, Texture);
// // Set our "myTextureSampler" sampler to use Texture Unit 0
// glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
//glLoadIdentity(); // Zresetowanie macierzy widoku
//
//############################################################################################
//Sterowanie
//############################################################################################
gluLookAt(
Foward - 100.0f * sin((Rotation + 180.0f) * GL_PI / 180.0f), // Pozycja kamery wokół łazika (w poziomie)
CameraHeight, // Wysokość kamery
Sides - 100.0f * cos((Rotation + 180.0f) * GL_PI / 180.0f), // Kamera wzdłuż osi X i Z
Foward, 0.0f, Sides, // Punkt, na który patrzy kamera (łazik)
0.0f, 1.0f, 0.0f // Wektor "góry"
);
// 2nd attribute buffer: UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Rysowanie mapy (nie porusza się)
glPushMatrix();
glColor3f(0.0, 1.0, 0.0); // Zielony kolor dla mapy
mapa.draw();
glPopMatrix();
// Draw the triangle!
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
// Rysowanie łazika (porusza się i obraca)
glPushMatrix();
glTranslatef(Foward, 0.0f, Sides); // Translacja łazika na jego pozycję
glRotatef(Rotation, 0.0f, 1.0f, 0.0f); // Obrót łazika wokół własnej osi
glColor3f(1.0, 0.0, 0.0); // Czerwony kolor dla łazika
user.draw();
UpdateRover();
glPopMatrix();
fpsCounter.update();
// Zamiana buforów (double buffering)
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
//glfwSwapBuffers(window);
//glfwPollEvents();
/*
szescian nowy;
nowy.create(0, 0, 0, 10);
nowy.create(-10, 20, 0, 10);
nowy.create(25, 10, 0, 10);
*/
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
/*
szescian nowy2;
nowy2.create(0, 10, 0, 10);
szescian nowy3;
nowy3.create(0, 20, -10, 10);
*/
//Uzyskanie siatki:
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Wyrysowanie prostokata:
//glRectd(-10.0,-10.0,20.0,20.0);
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix(); // wymagane
glMatrixMode(GL_MODELVIEW); // zmniejsza zużycie GPU
// Flush drawing commands
glFlush();
// glFlush();
}
// If necessary, creates a 3-3-2 palette for the device context listed.
@@ -483,13 +563,31 @@ HPALETTE GetOpenGLPalette(HDC hDC) {
// Return the handle to the new palette
return hRetPal;
}
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
void CreateConsole()
{
// Tworzenie nowej konsoli
if (AllocConsole())
{
// Przekierowanie standardowych strumieni do konsoli
FILE* conin;
FILE* conout;
FILE* conerr;
freopen_s(&conin, "conin$", "r", stdin);
freopen_s(&conout, "conout$", "w", stdout);
freopen_s(&conerr, "conout$", "w", stderr);
}
else
{
MessageBox(NULL, "Nie udało się utworzyć konsoli.", "Błąd", MB_OK | MB_ICONERROR);
}
}
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
CreateConsole();
MSG msg; // Windows message structure
WNDCLASS wc; // Windows class structure
HWND hWnd; // Storeage for window handle
hInstance = hInst;
// Register Window style
@@ -521,7 +619,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
// Window position and size
50, 50,
400, 400,
800, 800,
NULL,
NULL,
hInstance,
@@ -531,7 +629,11 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
if (hWnd == NULL) return FALSE;
const WORD ID_TIMER = 1;
SetTimer(hWnd, ID_TIMER, 100, NULL);
// Display the window
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
@@ -542,7 +644,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
}
return msg.wParam;
}
}
// Window procedure, handles all messages for this program
@@ -550,6 +652,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
static HGLRC hRC; // Permenant Rendering context
static HDC hDC; // Private GDI Device context
float radRotation = Rotation * GL_PI / 180.0f;
switch (message) {
// Window creation, setup for OpenGL
case WM_CREATE:
@@ -566,6 +669,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
SetupRC();
/*
glGenTextures(2, &texture[0]); // tworzy obiekt tekstury
// ładuje pierwszy obraz tekstury:
@@ -603,6 +708,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
// ustalenie sposobu mieszania tekstury z tłem
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
*/
break;
// Window is being destroyed, cleanup
@@ -626,7 +733,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
ChangeSize(LOWORD(lParam), HIWORD(lParam));
break;
// The painting function. This message sent by Windows
// whenever the screen needs updating.
case WM_PAINT:
@@ -636,12 +742,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
SwapBuffers(hDC);
// Validate the newly painted client area
if (!monitormode) {
ValidateRect(hWnd, NULL);
break;
}
else {
InvalidateRect(hWnd, NULL, FALSE);
}
// Windows is telling the application that it may modify
// the system palette. This message in essance asks the
// application for a new palette.
// Limit FPS
LimitFPS(targetFPS);
// Update FPS counter
fpsCounter.update();
break;
case WM_QUERYNEWPALETTE:
// If the palette was created.
if (hPalette) {
@@ -679,11 +792,31 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
break;
case WM_KEYUP:
switch (wParam) {
case 'W':
keyWPressed = false;
break;
case 'S':
keySPressed = false;
break;
case 'A':
keyAPressed = false;
break;
case 'D':
keyDPressed = false;
break;
// Obsługa innych klawiszy
}
break;
// Key press, check for arrow keys to do cube rotation.
case WM_KEYDOWN:
switch (wParam) {
case VK_UP:
xRot -= 5.0f;
break;
@@ -716,12 +849,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case ' ': // 32
polygonmode = !polygonmode;
getTime;
if (polygonmode) timestampedCout("Uwaga! Tryb wireframe jest niewydajny i powinien sluzyc tylko do debugowania!");
break;
case 'W':
keyWPressed = true;
break;
case 'S':
keySPressed = true;
break;
case 'A':
keyAPressed = true;
break;
case 'D':
keyDPressed = true;
break;
default:
getTime;
timestampedCout("Nacisnieto nierozpoznany klawisz: " << (int)wParam);
}
@@ -749,7 +895,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
case WM_TIMER:
{
RenderScene();
SwapBuffers(hDC);
ValidateRect(hWnd, NULL);
break;
}
default: // Passes it on if unproccessed
return (DefWindowProc(hWnd, message, wParam, lParam));
}
@@ -757,9 +909,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return (0L);
}
// Dialog procedure.
BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) {

Binary file not shown.

75
plane.cpp Normal file
View File

@@ -0,0 +1,75 @@
#include "plane.hpp"
plane::plane(float x, float y, float z, const char* modelpath){
this->c_x = x;
this->c_y = y;
this->c_z = z;
this->modelpath = modelpath;
timestampedCout("plane.cpp: Zaladowano dane w konstruktorze.")
}
void plane::loadModel() {
timestampedCout("plane.cpp:");
std::cout << " Ladowanie modelu ze sciezki " << this->modelpath << "...\n";
bool res = loadOBJ(this->modelpath, this->vertices, this->uvs, this->normals);
if (res) timestampedCout("Pomyslnie zaladowano model mapki.")
else timestampedCout("Nie udalo sie zaladowac modelu mapki.");
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, this->uvbuffer);
glBufferData(GL_ARRAY_BUFFER, this->uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
}
void plane::draw() {
// 1st attribute buffer: vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer: UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, this->uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw vertices
glDrawArrays(GL_TRIANGLES, 0, this->vertices.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
void plane::moveX(float x){
timestampedCout("dummy moveX");
}
void plane::moveY(float y){
timestampedCout("dummy moveY");
}
void plane::moveZ(float z){
timestampedCout("dummy moveZ");
}

33
plane.hpp Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <windows.h>
#include "GL/glew.h"
#include <gl/gl.h>
#include <gl/glu.h>
#include <vector>
#include <iostream>
#include "timeh.hpp"
#include "GL/glm/glm.hpp"
#include "loadOBJ.h"
class plane {
private:
float c_x{0};
float c_y{0};
float c_z{0};
float rot_x{0};
float rot_y{0};
float rot_z{0};
std::vector <glm::vec3> vertices;
std::vector <glm::vec2> uvs;
std::vector <glm::vec3> normals; // Won't be used at the moment.
GLuint vertexbuffer;
GLuint uvbuffer;
const char* modelpath;
public:
plane(float x, float y, float z, const char* modelpath);
void loadModel();
void draw();
void moveX(float x);
void moveY(float y);
void moveZ(float z);
};

7421
res/models/lazik4.obj Normal file

File diff suppressed because it is too large Load Diff

89
res/models/mapka.obj Normal file
View File

@@ -0,0 +1,89 @@
# Blender 4.2.1 LTS
# www.blender.org
o Plane
v -25.000000 -0.200000 25.000000
v 275.000000 -0.200000 25.000000
v -25.000000 -0.200000 -275.000000
v 275.000000 -0.200000 -275.000000
vn -0.0000 1.0000 -0.0000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
s 0
f 2/1/1 3/2/1 1/3/1
f 2/1/1 4/4/1 3/2/1
o Cube
v -15.000000 0.000000 15.000000
v -15.000000 40.000000 15.000000
v -15.000000 0.000000 -35.000004
v -15.000000 40.000000 -35.000004
v 15.000000 0.000000 15.000000
v 15.000000 40.000000 15.000000
v 15.000000 0.000000 -35.000004
v 15.000000 40.000000 -35.000004
v 0.000000 52.654823 15.000000
v 0.000000 52.654823 -35.000004
v -15.000000 20.000000 -35.000004
v 0.000000 40.000000 -35.000004
v 15.000000 20.000000 -35.000004
v 0.000000 20.000000 -35.000004
v -15.000000 10.000000 -35.000004
v -7.500000 20.000000 -35.000004
v 15.000000 10.000000 -35.000004
v 7.500000 20.000000 -35.000004
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.6448 0.7643 -0.0000
vn 0.6448 0.7643 -0.0000
vt 0.625000 0.000000
vt 0.500000 0.250000
vt 0.437500 0.250000
vt 0.625000 0.375000
vt 0.500000 0.500000
vt 0.500000 0.437500
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.375000 1.000000
vt 0.750000 0.750000
vt 0.000000 0.000000
vt 0.437500 0.500000
vt 0.625000 0.250000
vt 0.500000 0.375000
vt 0.500000 0.312500
vt 0.375000 0.250000
vt 0.750000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.000000
vt 0.375000 0.500000
vt 0.625000 1.000000
s 0
f 6/5/2 15/6/2 19/7/2
f 16/8/3 17/9/3 22/10/3
f 17/9/4 10/11/4 9/12/4
f 10/11/5 5/13/5 9/12/5
f 13/14/6 8/15/6 6/15/6
f 21/16/3 22/10/3 17/9/3
f 8/17/3 18/18/3 20/19/3
f 19/7/3 20/19/3 7/20/3
f 16/8/3 14/21/3 12/22/3
f 12/22/7 13/14/7 10/11/7
f 6/15/5 10/11/5 13/14/5
f 7/20/2 5/23/2 6/5/2
f 6/5/2 8/17/2 15/6/2
f 19/7/2 7/20/2 6/5/2
f 22/10/3 18/18/3 16/8/3
f 16/8/3 12/22/3 17/9/3
f 9/12/4 11/24/4 21/16/4
f 17/9/4 12/22/4 10/11/4
f 9/12/4 21/16/4 17/9/4
f 10/11/5 6/25/5 5/13/5
f 13/14/6 14/21/6 8/15/6
f 21/16/3 11/24/3 22/10/3
f 20/19/3 15/6/3 8/17/3
f 8/17/3 16/8/3 18/18/3
f 19/7/3 15/6/3 20/19/3
f 16/8/3 8/15/3 14/21/3
f 12/22/7 14/21/7 13/14/7

1101
res/models/mapka2.obj Normal file

File diff suppressed because it is too large Load Diff

2274083
res/models/mapka3.obj Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +0,0 @@
#include "szescian.h"
void szescian::create(float x, float y, float z, float KRAWEDZ) {
this->c_x = x;
this->c_y = y;
this->c_z = z;
// Parametry wierzcholkow
GLfloat sa[3] = { x + 0.0f, y + 0.0f, z + 0.0f };
GLfloat sb[3] = { x + KRAWEDZ, y + 0.0f, z + 0.0f };
GLfloat sc[3] = { x + KRAWEDZ, y + KRAWEDZ, z + 0.0f };
GLfloat sd[3] = { x + 0.0f, y + KRAWEDZ, z + 0.0f };
GLfloat se[3] = { x + 0.0f, y + 0.0f, z - KRAWEDZ };
GLfloat sf[3] = { x + KRAWEDZ, y + 0.0f, z - KRAWEDZ };
GLfloat sg[3] = { x + KRAWEDZ, y + KRAWEDZ, z - KRAWEDZ };
GLfloat sh[3] = { x + 0.0f, y + KRAWEDZ, z - KRAWEDZ };
// Sciany skladowe
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3fv(sa);
glVertex3fv(sb);
glVertex3fv(sc);
glVertex3fv(sd);
glEnd();
glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3fv(sb);
glVertex3fv(sf);
glVertex3fv(sg);
glVertex3fv(sc);
glEnd();
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_POLYGON);
glVertex3fv(sf);
glVertex3fv(se);
glVertex3fv(sh);
glVertex3fv(sg);
glEnd();
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3fv(se);
glVertex3fv(sa);
glVertex3fv(sd);
glVertex3fv(sh);
glEnd();
glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_POLYGON);
glVertex3fv(sd);
glVertex3fv(sc);
glVertex3fv(sg);
glVertex3fv(sh);
glEnd();
glColor3f(1.0f, 0.0f, 1.0f);
glBegin(GL_POLYGON);
glVertex3fv(sa);
glVertex3fv(sb);
glVertex3fv(sf);
glVertex3fv(se);
glEnd();
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
class szescian
{
private:
float c_x{0};
float c_y{0};
float c_z{0};
public:
void create(float x, float y, float z, float KRAWEDZ);
};

5
timeh.cpp Normal file
View File

@@ -0,0 +1,5 @@
#include "timeh.hpp"
std::time_t getTime() {
return std::time(nullptr);
}

5
timeh.hpp Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#include <ctime>
#include <iostream>
std::time_t getTime();
#define timestampedCout(msg) {std::time_t currentTime = getTime(); std::cout << "( " << currentTime << ") " << msg << "\n";}