6
5
internal static class Camera {
9
8
internal static OpenBveApi.Math.Vector3 Position = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0);
10
9
internal static OpenBveApi.Math.Orientation3 Orientation = OpenBveApi.Math.Orientation3.Default;
10
internal static OpenBveApi.Math.Vector3 GridLeafNodeCenter = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0);
11
internal static ObjectGrid.GridLeafNode GridLeafNode = null;
12
internal static ViewportOptions Viewport = new ViewportOptions(1.0, 1.0, 1.0, 2.0);
13
15
/// <summary>Stores options required to set up the viewport.</summary>
14
16
internal struct ViewportOptions {
15
18
/// <summary>The horizontal viewing angle in radians.</summary>
16
19
internal double HorizontalViewingAngle;
17
20
/// <summary>The vertical viewing angle in radians.</summary>
18
21
internal double VerticalViewingAngle;
19
22
internal double NearClippingPlane;
20
23
internal double FarClippingPlane;
21
25
/// <summary>Creates a new instance of the ViewportOptions structure.</summary>
22
26
/// <param name="HorizontalViewingAngle">The horizontal viewing angle in radians.</param>
23
27
/// <param name="VerticalViewingAngle">The vertical viewing angle in radians.</param>
24
28
/// <param name="NearClippingPlane">The distance to the near clipping plane in meters.</param>
25
29
/// <param name="FarClippingPlane">The distance to the far clipping plane in meters.</param>
26
internal ViewportOptions(double HorizontalViewingAngle, double VerticalViewingAngle, double NearClippingPlane, double FarClippingPlane) {
27
this.HorizontalViewingAngle = HorizontalViewingAngle;
28
this.VerticalViewingAngle = VerticalViewingAngle;
29
this.NearClippingPlane = NearClippingPlane;
30
this.FarClippingPlane = FarClippingPlane;
30
internal ViewportOptions(double horizontalViewingAngle, double verticalViewingAngle, double nearClippingPlane, double farClippingPlane) {
31
this.HorizontalViewingAngle = horizontalViewingAngle;
32
this.VerticalViewingAngle = verticalViewingAngle;
33
this.NearClippingPlane = nearClippingPlane;
34
this.FarClippingPlane = farClippingPlane;
32
36
/// <summary>Creates a new instance of the ViewportOptions structure.</summary>
33
37
/// <param name="VerticalViewingAngle">The vertical viewing angle in radians.</param>
34
38
/// <param name="NearClippingPlane">The distance to the near clipping plane in meters.</param>
35
39
/// <param name="FarClippingPlane">The distance to the far clipping plane in meters.</param>
36
40
/// <remarks>The horizontal viewing angle is determined automatically from the vertical viewing angle and the window's aspect ratio.</remarks>
37
internal ViewportOptions(double VerticalViewingAngle, double NearClippingPlane, double FarClippingPlane) {
38
this.HorizontalViewingAngle = 2.0 * Math.Atan(Math.Tan(0.5 * VerticalViewingAngle) * Window.Properties.AspectRatio);
39
this.VerticalViewingAngle = VerticalViewingAngle;
40
this.NearClippingPlane = NearClippingPlane;
41
this.FarClippingPlane = FarClippingPlane;
41
internal ViewportOptions(double verticalViewingAngle, double nearClippingPlane, double farClippingPlane) {
42
this.HorizontalViewingAngle = 2.0 * Math.Atan(Math.Tan(0.5 * verticalViewingAngle) * Screen.Properties.AspectRatio);
43
this.VerticalViewingAngle = verticalViewingAngle;
44
this.NearClippingPlane = nearClippingPlane;
45
this.FarClippingPlane = farClippingPlane;
44
50
/// <summary>Sets the viewport.</summary>
45
51
/// <param name="Options">The options to set up the viewport.</param>
46
internal static void SetViewport(ViewportOptions Options) {
47
Gl.glViewport(0, 0, Window.Properties.Width, Window.Properties.Height);
52
internal static void SetViewport(ViewportOptions options) {
53
Gl.glViewport(0, 0, Screen.Properties.Width, Screen.Properties.Height);
48
54
Gl.glMatrixMode(Gl.GL_PROJECTION);
49
55
Gl.glLoadIdentity();
50
56
const double inverseDegrees = 57.295779513082320877;
51
double aspectRatio = Math.Tan(0.5 * Options.HorizontalViewingAngle) / Math.Tan(0.5 * Options.VerticalViewingAngle);
52
Glu.gluPerspective(Options.VerticalViewingAngle * inverseDegrees, -aspectRatio, Options.NearClippingPlane, Options.FarClippingPlane);
57
double aspectRatio = Math.Tan(0.5 * options.HorizontalViewingAngle) / Math.Tan(0.5 * options.VerticalViewingAngle);
58
Glu.gluPerspective(options.VerticalViewingAngle * inverseDegrees, -aspectRatio, options.NearClippingPlane, options.FarClippingPlane);
53
59
Gl.glMatrixMode(Gl.GL_MODELVIEW);
54
60
Gl.glLoadIdentity();
64
// update grid leaf node
65
internal static void UpdateGridLeafNode() {
67
* Find the leaf node the camera is currently in.
69
ObjectGrid.GridLeafNode leaf;
70
if (ObjectGrid.Grid.GetLeafNode(Camera.Position, out leaf)) {
71
double x = 0.5 * (leaf.Rectangle.Left + leaf.Rectangle.Right);
72
double z = 0.5 * (leaf.Rectangle.Near + leaf.Rectangle.Far);
73
Camera.GridLeafNodeCenter = new OpenBveApi.Math.Vector3(x, 0.0, z);
76
Camera.GridLeafNodeCenter = new OpenBveApi.Math.Vector3(0.0, 0.0, 0.0);
79
* Check if the leaf node the camera is in has changed.
81
if (leaf != Camera.GridLeafNode) {
84
* The camera is within the bounds of a leaf node.
86
ObjectGrid.GridPopulatedLeafNode[] oldLeafNodes;
87
if (Camera.GridLeafNode != null) {
88
oldLeafNodes = Camera.GridLeafNode.VisibleLeafNodes;
92
ObjectGrid.GridPopulatedLeafNode[] newLeafNodes = leaf.VisibleLeafNodes;
94
* Find leaf nodes that were visible before but are not any longer.
96
if (oldLeafNodes != null) {
97
for (int i = 0; i < oldLeafNodes.Length; i++) {
99
for (int j = 0; j < newLeafNodes.Length; j++) {
100
if (oldLeafNodes[i] == newLeafNodes[j]) {
107
* This leaf node is not visible any longer. Remove its
108
* associated transparent faces from the renderer.
110
for (int j = 0; j < oldLeafNodes[i].TransparentFaceCount; j++) {
111
Renderer.TransparentWorldFaces.Remove(oldLeafNodes[i].TransparentFaces[j]);
113
oldLeafNodes[i].TransparentFaceCount = 0;
118
* Find leaf nodes that are visible now but were not before.
120
for (int i = 0; i < newLeafNodes.Length; i++) {
122
if (oldLeafNodes != null) {
123
for (int j = 0; j < oldLeafNodes.Length; j++) {
124
if (newLeafNodes[i] == oldLeafNodes[j]) {
132
* This leaf node has become visible. Add all
133
* its transparent faces to the renderer.
135
ObjectGrid.GridPopulatedLeafNode visibleLeaf = newLeafNodes[i];
136
if (visibleLeaf.TransparentFaceCount != 0) {
137
throw new InvalidOperationException("#65517: A bug in the transparency management occured.");
139
visibleLeaf.LoadTextures();
140
double x = 0.5 * (visibleLeaf.Rectangle.Left + visibleLeaf.Rectangle.Right);
141
double z = 0.5 * (visibleLeaf.Rectangle.Near + visibleLeaf.Rectangle.Far);
142
OpenBveApi.Math.Vector3 offset = new OpenBveApi.Math.Vector3(x, 0.0, z);
143
for (int j = 0; j < visibleLeaf.StaticOpaqueObjectCount; j++) {
144
int libraryIndex = visibleLeaf.StaticOpaqueObjects[j].LibraryIndex;
145
OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[libraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
147
for (int k = 0; k < mesh.Faces.Length; k++) {
149
if (mesh.Materials[mesh.Faces[k].Material].BlendMode == OpenBveApi.Geometry.BlendMode.Additive) {
153
Textures.ApiHandle apiHandle = mesh.Materials[mesh.Faces[k].Material].DaytimeTexture as Textures.ApiHandle;
154
if (apiHandle != null) {
155
Textures.TextureType type = Textures.RegisteredTextures[apiHandle.TextureIndex].Type;
156
if (type == Textures.TextureType.Unknown) {
157
throw new InvalidOperationException("#31596: A bug in the texture management occured.");
158
} else if (type == Textures.TextureType.Alpha) {
164
for (int h = 0; h < mesh.Faces[k].Vertices.Length; h++) {
165
if (mesh.Vertices[mesh.Faces[k].Vertices[h]].ReflectiveColor.A != 1.0f) {
172
OpenBveApi.Math.Vector3 position = visibleLeaf.StaticOpaqueObjects[j].GridPosition + offset;
173
OpenBveApi.Math.Orientation3 orientation = visibleLeaf.StaticOpaqueObjects[j].GridOrientation;
174
if (visibleLeaf.TransparentFaceCount == visibleLeaf.TransparentFaces.Length) {
175
Array.Resize<object>(ref visibleLeaf.TransparentFaces, visibleLeaf.TransparentFaces.Length << 1);
177
visibleLeaf.TransparentFaces[visibleLeaf.TransparentFaceCount] = Renderer.TransparentWorldFaces.Add(libraryIndex, k, position, orientation);
178
visibleLeaf.TransparentFaceCount++;
185
} else if (Camera.GridLeafNode != null) {
187
* Before, the camera was inside the bounds of
188
* a leaf node, but now, it is not anymore.
189
* Remove the transparent faces associated
190
* to the old leaf node from the renderer.
192
ObjectGrid.GridPopulatedLeafNode[] oldLeafNodes = Camera.GridLeafNode.VisibleLeafNodes;
193
for (int i = 0; i < oldLeafNodes.Length; i++) {
194
for (int j = 0; j < oldLeafNodes[i].TransparentFaceCount; j++) {
195
Renderer.TransparentWorldFaces.Remove(oldLeafNodes[i].TransparentFaces[j]);
197
oldLeafNodes[i].TransparentFaceCount = 0;
202
* Apply the found leaf node.
204
Camera.GridLeafNode = leaf;
b'\\ No newline at end of file'