|
| 1 | +(* |
| 2 | +# RSCamera |
| 3 | +*) |
| 4 | +{$DEFINE WL_CAMERA_INCLUDED} |
| 5 | +{$INCLUDE_ONCE WaspLib/osrs.simba} |
| 6 | + |
| 7 | +type |
| 8 | +(* |
| 9 | +## TRSCamera |
| 10 | +Record responsible of handling projection, similar to {ref}`MM2MS`. |
| 11 | +*) |
| 12 | + TRSCamera = record |
| 13 | + RenderDistance, |
| 14 | + X, Y, Z, Pitch, Yaw, Zoom: Integer; |
| 15 | + Player, Center, Offset: TPoint; |
| 16 | + |
| 17 | + HorizontalXs, HorizontalYs, VerticalXs, VerticalYs: TIntegerArray; |
| 18 | + Heights: TIntegerMatrix; |
| 19 | + |
| 20 | + Sines, Cosines: array [0..2047] of Int32; |
| 21 | + const MIN_ZOOM: Integer = 181; |
| 22 | + const MIN_PITCH: Integer = 128; |
| 23 | + const MAX_PITCH: Integer = 383; |
| 24 | + const SCENE_START: Integer = -((184 - 104) div 2) shl 7; |
| 25 | + const SCENE_END: Integer = (104 + ((184 - 104) div 2)) shl 7; |
| 26 | + end; |
| 27 | + |
| 28 | +procedure TRSCamera.Setup(); |
| 29 | +var |
| 30 | + i: Integer; |
| 31 | +begin |
| 32 | + Self.RenderDistance := 21; |
| 33 | + Self.Pitch := 383; |
| 34 | + Self.Zoom := 181; |
| 35 | + |
| 36 | + for i := 0 to 2047 do |
| 37 | + begin |
| 38 | + Self.Sines[i] := Round(65536*Sin(i*PI/1024)); |
| 39 | + Self.Cosines[i] := Round(65536*Cos(i*PI/1024)); |
| 40 | + end; |
| 41 | + |
| 42 | + if RSClient.Mode = ERSMode.FIXED then |
| 43 | + Self.Offset := [4,4]; |
| 44 | + |
| 45 | + Self.Offset.X += MainScreen.Bounds.Width div 2; |
| 46 | + Self.Offset.Y += MainScreen.Bounds.Height div 2; |
| 47 | + |
| 48 | + i := (Self.RenderDistance * 2 + 1) * Self.RenderDistance * 2 * 2; |
| 49 | + |
| 50 | + SetLength(Self.HorizontalXs, i); |
| 51 | + SetLength(Self.HorizontalYs, i); |
| 52 | + SetLength(Self.VerticalXs, i); |
| 53 | + SetLength(Self.VerticalYs, i); |
| 54 | + |
| 55 | + SetLength(Self.Heights, 184, 184); |
| 56 | + |
| 57 | + Self.X := 0; |
| 58 | + Self.Y := 0; |
| 59 | + Self.Center.X := Self.X; |
| 60 | + Self.Center.Y := Self.Y+674; |
| 61 | + |
| 62 | + Self.Player.X := Self.X; |
| 63 | + Self.Player.Y := Round(Self.Center.Y + Sin(3*HALF_PI) * (Self.X - Self.Center.X) + Cos(3*HALF_PI) * (Self.Y - Self.Center.Y)); |
| 64 | +end; |
| 65 | + |
| 66 | +procedure TRSCamera.SetPitch(value: Integer); |
| 67 | +const |
| 68 | + PITCH_DIFF: Integer := Self.MAX_PITCH - Self.MIN_PITCH; |
| 69 | +begin |
| 70 | + Self.Pitch := value; |
| 71 | + Self.Y := 5150 - Round(235 * (Self.MAX_PITCH - value) / PITCH_DIFF); |
| 72 | +end; |
| 73 | + |
| 74 | +procedure TRSCamera.SetupGrid(zoom: Integer; rads: Double); |
| 75 | +const |
| 76 | + PITCH_DIFF: Integer := Self.MAX_PITCH - Self.MIN_PITCH; |
| 77 | +var |
| 78 | + x, y, xi, yi: Int32; |
| 79 | + pt, tile: TPoint; |
| 80 | +begin |
| 81 | + Self.Z := -1650 + Round(1237 * (Self.MAX_PITCH - Self.Pitch) / PITCH_DIFF - (zoom/100) * 75); |
| 82 | + Self.Yaw := Trunc((rads / TAU) * 2047); |
| 83 | + Self.Zoom := Self.MIN_ZOOM + Round(ZOOM2RSZOOM[zoom] * 1267); |
| 84 | + |
| 85 | + for x := -Self.RenderDistance to Self.RenderDistance do |
| 86 | + begin |
| 87 | + pt.X := Self.Player.X + x * 128; |
| 88 | + tile.X := pt.X div 128; |
| 89 | + |
| 90 | + for y := -Self.RenderDistance+1 to Self.RenderDistance do |
| 91 | + begin |
| 92 | + pt.Y := Self.Player.Y + y * 128; |
| 93 | + tile.Y := pt.Y div 128; |
| 94 | + |
| 95 | + Self.HorizontalXs[xi] := pt.X - 64; |
| 96 | + Self.HorizontalXs[xi+1] := pt.X + 63; |
| 97 | + Self.HorizontalYs[yi] := pt.Y - 64; |
| 98 | + Self.HorizontalYs[yi+1] := pt.Y - 64; |
| 99 | + |
| 100 | + xi += 2; |
| 101 | + yi += 2; |
| 102 | + end; |
| 103 | + end; |
| 104 | + |
| 105 | + xi := 0; |
| 106 | + yi := 0; |
| 107 | + |
| 108 | + for y := -Self.RenderDistance to Self.RenderDistance do |
| 109 | + begin |
| 110 | + pt.Y := Self.Player.Y + y * 128; |
| 111 | + tile.Y := pt.Y div 128; |
| 112 | + |
| 113 | + for x := -Self.RenderDistance+1 to Self.RenderDistance do |
| 114 | + begin |
| 115 | + pt.X := Self.Player.X + x * 128; |
| 116 | + tile.X := pt.X div 128; |
| 117 | + |
| 118 | + Self.VerticalXs[xi] := pt.X - 64; |
| 119 | + Self.VerticalXs[xi+1] := pt.X - 64; |
| 120 | + Self.VerticalYs[yi] := pt.Y - 64; |
| 121 | + Self.VerticalYs[yi+1] := pt.Y + 63; |
| 122 | + |
| 123 | + xi += 2; |
| 124 | + yi += 2; |
| 125 | + end; |
| 126 | + end; |
| 127 | +end; |
| 128 | + |
| 129 | +function TRSCamera.GetHeights(xs, ys: TIntegerArray): TIntegerArray; |
| 130 | +var |
| 131 | + local, scene: TPoint; |
| 132 | + i, x, y, nHeight, sHeight: Int32; |
| 133 | +begin |
| 134 | + SetLength(Result, Length(xs)); |
| 135 | + |
| 136 | + for i := 0 to High(xs) do |
| 137 | + begin |
| 138 | + local.X := xs[I]; |
| 139 | + local.Y := ys[I]; |
| 140 | + |
| 141 | + scene.X := Sar(local.X, 7) + 40; |
| 142 | + scene.Y := Sar(local.Y, 7) + 40; |
| 143 | + |
| 144 | + if not InRange(scene.X, 0, 183) or not InRange(scene.Y, 0, 183) then |
| 145 | + Continue; |
| 146 | + |
| 147 | + x := local.X and 127; |
| 148 | + y := local.Y and 127; |
| 149 | + |
| 150 | + nHeight := Sar(x * Self.Heights[scene.X+1, scene.Y] + (128 - x) * Self.Heights[scene.X, scene.Y], 7); |
| 151 | + sHeight := Sar((128 - x) * Self.Heights[scene.X, scene.Y+1] + x * Self.Heights[scene.X+1, scene.Y+1], 7); |
| 152 | + |
| 153 | + Result[i] := Sar((128 - y) * nHeight + y * sHeight, 7); |
| 154 | + end; |
| 155 | +end; |
| 156 | + |
| 157 | + |
| 158 | +function TRSCamera.GetLinePoints(xs, ys: TIntegerArray; rads: Double): TPointArray; |
| 159 | +var |
| 160 | + zs: TIntegerArray; |
| 161 | + i, x, y, z, pitchSin, pitchCos, yawSin, yawCos, |
| 162 | + x1, y1, y2, z1: Int32; |
| 163 | + calc: Double; |
| 164 | + camX, camY, camZ: Int32; |
| 165 | +begin |
| 166 | + zs := Self.GetHeights(xs, ys); |
| 167 | + SetLength(Result, Length(xs)); |
| 168 | + |
| 169 | + camX := Round(Self.Center.X + Cos(rads) * (Self.X - Self.Center.X) - Sin(rads) * (Self.Y - Self.Center.Y)); |
| 170 | + camY := Round(Self.Center.Y + Sin(rads) * (Self.X - Self.Center.X) + Cos(rads) * (Self.Y - Self.Center.Y)); |
| 171 | + camZ := Self.Z; |
| 172 | + |
| 173 | + pitchSin := Self.Sines[Self.Pitch]; |
| 174 | + pitchCos := Self.Cosines[Self.Pitch]; |
| 175 | + yawSin := Self.Sines[Self.Yaw]; |
| 176 | + yawCos := Self.Cosines[Self.Yaw]; |
| 177 | + |
| 178 | + for i := 0 to High(xs) do |
| 179 | + begin |
| 180 | + x := xs[i]; |
| 181 | + y := ys[i]; |
| 182 | + z := zs[i]; |
| 183 | + |
| 184 | + if InRange(x, Self.SCENE_START, Self.SCENE_END) and InRange(y, Self.SCENE_START, Self.SCENE_END) then |
| 185 | + begin |
| 186 | + x -= camX; |
| 187 | + y -= camY; |
| 188 | + z -= camZ; |
| 189 | + |
| 190 | + y1 := Sar(y * yawCos - x * yawSin, 16); |
| 191 | + z1 := Sar(y1 * pitchCos + z * pitchSin, 16); |
| 192 | + |
| 193 | + if (z1 < 50) then Continue; |
| 194 | + |
| 195 | + x1 := Sar(x * yawCos + y * yawSin, 16); |
| 196 | + y2 := Sar(z * pitchCos - y1 * pitchSin, 16); |
| 197 | + |
| 198 | + calc := Self.Zoom / z1; |
| 199 | + Result[i].X := Round(Self.Offset.X + x1 * calc); |
| 200 | + Result[i].Y := Round(Self.Offset.Y + y2 * calc); |
| 201 | + end; |
| 202 | + end; |
| 203 | +end; |
| 204 | + |
| 205 | +function TRSCamera.GetPoints(zoom: Integer; rads: Double): TPointArray; |
| 206 | +var |
| 207 | + hPts, vPts: TPointArray; |
| 208 | + i: Integer; |
| 209 | +begin |
| 210 | + Self.SetupGrid(zoom, rads); |
| 211 | + hPts := Self.GetLinePoints(Self.HorizontalXs, Self.HorizontalYs, rads); |
| 212 | + vPts := Self.GetLinePoints(Self.VerticalXs, Self.VerticalYs, rads); |
| 213 | + |
| 214 | + for i := 0 to High(hPts) with 2 do |
| 215 | + begin |
| 216 | + Result += TPointArray.CreateFromLine(hPts[i], hPts[i+1]); |
| 217 | + Result += TPointArray.CreateFromLine(vPts[i], vPts[i+1]); |
| 218 | + end; |
| 219 | +end; |
| 220 | + |
| 221 | +var |
| 222 | +(* |
| 223 | +## RSCamera variable |
| 224 | +Global {ref}`TRSCamera` variable. |
| 225 | +*) |
| 226 | + RSCamera: TRSCamera; |
0 commit comments