diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 2cd58bb45a..8765ae4f72 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -828,6 +828,10 @@ bool Game_Interpreter::ExecuteCommand(lcf::rpg::EventCommand const& com) { return CommandManiacCallCommand(com); case 9901: return Command3DPicture(com); + case 9902: + return Command3DPictureRotate(com); + case 9903: + return CommandGet3DPictureRotate(com); default: return true; } @@ -5180,3 +5184,28 @@ bool Game_Interpreter::Command3DPicture(lcf::rpg::EventCommand const& com) { return true; } + +bool Game_Interpreter::Command3DPictureRotate(lcf::rpg::EventCommand const& com) { + int picID = ValueOrVariable(com.parameters[0], com.parameters[1]); + int rotX = ValueOrVariable(com.parameters[2], com.parameters[3]); + int rotY = ValueOrVariable(com.parameters[4], com.parameters[5]); + int rotZ = ValueOrVariable(com.parameters[6], com.parameters[7]); + + Main_Data::game_pictures->Rotate3D(picID, rotX, rotY, rotZ); + + return true; +} + +bool Game_Interpreter::CommandGet3DPictureRotate(lcf::rpg::EventCommand const& com) { + int picID = ValueOrVariable(com.parameters[0], com.parameters[1]); + int varX = ValueOrVariable(com.parameters[2], com.parameters[3]); + int varY = ValueOrVariable(com.parameters[4], com.parameters[5]); + int varZ = ValueOrVariable(com.parameters[6], com.parameters[7]); + + // Output::Debug(" {} {} {}", varX, varY, varZ); + + Main_Data::game_pictures->Get3DRotation(picID, varX, varY, varZ); + + return true; +} + diff --git a/src/game_interpreter.h b/src/game_interpreter.h index 47a2009297..c19a986ac7 100644 --- a/src/game_interpreter.h +++ b/src/game_interpreter.h @@ -290,6 +290,8 @@ class Game_Interpreter bool CommandManiacControlStrings(lcf::rpg::EventCommand const& com); bool CommandManiacCallCommand(lcf::rpg::EventCommand const& com); bool Command3DPicture(lcf::rpg::EventCommand const& com); + bool Command3DPictureRotate(lcf::rpg::EventCommand const& com); + bool CommandGet3DPictureRotate(lcf::rpg::EventCommand const& com); int DecodeInt(lcf::DBArray::const_iterator& it); const std::string DecodeString(lcf::DBArray::const_iterator& it); diff --git a/src/game_pictures.cpp b/src/game_pictures.cpp index 68cf86ca6e..93b47d63c3 100644 --- a/src/game_pictures.cpp +++ b/src/game_pictures.cpp @@ -600,7 +600,7 @@ void Game_Pictures::Picture::Update(bool is_battle) { } if (pic3D != nullptr) { - pic3D->Update(); + pic3D->Update(false); sprite->SetBitmap(pic3D->sprite); } } @@ -667,6 +667,16 @@ void Game_Pictures::Show3D(std::string n, int picID, int zoom, int dx, int dy, i pic.Show3D(n, zoom, dx, dy, rx, ry, rz); } +void Game_Pictures::Rotate3D(int picID, int rx, int ry, int rz) { + auto& pic = GetPicture(picID); + pic.Rotate3D(rx, ry, rz); +} + +void Game_Pictures::Get3DRotation(int picID, int vx, int vy, int vz) { + auto& pic = GetPicture(picID); + pic.Get3DRotation(vx, vy, vz); +} + void Game_Pictures::Picture::Show3D(std::string n, int zoom, int dx, int dy, int rx, int ry, int rz) { pic3D = new Spriteset_MapDoom(n, zoom, dx, dy, rx, ry, rz); @@ -675,3 +685,17 @@ void Game_Pictures::Picture::Show3D(std::string n, int zoom, int dx, int dy, int needs_update = true; } } + +void Game_Pictures::Picture::Rotate3D(int rx, int ry, int rz) { + if (pic3D) { + pic3D->setRotation(rx, ry, rz); + } +} + +void Game_Pictures::Picture::Get3DRotation(int vx, int vy, int vz) { + if (pic3D) { + pic3D->getRotation(vx, vy, vz); + } +} + + diff --git a/src/game_pictures.h b/src/game_pictures.h index eb578fdf32..af4483e885 100644 --- a/src/game_pictures.h +++ b/src/game_pictures.h @@ -86,6 +86,8 @@ class Game_Pictures { bool Show(int id, const ShowParams& params); void Move(int id, const MoveParams& params); void Show3D(std::string n, int picID, int zoom, int dx, int dy, int rx, int ry, int rz); + void Rotate3D(int picID, int rx, int ry, int rz); + void Get3DRotation(int picID, int vx, int vy, int vz); void Erase(int id); void EraseAll(); @@ -132,6 +134,8 @@ class Game_Pictures { bool IsWindowAttached() const; void Show3D(std::string n, int zoom, int dx, int dy, int rx, int ry, int rz); + void Rotate3D(int rx, int ry, int rz); + void Get3DRotation(int vx, int vy, int vz); Spriteset_MapDoom* pic3D = nullptr; }; diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 4868dd4c3b..a5943269e2 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -128,7 +128,7 @@ void Spriteset_Map::Update() { } void Spriteset_Map::doomUpdate() { - doom->Update(); + doom->Update(true); doom_lower->SetBitmap(doom->sprite); doom_upper->SetBitmap(doom->spriteUpper); } diff --git a/src/spritesetmap_doom.cpp b/src/spritesetmap_doom.cpp index af41dc362f..206e108fb3 100644 --- a/src/spritesetmap_doom.cpp +++ b/src/spritesetmap_doom.cpp @@ -3,6 +3,9 @@ #include "bitmap.h" #include #include +#include +#include +#include Spriteset_MapDoom::Spriteset_MapDoom() { @@ -62,6 +65,10 @@ Spriteset_MapDoom::Spriteset_MapDoom(std::string n, int zoom, int dx, int dy, in rotationY = ry; rotationZ = rz; + angleX = 0; + angleY = 0; + angleZ = 0; + for (auto& p : points3D) { p.x *= zoom; p.y *= zoom; @@ -80,6 +87,55 @@ Spriteset_MapDoom::Spriteset_MapDoom(std::string n, int zoom, int dx, int dy, in sprite = Bitmap::Create(Player::screen_width, Player::screen_height); spriteUpper = Bitmap::Create(Player::screen_width, Player::screen_height); + + Update(true); + + rotationX = 0; + rotationY = 0; + rotationZ = 0; + +} + +void Spriteset_MapDoom::setRotation(int rx, int ry, int rz) { + rotationX = rx; + rotationY = ry; + rotationZ = rz; +} + +void Spriteset_MapDoom::getRotation(int varX, int varY, int varZ) { + + //int x = (int)(angleX * 180 / M_PI / 1000) % 360; + //if (x < 0) + // x = 360 + x; + + //int y = (int)(angleY * 180 / M_PI / 1000) % 360; + //if (y < 0) + // y = 360 + y; + + //int z = (int)(angleZ * 180 / M_PI / 1000) % 360; + //if (z < 0) + // z = 360 + z; + + int x = (int)(angleX * 180 / M_PI) % 360; + int y = (int)(angleY * 180 / M_PI) % 360; + int z = (int)(angleZ * 180 / M_PI) % 360; + + // S'assurer que les angles sont positifs + if (x < 0) x = 360 + x; + if (y < 0) y = 360 + y; + if (z < 0) z = 360 + z; + + + auto p = points3D[points3D.size() - 1]; + x = p.x; + y = p.y; + z = p.z; + + Main_Data::game_variables->Set(varX, x); + Main_Data::game_variables->Set(varY, y); + Main_Data::game_variables->Set(varZ, z); + + //Output::Debug("A {} {} {}", x, y, z); } @@ -245,6 +301,8 @@ void Spriteset_MapDoom::Load_OBJ(std::string name) { }*/ } + points3D.push_back({ 0,0,0 }); + //for (auto p : pointsNoMaterial) { // p.color = color; // points3D.push_back(p); @@ -252,57 +310,78 @@ void Spriteset_MapDoom::Load_OBJ(std::string name) { //pointsNoMaterial.clear(); } -void Spriteset_MapDoom::Update() { +void Spriteset_MapDoom::Update(bool first) { //Output::Debug("Update"); - int refresh_rate = 1; + int refresh_rate = 2; - for (auto& p : points3D) { + if (rotationX != 0 || rotationY != 0 || rotationZ != 0 || first) { - p.x -= centeroid.x; - p.y -= centeroid.y; - p.z -= centeroid.z; - rotate(p, rotationX / 1000.0, rotationY / 1000.0, rotationZ / 1000.0); - p.x += centeroid.x; - p.y += centeroid.y; - p.z += centeroid.z; - //if (timer % refresh_rate == 1 || refresh_rate == 1) - //pixel(p.x, p.y, p.z, p.color); - } + angleX += rotationX / 1000.0; + angleY += rotationY / 1000.0; + angleZ += rotationZ / 1000.0; + + normalizeAngle(angleX); + normalizeAngle(angleY); + normalizeAngle(angleZ); - if (timer % refresh_rate == 1 || refresh_rate == 1) { + for (auto& p : points3D) { - for (auto& c : connections3D) { - // line(points3D[c.a], points3D[c.b]); + p.x -= centeroid.x; + p.y -= centeroid.y; + p.z -= centeroid.z; + rotate(p, rotationX / 1000.0, rotationY / 1000.0, rotationZ / 1000.0); + p.x += centeroid.x; + p.y += centeroid.y; + p.z += centeroid.z; + + //if (timer % refresh_rate == 1 || refresh_rate == 1) + //pixel(p.x, p.y, p.z, p.color); } - for (auto s : surfaces) { - std::vector s2; - for (auto p : s) { - Point p2 = { points3D[p.x].x, points3D[p.x].y, points3D[p.x].z, points3D[p.x].upper, p.color}; - s2.push_back(p2); + if (timer % refresh_rate == 1 || refresh_rate == 1 || first) { + + for (auto& c : connections3D) { + // line(points3D[c.a], points3D[c.b]); + } + for (auto s : surfaces) { - p2 = { points3D[p.y].x, points3D[p.y].y, points3D[p.y].z, points3D[p.y].upper, p.color }; - s2.push_back(p2); + std::vector s2; + for (auto p : s) { + Point p2 = { points3D[p.x].x, points3D[p.x].y, points3D[p.x].z, points3D[p.x].upper, p.color }; + s2.push_back(p2); + + p2 = { points3D[p.y].x, points3D[p.y].y, points3D[p.y].z, points3D[p.y].upper, p.color }; + s2.push_back(p2); + + // Output::Debug(" {} {} {}", p2.color.red, p2.color.green , p2.color.blue); + } + sortPoints(s2); + drawPolygon(s2); - // Output::Debug(" {} {} {}", p2.color.red, p2.color.green , p2.color.blue); } - sortPoints(s2); - drawPolygon(s2); - } + Show(); - Show(); + } + timer++; + points.clear(); + } +} +// Normalisation des angles pour rester entre 0 et 360 +void Spriteset_MapDoom::normalizeAngle(double& angle) { + angle = fmod(angle, 2 * M_PI); // Modulo 2π pour rester dans l'intervalle [0, 2π] + if (angle < 0) { + angle += 2 * M_PI; // Si négatif, on ajoute 2π pour ramener l'angle dans l'intervalle [0, 2π] } - timer++; - points.clear(); } + void Spriteset_MapDoom::pixel(float x, float y, float z, Color c) { - Point p = { x, y, z, false, c}; + Point p = { x, y, z, false, c, true}; if (z < 0) { p.upper = true; } @@ -420,24 +499,56 @@ float Spriteset_MapDoom::lerp(float a, float b, float f) return a + f * (b - a); } +//void Spriteset_MapDoom::rotate(Point& point, float x, float y, float z) { +// +// float rad = 0; +// +// rad = x; +// point.y = std::cos(rad) * point.y - std::sin(rad) * point.z; +// point.z = std::sin(rad) * point.y + std::cos(rad) * point.z; +// +// rad = y; +// point.x = std::cos(rad) * point.x + std::sin(rad) * point.z; +// point.z = -std::sin(rad) * point.x + std::cos(rad) * point.z; +// +// rad = z; +// point.x = std::cos(rad) * point.x - std::sin(rad) * point.y; +// point.y = std::sin(rad) * point.x + std::cos(rad) * point.y; +// +//} + void Spriteset_MapDoom::rotate(Point& point, float x, float y, float z) { + float rad; - float rad = 0; + // Variables temporaires pour stocker les nouvelles valeurs + float new_x, new_y, new_z; + // Rotation autour de l'axe X rad = x; - point.y = std::cos(rad) * point.y - std::sin(rad) * point.z; - point.z = std::sin(rad) * point.y + std::cos(rad) * point.z; + new_y = std::cos(rad) * point.y - std::sin(rad) * point.z; + new_z = std::sin(rad) * point.y + std::cos(rad) * point.z; + + point.y = new_y; + point.z = new_z; + // Rotation autour de l'axe Y rad = y; - point.x = std::cos(rad) * point.x + std::sin(rad) * point.z; - point.z = -std::sin(rad) * point.x + std::cos(rad) * point.z; + new_x = std::cos(rad) * point.x + std::sin(rad) * point.z; + new_z = -std::sin(rad) * point.x + std::cos(rad) * point.z; + point.x = new_x; + point.z = new_z; + + // Rotation autour de l'axe Z rad = z; - point.x = std::cos(rad) * point.x - std::sin(rad) * point.y; - point.y = std::sin(rad) * point.x + std::cos(rad) * point.y; + new_x = std::cos(rad) * point.x - std::sin(rad) * point.y; + new_y = std::sin(rad) * point.x + std::cos(rad) * point.y; + point.x = new_x; + point.y = new_y; } + bool Spriteset_MapDoom::comparePoints(const Point& p1, const Point& p2) { return p1.z < p2.z; } @@ -448,37 +559,55 @@ void Spriteset_MapDoom::Show() { spriteUpper->Clear(); float zmin = 0; - float zmax = points[0].z; + float zmax = 0; + bool f = true; for (const auto& p : points) { //Output::Debug(" {}", p.z); - zmin = std::max(zmin, p.z); - zmax = std::min(zmax, p.z); + if (f) { + zmax = p.z; + f = false; + } + else { + zmin = std::max(zmin, p.z); + zmax = std::min(zmax, p.z); + } } std::sort(points.begin(), points.end(), std::greater()); + bool pointsZB[999][999] = { false }; Rect r; Color c = Color(255,0,0,255); for (auto p : points) { - r = Rect(p.x + displayX + Player::screen_width / 2 , Player::screen_height - (p.y + displayY + Player::screen_height / 2), 1, 1); - int mult = ((p.z - zmin) / (zmax - zmin)) * 100; + int i = p.x + 999 / 2; + int j = p.y + 999 / 2; + + if (p.exist && !pointsZB[i][j]) + { + + pointsZB[i][j] = true; - int red, green, blue; - red = p.color.red; - green = p.color.green; - blue = p.color.blue; + r = Rect(p.x + displayX + Player::screen_width / 2, Player::screen_height - (p.y + displayY + Player::screen_height / 2), 1, 1); - //Output::Debug(" {} {} {}", red, green, blue); + int mult = ((p.z - zmin) / (zmax - zmin)) * 100; - c = Color(red * mult / 100, green * mult / 100, blue * mult / 100, 255); - //c = p.color; - sprite->FillRect(r, c); + int red, green, blue; + red = p.color.red; + green = p.color.green; + blue = p.color.blue; - if (p.upper) { - c = Color(255, 0, 0, 255); - spriteUpper->FillRect(r, c); + //Output::Debug(" {} {} {}", red, green, blue); + + c = Color(red * mult / 100, green * mult / 100, blue * mult / 100, 255); + //c = p.color; + sprite->FillRect(r, c); + + if (p.upper) { + c = Color(255, 0, 0, 255); + spriteUpper->FillRect(r, c); + } } } diff --git a/src/spritesetmap_doom.h b/src/spritesetmap_doom.h index 1e3b954ef7..86181c4ded 100644 --- a/src/spritesetmap_doom.h +++ b/src/spritesetmap_doom.h @@ -16,13 +16,14 @@ class Spriteset_MapDoom { int a, b; }; struct Point { - float x, y, z; - bool upper; + float x, y, z = -99999999; + bool upper = false; Color color; + bool exist = false; bool operator > (const Point& str) const { - return (z > str.z); + return (z < str.z); } }; @@ -33,12 +34,18 @@ class Spriteset_MapDoom { int rotationY = 0; int rotationZ = 0; + double angleX, angleY, angleZ = 0; + int timer = 0; Spriteset_MapDoom(); Spriteset_MapDoom(std::string n, int zoom, int dx, int dy, int rx, int ry, int rz); - void Update(); + void setRotation(int rx, int ry, int rz); + void getRotation(int varX, int varY, int varZ); + void Spriteset_MapDoom::normalizeAngle(double& angle); + + void Update(bool first); BitmapRef sprite; BitmapRef spriteUpper; @@ -67,7 +74,6 @@ class Spriteset_MapDoom { vec3 centeroid; void Show(); - SDL_Renderer* renderer; protected: