├── .gitignore ├── src ├── omicon.rc ├── openmrac.ico ├── osx │ └── openmrac.icns ├── shaders │ ├── color.fs.h │ ├── tex.fs.h │ ├── tex.vs.h │ ├── color.vs.h │ ├── glass_tint.vs.h │ ├── color_tex.vs.h │ ├── color_tex.fs.h │ ├── glass_tint.fs.h │ ├── light_tex.vs.h │ ├── glass_reflection.fs.h │ ├── car.vs.h │ ├── car_top.vs.h │ ├── glass_reflection.vs.h │ ├── car.fs.h │ ├── light_tex.fs.h │ ├── light_tex_sunk.vs.h │ ├── car_top.fs.h │ └── light_tex_sunk.fs.h ├── gameaux.h ├── control ├── appdefs.h ├── fopendir.h ├── openmrac.desktop ├── openmrac-es2.desktop ├── load_texture.h ├── rand1.h ├── bits.h ├── triboxint.h ├── cstring1.h ├── fopendir.cpp ├── datkey.h ├── ghost.h ├── pict2.cpp ├── gameaux.cpp ├── onelayout.h ├── error_msg.h ├── glm1.h ├── skysph.h ├── cam.h ├── mingw32 │ ├── mingw32-toolchain.cmake │ └── prereq.sh ├── Makefile.linux-es2 ├── rand1.cpp ├── Makefile.linux ├── 3dm.h ├── onelayout.cpp ├── gbuff_in.h ├── settings_dat.h ├── pict2_png.cpp ├── dpiaware_win32.cpp ├── particles.cpp ├── collider.h ├── pict2.h ├── shadermng.h ├── particles.h ├── Makefile.mingw ├── car2d.h ├── controls.h ├── minial.h ├── cam.cpp ├── datkey.cpp ├── gltext.h ├── gl_shared.h ├── octopus.h ├── cstring1.cpp ├── OpenMRac-SDL2.pro ├── ghost.cpp ├── settingsdialog.h ├── matmng.h ├── triboxint.cpp ├── gl1.h ├── soundmng.h ├── skysph.cpp ├── controls.cpp ├── gbuff_in.cpp ├── mainmenu.h ├── load_texture.cpp ├── gui.h ├── pict2_jpeg.cpp ├── soundmng.cpp ├── rbsolver.h ├── car2d.cpp ├── rbsolver.cpp ├── gamemenu.cpp ├── gltext.cpp └── gamemng.h ├── media └── openmrac-yt.jpg ├── tests-gl ├── test0-gl.png ├── test1-gl.png ├── test2-gl.png ├── test3-gl.png ├── test0-gles2.png ├── test1-gles2.png ├── test2-gles2.png ├── test3-gles2.png └── test4-gles2.png ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /src/omicon.rc: -------------------------------------------------------------------------------- 1 | 100 ICON "openmrac.ico" 2 | 3 | -------------------------------------------------------------------------------- /src/openmrac.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/src/openmrac.ico -------------------------------------------------------------------------------- /media/openmrac-yt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/media/openmrac-yt.jpg -------------------------------------------------------------------------------- /src/osx/openmrac.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/src/osx/openmrac.icns -------------------------------------------------------------------------------- /tests-gl/test0-gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test0-gl.png -------------------------------------------------------------------------------- /tests-gl/test1-gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test1-gl.png -------------------------------------------------------------------------------- /tests-gl/test2-gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test2-gl.png -------------------------------------------------------------------------------- /tests-gl/test3-gl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test3-gl.png -------------------------------------------------------------------------------- /tests-gl/test0-gles2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test0-gles2.png -------------------------------------------------------------------------------- /tests-gl/test1-gles2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test1-gles2.png -------------------------------------------------------------------------------- /tests-gl/test2-gles2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test2-gles2.png -------------------------------------------------------------------------------- /tests-gl/test3-gles2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test3-gles2.png -------------------------------------------------------------------------------- /tests-gl/test4-gles2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Franticware/OpenMRac/HEAD/tests-gl/test4-gles2.png -------------------------------------------------------------------------------- /src/shaders/color.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | varying vec4 vColor; 3 | 4 | void main() 5 | { 6 | gl_FragColor = vColor; 7 | } 8 | )GLSL"; 9 | -------------------------------------------------------------------------------- /src/gameaux.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_GAMEAUX_H 2 | #define HLIDAC_GAMEAUX_H 3 | 4 | void getdeltaT_init(); 5 | float getdeltaT(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/control: -------------------------------------------------------------------------------- 1 | Package: openmrac 2 | Version: 1.2 3 | Maintainer: Franticware 4 | Architecture: all 5 | Description: OpenMRac 6 | 3D racing game 7 | -------------------------------------------------------------------------------- /src/appdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef APPDEFS_H 2 | #define APPDEFS_H 3 | 4 | #define OPENMRAC_VERSION "" 5 | #define OPENMRAC_ORG "Franticware" 6 | #define OPENMRAC_APP "openmrac" 7 | 8 | #endif // APPDEFS_H 9 | -------------------------------------------------------------------------------- /src/shaders/tex.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform sampler2D uTex0; 3 | 4 | varying vec2 vTex; 5 | 6 | void main() 7 | { 8 | gl_FragColor = texture2D(uTex0, vTex); 9 | } 10 | )GLSL"; 11 | -------------------------------------------------------------------------------- /src/fopendir.h: -------------------------------------------------------------------------------- 1 | #ifndef FOPENDIR_H 2 | #define FOPENDIR_H 3 | 4 | #include 5 | 6 | FILE* fopenDir(const char* filename, const char* mode, const char* org, const char* app); 7 | 8 | #endif // FOPENDIR_H 9 | -------------------------------------------------------------------------------- /src/openmrac.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Categories=Application;Game; 3 | Exec=openmrac 4 | Icon=/usr/share/pixmaps/openmrac.ico 5 | Keywords=3D;multiplayer;car;racing;split-screen; 6 | Name=OpenMRac 7 | Terminal=false 8 | Type=Application 9 | -------------------------------------------------------------------------------- /src/openmrac-es2.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Categories=Application;Game; 3 | Exec=openmrac-es2 4 | Icon=/usr/share/pixmaps/openmrac-es2.ico 5 | Keywords=3D;multiplayer;car;racing;split-screen; 6 | Name=OpenMRac (ES2) 7 | Terminal=false 8 | Type=Application 9 | -------------------------------------------------------------------------------- /src/shaders/tex.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uProjModelViewMat; 3 | 4 | attribute vec3 aPos; 5 | attribute vec2 aTex; 6 | 7 | varying vec2 vTex; 8 | 9 | void main() 10 | { 11 | vTex = aTex; 12 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 13 | } 14 | )GLSL"; 15 | -------------------------------------------------------------------------------- /src/shaders/color.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uProjModelViewMat; 3 | 4 | attribute vec3 aPos; 5 | attribute vec4 aColor; 6 | 7 | varying vec4 vColor; 8 | 9 | void main() 10 | { 11 | vColor = aColor; 12 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 13 | } 14 | )GLSL"; 15 | -------------------------------------------------------------------------------- /src/shaders/glass_tint.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uProjModelViewMat; 3 | uniform mat3 uNormMat; 4 | 5 | attribute vec3 aPos; 6 | attribute vec2 aTex; 7 | 8 | varying vec2 vTex; 9 | 10 | void main() 11 | { 12 | vTex = aTex; 13 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 14 | } 15 | )GLSL"; 16 | -------------------------------------------------------------------------------- /src/load_texture.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_LOAD_TEXTURE_H 2 | #define HLIDAC_LOAD_TEXTURE_H 3 | 4 | #include "gl1.h" 5 | #include "pict2.h" 6 | 7 | GLuint load_texture(const Pict2& pict, bool bmipmap = false); 8 | GLuint load_texture_cube_map(const Pict2& pict); 9 | 10 | extern unsigned int g_texture_memory_usage; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/rand1.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_RAND1_H 2 | #define HLIDAC_RAND1_H 3 | 4 | void srand0(); // seed = 0 5 | void srand1(); // seed from time 6 | int rand1(); 7 | int randn1(int size); 8 | 9 | void swap_rand1(void* ptr1, void* ptr2, unsigned int size); 10 | void randn1mix(void* ptr, unsigned int size, unsigned int count); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/shaders/color_tex.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uProjModelViewMat; 3 | 4 | attribute vec3 aPos; 5 | attribute vec4 aColor; 6 | attribute vec2 aTex; 7 | 8 | varying vec2 vTex; 9 | varying vec4 vColor; 10 | 11 | void main() 12 | { 13 | vTex = aTex; 14 | vColor = aColor; 15 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 16 | } 17 | )GLSL"; 18 | -------------------------------------------------------------------------------- /src/shaders/color_tex.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform int uAlphaDiscard; 3 | uniform int uHalftone; 4 | 5 | uniform sampler2D uTex0; 6 | 7 | varying vec2 vTex; 8 | varying vec4 vColor; 9 | 10 | void main() 11 | { 12 | #insertHalftoneTest 13 | gl_FragColor = texture2D( uTex0, vTex ) * vColor; 14 | if (uAlphaDiscard != 0 && gl_FragColor.a < 0.5) 15 | discard; 16 | } 17 | )GLSL"; 18 | -------------------------------------------------------------------------------- /src/bits.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_BITS_H 2 | #define HLIDAC_BITS_H 3 | 4 | inline unsigned int bits_count(unsigned int value) 5 | { 6 | unsigned int ret = 0; 7 | unsigned int bit_selector = 1; 8 | while (bit_selector) 9 | { 10 | if (bit_selector & value) 11 | ++ret; 12 | bit_selector = bit_selector << 1; 13 | } 14 | return ret; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/shaders/glass_tint.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform int uHalftone; 3 | 4 | uniform sampler2D uTex0; 5 | 6 | varying vec2 vTex; 7 | varying vec3 vNormal; 8 | varying vec3 vCubeRay; 9 | 10 | void main() 11 | { 12 | #insertHalftoneTest 13 | vec4 texColor = texture2D( uTex0, vTex ); 14 | if (texColor.a >= 0.5) 15 | discard; 16 | gl_FragColor = vec4(0.0, 0.0, 0.0, 0.6); 17 | } 18 | )GLSL"; 19 | -------------------------------------------------------------------------------- /src/triboxint.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_TRIBOXINT_H 2 | #define HLIDAC_TRIBOXINT_H 3 | 4 | bool triboxint2(const float boxcen[3], const float a_2[3], const float v0[3], const float v1[3], const float v2[3]); 5 | 6 | inline bool triboxint(const float boxcen[3], const float a_2[3], const float v0[3], const float v1[3], const float v2[3]) 7 | { 8 | return triboxint2(boxcen, a_2, v0, v1, v2); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shaders/light_tex.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uModelViewMat; 3 | uniform mat4 uProjModelViewMat; 4 | uniform mat3 uNormMat; 5 | 6 | attribute vec3 aPos; 7 | attribute vec3 aNormal; 8 | attribute vec2 aTex; 9 | 10 | varying vec2 vTex; 11 | varying vec3 vNormal; 12 | 13 | void main() 14 | { 15 | vTex = aTex; 16 | vNormal = uNormMat * aNormal; 17 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 18 | } 19 | )GLSL"; 20 | -------------------------------------------------------------------------------- /src/cstring1.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_CSTRING1_H 2 | #define HLIDAC_CSTRING1_H 3 | 4 | #include 5 | 6 | bool isSpace(int c); 7 | bool isDigit(int c); 8 | bool strSuff(const char* str, const char* suff); 9 | bool strstrtok1(const char* str1, const char* str2); 10 | void uncomment(char* str); 11 | void strncat1(char* str_o, const char* str1_i, const char* str2_i, size_t num); 12 | bool strempty(const char* str); 13 | char* trim(char* str); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/fopendir.cpp: -------------------------------------------------------------------------------- 1 | #include "fopendir.h" 2 | #include 3 | 4 | FILE* fopenDir(const char* filename, const char* mode, const char* org, const char* app) 5 | { 6 | const char* noPath = ""; 7 | const char* path = SDL_GetPrefPath(org, app); 8 | if (path == 0) 9 | { 10 | path = noPath; 11 | } 12 | char filepath[1024] = {0}; 13 | snprintf(filepath, 1023, "%s%s", path, filename); 14 | return fopen(filepath, mode); 15 | } 16 | -------------------------------------------------------------------------------- /src/shaders/glass_reflection.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform vec4 uLightPos; 3 | uniform vec4 uLightAmbient; 4 | uniform vec4 uLightDiffuse; 5 | 6 | uniform int uHalftone; 7 | 8 | uniform sampler2D uTex0; 9 | uniform samplerCube uCube; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | #insertHalftoneTest 18 | vec4 texColor = texture2D(uTex0, vTex); 19 | if (texColor.a >= 0.5) 20 | discard; 21 | gl_FragColor = textureCube(uCube, vCubeRay); 22 | } 23 | )GLSL"; 24 | -------------------------------------------------------------------------------- /src/datkey.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_DATKEY_H 2 | #define HLIDAC_DATKEY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct Datfile { 9 | char p_fname[1024]; 10 | unsigned int p_size; 11 | unsigned int p_offset; 12 | }; 13 | 14 | class Datdec { // tar file reader 15 | public: 16 | bool init(const char* fname); 17 | bool load(const char* fname); 18 | bool exists(const char* fname) const; 19 | char p_fname[1024]; 20 | std::vector p_files; 21 | std::vector p_buff; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/ghost.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Ghost { 5 | Ghost(bool frames = true); 6 | bool load(int track, int reverse); 7 | void save(); 8 | void copyFrom(const Ghost& gnew); 9 | 10 | int m_version; // verze souboru 11 | int m_track; // číslo tratě 12 | int m_reverse; 13 | int m_car; 14 | int m_carcolor; 15 | float m_seconds; 16 | int m_maxnum; 17 | int m_num; // počet uložených snímků při 10 fps 18 | std::vector m_frames; 19 | 20 | void getfname(char* buff); // 1024 bajtů 21 | }; 22 | -------------------------------------------------------------------------------- /src/pict2.cpp: -------------------------------------------------------------------------------- 1 | #include "pict2.h" 2 | 3 | bool Pict2::r2a() 4 | { 5 | for (int i = 0; i != p_w * p_h; ++i) 6 | { 7 | p_px[i * 4 + 3] = p_px[i * 4 + 2]; 8 | p_px[i * 4 + 2] = 0xff; 9 | p_px[i * 4 + 1] = 0xff; 10 | p_px[i * 4 + 0] = 0xff; 11 | } 12 | 13 | return true; 14 | } 15 | 16 | bool Pict2::r2a(const Pict2& pict) 17 | { 18 | if (p_w != pict.p_w || p_h != pict.p_h) 19 | return false; 20 | 21 | for (int i = 0; i != p_w * p_h; ++i) 22 | { 23 | p_px[i * 4 + 3] = *(pict.c_px() + i * 4 + 2); 24 | } 25 | 26 | return true; 27 | } 28 | -------------------------------------------------------------------------------- /src/gameaux.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double GetSystemTime() 4 | { 5 | return SDL_GetTicks(); 6 | } 7 | 8 | void getdeltaT_init() 9 | { 10 | } 11 | 12 | float getdeltaT() 13 | { 14 | static bool bfirstrun = true; 15 | static double tm_prev; 16 | if (bfirstrun) 17 | { 18 | tm_prev = (double)GetSystemTime()/1000.f; 19 | bfirstrun = false; 20 | return 0.f; 21 | } 22 | double tm_now = (double)GetSystemTime()/1000.f; 23 | double deltaT = tm_now-tm_prev; 24 | tm_prev = tm_now; 25 | if (deltaT < 0.f) 26 | return 0.f; 27 | return deltaT; 28 | } 29 | -------------------------------------------------------------------------------- /src/shaders/car.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uModelViewMat; 3 | uniform mat4 uProjModelViewMat; 4 | uniform mat4 uTexMat; 5 | uniform mat3 uNormMat; 6 | 7 | attribute vec3 aPos; 8 | attribute vec3 aNormal; 9 | attribute vec2 aTex; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | vTex = aTex; 18 | vNormal = uNormMat * aNormal; 19 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 20 | vec3 eyePos = vec3(uModelViewMat * vec4(aPos, 1.0)); 21 | vCubeRay = normalize(mat3(uTexMat) * reflect(eyePos, vNormal)); 22 | } 23 | )GLSL"; 24 | -------------------------------------------------------------------------------- /src/shaders/car_top.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uModelViewMat; 3 | uniform mat4 uProjModelViewMat; 4 | uniform mat4 uTexMat; 5 | uniform mat3 uNormMat; 6 | 7 | attribute vec3 aPos; 8 | attribute vec3 aNormal; 9 | attribute vec2 aTex; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | vTex = aTex; 18 | vNormal = uNormMat * aNormal; 19 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 20 | vec3 eyePos = vec3(uModelViewMat * vec4(aPos, 1.0)); 21 | vCubeRay = normalize(mat3(uTexMat) * reflect(eyePos, vNormal)); 22 | } 23 | )GLSL"; 24 | -------------------------------------------------------------------------------- /src/shaders/glass_reflection.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uModelViewMat; 3 | uniform mat4 uProjModelViewMat; 4 | uniform mat4 uTexMat; 5 | uniform mat3 uNormMat; 6 | 7 | attribute vec3 aPos; 8 | attribute vec3 aNormal; 9 | attribute vec2 aTex; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | vTex = aTex; 18 | vNormal = uNormMat * aNormal; 19 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 20 | vec3 eyePos = vec3(uModelViewMat * vec4(aPos, 1.0)); 21 | vCubeRay = normalize(mat3(uTexMat) * reflect(eyePos, vNormal)); 22 | } 23 | )GLSL"; 24 | -------------------------------------------------------------------------------- /src/onelayout.h: -------------------------------------------------------------------------------- 1 | #ifndef ONELAYOUT_H 2 | #define ONELAYOUT_H 3 | 4 | #include 5 | #include 6 | 7 | class OneLayout 8 | { 9 | public: 10 | OneLayout(int pos, int margin); 11 | void add(int size); 12 | int getPos() const; 13 | int getSize() const; 14 | int getCellP(int cell) const; 15 | int getCellS(int cell, int cells) const; 16 | std::tuple getCellPS(int cell, int cells) const; 17 | std::tuple getCellPV(int cell, int value) const; 18 | 19 | private: 20 | int m_pos; 21 | int m_margin; 22 | std::vector m_cellSizes; 23 | }; 24 | 25 | #endif // ONELAYOUT_H 26 | -------------------------------------------------------------------------------- /src/error_msg.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_MSG_H 2 | #define ERROR_MSG_H 3 | 4 | #if defined(__WIN32__) 5 | 6 | #include 7 | 8 | extern SDL_Window* gameWindow; 9 | 10 | #define error_msg(...) do { \ 11 | char buff[256] = {0}; snprintf(buff, 255, __VA_ARGS__); \ 12 | size_t len = strlen(buff); \ 13 | if (len > 0 && buff[len - 1] == '\n') buff[len - 1] = 0; \ 14 | SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", buff, gameWindow); \ 15 | } while (0) 16 | 17 | #else 18 | 19 | #include 20 | #define error_msg(...) do { fprintf(stderr, __VA_ARGS__); fflush(stderr); } while (0) 21 | 22 | #endif 23 | 24 | #endif // ERROR_MSG_H 25 | -------------------------------------------------------------------------------- /src/glm1.h: -------------------------------------------------------------------------------- 1 | #ifndef GLM1_H 2 | #define GLM1_H 3 | 4 | #include // glm::vec3 5 | #include // glm::vec4 6 | #include // glm::mat4 7 | #include // glm::translate, glm::rotate, glm::scale 8 | #include // glm::perspective 9 | #include // glm::pi 10 | #include // glm::value_ptr 11 | 12 | namespace glm 13 | { 14 | inline void assign1(float* fa, const glm::vec2& v) { fa[0] = v[0]; fa[1] = v[1]; } 15 | inline void assign1(float* fa, const glm::vec3& v) { fa[0] = v[0]; fa[1] = v[1]; fa[2] = v[2]; } 16 | inline void assign1(float* fa, const glm::vec4& v) { fa[0] = v[0]; fa[1] = v[1]; fa[2] = v[2]; fa[3] = v[3]; } 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shaders/car.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform vec4 uLightPos; 3 | uniform vec4 uLightAmbient; 4 | uniform vec4 uLightDiffuse; 5 | 6 | uniform int uHalftone; 7 | 8 | uniform sampler2D uTex0; 9 | uniform samplerCube uCube; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | #insertHalftoneTest 18 | vec4 texColor = texture2D(uTex0, vTex); 19 | vec4 envColor = textureCube(uCube, vCubeRay); 20 | vec3 normal = vNormal; 21 | float intensity = max(0.0, dot(normal, uLightPos.xyz)); 22 | vec4 color = vec4(vec3(intensity), 1.0) * uLightDiffuse + uLightAmbient; 23 | color.rgb = clamp(color.rgb, 0.0, 1.0); 24 | color.a = 1.0; 25 | gl_FragColor = texColor * color + vec4(envColor.rgb, 0.0); 26 | } 27 | )GLSL"; 28 | -------------------------------------------------------------------------------- /src/skysph.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_SKYSPH_H 2 | #define HLIDAC_SKYSPH_H 3 | 4 | #include "pict2.h" 5 | #include "gl1.h" 6 | #include "glm1.h" 7 | #include "gl_shared.h" 8 | 9 | #include 10 | #include 11 | 12 | class Gamemng; 13 | 14 | class Skysph 15 | { 16 | public: 17 | Skysph() : r(0), ang(0), size(0) { } 18 | void init(Gamemng* gamemng, float r_prm, float ang_prm, int h = 40, int v = 10); 19 | void set_tex(SharedGLtex tex_sky_prm) { tex_sky = tex_sky_prm; } 20 | void render(const glm::mat4& sky_mat); 21 | float r; 22 | float ang; 23 | std::vector vert; 24 | SharedGLbuf arrayBuf; 25 | std::vector tris; 26 | SharedGLbuf elemBuf; 27 | unsigned int size; 28 | SharedGLtex tex_sky; 29 | 30 | float light_pos[4]; 31 | Gamemng* p_gamemng; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/cam.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_CAM_H 2 | #define HLIDAC_CAM_H 3 | 4 | #include "glm1.h" 5 | 6 | class Cam { 7 | public: 8 | void init(float x, float y, float z, float ax, float ay, float speed_transf, float speed_rot); 9 | void move_l(float T); // move left 10 | void move_r(float T); // move right 11 | void move_b(float T); // move back 12 | void move_f(float T); // move forward 13 | void move_d(float T); // move down - currently does nothing 14 | void move_u(float T); // move up - currently does nothing 15 | void turn_l(float T); 16 | void turn_r(float T); 17 | void turn_d(float T); 18 | void turn_u(float T); 19 | 20 | /*void save(); 21 | void load();*/ 22 | 23 | glm::mat4 transform() const; 24 | 25 | float p_pos[3]; 26 | float p_ax; 27 | float p_ay; 28 | float p_vx; 29 | float p_va; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/shaders/light_tex.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform vec4 uLightPos; 3 | uniform vec4 uLightAmbient; 4 | uniform vec4 uLightDiffuse; 5 | 6 | uniform int uAlphaDiscard; 7 | uniform int uHalftone; 8 | 9 | uniform sampler2D uTex0; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | 14 | void main() 15 | { 16 | #insertHalftoneTest 17 | vec3 normal = vNormal; 18 | if (!gl_FrontFacing) 19 | { 20 | normal = -normal; 21 | } 22 | float intensity = max(0.0, dot(normal, uLightPos.xyz)); 23 | vec4 color = vec4(vec3(intensity), 1.0) * uLightDiffuse + uLightAmbient; 24 | color.r = clamp(color.r, 0.0, 1.0); 25 | color.g = clamp(color.g, 0.0, 1.0); 26 | color.b = clamp(color.b, 0.0, 1.0); 27 | color.a = 1.0; 28 | gl_FragColor = texture2D( uTex0, vTex ) * color; 29 | if (uAlphaDiscard != 0 && gl_FragColor.a < 0.5) 30 | discard; 31 | } 32 | )GLSL"; 33 | -------------------------------------------------------------------------------- /src/shaders/light_tex_sunk.vs.h: -------------------------------------------------------------------------------- 1 | vs=R"GLSL( 2 | uniform mat4 uModelViewMat; 3 | uniform mat4 uProjModelViewMat; 4 | uniform mat3 uNormMat; 5 | 6 | attribute vec3 aPos; 7 | attribute vec3 aNormal; 8 | attribute vec3 aTan; 9 | attribute vec3 aBitan; 10 | attribute vec2 aTex; 11 | 12 | varying vec2 vTex; 13 | varying vec3 vNormal; 14 | varying vec3 vTan; 15 | varying vec3 vBitan; 16 | varying vec3 vEyePos; 17 | varying mat3 vTBN; 18 | 19 | void main() 20 | { 21 | vTex = aTex; 22 | vNormal = uNormMat * aNormal; 23 | vTan = uNormMat * aTan; 24 | vBitan = uNormMat * aBitan; 25 | vTBN[0][0] = vTan.x; vTBN[1][0] = vTan.y; vTBN[2][0] = vTan.z; 26 | vTBN[0][1] = vBitan.x; vTBN[1][1] = vBitan.y; vTBN[2][1] = vBitan.z; 27 | vTBN[0][2] = vNormal.x; vTBN[1][2] = vNormal.y; vTBN[2][2] = vNormal.z; 28 | vEyePos = vec3(uModelViewMat * vec4(aPos, 1.0)); 29 | gl_Position = uProjModelViewMat * vec4(aPos, 1.0); 30 | } 31 | )GLSL"; 32 | -------------------------------------------------------------------------------- /src/shaders/car_top.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform vec4 uLightPos; 3 | uniform vec4 uLightAmbient; 4 | uniform vec4 uLightDiffuse; 5 | 6 | uniform int uHalftone; 7 | 8 | uniform sampler2D uTex0; 9 | uniform samplerCube uCube; 10 | 11 | varying vec2 vTex; 12 | varying vec3 vNormal; 13 | varying vec3 vCubeRay; 14 | 15 | void main() 16 | { 17 | #insertHalftoneTest 18 | vec4 texColor = texture2D( uTex0, vTex ); 19 | if (texColor.a < 0.5) 20 | discard; 21 | if (!gl_FrontFacing) 22 | { 23 | gl_FragColor = vec4(0.0, 0.0, 0.0, texColor.a); 24 | } 25 | else 26 | { 27 | vec4 envColor = textureCube(uCube, vCubeRay); 28 | vec3 normal = vNormal; 29 | float intensity = max(0.0, dot(normal, uLightPos.xyz)); 30 | vec4 color = vec4(vec3(intensity), 1.0) * uLightDiffuse + uLightAmbient; 31 | color.rgb = clamp(color.rgb, 0.0, 1.0); 32 | color.a = 1.0; 33 | gl_FragColor = texColor * color + vec4(envColor.rgb, 0.0); 34 | } 35 | } 36 | )GLSL"; 37 | -------------------------------------------------------------------------------- /src/mingw32/mingw32-toolchain.cmake: -------------------------------------------------------------------------------- 1 | # CMake Toolchain File for MinGW32 Cross Compilation 2 | 3 | # the name of the target operating system 4 | set(CMAKE_SYSTEM_NAME Windows) 5 | 6 | # which tools to use 7 | set(CMAKE_C_COMPILER /usr/bin/i686-w64-mingw32-gcc) 8 | set(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++) 9 | 10 | # here is where the target environment located 11 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) 12 | 13 | # adjust the default behavior of the FIND_XXX() commands: 14 | 15 | # search programs in the host environment 16 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 17 | 18 | # search headers and libraries in the target environment 19 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 20 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 21 | 22 | #set(CMAKE_INSTALL_PREFIX ${CMAKE_FIND_ROOT_PATH}/usr CACHE FILEPATH "install path prefix") 23 | 24 | # initialize required linker flags 25 | #set(CMAKE_EXE_LINKER_FLAGS_INIT "-static-libgcc -static-libstdc++") 26 | 27 | set(CMAKE_SYSTEM_PROCESSOR "X86") 28 | 29 | # end of toolchain file 30 | -------------------------------------------------------------------------------- /src/Makefile.linux-es2: -------------------------------------------------------------------------------- 1 | prefix ?= /usr/local 2 | CXXFLAGS += -O2 -Wall -Wextra -DDIR_OPENMRAC_DAT=$(prefix)/share/openmrac/ -fno-exceptions -fPIC -std=c++20 -DNDEBUG -DUSE_GLESv2 3 | LDFLAGS += -lSDL2 -lGLESv2 -lopenal -ljpeg -lpng -lm -s -lstdc++ 4 | 5 | CC ?= g++ 6 | override LD = $(CC) 7 | TARGET = openmrac-es2 8 | OBJS := $(sort $(shell ls *.cpp | grep -v _win32.cpp | sed 's/.cpp/.o/g' | tr '\n' ' ')) 9 | 10 | .PHONY: all clean install uninstall 11 | 12 | all: $(TARGET) 13 | 14 | clean: 15 | rm -f *.o $(TARGET) 16 | 17 | %.o: %.cpp *.h shaders/*.h 18 | $(CC) -c $(CXXFLAGS) $< 19 | 20 | $(TARGET): $(OBJS) 21 | $(LD) -o $(TARGET) $(OBJS) $(LDFLAGS) 22 | 23 | install: all uninstall 24 | sudo cp $(TARGET) /usr/bin/$(TARGET) 25 | sudo cp openmrac.ico /usr/share/pixmaps/$(TARGET).ico 26 | sudo cp $(TARGET).desktop /usr/share/applications/$(TARGET).desktop 27 | sudo update-desktop-database || true 28 | 29 | uninstall: 30 | sudo rm -f /usr/bin/$(TARGET) 31 | sudo rm -f /usr/share/pixmaps/$(TARGET).ico 32 | sudo rm -f /usr/share/applications/$(TARGET).desktop 33 | sudo update-desktop-database || true 34 | -------------------------------------------------------------------------------- /src/rand1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rand1.h" 4 | 5 | int rand1() 6 | { 7 | return rand(); 8 | } 9 | 10 | void srand0() 11 | { 12 | srand(0); 13 | } 14 | 15 | void srand1() 16 | { 17 | std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); 18 | srand(ms.count()); 19 | } 20 | 21 | int randn1(int size) 22 | { 23 | const int rozsah_casti = RAND_MAX / size; 24 | int r; 25 | 26 | do r = rand1() / rozsah_casti; 27 | while (r >= size); 28 | 29 | return r; 30 | } 31 | 32 | void swap_rand1(void* ptr1, void* ptr2, unsigned int size) 33 | { 34 | if (ptr1 == ptr2) 35 | return; 36 | for (unsigned int i = 0; i != size; ++i) 37 | { 38 | ((unsigned char*)(ptr1))[i] ^= ((unsigned char*)(ptr2))[i]; 39 | ((unsigned char*)(ptr2))[i] ^= ((unsigned char*)(ptr1))[i]; 40 | ((unsigned char*)(ptr1))[i] ^= ((unsigned char*)(ptr2))[i]; 41 | } 42 | } 43 | 44 | void randn1mix(void* ptr, unsigned int size, unsigned int count) 45 | { 46 | unsigned char* ptr1 = (unsigned char*)ptr; 47 | for (int i = 0; i < int(count)-1; ++i) 48 | { 49 | int j = i + randn1(int(count)-i); 50 | swap_rand1(ptr1+i*size, ptr1+j*size, size); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Makefile.linux: -------------------------------------------------------------------------------- 1 | prefix ?= /usr/local 2 | CXXFLAGS += -O2 -Wall -Wextra -DDIR_OPENMRAC_DAT=$(prefix)/share/openmrac/ -fno-exceptions -fPIC -std=c++20 -DNDEBUG 3 | LDFLAGS += -lSDL2 -lGL -lopenal -ljpeg -lpng -lm -s -lstdc++ 4 | 5 | # Uncomment the following two lines to use MiniAL instead of OpenAL: 6 | #CXXFLAGS += -O2 -Wall -Wextra -DDIR_OPENMRAC_DAT=$(prefix)/share/openmrac/ -DUSE_MINIAL -fno-exceptions -fPIC 7 | #LDFLAGS += -lSDL2 -lGL -ljpeg -lpng -lm -s -lstdc++ 8 | 9 | CC ?= g++ 10 | override LD = $(CC) 11 | TARGET = openmrac 12 | OBJS := $(sort $(shell ls *.cpp | grep -v _win32.cpp | sed 's/.cpp/.o/g' | tr '\n' ' ')) 13 | 14 | .PHONY: all clean install uninstall 15 | 16 | all: $(TARGET) 17 | 18 | clean: 19 | rm -f *.o $(TARGET) 20 | 21 | %.o: %.cpp *.h shaders/*.h 22 | $(CC) -c $(CPPFLAGS) $(CXXFLAGS) $< 23 | 24 | $(TARGET): $(OBJS) 25 | $(LD) -o $(TARGET) $(OBJS) $(LDFLAGS) 26 | 27 | install: all uninstall 28 | sudo cp openmrac /usr/bin/openmrac 29 | sudo cp openmrac.ico /usr/share/pixmaps/openmrac.ico 30 | sudo cp openmrac.desktop /usr/share/applications/openmrac.desktop 31 | sudo update-desktop-database || true 32 | 33 | uninstall: 34 | sudo rm -f /usr/bin/openmrac 35 | sudo rm -f /usr/share/pixmaps/openmrac.ico 36 | sudo rm -f /usr/share/applications/openmrac.desktop 37 | sudo update-desktop-database || true 38 | -------------------------------------------------------------------------------- /src/3dm.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_3DM_H 2 | #define HLIDAC_3DM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "gl_shared.h" 9 | 10 | class O3dm { 11 | public: 12 | std::vector p_i; // pole indexů faců 13 | SharedGLbuf p_buf; 14 | unsigned int p_m = 0; // id materiálu 15 | unsigned int p_gi = 0; // index transformační skupiny 16 | void initBuf(); 17 | }; 18 | 19 | enum class T3dmA { 20 | Pos0 = 0, 21 | Pos1, 22 | Pos2, 23 | Tex0, 24 | Tex1, 25 | Norm0, 26 | Norm1, 27 | Norm2, 28 | Tan0, 29 | Tan1, 30 | Tan2, 31 | Bitan0, 32 | Bitan1, 33 | Bitan2, 34 | //Dummy0, 35 | //Dummy1, 36 | Count 37 | }; 38 | 39 | class T3dm { 40 | public: 41 | void load(const char* fname, const char** o_names = 0); // grouping names (0 - model je statický, transformace konečná) 42 | void scale(float aspect); 43 | int getgidobj(unsigned int gid) const; // najde první objekt s číslem skupiny, pokud ne, vrátí -1 44 | std::vector p_v; // viz T3dmA 45 | SharedGLbuf p_buf; 46 | std::vector p_o; // objekty 47 | std::vector p_m; // materiály 48 | std::vector p_cen; // středy objektů 49 | void clear() { p_v.clear(); p_o.clear(); p_m.clear(); p_cen.clear(); } 50 | void initBuf(); 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/onelayout.cpp: -------------------------------------------------------------------------------- 1 | #include "onelayout.h" 2 | #include 3 | #include 4 | 5 | OneLayout::OneLayout(int pos, int margin) : 6 | m_pos(pos), 7 | m_margin(margin) 8 | { 9 | } 10 | 11 | void OneLayout::add(int size) 12 | { 13 | m_cellSizes.push_back(size); 14 | } 15 | 16 | int OneLayout::getPos() const 17 | { 18 | return m_pos; 19 | } 20 | 21 | int OneLayout::getSize() const 22 | { 23 | return std::accumulate(m_cellSizes.begin(), m_cellSizes.end(), 2 * m_margin); 24 | } 25 | 26 | int OneLayout::getCellP(int cell) const 27 | { 28 | int cellP = m_pos + m_margin; 29 | for (int i = 0; i < cell; ++i) 30 | { 31 | assert(i < static_cast(m_cellSizes.size())); 32 | cellP += m_cellSizes[i]; 33 | } 34 | return cellP; 35 | } 36 | 37 | int OneLayout::getCellS(int cell, int cells) const 38 | { 39 | int cellS = 0; 40 | for (int i = 0; i != cells; ++i) 41 | { 42 | assert(cell + i < static_cast(m_cellSizes.size())); 43 | cellS += m_cellSizes[cell + i]; 44 | } 45 | return cellS; 46 | } 47 | 48 | std::tuple OneLayout::getCellPS(int cell, int cells) const 49 | { 50 | return std::make_tuple(getCellP(cell), getCellS(cell, cells)); 51 | } 52 | 53 | std::tuple OneLayout::getCellPV(int cell, int value) const 54 | { 55 | return std::make_tuple(getCellP(cell), value); 56 | } 57 | -------------------------------------------------------------------------------- /src/gbuff_in.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_GBUFF_IN_H 2 | #define HLIDAC_GBUFF_IN_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "datkey.h" 8 | 9 | class Gbuff_in { 10 | public: 11 | Gbuff_in() : p_bactive(false), p_bdat(false), p_bbin(false), p_buff_pos(0), p_fin(0), p_stdin_buff_ptr(0), p_stdin_buff_sz(0) { } 12 | ~Gbuff_in() { if (p_fin) ::fclose(p_fin); } 13 | void init_stdin() { p_bdat = false; } 14 | bool init_dat(const char* fname); 15 | // společné fce 16 | bool exists(const char* fname) const { return p_datdec.exists(fname); } 17 | bool f_open(const char* fname, const char* mode); /* "r" nebo "rb" */ 18 | void fclose(); // normálně int fclose(FILE*) 19 | // fce pro práci s textovým souborem 20 | char* fgets(char* str, int num); // normálně char * fgets ( char * str, int num, FILE * stream ) 21 | void rewind(); 22 | // fce pro práci s binárním souborem 23 | /*const*/ uint8_t* fbuffptr(); 24 | unsigned int fbuffsz(); 25 | private: 26 | bool p_bactive; 27 | bool p_bdat; // načítání z datového souboru místo normálních souborů 28 | bool p_bbin; // načítání z binárního bufferu 29 | Datdec p_datdec; 30 | unsigned int p_buff_pos; 31 | FILE* p_fin; 32 | std::vector p_stdin_buff_ptr; 33 | unsigned int p_stdin_buff_sz; 34 | }; 35 | 36 | extern Gbuff_in gbuff_in; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022, Vojtěch Salajka 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /src/settings_dat.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_DAT_H 2 | #define SETTINGS_DAT_H 3 | 4 | #include "controls.h" 5 | 6 | #include 7 | 8 | struct Sett_entry_base { 9 | char key[256]; 10 | unsigned int val, minval, maxval; 11 | char comment[256]; 12 | }; 13 | 14 | struct Sett_entry { 15 | unsigned int val, defaultVal; 16 | }; 17 | 18 | class Settings { 19 | public: 20 | Settings(const char* filename, std::vector* joystickDevices, std::vector* joystickNotConnectedDevices, Control* controls); 21 | int load(); // 0 - ok, jinak error 22 | int save(); 23 | int set(const char* key, unsigned int val); 24 | const char* getOpenalDevice() const; 25 | unsigned int get(const char* key); 26 | void setOpenalDevice(const char* device); 27 | unsigned int getDefault(const char* key); 28 | void getJoystickName(char* buffer, int size, int i); 29 | 30 | void getControlName(char* buff, unsigned n, unsigned i, bool joystickName); 31 | 32 | std::vector entry; 33 | unsigned int entry_size; 34 | std::vector* joystickDevices; 35 | std::vector* joystickNotConnectedDevices; 36 | Control* controls; 37 | const char* filename; 38 | 39 | static const char* controlNames[16]; 40 | 41 | bool openalDeviceDefault; 42 | std::string openalDeviceName; // jméno, pokud není default 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/pict2_png.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef PNG_1_6_37_STATIC 4 | #include "libpng-1.6.37/png.h" 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "pict2.h" 10 | 11 | int Pict2::loadpng(const void* data, unsigned int size) 12 | { 13 | return loadpng_pom(false, data, size); 14 | } 15 | 16 | int Pict2::loadpng(const char* fname) 17 | { 18 | return loadpng_pom(true, fname, 0); 19 | } 20 | 21 | // 0: ERROR; 1: OK; > 1: WARNING, OTHER 22 | int Pict2::loadpng_pom(bool bfile, const void* fname_data, unsigned int data_size) /*data_size použito, pokud bfile je false*/ // 8bitovou paletu nezkonvertuje na RGB (default = false) 23 | { 24 | png_image image; 25 | memset(&image, 0, sizeof(image)); 26 | image.version = PNG_IMAGE_VERSION; 27 | if (bfile) 28 | { 29 | if (!png_image_begin_read_from_file(&image, (const char*)fname_data)) { 30 | return 0; 31 | } 32 | } 33 | else 34 | { 35 | if (!png_image_begin_read_from_memory(&image, fname_data, data_size)) { 36 | return 0; 37 | } 38 | } 39 | image.format = PNG_FORMAT_RGBA; 40 | create(image.width, image.height, 0); 41 | // a negative stride indicates that the bottom-most row is first in the buffer 42 | // (as expected by openGL) 43 | if (!png_image_finish_read(&image, NULL, p_px.data(), -PNG_IMAGE_ROW_STRIDE(image), NULL)) { 44 | png_image_free(&image); 45 | return 0; 46 | } 47 | return 1; 48 | } 49 | -------------------------------------------------------------------------------- /src/dpiaware_win32.cpp: -------------------------------------------------------------------------------- 1 | // Disable DPI scaling on Windows 2 | 3 | #if defined(__WIN32__) 4 | 5 | #include 6 | 7 | #ifndef DPI_ENUMS_DECLARED 8 | typedef enum PROCESS_DPI_AWARENESS 9 | { 10 | PROCESS_DPI_UNAWARE = 0, 11 | PROCESS_SYSTEM_DPI_AWARE = 1, 12 | PROCESS_PER_MONITOR_DPI_AWARE = 2 13 | } PROCESS_DPI_AWARENESS; 14 | #endif 15 | 16 | typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void); 17 | typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS); 18 | 19 | bool win32_SetProcessDpiAware(void) { 20 | HMODULE shcore = LoadLibraryA("Shcore.dll"); 21 | SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness = NULL; 22 | if (shcore) { 23 | SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T) GetProcAddress(shcore, "SetProcessDpiAwareness"); 24 | } 25 | HMODULE user32 = LoadLibraryA("User32.dll"); 26 | SETPROCESSDPIAWARE_T SetProcessDPIAware = NULL; 27 | if (user32) { 28 | SetProcessDPIAware = (SETPROCESSDPIAWARE_T) GetProcAddress(user32, "SetProcessDPIAware"); 29 | } 30 | 31 | bool ret = false; 32 | if (SetProcessDpiAwareness) { 33 | ret = SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) == S_OK; 34 | } else if (SetProcessDPIAware) { 35 | ret = SetProcessDPIAware() != 0; 36 | } 37 | 38 | if (user32) { 39 | FreeLibrary(user32); 40 | } 41 | if (shcore) { 42 | FreeLibrary(shcore); 43 | } 44 | return ret; 45 | } 46 | 47 | volatile bool ha = win32_SetProcessDpiAware(); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/shaders/light_tex_sunk.fs.h: -------------------------------------------------------------------------------- 1 | fs=R"GLSL( 2 | uniform vec4 uLightPos; 3 | uniform vec4 uLightAmbient; 4 | uniform vec4 uLightDiffuse; 5 | 6 | uniform sampler2D uTex0; 7 | uniform sampler2D uTex1; 8 | 9 | varying vec2 vTex; 10 | varying vec3 vNormal; 11 | varying vec3 vTan; 12 | varying vec3 vBitan; 13 | varying vec3 vEyePos; 14 | varying mat3 vTBN; 15 | 16 | void main() 17 | { 18 | vec3 normal = vNormal; 19 | if (!gl_FrontFacing) 20 | { 21 | normal = -normal; 22 | } 23 | float intensity = max(0.0, dot(normal, uLightPos.xyz)); 24 | vec4 color = vec4(vec3(intensity), 1.0) * uLightDiffuse + uLightAmbient; 25 | color.r = clamp(color.r, 0.0, 1.0); 26 | color.g = clamp(color.g, 0.0, 1.0); 27 | color.b = clamp(color.b, 0.0, 1.0); 28 | color.a = 1.0; 29 | vec4 texColorTop = texture2D(uTex0, vTex); 30 | vec4 colorSunk = texture2D(uTex1, vTex); 31 | vec3 eyeDir = normalize(vEyePos); 32 | vec3 tbnTrans = vTBN * eyeDir; 33 | vec2 offset = tbnTrans.xy / tbnTrans.z * (colorSunk.a * 0.04); 34 | vec2 texc = vTex - offset; 35 | float hiA = colorSunk.a; 36 | if (hiA == 0.0) hiA = 1.0; 37 | float frameMid = texture2D(uTex1, vTex - offset * 0.5).a; 38 | vec4 texColorFrame = texture2D(uTex1, texc); 39 | float frameA = min(texColorFrame.a, frameMid); 40 | float hiFrameA = frameA; 41 | if (hiFrameA == 0.0) hiFrameA = 1.0; 42 | vec4 texColorBtm = mix(colorSunk, texture2D(uTex0, texc), frameA/hiFrameA); 43 | gl_FragColor = mix(texColorTop, texColorBtm, colorSunk.a/hiA) * color; 44 | } 45 | )GLSL"; 46 | -------------------------------------------------------------------------------- /src/particles.cpp: -------------------------------------------------------------------------------- 1 | #include "particles.h" 2 | #include "rbsolver.h" 3 | #include "glm1.h" 4 | 5 | #include 6 | 7 | /// Particle 8 | 9 | bool Particle::step(float deltaT) 10 | { 11 | for (int i = 0; i != 3; ++i) 12 | { 13 | position[i] += velocity[i] * deltaT; 14 | } 15 | float deccelerationSize = 1.f; 16 | 17 | glm::vec3 decceleration(velocity[0], velocity[1], velocity[2]); 18 | glm::normalize(decceleration); 19 | for (int i = 0; i != 3; ++i) 20 | { 21 | decceleration[i] *= deccelerationSize * deltaT; 22 | velocity[i] -= decceleration[i]; 23 | } 24 | radius += radiusIncreaseSpeed * deltaT; 25 | if (position[1] < radius) 26 | position[1] = radius; 27 | density -= densityDecreaseSpeed * deltaT; 28 | return density > 0.f; 29 | } 30 | 31 | /// Particles 32 | 33 | Particles::Particles() 34 | { 35 | const int initialAllocationSize = 50; 36 | m_particleContainer.reserve(initialAllocationSize); 37 | } 38 | 39 | void Particles::step(float deltaT) 40 | { 41 | for (unsigned i = 0; i < m_particleContainer.size(); ++i) 42 | { 43 | Particle& particle = m_particleContainer[i]; 44 | bool existsAfterStep = particle.step(deltaT); 45 | if (!existsAfterStep) 46 | { 47 | if (m_particleContainer.size() > 1) 48 | { 49 | std::swap(particle, m_particleContainer.back()); 50 | } 51 | m_particleContainer.pop_back(); 52 | } 53 | } 54 | ++m_stepCounter; 55 | } 56 | 57 | void Particles::newParticle(const Particle& particle) 58 | { 59 | m_particleContainer.push_back(particle); 60 | } 61 | -------------------------------------------------------------------------------- /src/collider.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_COLLIDER_H 2 | #define HLIDAC_COLLIDER_H 3 | 4 | #include "3dm.h" 5 | #include "rbsolver.h" 6 | #include "soundmng.h" 7 | #include 8 | 9 | inline bool isintersect(const float* t) 10 | { 11 | return t[0] >= 0.f && t[0] <= 1.f && t[1] >= 0.f && t[1] <= 1.f; 12 | } 13 | 14 | class ColliderGrid { 15 | public: 16 | std::vector points; // pole ukazatelů na vrcholy 17 | unsigned int points_sz = 0; 18 | std::vector lines; // pole ukazatelů na úsečky 19 | unsigned int lines_sz = 0; 20 | }; 21 | 22 | class Collider { 23 | public: 24 | Collider() : p_gs(0), p_r(0), p_r_m2(0), p_r_m2_p2(0), p_colg(0), p_rbos(0), p_rbos_sz(0), p_bbox_sz(0), p_players(0), p_sound_crash(0) { } 25 | void init(float gs, float r, const T3dm* t3dm, RBSolver** rbos, unsigned int rbos_sz); 26 | void test(); 27 | 28 | void render(float x, float y); 29 | int get_subg(const float pos[2]) const; 30 | 31 | bool test_line(const unsigned int pos[2], unsigned int iline); 32 | bool test_point(const unsigned int pos[2], unsigned int ipoint); 33 | 34 | void create_grid(const unsigned int pos[2], 35 | std::vector &ilines, std::vector &ipoints, unsigned int &lines_sz, unsigned int &points_sz, bool pass2 = false); 36 | 37 | float p_gs; // stana čtverečku 38 | float p_r; 39 | float p_r_m2; 40 | float p_r_m2_p2; 41 | 42 | float p_base[2]; 43 | float p_top[2]; 44 | unsigned int p_sz[2]; 45 | 46 | std::vector p_colg; // čtvercová síť s příslušnými kolizními objekty 47 | float p_cen[2]; // střed 48 | 49 | RBSolver** p_rbos; 50 | unsigned int p_rbos_sz; 51 | 52 | std::vector p_bbox; 53 | unsigned int p_bbox_sz; 54 | 55 | unsigned int p_players; // počet hráčů ve hře, kvůli zvuku 56 | 57 | Sound_crash* p_sound_crash; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/pict2.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_PICT_H 2 | #define HLIDAC_PICT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Pict2 { 10 | public: 11 | Pict2() : p_w(0), p_h(0) {} 12 | explicit Pict2(int prm_w, int prm_h, const unsigned char* prm_px) { 13 | create(prm_w, prm_h, prm_px); 14 | } 15 | typedef std::vector Vec_b; 16 | int loadjpeg(const char*); 17 | int loadjpeg(const void*, unsigned int); 18 | int loadpng(const void*, unsigned int); 19 | int loadpng(const char*); 20 | void assign(int prm_w, int prm_h, const unsigned char* prm_px) { 21 | clear(); create(prm_w, prm_h, prm_px); } 22 | void clear() { p_px.clear(); p_w = 0; p_h = 0; } 23 | bool empty() const { return !(p_w && p_h && !p_px.empty()); } 24 | bool r2a(); 25 | bool r2a(const Pict2& pict); 26 | int w() const { return p_w; } 27 | int h() const { return p_h; } 28 | uint8_t* px() { return p_px.data(); } 29 | const unsigned char* c_px() const { return p_px.data(); } 30 | unsigned char* px(int x, int y, int c = 0) { return p_px.data()+(x+y*p_w)*4+c; } 31 | const unsigned char* c_px(int x, int y, int c = 0) const { return p_px.data()+(x+y*p_w)*4+c; } 32 | unsigned char& operator[](size_t i) { return p_px[i]; } 33 | const unsigned char& operator[](size_t i) const { return p_px[i]; } 34 | private: 35 | int p_w, p_h; // private width, height, depth 36 | std::vector p_px; // pixels 37 | void create(int prm_w, int prm_h, const unsigned char* prm_px) { 38 | p_w = prm_w; p_h = prm_h; 39 | p_px.resize(p_w*p_h*4); 40 | if (prm_px) std::copy_n(prm_px, p_px.size(), p_px.begin()); 41 | } 42 | int loadpng_pom(bool bfile, const void* fname_data, unsigned int data_size); 43 | int loadjpeg_pom(bool bfile, const void* fname_data, unsigned int data_size); 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/shadermng.h: -------------------------------------------------------------------------------- 1 | #ifndef SHADERMNG_H 2 | #define SHADERMNG_H 3 | 4 | #include "gl1.h" 5 | #include "glm1.h" 6 | 7 | enum class ShaderId { 8 | NoShader = -1, 9 | Color = 0, 10 | Tex, 11 | ColorTex, // uses AlphaDiscard 12 | LightTex, // uses AlphaDiscard 13 | LightTexSunk, // uses AlphaDiscard 14 | Car, // never alpha discard 15 | CarTop, // always alpha discard 16 | GlassTint, 17 | GlassReflection, 18 | Count 19 | }; 20 | 21 | enum class ShaderAttrib { 22 | Pos, 23 | Color, 24 | Tex, 25 | Normal, 26 | Tan, 27 | Bitan, 28 | Count 29 | }; 30 | 31 | enum class ShaderUniMat4 { 32 | ProjMat, 33 | ModelViewMat, 34 | TexMat, 35 | Count 36 | }; 37 | 38 | enum class ShaderUniVec4 { 39 | LightPos, 40 | LightAmbient, 41 | LightDiffuse, 42 | Count 43 | }; 44 | 45 | enum class ShaderUniInt { 46 | AlphaDiscard, 47 | Halftone, 48 | Count 49 | }; 50 | 51 | enum class ShaderUniTex { 52 | Tex0, 53 | Tex1, 54 | Cube, 55 | Count 56 | }; 57 | 58 | class ShaderWrap 59 | { 60 | public: 61 | GLuint program; 62 | GLint mat4locs[(int)ShaderUniMat4::Count]; 63 | GLint pmvloc; 64 | GLint normloc; 65 | GLint vec4locs[(int)ShaderUniVec4::Count]; 66 | GLint intlocs[(int)ShaderUniInt::Count]; 67 | }; 68 | 69 | class ShaderMng 70 | { 71 | public: 72 | ShaderMng(); 73 | 74 | void init(); 75 | void use(ShaderId id); 76 | void set(ShaderUniMat4 id, glm::mat4 m); 77 | void set(ShaderUniVec4 id, glm::vec4 v); 78 | void set(ShaderUniInt id, GLint i); 79 | 80 | ShaderId currentShader; 81 | 82 | ShaderWrap shaders[(int)ShaderId::Count]; 83 | glm::mat4 mat4s[(int)ShaderUniMat4::Count]; 84 | glm::mat4 mat4pmv; 85 | glm::mat3 mat3norm; 86 | glm::vec4 vec4s[(int)ShaderUniVec4::Count]; 87 | GLint ints[(int)ShaderUniInt::Count]; 88 | }; 89 | 90 | #endif // SHADERMNG_H 91 | -------------------------------------------------------------------------------- /src/particles.h: -------------------------------------------------------------------------------- 1 | #ifndef PARTICLES_H 2 | #define PARTICLES_H 3 | 4 | #include 5 | 6 | struct Particle 7 | { 8 | Particle(float posX, float posY, float posZ, float vX, float vY, float vZ, int texCfg, float r, float rIncSpeed, float dens, float densDecSpeed) 9 | { 10 | position[0] = posX + vX * r; 11 | position[1] = posY + vY * r; 12 | position[2] = posZ + vZ * r; 13 | velocity[0] = vX; 14 | velocity[1] = vY; 15 | velocity[2] = vZ; 16 | texConfig = texCfg; 17 | radius = r; 18 | radiusIncreaseSpeed = rIncSpeed; 19 | density = dens; 20 | densityDecreaseSpeed = densDecSpeed; 21 | } 22 | 23 | Particle() 24 | { 25 | position[0] = 0; 26 | position[1] = 0; 27 | position[2] = 0; 28 | velocity[0] = 0; 29 | velocity[1] = 0; 30 | velocity[2] = 0; 31 | texConfig = 0; 32 | radius = 0; 33 | radiusIncreaseSpeed = 1; 34 | density = 0; 35 | densityDecreaseSpeed = 1; 36 | } 37 | 38 | bool step(float deltaT); // true - po kroku existuje, false - po kroku zmizí 39 | 40 | float position[3]; // aktuální pozice 41 | float velocity[3]; // aktuální rychlost 42 | int texConfig; // 0, 1, 2 nebo 3 - konfigurace (natočení) textury 43 | float radius; // aktuální velikost (poloměr!) 44 | float radiusIncreaseSpeed; // lineární rychlost zvětšování 45 | float density; // průhlednost 46 | float densityDecreaseSpeed; // lineární rychlost zprůhledňování 47 | }; 48 | 49 | class Particles 50 | { 51 | public: 52 | Particles(); 53 | void clear() 54 | { 55 | m_particleContainer.clear(); 56 | m_stepCounter = 0; 57 | } 58 | void step(float deltaT); 59 | void newParticle(const Particle& particle); 60 | 61 | std::vector m_particleContainer; 62 | unsigned m_stepCounter; 63 | }; 64 | 65 | #endif // PARTICLES_H 66 | -------------------------------------------------------------------------------- /src/Makefile.mingw: -------------------------------------------------------------------------------- 1 | LIBSDL2_INCLUDEPATH =mingw32/SDL2/i686-w64-mingw32/include 2 | LIBSDL2_LIB_PATH =mingw32/SDL2/i686-w64-mingw32/lib 3 | LIBSDL2_LIB =libSDL2.dll.a 4 | 5 | LIBGLM_INCLUDEPATH =mingw32/glm/ 6 | 7 | LIBGLEW_INCLUDEPATH =mingw32/glew/include 8 | LIBGLEW_LIB_PATH =mingw32/glew/lib/Release/Win32 9 | LIBGLEW_LIB =glew32.lib 10 | 11 | LIBZLIB_LIB_PATH =mingw32/zlib 12 | LIBZLIB_LIB =libzlibstatic.a 13 | 14 | LIBPNG_INCLUDEPATH =mingw32/libpng 15 | LIBPNG_LIB_PATH =mingw32/libpng 16 | LIBPNG_LIB =libpng.a 17 | 18 | LIBJPEG_INCLUDEPATH =mingw32/libjpeg-turbo 19 | LIBJPEG_LIB_PATH =mingw32/libjpeg-turbo 20 | LIBJPEG_LIB =libjpeg.a 21 | LIBJPEG_DEF = 22 | 23 | #LIBJPEG_INCLUDEPATH =jpeg 24 | #LIBJPEG_LIB_PATH =jpeg/.libs 25 | #LIBJPEG_LIB =libjpeg.a 26 | #LIBJPEG_DEF =-DJPEG_NOT_TURBO 27 | 28 | CFLAGS = -O2 -Wall -Wextra -Wno-cast-function-type -DUSE_MINIAL -DSDL_MAIN_HANDLED -fno-exceptions -fPIC -std=c++20 -I$(LIBSDL2_INCLUDEPATH) -I$(LIBJPEG_INCLUDEPATH) -I$(LIBPNG_INCLUDEPATH) -I$(LIBGLM_INCLUDEPATH) -I$(LIBGLEW_INCLUDEPATH) -DM_PI=3.14159265358979323846 -DM_PIf=3.14159265358979323846f $(LIBJPEG_DEF) -DNDEBUG 29 | LFLAGS = $(LIBSDL2_LIB_PATH)/$(LIBSDL2_LIB) $(LIBJPEG_LIB_PATH)/$(LIBJPEG_LIB) $(LIBPNG_LIB_PATH)/$(LIBPNG_LIB) $(LIBZLIB_LIB_PATH)/$(LIBZLIB_LIB) $(LIBGLEW_LIB_PATH)/$(LIBGLEW_LIB) -lopengl32 -lm -s -static-libstdc++ -static-libgcc -static -mwindows 30 | 31 | CXX = i686-w64-mingw32-g++ 32 | LINK = i686-w64-mingw32-g++ 33 | WINDRES= i686-w64-mingw32-windres 34 | 35 | TARGET = openmrac.exe 36 | RES = omicon.res 37 | OBJS := $(shell ls *.cpp | sed 's/.cpp/.o/g' | tr '\n' ' ') 38 | 39 | .PHONY: all clean dist 40 | 41 | all: $(TARGET) 42 | 43 | clean: 44 | rm -f *.o $(RES) $(TARGET) 45 | 46 | %.o: %.cpp *.h shaders/*.h 47 | $(CXX) -c $(CFLAGS) $< 48 | 49 | %.res: %.rc 50 | $(WINDRES) $< -O coff -o $@ 51 | 52 | $(TARGET): $(RES) $(OBJS) 53 | $(LINK) -o $(TARGET) $(OBJS) $(RES) $(LFLAGS) 54 | 55 | dist: all 56 | $(eval DISTDIR := openmrac-$(shell date +%Y%m%d -r openmrac.exe)) 57 | mkdir -p $(DISTDIR) 58 | rm -f $(DISTDIR)/* 59 | cp openmrac.exe $(DISTDIR) 60 | cp mingw32/glew32.dll $(DISTDIR) 61 | cp mingw32/SDL2.dll $(DISTDIR) 62 | cp ../../OpenMRac-data/openmrac.dat $(DISTDIR) 63 | -------------------------------------------------------------------------------- /src/car2d.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_CAR2D_H 2 | #define HLIDAC_CAR2D_H 3 | 4 | #include "rbsolver.h" 5 | 6 | class Car2D { 7 | public: 8 | void init(float whf_x, float whf_y, float whb_x, float whb_y, RBSolver* rbsolver); 9 | 10 | float p_whf_x; // přední osa (+) 11 | float p_whf_y; // šířka předních kol (+) 12 | float p_whb_x; // zadní osa (-) 13 | float p_whb_y; // šířka zadních kol (+) 14 | float p_whl_a; // úhel natočení levého předního kola 15 | float p_whr_a; // pravého 16 | float p_whl_a_i; // úhel - 0 .. 1 17 | float p_whr_a_i; // 18 | float p_whl_a_ren_i; // úhel kol pro zobrazení 19 | float p_whl_a_ren; 20 | 21 | bool p_b_acc; 22 | bool p_b_brake; 23 | 24 | float p_v_prev[2]; 25 | float p_av_prev; 26 | 27 | float p_brake_i; // síla brzdy 0..1 28 | float p_brake_f; // velikost síly brzdy - brzdí všechna kola a u ruční jenom zadní (ruční tady nemáme) 29 | 30 | RBSolver* p_rbsolver; 31 | 32 | void steer_left(); 33 | void steer_right(); 34 | void steer_center(); 35 | void steer_aux(); 36 | 37 | void go_forward(); // dopředu / brzda při couvání 38 | void go_backward(); // dozadu / brzda při jízdě vpřed 39 | void go_zero(); // 40 | void go_brake(); // brzda - obě klávesy 41 | 42 | float p_engine_pitch; 43 | 44 | float get_engine_pitch(); 45 | void damp_engine_pitch(float f); 46 | 47 | float get_acc_aux(); 48 | float get_rev_aux(); 49 | 50 | void get_Fb_whl_acc(float F[2], float A[2]); 51 | void get_Fb_whr_acc(float F[2], float A[2]); 52 | void get_Fb_whl_rev(float F[2], float A[2]); 53 | void get_Fb_whr_rev(float F[2], float A[2]); 54 | float get_Fb_whfl_sl(float F[2], float A[2]); 55 | float get_Fb_whfr_sl(float F[2], float A[2]); 56 | float get_Fb_whbl_sl(float F[2], float A[2]); 57 | float get_Fb_whbr_sl(float F[2], float A[2]); 58 | 59 | float get_Fb_wh_sl_aux(float F[2], const float A[2], float sl_ratio1, float wh_a = 0.f); 60 | 61 | float add_sl_F(); 62 | 63 | void brake_end(); 64 | 65 | }; 66 | 67 | // Orientace auta 68 | // |y 69 | // | 70 | // +-b-|-f-+ 71 | // | 0------> x 72 | // +-b---f-+ 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenMRac 2 | 3 | [![OpenMRac youtube video](media/openmrac-yt.jpg)](https://youtu.be/r3hLTo5Nu1g) 4 | 5 | OpenMRac is a split-screen racing game. It is a tweaked source release of [MultiRacer](https://www.franticware.com/multiracer). 6 | 7 | Programming was done by Vojtěch Salajka. 8 | Porting to big endian architectures for Amiga-like OSes was done by [Szilárd Biró](https://github.com/BSzili). 9 | 10 | ⚠️ Beware! The source code is old and messy, plus most comments are in Czech 😁 11 | 12 | Creating forks and porting to additional platforms is encouraged, but these typically will not be merged back to the main repo. The same applies to mods. 13 | 14 | Franticware claims rights to the name "MultiRacer" which should not be used by other parties for their products or ports. That is the reason for changing the title to OpenMRac, to which no such restrictions apply. 15 | 16 | Game data files are in a separate repository under a different license: https://github.com/Franticware/OpenMRac-data 17 | 18 | # Installation Instructions 19 | 20 | ## Windows 21 | 22 | Download here: https://www.franticware.com/openmrac 23 | 24 | ## Linux 25 | 26 | ### Arch-based (Arch, Manjaro, EndeavourOS, ...) 27 | 28 | Install **openmrac** package from AUR 29 | 30 | ### Debian-based (Debian, Raspberry Pi OS, Ubuntu, MX Linux, Mint, ...) 31 | 32 | * The openmrac and openmrac-data packages are now available in many Debian-based distributions. If not, please use method described in the following section (Other). 33 | 34 | * Note: The openmrac-es2 package is planned (OpenGL ES 2.0 variant) which might be better suited for SBCs based on RISC-V and ARM. 35 | 36 | ### Other (openSUSE, Fedora, ...) 37 | 38 | ``` 39 | git clone https://github.com/Franticware/OpenMRac-data.git 40 | cd OpenMRac-data 41 | make install 42 | cd .. 43 | 44 | git clone https://github.com/Franticware/OpenMRac.git 45 | cd OpenMRac/src 46 | make -f Makefile.linux install 47 | cd ../.. 48 | ``` 49 | 50 | ## Mac OS X 51 | TODO 52 | 53 | # Branches 54 | 55 | * [main](https://github.com/Franticware/OpenMRac/tree/main) - current SDL 2 version, OpenGL with shaders 56 | * [legacy](https://github.com/Franticware/OpenMRac/tree/legacy) - older SDL 1.2 version, OpenGL 1.x (no shaders) 57 | * [dos-3dfx](https://github.com/Franticware/OpenMRac/tree/dos-3dfx) - version for DOS with 3dfx cards, based on the legacy branch 58 | -------------------------------------------------------------------------------- /src/mingw32/prereq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TOOLCHAIN_FILE="../mingw32-toolchain.cmake" 4 | 5 | GLEWVER=2.2.0 6 | rm -Rf 7 | rm -f glew-$GLEWVER-win32.zip 8 | rm -f glew32.dll 9 | wget https://github.com/nigels-com/glew/releases/download/glew-$GLEWVER/glew-$GLEWVER-win32.zip 10 | unzip glew-$GLEWVER-win32.zip 11 | mv glew-$GLEWVER glew 12 | cp glew/bin/Release/Win32/glew32.dll . 13 | 14 | SDL2VER=2.26.3 15 | rm -Rf SDL2 16 | rm -f SDL2-devel-$SDL2VER-mingw.tar.gz SDL2.dll 17 | wget https://libsdl.org/release/SDL2-devel-$SDL2VER-mingw.tar.gz 18 | tar -xvf SDL2-devel-$SDL2VER-mingw.tar.gz 19 | mv SDL2-$SDL2VER SDL2 20 | cp SDL2/i686-w64-mingw32/bin/SDL2.dll . 21 | 22 | git clone https://github.com/g-truc/glm.git 23 | 24 | : <<'END' 25 | LIBJPEGVER=9e 26 | rm -Rf jpeg 27 | rm -f jpegsrc.v$LIBJPEGVER.tar.gz 28 | wget https://www.ijg.org/files/jpegsrc.v$LIBJPEGVER.tar.gz 29 | tar -xvf jpegsrc.v$LIBJPEGVER.tar.gz 30 | mv jpeg-$LIBJPEGVER jpeg 31 | cd jpeg 32 | ./configure --host=i686-w64-mingw32 33 | make 34 | cd .. 35 | END 36 | 37 | rm -Rf libjpeg-turbo 38 | git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git 39 | cd libjpeg-turbo 40 | cmake -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ 41 | -S. -B. \ 42 | -DCMAKE_GNUtoMS:BOOL="0" -DCMAKE_BUILD_TYPE:STRING="MinSizeRel" -DCMAKE_INSTALL_PREFIX:PATH="." -DCMAKE_SYSTEM_PROCESSOR:STRING="" -DWITH_ARITH_DEC:BOOL="0" -DCMAKE_INSTALL_LIBDIR:PATH="lib" -DWITH_SIMD:BOOL="1" -DWITH_TURBOJPEG:BOOL="0" -DPKGNAME:STRING="libjpeg-turbo" -DBUILD:STRING="20221228" -DWITH_ARITH_ENC:BOOL="0" -DENABLE_SHARED:BOOL="0" 43 | make 44 | cd .. 45 | 46 | rm -Rf zlib 47 | git clone https://github.com/madler/zlib 48 | cd zlib 49 | cmake -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ 50 | -S. -B. \ 51 | -DLIBRARY_OUTPUT_PATH:PATH="" -DINSTALL_LIB_DIR:PATH="/usr/local/lib" -DCMAKE_BUILD_TYPE:STRING="MinSizeRel" -DCMAKE_INSTALL_PREFIX:PATH="/usr/local" -DINSTALL_MAN_DIR:PATH="/usr/local/share/man" -DINSTALL_PKGCONFIG_DIR:PATH="/usr/local/share/pkgconfig" -DEXECUTABLE_OUTPUT_PATH:PATH="" 52 | make 53 | cd .. 54 | 55 | rm -Rf libpng 56 | git clone https://github.com/glennrp/libpng 57 | cd libpng 58 | cmake -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ 59 | -S. -B. \ 60 | -DZLIB_INCLUDE_DIRS:PATH="../zlib" -DPNG_SHARED:BOOL="0" -DCMAKE_INSTALL_PREFIX:PATH="/usr/local" -DCMAKE_BUILD_TYPE:STRING="MinSizeRel" -DPNG_PREFIX:STRING="" -DPNG_BUILD_ZLIB:BOOL="1" 61 | make 62 | cd .. 63 | -------------------------------------------------------------------------------- /src/controls.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTROLS_H 2 | #define CONTROLS_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | struct Control 10 | { 11 | enum {E_NONE, E_KEYBOARD, E_MBUTTON, E_JAXIS, E_JHAT, E_JBUTTON}; 12 | enum {JAXIS_NEGATIVE = -2, JAXIS_NEGATIVE_HALF = -1, JAXIS_POSITIVE_HALF = 1, JAXIS_POSITIVE = 2}; 13 | Control() : type(E_NONE) { } 14 | Control(unsigned sym) : type(E_KEYBOARD), i(sym) { } 15 | int type; // <- enum 16 | unsigned i; // key, mouse button, joystick axis, joystick hat, or joystick button 17 | int joystickDeviceIndex; // -1 = not connected 18 | int joystickNotConnectedIndex; // index do seznamu nepřipojených joysticků 19 | int joystickAxisValue; // -2, -1, 1, 2 20 | unsigned joystickHatValue; 21 | }; 22 | 23 | struct JoystickParameters 24 | { 25 | int axes, balls, hats, buttons; 26 | std::string name; 27 | 28 | bool operator==(const JoystickParameters& other) const 29 | { 30 | return axes == other.axes && balls == other.balls && hats == other.hats && buttons == other.buttons && name == other.name; 31 | } 32 | }; 33 | 34 | struct AxisState // for axis range detection 35 | { 36 | enum {E_INITIAL_NONE, E_INITIAL_NEGATIVE, E_INITIAL_ZERO, E_INITIAL_POSITIVE, E_ENTER_POSITIVE, E_ENTER_NEGATIVE}; 37 | /* return value: 38 | * -2 +- 39 | * -1 0- 40 | * 0 none 41 | * 1 0+ 42 | * 2 -+ 43 | */ 44 | int updateState(Sint16 value, bool enterMode); 45 | 46 | void resetEnterMode(); 47 | 48 | static int convertValue(Sint16 value); // -1, 0, 1 ... -, center, +; -2 ... undefined 49 | 50 | AxisState() : lastPosition(-2), state(E_INITIAL_NONE) { } 51 | int lastPosition; 52 | int state; 53 | }; 54 | 55 | struct JoystickIdentifier 56 | { 57 | JoystickParameters parameters; 58 | int parametersIndex; // identical devices indexing 59 | 60 | bool operator==(const JoystickIdentifier& other) const 61 | { 62 | return parameters == other.parameters && parametersIndex == other.parametersIndex; 63 | } 64 | }; 65 | 66 | struct JoystickDevice 67 | { 68 | JoystickIdentifier identifier; 69 | std::vector axesStates; 70 | SDL_Joystick* device; 71 | 72 | void open(int index); 73 | void close(); 74 | }; 75 | 76 | void initializeParametersIndices(std::vector& devices); 77 | 78 | #endif // CONTROLS_H 79 | -------------------------------------------------------------------------------- /src/minial.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2022, Vojtěch Salajka. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ 2 | 3 | #ifndef MINIAL_H 4 | #define MINIAL_H 5 | 6 | #include 7 | 8 | struct ALCcontext; 9 | struct ALCdevice; 10 | 11 | typedef char ALCboolean; 12 | typedef char ALCchar; 13 | typedef int ALCenum; 14 | typedef int ALCint; 15 | typedef unsigned int ALuint; 16 | 17 | #define ALC_DEVICE_SPECIFIER 0x1005 18 | #define ALC_ALL_DEVICES_SPECIFIER 0x1013 19 | 20 | ALCboolean alcCloseDevice(ALCdevice *device); 21 | ALCcontext* alcCreateContext(ALCdevice *device, const ALCint *attrlist); 22 | void alcDestroyContext(ALCcontext *context); 23 | const ALCchar* alcGetString(ALCdevice *device, ALCenum param); 24 | ALCboolean alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); 25 | ALCboolean alcMakeContextCurrent(ALCcontext *context); 26 | ALCdevice* alcOpenDevice(const ALCchar *devicename); 27 | 28 | typedef int ALenum; 29 | typedef float ALfloat; 30 | typedef int ALint; 31 | typedef int ALsizei; 32 | typedef unsigned int ALuint; 33 | typedef void ALvoid; 34 | 35 | #define AL_PITCH 0x1003 36 | #define AL_POSITION 0x1004 37 | #define AL_VELOCITY 0x1006 38 | #define AL_LOOPING 0x1007 39 | #define AL_BUFFER 0x1009 40 | #define AL_GAIN 0x100A 41 | #define AL_ORIENTATION 0x100F 42 | #define AL_SAMPLE_OFFSET 0x1025 43 | #define AL_FORMAT_MONO16 0x1101 44 | 45 | void alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); 46 | void alDeleteBuffers(ALsizei n, const ALuint *buffers); 47 | void alDeleteSources(ALsizei n, const ALuint *sources); 48 | void alGenBuffers(ALsizei n, ALuint *buffers); 49 | void alGenSources(ALsizei n, ALuint *sources); 50 | void alListenerfv(ALenum param, const ALfloat *values); 51 | void alSourcef(ALuint source, ALenum param, ALfloat value); 52 | void alSourcefv(ALuint source, ALenum param, const ALfloat *values); 53 | void alSourcei(ALuint source, ALenum param, ALint value); 54 | void alSourcePlay(ALuint source); 55 | void alSourceRewind(ALuint source); 56 | void alSourceStop(ALuint source); 57 | 58 | extern int MA_lowLatency; 59 | extern int MA_frequency; 60 | 61 | #endif // MINIAL_H 62 | -------------------------------------------------------------------------------- /src/cam.cpp: -------------------------------------------------------------------------------- 1 | #include "cam.h" 2 | #include 3 | #include 4 | #include "gl1.h" 5 | #include 6 | 7 | //void Cam::save() 8 | //{ 9 | // FILE* fout = fopen("cam.dat", "wb"); 10 | // if (!fout) return; 11 | // fwrite(p_pos, sizeof(float), 3, fout); 12 | // fwrite(&p_ax, sizeof(float), 1, fout); 13 | // fwrite(&p_ay, sizeof(float), 1, fout); 14 | // fclose(fout); 15 | //} 16 | 17 | //void Cam::load() 18 | //{ 19 | // FILE* fin = fopen("cam.dat", "rb"); 20 | // if (!fin) return; 21 | // fread(p_pos, sizeof(float), 3, fin); 22 | // fread(&p_ax, sizeof(float), 1, fin); 23 | // fread(&p_ay, sizeof(float), 1, fin); 24 | // fclose(fin); 25 | //} 26 | 27 | void Cam::init(float x, float y, float z, float ax, float ay, float speed_transf, float speed_rot) 28 | { 29 | p_pos[0] = x; 30 | p_pos[1] = y; 31 | p_pos[2] = z; 32 | p_ax = ax; 33 | p_ay = ay; 34 | p_vx = speed_transf; 35 | p_va = speed_rot; 36 | } 37 | 38 | void Cam::move_l(float T) 39 | { 40 | p_pos[0] -= cosf(p_ay)*p_vx*T; 41 | p_pos[2] += sinf(p_ay)*p_vx*T; 42 | } 43 | 44 | void Cam::move_r(float T) 45 | { 46 | p_pos[0] += cosf(p_ay)*p_vx*T; 47 | p_pos[2] -= sinf(p_ay)*p_vx*T; 48 | } 49 | 50 | void Cam::move_b(float T) 51 | { 52 | p_pos[0] += sinf(p_ay)*cosf(p_ax)*p_vx*T; 53 | p_pos[2] += cosf(p_ay)*cosf(p_ax)*p_vx*T; 54 | p_pos[1] -= sinf(p_ax)*p_vx*T; 55 | } 56 | 57 | void Cam::move_f(float T) 58 | { 59 | p_pos[0] -= sinf(p_ay)*cosf(p_ax)*p_vx*T; 60 | p_pos[2] -= cosf(p_ay)*cosf(p_ax)*p_vx*T; 61 | p_pos[1] += sinf(p_ax)*p_vx*T; 62 | } 63 | 64 | void Cam::move_d(float T) 65 | { 66 | p_pos[1] -= p_vx*T; 67 | } 68 | 69 | void Cam::move_u(float T) 70 | { 71 | p_pos[1] += p_vx*T; 72 | } 73 | 74 | void Cam::turn_l(float T) 75 | { 76 | p_ay += p_va*T; 77 | } 78 | 79 | void Cam::turn_r(float T) 80 | { 81 | p_ay -= p_va*T; 82 | } 83 | 84 | void Cam::turn_d(float T) 85 | { 86 | p_ax -= p_va*T; 87 | } 88 | 89 | void Cam::turn_u(float T) 90 | { 91 | p_ax += p_va*T; 92 | } 93 | 94 | glm::mat4 Cam::transform() const 95 | { 96 | //printf("%f, %f, %f, %f, %f\n", p_pos[0], p_pos[1], p_pos[2], p_ax, p_ay); fflush(stdout); 97 | glm::mat4 ret(1); 98 | ret = glm::rotate(ret, -p_ax, glm::vec3(1.f, 0.f, 0.f)); 99 | ret = glm::rotate(ret, -p_ay, glm::vec3(0.f, 1.f, 0.f)); 100 | ret = glm::translate(ret, glm::vec3(-p_pos[0], -p_pos[1], -p_pos[2])); 101 | return ret; 102 | } 103 | -------------------------------------------------------------------------------- /src/datkey.cpp: -------------------------------------------------------------------------------- 1 | #include "datkey.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | bool Datdec::load(const char* fname) 9 | { 10 | unsigned int i = 0; 11 | while (i != p_files.size()) 12 | { 13 | if (strcmp(p_files[i].p_fname, fname) == 0) 14 | break; 15 | ++i; 16 | } 17 | if (i == p_files.size()) 18 | { 19 | p_buff.clear(); 20 | return false; 21 | } 22 | FILE* fin = fopen(p_fname, "rb"); 23 | fseek(fin, p_files[i].p_offset, SEEK_SET); 24 | p_buff.resize(p_files[i].p_size); 25 | size_t newSize = fread(&p_buff[0], 1, p_files[i].p_size, fin); 26 | p_buff.resize(newSize); 27 | fclose(fin); 28 | return true; 29 | } 30 | 31 | bool Datdec::exists(const char* fname) const 32 | { 33 | unsigned int i = 0; 34 | while (i != p_files.size()) 35 | { 36 | if (strcmp(p_files[i].p_fname, fname) == 0) 37 | break; 38 | ++i; 39 | } 40 | return i != p_files.size(); 41 | } 42 | 43 | struct TarHeader 44 | { /* byte offset */ 45 | char name[100]; /* 0 */ 46 | char mode[8]; /* 100 */ 47 | char uid[8]; /* 108 */ 48 | char gid[8]; /* 116 */ 49 | char size[12]; /* 124 */ 50 | }; 51 | 52 | bool Datdec::init(const char* fname) 53 | { 54 | strncpy(p_fname, fname, 1023); 55 | FILE* fin = fopen(p_fname, "rb"); 56 | if (fin == NULL) 57 | return false; 58 | unsigned char tarBlock[512]; 59 | TarHeader tarHeader; 60 | Datfile f; 61 | size_t offset = 0; 62 | for (;;) 63 | { 64 | if (fread(tarBlock, 512, 1, fin) != 1) 65 | { 66 | fclose(fin); 67 | return true; 68 | } 69 | offset += 512; 70 | memcpy(&tarHeader, tarBlock, sizeof(TarHeader)); 71 | if (tarHeader.name[0] == 0) 72 | { 73 | fclose(fin); 74 | return true; 75 | } 76 | f.p_fname[99] = 0; 77 | strncpy(f.p_fname, tarHeader.name, 99); 78 | int fileSize = 0; 79 | if (sscanf(tarHeader.size, "%o", &fileSize) != 1) 80 | { 81 | fclose(fin); 82 | return false; 83 | } 84 | f.p_size = fileSize; 85 | f.p_offset = offset; 86 | int blocks = fileSize / 512 + !!(fileSize % 512); 87 | fseek(fin, blocks * 512, SEEK_CUR); 88 | offset += blocks * 512; 89 | p_files.push_back(f); 90 | } 91 | return true; 92 | } 93 | -------------------------------------------------------------------------------- /src/gltext.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_GLTEXT_H 2 | #define HLIDAC_GLTEXT_H 3 | 4 | #include 5 | #include "gl1.h" 6 | #include "gl_shared.h" 7 | 8 | #include 9 | 10 | #include "glm1.h" 11 | 12 | struct Glfchar { 13 | float vertw; 14 | float texc[4]; // l, r, b, t 15 | }; 16 | 17 | class Glfont { 18 | public: 19 | Glfont() : p_dist(0), p_charmap_start(0), p_charmap_size(0), p_defaultchar(0) { } 20 | void init(const unsigned int mapsize[2]/*počet znaků*/, const unsigned int mapsize1[2]/*rozměry jednoho znaku*/, unsigned int mapcharh, const char* mapfname); 21 | void set_texture(SharedGLtex texture); 22 | unsigned int get_char_i(char c) const; 23 | SharedGLtex p_texture; 24 | float p_dist; // vzdálenost mezi znaky 25 | Glfchar p_charmap[256]; 26 | unsigned int p_charmap_start; 27 | unsigned int p_charmap_size; 28 | unsigned char p_defaultchar; 29 | }; 30 | 31 | struct Gltline { 32 | std::vector vert; 33 | SharedGLbuf buf; 34 | bool bufUpdated = false; 35 | unsigned int size = 0, isize = 0; // počet vrcholů 36 | float w = 0; // šířka řádku 37 | float color_b[4]; // barva spodní části písmen 38 | float bkgrect[12]; // obdélník na pozadí textu 39 | }; 40 | 41 | class ShaderMng; 42 | 43 | class Gltext { 44 | public: 45 | Gltext() : p_font(0), p_h(0), p_w(0), p_cen_x(0), p_cen_y(0), p_fontsize(0), p_b_bkgrect(false) { } 46 | void init(unsigned int w, unsigned int h, float fontsize, int cen_x, int cen_y, const Glfont* font, 47 | const float color_b[4]); // počet písmen na řádku, počet písmen na výšku, výška znaků, zarovnání znaků, , odkaz na font, barvy 48 | void set_pos(float x, float y); 49 | void set_color(const float color[4]); 50 | void set_color(unsigned int i/*číslo řádku*/, const float color[4]); 51 | void set_bkgrect(const float* color = NULL); 52 | void puts(unsigned int i/*číslo řádku*/, const char* text); 53 | void render(GLuint texture, ShaderMng* shadermng, bool useColor = false, float scale = 1.f); 54 | void render_c(GLuint texture, ShaderMng* shadermng); 55 | void render_c(ShaderMng* shadermng) { render_c(p_font->p_texture, shadermng); } 56 | void renderscale(float scale, GLuint texture, ShaderMng* shadermng); 57 | 58 | glm::mat4 mtrx; 59 | 60 | const Glfont* p_font; // odkaz na font 61 | std::vector p_lines; // řádky 62 | unsigned int p_h; // počet řádků 63 | unsigned int p_w; 64 | int p_cen_x; 65 | int p_cen_y; 66 | float p_fontsize; // výška znaků 67 | 68 | float p_color_bkgrect[4]; 69 | bool p_b_bkgrect; 70 | 71 | std::vector indices; 72 | SharedGLbuf buf; 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/gl_shared.h: -------------------------------------------------------------------------------- 1 | #ifndef GL_SHARED_H 2 | #define GL_SHARED_H 3 | 4 | #include "gl1.h" 5 | #include 6 | #include 7 | //#include 8 | 9 | /* 10 | * Based on Madhu Raykar's 2006 article "Implementing a simple smart pointer in C++" 11 | * Things were way simpler back then... 12 | */ 13 | 14 | template class SharedGLobj 15 | { 16 | private: 17 | class RC 18 | { 19 | private: 20 | uint32_t count; // reference count 21 | 22 | public: 23 | void AddRef() 24 | { 25 | // increment the reference count 26 | count++; 27 | } 28 | 29 | int Release() 30 | { 31 | assert(count > 0); 32 | // decrement the reference count and 33 | // return the reference count. 34 | return --count; 35 | } 36 | }; 37 | 38 | GLuint pData; // OpenGL object name, 0 - no object 39 | RC* reference; // reference count 40 | 41 | void create() 42 | { 43 | if (pData) 44 | { 45 | reference = new RC(); 46 | reference->AddRef(); 47 | //printf("ctor %u\n", pValue); fflush(stdout); 48 | } 49 | } 50 | 51 | void destroy() 52 | { 53 | if (pData) 54 | { 55 | assert(reference); 56 | if (reference->Release() == 0) 57 | { 58 | DelFun(1, &pData); 59 | checkGL(); 60 | delete reference; 61 | //printf("dtor %u\n", pData); fflush(stdout); 62 | } 63 | } 64 | } 65 | 66 | public: 67 | SharedGLobj() : pData(0), reference(nullptr) 68 | { 69 | create(); 70 | } 71 | 72 | SharedGLobj(GLuint pValue) : pData(pValue), reference(nullptr) 73 | { 74 | create(); 75 | } 76 | 77 | SharedGLobj(const SharedGLobj& sp) : pData(sp.pData), reference(sp.reference) 78 | { 79 | if (pData) 80 | { 81 | assert(reference); 82 | reference->AddRef(); 83 | } 84 | } 85 | 86 | ~SharedGLobj() 87 | { 88 | destroy(); 89 | } 90 | 91 | SharedGLobj& operator = (const SharedGLobj& sp) 92 | { 93 | if (this != &sp) // avoid self assignment 94 | { 95 | destroy(); 96 | pData = sp.pData; 97 | reference = sp.reference; 98 | if (pData) 99 | { 100 | assert(reference); 101 | reference->AddRef(); 102 | } 103 | } 104 | return *this; 105 | } 106 | 107 | operator GLuint() const { return pData; } 108 | }; 109 | 110 | using SharedGLtex = SharedGLobj; 111 | using SharedGLbuf = SharedGLobj; 112 | 113 | #endif // GL_SHARED_H 114 | -------------------------------------------------------------------------------- /src/octopus.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_OCTOPUS_H 2 | #define HLIDAC_OCTOPUS_H 3 | 4 | #include "3dm.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "gl_shared.h" 11 | 12 | class Octocm { 13 | public: 14 | std::vector p_i; 15 | SharedGLbuf p_buf; 16 | 17 | void initBuf() 18 | { 19 | GLuint tmpBuf; 20 | glGenBuffers(1, &tmpBuf); 21 | p_buf = tmpBuf; 22 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_buf); 23 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_i.size() * sizeof(GLushort), p_i.data(), GL_STATIC_DRAW); 24 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 25 | } 26 | 27 | unsigned int p_sz = 0; 28 | }; 29 | 30 | class Octopus; 31 | 32 | class Octocube { 33 | public: 34 | Octocube(); 35 | int test(const float modelview_matrix[16]); // 0 - mimo, 1 - plně, 2 - část 36 | void subdiv(); 37 | void count_maxsub(unsigned int* count); 38 | 39 | void render_level_pom(unsigned int lev); 40 | 41 | int render_pass1(const float modelview_matrix[16]); 42 | 43 | std::vector p_mi; // indexy příslušné materiálům 44 | std::unique_ptr p_sub[8]; // tam, kde je 0, nejsou další tris 45 | Octocube* p_up; // předek této octocube 46 | float p_cen[3]; // střed bounding sphere 47 | float p_cen_t[3]; // transformovaný střed (pro sort) 48 | float p_r; // poloměr bounding sphere 49 | float p_a_2; // polovina strany krychle 50 | unsigned int p_lev; // úroveň dělení 51 | Octopus* p_base; // základní předek všech octocube 52 | 53 | unsigned int p_face_num; // počet faců v octocube 54 | }; 55 | 56 | class Octopus { 57 | public: 58 | Octopus() : p_near(0), p_far(0), p_vw(0), p_vw_sz(0), p_t3dm(nullptr), p_m_sz(0), p_min_tris(0), p_max_lev(0) 59 | { 60 | for (int i = 0; i != 2; ++i) 61 | { 62 | p_left[i] = p_right[i] = p_bottom[i] = p_top[i] = 0; 63 | } 64 | } 65 | void init(const float frustum[6], const T3dm& t3dm, unsigned int min_tris, unsigned int max_lev); 66 | void init_frustum(const float frustum[6]); 67 | void render_bbox(); 68 | void render_level(unsigned int lev); 69 | 70 | void render_pass1(const float modelview_matrix[16]); 71 | void render_pass1_lim(const float modelview_matrix[16], unsigned int face_limit); // začátek testování bboxů 72 | //void render_pass2(); 73 | 74 | float p_left[2]; // hranice frustumu 75 | float p_right[2]; 76 | float p_bottom[2]; 77 | float p_top[2]; 78 | float p_near; 79 | float p_far; 80 | std::unique_ptr p_oc; // základní krychle (octocube) 81 | std::vector p_vw; // pole ukazatelů na octocube pro poznamenání nalezených octocube 82 | unsigned int p_vw_sz; // počet nalezených položek 83 | const T3dm* p_t3dm; 84 | unsigned int p_m_sz; // počet materiálů 85 | 86 | unsigned int p_min_tris, p_max_lev; 87 | }; 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/cstring1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool isSpace(int c) 4 | { 5 | return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; 6 | } 7 | 8 | bool isDigit(int c) 9 | { 10 | return c >= '0' && c <= '9'; 11 | } 12 | 13 | bool strSuff(const char* str, const char* suff) 14 | { 15 | if (strlen(str) < strlen(suff)) 16 | return false; 17 | return !strcmp(str+strlen(str)-strlen(suff), suff); 18 | } 19 | 20 | bool strstrtok1(const char* str1, const char* str2) 21 | { 22 | const char* str_pos = str1; 23 | while ((str_pos = strstr(str_pos, str2))) 24 | { 25 | if ((str_pos == str1 || isSpace(*(str_pos-1))) && (isSpace(str_pos[strlen(str2)]) || str_pos[strlen(str2)] == '\0')) 26 | return true; 27 | ++str_pos; 28 | } 29 | return false; 30 | } 31 | 32 | void uncomment(char* str) 33 | { 34 | bool insideString = false; 35 | for (unsigned i = 0; i != strlen(str); ++i) 36 | { 37 | if (str[i] == '"') 38 | { 39 | insideString = !insideString; 40 | } 41 | if (!insideString) 42 | { 43 | if (str[i] == '/' && str[i+1] == '/') 44 | { 45 | str[i] = 0; 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | 52 | void strncat1(char* str_o, const char* str1_i, const char* str2_i, size_t num) 53 | { 54 | bool b1 = true; 55 | unsigned int i = 0; 56 | while (i != num) 57 | { 58 | if (b1) 59 | { 60 | if (*str1_i) 61 | { 62 | *str_o = *str1_i; 63 | ++str_o; 64 | ++str1_i; 65 | } else { 66 | b1 = false; 67 | } 68 | } 69 | if (!b1) 70 | { 71 | if (*str2_i) 72 | { 73 | *str_o = *str2_i; 74 | ++str_o; 75 | ++str2_i; 76 | } else { 77 | *str_o = '\0'; 78 | break; 79 | } 80 | } 81 | ++i; 82 | } 83 | } 84 | 85 | bool strempty(const char* str) 86 | { 87 | for (unsigned int i = 0; i != strlen(str); ++i) 88 | { 89 | if (!isSpace(str[i])) 90 | return false; 91 | } 92 | return true; 93 | } 94 | 95 | char* trim(char* str) 96 | { 97 | char* ret = str; 98 | for (size_t i = 0; i != strlen(str); ++i) 99 | { 100 | //if (str[i] != ' ' && str[i] != '\r' && 101 | if (!isSpace(str[i])) 102 | { 103 | ret = str + i; 104 | break; 105 | } 106 | } 107 | for (size_t i = strlen(ret); i != 0; --i) 108 | { 109 | if (isSpace(ret[i-1])) 110 | { 111 | ret[i-1] = 0; 112 | } 113 | else 114 | { 115 | break; 116 | } 117 | } 118 | return ret; 119 | } 120 | -------------------------------------------------------------------------------- /src/OpenMRac-SDL2.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console c++20 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | TARGET = openmrac 7 | 8 | QMAKE_CXXFLAGS += -fno-exceptions 9 | 10 | QMAKE_CXXFLAGS += -DDIR_OPENMRAC_DAT=/usr/share/openmrac/ 11 | 12 | # disable assert 13 | #QMAKE_CXXFLAGS += -DNDEBUG 14 | 15 | # output test screenshot 16 | #QMAKE_CXXFLAGS += -DTEST_SCRSHOT=0 17 | 18 | # opengl error log 19 | #QMAKE_CXXFLAGS += -DENABLE_CHECKGL=1 20 | 21 | QMAKE_CXXFLAGS += -DUSE_MINIAL 22 | #LIBS += -lopenal 23 | 24 | # libGL 25 | #LIBS += -lSDL2 -lGL -ljpeg -lpng 26 | 27 | # libGLESv2 28 | QMAKE_CXXFLAGS += -DUSE_GLESv2 29 | LIBS += -lSDL2 -lGLESv2 -ljpeg -lpng 30 | 31 | INCLUDEPATH += \ 32 | /usr/include 33 | 34 | SOURCES += \ 35 | 3dm.cpp \ 36 | cam.cpp \ 37 | car2d.cpp \ 38 | collider.cpp \ 39 | controls.cpp \ 40 | cstring1.cpp \ 41 | datkey.cpp \ 42 | dpiaware_win32.cpp \ 43 | fopendir.cpp \ 44 | gameaux.cpp \ 45 | gamemenu.cpp \ 46 | gamemng.cpp \ 47 | gamemng_frame.cpp \ 48 | gamemng_load.cpp \ 49 | gbuff_in.cpp \ 50 | ghost.cpp \ 51 | gltext.cpp \ 52 | gui.cpp \ 53 | guifont.cpp \ 54 | load_texture.cpp \ 55 | main.cpp \ 56 | mainmenu.cpp \ 57 | matmng.cpp \ 58 | minial.cpp \ 59 | octopus.cpp \ 60 | onelayout.cpp \ 61 | particles.cpp \ 62 | pict2.cpp \ 63 | pict2_jpeg.cpp \ 64 | pict2_png.cpp \ 65 | rand1.cpp \ 66 | rbsolver.cpp \ 67 | settings_dat.cpp \ 68 | settingsdialog.cpp \ 69 | shadermng.cpp \ 70 | skysph.cpp \ 71 | soundmng.cpp \ 72 | triboxint.cpp 73 | 74 | HEADERS += \ 75 | 3dm.h \ 76 | appdefs.h \ 77 | bits.h \ 78 | cam.h \ 79 | car2d.h \ 80 | collider.h \ 81 | controls.h \ 82 | cstring1.h \ 83 | datkey.h \ 84 | error_msg.h \ 85 | fopendir.h \ 86 | gameaux.h \ 87 | gamemng.h \ 88 | gbuff_in.h \ 89 | ghost.h \ 90 | gl1.h \ 91 | gl_shared.h \ 92 | glm1.h \ 93 | gltext.h \ 94 | gui.h \ 95 | load_texture.h \ 96 | mainmenu.h \ 97 | matmng.h \ 98 | minial.h \ 99 | octopus.h \ 100 | onelayout.h \ 101 | particles.h \ 102 | pict2.h \ 103 | rand1.h \ 104 | rbsolver.h \ 105 | settings_dat.h \ 106 | settingsdialog.h \ 107 | shadermng.h \ 108 | shaders/car.fs.h \ 109 | shaders/car.vs.h \ 110 | shaders/car_top.fs.h \ 111 | shaders/car_top.vs.h \ 112 | shaders/color.fs.h \ 113 | shaders/color.vs.h \ 114 | shaders/color_tex.fs.h \ 115 | shaders/color_tex.vs.h \ 116 | shaders/glass_reflection.fs.h \ 117 | shaders/glass_reflection.vs.h \ 118 | shaders/glass_tint.fs.h \ 119 | shaders/glass_tint.vs.h \ 120 | shaders/light_tex.fs.h \ 121 | shaders/light_tex.vs.h \ 122 | shaders/light_tex_sunk.fs.h \ 123 | shaders/light_tex_sunk.vs.h \ 124 | shaders/tex.fs.h \ 125 | shaders/tex.vs.h \ 126 | skysph.h \ 127 | soundmng.h \ 128 | triboxint.h 129 | -------------------------------------------------------------------------------- /src/ghost.cpp: -------------------------------------------------------------------------------- 1 | #include "ghost.h" 2 | #include "fopendir.h" 3 | #include "appdefs.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Ghost::Ghost(bool frames) { 9 | m_version = 104; 10 | m_track = 0; 11 | m_reverse = 0; 12 | m_car = 0; 13 | m_carcolor = 0; 14 | m_seconds = 0; 15 | m_maxnum = 1800; 16 | m_num = 0; 17 | m_frames.resize(frames ? m_maxnum*4 : 0); 18 | } 19 | 20 | bool Ghost::load(int track, int reverse) { 21 | m_track = track; 22 | m_reverse = reverse; 23 | char filename[1024]; 24 | getfname(filename); 25 | std::unique_ptr fin(fopenDir(filename, "rb", OPENMRAC_ORG, OPENMRAC_APP), &fclose); 26 | if (fin.get() == nullptr) return false; 27 | if (fread(&m_version, sizeof(int), 1, fin.get()) != 1) return false; 28 | if (m_version != 104) return false; 29 | if (fread(&m_track, sizeof(int), 1, fin.get()) != 1) return false; 30 | if (m_track != track) return false; 31 | if (fread(&m_reverse, sizeof(int), 1, fin.get()) != 1) return false; 32 | if (m_reverse != reverse) return false; 33 | if (fread(&m_car, sizeof(int), 1, fin.get()) != 1) return false; 34 | if (m_car < 0 || m_car >= 3) return false; 35 | if (fread(&m_carcolor, sizeof(int), 1, fin.get()) != 1) return false; 36 | if (m_carcolor < 0 || m_carcolor >= 4) return false; 37 | if (fread(&m_seconds, sizeof(float), 1, fin.get()) != 1) return false; 38 | if (m_seconds < 10.0 || m_seconds > 31536000.0) return false; 39 | if (!m_frames.empty()) 40 | { 41 | if (fread(&m_num, sizeof(int), 1, fin.get()) != 1) return false; 42 | if (m_num < 0 || m_num > m_maxnum) return false; 43 | if (static_cast(fread(m_frames.data(), sizeof(float)*4, m_num, fin.get())) != m_num) return false; 44 | } 45 | return true; 46 | } 47 | 48 | void Ghost::save() { 49 | char filename[1024]; 50 | getfname(filename); 51 | FILE* fout = fopenDir(filename, "wb", OPENMRAC_ORG, OPENMRAC_APP); 52 | if (fout == NULL) return; 53 | fwrite(&m_version, sizeof(int), 1, fout); 54 | fwrite(&m_track, sizeof(int), 1, fout); 55 | fwrite(&m_reverse, sizeof(int), 1, fout); 56 | fwrite(&m_car, sizeof(int), 1, fout); 57 | fwrite(&m_carcolor, sizeof(int), 1, fout); 58 | fwrite(&m_seconds, sizeof(float), 1, fout); 59 | if (!m_frames.empty()) 60 | { 61 | fwrite(&m_num, sizeof(int), 1, fout); 62 | fwrite(m_frames.data(), sizeof(float)*4, m_num, fout); 63 | } 64 | fclose(fout); 65 | } 66 | 67 | void Ghost::getfname(char* buff) { // 1024 bajtů 68 | buff[1023] = 0; 69 | const char* filenames[4] = {"speedway", "boulevard", "suburb", "ironworks"}; 70 | snprintf(buff, 1023, "%s%s.mrr", filenames[m_track], m_reverse ? "-rev" : ""); 71 | } 72 | 73 | void Ghost::copyFrom(const Ghost& gnew) { 74 | m_version = gnew.m_version; 75 | m_track = gnew.m_track; 76 | m_reverse = gnew.m_reverse; 77 | m_car = gnew.m_car; 78 | m_carcolor = gnew.m_carcolor; 79 | m_seconds = gnew.m_seconds; 80 | m_maxnum = gnew.m_maxnum; 81 | if (m_frames.empty() || gnew.m_frames.empty()) 82 | { 83 | m_num = 0; 84 | } 85 | else 86 | { 87 | m_num = gnew.m_num; 88 | std::copy_n(gnew.m_frames.begin(), m_num * 4, m_frames.begin()); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/settingsdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSDIALOG_H 2 | #define SETTINGSDIALOG_H 3 | 4 | #include "gui.h" 5 | #include "onelayout.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct ScreenMode 12 | { 13 | ScreenMode(int w, int h, int f) : 14 | width(w), height(h), fullscreen(f) 15 | { 16 | } 17 | int width; 18 | int height; 19 | int fullscreen; 20 | 21 | bool operator<(const ScreenMode& other) const 22 | { 23 | if (width < other.width) 24 | return true; 25 | if (width > other.width) 26 | return false; 27 | if (height < other.height) 28 | return true; 29 | if (height > other.height) 30 | return false; 31 | if (fullscreen < other.fullscreen) 32 | return true; 33 | return false; 34 | } 35 | 36 | bool operator==(const ScreenMode& other) const 37 | { 38 | return width == other.width && height == other.height && fullscreen == other.fullscreen; 39 | } 40 | 41 | std::string getAspectRatioString() const 42 | { 43 | int ratioWs[] = {5,4,16,16}; 44 | int ratioHs[] = {4,3,10,9}; 45 | for (int i = 0; i != 4; ++i) 46 | { 47 | if (width * ratioHs[i] == height * ratioWs[i]) 48 | { 49 | char buff[64] = {0}; 50 | snprintf(buff, 63, "(%d:%d) ", ratioWs[i], ratioHs[i]); 51 | return buff; 52 | } 53 | } 54 | return ""; 55 | } 56 | }; 57 | 58 | class SettingsDialog : public GuiDialog 59 | { 60 | public: 61 | SettingsDialog( 62 | int renderer, 63 | const std::vector& screenModes, 64 | ScreenMode currentScreenModeIndex, 65 | ScreenMode defaultScreenModeIndex, 66 | bool currentVsyncState, 67 | int currentAntialiasingMode, 68 | int currentTextureFilter, 69 | bool currentFpsState, 70 | const std::vector& openalDevices, 71 | const char* currentOpenalDevice, 72 | int currentRateIndex, 73 | bool lowLatency, 74 | bool minial 75 | ); 76 | 77 | virtual void onQuit(); 78 | virtual void onButton(int itemIndex); 79 | virtual void onKeyDown(SDL_Keycode k); 80 | virtual void onKeyUp(SDL_Keycode k); 81 | 82 | int getRenderer(); 83 | int getSelectedScreenMode() const; 84 | bool getVsyncChecked() const; 85 | int getAntialiasingMode() const; 86 | int getTextureFilter() const; 87 | bool getShowFpsChecked() const; 88 | const char* getOpenalDevice() const; 89 | int getFreqIndex() const; 90 | bool getLowLatencyChecked() const; 91 | 92 | bool m_continue; // pokračovat v programu? 93 | 94 | private: 95 | OneLayout m_horLay; 96 | OneLayout m_horBtnLay; 97 | OneLayout m_verLay; 98 | 99 | int m_defaultScreenModeIndex; 100 | std::vector m_openalDevices; 101 | 102 | // gui item indices 103 | int m_rendererComboIndex; 104 | int m_resolutionsComboIndex; 105 | int m_vsyncIndex; 106 | int m_antialiasingIndex; 107 | int m_textureFilterIndex; 108 | int m_showFpsIndex; 109 | int m_audioDevicesComboIndex; 110 | int m_freqComboIndex; 111 | int m_lowLatencyIndex; 112 | int m_okButtonIndex; 113 | int m_cancelButtonIndex; 114 | int m_defaultsButtonIndex; 115 | 116 | bool m_returnPressed; 117 | bool m_enterPressed; 118 | bool m_escPressed; 119 | }; 120 | 121 | #endif // SETTINGSDIALOG_H 122 | -------------------------------------------------------------------------------- /src/matmng.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_MATMNG_H 2 | #define HLIDAC_MATMNG_H 3 | 4 | #include "3dm.h" 5 | #include "octopus.h" 6 | #include "pict2.h" 7 | #include "glm1.h" 8 | #include "gl1.h" 9 | #include "gl_shared.h" 10 | #include 11 | 12 | class Transf { 13 | public: 14 | void init(unsigned int i_from, unsigned int i_size) 15 | { 16 | p_ibegin = i_from; 17 | p_iend = i_from+i_size; 18 | p_mwmx.clear(); p_mwmx.resize(i_size); 19 | } 20 | void set_mwmx(const glm::mat4& mwmx, unsigned int i_pos) 21 | { 22 | if (i_pos >= p_ibegin && i_pos < p_iend) 23 | { 24 | p_mwmx[i_pos-p_ibegin] = mwmx; 25 | } 26 | } 27 | glm::mat4 mult_mwmx(unsigned int i_pos) const 28 | { 29 | // get multiplication matrix for sub-object 30 | if (i_pos >= p_ibegin && i_pos < p_iend) 31 | { 32 | return p_mwmx[i_pos-p_ibegin]; 33 | } 34 | return glm::mat4(1); 35 | } 36 | 37 | unsigned int p_ibegin = 0; 38 | unsigned int p_iend = 0; 39 | std::vector p_mwmx; 40 | }; 41 | 42 | class Mat { 43 | public: 44 | Mat() : balpha_test(false), benv_map(false), bboth_side(false), blighting(false), bmipmap(false), bsunken(false), special(0) { texd_name[0] = 0; texa_name[0] = 0; sund_name[0] = 0; suna_name[0] = 0; } 45 | void load(const char* fname); 46 | void default_mat(); 47 | void setgl(); 48 | 49 | SharedGLtex texture; // id textury 50 | SharedGLtex texsunk; // id sunken textury 51 | bool balpha_test; // alfa test 52 | bool benv_map; // mapa prostředí 53 | bool bboth_side; // oboustranný materiál 54 | bool blighting; 55 | bool bmipmap; // 56 | bool bsunken; 57 | char texd_name[256]; // název difuzní textury 58 | char texa_name[256]; // název alfa textury 59 | char sund_name[256]; // název barvy sunken textury 60 | char suna_name[256]; // název alpha sunken textury 61 | int special; // zároveň bspecial; 0 - nothing, 1 - two-sided top car part, 2 - blended (fence around Speedway), 3 - shadow 62 | float color[4]; 63 | }; 64 | 65 | class Matmng { 66 | public: 67 | void load(const T3dm* t3dm); 68 | const T3dm* p_t3dm = nullptr; 69 | std::vector p_mat; 70 | }; 71 | 72 | class Gamemng; 73 | 74 | class Rendermng { 75 | public: 76 | Rendermng() : p_t3dm(0), p_matmng(0), p_octopus(0), p_boctocube(false), b_visible(false), p_transf(0) { } 77 | void init(Gamemng* gamemng, const T3dm* t3dm, const Matmng* matmng, Octopus* octopus = 0); 78 | void set_oc(const float frustum[6], const T3dm& t3dm); // nastaví jednotlivou octocube (asi) 79 | void set_transf(const Transf* transf) { p_transf = transf; } 80 | void render_o_pass1(const float* modelview_matrix); 81 | void render_o_pass1_lim(const float* modelview_matrix, unsigned int face_limit); 82 | void render_o_pass2(const glm::mat4& m); 83 | void render_o_pass_glassTint(const glm::mat4& m); 84 | void render_o_pass_glassReflection(const glm::mat4& m); 85 | void render_o_pass3(); 86 | void render_o_pass_s2(); 87 | void render_o_pass_s3(); 88 | bool isVisible() const 89 | { 90 | return !(p_boctocube && !b_visible); 91 | } 92 | const T3dm* p_t3dm; 93 | const Matmng* p_matmng; 94 | Gamemng* p_gamemng; 95 | Octopus* p_octopus; // pokud == 0 -> nepoužito 96 | bool p_boctocube; 97 | Octocube p_octocube; 98 | bool b_visible; 99 | Octopus p_octocube_base; 100 | SharedGLtex p_skycmtex; 101 | const Transf* p_transf; 102 | }; 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/triboxint.cpp: -------------------------------------------------------------------------------- 1 | float det3(const float c0[3], const float c1[3], const float c2[3]) 2 | { 3 | return c0[0]*c1[1]*c2[2]+c0[1]*c1[2]*c2[0]+c0[2]*c1[0]*c2[1] 4 | -c2[0]*c1[1]*c0[2]-c2[1]*c1[2]*c0[0]-c2[2]*c1[0]*c0[1]; 5 | } 6 | 7 | void intersect3pl(float res[3], const float A[3], const float p[3], const float q[3], const float X[3], const float v[3]) 8 | { 9 | float det_b = det3(p, q, v); // tady je minus, i tam, takze se to zkrati 10 | float XmA[3] = {X[0]-A[0], X[1]-A[1], X[2]-A[2]}; 11 | res[0] = det3(XmA, q, v)/det_b; 12 | res[1] = det3(p, XmA, v)/det_b; 13 | res[2] = -det3(p, q, XmA)/det_b; 14 | } 15 | 16 | bool isintquad(const float fv[3]) 17 | { 18 | return fv[0] >= 0.f && fv[0] <= 1.f && fv[1] >= 0.f && fv[1] <= 1.f && fv[2] >= 0.f && fv[2] <= 1.f; 19 | } 20 | 21 | bool isinttri(const float fv[3]) 22 | { 23 | return isintquad(fv) && fv[0]+fv[1] <= 1.f; 24 | } 25 | 26 | bool triboxint2(const float boxcen[3], const float a_2[3], const float v0[3], const float v1[3], const float v2[3]) 27 | { 28 | float mincoord[3]; 29 | float maxcoord[3]; 30 | for (int i = 0; i != 3; ++i) 31 | { 32 | mincoord[i] = boxcen[i]-a_2[i]; 33 | maxcoord[i] = boxcen[i]+a_2[i]; 34 | 35 | // optimalizace - hned na začátku se vyhážou trojúhelníky úplně mimo 36 | if (v0[i] > maxcoord[i] && v1[i] > maxcoord[i] && v2[i] > maxcoord[i]) 37 | return false; 38 | if (v0[i] < mincoord[i] && v1[i] < mincoord[i] && v2[i] < mincoord[i]) 39 | return false; 40 | } 41 | // testují se vrcholy trojúhelníků na přítomnost v krychli 42 | if ((v0[0] <= maxcoord[0] && v0[0] >= mincoord[0] 43 | && v0[1] <= maxcoord[1] && v0[1] >= mincoord[1] 44 | && v0[2] <= maxcoord[2] && v0[2] >= mincoord[2]) || 45 | (v1[0] <= maxcoord[0] && v1[0] >= mincoord[0] 46 | && v1[1] <= maxcoord[1] && v1[1] >= mincoord[1] 47 | && v1[2] <= maxcoord[2] && v1[2] >= mincoord[2]) || 48 | (v2[0] <= maxcoord[0] && v2[0] >= mincoord[0] 49 | && v2[1] <= maxcoord[1] && v2[1] >= mincoord[1] 50 | && v2[2] <= maxcoord[2] && v2[2] >= mincoord[2])) 51 | return true; 52 | 53 | // test průniku hran trojúhelníku se stěnami krychle 54 | 55 | float quadv0[3] = {maxcoord[0]-mincoord[0], 0, 0}; // vektory pro použití ve čtvercích 56 | float quadv1[3] = {0, maxcoord[1]-mincoord[1], 0}; 57 | float quadv2[3] = {0, 0, maxcoord[2]-mincoord[2]}; 58 | float quadp0[3] = {mincoord[0], mincoord[1], mincoord[2]}; // rohy čtverců 59 | float quadp1[3] = {maxcoord[0], mincoord[1], mincoord[2]}; 60 | float quadp2[3] = {mincoord[0], maxcoord[1], mincoord[2]}; 61 | float quadp3[3] = {mincoord[0], mincoord[1], maxcoord[2]}; 62 | 63 | float* quads_p [6] = {quadp0, quadp0, quadp0, quadp1, quadp2, quadp3}; // definice všech čtverců 64 | float* quads_v0[6] = {quadv1, quadv0, quadv0, quadv1, quadv0, quadv0}; 65 | float* quads_v1[6] = {quadv2, quadv2, quadv1, quadv2, quadv2, quadv1}; 66 | 67 | float triv0[3] = {v1[0]-v0[0], v1[1]-v0[1], v1[2]-v0[2]}; // vektory linek trojůhelníku 68 | float triv1[3] = {v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2]}; 69 | float triv2[3] = {v0[0]-v2[0], v0[1]-v2[1], v0[2]-v2[2]}; 70 | 71 | const float* trilines_p[3] = {v0, v1, v2}; 72 | float* trilines_v[3] = {triv0, triv1, triv2}; 73 | 74 | for (int i = 0; i != 6; ++i) 75 | for (int j = 0; j != 3; ++j) 76 | { 77 | float int_res[3]; 78 | intersect3pl(int_res, quads_p[i], quads_v0[i], quads_v1[i], trilines_p[j], trilines_v[j]); 79 | if (isintquad(int_res)) 80 | return true; 81 | } 82 | 83 | return false; 84 | } 85 | -------------------------------------------------------------------------------- /src/gl1.h: -------------------------------------------------------------------------------- 1 | #ifndef GL1_H 2 | #define GL1_H 3 | 4 | #define PROFILE_COMPAT 0 5 | #define PROFILE_ES2 1 6 | #define PROFILE_CORE33 2 7 | 8 | #ifdef USE_GLESv2 9 | #define PROFILE_MIN PROFILE_ES2 10 | #define PROFILE_MAX PROFILE_ES2 11 | #else 12 | #define PROFILE_MIN PROFILE_COMPAT 13 | #define PROFILE_MAX PROFILE_CORE33 14 | #endif 15 | 16 | #if defined(__WIN32__) 17 | 18 | //#define GLEW_STATIC 19 | #include 20 | 21 | inline bool initGlExt(void) 22 | { 23 | //glewExperimental = 1; // If using GLEW version 1.13 or earlier 24 | return glewInit() == GLEW_OK; 25 | } 26 | 27 | #define GLEXT_ERROR_MESSAGE "glewInit error" 28 | 29 | // GLES2 did not work on windows 30 | #define DEFAULT_PROFILE PROFILE_COMPAT 31 | 32 | #define GLDEBUG_APIENTRY __attribute__((stdcall)) 33 | 34 | #else 35 | 36 | #if USE_GLESv2 37 | #include 38 | #else 39 | #define GL_GLEXT_PROTOTYPES 40 | #include 41 | #endif 42 | 43 | inline bool initGlExt(void) 44 | { 45 | return true; 46 | } 47 | 48 | #define GLEXT_ERROR_MESSAGE "" 49 | 50 | #define DEFAULT_PROFILE PROFILE_ES2 51 | 52 | #define GLDEBUG_APIENTRY APIENTRY 53 | 54 | #endif // __WIN32__ 55 | 56 | #define ENABLE_GLDEBUG 0 57 | #define ENABLE_glslangValidator 0 58 | 59 | extern int g_opengl_profile; 60 | 61 | inline void glDepthRange1(float a, float b) 62 | { 63 | #ifdef USE_GLESv2 64 | glDepthRangef(a, b); 65 | #else 66 | if (g_opengl_profile == PROFILE_ES2) 67 | glDepthRangef(a, b); 68 | else 69 | glDepthRange(a, b); 70 | #endif 71 | } 72 | 73 | #undef glDepthRangef 74 | #define glDepthRangef use_glDepthRange1_instead_of_glDepthRangef 75 | #undef glDepthRange 76 | #define glDepthRange use_glDepthRange1_instead_of_glDepthRange 77 | 78 | inline void glDeleteBuffers1(GLsizei n, const GLuint * buffers) 79 | { 80 | // workaround for GLEW (win32), no harm on other platforms 81 | glDeleteBuffers(n, buffers); 82 | } 83 | 84 | #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY 85 | #define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF 86 | #endif 87 | #ifndef GL_TEXTURE_MAX_ANISOTROPY 88 | #define GL_TEXTURE_MAX_ANISOTROPY 0x84FE 89 | #endif 90 | 91 | #define ASSERT_ANISOTROPY 92 | 93 | #if ENABLE_CHECKGL 94 | #include 95 | #include 96 | 97 | #define checkGL_case(a) case a: fprintf(stderr, "gl err %s (0x%x)\n", #a, a); break 98 | 99 | inline void checkGL() 100 | { 101 | GLenum err = glGetError(); 102 | //assert(err == GL_NO_ERROR); 103 | if (err != GL_NO_ERROR) 104 | { 105 | switch (err) 106 | { 107 | checkGL_case(GL_INVALID_OPERATION); 108 | checkGL_case(GL_INVALID_ENUM); 109 | checkGL_case(GL_INVALID_VALUE); 110 | default: fprintf(stderr, "gl err %u (0x%x)\n", err, err); break; 111 | } 112 | fflush(stderr); 113 | } 114 | } 115 | 116 | #undef checkGL_case 117 | 118 | #else 119 | inline void checkGL() { } 120 | #endif 121 | 122 | extern int g_multisampleMode; 123 | 124 | /* 125 | inline void setStandardAlphaTest(bool enable) 126 | { 127 | #if !defined(__MACOSX__) && !defined(__MORPHOS__) 128 | if (g_multisampleMode) 129 | { 130 | if (enable) 131 | { 132 | glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); 133 | checkGL(); 134 | } 135 | else 136 | { 137 | glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); 138 | checkGL(); 139 | } 140 | } 141 | else 142 | #endif 143 | { 144 | if (enable) 145 | { 146 | glEnable(GL_ALPHA_TEST); 147 | checkGL(); 148 | } 149 | else 150 | { 151 | glDisable(GL_ALPHA_TEST); 152 | checkGL(); 153 | } 154 | } 155 | } 156 | */ 157 | 158 | #endif // GL1_H 159 | -------------------------------------------------------------------------------- /src/soundmng.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_SOUNDMNG_H 2 | #define HLIDAC_SOUNDMNG_H 3 | 4 | #include 5 | 6 | #ifdef USE_MINIAL 7 | #include "minial.h" 8 | #else 9 | #include 10 | #endif 11 | 12 | #include 13 | 14 | #if SDL_BYTEORDER == SDL_LIL_ENDIAN 15 | inline void swapArrayLE16(unsigned char* , unsigned int ) 16 | { 17 | // do nothing 18 | } 19 | #else 20 | inline void swapArrayLE16(unsigned char* data, unsigned int size) 21 | { 22 | short* shortData = reinterpret_cast(data); 23 | unsigned int count = size / 2; 24 | for (unsigned int i = 0; i != count; ++i) 25 | { 26 | shortData[i] = SDL_SwapLE16(shortData[i]); 27 | } 28 | } 29 | #endif 30 | 31 | inline void tweakLoop(unsigned char* data, unsigned int size) 32 | { 33 | short* shortData = reinterpret_cast(data); 34 | unsigned int count = size / 2; 35 | float first = shortData[1]; 36 | float last = shortData[count - 2]; 37 | shortData[0] = first + (last - first) * 0.3; 38 | shortData[count - 1] = last + (first - last) * 0.3; 39 | } 40 | 41 | typedef ALuint ALbuffer; 42 | typedef ALuint ALsource; 43 | 44 | class Sound_game_static { 45 | public: 46 | Sound_game_static() { 47 | for (int i = 0; i != 4; ++i) 48 | { 49 | p_skid_stream[i] = 0; 50 | p_engine0_stream[i] = 0; 51 | p_engine1_stream[i] = 0; 52 | } 53 | for (int i = 0; i != 10; ++i) 54 | p_hit_stream[i] = 0; 55 | p_test_stream = 0; 56 | p_skid_sample = 0; 57 | p_hit_sample[0] = 0; 58 | p_hit_sample[1] = 0; 59 | } 60 | 61 | void init(); 62 | void load(unsigned int i, ALbuffer p_engine0_sample, ALbuffer p_engine1_sample); 63 | 64 | ALsource p_skid_stream[4]; 65 | ALsource p_engine0_stream[4]; 66 | ALsource p_engine1_stream[4]; 67 | ALsource p_hit_stream[10]; 68 | 69 | ALsource p_test_stream; 70 | 71 | ALbuffer p_skid_sample; 72 | ALbuffer p_hit_sample[2]; 73 | 74 | void playSoundTest(float); 75 | }; 76 | 77 | class Sound_car { 78 | public: 79 | Sound_car() : p_skid_stream(0), p_engine0_stream(0), p_engine1_stream(0), p_engine0_state(0), p_engine1_state(0), p_skid_state(0), p_time(0), 80 | p_T(0), p_running_pitch(0), p_pan(0), p_player(0), p_brake_volume(0), p_engine_on(0), p_global_volume(0) { } 81 | void init(ALsource stream_idle, ALsource stream_running, float running_pitch, ALsource stream_skid, int player, int players_n); 82 | void frame(float deltaT, int engine_state/*0 - nultý, 1 - první, 2 - první potichu*/, float engine_pitch, const float velocity[2]); 83 | void stop(); 84 | ALsource p_skid_stream; 85 | ALsource p_engine0_stream; 86 | ALsource p_engine1_stream; 87 | int p_engine0_state; // 0 - nehraje, 1 - hraje 88 | int p_engine1_state; // 0 - nehraje, 1 - hraje 89 | int p_skid_state; // 0 - nehraje, 1 - hraje 90 | float p_time; // aktualizace každých 100 ms 91 | float p_T; // 100 ms 92 | float p_running_pitch; // tón základního zvuku běžícího motoru 93 | int p_pan; // -1 vlevo, 0 střed, 1 vpravo 94 | int p_player; 95 | float p_brake_volume; 96 | int p_engine_on; 97 | const float* p_global_volume; 98 | }; 99 | 100 | class Sound_crash { 101 | public: 102 | Sound_crash() { p_sz_samples = 2; p_width = 5; p_global_volume = 0; p_hit_stream = 0; p_fronta_pos[0] = 0; p_fronta_pos[1] = 0; } 103 | void init(ALsource* stream_hit); // load zvuků 104 | void play(float c_j); // přehraje zvuk nárazu 105 | int p_sz_samples; 106 | int p_width; // šířka fronty 107 | ALsource* p_hit_stream; 108 | int p_fronta_pos[10]; // stačí 2 109 | 110 | const float* p_global_volume; 111 | // n = 3 112 | // f = 5 113 | // samply[n] 114 | // fronty[f*n] 115 | // fronty_i[n] 116 | }; 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /src/skysph.cpp: -------------------------------------------------------------------------------- 1 | #include "skysph.h" 2 | #include "gamemng.h" 3 | #include 4 | #include "gl1.h" 5 | 6 | /* orientace úhlu */ 7 | /* 8 | +------- x 9 | | 10 | | 11 | | 12 | z -> ang 13 | */ 14 | 15 | void Skysph::init(Gamemng* gamemng, float r_prm, float ang_prm, int h, int v) // úhel ve stupních 16 | { 17 | p_gamemng = gamemng; 18 | 19 | vert.clear(); 20 | tris.clear(); 21 | 22 | float ah = ang_prm/180.f*M_PI; 23 | float av = M_PI*0.25f; 24 | light_pos[0] = sinf(ah)*cosf(av); 25 | light_pos[1] = sinf(av); 26 | light_pos[2] = cosf(ah)*cosf(av); 27 | light_pos[3] = 0.f; 28 | r = r_prm; 29 | ang = ang_prm; 30 | size = v*(h)*4; 31 | for (int y = 0; y != v; ++y) 32 | { 33 | for (int x = 0; x != h+1; ++x) 34 | { 35 | float uhel_h = ang/180.f*M_PI+M_PI*2.f/float(h)*float(x)+M_PI; 36 | float uhel_v = (-M_PI/2.f)/10.f+(M_PI/2.f)*1.1/float(v)*float(y); 37 | vert.push_back(sinf(uhel_h)*cosf(uhel_v)*r); 38 | vert.push_back(sinf(uhel_v)*r); 39 | vert.push_back(cosf(uhel_h)*cosf(uhel_v)*r); 40 | vert.push_back(float(x)/float(h)); 41 | vert.push_back(float(uhel_v/M_PI*2.f*2.f)); 42 | int y1 = y+1; 43 | int x1 = (x+1);//%h; 44 | if (x != h) 45 | { 46 | if (y1 == v) 47 | { 48 | tris.push_back(v*(h+1)); 49 | tris.push_back(x1+y*(h+1)); 50 | tris.push_back(x+y*(h+1)); 51 | } else { 52 | tris.push_back(x+y1*(h+1)); 53 | tris.push_back(x1+y1*(h+1)); 54 | tris.push_back(x1+y*(h+1)); 55 | 56 | tris.push_back(x+y1*(h+1)); 57 | tris.push_back(x1+y*(h+1)); 58 | tris.push_back(x+y*(h+1)); 59 | } 60 | } 61 | } 62 | } 63 | vert.push_back(0.f); 64 | vert.push_back(r); 65 | vert.push_back(0.f); 66 | vert.push_back(0.5f); 67 | vert.push_back(1.f); 68 | 69 | GLuint tmpBuf; 70 | glGenBuffers(1, &tmpBuf); 71 | arrayBuf = tmpBuf; 72 | glGenBuffers(1, &tmpBuf); 73 | elemBuf = tmpBuf; 74 | 75 | glBindBuffer(GL_ARRAY_BUFFER, arrayBuf); 76 | glBufferData(GL_ARRAY_BUFFER, vert.size() * sizeof(float), vert.data(), GL_STATIC_DRAW); 77 | 78 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elemBuf); 79 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, tris.size() * sizeof(uint16_t), tris.data(), GL_STATIC_DRAW); 80 | 81 | glBindBuffer(GL_ARRAY_BUFFER, 0); 82 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 83 | } 84 | 85 | void Skysph::render(const glm::mat4& sky_mat) 86 | { 87 | p_gamemng->p_shadermng.use(ShaderId::Tex); 88 | p_gamemng->p_shadermng.set(ShaderUniMat4::ModelViewMat, sky_mat); 89 | 90 | glDepthRange1(1, 1); checkGL(); 91 | glDepthFunc(GL_LEQUAL); checkGL(); 92 | 93 | glBindTexture(GL_TEXTURE_2D, tex_sky); checkGL(); 94 | 95 | glBindBuffer(GL_ARRAY_BUFFER, arrayBuf); 96 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elemBuf); 97 | 98 | glEnableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 99 | glVertexAttribPointer((GLuint)ShaderAttrib::Pos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0); checkGL(); 100 | 101 | glEnableVertexAttribArray((GLuint)ShaderAttrib::Tex); checkGL(); 102 | glVertexAttribPointer((GLuint)ShaderAttrib::Tex, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(sizeof(float)*3)); checkGL(); 103 | 104 | glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_SHORT, 0); checkGL(); 105 | 106 | glDisableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 107 | glDisableVertexAttribArray((GLuint)ShaderAttrib::Tex); checkGL(); 108 | 109 | glBindBuffer(GL_ARRAY_BUFFER, 0); 110 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 111 | 112 | glDepthFunc(GL_LESS); checkGL(); 113 | glDepthRange1(0, 1); checkGL(); 114 | } 115 | -------------------------------------------------------------------------------- /src/controls.cpp: -------------------------------------------------------------------------------- 1 | #include "controls.h" 2 | 3 | /* return value: 4 | * -2 +- 5 | * -1 0- 6 | * 0 none 7 | * 1 0+ 8 | * 2 -+ 9 | */ 10 | int AxisState::updateState(Sint16 value, bool enterMode) 11 | { 12 | int position = convertValue(value); 13 | if (position >= -1 && position <= 1) 14 | { 15 | lastPosition = position; 16 | } 17 | if (enterMode) 18 | { 19 | if (state == E_INITIAL_NONE) 20 | { 21 | if (position == -1) 22 | { 23 | state = E_INITIAL_NEGATIVE; 24 | } 25 | else if (position == 0) 26 | { 27 | state = E_INITIAL_ZERO; 28 | } 29 | else if (position == 1) 30 | { 31 | state = E_INITIAL_POSITIVE; 32 | } 33 | } 34 | else if (state == E_INITIAL_ZERO) 35 | { 36 | if (position == 1) 37 | { 38 | return 1; 39 | } 40 | else if (position == -1) 41 | { 42 | return -1; 43 | } 44 | } 45 | else if (state == E_INITIAL_POSITIVE) 46 | { 47 | if (position == 0) 48 | { 49 | state = E_ENTER_NEGATIVE; 50 | } 51 | } 52 | else if (state == E_INITIAL_NEGATIVE) 53 | { 54 | if (position == 0) 55 | { 56 | state = E_ENTER_POSITIVE; 57 | } 58 | } 59 | else if (state == E_ENTER_POSITIVE) 60 | { 61 | if (position == 1) 62 | { 63 | return 2; 64 | } 65 | } 66 | else if (state == E_ENTER_NEGATIVE) 67 | { 68 | if (position == -1) 69 | { 70 | return -2; 71 | } 72 | } 73 | } 74 | else 75 | { 76 | if (position == -1) 77 | { 78 | state = E_INITIAL_NEGATIVE; 79 | } 80 | else if (position == 0) 81 | { 82 | state = E_INITIAL_ZERO; 83 | } 84 | else if (position == 1) 85 | { 86 | state = E_INITIAL_POSITIVE; 87 | } 88 | } 89 | return 0; 90 | } 91 | 92 | void AxisState::resetEnterMode() 93 | { 94 | if (lastPosition == -1) 95 | { 96 | state = E_INITIAL_NEGATIVE; 97 | } 98 | else if (lastPosition == 0) 99 | { 100 | state = E_INITIAL_ZERO; 101 | } 102 | else if (lastPosition == 1) 103 | { 104 | state = E_INITIAL_POSITIVE; 105 | } 106 | } 107 | 108 | int AxisState::convertValue(Sint16 value) // -1, 0, 1 ... -, center, +; -2 ... undefined 109 | { 110 | if (value < -24576) 111 | { 112 | return -1; 113 | } 114 | else if (value > -8192 && value < 8192) 115 | { 116 | return 0; 117 | } 118 | else if (value > 24576) 119 | { 120 | return 1; 121 | } 122 | else 123 | { 124 | return -2; 125 | } 126 | } 127 | 128 | void JoystickDevice::open(int index) 129 | { 130 | device = SDL_JoystickOpen(index); 131 | identifier.parameters.name = SDL_JoystickName(device); 132 | identifier.parameters.axes = SDL_JoystickNumAxes(device); 133 | identifier.parameters.balls = SDL_JoystickNumBalls(device); 134 | identifier.parameters.hats = SDL_JoystickNumHats(device); 135 | identifier.parameters.buttons = SDL_JoystickNumButtons(device); 136 | identifier.parametersIndex = -1; 137 | axesStates.resize(identifier.parameters.axes); 138 | } 139 | 140 | void JoystickDevice::close() 141 | { 142 | if (device) 143 | { 144 | SDL_JoystickClose(device); 145 | } 146 | } 147 | 148 | void initializeParametersIndices(std::vector& devices) 149 | { 150 | for (unsigned i = 0; i != devices.size(); ++i) 151 | { 152 | int index = 0; 153 | if (devices[i].identifier.parametersIndex == -1) 154 | { 155 | for (unsigned j = i; j != devices.size(); ++j) 156 | { 157 | if (devices[i].identifier.parameters == devices[j].identifier.parameters) 158 | { 159 | devices[j].identifier.parametersIndex = index; 160 | } 161 | } 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/gbuff_in.cpp: -------------------------------------------------------------------------------- 1 | #include "gbuff_in.h" 2 | 3 | Gbuff_in gbuff_in; 4 | 5 | bool Gbuff_in::init_dat(const char* fname) 6 | { 7 | p_bdat = true; 8 | return p_datdec.init(fname); 9 | } 10 | 11 | void Gbuff_in::rewind() 12 | { 13 | if (p_bactive) 14 | { 15 | if (p_bdat) 16 | { 17 | p_buff_pos = 0; 18 | } else { 19 | if (!p_bbin) 20 | ::rewind(p_fin); 21 | } 22 | } 23 | } 24 | 25 | char* Gbuff_in::fgets(char* str, int num) 26 | { 27 | if (p_bactive) 28 | { 29 | if (p_bdat) 30 | { 31 | if (p_buff_pos == p_datdec.p_buff.size()) 32 | return 0; 33 | int i = 0; 34 | while (i+1 < num && p_buff_pos < p_datdec.p_buff.size()) 35 | { 36 | if (p_datdec.p_buff[p_buff_pos] != '\r') 37 | { 38 | str[i] = p_datdec.p_buff[p_buff_pos]; 39 | ++i; 40 | if (p_datdec.p_buff[p_buff_pos] == '\n') 41 | { 42 | ++p_buff_pos; 43 | break; 44 | } 45 | } 46 | ++p_buff_pos; 47 | } 48 | if (num > 0) 49 | str[i] = '\0'; 50 | if (strlen(str) == 0) 51 | return 0; 52 | return str; 53 | } else { 54 | if (!p_bbin) 55 | { 56 | return ::fgets(str, num, p_fin); 57 | } else { 58 | return 0; 59 | } 60 | } 61 | } 62 | return 0; 63 | } 64 | 65 | /*const*/ uint8_t* Gbuff_in::fbuffptr() 66 | { 67 | if (p_bactive && p_bbin) 68 | { 69 | if (p_bdat) 70 | { 71 | return p_datdec.p_buff.data(); 72 | } else { 73 | return p_stdin_buff_ptr.data(); 74 | } 75 | } 76 | return 0; 77 | } 78 | 79 | unsigned int Gbuff_in::fbuffsz() 80 | { 81 | if (p_bactive && p_bbin) 82 | { 83 | if (p_bdat) 84 | { 85 | return p_datdec.p_buff.size(); 86 | } else { 87 | return p_stdin_buff_sz; 88 | } 89 | } 90 | return 0; 91 | } 92 | 93 | bool Gbuff_in::f_open(const char* fname, const char* mode) /* "r" nebo "rb" */ 94 | { 95 | if (p_bactive) // pokud je soubor otevřený, neotevře se jiný a vrátí se false (chyba) 96 | return false; 97 | // parametr mode je "r" 98 | if (strlen(mode) == 1 && *mode == 'r') 99 | { 100 | if (p_bdat) 101 | { 102 | if (!p_datdec.load(fname)) 103 | return false; 104 | } else { 105 | p_fin = ::fopen(fname, mode); 106 | //fprintf(stderr, "%s %s\n", __PRETTY_FUNCTION__, fname); 107 | if (p_fin == NULL) 108 | return false; 109 | } 110 | p_bactive = true; 111 | p_bbin = false; 112 | return true; 113 | } 114 | // parametr mode je "rb" 115 | else if (strlen(mode) == 2 && *mode == 'r' && mode[1] == 'b') 116 | { 117 | if (p_bdat) // otevření z paku 118 | { 119 | if (!p_datdec.load(fname)) 120 | return false; 121 | } else { // otevření normálního souboru 122 | FILE* fin = ::fopen(fname, mode); 123 | //fprintf(stderr, "%s %s\n", __PRETTY_FUNCTION__, fname); 124 | if (fin == NULL) 125 | return false; 126 | ::fseek(fin, 0, SEEK_END); 127 | p_stdin_buff_sz = ::ftell(fin); 128 | ::rewind(fin); 129 | p_stdin_buff_ptr.resize(p_stdin_buff_sz); 130 | ::fread(p_stdin_buff_ptr.data(), 1, p_stdin_buff_sz, fin); 131 | ::fclose(fin); 132 | } 133 | p_bactive = true; 134 | p_bbin = true; // je otevřený binární soubor 135 | return true; 136 | } 137 | else return false; 138 | } 139 | 140 | void Gbuff_in::fclose() 141 | { 142 | p_bactive = false; 143 | if (p_bbin) 144 | { 145 | if (p_bdat) 146 | { 147 | p_stdin_buff_ptr.clear(); 148 | p_stdin_buff_sz = 0; 149 | } else { // normální soubor 150 | p_stdin_buff_ptr.clear(); 151 | p_stdin_buff_sz = 0; 152 | } 153 | } else { // textový soubor 154 | if (p_bdat) 155 | { 156 | p_buff_pos = 0; 157 | } else { // normální soubor 158 | if (p_fin) 159 | ::fclose(p_fin); 160 | p_fin = 0; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/mainmenu.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_MAINMENU_H 2 | #define HLIDAC_MAINMENU_H 3 | 4 | #include "gamemng.h" 5 | #include "gltext.h" 6 | #include "settings_dat.h" 7 | 8 | #include 9 | #include 10 | 11 | enum MainMenu_states { 12 | STATE_RACE = 0, STATE_CONTROLS, STATE_OPTIONS, STATE_BEST_LAPS, STATE_QUIT, STATE_Q, 13 | 14 | STATE_R_NUM, STATE_R_CAR1, STATE_R_CAR2, STATE_R_CAR3, STATE_R_CAR4, 15 | STATE_R_TRACK, STATE_R_LAPS, STATE_R_DIRECTION, STATE_R_DAYTIME, STATE_R_GO, 16 | 17 | STATE_CONTROLS_BEGIN, 18 | STATE_CONTROLS_TEST_KEYBOARD = STATE_CONTROLS_BEGIN, 19 | STATE_CONTROLS_P1_UP, STATE_CONTROLS_P1_DOWN, STATE_CONTROLS_P1_LEFT, STATE_CONTROLS_P1_RIGHT, 20 | STATE_CONTROLS_P2_UP, STATE_CONTROLS_P2_DOWN, STATE_CONTROLS_P2_LEFT, STATE_CONTROLS_P2_RIGHT, 21 | STATE_CONTROLS_P3_UP, STATE_CONTROLS_P3_DOWN, STATE_CONTROLS_P3_LEFT, STATE_CONTROLS_P3_RIGHT, 22 | STATE_CONTROLS_P4_UP, STATE_CONTROLS_P4_DOWN, STATE_CONTROLS_P4_LEFT, STATE_CONTROLS_P4_RIGHT, 23 | STATE_CONTROLS_END, 24 | 25 | STATE_CONTROLS_TEST_KEYBOARD_SCREEN = STATE_CONTROLS_END, 26 | 27 | STATE_OPTIONS_SOUNDVOL, STATE_OPTIONS_VIEWDIST, 28 | 29 | STATE_BEST_LAPS_SCREEN, 30 | 31 | STATE_CAR_SEL, 32 | 33 | STATE_TRACK_SEL, 34 | }; 35 | 36 | class Gamemng; 37 | 38 | 39 | #if defined(__amigaos4__) 40 | #define Menu Menu_ 41 | #endif 42 | 43 | class MainMenu { 44 | public: 45 | MainMenu() : p_bactive(false), p_state(0), p_car_i(0), p_gamemng(nullptr), p_settings(nullptr), p_controlsChanged(false), p_players(0), p_laps(0), 46 | p_direction_sel(false), p_sky_sel(0), p_sound_vol(0), p_view_dist(0), p_track_sel(0), p_testKeysCount(0), p_enterMode(false) { } 47 | void init(Gamemng* gamemng, Settings* settings); 48 | void menu(); // nahrát textury a změnit stav 49 | void game(); // uvolnit textury a změnit stav 50 | void save_settings(); 51 | bool keydown(unsigned int sym); 52 | void event(const SDL_Event& e); 53 | void afterEvent(); 54 | void loadAndPrintBestTimes(); 55 | void render(); // vykreslení menu 56 | 57 | void exitEnterMode(); 58 | 59 | bool p_bactive; // na začátku false, na true se změní po zavolání menu() 60 | int p_state; // = 0 61 | int p_car_sel[4]; // 62 | int p_car_i; // <0, 4), číslo auta u stavu STATE_CAR_SEL 63 | int p_car_tex_sel[4]; // 64 | 65 | Gamemng* p_gamemng; // pomocí tohoto se získá ukazatel na glfont 66 | Settings* p_settings; 67 | 68 | bool p_controlsChanged; 69 | 70 | SharedGLtex p_logo_textura; 71 | SharedGLbuf p_logoBuf; 72 | SharedGLbuf p_carBuf; 73 | SharedGLbuf p_arrowBuf; 74 | SharedGLbuf p_arrowElemBuf; 75 | 76 | bool p_bufUpdated = false; // GL buffer updated with latest data? 77 | SharedGLbuf p_buf; 78 | SharedGLbuf p_elemBuf; 79 | 80 | // další struktura na textury aut, možná propojená s gamemng, to samé tratě 81 | Gltext p_text_main; 82 | Gltext p_text_main_ver; 83 | Gltext p_text_main_www; 84 | Gltext p_text_race_go, p_text_race_n, p_text_race_car, p_text_race_car2, 85 | p_text_race_track0, p_text_race_track1, p_text_race_track24, p_text_race_track35;//, p_text_race_laps; 86 | Gltext p_text_race_status; 87 | Gltext p_text_test_keyboard, p_text_test_keyboard_description, p_text_test_keyboard_status; 88 | Gltext p_text_controls, p_text_controls0, p_text_controls1, p_text_controls2, p_text_controls_status, p_text_controls_status_enter; 89 | Gltext p_text_opt, p_text_opt2, p_text_opt3; 90 | Gltext p_text_carsel; 91 | 92 | Gltext p_text_best_laps; 93 | Gltext p_text_best_laps_header; 94 | Gltext p_text_best_laps_tracks; 95 | Gltext p_text_best_laps_tracks_reversed_flag; 96 | Gltext p_text_best_laps_cars; 97 | Gltext p_text_best_laps_times; 98 | 99 | float p_opt_verts[4*3*2]; 100 | float p_opt_color0[3]; 101 | float p_opt_color1[3]; 102 | 103 | unsigned int p_players; // 1 - 4 104 | unsigned int p_laps; // 1 - 50 105 | bool p_direction_sel; 106 | int p_daytime_sel; 107 | int p_sky_sel; 108 | int p_sound_vol; 109 | int p_view_dist; 110 | 111 | int p_cars_sel[4]; 112 | int p_cars_tex_sel[4]; 113 | 114 | int p_track_sel; 115 | 116 | void countKeys(); 117 | int p_testKeysCount; 118 | SDL_Keycode p_testKeysLastKeyDown; 119 | SDL_Keycode p_testKeysLastKeyUp; 120 | std::map p_testKeysMap; 121 | 122 | bool p_enterMode; 123 | 124 | SharedGLtex p_tex_sel_bnd; // pracovní proměnná pro aktivní texturu výběru 125 | 126 | static const float font_color[4]; 127 | static const float font_color_disconnected[4]; 128 | static const float font_color_ver[4]; 129 | static const float font_color_hi[4]; 130 | static const float font_color_enter[4]; 131 | }; 132 | 133 | #endif // HLIDAC_MAINMENU_H 134 | 135 | -------------------------------------------------------------------------------- /src/load_texture.cpp: -------------------------------------------------------------------------------- 1 | #include "load_texture.h" 2 | #include "bits.h" 3 | 4 | unsigned int g_texture_memory_usage = 0; 5 | 6 | extern int g_textureFiltering; 7 | 8 | static const GLint textureWrap = GL_REPEAT; 9 | 10 | GLuint load_texture(const Pict2& pict, bool bmipmap) 11 | { 12 | if (bits_count(pict.w()) != 1) 13 | return 0; 14 | if (bits_count(pict.h()) != 1 && bits_count(pict.h()+1) != 1) 15 | return 0; 16 | { 17 | GLuint textura; 18 | glGenTextures(1, &textura); checkGL(); 19 | glBindTexture(GL_TEXTURE_2D, textura); checkGL(); 20 | if (!bmipmap) // no mipmaps 21 | { 22 | unsigned int pict_h = pict.h(); 23 | if (bits_count(pict.h()) != 1 && bits_count(pict.h()+1) == 1) // předpřipravené mipmapy 24 | pict_h = (pict.h()+1)/2; 25 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pict.w(), pict_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pict.c_px()); checkGL(); 26 | g_texture_memory_usage += 4*pict.w()*pict_h; 27 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); checkGL(); 28 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); checkGL(); 29 | 30 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrap); checkGL(); 31 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrap); checkGL(); 32 | } else { // mipmaps 33 | if (bits_count(pict.h()) != 1 && bits_count(pict.h()+1) == 1) // předpřipravené mipmapy 34 | { 35 | unsigned int pict_h = (pict.h()+1)/2; 36 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pict.w(), pict_h, 0, /*GL_BGRA*/GL_RGBA, GL_UNSIGNED_BYTE, pict.c_px()); checkGL(); 37 | unsigned int pict_w = pict.w()/2; 38 | unsigned int start_y = pict_h; 39 | pict_h /= 2; 40 | std::vector data(pict_w*pict_h*4); 41 | unsigned int miplevel = 1; 42 | while (pict_w || pict_h) 43 | { 44 | for (unsigned int x = 0; x != pict_w; ++x) 45 | { 46 | for (unsigned int y = 0; y != pict_h; ++y) 47 | { 48 | memcpy(data.data()+(x+y*pict_w)*4, pict.c_px(x, y+start_y), 4); 49 | } 50 | } 51 | 52 | glTexImage2D(GL_TEXTURE_2D, miplevel, GL_RGBA, std::max(pict_w, (unsigned int)1), std::max(pict_h, (unsigned int)1), 0, /*GL_BGRA*/GL_RGBA, GL_UNSIGNED_BYTE, data.data()); checkGL(); 53 | g_texture_memory_usage += 4*pict.w()*pict_h; 54 | start_y += pict_h; 55 | pict_w /= 2; 56 | pict_h /= 2; 57 | ++miplevel; 58 | } 59 | } else { 60 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pict.w(), pict.h(), 0, /*GL_BGRA*/GL_RGBA, GL_UNSIGNED_BYTE, pict.c_px()); checkGL(); 61 | glGenerateMipmap(GL_TEXTURE_2D); 62 | g_texture_memory_usage += 4*pict.w()*pict.h()+4*pict.w()*pict.h()/2; 63 | } 64 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_textureFiltering > 0 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_NEAREST); checkGL(); 65 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); checkGL(); 66 | 67 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textureWrap); checkGL(); 68 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textureWrap); checkGL(); 69 | } 70 | if (g_textureFiltering == 2) 71 | { 72 | #ifndef DISABLE_ANISOTROPY 73 | ASSERT_ANISOTROPY 74 | GLfloat maxAniso = 0.0f; 75 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &maxAniso); 76 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, maxAniso); checkGL(); 77 | #endif 78 | } 79 | glBindTexture(GL_TEXTURE_2D, 0); checkGL(); 80 | return textura; 81 | } 82 | return 0; 83 | } 84 | 85 | GLuint load_texture_cube_map(const Pict2& pict) 86 | { 87 | if (pict.w()*6 != pict.h()) 88 | return 0; 89 | GLuint ret = 0; 90 | glGenTextures(1, &ret); checkGL(); 91 | glBindTexture(GL_TEXTURE_CUBE_MAP, ret); checkGL(); 92 | static const GLenum faceTarget[6] = { 93 | GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 94 | GL_TEXTURE_CUBE_MAP_POSITIVE_X, 95 | GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 96 | GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 97 | GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 98 | GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 99 | }; 100 | for (unsigned int i = 0; i != 6; ++i) 101 | { 102 | glTexImage2D(faceTarget[i], 103 | 0, //level 104 | GL_RGBA, //internal format 105 | pict.w(), //width 106 | pict.w(), //height 107 | 0, //border 108 | GL_RGBA, //format 109 | GL_UNSIGNED_BYTE, //type 110 | pict.c_px()+pict.w()*pict.w()*4*i); checkGL(); // pixel data 111 | g_texture_memory_usage += pict.w()*pict.w()*4; 112 | } 113 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); checkGL(); 114 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); checkGL(); 115 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGL(); 116 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGL(); 117 | glBindTexture(GL_TEXTURE_CUBE_MAP, 0); checkGL(); 118 | return ret; 119 | } 120 | -------------------------------------------------------------------------------- /src/gui.h: -------------------------------------------------------------------------------- 1 | #ifndef GUI_H 2 | #define GUI_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | struct GUI_Surface 11 | { 12 | Uint32 w, h; 13 | std::vector pixels; 14 | }; 15 | 16 | int GUI_BlitSurface(const GUI_Surface& src, 17 | const SDL_Rect* srcrect, 18 | GUI_Surface& dst, 19 | const SDL_Rect* dstrect); 20 | 21 | int GUI_FillRect(GUI_Surface& dst, const SDL_Rect* rect, Uint32 color); 22 | 23 | struct GuiFont 24 | { 25 | static const int WIDTH; 26 | static const int HEIGHT; 27 | static const unsigned char DATA[]; 28 | static const int CHARACTER_COUNT; 29 | static const int CHARACTER_POSITIONS[]; 30 | static const int CHARACTER_WIDTHS[]; 31 | }; 32 | 33 | struct GuiData 34 | { 35 | void initData(); 36 | 37 | std::vector m_whiteFontPixels; 38 | GUI_Surface m_whiteFontSurface; 39 | 40 | std::vector m_blackFontPixels; 41 | GUI_Surface m_blackFontSurface; 42 | 43 | GUI_Surface m_guiComboSurface; 44 | GUI_Surface m_guiCornersSurface; 45 | GUI_Surface m_guiTickSurface; 46 | 47 | static const Uint32 COLOR_BACKGROUND1; 48 | static const Uint32 COLOR_BUTTON; 49 | static const Uint32 COLOR_MOUSEOVER; 50 | static const Uint32 COLOR_CLICKED; 51 | static const Uint32 COLOR_EDGE; 52 | static const Uint32 COLOR_FRAME; 53 | static const Uint32 COLOR_SELECTED; 54 | 55 | private: 56 | static Uint32 COMBO_SURFACE_DATA[]; 57 | static const int COMBO_SURFACE_WIDTH; 58 | static const int COMBO_SURFACE_HEIGHT; 59 | 60 | static Uint32 CORNERS_SURFACE_DATA[]; 61 | static const int CORNERS_SURFACE_WIDTH; 62 | static const int CORNERS_SURFACE_HEIGHT; 63 | 64 | static Uint32 TICK_SURFACE_DATA[]; 65 | static const int TICK_SURFACE_WIDTH; 66 | static const int TICK_SURFACE_HEIGHT; 67 | }; 68 | 69 | // performance-oriented design 70 | struct GuiItem 71 | { 72 | enum EType 73 | { 74 | FRAME, 75 | LABEL, 76 | BUTTON, 77 | CHECK, 78 | COMBO 79 | }; 80 | GuiItem(EType type, std::tuple xw, std::tuple yh, const std::string& text = std::string(), bool hidden = false) : 81 | type(type), 82 | x(std::get<0>(xw)), 83 | y(std::get<0>(yh)), 84 | width(std::get<1>(xw)), 85 | height(std::get<1>(yh)), 86 | text(text), 87 | checked(false), 88 | items(std::vector()), 89 | currentItem(0), 90 | itemHeight(20), 91 | visibleItemCount(2), 92 | pressedByKey(false), 93 | hidden(hidden) 94 | { 95 | //assert(type != COMBO); 96 | } 97 | GuiItem(EType type, std::tuple xw, std::tuple yh, const std::vector& items, int currentItem, int itemHeight, int visibleItemCount, bool hidden = false) : 98 | type(type), 99 | x(std::get<0>(xw)), 100 | y(std::get<0>(yh)), 101 | width(std::get<1>(xw)), 102 | height(std::get<1>(yh)), 103 | text(""), 104 | checked(false), 105 | items(items), 106 | currentItem(currentItem), 107 | itemHeight(itemHeight), 108 | visibleItemCount(visibleItemCount), 109 | pressedByKey(false), 110 | hidden(hidden) 111 | { 112 | //assert(type == COMBO); 113 | //assert(visibleItemCount >= 2); 114 | } 115 | 116 | int getComboFields() const; 117 | 118 | EType type; 119 | int x, y, width, height; 120 | std::string text; // for other than combo and frame 121 | 122 | // check data 123 | bool checked; 124 | 125 | // combo data 126 | std::vector items; 127 | int currentItem; 128 | int itemHeight; 129 | int visibleItemCount; 130 | bool pressedByKey; 131 | bool hidden; 132 | }; 133 | 134 | class GuiDialog 135 | { 136 | public: 137 | GuiDialog(); 138 | 139 | void init(int width, int height, const char* caption); 140 | 141 | void drawText(const char* text, int x, int y, int width); 142 | 143 | void drawCenteredText(const char* text, int x, int y); 144 | 145 | void paint(); 146 | 147 | void execute(); 148 | 149 | virtual void onQuit(); 150 | 151 | virtual void onButton(int itemIndex); 152 | 153 | virtual void onKeyDown(SDL_Keycode k); 154 | 155 | virtual void onKeyUp(SDL_Keycode k); 156 | 157 | int m_width, m_height; 158 | std::string m_caption; 159 | 160 | SDL_Window* m_guiWindow; 161 | SDL_Renderer* m_renderer; 162 | SDL_Texture* m_texture; 163 | 164 | GUI_Surface m_backSurface; 165 | 166 | std::vector m_items; 167 | 168 | bool m_whiteFont; 169 | 170 | int m_expandedItem; 171 | int m_expandedComboScroll; 172 | 173 | int m_state; // 0 - none, 1 - mouseOver, 2 - mouseDown 174 | int m_stateItem; 175 | int m_stateExpandedComboItem; 176 | 177 | int m_lastMouseX; 178 | int m_lastMouseY; 179 | 180 | 181 | bool m_paint; 182 | 183 | bool m_eventLoopDone; 184 | 185 | static const int COMBO_ARROW_WIDTH; 186 | 187 | private: 188 | void mouseStateChanged(int x, int y, bool leftButton); 189 | 190 | int getItem(int x, int y); 191 | 192 | int getExpandedComboItem(int x, int y); 193 | 194 | Uint32 stateToColor(int state) 195 | { 196 | if (state == 0) 197 | { 198 | return GuiData::COLOR_BUTTON; 199 | } 200 | else if (state == 1) 201 | { 202 | return GuiData::COLOR_MOUSEOVER; 203 | } 204 | else 205 | { 206 | return GuiData::COLOR_CLICKED; 207 | } 208 | } 209 | 210 | GuiData m_guiData; 211 | }; 212 | 213 | #endif // GUI_H 214 | -------------------------------------------------------------------------------- /src/pict2_jpeg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C" 5 | { 6 | #ifdef JPEG_9D_STATIC 7 | #include "jpeg-9d/jpeglib.h" 8 | #include "jpeg-9d/jerror.h" 9 | #else 10 | #include 11 | #include 12 | #endif 13 | } 14 | 15 | #include "pict2.h" 16 | 17 | struct my_error_mgr { 18 | jpeg_error_mgr pub; 19 | int* ret; 20 | jmp_buf setjmp_buffer; 21 | }; 22 | 23 | METHODDEF(void) my_error_exit(j_common_ptr cinfo) 24 | { 25 | longjmp(((my_error_mgr*)(((jpeg_compress_struct*)cinfo)->err))->setjmp_buffer, 1); 26 | } 27 | 28 | METHODDEF(void) my_emit_message(j_common_ptr cinfo, int) 29 | { 30 | *(((my_error_mgr*)(((jpeg_compress_struct*)cinfo)->err))->ret) |= 4; 31 | } 32 | 33 | METHODDEF(void) my_output_message(j_common_ptr) 34 | { 35 | } 36 | 37 | // 38 | 39 | int Pict2::loadjpeg(const char* fname) 40 | { 41 | return loadjpeg_pom(true, fname, 0); 42 | } 43 | 44 | int Pict2::loadjpeg(const void* data, unsigned int size) 45 | { 46 | return loadjpeg_pom(false, data, size); 47 | } 48 | 49 | METHODDEF(void) my_init_source(j_decompress_ptr /*cinfo*/) 50 | { 51 | } 52 | 53 | METHODDEF(boolean) my_fill_input_buffer(j_decompress_ptr cinfo) 54 | { 55 | ERREXIT(cinfo, 1); 56 | return TRUE; 57 | } 58 | 59 | METHODDEF(void) my_skip_input_data(j_decompress_ptr cinfo, long num_bytes) 60 | { 61 | if (num_bytes <= 0) 62 | return; 63 | if ((unsigned int)num_bytes > cinfo->src->bytes_in_buffer) 64 | ERREXIT(cinfo, 1); 65 | cinfo->src->bytes_in_buffer -= num_bytes; 66 | cinfo->src->next_input_byte += num_bytes; 67 | } 68 | 69 | METHODDEF(void) my_term_source(j_decompress_ptr /*cinfo*/) 70 | { 71 | } 72 | 73 | int Pict2::loadjpeg_pom(bool bfile, const void* fname_data, unsigned int data_size) 74 | { 75 | /* This struct contains the JPEG decompression parameters and pointers to 76 | * working space (which is allocated as needed by the JPEG library). 77 | */ 78 | struct jpeg_decompress_struct cinfo; 79 | /* We use our private extension JPEG error handler. 80 | * Note that this struct must live as long as the main JPEG parameter 81 | * struct, to avoid dangling-pointer problems. 82 | */ 83 | my_error_mgr jerr; 84 | /* More stuff */ 85 | static FILE* fin = 0; /* source file */ 86 | JSAMPARRAY buffer; /* Output row buffer */ 87 | int row_stride; /* physical row width in output buffer */ 88 | 89 | jpeg_source_mgr source_mgr; 90 | 91 | int ret = 1; 92 | 93 | clear(); 94 | 95 | /* In this example we want to open the input file before doing anything else, 96 | * so that the setjmp() error recovery below can assume the file is open. 97 | * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that 98 | * requires it in order to read binary files. 99 | */ 100 | 101 | if (bfile) 102 | { 103 | fin = fopen((const char*)fname_data, "rb"); 104 | if (!fin) 105 | return 0; 106 | } 107 | 108 | /* Step 1: allocate and initialize JPEG decompression object */ 109 | 110 | /* We set up the normal JPEG error routines, then override error_exit. */ 111 | cinfo.err = jpeg_std_error((jpeg_error_mgr*)&jerr); 112 | jerr.pub.error_exit = my_error_exit; 113 | jerr.pub.emit_message = my_emit_message; 114 | jerr.pub.output_message = my_output_message; 115 | jerr.ret = &ret; 116 | 117 | if (setjmp(jerr.setjmp_buffer)) 118 | { 119 | clear(); 120 | jpeg_destroy_decompress(&cinfo); 121 | /*if (buncreate) 122 | uncreate();*/ 123 | if (bfile) 124 | fclose(fin); 125 | return 0; 126 | } 127 | 128 | /* Now we can initialize the JPEG decompression object. */ 129 | jpeg_create_decompress(&cinfo); 130 | 131 | /* Step 2: specify data source (eg, a file) */ 132 | 133 | if (bfile) 134 | jpeg_stdio_src(&cinfo, fin); 135 | else { 136 | source_mgr.next_input_byte = (const unsigned char*)fname_data; 137 | source_mgr.bytes_in_buffer = data_size; 138 | 139 | source_mgr.init_source = my_init_source; 140 | source_mgr.fill_input_buffer = my_fill_input_buffer; 141 | source_mgr.skip_input_data = my_skip_input_data; 142 | source_mgr.resync_to_restart = jpeg_resync_to_restart; 143 | source_mgr.term_source = my_term_source; 144 | cinfo.src = &source_mgr; 145 | } 146 | 147 | /* Step 3: read file parameters with jpeg_read_header() */ 148 | 149 | jpeg_read_header(&cinfo, TRUE); 150 | /* We can ignore the return value from jpeg_read_header since 151 | * (a) suspension is not possible with the stdio data source, and 152 | * (b) we passed TRUE to reject a tables-only JPEG file as an error. 153 | * See libjpeg.doc for more info. 154 | */ 155 | 156 | /* Step 4: set parameters for decompression */ 157 | 158 | /* In this example, we don't need to change any of the defaults set by 159 | * jpeg_read_header(), so we do nothing here. 160 | */ 161 | 162 | /* Step 5: Start decompressor */ 163 | 164 | jpeg_start_decompress(&cinfo); 165 | /* We can ignore the return value since suspension is not possible 166 | * with the stdio data source. 167 | */ 168 | 169 | { 170 | cinfo.out_color_space = JCS_EXT_RGBA; 171 | create(cinfo.output_width, cinfo.output_height, 0); 172 | row_stride = cinfo.output_width * 4; 173 | buffer = (*cinfo.mem->alloc_sarray) 174 | ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); 175 | while (cinfo.output_scanline < cinfo.output_height) { 176 | jpeg_read_scanlines(&cinfo, buffer, 1); 177 | memcpy(p_px.data()+(cinfo.output_height-cinfo.output_scanline)*row_stride, *buffer, row_stride); 178 | } 179 | } 180 | 181 | /* Step 7: Finish decompression */ 182 | jpeg_finish_decompress(&cinfo); 183 | /* We can ignore the return value since suspension is not possible 184 | * with the stdio data source. 185 | */ 186 | 187 | /* Step 8: Release JPEG decompression object */ 188 | 189 | /* This is an important step since it will release a good deal of memory. */ 190 | jpeg_destroy_decompress(&cinfo); 191 | 192 | /* After finish_decompress, we can close the input file. 193 | * Here we postpone it until after no more JPEG errors are possible, 194 | * so as to simplify the setjmp error logic above. (Actually, I don't 195 | * think that jpeg_destroy can do an error exit, but why assume anything...) 196 | */ 197 | if (bfile) 198 | fclose(fin); 199 | 200 | if (empty()) 201 | { 202 | clear(); 203 | return 0; 204 | } 205 | 206 | /* At this point you may want to check to see whether any corrupt-data 207 | * warnings occurred (test whether jerr.pub.num_warnings is nonzero). 208 | */ 209 | 210 | if (jerr.pub.num_warnings) 211 | ret |= 4; 212 | 213 | /* And we're done! */ 214 | return ret; 215 | } 216 | -------------------------------------------------------------------------------- /src/soundmng.cpp: -------------------------------------------------------------------------------- 1 | #include "soundmng.h" 2 | #include "rand1.h" 3 | #include "gbuff_in.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int g_sound_on = 1; 10 | static const float maxGain = 0.9f; 11 | 12 | extern std::vector global_al_sources; 13 | extern std::vector global_al_buffers; 14 | 15 | ALuint createSource(ALuint buffer) 16 | { 17 | ALuint source; 18 | alGenSources(1, &source); global_al_sources.push_back(source); 19 | const ALfloat sourcePos[] = { 0.0, 0.0, 0.0 }; 20 | const ALfloat sourceVel[] = { 0.0, 0.0, 0.0 }; 21 | alSourcef (source, AL_PITCH, 1.0 ); 22 | alSourcef (source, AL_GAIN, 1.0 * maxGain ); 23 | alSourcefv(source, AL_POSITION, sourcePos); 24 | alSourcefv(source, AL_VELOCITY, sourceVel); 25 | alSourcei (source, AL_LOOPING, 0); 26 | if (buffer != 0) 27 | alSourcei (source, AL_BUFFER, buffer); 28 | return source; 29 | } 30 | 31 | void Sound_game_static::playSoundTest(float gain) 32 | { 33 | alSourceStop(p_test_stream); 34 | alSourceRewind(p_test_stream); 35 | alSourcef(p_test_stream, AL_GAIN, gain*maxGain); 36 | alSourcePlay(p_test_stream); 37 | } 38 | 39 | void Sound_game_static::init() 40 | { 41 | gbuff_in.f_open("crash0.raw", "rb"); 42 | alGenBuffers(1, &(p_hit_sample[0])); global_al_buffers.push_back(p_hit_sample[0]); 43 | swapArrayLE16(gbuff_in.fbuffptr(), gbuff_in.fbuffsz()); 44 | alBufferData(p_hit_sample[0], AL_FORMAT_MONO16, gbuff_in.fbuffptr(), gbuff_in.fbuffsz(), 22050); 45 | gbuff_in.fclose(); 46 | 47 | gbuff_in.f_open("crash1.raw", "rb"); 48 | alGenBuffers(1, &(p_hit_sample[1])); global_al_buffers.push_back(p_hit_sample[1]); 49 | swapArrayLE16(gbuff_in.fbuffptr(), gbuff_in.fbuffsz()); 50 | alBufferData(p_hit_sample[1], AL_FORMAT_MONO16, gbuff_in.fbuffptr(), gbuff_in.fbuffsz(), 22050); 51 | gbuff_in.fclose(); 52 | 53 | gbuff_in.f_open("skid.raw", "rb"); 54 | alGenBuffers(1, &(p_skid_sample)); global_al_buffers.push_back(p_skid_sample); 55 | swapArrayLE16(gbuff_in.fbuffptr(), gbuff_in.fbuffsz()); 56 | tweakLoop(gbuff_in.fbuffptr(), gbuff_in.fbuffsz()); 57 | alBufferData(p_skid_sample, AL_FORMAT_MONO16, gbuff_in.fbuffptr(), gbuff_in.fbuffsz(), 22050); 58 | gbuff_in.fclose(); 59 | 60 | for (unsigned int i = 0; i != 4; ++i) { 61 | p_skid_stream[i] = createSource(p_skid_sample); 62 | } 63 | for (int j = 0; j != 2; ++j) 64 | for (int i = 0; i != 5; ++i) { 65 | p_hit_stream[i+j*5] = createSource(p_hit_sample[j]); 66 | } 67 | 68 | p_test_stream = createSource(p_hit_sample[0]); 69 | } 70 | 71 | void Sound_game_static::load(unsigned int i, ALbuffer engine0_sample, ALbuffer engine1_sample) 72 | { 73 | if (i >= 4) 74 | return; 75 | if (p_engine0_stream[i] == 0) 76 | p_engine0_stream[i] = createSource(engine0_sample); 77 | else 78 | alSourcei(p_engine0_stream[i], AL_BUFFER, engine0_sample); 79 | if (p_engine1_stream[i] == 0) 80 | p_engine1_stream[i] = createSource(engine1_sample); 81 | else 82 | alSourcei(p_engine1_stream[i], AL_BUFFER, engine1_sample); 83 | } 84 | 85 | void Sound_car::stop() 86 | { 87 | alSourceStop(p_engine0_stream); 88 | p_engine0_state = 0; 89 | alSourceStop(p_engine1_stream); 90 | p_engine1_state = 0; 91 | alSourceStop(p_skid_stream); 92 | p_skid_state = 0; 93 | } 94 | 95 | const float engine1_volume0 = 0.75f; 96 | 97 | void Sound_car::frame(float deltaT, int engine_state /*0 - nultý, 1 - první, 2 - první potichu*/, float engine_pitch, const float velocity[2]) 98 | { 99 | // 100 | p_time += deltaT; 101 | if (p_time >= p_T) p_time = 0.f; else return; 102 | if (!p_engine_on && engine_state == 2) 103 | engine_state = 0; 104 | if (engine_state == 0) 105 | { 106 | p_engine_on = 0; 107 | alSourcef(p_engine0_stream, AL_GAIN, 0.5f**p_global_volume*maxGain); 108 | if (!p_engine0_state) { 109 | alSourcePlay(p_engine0_stream); 110 | p_engine0_state = 1; 111 | } 112 | if (p_engine1_state) { 113 | alSourceStop(p_engine1_stream); 114 | p_engine1_state = 0; 115 | } 116 | } else { 117 | if (engine_state == 1) { 118 | p_engine_on = 1; 119 | alSourcef(p_engine1_stream, AL_GAIN, engine1_volume0**p_global_volume*maxGain); 120 | } else { 121 | alSourcef(p_engine1_stream, AL_GAIN, 0.5f**p_global_volume*maxGain); 122 | } 123 | 124 | alSourcef(p_engine1_stream, AL_PITCH, engine_pitch*p_running_pitch); 125 | 126 | if (!p_engine1_state) { 127 | alSourcePlay(p_engine1_stream); 128 | p_engine1_state = 1; 129 | } 130 | if (p_engine0_state) { 131 | alSourceStop(p_engine0_stream); 132 | p_engine0_state = 0; 133 | } 134 | } 135 | 136 | if (p_brake_volume <= 0.f) 137 | { 138 | if (p_skid_state) { 139 | alSourceStop(p_skid_stream); 140 | p_skid_state = 0; 141 | } 142 | } else { 143 | alSourcef(p_skid_stream, AL_GAIN, p_brake_volume**p_global_volume*maxGain); 144 | 145 | float speed = std::sqrt(velocity[0]*velocity[0] + velocity[1]*velocity[1]); 146 | float skidPitch = 0.8f+(speed - 6.f)/24.f*0.4f; 147 | if (skidPitch < 0.8f) skidPitch = 0.8f; 148 | if (skidPitch > 1.1f) skidPitch = 1.1f; 149 | 150 | alSourcef (p_skid_stream, AL_PITCH, skidPitch); 151 | 152 | if (!p_skid_state) { 153 | alSourcePlay(p_skid_stream); 154 | p_skid_state = 1; 155 | } 156 | } 157 | } 158 | 159 | void Sound_car::init(ALsource stream_idle, ALsource stream_running, float running_pitch, ALsource stream_skid, int player, int players_n) 160 | { 161 | p_brake_volume = 0.f; 162 | // toto zásadně změnit 163 | p_running_pitch = running_pitch; 164 | 165 | p_player = player; 166 | switch (players_n) 167 | { 168 | case 1: 169 | p_pan = 0; 170 | break; 171 | case 2: 172 | if (player == 0) p_pan = -1; else p_pan = 1; 173 | break; 174 | default: // 3, 4 175 | if (player < 2) p_pan = -1; else p_pan = 1; 176 | } 177 | p_engine0_stream = stream_idle; 178 | p_engine1_stream = stream_running; 179 | p_skid_stream = stream_skid; 180 | p_time = 0.f; 181 | p_T = 0.01f; 182 | 183 | alSourcei(p_engine0_stream, AL_LOOPING, 1); 184 | alSourcei(p_engine1_stream, AL_LOOPING, 1); 185 | alSourcei(p_skid_stream, AL_LOOPING, 1); 186 | // nejmenší délka v samplech je 32000 187 | alSourcef(p_engine0_stream, AL_SAMPLE_OFFSET, 32000.0*double(player)/double(players_n)); 188 | alSourcef(p_engine0_stream, AL_SAMPLE_OFFSET, 32000.0*double(player)/double(players_n)); 189 | alSourcef(p_engine0_stream, AL_SAMPLE_OFFSET, 32000.0*double(player)/double(players_n)); 190 | 191 | alSourcef(p_engine0_stream, AL_GAIN, 0.5**p_global_volume); 192 | alSourcef(p_engine1_stream, AL_GAIN, engine1_volume0**p_global_volume*maxGain); 193 | 194 | p_engine0_state = 0; // 0 - nehraje, 1 - hraje 195 | p_engine1_state = 0; // 0 - nehraje, 1 - hraje 196 | p_skid_state = 0; 197 | 198 | p_engine_on = 0; 199 | } 200 | 201 | void Sound_crash::init(ALsource* stream_hit) // load zvuků 202 | { 203 | p_hit_stream = stream_hit; 204 | } 205 | 206 | void Sound_crash::play(float c_j) // přehraje zvuk nárazu 207 | { 208 | if (c_j <= 400.f) return; 209 | float volume = c_j/12000.f; 210 | if (volume > 1.f) volume = 1.f; 211 | if (volume < 0.f) volume = 0.f; 212 | static const int sampleIndexer[6] = {0, 1, 0, 1, 0, 1}; 213 | int sample_sel =sampleIndexer[randn1(5)]; 214 | int stream_sel = p_fronta_pos[sample_sel]++; 215 | p_fronta_pos[sample_sel] %= p_width; 216 | int sel = stream_sel+sample_sel*p_width; 217 | 218 | alSourceStop(p_hit_stream[sel]); 219 | alSourceRewind(p_hit_stream[sel]); 220 | alSourcef(p_hit_stream[sel], AL_GAIN, volume**p_global_volume*maxGain); 221 | 222 | float pitch_min = 0.88; 223 | float pitch = pitch_min+randn1(int((1.f-pitch_min)*2.f*1000.f))*0.001; 224 | alSourcef(p_hit_stream[sel], AL_PITCH, pitch); 225 | alSourcePlay(p_hit_stream[sel]); 226 | } 227 | -------------------------------------------------------------------------------- /src/rbsolver.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_RBSOLVER_H 2 | #define HLIDAC_RBSOLVER_H 3 | 4 | #include "3dm.h" 5 | #include 6 | #include 7 | 8 | namespace RBf { 9 | inline bool equals(const float* u, const float* v) 10 | { 11 | return u[0] == v[0] && u[1] == v[1]; 12 | } 13 | inline void zerov(float* ret) 14 | { 15 | ret[0] = 0.f; 16 | ret[1] = 0.f; 17 | } 18 | inline const float* zerov() 19 | { 20 | static const float ret[2] = {0.f, 0.f}; 21 | return ret; 22 | } 23 | inline void cpy(float* ret, const float* v) 24 | { 25 | ret[0] = v[0]; 26 | ret[1] = v[1]; 27 | } 28 | // vector add 29 | inline float* add(float* ret, const float* u, const float* v) 30 | { 31 | ret[0] = u[0] + v[0]; 32 | ret[1] = u[1] + v[1]; 33 | return ret; 34 | } 35 | inline float* add(const float* u, const float* v) 36 | { 37 | static float ret[2]; 38 | ret[0] = u[0] + v[0]; 39 | ret[1] = u[1] + v[1]; 40 | return ret; 41 | } 42 | inline float* ladd(float* ret, const float* v) 43 | { 44 | ret[0] += v[0]; 45 | ret[1] += v[1]; 46 | return ret; 47 | } 48 | // vector subtract 49 | inline float* sub(float* ret, const float* u, const float* v) 50 | { 51 | ret[0] = u[0] - v[0]; 52 | ret[1] = u[1] - v[1]; 53 | return ret; 54 | } 55 | inline float* sub(const float* u, const float* v) 56 | { 57 | static float ret[2]; 58 | ret[0] = u[0] - v[0]; 59 | ret[1] = u[1] - v[1]; 60 | return ret; 61 | } 62 | inline float* lsub(float* ret, const float* v) 63 | { 64 | ret[0] -= v[0]; 65 | ret[1] -= v[1]; 66 | return ret; 67 | } 68 | // vector multiply 69 | inline float* mul(float* ret, const float* v, float a) 70 | { 71 | ret[0] = v[0]*a; 72 | ret[1] = v[1]*a; 73 | return ret; 74 | } 75 | inline float* mul(const float* v, float a) 76 | { 77 | static float ret[2]; 78 | ret[0] = v[0]*a; 79 | ret[1] = v[1]*a; 80 | return ret; 81 | } 82 | inline float* lmul(float* ret, float a) 83 | { 84 | ret[0] *= a; 85 | ret[1] *= a; 86 | return ret; 87 | } 88 | // vector divide 89 | /* unsafe */ inline float* div(float* ret, const float* v, float a) 90 | { 91 | ret[0] = v[0]/a; 92 | ret[1] = v[1]/a; 93 | return ret; 94 | } 95 | /* unsafe */ inline float* div(const float* v, float a) 96 | { 97 | static float ret[2]; 98 | ret[0] = v[0]/a; 99 | ret[1] = v[1]/a; 100 | return ret; 101 | } 102 | /* unsafe */ inline float* ldiv(float* ret, float a) 103 | { 104 | ret[0] /= a; 105 | ret[1] /= a; 106 | return ret; 107 | } 108 | inline float xprod(const float* u, const float* v) 109 | { 110 | return u[0]*v[1]-u[1]*v[0]; 111 | } 112 | inline float dprod(const float* u, const float* v) 113 | { 114 | return u[0]*v[0]+u[1]*v[1]; 115 | } 116 | inline float len2(const float* v) // délka vektoru^2 117 | { 118 | return v[0]*v[0]+v[1]*v[1]; 119 | } 120 | inline float len(const float* v) // délka vektoru^2 121 | { 122 | return sqrtf(len2(v)); 123 | } 124 | inline float safe(float f) 125 | { 126 | if (!std::isfinite(f)) 127 | return 0.f; 128 | return f; 129 | } 130 | inline void safe(float* v) 131 | { 132 | v[0] = safe(v[0]); 133 | v[1] = safe(v[1]); 134 | } 135 | inline void norm_s(float* v) 136 | { 137 | ldiv(v, len(v)); 138 | safe(v); 139 | } 140 | inline void norm_s(float* v1, const float* v) 141 | { 142 | div(v1, v, len(v)); 143 | safe(v1); 144 | } 145 | /* unsafe */ inline void norm(float* v) 146 | { 147 | ldiv(v, len(v)); 148 | } 149 | /* unsafe */ inline void norm(float* v1, const float* v) 150 | { 151 | div(v1, v, len(v)); 152 | } 153 | /* unsafe */ inline float dist(const float* x, const float* a, const float* v) // vzdálenost bodu od přímky //^2 154 | { 155 | return (xprod(v,x)+xprod(a,v))/len(v); 156 | } 157 | inline float distn(const float* x, const float* a, const float* v) // vzdálenost bodu od přímky 158 | { 159 | return xprod(v,x)+xprod(a,v); 160 | } 161 | inline void rot(float* m, float a) // vytvoření 2D rotační matice 162 | { 163 | m[0] = cosf(a); 164 | m[1] = sinf(a); 165 | } 166 | inline void rot(float* f, const float* m, const float* f0) // aplikace 2D rotační matice 167 | { 168 | f[0] = m[0]*f0[0]-m[1]*f0[1]; 169 | f[1] = m[1]*f0[0]+m[0]*f0[1]; 170 | } 171 | /* unsafe */ inline float intersect(const float* u, const float* b, const float* v) // průsečík přímek ([0], (u)) a ([b], (v)) 172 | { 173 | return xprod(v,b)/xprod(v,u); // průsečík = výsledek*u 174 | } 175 | /* unsafe */ inline float intersect2(const float* u, const float* b, const float* v) // průsečík přímek ([0], (u)) a ([b], (v)) 176 | { 177 | return xprod(b,u)/xprod(u,v); // průsečík = výsledek*u 178 | } 179 | 180 | /* unsafe */ inline float intersect(const float* a, const float* u, const float* b, const float* v) // průsečík přímek ([0], (u)) a ([b], (v)) 181 | { 182 | float b2[2]; 183 | sub(b2, b, a); 184 | return intersect(u, b2, v); // průsečík = výsledek*u 185 | } 186 | /* unsafe */ inline float intersect2(const float* a, const float* u, const float* b, const float* v) // průsečík přímek ([0], (u)) a ([b], (v)) 187 | { 188 | float b2[2]; 189 | sub(b2, b, a); 190 | return intersect2(u, b2, v); // průsečík = výsledek*u 191 | } 192 | 193 | inline bool line_intersect(const float* u, const float* b, const float* v) 194 | { 195 | float int_result = intersect (u, b, v); 196 | float int_result2 = intersect2(u, b, v); 197 | if (int_result >= 0.f && int_result <= 1.f && int_result2 >= 0.f && int_result2 <= 1.f) 198 | return true; 199 | return false; 200 | } 201 | inline bool line_intersect(const float* a, const float* u, const float* b, const float* v) 202 | { 203 | float b2[2]; 204 | sub(b2, b, a); 205 | float int_result = intersect (u, b2, v); 206 | float int_result2 = intersect2(u, b2, v); 207 | if (int_result >= 0.f && int_result <= 1.f && int_result2 >= 0.f && int_result2 <= 1.f) 208 | return true; 209 | return false; 210 | } 211 | inline void intersect3(float* t, const float* a, const float* u, const float* b, const float* v) 212 | { 213 | float b2[2]; 214 | sub(b2, b, a); 215 | t[0] = intersect (u, b2, v); 216 | t[1] = intersect2(u, b2, v); 217 | } 218 | inline void perp(float* ret, const float* v) // kolmý (perpendicular) vektor - kladný technický směr 219 | { 220 | ret[0] = -v[1]; 221 | ret[1] = v[0]; 222 | } 223 | inline void perp(float* v) // kolmý (perpendicular) vektor - kladný technický směr 224 | { 225 | float f; 226 | f = v[0]; 227 | v[0] = -v[1]; 228 | v[1] = f; 229 | } 230 | inline void neg(float* v) 231 | { 232 | v[0] = -v[0]; 233 | v[1] = -v[1]; 234 | } 235 | inline void neg(float* ret, const float* v) 236 | { 237 | ret[0] = -v[0]; 238 | ret[1] = -v[1]; 239 | } 240 | } 241 | 242 | void damp_v(float* p_v, float f/*součinitel smykového tření*/, float p_T); 243 | 244 | class TimeSync { 245 | public: 246 | void init(float T = 0.01); 247 | void add_deltaT(float deltaT); 248 | bool step(); 249 | 250 | float p_prevT; 251 | float p_T; 252 | }; 253 | 254 | struct BBox { 255 | float x[2]; // bod 256 | float v[2]; // vektor 257 | float v1[2]; // normalizovaný vektor 258 | float n1[2]; // normalizovaný normálový vektor bodu mířící dovnitř 259 | BBox* next; // ukazatel na další bod 260 | unsigned int bnconv; // je bod nekonvexní (např. roh objektu) 261 | }; 262 | 263 | void bbox_create(std::vector &bbox, unsigned int& size, float* center, const T3dm* t3dm); 264 | 265 | class RBSolver { 266 | public: 267 | void init(const float* x, float ax, const float* v, float av, float m, float am, const TimeSync* timesync, const T3dm* t3dm); 268 | void addF(const float* F, const float* A = 0); // přidání další síly k výslednici, souřadnice světa (0 - síla působí v těžišti) 269 | void addFb(const float* F, const float* A = 0); // přidání další síly k výslednici, souřadnice objektu (0 - síla působí v těžišti) 270 | void update(bool bstep); 271 | 272 | void damp_v(float f); 273 | void damp_av(float f, float r); 274 | 275 | void get_tm(float* tm); 276 | 277 | void get_vp(float* vp, float* pp, const float* pt) const; // rychlost, bod v globál. souř., kolmý vektor od středu k bodu 278 | 279 | float v_a_dprod(); 280 | 281 | const TimeSync* p_timesync; 282 | 283 | float p_x[2]; // polohový vektor 284 | float p_ax; // úhel 285 | float p_x0[2]; // extrapolovaný polohový vektor 286 | float p_ax0; // extrapolovaný úhel 287 | float p_x_prev[2]; // polohový vektor 288 | float p_ax_prev; // úhel 289 | float p_v[2]; // rychlost 290 | float p_av; // úhlová rychlost 291 | float p_a[2]; // zrychlení 292 | float p_aa; // úhlové zrychlení 293 | float p_m; // hmotnost 294 | float p_am; // moment setrvačnosti 295 | float p_F[2]; // síla 296 | float p_aF; // moment síly 297 | 298 | bool p_bupdm; 299 | float p_tm[2]; 300 | std::vector p_bbox; 301 | std::vector p_bbox_rot; 302 | unsigned int p_bbox_sz; 303 | 304 | bool p_bcolprev; // v předchozím kroku byla kolize 305 | bool p_bcolnow; 306 | }; 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /src/car2d.cpp: -------------------------------------------------------------------------------- 1 | #include "car2d.h" 2 | #include 3 | #include 4 | 5 | using namespace RBf; 6 | 7 | const float g_front_slip_ratio = 1.3f;//1.2; 8 | const float g_slip_rot_ratio = 1.005; 9 | const float g_back_slip_ratio = g_front_slip_ratio*g_slip_rot_ratio; 10 | 11 | void Car2D::init(float whf_x, float whf_y, float whb_x, float whb_y, RBSolver* rbsolver) 12 | { 13 | p_whf_x = whf_x; 14 | p_whf_y = whf_y; 15 | p_whb_x = whb_x; 16 | p_whb_y = whb_y; 17 | p_whl_a = 0.f; 18 | p_whr_a = 0.f; 19 | p_whl_a_i = 0.f; 20 | p_whr_a_i = 0.f; 21 | p_whl_a_ren = 0.f; 22 | p_whl_a_ren_i = 0.f; 23 | p_rbsolver = rbsolver; 24 | p_engine_pitch = 1.f; 25 | p_b_acc = false; 26 | p_b_brake = false; 27 | p_brake_i = 0.f; 28 | zerov(p_v_prev); 29 | p_av_prev = 0.f; 30 | } 31 | 32 | void Car2D::damp_engine_pitch(float f) 33 | { 34 | p_engine_pitch /= f; 35 | if (p_engine_pitch < 1.f) 36 | p_engine_pitch = 1.f; 37 | } 38 | 39 | void Car2D::go_forward() 40 | { 41 | p_b_brake = false; 42 | if (p_rbsolver->v_a_dprod() >= 0.0f) 43 | { 44 | float Fpom[2]; 45 | float Apom[2]; 46 | get_Fb_whl_acc(Fpom, Apom); 47 | p_rbsolver->addFb(Fpom, Apom); 48 | get_Fb_whr_acc(Fpom, Apom); 49 | p_rbsolver->addFb(Fpom, Apom); 50 | p_b_acc = true; 51 | 52 | p_brake_i = 0.f; 53 | } else { 54 | go_brake(); 55 | p_b_acc = false; 56 | } 57 | } 58 | 59 | void Car2D::go_backward() 60 | { 61 | p_b_brake = false; 62 | if (p_rbsolver->v_a_dprod() <= 0.0f) 63 | { 64 | float Fpom[2]; 65 | float Apom[2]; 66 | get_Fb_whl_rev(Fpom, Apom); 67 | p_rbsolver->addFb(Fpom, Apom); 68 | get_Fb_whr_rev(Fpom, Apom); 69 | p_rbsolver->addFb(Fpom, Apom); 70 | p_b_acc = true; 71 | 72 | p_brake_i = 0.f; 73 | } else { 74 | go_brake(); 75 | p_b_acc = false; 76 | } 77 | } 78 | 79 | void Car2D::go_zero() 80 | { 81 | p_b_brake = false; 82 | // nic 83 | p_b_acc = false; 84 | p_brake_i = 0.f; 85 | } 86 | 87 | void Car2D::go_brake() 88 | { 89 | cpy(p_v_prev, p_rbsolver->p_v); 90 | p_av_prev = p_rbsolver->p_av; 91 | p_b_brake = true; 92 | p_b_acc = false; 93 | p_brake_i += 2*p_rbsolver->p_timesync->p_T; 94 | if (p_brake_i > 1.f) 95 | p_brake_i = 1.f; 96 | 97 | float brake_F = p_rbsolver->p_m*5.f*(g_front_slip_ratio+g_back_slip_ratio); 98 | 99 | float v_pom[2]; 100 | cpy(v_pom, p_rbsolver->p_v); 101 | norm(v_pom); 102 | lmul(v_pom, -brake_F); 103 | safe(v_pom); 104 | 105 | p_rbsolver->addF(v_pom); 106 | } 107 | 108 | void Car2D::brake_end() 109 | { 110 | if (p_b_brake && dprod(p_v_prev, p_rbsolver->p_v) <= 0.f) 111 | zerov(p_rbsolver->p_v); 112 | if (p_b_brake && p_av_prev*p_rbsolver->p_av <= 0.f) 113 | p_rbsolver->p_av = 0.f; 114 | } 115 | 116 | float Car2D::add_sl_F() 117 | { 118 | float Fpom[2]; 119 | float Apom[2]; 120 | 121 | float sl_gain_pom = get_Fb_whfl_sl(Fpom, Apom); 122 | p_rbsolver->addFb(Fpom, Apom); 123 | 124 | sl_gain_pom = std::max(sl_gain_pom, get_Fb_whfr_sl(Fpom, Apom)); 125 | p_rbsolver->addFb(Fpom, Apom); 126 | 127 | sl_gain_pom = std::max(sl_gain_pom, get_Fb_whbl_sl(Fpom, Apom)); 128 | p_rbsolver->addFb(Fpom, Apom); 129 | 130 | sl_gain_pom = std::max(sl_gain_pom, get_Fb_whbr_sl(Fpom, Apom)); 131 | p_rbsolver->addFb(Fpom, Apom); 132 | 133 | return sl_gain_pom; 134 | // síla tření, použití pro zvuk - předělat 135 | float ret = sl_gain_pom/50000.f; 136 | if (ret < 0.3f) 137 | ret = (ret-0.2)*3; 138 | else if (ret > 1.f) 139 | ret = 1.f; 140 | if (ret < 0.f) 141 | ret = 0.f; 142 | return ret; 143 | } 144 | 145 | void Car2D::steer_left() 146 | { 147 | if (p_whl_a_i < 0) 148 | p_whl_a_i = 0; 149 | p_whl_a_i += 0.8*p_rbsolver->p_timesync->p_T; 150 | if (p_whl_a_i > 1.f) 151 | p_whl_a_i = 1.f; 152 | p_whr_a_i = p_whl_a_i; 153 | if (p_whl_a_ren_i < p_whl_a_i) 154 | { 155 | p_whl_a_ren_i += 8*p_rbsolver->p_timesync->p_T; 156 | if (p_whl_a_ren_i > p_whl_a_i) 157 | p_whl_a_ren_i = p_whl_a_i; 158 | } 159 | steer_aux(); 160 | } 161 | 162 | void Car2D::steer_right() 163 | { 164 | if (p_whl_a_i > 0) 165 | p_whl_a_i = 0; 166 | p_whl_a_i -= 0.8*p_rbsolver->p_timesync->p_T; 167 | if (p_whl_a_i < -1.f) 168 | p_whl_a_i = -1.f; 169 | p_whr_a_i = p_whl_a_i; 170 | if (p_whl_a_ren_i > p_whl_a_i) 171 | { 172 | p_whl_a_ren_i -= 8*p_rbsolver->p_timesync->p_T; 173 | if (p_whl_a_ren_i < p_whl_a_i) 174 | p_whl_a_ren_i = p_whl_a_i; 175 | } 176 | steer_aux(); 177 | } 178 | 179 | void Car2D::steer_center() 180 | { 181 | p_whl_a_i = 0; 182 | p_whr_a_i = p_whl_a_i; 183 | if (p_whl_a_ren_i > 0.f) 184 | { 185 | p_whl_a_ren_i -= 8*p_rbsolver->p_timesync->p_T; 186 | if (p_whl_a_ren_i < 0.f) 187 | p_whl_a_ren_i = 0.f; 188 | } 189 | else if (p_whl_a_ren_i < 0.f) 190 | { 191 | p_whl_a_ren_i += 8*p_rbsolver->p_timesync->p_T; 192 | if (p_whl_a_ren_i > 0.f) 193 | p_whl_a_ren_i = 0.f; 194 | } 195 | steer_aux(); 196 | } 197 | 198 | void Car2D::steer_aux() 199 | { 200 | float whl_a_max = (-logf((len(p_rbsolver->p_v)*0.02+0.2)*0.8)+0.56)*0.3+0.25; 201 | if (whl_a_max < 0.25) 202 | whl_a_max = 0.25; 203 | whl_a_max -= 0.125; 204 | whl_a_max *= M_PI*0.25; 205 | p_whl_a = p_whl_a_i*whl_a_max; 206 | p_whr_a = p_whr_a_i*whl_a_max; 207 | p_whl_a_ren = whl_a_max*p_whl_a_ren_i; 208 | } 209 | 210 | float get_acc_aux0(float v) 211 | { 212 | if (v > 40) 213 | return 0; 214 | if (v > 28) 215 | return 0.6*1.5; 216 | if (v > 18) 217 | return 1*1.5; 218 | if (v > 10) 219 | return 1.3*1.5; 220 | if (v > 1) 221 | return 5*1.5; 222 | return 10; 223 | } 224 | 225 | float Car2D::get_acc_aux() 226 | { 227 | return get_acc_aux0(len(p_rbsolver->p_v))*1.2; 228 | } 229 | 230 | float Car2D::get_rev_aux() 231 | { 232 | float v = len(p_rbsolver->p_v); 233 | if (v > 10) 234 | return 0; 235 | if (v > 1) 236 | return 3; 237 | return 10; 238 | } 239 | 240 | void Car2D::get_Fb_whl_acc(float F[2], float A[2]) // získání síly zadního kola při sešlápnutém plynu 241 | { 242 | F[0] = p_rbsolver->p_m*get_acc_aux()*0.5; 243 | F[1] = 0; 244 | A[0] = p_whb_x; 245 | A[1] = p_whb_y; 246 | } 247 | 248 | void Car2D::get_Fb_whr_acc(float F[2], float A[2]) 249 | { 250 | F[0] = p_rbsolver->p_m*get_acc_aux()*0.5; // zrychlení je zhruba 10 m.s^-1 251 | F[1] = 0; 252 | A[0] = p_whb_x; 253 | A[1] = -p_whb_y; 254 | } 255 | 256 | void Car2D::get_Fb_whl_rev(float F[2], float A[2]) // získání síly zadního kola při sešlápnutém plynu 257 | { 258 | F[0] = -p_rbsolver->p_m*get_rev_aux()*0.5; 259 | F[1] = 0; 260 | A[0] = p_whb_x; 261 | A[1] = p_whb_y; 262 | } 263 | 264 | void Car2D::get_Fb_whr_rev(float F[2], float A[2]) 265 | { 266 | F[0] = -p_rbsolver->p_m*get_rev_aux()*0.5; 267 | F[1] = 0; 268 | A[0] = p_whb_x; 269 | A[1] = -p_whb_y; 270 | } 271 | 272 | float Car2D::get_Fb_wh_sl_aux(float F[2], const float A[2], float sl_ratio1, float wh_a) 273 | { 274 | float tm[2]; 275 | p_rbsolver->get_tm(tm); 276 | float r[2]; 277 | RBf::rot(r, tm, A); 278 | RBf::perp(r); 279 | RBf::lmul(r, p_rbsolver->p_av); 280 | RBf::ladd(r, p_rbsolver->p_v); // v' = v + av*r 281 | typedef float floatv[2]; 282 | floatv& v = r; 283 | float va = atan2(v[1], v[0]); // úhel rychlosti 284 | float wa = p_rbsolver->p_ax+wh_a; // úhel kol 285 | float da = wa-va; // rozdíl úhlů 286 | float sa = sinf(da); // sin da 287 | 288 | float delka = sa*sqrtf(RBf::len(v))*p_rbsolver->p_m*p_rbsolver->p_am/100; 289 | 290 | F[0] = -sinf(wh_a)*delka; 291 | F[1] = cosf(wh_a)*delka; 292 | 293 | float delka_F = len(F); 294 | float sl_F = p_rbsolver->p_m/4*10*sl_ratio1; 295 | if (delka_F > sl_F) 296 | { 297 | ldiv(F, delka_F); 298 | lmul(F, sl_F); 299 | } 300 | 301 | return std::max(0.0f, delka_F-sl_F); 302 | } 303 | 304 | float Car2D::get_Fb_whfl_sl(float F[2], float A[2]) // získání síly zatáčení levého předního kola (v potaz se bere předchozí rychlost) 305 | { 306 | A[0] = p_whf_x; 307 | A[1] = p_whf_y; 308 | return get_Fb_wh_sl_aux(F, A, g_front_slip_ratio, p_whl_a); 309 | } 310 | 311 | float Car2D::get_Fb_whfr_sl(float F[2], float A[2]) 312 | { 313 | A[0] = p_whf_x; 314 | A[1] = -p_whf_y; 315 | return get_Fb_wh_sl_aux(F, A, g_front_slip_ratio, p_whr_a); 316 | } 317 | 318 | float Car2D::get_Fb_whbl_sl(float F[2], float A[2]) // získání síly zatáčení levého předního kola (v potaz se bere předchozí rychlost) 319 | { 320 | A[0] = p_whb_x; 321 | A[1] = p_whb_y; 322 | return get_Fb_wh_sl_aux(F, A, g_back_slip_ratio); 323 | } 324 | 325 | float Car2D::get_Fb_whbr_sl(float F[2], float A[2]) 326 | { 327 | A[0] = p_whb_x; 328 | A[1] = -p_whb_y; 329 | return get_Fb_wh_sl_aux(F, A, g_back_slip_ratio); 330 | } 331 | 332 | float Car2D::get_engine_pitch() 333 | { 334 | if (!p_b_acc && !p_b_brake) 335 | return p_engine_pitch; 336 | 337 | float ret = 1.0f; 338 | float v = len(p_rbsolver->p_v); 339 | 340 | if (p_rbsolver->v_a_dprod() < 0.0f) 341 | { 342 | v /= 10.f; 343 | v *= 0.4f; 344 | v += 1.f; 345 | ret = v; 346 | if (ret > 1.4f) 347 | ret = 1.4f; 348 | p_engine_pitch = ret; 349 | return v; 350 | } 351 | 352 | if (v > 40) 353 | { 354 | ret = 1.4; 355 | } 356 | else if (v > 28) 357 | { 358 | v -= 28.f; 359 | v /= (40.f-28.f); 360 | v *= 0.4f; 361 | v += 1.f; 362 | ret = v; 363 | } 364 | else if (v > 18) 365 | { 366 | v -= 18.f; 367 | v /= (28.f-18.f); 368 | v *= 0.4f; 369 | v += 1.f; 370 | ret = v; 371 | } 372 | else if (v > 10) 373 | { 374 | v -= 10.f; 375 | v /= (18.f-10.f); 376 | v *= 0.4f; 377 | v += 1.f; 378 | ret = v; 379 | } else { 380 | v /= 10.f; 381 | v *= 0.4f; 382 | v += 1.f; 383 | ret = v; 384 | } 385 | if (ret > 1.4f) 386 | ret = 1.4f; 387 | p_engine_pitch = ret; 388 | return ret; 389 | } 390 | -------------------------------------------------------------------------------- /src/rbsolver.cpp: -------------------------------------------------------------------------------- 1 | #include "rbsolver.h" 2 | #include 3 | 4 | using namespace RBf; 5 | 6 | void TimeSync::init(float T) 7 | { 8 | p_T = T; 9 | p_prevT = 0.f; 10 | } 11 | 12 | void TimeSync::add_deltaT(float deltaT) 13 | { 14 | p_prevT += deltaT; 15 | } 16 | 17 | bool TimeSync::step() 18 | { 19 | if (p_prevT >= p_T) 20 | { 21 | p_prevT -= p_T; 22 | return true; 23 | } 24 | return false; 25 | } 26 | 27 | void RBSolver::get_vp(float* vp, float* pp, const float* pt) const 28 | { 29 | sub(pp, pt, p_x); 30 | perp(pp); 31 | mul(vp, pp, p_av); 32 | ladd(vp, p_v); 33 | } 34 | 35 | void damp_v(float* p_v, float f/*součinitel smykového tření*/, float p_T) 36 | { 37 | float a = f*10; 38 | float dv = a*p_T; 39 | if (len2(p_v) > dv*dv) 40 | { 41 | float v[2]; 42 | norm(v, p_v); 43 | lmul(v, dv); 44 | safe(v); 45 | lsub(p_v, v); 46 | } else { 47 | zerov(p_v); 48 | } 49 | } 50 | 51 | void RBSolver::damp_v(float f/*součinitel smykového tření*/) 52 | { 53 | float a = f*10; 54 | float dv = a*p_timesync->p_T; 55 | if (len2(p_v) > dv*dv) 56 | { 57 | float v[2]; 58 | norm(v, p_v); 59 | lmul(v, dv); 60 | safe(v); 61 | lsub(p_v, v); 62 | } else { 63 | zerov(p_v); 64 | } 65 | } 66 | 67 | void RBSolver::damp_av(float f, float r) 68 | { 69 | float Ft = f*p_m*10; 70 | float Mt = 0.66667*Ft*r; 71 | float aa = Mt/p_am; 72 | float d_av = aa*p_timesync->p_T; 73 | if (fabs(p_av) > d_av) 74 | { 75 | if (p_av >= 0.f) 76 | p_av -= d_av; 77 | else 78 | p_av += d_av; 79 | } else { 80 | p_av = 0.f; 81 | } 82 | } 83 | 84 | struct BBox_ln { 85 | unsigned int b_ln; 86 | unsigned int i0,i1; 87 | }; 88 | 89 | // přidat podporu ibound - DONE 90 | // zpřehlednit kód, m_o a m_o2 předělat z referencí na ukazatele! 91 | void bbox_create(std::vector &bbox, unsigned int& size, float* center, const T3dm* t3dm) 92 | { 93 | int i_tst = t3dm->getgidobj(1); 94 | if (t3dm->p_o.size() == 0 || i_tst == -1) 95 | { 96 | bbox.clear(); 97 | size = 0; 98 | return; 99 | } 100 | const O3dm& m_o = t3dm->p_o[i_tst]; 101 | if (m_o.p_i.size() == 0) 102 | { 103 | bbox.clear(); 104 | size = 0; 105 | return; 106 | } 107 | unsigned int ln_sz = m_o.p_i.size()/3*3; 108 | unsigned int ln_sz2 = 0; 109 | 110 | int i_tst2 = t3dm->getgidobj(3); // ibound 111 | bool bobj2 = true; 112 | if (t3dm->p_o.size() == 0 || i_tst2 == -1) 113 | { 114 | bobj2 = false; 115 | } 116 | const O3dm& m_o2 = t3dm->p_o[bobj2?i_tst2:i_tst]; // i_tst je tam proto, aby tam něco bylo 117 | if (m_o2.p_i.size() == 0) 118 | { 119 | bobj2 = false; 120 | } 121 | if (bobj2) 122 | ln_sz2 = m_o2.p_i.size()/3*3; 123 | { 124 | std::vector b_ln(ln_sz+ln_sz2); 125 | for (unsigned int i = 0; i != ln_sz; ++i) 126 | { 127 | b_ln[i].b_ln = 1; 128 | // indexy jednotlivých linek 129 | b_ln[i].i0 = m_o.p_i[i]; 130 | if (i%3 == 2) 131 | b_ln[i].i1 = m_o.p_i[i-2]; 132 | else 133 | b_ln[i].i1 = m_o.p_i[i+1]; 134 | } 135 | for (unsigned int i = 0; i != ln_sz2; ++i) 136 | { 137 | b_ln[i+ln_sz].b_ln = 1; 138 | // indexy jednotlivých linek 139 | b_ln[i+ln_sz].i1 = m_o2.p_i[i]; 140 | if (i%3 == 2) 141 | b_ln[i+ln_sz].i0 = m_o2.p_i[i-2]; 142 | else 143 | b_ln[i+ln_sz].i0 = m_o2.p_i[i+1]; 144 | } 145 | ln_sz += ln_sz2; 146 | 147 | for (unsigned int i = 0; i != ln_sz; ++i) 148 | { 149 | float f_i0[2] = {t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i0+2], t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i0]}; 150 | float f_i1[2] = {t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i1+2], t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i1]}; 151 | for (unsigned int j = 0; j != ln_sz; ++j) 152 | { 153 | float f_i0_2[2] = {t3dm->p_v[(size_t)T3dmA::Count*b_ln[j].i0+2], t3dm->p_v[(size_t)T3dmA::Count*b_ln[j].i0]}; 154 | float f_i1_2[2] = {t3dm->p_v[(size_t)T3dmA::Count*b_ln[j].i1+2], t3dm->p_v[(size_t)T3dmA::Count*b_ln[j].i1]}; 155 | 156 | if (equals(f_i0, f_i0_2) && b_ln[i].i0 > b_ln[j].i0) 157 | b_ln[i].i0 = b_ln[j].i0; 158 | if (equals(f_i0, f_i1_2) && b_ln[i].i0 > b_ln[j].i1) 159 | b_ln[i].i0 = b_ln[j].i1; 160 | if (equals(f_i1, f_i0_2) && b_ln[i].i1 > b_ln[j].i0) 161 | b_ln[i].i1 = b_ln[j].i0; 162 | if (equals(f_i1, f_i1_2) && b_ln[i].i1 > b_ln[j].i1) 163 | b_ln[i].i1 = b_ln[j].i1; 164 | } 165 | } 166 | for (unsigned int i = 0; i != ln_sz; ++i) { // vyhození neokrajových linek 167 | for (unsigned int j = 0; j != ln_sz; ++j) { 168 | if (b_ln[i].i0 == b_ln[j].i1 && b_ln[i].i1 == b_ln[j].i0) // linka je tam dvakrát 169 | { 170 | b_ln[i].b_ln = 0; 171 | break; 172 | } 173 | } 174 | } 175 | size = 0; 176 | for (unsigned int i = 0; i != ln_sz; ++i) // zjištění počtu nevyhozených linek 177 | { 178 | if (b_ln[i].b_ln) 179 | { 180 | ++size; 181 | } 182 | } 183 | bbox.resize(size); 184 | 185 | center[0] = t3dm->p_cen[5]; 186 | center[1] = t3dm->p_cen[3]; 187 | 188 | for (unsigned int i = 0, j = 0; i != ln_sz; ++i) // zjištění souřadnic okrajových linek 189 | { 190 | if (b_ln[i].b_ln) 191 | { 192 | bbox[j].x[0] = t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i0+(size_t)T3dmA::Pos2]; 193 | bbox[j].x[1] = t3dm->p_v[(size_t)T3dmA::Count*b_ln[i].i0+(size_t)T3dmA::Pos0]; 194 | 195 | ladd(bbox[j].x, center); // přepočet do absolutních souřadnic podle středu objektu 196 | 197 | bbox[j].v [0] = 0.f; 198 | bbox[j].v [1] = 1.f; 199 | bbox[j].v1[0] = 0.f; 200 | bbox[j].v1[1] = 1.f; 201 | bbox[j].n1[0] = 1.f; 202 | bbox[j].n1[1] = 0.f; 203 | bbox[j].bnconv = 0; 204 | 205 | bbox[j].next = 0;//bbox; 206 | for (unsigned int k = 0, l = 0; k != ln_sz; ++k) 207 | { 208 | if (b_ln[k].b_ln) 209 | { 210 | if (b_ln[i].i1 == b_ln[k].i0) 211 | { 212 | bbox[j].next = bbox.data()+l; 213 | break; 214 | } 215 | ++l; 216 | } 217 | } 218 | ++j; 219 | } 220 | } 221 | } 222 | 223 | for (unsigned int i = 0; i != size; ++i) // zjištění, zda navazují (ukazatelem) všechny linky 224 | { 225 | if (bbox[i].next == 0) 226 | { 227 | bbox[i].next = bbox.data(); 228 | } 229 | } 230 | 231 | for (unsigned int i = 0; i != size; ++i) // výpočet směrových vektorů linek 232 | { 233 | bbox[i].v[0] = bbox[i].next->x[0] - bbox[i].x[0]; 234 | bbox[i].v[1] = bbox[i].next->x[1] - bbox[i].x[1]; 235 | norm_s(bbox[i].v1, bbox[i].v); 236 | } 237 | for (unsigned int i = 0; i != size; ++i) // výpočet os úhlů, osy míří dovnitř objektu 238 | { 239 | add(bbox[i].next->n1, bbox[i].v1, bbox[i].next->v1); 240 | perp(bbox[i].next->n1); 241 | norm_s(bbox[i].next->n1); 242 | if (dist(bbox[i].x, bbox[i].next->x, bbox[i].next->v1) < 0.f) // vrchol je nekonvexní 243 | { 244 | bbox[i].next->bnconv = 1; 245 | } 246 | } 247 | } 248 | 249 | void RBSolver::init(const float* x, float ax, const float* v, float av, float m, float am, const TimeSync* timesync, const T3dm* t3dm) 250 | { 251 | p_x0[0] = p_x[0] = x[0]; 252 | p_x0[1] = p_x[1] = x[1]; 253 | p_v[0] = v[0]; 254 | p_v[1] = v[1]; 255 | p_ax0 = p_ax = ax; 256 | p_av = av; 257 | p_m = m; 258 | p_am = am; 259 | p_bupdm = true; 260 | p_timesync = timesync; 261 | zerov(p_F); 262 | p_aF = 0.f; 263 | float center[2]; 264 | bbox_create(p_bbox, p_bbox_sz, center, t3dm); 265 | p_bbox_rot.resize(p_bbox_sz); 266 | for (unsigned int i = 0; i != p_bbox_sz; ++i) 267 | { 268 | p_bbox_rot[i].next = p_bbox_rot.data()+(p_bbox[i].next-p_bbox.data()); // nic moc kód 269 | } 270 | p_bcolprev = true; 271 | } 272 | 273 | void RBSolver::addF(const float* F, const float* A) 274 | { 275 | ladd(p_F, F); 276 | if (A) 277 | { 278 | p_aF += len(F)*safe(dist(p_x, A, F)); 279 | } 280 | } 281 | 282 | float RBSolver::v_a_dprod() 283 | { 284 | float ang_vec[2] = {cosf(p_ax), sinf(p_ax)}; 285 | return dprod(p_v, ang_vec); 286 | } 287 | 288 | void RBSolver::addFb(const float* F, const float* A) 289 | { 290 | if (p_bupdm) // pokud rotační matice (jenom hodnota sin a cos alfa) ještě není vytvořena 291 | { 292 | p_bupdm = false; 293 | rot(p_tm, p_ax); // vytvoř rotační matici 294 | } 295 | float F1[2]; // transformovaná síla 296 | rot(F1, p_tm, F); // transformace síly 297 | ladd(p_F, F1); 298 | if (A) // pokud síla nepůsobí v těžišti 299 | { 300 | float b_x[] = {0, 0}; 301 | p_aF += len(F)*safe(dist(b_x, A, F)); 302 | } 303 | } 304 | 305 | void RBSolver::update(bool bstep) 306 | { 307 | p_bupdm = true; 308 | if (bstep) 309 | { 310 | cpy(p_x_prev, p_x); 311 | p_ax_prev = p_ax; 312 | 313 | div(p_a, p_F, p_m); // p_a = p_F / p_m 314 | p_aa = p_aF/p_am; 315 | ladd(p_v, mul(p_a, p_timesync->p_T)); // p_v += p_a * p_T; 316 | p_av += p_aa*p_timesync->p_T; // úhlová rychlost += úhlové zrychlení * T 317 | ladd(p_x, mul(p_v, p_timesync->p_T)); // p_x += p_v * p_T; 318 | p_ax += p_av*p_timesync->p_T; 319 | 320 | zerov(p_F); 321 | p_aF = 0; 322 | } else { 323 | float a0[2]; 324 | div(a0, p_F, p_m); // p_a = p_F / p_m 325 | float aa0 = p_aF/p_am; 326 | float v0[2]; 327 | add(v0, p_v, mul(a0, p_timesync->p_prevT)); // p_v += p_a * p_T; 328 | float av0 = p_av+aa0*p_timesync->p_prevT; // úhlová rychlost += úhlové zrychlení * T 329 | add(p_x0, p_x, mul(v0, p_timesync->p_prevT)); // p_x += p_v * p_T; 330 | p_ax0 = p_ax+av0*p_timesync->p_prevT; 331 | 332 | zerov(p_F); 333 | p_aF = 0; 334 | } 335 | } 336 | 337 | void RBSolver::get_tm(float* tm) 338 | { 339 | if (p_bupdm) 340 | { 341 | p_bupdm = false; 342 | rot(p_tm, p_ax); // vytvoř rotační matici 343 | } 344 | cpy(tm, p_tm); 345 | } 346 | 347 | -------------------------------------------------------------------------------- /src/gamemenu.cpp: -------------------------------------------------------------------------------- 1 | #include "gamemng.h" 2 | #include "mainmenu.h" 3 | 4 | #include 5 | 6 | /* 7 | Restart Race 8 | Test Keys -> GMSTATE_T 9 | Options 10 | End Race 11 | Quit to Menu 12 | */ 13 | 14 | void Gamemenu::init() 15 | { 16 | float font_color[4] = {0.6, 0.6, 0.6, 1}; 17 | gltext_menu.init(40, 6, 2.f, 0, 0, &(p_gamemng->p_glfont), font_color); 18 | gltext_menu.set_pos(0.f, 0.f); 19 | gltext_menu.puts(0, 20 | "Restart Race\n" 21 | "Test Keys\n" 22 | "Options\n" 23 | "End Race\n" 24 | "Quit to Menu\n" 25 | ); 26 | 27 | p_text_opt.init(40, 5, 2.f, 0, 0, &(p_gamemng->p_glfont), font_color); 28 | p_text_opt.set_pos(0.f, 0.f); 29 | p_text_opt.puts(0, 30 | STRING_OPTIONS_TITLE 31 | ); 32 | 33 | p_text_opt2.init(40, 5, 2.f, -1, 0, &(p_gamemng->p_glfont), font_color); 34 | p_text_opt2.set_pos(0.f, 0.f); 35 | p_text_opt2.puts(0, 36 | STRING_OPTIONS_LABELS 37 | ); 38 | 39 | p_text_opt3.init(40, 5, 2.f, 1, 0, &(p_gamemng->p_glfont), font_color); 40 | p_text_opt3.set_pos(0.f, 0.f); 41 | p_text_opt3.puts(0, 42 | STRING_OPTIONS_ARROWS 43 | ); 44 | 45 | // 24 prvků 46 | float ycmin = -0.7f*0.319f, ycmax = 0.7f*0.319f; 47 | float xcmin = 0.f*0.319f, xcmax = 8.f*0.319f; 48 | float xposun = 4.3f*0.319f; 49 | p_opt_verts[0] = xcmin+xposun; 50 | p_opt_verts[1] = ycmin; 51 | p_opt_verts[2] = -10; 52 | 53 | p_opt_verts[3] = xcmax+xposun; 54 | p_opt_verts[4] = ycmin; 55 | p_opt_verts[5] = -10; 56 | 57 | p_opt_verts[6] = xcmax+xposun; 58 | p_opt_verts[7] = ycmax; 59 | p_opt_verts[8] = -10; 60 | 61 | p_opt_verts[9] = xcmin+xposun; 62 | p_opt_verts[10] = ycmax; 63 | p_opt_verts[11] = -10; 64 | 65 | /////////////////////////// 66 | float yposun = -2.f*0.319f; 67 | 68 | p_opt_verts[12] = p_opt_verts[0]; 69 | p_opt_verts[13] = p_opt_verts[1]+yposun; 70 | p_opt_verts[14] = p_opt_verts[2]; 71 | 72 | p_opt_verts[15] = p_opt_verts[3]; 73 | p_opt_verts[16] = p_opt_verts[4]+yposun; 74 | p_opt_verts[17] = p_opt_verts[5]; 75 | 76 | p_opt_verts[18] = p_opt_verts[6]; 77 | p_opt_verts[19] = p_opt_verts[7]+yposun; 78 | p_opt_verts[20] = p_opt_verts[8]; 79 | 80 | p_opt_verts[21] = p_opt_verts[9]; 81 | p_opt_verts[22] = p_opt_verts[10]+yposun; 82 | p_opt_verts[23] = p_opt_verts[11]; 83 | 84 | p_bufUpdated = false; 85 | 86 | GLuint tmpBuf; 87 | glGenBuffers(1, &tmpBuf); 88 | p_buf = tmpBuf; 89 | glGenBuffers(1, &tmpBuf); 90 | p_elemBuf = tmpBuf; 91 | 92 | glBindBuffer(GL_ARRAY_BUFFER, p_buf); 93 | glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(float), 0, GL_DYNAMIC_DRAW); 94 | glBindBuffer(GL_ARRAY_BUFFER, 0); 95 | 96 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_elemBuf); 97 | static const GLushort quad0_1[12] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 }; 98 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad0_1), quad0_1, GL_STATIC_DRAW); 99 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 100 | } 101 | 102 | void Gamemenu::render() 103 | { 104 | 105 | if (state >= GMSTATE_RESTART && state <= GMSTATE_QUIT) 106 | { 107 | gltext_menu.render_c(&p_gamemng->p_shadermng); 108 | } 109 | else if (state >= GMSTATE_O_SOUNDVOL && state <= GMSTATE_O_VIEWDIST) 110 | { 111 | p_text_opt.render_c(&p_gamemng->p_shadermng); 112 | p_text_opt2.render_c(&p_gamemng->p_shadermng); 113 | p_text_opt3.render_c(&p_gamemng->p_shadermng); 114 | p_gamemng->p_shadermng.use(ShaderId::Color); 115 | p_gamemng->p_shadermng.set(ShaderUniMat4::ModelViewMat, glm::mat4(1)); 116 | glDisable(GL_BLEND); checkGL(); 117 | glBindBuffer(GL_ARRAY_BUFFER, p_buf); checkGL(); 118 | if (!p_bufUpdated) 119 | { 120 | p_bufUpdated = true; 121 | glBufferSubData(GL_ARRAY_BUFFER, 0, 24 * sizeof(float), p_opt_verts); checkGL(); 122 | } 123 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_elemBuf); checkGL(); 124 | glEnableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 125 | glVertexAttribPointer((GLuint)ShaderAttrib::Pos, 3, GL_FLOAT, GL_FALSE, 0, 0); 126 | glVertexAttrib3fv((GLuint)ShaderAttrib::Color, p_opt_color0); checkGL(); 127 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); checkGL(); 128 | glVertexAttrib3fv((GLuint)ShaderAttrib::Color, p_opt_color1); checkGL(); 129 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)(sizeof(GLushort)*6)); checkGL(); 130 | glDisableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 131 | glBindBuffer(GL_ARRAY_BUFFER, 0); 132 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 133 | } 134 | } 135 | 136 | void Gamemenu::keydown(unsigned int sym) 137 | { 138 | if (!bmenu) 139 | { 140 | if (sym == SDLK_ESCAPE) 141 | { 142 | p_gamemng->gamemenu_sw(false); 143 | } 144 | else if ((sym == SDLK_RETURN || sym == SDLK_KP_ENTER) && p_gamemng->p_state == 2) 145 | { 146 | p_gamemng->gamemenu_sw(false); 147 | } 148 | else return; 149 | } else { 150 | switch (state) 151 | { 152 | case GMSTATE_RESTART: 153 | if (sym == SDLK_ESCAPE) p_gamemng->gamemenu_sw(true); 154 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) 155 | { 156 | p_gamemng->gamemenu_sw(true); 157 | p_gamemng->restart(); 158 | } 159 | else if (sym == SDLK_DOWN) state = p_gamemng->p_state != 2 ? GMSTATE_TEST : GMSTATE_OPTIONS; 160 | else if (sym == SDLK_UP) state = GMSTATE_QUIT; 161 | break; 162 | case GMSTATE_TEST: 163 | if (sym == SDLK_ESCAPE) p_gamemng->gamemenu_sw(true); 164 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) state = GMSTATE_T; 165 | else if (sym == SDLK_DOWN) state = GMSTATE_OPTIONS; 166 | else if (sym == SDLK_UP) state = GMSTATE_RESTART; 167 | break; 168 | case GMSTATE_OPTIONS: 169 | if (sym == SDLK_ESCAPE) p_gamemng->gamemenu_sw(true); 170 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) state = GMSTATE_O_SOUNDVOL; 171 | else if (sym == SDLK_DOWN) state = p_gamemng->p_state != 2 ? GMSTATE_END : GMSTATE_QUIT; 172 | else if (sym == SDLK_UP) state = p_gamemng->p_state != 2 ? GMSTATE_TEST : GMSTATE_RESTART; 173 | break; 174 | case GMSTATE_END: 175 | if (sym == SDLK_ESCAPE) p_gamemng->gamemenu_sw(true); 176 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) 177 | { 178 | p_gamemng->gamemenu_sw(true); 179 | p_gamemng->end_race(); 180 | } 181 | else if (sym == SDLK_DOWN) state = GMSTATE_QUIT; 182 | else if (sym == SDLK_UP) state = GMSTATE_OPTIONS; 183 | break; 184 | case GMSTATE_QUIT: 185 | if (sym == SDLK_ESCAPE) p_gamemng->gamemenu_sw(true); 186 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) 187 | { 188 | p_settings->set("sound_volume", p_gamemng->get_global_volume()); 189 | p_settings->set("view_distance", p_gamemng->get_far()); 190 | p_gamemng->gamemenu_sw(true); 191 | p_gamemng->quit_race(); // vypne zvuk 192 | p_menu->menu(); 193 | } 194 | else if (sym == SDLK_DOWN) state = GMSTATE_RESTART; 195 | else if (sym == SDLK_UP) state = p_gamemng->p_state != 2 ? GMSTATE_END : GMSTATE_OPTIONS; 196 | break; 197 | case GMSTATE_T: 198 | if (sym == SDLK_ESCAPE) state = GMSTATE_TEST; 199 | break; 200 | case GMSTATE_O_SOUNDVOL: 201 | if (sym == SDLK_ESCAPE) state = GMSTATE_OPTIONS; 202 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) state = GMSTATE_OPTIONS; 203 | else if (sym == SDLK_LEFT || sym == SDLK_RIGHT) 204 | { 205 | if (sym == SDLK_LEFT) 206 | { 207 | p_gamemng->set_global_volume(p_gamemng->get_global_volume()-5); 208 | } 209 | else 210 | { 211 | p_gamemng->set_global_volume(p_gamemng->get_global_volume()+5); 212 | } 213 | p_gamemng->p_sound_game_static.playSoundTest(p_gamemng->get_global_volume() * 0.01f); 214 | } 215 | else if (sym == SDLK_DOWN) state = GMSTATE_O_VIEWDIST; 216 | else if (sym == SDLK_UP) state = GMSTATE_O_VIEWDIST; 217 | break; 218 | case GMSTATE_O_VIEWDIST: 219 | if (sym == SDLK_ESCAPE) state = GMSTATE_OPTIONS; 220 | else if (sym == SDLK_RETURN || sym == SDLK_KP_ENTER) state = GMSTATE_OPTIONS; 221 | else if (sym == SDLK_LEFT) { p_gamemng->set_far(p_gamemng->get_far()-1); } 222 | else if (sym == SDLK_RIGHT) { p_gamemng->set_far(p_gamemng->get_far()+1); } 223 | else if (sym == SDLK_DOWN) state = GMSTATE_O_SOUNDVOL; 224 | else if (sym == SDLK_UP) state = GMSTATE_O_SOUNDVOL; 225 | break; 226 | } 227 | } 228 | float font_color[4] = {0.6, 0.6, 0.6, 1}; 229 | float font_color_hi[4] = {1, 1, 1, 1}; 230 | if (state >= GMSTATE_RESTART && state <= GMSTATE_QUIT) 231 | { 232 | if (p_gamemng->p_state != 2) 233 | { 234 | gltext_menu.puts(0, 235 | "Restart Race\n" 236 | "Test Keys\n" 237 | "Options\n" 238 | "End Race\n" 239 | "Quit to Menu\n" 240 | ); 241 | gltext_menu.set_color(font_color); 242 | gltext_menu.set_color(state - GMSTATE_RESTART, font_color_hi); 243 | } else { 244 | gltext_menu.puts(0, 245 | "\n" 246 | "Restart Race\n" 247 | "Options\n" 248 | "Quit to Menu\n" 249 | "\n" 250 | ); 251 | gltext_menu.set_color(font_color); 252 | if (state == GMSTATE_RESTART) gltext_menu.set_color(1, font_color_hi); 253 | else if (state == GMSTATE_OPTIONS) gltext_menu.set_color(2, font_color_hi); 254 | else if (state == GMSTATE_QUIT) gltext_menu.set_color(3, font_color_hi); 255 | } 256 | } 257 | else if (state >= GMSTATE_O_SOUNDVOL && state <= GMSTATE_O_VIEWDIST) 258 | { 259 | p_text_opt2.set_color(font_color); 260 | p_text_opt2.set_color(state-GMSTATE_O_SOUNDVOL+2, font_color_hi); 261 | p_text_opt3.set_color(font_color); 262 | p_text_opt3.set_color(state-GMSTATE_O_SOUNDVOL+2, font_color_hi); 263 | 264 | 265 | p_opt_color0[0] = p_opt_color0[1] = p_opt_color0[2] = (state == GMSTATE_O_SOUNDVOL) ? 1.f : 0.6f; 266 | p_opt_color1[0] = p_opt_color1[1] = p_opt_color1[2] = (state == GMSTATE_O_SOUNDVOL) ? 0.6f : 1.f; 267 | 268 | float xcmax = 8.f*0.319f; 269 | float xposun = 4.3f*0.319f; 270 | 271 | p_opt_verts[3] = xcmax*p_gamemng->get_global_volume()*0.01f+xposun; 272 | p_opt_verts[6] = xcmax*p_gamemng->get_global_volume()*0.01f+xposun; 273 | 274 | p_opt_verts[15] = xcmax*p_gamemng->get_far()*0.1f+xposun; 275 | p_opt_verts[18] = xcmax*p_gamemng->get_far()*0.1f+xposun; 276 | 277 | p_bufUpdated = false; 278 | } 279 | } 280 | 281 | void Gamemng::gamemenu_sw(bool b_quit) 282 | { 283 | if (b_quit) 284 | p_gamemenu.bmenu = false; 285 | else 286 | { 287 | p_gamemenu.bmenu = true; 288 | p_gamemenu.state = GMSTATE_RESTART; 289 | } 290 | if (p_gamemenu.bmenu) 291 | { 292 | // zastav zvuky 293 | for (unsigned int i = 0; i != p_players; ++i) 294 | { 295 | p_sound_car[i].stop(); 296 | } 297 | //SDL_EnableKeyRepeat(500, 30); 298 | } else { 299 | // rozjeď zvuky - to udělá automaticky frame díky chytrému stop(); 300 | //SDL_EnableKeyRepeat(0, 0); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/gltext.cpp: -------------------------------------------------------------------------------- 1 | #include "load_texture.h" 2 | #include "gltext.h" 3 | #include "pict2.h" 4 | #include "gbuff_in.h" 5 | #include "matmng.h" 6 | #include 7 | #include "shadermng.h" 8 | 9 | void Glfont::set_texture(SharedGLtex texture) 10 | { 11 | p_texture = texture; 12 | } 13 | 14 | void Gltext::set_pos(float x, float y) 15 | { 16 | static const float scaletext = 0.319f; 17 | mtrx = glm::scale(glm::mat4(1), glm::vec3(scaletext, scaletext, 1.f)); 18 | mtrx = glm::translate(mtrx, glm::vec3(x, y, 0.f)); 19 | } 20 | 21 | void Gltext::render(GLuint texture, ShaderMng* shadermng, bool useColor, float scale) 22 | { 23 | glm::mat4 m = glm::scale(mtrx, glm::vec3(scale, scale, 1.f)); 24 | shadermng->set(ShaderUniMat4::ModelViewMat, m); 25 | shadermng->use(ShaderId::ColorTex); 26 | shadermng->set(ShaderUniInt::AlphaDiscard, (GLint)0); 27 | glBindTexture(GL_TEXTURE_2D, texture); checkGL(); 28 | glEnable(GL_BLEND); checkGL(); 29 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkGL(); 30 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); 31 | glEnableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 32 | glEnableVertexAttribArray((GLuint)ShaderAttrib::Tex); checkGL(); 33 | for (unsigned int i = 0; i != p_h; ++i) 34 | { 35 | glBindBuffer(GL_ARRAY_BUFFER, p_lines[i].buf); 36 | if (!p_lines[i].bufUpdated) 37 | { 38 | glBufferSubData(GL_ARRAY_BUFFER, 0, p_lines[i].vert.size() * sizeof(float), p_lines[i].vert.data()); 39 | p_lines[i].bufUpdated = true; 40 | } 41 | if (useColor) 42 | { 43 | glVertexAttrib4fv((GLuint)ShaderAttrib::Color, p_lines[i].color_b); 44 | } 45 | glVertexAttribPointer((GLuint)ShaderAttrib::Pos, 3, GL_FLOAT, GL_FALSE, sizeof(float)*5, 0); 46 | glVertexAttribPointer((GLuint)ShaderAttrib::Tex, 2, GL_FLOAT, GL_FALSE, sizeof(float)*5, (void*)(sizeof(float)*3)); 47 | glDrawElements(GL_TRIANGLES, p_lines[i].isize, GL_UNSIGNED_SHORT, 0); checkGL(); 48 | } 49 | glDisableVertexAttribArray((GLuint)ShaderAttrib::Pos); checkGL(); 50 | glDisableVertexAttribArray((GLuint)ShaderAttrib::Tex); checkGL(); 51 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 52 | glBindBuffer(GL_ARRAY_BUFFER, 0); 53 | glDisable(GL_BLEND); checkGL(); 54 | } 55 | 56 | void Gltext::render_c(GLuint texture, ShaderMng* shadermng) 57 | { 58 | render(texture, shadermng, true); 59 | } 60 | 61 | void Gltext::renderscale(float scale, GLuint texture, ShaderMng* shadermng) 62 | { 63 | render(texture, shadermng, false, scale); 64 | } 65 | 66 | unsigned int Glfont::get_char_i(char c) const 67 | { 68 | unsigned char uc = c; 69 | unsigned int ret = (unsigned int)uc; 70 | if (ret < p_charmap_start) 71 | ret = (unsigned int)p_defaultchar; 72 | else if (ret >= p_charmap_start+p_charmap_size) 73 | ret = (unsigned int)p_defaultchar; 74 | return ret; 75 | } 76 | 77 | void Gltext::puts(unsigned int i/*číslo řádku*/, const char* text) 78 | { 79 | for (;;) 80 | { 81 | if (i >= p_h) 82 | return; 83 | unsigned int utextsz = 0; 84 | while (text[utextsz] != '\n' && text[utextsz] != '\0') 85 | ++utextsz; 86 | // vypsat text 87 | // délka textu se omezí délkou alokovaného pole pro výpis textu 88 | unsigned int textsz1 = std::min(utextsz, p_w); // použitá délka řádku 89 | p_lines[i].size = textsz1*4; // počet vrcholů na řádku pro render 90 | p_lines[i].isize = textsz1*6; // počet vrcholů na řádku pro render 91 | float line_w = 0.f; // délka řádku je součet délek všech znaků a mezer mezi nimi, mezera je i za posledním znakem 92 | for (unsigned int i0 = 0; i0 != textsz1; ++i0) 93 | line_w += p_font->p_charmap[p_font->get_char_i(text[i0])].vertw + p_font->p_dist; 94 | line_w *= p_fontsize; // šířka se zvětší podle velikosti písma 95 | float line_left = 0.f; // levá relativní souřadnice textu (relativní k pozici p_pos) 96 | if (p_cen_x == 0) // střed 97 | line_left = -line_w*0.5f; 98 | else if (p_cen_x > 0) // zarovnání vlevo 99 | line_left = 0.f; 100 | else // p_cen_y < 0 // zarovnání vpravo 101 | line_left = -line_w; 102 | 103 | float char_left = 0.f; 104 | float char_right = 0.f; 105 | 106 | // nastavení obdélníka na pozadí 107 | p_lines[i].bkgrect[0] = p_lines[i].bkgrect[9] = line_left-p_font->p_dist; 108 | p_lines[i].bkgrect[3] = p_lines[i].bkgrect[6] = line_left+line_w; 109 | 110 | for (unsigned int j = 0; j != textsz1; ++j) 111 | { 112 | // x-ová souřadnice textu, ostatní byly nastaveny při inicializaci 113 | char_right = char_left + (p_font->p_charmap[p_font->get_char_i(text[j])].vertw)*p_fontsize; 114 | p_lines[i].vert[(j*4+0)*5+0] = line_left+char_left; 115 | p_lines[i].vert[(j*4+1)*5+0] = line_left+char_right; 116 | p_lines[i].vert[(j*4+2)*5+0] = line_left+char_right; 117 | p_lines[i].vert[(j*4+3)*5+0] = line_left+char_left; 118 | char_left = char_right + p_font->p_dist*p_fontsize; 119 | 120 | // texturové souřadnice 121 | p_lines[i].vert[(j*4+0)*5+3] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[0]; 122 | p_lines[i].vert[(j*4+1)*5+3] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[1]; 123 | p_lines[i].vert[(j*4+2)*5+3] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[1]; 124 | p_lines[i].vert[(j*4+3)*5+3] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[0]; 125 | 126 | p_lines[i].vert[(j*4+0)*5+4] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[2]; 127 | p_lines[i].vert[(j*4+1)*5+4] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[2]; 128 | p_lines[i].vert[(j*4+2)*5+4] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[3]; 129 | p_lines[i].vert[(j*4+3)*5+4] = p_font->p_charmap[p_font->get_char_i(text[j])].texc[3]; 130 | 131 | p_lines[i].bufUpdated = false; 132 | } 133 | // přechod na další řádek 134 | if (text[utextsz] == '\n') 135 | { 136 | ++i; 137 | text = text+utextsz+1; 138 | } 139 | else 140 | { 141 | break; 142 | } 143 | } 144 | } 145 | 146 | void Gltext::init(unsigned int w, unsigned int h, float fontsize, int cen_x, int cen_y, const Glfont* font, 147 | const float color_b[4]) 148 | { 149 | p_h = h; 150 | p_w = w; 151 | p_lines.resize(p_h); 152 | p_fontsize = fontsize; 153 | p_cen_x = cen_x; 154 | p_cen_y = cen_y; 155 | p_font = font; 156 | for (unsigned int i = 0; i != p_h; ++i) 157 | { 158 | memcpy(p_lines[i].color_b, color_b, sizeof(float)*4); 159 | p_lines[i].size = 0; // max p_w*4 160 | p_lines[i].vert.clear(); 161 | p_lines[i].vert.resize(p_w*4*5); 162 | 163 | GLuint tmpBuf; 164 | glGenBuffers(1, &tmpBuf); 165 | p_lines[i].buf = tmpBuf; 166 | glBindBuffer(GL_ARRAY_BUFFER, p_lines[i].buf); 167 | glBufferData(GL_ARRAY_BUFFER, p_lines[i].vert.size() * sizeof(float), 0, GL_DYNAMIC_DRAW); 168 | glBindBuffer(GL_ARRAY_BUFFER, 0); 169 | } 170 | indices.clear(); 171 | indices.resize(p_w*6); 172 | float text_h = float(p_h)*p_fontsize; 173 | float text_top = 0.f; 174 | if (p_cen_y == 0) 175 | text_top = text_h*0.5f; 176 | else if (p_cen_y > 0) 177 | text_top = text_h; 178 | else // p_cen_y < 0 179 | text_top = 0.f; 180 | 181 | for (unsigned int i = 0; i != p_h; ++i) 182 | { 183 | p_lines[i].bkgrect[0] = p_lines[i].bkgrect[3] = p_lines[i].bkgrect[6] = p_lines[i].bkgrect[9] = 0.f; 184 | p_lines[i].bkgrect[1] = p_lines[i].bkgrect[4] = text_top-(float(i)+1.f)*p_fontsize; 185 | p_lines[i].bkgrect[2] = p_lines[i].bkgrect[5] = p_lines[i].bkgrect[8] = p_lines[i].bkgrect[11] = -10.f; 186 | p_lines[i].bkgrect[7] = p_lines[i].bkgrect[10] = text_top-(float(i))*p_fontsize; 187 | for (unsigned int j = 0; j != p_w; ++j) 188 | { 189 | // z-ové souřadnice textu jsou napevno -10 190 | p_lines[i].vert[(j*4+0)*5+2] = -10.f; 191 | p_lines[i].vert[(j*4+1)*5+2] = -10.f; 192 | p_lines[i].vert[(j*4+2)*5+2] = -10.f; 193 | p_lines[i].vert[(j*4+3)*5+2] = -10.f; 194 | 195 | // x-ové souřadnice se inicializují na 0 196 | p_lines[i].vert[(j*4+0)*5+0] = 0.f; 197 | p_lines[i].vert[(j*4+1)*5+0] = 0.f; 198 | p_lines[i].vert[(j*4+2)*5+0] = 0.f; 199 | p_lines[i].vert[(j*4+3)*5+0] = 0.f; 200 | 201 | // souřadnice se odečítají, protože pozice se počítá odspodu 202 | p_lines[i].vert[(j*4+0)*5+1] = text_top-(float(i)+1.f)*p_fontsize; 203 | p_lines[i].vert[(j*4+1)*5+1] = text_top-(float(i)+1.f)*p_fontsize; 204 | p_lines[i].vert[(j*4+2)*5+1] = text_top-(float(i))*p_fontsize; 205 | p_lines[i].vert[(j*4+3)*5+1] = text_top-(float(i))*p_fontsize; 206 | } 207 | p_lines[i].bufUpdated = false; 208 | } 209 | 210 | for (unsigned int j = 0; j != p_w; ++j) 211 | { 212 | indices[j * 6 + 0] = j * 4 + 0; 213 | indices[j * 6 + 1] = j * 4 + 1; 214 | indices[j * 6 + 2] = j * 4 + 2; 215 | indices[j * 6 + 3] = j * 4 + 0; 216 | indices[j * 6 + 4] = j * 4 + 2; 217 | indices[j * 6 + 5] = j * 4 + 3; 218 | } 219 | 220 | GLuint tmpBuf; 221 | glGenBuffers(1, &tmpBuf); 222 | buf = tmpBuf; 223 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); 224 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), indices.data(), GL_STATIC_DRAW); 225 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 226 | } 227 | 228 | void Glfont::init(const unsigned int mapsize[2]/*počet znaků*/, const unsigned int mapsize1[2]/*rozměry jednoho znaku*/, unsigned int mapcharh, const char* mapfname) 229 | { 230 | p_charmap_start = 32; 231 | p_charmap_size = mapsize[0]*mapsize[1]; 232 | p_defaultchar = 127; 233 | p_dist = 0.1-0.12; 234 | 235 | Pict2 pict; 236 | gbuff_in.f_open(mapfname, "rb"); 237 | pict.loadpng(gbuff_in.fbuffptr(), gbuff_in.fbuffsz()); 238 | gbuff_in.fclose(); 239 | // 240 | 241 | for (unsigned int y0 = 0; y0 != mapsize[1]; ++y0) 242 | { 243 | for (unsigned int y1 = mapcharh; y1 != mapsize1[1]; ++y1) 244 | { 245 | for (unsigned int x = 0; x != (unsigned int)pict.w(); ++x) 246 | { 247 | *(pict.px(x, y0*mapsize1[1]+y1, 0)) = 0; 248 | } 249 | } 250 | } 251 | 252 | unsigned int i = p_charmap_start; 253 | for (unsigned int y = 0; y != mapsize[1]; ++y) 254 | { 255 | for (unsigned int x = 0; x != mapsize[0]; ++x) 256 | { 257 | 258 | p_charmap[i].texc[0] = float(x*mapsize1[0])/float(pict.w()); 259 | unsigned int char_w = 0; 260 | while (char_w < mapsize1[0] && *(pict.px(char_w+x*mapsize1[0], y*mapsize1[1], 0)) < 64) 261 | ++char_w; 262 | for (unsigned int x1 = x*mapsize1[0]+char_w; x1 != (x+1)*mapsize1[0]; ++x1) 263 | for (unsigned int y1 = y*mapsize1[1]; y1 != y*mapsize1[1]+mapcharh; ++y1) 264 | *(pict.px(x1, y1, 0)) = 0; 265 | p_charmap[i].texc[1] = float(x*mapsize1[0]+char_w)/float(pict.w()); 266 | p_charmap[i].texc[2] = float(y*mapsize1[1])/float(pict.h()); 267 | p_charmap[i].texc[3] = float(y*mapsize1[1]+mapcharh)/float(pict.h()); 268 | p_charmap[i].vertw = float(char_w)/float(mapsize1[1]); 269 | ++i; 270 | } 271 | } 272 | } 273 | 274 | void Gltext::set_bkgrect(const float* color) 275 | { 276 | p_b_bkgrect = color; 277 | if (p_b_bkgrect) 278 | memcpy(p_color_bkgrect, color, 4*sizeof(color)); 279 | } 280 | 281 | void Gltext::set_color(unsigned int i/*číslo řádku*/, const float color[4]) 282 | { 283 | if (i < p_h) 284 | memcpy(p_lines[i].color_b, color, 4*sizeof(float)); 285 | } 286 | 287 | void Gltext::set_color(const float color[4]) 288 | { 289 | for (unsigned int i = 0; i != p_h; ++i) 290 | { 291 | set_color(i/*číslo řádku*/, color); 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /src/gamemng.h: -------------------------------------------------------------------------------- 1 | #ifndef HLIDAC_GAMEMNG_H 2 | #define HLIDAC_GAMEMNG_H 3 | 4 | #include "3dm.h" 5 | #include "octopus.h" 6 | #include "matmng.h" 7 | #include "collider.h" 8 | #include "rbsolver.h" 9 | #include "car2d.h" 10 | #include "skysph.h" 11 | #include "gltext.h" 12 | #include "soundmng.h" 13 | #include "settings_dat.h" 14 | #include "ghost.h" 15 | #include "particles.h" 16 | #include "shadermng.h" 17 | 18 | #include 19 | #include 20 | #include "gl1.h" 21 | #include "gl_shared.h" 22 | 23 | #define STRING_OPTIONS_TITLE "Options\n\n\n\n" 24 | #define STRING_OPTIONS_LABELS "\n\nSound Volume:\nView Distance:" 25 | #define STRING_OPTIONS_ARROW "< >" 26 | #define STRING_OPTIONS_ARROWS "\n\n " STRING_OPTIONS_ARROW "\n " STRING_OPTIONS_ARROW "\n" 27 | 28 | enum Gamemenu_states { 29 | GMSTATE_RESTART = 0, GMSTATE_TEST, GMSTATE_OPTIONS, GMSTATE_END, GMSTATE_QUIT, 30 | GMSTATE_T, 31 | GMSTATE_O_SOUNDVOL, GMSTATE_O_VIEWDIST, 32 | }; 33 | 34 | extern SDL_Window* gameWindow; 35 | 36 | struct Gamemap { 37 | Gamemap() : light_ah(0), light_av(0) { filename[0] = 0; filename_tex[0] = 0; name[0] = 0; } 38 | char filename[256]; 39 | float light_ah; 40 | float light_av; 41 | 42 | // textura 43 | char filename_tex[256]; 44 | char name[256]; 45 | SharedGLtex pict_tex; 46 | }; 47 | 48 | struct Gameobj { 49 | Gameobj() : m(0), r(0), f(0) { filename[0] = 0; } 50 | char filename[256]; 51 | float m; // hmotnost 52 | float r; // poloměr pro výpočet momentu setrvačnosti a třecí síly 53 | float f; // tření 54 | // model a materiály 55 | std::unique_ptr t3dm; 56 | std::unique_ptr matmng; 57 | }; 58 | 59 | struct Car_th { 60 | Car_th() { fname[0] = 0; } 61 | SharedGLtex tex; // textura 62 | float color[4]; 63 | char fname[256]; // jméno souboru s texturou 64 | }; 65 | 66 | struct Gamecar { 67 | Gamecar() : engine1_pitch(0) { fname_sample_engine0[0] = 0; fname_sample_engine1[0] = 0; name[0] = 0; } 68 | char filename[256]; 69 | char filename_cmo[256]; 70 | // model a materiály 71 | std::vector names; // jména pro výměnu původních textur, počet je sz_names*sz_mods 72 | std::vector pict_tex; // obrázek s texturou do menu, počet je v sz_mods 73 | unsigned int sz_names; 74 | 75 | char fname_sample_engine0[256]; 76 | char fname_sample_engine1[256]; 77 | float engine1_pitch; 78 | 79 | ALbuffer p_engine0_sample; 80 | ALbuffer p_engine1_sample; 81 | 82 | glm::vec3 exhaust_position; 83 | glm::vec3 exhaust_direction; 84 | 85 | char name[256]; 86 | }; 87 | 88 | struct Gamesky { 89 | Gamesky() { sky_tex[0] = 0; skycm_tex[0] = 0; } 90 | char sky_tex[256]; 91 | char skycm_tex[256]; 92 | float light_amb[4]; 93 | float light_diff[4]; 94 | // model a materiály 95 | }; 96 | 97 | struct Mapobj { 98 | Mapobj() : vert_i(0), ang(0), id(0), r(0), f(0) { pos[0] = 0; pos[1] = 0; } 99 | unsigned int vert_i; 100 | float ang; 101 | float pos[2]; 102 | unsigned int id; 103 | float r; 104 | float f; 105 | std::unique_ptr rbo; 106 | std::unique_ptr rendermng; 107 | }; 108 | 109 | struct Playerkeys { 110 | unsigned char key_left, key_right, key_down, key_up; 111 | }; 112 | 113 | struct Playerhud { 114 | Gltext speed; 115 | Gltext speed_km_h; 116 | Gltext laptime_l; 117 | Gltext laptime_r_lap; 118 | Gltext laptime_l1; 119 | Gltext laptime_l_best; 120 | Gltext laptime_r; 121 | Gltext laptime_r1; 122 | Gltext newrecord; 123 | 124 | Gltext position; 125 | }; 126 | 127 | struct Results { 128 | Gltext title; 129 | Gltext line0; // Position, time, best lap 130 | Gltext position; 131 | Gltext time; 132 | Gltext best; 133 | }; 134 | 135 | struct Keytest { 136 | Gltext player, left, right, down, up; 137 | }; 138 | 139 | struct Playerstate { 140 | int lap_i; 141 | int lap_i_max; // největší zatím dosažená hodnota čísla kola a je min. 1 142 | float lap_time; // aktualni cas v kole v sekundach 143 | float best_time; // aktualni cas v kole v sekundach 144 | float race_time; // aktualni cas v zavode v sekundach 145 | 146 | int state; // 0 - nic, 1 - pred carou, 2 - za carou/na care 147 | int state_prev; 148 | 149 | int state_finish; // 0 - neskončil, 1 - skončil; 150 | float finish_time; // až bude finish time u všech > neco.f, Gamemng::p_state = 2 (zobrazení výsledků) 151 | int player; // <0, 4) 152 | 153 | float position_time; 154 | int state_position; 155 | 156 | }; 157 | 158 | class Gamemng; 159 | class MainMenu; 160 | 161 | class Gamemenu { 162 | public: 163 | Gamemenu() : bmenu(false), state(0), p_gamemng(0), p_settings(0), p_menu(0) 164 | { 165 | for (int i = 0; i != 24; ++i) 166 | { 167 | p_opt_verts[i] = 0; 168 | } 169 | for (int i = 0; i != 3; ++i) 170 | { 171 | p_opt_color0[i] = 0; 172 | p_opt_color1[i] = 0; 173 | } 174 | p_bufUpdated = false; 175 | } 176 | void sw(); 177 | void keydown(unsigned int sym); 178 | void render(); 179 | void init(); 180 | 181 | bool bmenu; 182 | int state; 183 | Gamemng* p_gamemng; 184 | Settings* p_settings; 185 | MainMenu* p_menu; 186 | 187 | Gltext gltext_menu; 188 | Gltext p_text_opt, p_text_opt2, p_text_opt3; 189 | 190 | float p_opt_verts[24]; 191 | float p_opt_color0[3]; 192 | float p_opt_color1[3]; 193 | 194 | bool p_bufUpdated = false; // GL buffer updated with latest data? 195 | SharedGLbuf p_buf; 196 | SharedGLbuf p_elemBuf; 197 | }; 198 | 199 | //typedef float Gamemtrx[16]; 200 | 201 | class Carcam { 202 | public: 203 | void init(float r, float y, float ang, float h_ang, const float* , const float* ang0, const float* pos0, const TimeSync* timesync, const Collider* collider); // úhly jsou v radiánech, h_ang ve stupních 204 | void update(bool bstep); 205 | glm::mat4 transf(); 206 | 207 | const float* p_ang_base; 208 | const float* p_ang0_base; 209 | const float* p_pos0_base; 210 | const TimeSync* p_timesync; 211 | float p_r; 212 | float p_r0; 213 | float p_mindist; // nejmenší vzdálenost od zdi 214 | float p_y; 215 | float p_h_ang; 216 | 217 | float p_ang; 218 | float p_ang0; 219 | 220 | const Collider* p_collider; 221 | }; 222 | 223 | const char* time_m_s(float time); 224 | 225 | class Gamemng { 226 | public: 227 | Gamemng() : 228 | p_rbos(0), p_reverse(false), p_players(0), 229 | p_wide169(false), p_far(0), p_car2do(0), p_car2dp(0), p_cartransf(0), p_carrendermng(0), 230 | p_ghostmodel(0), p_ghostmatmng(0), p_ghostrendermng(0), p_ghosttransf(0), 231 | p_isGhost(0), p_ghostUpdated(0), p_ghostAvailable(0), 232 | p_ghost_time(0), p_finished(0), p_laps(0), p_settings(0) 233 | { 234 | for (int i = 0; i != 4; ++i) 235 | { 236 | p_carmodel[i] = 0; 237 | p_carmatmng[i] = 0; 238 | p_ghost_step[i] = 0; 239 | } 240 | } 241 | ~Gamemng() 242 | { 243 | unload(); 244 | } 245 | void unload(); 246 | void init(const char* maps_def, const char* objs_def, const char* cars_def, const char* skies_def); // vytvořit skysph 247 | void init_sound(); 248 | bool load(int players_sel, const int* cars_sel/*[4]*/, const int* cars_tex_sel, int map_sel, int sky_sel, bool breverse); 249 | void restart(); 250 | void input(unsigned char keys[4*4]); // předání pole pravdivostních hodnot stisku kláves 251 | void frame(float deltaT, const glm::mat4& freecam_mtrx); 252 | void render_smoke(const glm::mat4& m); 253 | void render_frame(const glm::mat4& m); 254 | 255 | void render_black(); 256 | void render_bricks(); 257 | void render_black_background(); 258 | 259 | void set_scissor(int player); 260 | void unset_scissor(); 261 | void set_laps(int laps) { p_laps = laps; } 262 | void set_proj_mtrx(); // vstupem je p_frust 263 | void set_far(int far); // 0 - 10 264 | void gamemenu_sw(bool b_quit = false); 265 | void end_race(); 266 | void init_keytest(); 267 | 268 | void quit_race(); 269 | ////////////////////////////////////////////////////// 270 | Playerkeys p_playerkeys[4]; 271 | 272 | ShaderMng p_shadermng; 273 | Skysph p_skysph; 274 | 275 | SharedGLtex p_whitetex; 276 | SharedGLtex p_smoketex; // přenosná textura - z init, zrušit v destruktoru 277 | SharedGLtex p_skycmtex; // cube map or sphere map 278 | 279 | // 280 | SharedGLbuf p_smokebuf; 281 | uint32_t p_smokeCount; 282 | 283 | SharedGLbuf p_blackBuf; 284 | SharedGLbuf p_brickBuf; 285 | 286 | // skytex spravuje p_skysph 287 | float p_skyang; 288 | 289 | glm::mat4 p_mtrx_texcm; 290 | 291 | std::vector p_maps; 292 | std::vector p_objs; 293 | std::vector p_cars; 294 | std::vector p_skies; 295 | 296 | std::vector p_mapobjs; // objektová mapa 297 | 298 | // model a materiály mapy 299 | 300 | std::unique_ptr p_carmodel[4]; 301 | std::unique_ptr p_carmatmng[4]; 302 | 303 | std::unique_ptr p_map_model; 304 | std::unique_ptr p_map_matmng; 305 | std::unique_ptr p_map_oct; 306 | std::unique_ptr p_map_rendermng; 307 | 308 | std::unique_ptr p_collider; 309 | std::vector p_rbos; 310 | 311 | float p_finish[2]; 312 | bool p_reverse; 313 | unsigned int p_players; 314 | 315 | TimeSync p_timesync; 316 | TimeSync p_particleTimesync; 317 | 318 | float p_light_position[4]; 319 | float p_light_ambient[4]; 320 | float p_light_diffuse[4]; 321 | 322 | GLint p_viewport[2]; 323 | GLint p_scissor[2]; 324 | float p_aspect; 325 | float p_frust[4]; // hodnoty abs(left) a abs(top) ve vzdálenosti (-)1, abs(near), abs(far) 326 | 327 | bool p_wide169; // aspect ratio is 16:9 328 | 329 | int p_far; 330 | 331 | int get_far() { return p_far; } 332 | 333 | int p_cars_sel[4]; 334 | std::vector p_car2do; // pole objektů aut 335 | std::vector p_car2dp; 336 | std::vector p_cartransf; 337 | std::vector p_carrendermng; 338 | std::vector p_particles; 339 | 340 | std::vector p_ghostmodel; // pole 341 | std::vector p_ghostmatmng; // pole 342 | std::vector p_ghostrendermng; // pole 343 | std::vector p_ghosttransf; // pole 344 | 345 | std::unique_ptr p_ghostOld; 346 | std::vector p_ghostNew; // pole 4 prvků 347 | int p_isGhost; // times 1 (now only used for rendering) 348 | int p_ghostUpdated; // times 1 349 | int p_ghostAvailable; // times 1 350 | int p_ghost_step[4]; // times 4 351 | float p_ghost_wheel_rot; // times 1 (only used for rendering) 352 | float p_ghost_x_prev[2]; // times 1 (used for computing wheel rotation) 353 | float p_newlaprecordtxttime[4]; // times 4 354 | float p_ghost_time; // times 1 (?) 355 | 356 | float p_wheel_rot[4]; 357 | 358 | Carcam p_carcam[4]; 359 | 360 | glm::mat4 p_proj_mtrx[4]; 361 | glm::mat4 p_proj_mtrx0; 362 | glm::mat4 p_proj_mtrx_active; 363 | 364 | Glfont p_glfont; 365 | float p_fpscoord[2]; 366 | Gltext p_gltext_fps; 367 | 368 | Playerhud p_playerhud[4]; 369 | void init_hud(); 370 | 371 | Playerstate p_playerstate[4]; 372 | 373 | int p_finished; 374 | 375 | int p_laps; 376 | 377 | int p_state; // 0 - uvodni kamera, 1 - hra, 2 - konec zavodu 378 | float p_state0_time; 379 | float p_state0_5_time; // GO! 380 | bool p_state0_5; 381 | Gltext p_gltext_start; 382 | Carcam p_startcam[4]; 383 | 384 | SharedGLtex p_fonttex; 385 | 386 | std::unique_ptr p_sound_crash; 387 | std::vector p_sound_car; 388 | 389 | float p_global_volume; 390 | 391 | int p_global_volume_i; 392 | 393 | int get_global_volume() { return p_global_volume_i; } 394 | void set_global_volume(int volume) { if (volume < 0) volume = 0; else if (volume > 100) volume = 100; 395 | p_global_volume_i = volume; p_global_volume = p_global_volume_i*0.01f; } 396 | 397 | 398 | Gamemenu p_gamemenu; 399 | bool p_bfps; 400 | 401 | Results p_results; 402 | 403 | Keytest p_keytest[4]; 404 | 405 | Sound_game_static p_sound_game_static; 406 | 407 | Settings* p_settings; 408 | 409 | }; 410 | 411 | #endif 412 | --------------------------------------------------------------------------------