1 using System.Linq; 2 using OpenBveApi.Colors; 3 using OpenBveApi.Math; 4 using OpenBveApi.Textures; 5 using OpenBveApi.World; 6 using OpenTK.Graphics.OpenGL; 7 using Vector2 = OpenBveApi.Math.Vector2; 8 9 namespace LibRender2.Primitives 10 { 11 /// <summary>A Cube of nomimal 1.0 size</summary> 12 public class Cube 13 { 14 private readonly BaseRenderer renderer; 15 private readonly VertexArrayObject defaultVAO; 16 17 /// <summary>Creates a new cube</summary> Cube(BaseRenderer renderer)18 public Cube(BaseRenderer renderer) : this(renderer, Color128.White) 19 { 20 } 21 22 /// <summary>Creates a new colored cube</summary> Cube(BaseRenderer renderer, Color128 color)23 public Cube(BaseRenderer renderer, Color128 color) 24 { 25 this.renderer = renderer; 26 27 LibRenderVertex[] vertexData = 28 { 29 // back 30 new LibRenderVertex 31 { 32 Position = new Vector3f(1.0f, 1.0f, 1.0f), 33 UV = Vector2f.Null, 34 Color = color 35 }, 36 new LibRenderVertex 37 { 38 Position = new Vector3f(-1.0f, 1.0f, 1.0f), 39 UV = Vector2f.Right, 40 Color = color 41 }, 42 new LibRenderVertex 43 { 44 Position = new Vector3f(-1.0f, -1.0f, 1.0f), 45 UV = Vector2f.One, 46 Color = color 47 }, 48 new LibRenderVertex 49 { 50 Position = new Vector3f(1.0f, -1.0f, 1.0f), 51 UV = Vector2f.Down, 52 Color = color 53 }, 54 55 // right 56 new LibRenderVertex 57 { 58 Position = new Vector3f(1.0f, 1.0f, 1.0f), 59 UV = Vector2f.Right, 60 Color = color 61 }, 62 new LibRenderVertex 63 { 64 Position = new Vector3f(1.0f, -1.0f, 1.0f), 65 UV = Vector2f.One, 66 Color = color 67 }, 68 new LibRenderVertex 69 { 70 Position = new Vector3f(1.0f, -1.0f, -1.0f), 71 UV = Vector2f.Down, 72 Color = color 73 }, 74 new LibRenderVertex 75 { 76 Position = new Vector3f(1.0f, 1.0f, -1.0f), 77 UV = Vector2f.Null, 78 Color = color 79 }, 80 81 // top 82 new LibRenderVertex 83 { 84 Position = new Vector3f(1.0f, 1.0f, 1.0f), 85 UV = Vector2f.Right, 86 Color = color 87 }, 88 new LibRenderVertex 89 { 90 Position = new Vector3f(1.0f, 1.0f, -1.0f), 91 UV = Vector2f.One, 92 Color = color 93 }, 94 new LibRenderVertex 95 { 96 Position = new Vector3f(-1.0f, 1.0f, -1.0f), 97 UV = Vector2f.Down, 98 Color = color 99 }, 100 new LibRenderVertex 101 { 102 Position = new Vector3f(-1.0f, 1.0f, 1.0f), 103 UV = Vector2f.Null, 104 Color = color 105 }, 106 107 // front 108 new LibRenderVertex 109 { 110 Position = new Vector3f(-1.0f, -1.0f, -1.0f), 111 UV = Vector2f.Down, 112 Color = color 113 }, 114 new LibRenderVertex 115 { 116 Position = new Vector3f(-1.0f, 1.0f, -1.0f), 117 UV = Vector2f.Null, 118 Color = color 119 }, 120 new LibRenderVertex 121 { 122 Position = new Vector3f(1.0f, 1.0f, -1.0f), 123 UV = Vector2f.Right, 124 Color = color 125 }, 126 new LibRenderVertex 127 { 128 Position = new Vector3f(1.0f, -1.0f, -1.0f), 129 UV = Vector2f.One, 130 Color = color 131 }, 132 133 // left 134 new LibRenderVertex 135 { 136 Position = new Vector3f(-1.0f, -1.0f, -1.0f), 137 UV = Vector2f.One, 138 Color = color 139 }, 140 new LibRenderVertex 141 { 142 Position = new Vector3f(-1.0f, -1.0f, 1.0f), 143 UV = Vector2f.Down, 144 Color = color 145 }, 146 new LibRenderVertex 147 { 148 Position = new Vector3f(-1.0f, 1.0f, 1.0f), 149 UV = Vector2f.Null, 150 Color = color 151 }, 152 new LibRenderVertex 153 { 154 Position = new Vector3f(-1.0f, 1.0f, -1.0f), 155 UV = Vector2f.Right, 156 Color = color 157 }, 158 159 // bottom 160 new LibRenderVertex 161 { 162 Position = new Vector3f(-1.0f, -1.0f, -1.0f), 163 UV = Vector2f.Null, 164 Color = color 165 }, 166 new LibRenderVertex 167 { 168 Position = new Vector3f(1.0f, -1.0f, -1.0f), 169 UV = Vector2f.Right, 170 Color = color 171 }, 172 new LibRenderVertex 173 { 174 Position = new Vector3f(1.0f, -1.0f, 1.0f), 175 UV = Vector2f.One, 176 Color = color 177 }, 178 new LibRenderVertex 179 { 180 Position = new Vector3f(-1.0f, -1.0f, 1.0f), 181 UV = Vector2f.Down, 182 Color = color 183 } 184 }; 185 186 if (!renderer.ForceLegacyOpenGL) 187 { 188 defaultVAO = new VertexArrayObject(); 189 defaultVAO.Bind(); 190 defaultVAO.SetVBO(new VertexBufferObject(vertexData, BufferUsageHint.StaticDraw)); 191 defaultVAO.SetIBO(new IndexBufferObjectUS(Enumerable.Range(0, vertexData.Length).Select(x => (ushort)x).ToArray(), BufferUsageHint.StaticDraw)); 192 defaultVAO.SetAttributes(renderer.DefaultShader.VertexLayout); 193 defaultVAO.UnBind(); 194 } 195 } 196 197 /// <summary>Draws a 3D cube</summary> 198 /// <param name="Position">The position in world-space</param> 199 /// <param name="Direction">The direction vector</param> 200 /// <param name="Up">The up vector</param> 201 /// <param name="Side">The side vector</param> 202 /// <param name="Size">The size of the cube in M</param> 203 /// <param name="Camera">The camera position</param> 204 /// <param name="TextureIndex">The texture to apply</param> Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, double Size, Vector3 Camera, Texture TextureIndex)205 public void Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, double Size, Vector3 Camera, Texture TextureIndex) 206 { 207 if (renderer.AvailableNewRenderer) 208 { 209 Draw(Position, Direction, Up, Side, new Vector3(Size, Size, Size), Camera, TextureIndex); 210 } 211 else 212 { 213 DrawImmediate(Position, Direction, Up, Side, new Vector3(Size, Size, Size), Camera, TextureIndex); 214 } 215 } 216 217 /// <summary>Draws a 3D cube</summary> 218 /// <param name="Position">The position in world-space</param> 219 /// <param name="Direction">The direction vector</param> 220 /// <param name="Up">The up vector</param> 221 /// <param name="Side">The side vector</param> 222 /// <param name="Size">A 3D vector describing the size of the cube</param> 223 /// <param name="Camera">The camera position</param> 224 /// <param name="TextureIndex">The texture to apply</param> Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex)225 public void Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex) 226 { 227 if (renderer.AvailableNewRenderer) 228 { 229 DrawRetained(defaultVAO, Position, Direction, Up, Side, Size, Camera, TextureIndex); 230 } 231 else 232 { 233 DrawImmediate(Position, Direction, Up, Side, Size, Camera, TextureIndex); 234 } 235 } 236 237 /// <summary>Draws a 3D cube</summary> 238 /// <param name="VAO"></param> 239 /// <param name="Position">The position in world-space</param> 240 /// <param name="Direction">The direction vector</param> 241 /// <param name="Up">The up vector</param> 242 /// <param name="Side">The side vector</param> 243 /// <param name="Size">A 3D vector describing the size of the cube</param> 244 /// <param name="Camera">The camera position</param> 245 /// <param name="TextureIndex">The texture to apply</param> DrawRetained(VertexArrayObject VAO, Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex)246 private void DrawRetained(VertexArrayObject VAO, Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex) 247 { 248 renderer.DefaultShader.Activate(); 249 renderer.ResetShader(renderer.DefaultShader); 250 // matrix 251 renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); 252 renderer.DefaultShader.SetCurrentModelViewMatrix(Matrix4D.Scale(Size) * (Matrix4D)new Transformation(Direction, Up, Side) * Matrix4D.CreateTranslation(Position.X - Camera.X, Position.Y - Camera.Y, -Position.Z + Camera.Z) * renderer.CurrentViewMatrix); 253 254 // texture 255 if (TextureIndex != null && renderer.currentHost.LoadTexture(ref TextureIndex, OpenGlTextureWrapMode.ClampClamp)) 256 { 257 GL.Enable(EnableCap.Texture2D); 258 GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); 259 } 260 else 261 { 262 GL.Disable(EnableCap.Texture2D); 263 } 264 265 // render polygon 266 VAO.Bind(); 267 VAO.Draw(PrimitiveType.Quads); 268 GL.Disable(EnableCap.Texture2D); 269 } 270 271 /// <summary>Draws a 3D cube in immediate mode</summary> 272 /// <param name="Position">The position in world-space</param> 273 /// <param name="Direction">The direction vector</param> 274 /// <param name="Up">The up vector</param> 275 /// <param name="Side">The side vector</param> 276 /// <param name="Size">A 3D vector describing the size of the cube</param> 277 /// <param name="Camera">The camera position</param> 278 /// <param name="TextureIndex">The texture to apply</param> DrawImmediate(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex)279 private void DrawImmediate(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex) 280 { 281 renderer.LastBoundTexture = null; 282 GL.MatrixMode(MatrixMode.Projection); 283 GL.PushMatrix(); 284 GL.LoadIdentity(); 285 OpenTK.Matrix4d perspective = OpenTK.Matrix4d.Perspective(renderer.Camera.VerticalViewingAngle, -renderer.Screen.AspectRatio, 0.2, 1000.0); 286 GL.MultMatrix(ref perspective); 287 double dx = renderer.Camera.AbsoluteDirection.X; 288 double dy = renderer.Camera.AbsoluteDirection.Y; 289 double dz = renderer.Camera.AbsoluteDirection.Z; 290 double ux = renderer.Camera.AbsoluteUp.X; 291 double uy = renderer.Camera.AbsoluteUp.Y; 292 double uz = renderer.Camera.AbsoluteUp.Z; 293 OpenTK.Matrix4d lookat = OpenTK.Matrix4d.LookAt(0.0, 0.0, 0.0, dx, dy, dz, ux, uy, uz); 294 GL.MatrixMode(MatrixMode.Modelview); 295 GL.PushMatrix(); 296 GL.LoadMatrix(ref lookat); 297 Vector3[] v = new Vector3[8]; 298 v[0] = new Vector3(Size.X, Size.Y, -Size.Z); 299 v[1] = new Vector3(Size.X, -Size.Y, -Size.Z); 300 v[2] = new Vector3(-Size.X, -Size.Y, -Size.Z); 301 v[3] = new Vector3(-Size.X, Size.Y, -Size.Z); 302 v[4] = new Vector3(Size.X, Size.Y, Size.Z); 303 v[5] = new Vector3(Size.X, -Size.Y, Size.Z); 304 v[6] = new Vector3(-Size.X, -Size.Y, Size.Z); 305 v[7] = new Vector3(-Size.X, Size.Y, Size.Z); 306 for (int i = 0; i < 8; i++) 307 { 308 v[i].Rotate(Direction, Up, Side); 309 v[i] += Position - Camera; 310 } 311 int[][] Faces = new int[6][]; 312 Faces[0] = new[] { 0, 1, 2, 3 }; 313 Faces[1] = new[] { 0, 4, 5, 1 }; 314 Faces[2] = new[] { 0, 3, 7, 4 }; 315 Faces[3] = new[] { 6, 5, 4, 7 }; 316 Faces[4] = new[] { 6, 7, 3, 2 }; 317 Faces[5] = new[] { 6, 2, 1, 5 }; 318 if (TextureIndex == null || !renderer.currentHost.LoadTexture(ref TextureIndex, OpenGlTextureWrapMode.ClampClamp)) 319 { 320 GL.Disable(EnableCap.Texture2D); 321 for (int i = 0; i < 6; i++) 322 { 323 GL.Begin(PrimitiveType.Quads); 324 for (int j = 0; j < 4; j++) 325 { 326 GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); 327 } 328 GL.End(); 329 } 330 GL.PopMatrix(); 331 332 GL.MatrixMode(MatrixMode.Projection); 333 GL.PopMatrix(); 334 return; 335 } 336 GL.Enable(EnableCap.Texture2D); 337 GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); 338 Vector2[][] t = new Vector2[6][]; 339 t[0] = new[] { new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0) }; 340 t[1] = new[] { new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) }; 341 t[2] = new[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; 342 t[3] = new[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; 343 t[4] = new[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; 344 t[5] = new[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; 345 for (int i = 0; i < 6; i++) 346 { 347 GL.Begin(PrimitiveType.Quads); 348 GL.Color3(1.0, 1.0, 1.0); 349 for (int j = 0; j < 4; j++) 350 { 351 GL.TexCoord2(t[i][j].X, t[i][j].Y); 352 GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); 353 } 354 GL.End(); 355 } 356 GL.PopMatrix(); 357 358 GL.MatrixMode(MatrixMode.Projection); 359 GL.PopMatrix(); 360 } 361 } 362 } 363