sw_clipper.cpp
1 // Copyright 2023 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #include <array> 6 #include <cstddef> 7 #include "video_core/pica/regs_texturing.h" 8 #include "video_core/renderer_software/sw_clipper.h" 9 10 namespace SwRenderer { 11 12 using Pica::TexturingRegs; 13 14 void FlipQuaternionIfOpposite(Common::Vec4<f24>& a, const Common::Vec4<f24>& b) { 15 if (Common::Dot(a, b) < f24::Zero()) { 16 a *= f24::FromFloat32(-1.0f); 17 } 18 }; 19 20 int SignedArea(const Common::Vec2<Fix12P4>& vtx1, const Common::Vec2<Fix12P4>& vtx2, 21 const Common::Vec2<Fix12P4>& vtx3) { 22 const auto vec1 = Common::MakeVec(vtx2 - vtx1, 0); 23 const auto vec2 = Common::MakeVec(vtx3 - vtx1, 0); 24 // TODO: There is a very small chance this will overflow for sizeof(int) == 4 25 return Common::Cross(vec1, vec2).z; 26 }; 27 28 std::tuple<f24, f24, f24, PAddr> ConvertCubeCoord(f24 u, f24 v, f24 w, 29 const Pica::TexturingRegs& regs) { 30 const float abs_u = std::abs(u.ToFloat32()); 31 const float abs_v = std::abs(v.ToFloat32()); 32 const float abs_w = std::abs(w.ToFloat32()); 33 f24 x, y, z; 34 PAddr addr; 35 if (abs_u > abs_v && abs_u > abs_w) { 36 if (u > f24::Zero()) { 37 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveX); 38 y = -v; 39 } else { 40 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeX); 41 y = v; 42 } 43 x = -w; 44 z = u; 45 } else if (abs_v > abs_w) { 46 if (v > f24::Zero()) { 47 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveY); 48 x = u; 49 } else { 50 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeY); 51 x = -u; 52 } 53 y = w; 54 z = v; 55 } else { 56 if (w > f24::Zero()) { 57 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::PositiveZ); 58 y = -v; 59 } else { 60 addr = regs.GetCubePhysicalAddress(TexturingRegs::CubeFace::NegativeZ); 61 y = v; 62 } 63 x = u; 64 z = w; 65 } 66 const f24 z_abs = f24::FromFloat32(std::abs(z.ToFloat32())); 67 const f24 half = f24::FromFloat32(0.5f); 68 return std::make_tuple(x / z * half + half, y / z * half + half, z_abs, addr); 69 } 70 71 bool IsRightSideOrFlatBottomEdge(const Common::Vec2<Fix12P4>& vtx, 72 const Common::Vec2<Fix12P4>& line1, 73 const Common::Vec2<Fix12P4>& line2) { 74 if (line1.y == line2.y) { 75 // Just check if vertex is above us => bottom line parallel to x-axis 76 return vtx.y < line1.y; 77 } else { 78 // Check if vertex is on our left => right side 79 // TODO: Not sure how likely this is to overflow 80 const auto svtx = vtx.Cast<s32>(); 81 const auto sline1 = line1.Cast<s32>(); 82 const auto sline2 = line2.Cast<s32>(); 83 return svtx.x < 84 sline1.x + (sline2.x - sline1.x) * (svtx.y - sline1.y) / (sline2.y - sline1.y); 85 } 86 } 87 88 } // namespace SwRenderer