// constructors /// <summary>Creates a new instance of this class.</summary> /// <param name="ambientLight">The ambient light color.</param> /// <param name="diffuseLight">The diffuse light color.</param> /// <param name="specularLight">The specular light color.</param> /// <param name="lightDirection">The direction the light shines at.</param> public DirectionalLight(Color.ColorRGB ambientLight, Color.ColorRGB diffuseLight, Color.ColorRGB specularLight, Math.Vector3 lightDirection) { this.AmbientLight = ambientLight; this.DiffuseLight = diffuseLight; this.SpecularLight = specularLight; this.LightDirection = lightDirection; }
/// <summary>Releases the emergency brake</summary> internal void UnapplyEmergencyBrake() { if (Handles.EmergencyBrake.Driver) { // sound Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleRelease.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleRelease.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } // apply if (Handles.Brake is AirBrakeHandle) { ApplyAirBrakeHandle(AirBrakeHandleState.Service); } else { ApplyNotch(0, !Handles.SingleHandle, Handles.Brake.MaximumNotch, true); } Handles.EmergencyBrake.Driver = false; // plugin if (Plugin == null) { return; } Plugin.UpdatePower(); Plugin.UpdateBrake(); } }
/// <summary>Draws a 3D cube</summary> /// <param name="VAO"></param> /// <param name="Position">The position in world-space</param> /// <param name="Direction">The direction vector</param> /// <param name="Up">The up vector</param> /// <param name="Side">The side vector</param> /// <param name="Size">A 3D vector describing the size of the cube</param> /// <param name="Camera">The camera position</param> /// <param name="TextureIndex">The texture to apply</param> public void Draw(VertexArrayObject VAO, OpenBveApi.Math.Vector3 Position, OpenBveApi.Math.Vector3 Direction, OpenBveApi.Math.Vector3 Up, OpenBveApi.Math.Vector3 Side, OpenBveApi.Math.Vector3 Size, OpenBveApi.Math.Vector3 Camera, Texture TextureIndex) { renderer.DefaultShader.Activate(); renderer.ResetShader(renderer.DefaultShader); // matrix renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); 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); // texture if (TextureIndex != null && renderer.currentHost.LoadTexture(TextureIndex, OpenGlTextureWrapMode.ClampClamp)) { renderer.DefaultShader.SetIsTexture(true); renderer.DefaultShader.SetTexture(0); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); } else { GL.Disable(EnableCap.Texture2D); } // render polygon VAO.Bind(); VAO.Draw(renderer.DefaultShader.VertexLayout, PrimitiveType.Quads); VAO.UnBind(); GL.BindTexture(TextureTarget.Texture2D, 0); renderer.DefaultShader.Deactivate(); GL.Disable(EnableCap.Texture2D); }
internal void CreateObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { if (Prototype != null) { CreateObject(Prototype, Position, BaseTransformation, AuxTransformation, -1, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0); } }
/// <summary>Applies a loco brake notch to this train</summary> /// <param name="NotchValue">The loco brake notch value</param> /// <param name="Relative">Whether this is relative to the current notch</param> internal void ApplyLocoBrakeNotch(int NotchValue, bool Relative) { int b = Relative ? NotchValue + Handles.LocoBrake.Driver : NotchValue; if (b < 0) { b = 0; } else if (b > Handles.LocoBrake.MaximumNotch) { b = Handles.LocoBrake.MaximumNotch; } // brake sound if (b < Handles.LocoBrake.Driver) { // brake release Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.Brake.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.Brake.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } if (b > 0) { // brake release (not min) buffer = Cars[DriverCar].Sounds.BrakeHandleRelease.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleRelease.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } else { // brake min buffer = Cars[DriverCar].Sounds.BrakeHandleMin.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleMin.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } else if (b > Handles.LocoBrake.Driver) { // brake Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleApply.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleApply.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } Handles.LocoBrake.Driver = b; Handles.LocoBrake.Actual = b; //TODO: FIXME }
/// <summary>Draws a 3D cube</summary> /// <param name="Position">The position in world-space</param> /// <param name="Direction">The direction vector</param> /// <param name="Up">The up vector</param> /// <param name="Side">The side vector</param> /// <param name="Size">A 3D vector describing the size of the cube</param> /// <param name="Camera">The camera position</param> /// <param name="TextureIndex">The texture to apply</param> public void Draw(OpenBveApi.Math.Vector3 Position, OpenBveApi.Math.Vector3 Direction, OpenBveApi.Math.Vector3 Up, OpenBveApi.Math.Vector3 Side, OpenBveApi.Math.Vector3 Size, OpenBveApi.Math.Vector3 Camera, Texture TextureIndex) { if (renderer.currentOptions.IsUseNewRenderer) { Draw(defaultVAO, Position, Direction, Up, Side, Size, Camera, TextureIndex); } else { DrawImmediate(Position, Direction, Up, Side, Size, Camera, TextureIndex); } }
internal int CreateStaticObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { StaticObject obj = Prototype as StaticObject; if (obj == null) { Interface.AddMessage(MessageType.Error, false, "Attempted to use an animated object where only static objects are allowed."); return(-1); } return(base.CreateStaticObject(obj, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, AccurateObjectDisposalZOffset, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness)); }
// reset camera internal static void ResetCamera() { Renderer.Camera.AbsolutePosition = new Vector3(0.0, 2.5, -5.0); Renderer.Camera.AbsoluteDirection = new Vector3(-Renderer.Camera.AbsolutePosition.X, -Renderer.Camera.AbsolutePosition.Y, -Renderer.Camera.AbsolutePosition.Z); Renderer.Camera.AbsoluteSide = new Vector3(-Renderer.Camera.AbsolutePosition.Z, 0.0, Renderer.Camera.AbsolutePosition.X); Renderer.Camera.AbsoluteDirection.Normalize(); Renderer.Camera.AbsoluteSide.Normalize(); Renderer.Camera.AbsoluteUp = Vector3.Cross(Renderer.Camera.AbsoluteDirection, Renderer.Camera.AbsoluteSide); Renderer.Camera.VerticalViewingAngle = 45.0.ToRadians(); Renderer.Camera.HorizontalViewingAngle = 2.0 * Math.Atan(Math.Tan(0.5 * Renderer.Camera.VerticalViewingAngle) * Renderer.Screen.AspectRatio); Renderer.Camera.OriginalVerticalViewingAngle = Renderer.Camera.VerticalViewingAngle; }
internal void CreateObject(UnifiedObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, int SectionIndex, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { if (Prototype is StaticObject) { StaticObject s = (StaticObject)Prototype; if (s.Mesh.Faces.Length == 0) { return; } CreateStaticObject(s, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness); } else if (Prototype is AnimatedObjectCollection) { AnimatedObjectCollection a = (AnimatedObjectCollection)Prototype; a.CreateObject(Position, BaseTransformation, AuxTransformation, SectionIndex, AccurateObjectDisposal, StartingDistance, EndingDistance, BlockLength, TrackPosition, Brightness, true); } }
/// <summary>May be called from a .Net plugin, in order to play a sound from a specific car of a train</summary> /// <param name="index">The plugin-based of the sound to play</param> /// <param name="volume">The volume of the sound- A volume of 1.0 represents nominal volume</param> /// <param name="pitch">The pitch of the sound- A pitch of 1.0 represents nominal pitch</param> /// <param name="looped">Whether the sound is looped</param> /// <param name="CarIndex">The index of the car which is to emit the sound</param> /// <returns>The sound handle, or null if not successful</returns> internal SoundHandleEx PlaySound(int index, double volume, double pitch, bool looped, int CarIndex) { if (index >= 0 && index < this.Train.Cars[this.Train.DriverCar].Sounds.Plugin.Length && this.Train.Cars[this.Train.DriverCar].Sounds.Plugin[index].Buffer != null && CarIndex < this.Train.Cars.Length && CarIndex >= 0) { SoundBuffer buffer = Train.Cars[Train.DriverCar].Sounds.Plugin[index].Buffer; OpenBveApi.Math.Vector3 position = this.Train.Cars[this.Train.DriverCar].Sounds.Plugin[index].Position; SoundSource source = Program.Sounds.PlaySound(buffer, pitch, volume, position, Train.Cars[CarIndex], looped); if (this.SoundHandlesCount == this.SoundHandles.Length) { Array.Resize(ref this.SoundHandles, this.SoundHandles.Length << 1); } this.SoundHandles[this.SoundHandlesCount] = new SoundHandleEx(volume, pitch, source); this.SoundHandlesCount++; return(this.SoundHandles[this.SoundHandlesCount - 1]); } return(null); }
/// <summary>Applies a reverser notch</summary> /// <param name="Value">The notch to apply</param> /// <param name="Relative">Whether this is an absolute value or relative to the previous</param> internal void ApplyReverser(int Value, bool Relative) { int a = (int)Handles.Reverser.Driver; int r = Relative ? a + Value : Value; if (r < -1) { r = -1; } if (r > 1) { r = 1; } if (a != r) { Handles.Reverser.Driver = (ReverserPosition)r; if (Plugin != null) { Plugin.UpdateReverser(); } Game.AddBlackBoxEntry(Game.BlackBoxEventToken.None); // sound if (a == 0 & r != 0) { Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.ReverserOn.Buffer; if (buffer == null) { return; } OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.ReverserOn.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } else if (a != 0 & r == 0) { Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.ReverserOff.Buffer; if (buffer == null) { return; } OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.ReverserOff.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } }
internal static void MouseEvent(object sender, MouseButtonEventArgs e) { MouseCameraPosition = Camera.AbsolutePosition; MouseCameraDirection = Camera.AbsoluteDirection; MouseCameraUp = Camera.AbsoluteUp; MouseCameraSide = Camera.AbsoluteSide; if (e.Button == OpenTK.Input.MouseButton.Left) { MouseButton = e.Mouse.LeftButton == ButtonState.Pressed ? 1 : 0; } if (e.Button == OpenTK.Input.MouseButton.Right) { MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 2 : 0; } if (e.Button == OpenTK.Input.MouseButton.Middle) { MouseButton = e.Mouse.RightButton == ButtonState.Pressed ? 3 : 0; } previousMouseState = Mouse.GetState(); }
// render scene internal void RenderScene(double TimeElapsed) { // initialize ResetOpenGlState(); if (OptionWireFrame) { if (Program.CurrentRoute.CurrentFog.Start < Program.CurrentRoute.CurrentFog.End) { const float fogDistance = 600.0f; float n = (fogDistance - Program.CurrentRoute.CurrentFog.Start) / (Program.CurrentRoute.CurrentFog.End - Program.CurrentRoute.CurrentFog.Start); float cr = n * inv255 * Program.CurrentRoute.CurrentFog.Color.R; float cg = n * inv255 * Program.CurrentRoute.CurrentFog.Color.G; float cb = n * inv255 * Program.CurrentRoute.CurrentFog.Color.B; GL.ClearColor(cr, cg, cb, 1.0f); } else { GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); } } GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); UpdateViewport(ViewportChangeMode.ChangeToScenery); // set up camera CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); if (!AvailableNewRenderer) { GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)Lighting.OptionLightPosition.X, (float)Lighting.OptionLightPosition.Y, (float)-Lighting.OptionLightPosition.Z, 0.0f }); } Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } // fog double fd = Program.CurrentRoute.NextFog.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition; if (fd != 0.0) { float fr = (float)((CameraTrackFollower.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition) / fd); float frc = 1.0f - fr; Program.CurrentRoute.CurrentFog.Start = Program.CurrentRoute.PreviousFog.Start * frc + Program.CurrentRoute.NextFog.Start * fr; Program.CurrentRoute.CurrentFog.End = Program.CurrentRoute.PreviousFog.End * frc + Program.CurrentRoute.NextFog.End * fr; Program.CurrentRoute.CurrentFog.Color.R = (byte)(Program.CurrentRoute.PreviousFog.Color.R * frc + Program.CurrentRoute.NextFog.Color.R * fr); Program.CurrentRoute.CurrentFog.Color.G = (byte)(Program.CurrentRoute.PreviousFog.Color.G * frc + Program.CurrentRoute.NextFog.Color.G * fr); Program.CurrentRoute.CurrentFog.Color.B = (byte)(Program.CurrentRoute.PreviousFog.Color.B * frc + Program.CurrentRoute.NextFog.Color.B * fr); if (!Program.CurrentRoute.CurrentFog.IsLinear) { Program.CurrentRoute.CurrentFog.Density = (byte)(Program.CurrentRoute.PreviousFog.Density * frc + Program.CurrentRoute.NextFog.Density * fr); } } else { Program.CurrentRoute.CurrentFog = Program.CurrentRoute.PreviousFog; } // render background GL.Disable(EnableCap.DepthTest); Program.CurrentRoute.UpdateBackground(TimeElapsed, Program.Renderer.CurrentInterface != InterfaceType.Normal); events.Render(Camera.AbsolutePosition); // fog float aa = Program.CurrentRoute.CurrentFog.Start; float bb = Program.CurrentRoute.CurrentFog.End; if (aa < bb & aa < Program.CurrentRoute.CurrentBackground.BackgroundImageDistance) { OptionFog = true; Fog.Start = aa; Fog.End = bb; Fog.Color = Program.CurrentRoute.CurrentFog.Color; Fog.Density = Program.CurrentRoute.CurrentFog.Density; Fog.IsLinear = Program.CurrentRoute.CurrentFog.IsLinear; Fog.SetForImmediateMode(); } else { OptionFog = false; } // world layer // opaque face if (AvailableNewRenderer) { //Setup the shader for rendering the scene DefaultShader.Activate(); if (OptionLighting) { DefaultShader.SetIsLight(true); TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); DefaultShader.SetLightPosition(TransformedLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); DefaultShader.SetLightModel(Lighting.LightModel); } if (OptionFog) { DefaultShader.SetIsFog(true); DefaultShader.SetFog(Fog); } DefaultShader.SetTexture(0); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } ResetOpenGlState(); foreach (FaceState face in VisibleObjects.OpaqueFaces) { face.Draw(); } // alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.AlphaFaces) { face.Draw(); } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { face.Draw(); } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } face.Draw(); } else { if (additive) { SetAlphaFunc(); additive = false; } face.Draw(); } } } // motion blur ResetOpenGlState(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.Disable(EnableCap.DepthTest); GL.DepthMask(false); OptionLighting = false; if (Interface.CurrentOptions.MotionBlur != MotionBlurMode.None) { DefaultShader.Deactivate(); MotionBlur.RenderFullscreen(Interface.CurrentOptions.MotionBlur, FrameRate, Math.Abs(Camera.CurrentSpeed)); } // overlay layer OptionFog = false; UpdateViewport(ViewportChangeMode.ChangeToCab); if (AvailableNewRenderer) { /* * We must reset the shader between overlay and world layers for correct lighting results. * Additionally, the viewport change updates the projection matrix */ DefaultShader.Activate(); ResetShader(DefaultShader); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); if (Camera.CurrentRestriction == CameraRestrictionMode.NotAvailable || Camera.CurrentRestriction == CameraRestrictionMode.Restricted3D) { ResetOpenGlState(); // TODO: inserted GL.Clear(ClearBufferMask.DepthBufferBit); OptionLighting = true; Color24 prevOptionAmbientColor = Lighting.OptionAmbientColor; Color24 prevOptionDiffuseColor = Lighting.OptionDiffuseColor; Lighting.OptionAmbientColor = Color24.LightGrey; Lighting.OptionDiffuseColor = Color24.LightGrey; if (AvailableNewRenderer) { DefaultShader.SetIsLight(true); TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); DefaultShader.SetLightPosition(TransformedLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); DefaultShader.SetLightModel(Lighting.LightModel); } else { GL.Light(LightName.Light0, LightParameter.Ambient, new[] { inv255 * 178, inv255 * 178, inv255 * 178, 1.0f }); GL.Light(LightName.Light0, LightParameter.Diffuse, new[] { inv255 * 178, inv255 * 178, inv255 * 178, 1.0f }); } // overlay opaque face foreach (FaceState face in VisibleObjects.OverlayOpaqueFaces) { face.Draw(); } // overlay alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInOverlayAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { face.Draw(); } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { face.Draw(); } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } face.Draw(); } else { if (additive) { SetAlphaFunc(); additive = false; } face.Draw(); } } } Lighting.OptionAmbientColor = prevOptionAmbientColor; Lighting.OptionDiffuseColor = prevOptionDiffuseColor; Lighting.Initialize(); } else { /* * Render 2D Cab * This is actually an animated object generated on the fly and held in memory */ ResetOpenGlState(); OptionLighting = false; if (AvailableNewRenderer) { DefaultShader.SetIsLight(false); } SetBlendFunc(); UnsetAlphaFunc(); GL.Disable(EnableCap.DepthTest); GL.DepthMask(false); VisibleObjects.SortPolygonsInOverlayAlphaFaces(); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { face.Draw(); } } if (AvailableNewRenderer) { /* * Must remember to de-activate at the end of the render sequence if in GL3 mode. * The overlays currently use immediate mode and do not work correctly with the shader active */ DefaultShader.Deactivate(); } // render touch OptionLighting = false; Touch.RenderScene(); // render overlays ResetOpenGlState(); UnsetAlphaFunc(); SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); //FIXME: Remove when text switches between two renderer types GL.Disable(EnableCap.DepthTest); overlays.Render(TimeElapsed); OptionLighting = true; }
/// <summary>Draws a 3D cube in immediate mode</summary> /// <param name="Position">The position in world-space</param> /// <param name="Direction">The direction vector</param> /// <param name="Up">The up vector</param> /// <param name="Side">The side vector</param> /// <param name="Size">A 3D vector describing the size of the cube</param> /// <param name="Camera">The camera position</param> /// <param name="TextureIndex">The texture to apply</param> public void DrawImmediate(OpenBveApi.Math.Vector3 Position, OpenBveApi.Math.Vector3 Direction, OpenBveApi.Math.Vector3 Up, OpenBveApi.Math.Vector3 Side, OpenBveApi.Math.Vector3 Size, OpenBveApi.Math.Vector3 Camera, Texture TextureIndex) { renderer.LastBoundTexture = null; GL.MatrixMode(MatrixMode.Projection); GL.PushMatrix(); GL.LoadIdentity(); OpenTK.Matrix4d perspective = OpenTK.Matrix4d.Perspective(renderer.Camera.VerticalViewingAngle, -renderer.Screen.AspectRatio, 0.2, 1000.0); GL.MultMatrix(ref perspective); double dx = renderer.Camera.AbsoluteDirection.X; double dy = renderer.Camera.AbsoluteDirection.Y; double dz = renderer.Camera.AbsoluteDirection.Z; double ux = renderer.Camera.AbsoluteUp.X; double uy = renderer.Camera.AbsoluteUp.Y; double uz = renderer.Camera.AbsoluteUp.Z; OpenTK.Matrix4d lookat = OpenTK.Matrix4d.LookAt(0.0, 0.0, 0.0, dx, dy, dz, ux, uy, uz); GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadMatrix(ref lookat); Vector3[] v = new Vector3[8]; v[0] = new Vector3(Size.X, Size.Y, -Size.Z); v[1] = new Vector3(Size.X, -Size.Y, -Size.Z); v[2] = new Vector3(-Size.X, -Size.Y, -Size.Z); v[3] = new Vector3(-Size.X, Size.Y, -Size.Z); v[4] = new Vector3(Size.X, Size.Y, Size.Z); v[5] = new Vector3(Size.X, -Size.Y, Size.Z); v[6] = new Vector3(-Size.X, -Size.Y, Size.Z); v[7] = new Vector3(-Size.X, Size.Y, Size.Z); for (int i = 0; i < 8; i++) { v[i].Rotate(Direction, Up, Side); v[i] += Position - Camera; } int[][] Faces = new int[6][]; Faces[0] = new int[] { 0, 1, 2, 3 }; Faces[1] = new int[] { 0, 4, 5, 1 }; Faces[2] = new int[] { 0, 3, 7, 4 }; Faces[3] = new int[] { 6, 5, 4, 7 }; Faces[4] = new int[] { 6, 7, 3, 2 }; Faces[5] = new int[] { 6, 2, 1, 5 }; if (TextureIndex == null || !renderer.currentHost.LoadTexture(TextureIndex, OpenGlTextureWrapMode.ClampClamp)) { GL.Disable(EnableCap.Texture2D); for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); for (int j = 0; j < 4; j++) { GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); } GL.End(); } return; } GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); Vector2[][] t = new Vector2[6][]; t[0] = new Vector2[] { new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0) }; t[1] = new Vector2[] { new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) }; t[2] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[3] = new Vector2[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; t[4] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; t[5] = new Vector2[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; for (int i = 0; i < 6; i++) { GL.Begin(PrimitiveType.Quads); GL.Color3(1.0, 1.0, 1.0); for (int j = 0; j < 4; j++) { GL.TexCoord2(t[i][j].X, t[i][j].Y); GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); } GL.End(); } GL.PopMatrix(); GL.MatrixMode(MatrixMode.Projection); GL.PopMatrix(); }
/// <summary>Updates the sound component. Should be called every frame.</summary> /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param> private static void UpdateInverseModel(double timeElapsed) { /* * Set up the listener. * */ OpenBveApi.Math.Vector3 listenerPosition = World.AbsoluteCameraPosition; OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection); OpenBveApi.Math.Vector3 listenerVelocity; if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead | World.CameraMode == World.CameraViewMode.Exterior) { TrainManager.Car car = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar]; OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition; if (diff.IsNullVector()) { listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Forward; } else { listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff); } } else { listenerVelocity = OpenBveApi.Math.Vector3.Null; } AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f); AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z); var Orientation = new float[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z }; AL.Listener(ALListenerfv.Orientation, ref Orientation); /* * Set up the atmospheric attributes. * */ double elevation = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation; double airTemperature = Game.GetAirTemperature(elevation); double airPressure = Game.GetAirPressure(elevation, airTemperature); double speedOfSound = Game.GetSpeedOfSound(airPressure, airTemperature); try { AL.SpeedOfSound((float)speedOfSound); } catch { } /* * Collect all sounds that are to be played * and ensure that all others are stopped. * */ List <SoundSourceAttenuation> toBePlayed = new List <SoundSourceAttenuation>(); for (int i = 0; i < SourceCount; i++) { if (Sources[i].State == SoundSourceState.StopPending) { /* * The sound is still playing but is to be stopped. * Stop the sound, then remove it from the list of * sound sources. * */ AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } else if (Sources[i].State == SoundSourceState.Stopped) { /* * The sound was already stopped. Remove it from * the list of sound sources. * */ Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } else if (GlobalMute) { /* * The sound is playing or about to be played, but * the global mute option is enabled. Stop the sound * sound if necessary, then remove it from the list * of sound sources if the sound is not looping. * */ if (Sources[i].State == SoundSourceState.Playing) { AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.PlayPending; Sources[i].OpenAlSourceName = 0; } if (!Sources[i].Looped) { Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } } else { /* * The sound is to be played or is already playing. * */ if (Sources[i].State == SoundSourceState.Playing) { int state; AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state); if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing) { /* * The sound is not playing any longer. * Remove it from the list of sound sources. * */ AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; continue; } } /* * Calculate the gain, then add the sound * to the list of sounds to be played. * */ OpenBveApi.Math.Vector3 position; switch (Sources[i].Type) { case SoundType.TrainCar: OpenBveApi.Math.Vector3 direction; var Train = (TrainManager.Train)Sources[i].Parent; Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position.X, Sources[i].Position.Y, Sources[i].Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z); break; case SoundType.AnimatedObject: var WorldSound = (ObjectManager.WorldSound)Sources[i].Parent; position = WorldSound.Follower.WorldPosition + WorldSound.Position; break; default: position = Sources[i].Position; break; } OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition; double distance = positionDifference.Norm(); double radius = Sources[i].Radius; if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead) { if (Sources[i].Parent != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar) { radius *= 0.5; } } double gain; if (distance < 2.0 * radius) { gain = 1.0 - distance * distance * (4.0 * radius - distance) / (16.0 * radius * radius * radius); } else { gain = radius / distance; } gain *= Sources[i].Volume; if (gain <= 0.0) { /* * The gain is too low. Stop the sound if playing, * but keep looping sounds pending. * */ if (Sources[i].State == SoundSourceState.Playing) { AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.PlayPending; Sources[i].OpenAlSourceName = 0; } if (!Sources[i].Looped) { Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } } else { /* * Add the source. * */ toBePlayed.Add(new SoundSourceAttenuation(Sources[i], gain, distance)); } } } /* * Now that we have the list of sounds that are to be played, * sort them by their gain so that we can determine and * adjust the clamp factor. * */ double clampFactor = Math.Exp(LogClampFactor); for (int i = 0; i < toBePlayed.Count; i++) { toBePlayed[i].Gain -= clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance; } toBePlayed.Sort(); for (int i = 0; i < toBePlayed.Count; i++) { toBePlayed[i].Gain += clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance; } double desiredLogClampFactor; int index = Interface.CurrentOptions.SoundNumber; if (toBePlayed.Count <= index) { desiredLogClampFactor = MinLogClampFactor; } else { double cutoffDistance = toBePlayed[index].Distance; if (cutoffDistance <= 0.0) { desiredLogClampFactor = MaxLogClampFactor; } else { double cutoffGain = toBePlayed[index].Gain; desiredLogClampFactor = Math.Log(cutoffGain / (cutoffDistance * cutoffDistance)); if (desiredLogClampFactor < MinLogClampFactor) { desiredLogClampFactor = MinLogClampFactor; } else if (desiredLogClampFactor > MaxLogClampFactor) { desiredLogClampFactor = MaxLogClampFactor; } } } const double rate = 3.0; if (LogClampFactor < desiredLogClampFactor) { LogClampFactor += timeElapsed * rate; if (LogClampFactor > desiredLogClampFactor) { LogClampFactor = desiredLogClampFactor; } } else if (LogClampFactor > desiredLogClampFactor) { LogClampFactor -= timeElapsed * rate; if (LogClampFactor < desiredLogClampFactor) { LogClampFactor = desiredLogClampFactor; } } /* * Play the sounds. * */ clampFactor = Math.Exp(LogClampFactor); for (int i = index; i < toBePlayed.Count; i++) { toBePlayed[i].Gain = 0.0; } for (int i = 0; i < toBePlayed.Count; i++) { SoundSource source = toBePlayed[i].Source; double gain = toBePlayed[i].Gain - clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance; if (gain <= 0.0) { /* * Stop the sound. * */ if (source.State == SoundSourceState.Playing) { AL.DeleteSources(1, ref source.OpenAlSourceName); source.State = SoundSourceState.PlayPending; source.OpenAlSourceName = 0; } if (!source.Looped) { source.State = SoundSourceState.Stopped; source.OpenAlSourceName = 0; } } else { /* * Ensure the buffer is loaded, then play the sound. * */ if (source.State != SoundSourceState.Playing) { LoadBuffer(source.Buffer); if (source.Buffer.Loaded) { AL.GenSources(1, out source.OpenAlSourceName); AL.Source(source.OpenAlSourceName, ALSourcei.Buffer, source.Buffer.OpenAlBufferName); } else { /* * We cannot play the sound because * the buffer could not be loaded. * */ source.State = SoundSourceState.Stopped; continue; } } OpenBveApi.Math.Vector3 position; OpenBveApi.Math.Vector3 velocity; switch (source.Type) { case SoundType.TrainCar: OpenBveApi.Math.Vector3 direction; var Train = (TrainManager.Train)source.Parent; Train.Cars[source.Car].CreateWorldCoordinates(source.Position.X, source.Position.Y, source.Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z); velocity = Train.Cars[source.Car].Specs.CurrentSpeed * direction; break; case SoundType.AnimatedObject: var WorldSound = (ObjectManager.WorldSound)source.Parent; position = WorldSound.Follower.WorldPosition + WorldSound.Position; velocity = OpenBveApi.Math.Vector3.Null; break; default: position = source.Position; velocity = OpenBveApi.Math.Vector3.Null; break; } position -= listenerPosition; AL.Source(source.OpenAlSourceName, ALSource3f.Position, (float)position.X, (float)position.Y, (float)position.Z); AL.Source(source.OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z); AL.Source(source.OpenAlSourceName, ALSourcef.Pitch, (float)source.Pitch); AL.Source(source.OpenAlSourceName, ALSourcef.Gain, (float)gain); if (source.State != SoundSourceState.Playing) { AL.Source(source.OpenAlSourceName, ALSourceb.Looping, source.Looped); AL.SourcePlay(source.OpenAlSourceName); source.State = SoundSourceState.Playing; } } } }
// constructors /// <summary>Creates a new instance of this class.</summary> /// <param name="position">The default position of the camera.</param> /// <param name="orientation">The default orientation of the camera.</param> /// <param name="lightingModel">The lighting model used by this route.</param> public RouteData(Math.Vector3 position, Math.Orientation3 orientation, LightingModel lightingModel) { this.Position = position; this.Orientation = orientation; this.LightingModel = lightingModel; }
internal int CreateStaticObject(StaticObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition) { return(base.CreateStaticObject(Prototype, Position, BaseTransformation, AuxTransformation, AccurateObjectDisposal, 0.0, StartingDistance, EndingDistance, BlockLength, TrackPosition, 1.0)); }
/// <summary>Updates the sound component. Should be called every frame.</summary> /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param> private static void UpdateLinearModel(double timeElapsed) { /* * Set up the listener * */ OpenBveApi.Math.Vector3 listenerPosition = World.AbsoluteCameraPosition; OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection); OpenBveApi.Math.Vector3 listenerVelocity; if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead | World.CameraMode == World.CameraViewMode.Exterior) { TrainManager.Car car = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar]; OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition; listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff) + World.CameraAlignmentSpeed.Position; } else { listenerVelocity = World.CameraAlignmentSpeed.Position; } AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f); AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z); var Orientation = new[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z }; AL.Listener(ALListenerfv.Orientation, ref Orientation); /* * Set up the atmospheric attributes * */ double elevation = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation; double airTemperature = Game.GetAirTemperature(elevation); double airPressure = Game.GetAirPressure(elevation, airTemperature); double speedOfSound = Game.GetSpeedOfSound(airPressure, airTemperature); try { AL.SpeedOfSound((float)speedOfSound); } catch { } /* * Update the sound sources * */ int actuallyPlaying = 0; for (int i = 0; i < SourceCount; i++) { if (Sources[i].State == SoundSourceState.StopPending) { /* * The sound is still playing but is to be stopped. * Stop the sound, then remove it from the list of * sound sources. * */ AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } else if (Sources[i].State == SoundSourceState.Stopped) { /* * The sound was already stopped. Remove it from * the list of sound sources. * */ Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } else if (GlobalMute) { /* * The sound is playing or about to be played, but * the global mute option is enabled. Stop the sound * sound if necessary, then remove it from the list * of sound sources if the sound is not looping. * */ if (Sources[i].State == SoundSourceState.Playing) { AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.PlayPending; Sources[i].OpenAlSourceName = 0; } if (!Sources[i].Looped) { Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } } else { /* * The sound is to be played or is already playing. * Calculate the sound gain. * */ OpenBveApi.Math.Vector3 direction; OpenBveApi.Math.Vector3 position; OpenBveApi.Math.Vector3 velocity; switch (Sources[i].Type) { case SoundType.TrainCar: var Train = (TrainManager.Train)Sources[i].Parent; Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position.X, Sources[i].Position.Y, Sources[i].Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z); velocity = Train.Cars[Sources[i].Car].Specs.CurrentSpeed * direction; break; case SoundType.AnimatedObject: var WorldSound = (ObjectManager.WorldSound)Sources[i].Parent; //TODO: Calculate speed... position = WorldSound.Follower.WorldPosition + WorldSound.Position; velocity = Vector3.Null; break; default: position = Sources[i].Position; velocity = Vector3.Null; break; } OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition; double gain; if (GlobalMute) { gain = 0.0; } else { double distance = positionDifference.Norm(); double innerRadius = Sources[i].Radius; if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead) { if (Sources[i].Parent != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar) { innerRadius *= 0.5; } } double outerRadius = OuterRadiusFactor * innerRadius; if (distance < outerRadius) { if (distance <= innerRadius) { gain = Sources[i].Volume; } else { gain = (distance - outerRadius) / (innerRadius - outerRadius); gain *= Sources[i].Volume; } gain = 3.0 * gain * gain - 2.0 * gain * gain * gain; } else { gain = 0.0; } } if (gain <= GainThreshold) { /* * If the gain is too low to be audible, stop the sound. * If the sound is not looping, stop it if necessary, * then remove it from the list of sound sources. * */ if (Sources[i].State == SoundSourceState.Playing) { AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.PlayPending; Sources[i].OpenAlSourceName = 0; } if (!Sources[i].Looped) { Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } } else { /* * Play the sound and update position, velocity, pitch and gain. * For non-looping sounds, check if the sound is still playing. * */ gain = (gain - GainThreshold) / (1.0 - GainThreshold); if (Sources[i].State != SoundSourceState.Playing) { LoadBuffer(Sources[i].Buffer); if (Sources[i].Buffer.Loaded) { AL.GenSources(1, out Sources[i].OpenAlSourceName); AL.Source(Sources[i].OpenAlSourceName, ALSourcei.Buffer, Sources[i].Buffer.OpenAlBufferName); } else { /* * We cannot play the sound because * the buffer could not be loaded. * */ Sources[i].State = SoundSourceState.Stopped; continue; } } AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Position, (float)positionDifference.X, (float)positionDifference.Y, (float)positionDifference.Z); AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z); AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Pitch, (float)Sources[i].Pitch); AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Gain, (float)gain); if (Sources[i].State != SoundSourceState.Playing) { AL.Source(Sources[i].OpenAlSourceName, ALSourceb.Looping, Sources[i].Looped); AL.SourcePlay(Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.Playing; } if (!Sources[i].Looped) { int state; AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state); if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing) { /* * The sound is not playing any longer. * Remove it from the list of sound sources. * */ AL.DeleteSources(1, ref Sources[i].OpenAlSourceName); Sources[i].State = SoundSourceState.Stopped; Sources[i].OpenAlSourceName = 0; Sources[i] = Sources[SourceCount - 1]; SourceCount--; i--; } else { actuallyPlaying++; } } else { actuallyPlaying++; } } } } /* * Adjust the outer radius factor / the clamp factor. * */ if (actuallyPlaying >= Interface.CurrentOptions.SoundNumber - 2) { /* * Too many sounds are playing. * Reduce the outer radius factor. * */ OuterRadiusFactorSpeed -= timeElapsed; if (OuterRadiusFactorSpeed < -OuterRadiusFactorMaximumSpeed) { OuterRadiusFactorSpeed = -OuterRadiusFactorMaximumSpeed; } } else if (actuallyPlaying <= Interface.CurrentOptions.SoundNumber - 6) { /* * Only few sounds are playing. * Increase the outer radius factor. * */ OuterRadiusFactorSpeed += timeElapsed; if (OuterRadiusFactorSpeed > OuterRadiusFactorMaximumSpeed) { OuterRadiusFactorSpeed = OuterRadiusFactorMaximumSpeed; } } else { /* * Neither too many nor too few sounds are playing. * Stabilize the outer radius factor. * */ if (OuterRadiusFactorSpeed < 0.0) { OuterRadiusFactorSpeed += timeElapsed; if (OuterRadiusFactorSpeed > 0.0) { OuterRadiusFactorSpeed = 0.0; } } else { OuterRadiusFactorSpeed -= timeElapsed; if (OuterRadiusFactorSpeed < 0.0) { OuterRadiusFactorSpeed = 0.0; } } } OuterRadiusFactor += OuterRadiusFactorSpeed * timeElapsed; if (OuterRadiusFactor < OuterRadiusFactorMinimum) { OuterRadiusFactor = OuterRadiusFactorMinimum; OuterRadiusFactorSpeed = 0.0; } else if (OuterRadiusFactor > OuterRadiusFactorMaximum) { OuterRadiusFactor = OuterRadiusFactorMaximum; OuterRadiusFactorSpeed = 0.0; } }
public void RenderFace(Shader Shader, ObjectState State, MeshFace Face, Vector3 EyePosition, bool IsDebugTouchMode = false) { if (State.Prototype.Mesh.Vertices.Length < 1) { return; } VertexTemplate[] vertices = State.Prototype.Mesh.Vertices; MeshMaterial material = State.Prototype.Mesh.Materials[Face.Material]; VertexArrayObject VAO = (VertexArrayObject)State.Prototype.Mesh.VAO; VertexArrayObject NormalsVAO = (VertexArrayObject)State.Prototype.Mesh.NormalsVAO; if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0) { GL.Disable(EnableCap.CullFace); } else if (OptionBackFaceCulling) { if ((Face.Flags & MeshFace.Face2Mask) == 0) { GL.Enable(EnableCap.CullFace); } } // matrix Matrix4D modelMatrix = State.Scale * State.Rotate * State.Translation * Matrix4D.CreateTranslation(-EyePosition); Matrix4D modelViewMatrix = modelMatrix * CurrentViewMatrix; Shader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); Shader.SetCurrentModelViewMatrix(modelViewMatrix); Shader.SetCurrentNormalMatrix(Matrix4D.Transpose(Matrix4D.Invert(modelViewMatrix))); Shader.SetCurrentTextureMatrix(State.TextureTranslation); if (OptionWireFrame || IsDebugTouchMode) { VAO.Bind(); VAO.Draw(Shader.VertexLayout, PrimitiveType.LineLoop, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); return; } // lighting if (material.NighttimeTexture == null) { if (OptionLighting) { Shader.SetIsLight(true); Shader.SetLightPosition(new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z)); Shader.SetLightAmbient(new Color4(Lighting.OptionAmbientColor.R, Lighting.OptionAmbientColor.G, Lighting.OptionAmbientColor.B, 255)); Shader.SetLightDiffuse(new Color4(Lighting.OptionDiffuseColor.R, Lighting.OptionDiffuseColor.G, Lighting.OptionDiffuseColor.B, 255)); Shader.SetLightSpecular(new Color4(Lighting.OptionSpecularColor.R, Lighting.OptionSpecularColor.G, Lighting.OptionSpecularColor.B, 255)); Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO Shader.SetMaterialDiffuse(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); Shader.SetMaterialSpecular(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0) { Shader.SetMaterialEmission(new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255)); } else { Shader.SetMaterialEmission(new Color4(0.0f, 0.0f, 0.0f, 1.0f)); } Shader.SetMaterialShininess(1.0f); Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } } else { Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO } } else { Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A)); // TODO } // fog if (OptionFog) { Shader.SetIsFog(true); Shader.SetFogStart(Fog.Start); Shader.SetFogEnd(Fog.End); Shader.SetFogColor(new Color4(Fog.Color.R, Fog.Color.G, Fog.Color.B, 255)); } PrimitiveType DrawMode; switch (Face.Flags & MeshFace.FaceTypeMask) { case MeshFace.FaceTypeTriangles: DrawMode = PrimitiveType.Triangles; break; case MeshFace.FaceTypeTriangleStrip: DrawMode = PrimitiveType.TriangleStrip; break; case MeshFace.FaceTypeQuads: DrawMode = PrimitiveType.Quads; break; case MeshFace.FaceTypeQuadStrip: DrawMode = PrimitiveType.QuadStrip; break; default: DrawMode = PrimitiveType.Polygon; break; } // daytime polygon { // texture if (material.DaytimeTexture != null) { if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { GL.Enable(EnableCap.Texture2D); Shader.SetIsTexture(true); Shader.SetTexture(0); GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name); } } // blend mode float factor; if (material.BlendMode == MeshMaterialBlendMode.Additive) { factor = 1.0f; GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); Shader.SetIsFog(false); } else if (material.NighttimeTexture == null) { float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } factor = 1.0f - 0.7f * blend; } else { factor = 1.0f; } Shader.SetBrightness(factor); float alphaFactor; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData); } else { alphaFactor = 1.0f; } Shader.SetOpacity(inv255 * material.Color.A * alphaFactor); // render polygon VAO.Bind(); VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); GL.BindTexture(TextureTarget.Texture2D, 0); } // nighttime polygon if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) { // texture GL.Enable(EnableCap.Texture2D); Shader.SetIsTexture(true); Shader.SetTexture(0); GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name); GL.Enable(EnableCap.Blend); // alpha test GL.Enable(EnableCap.AlphaTest); GL.AlphaFunc(AlphaFunction.Greater, 0.0f); // blend mode float alphaFactor; if (material.GlowAttenuationData != 0) { alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData); float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (blend > 1.0f) { blend = 1.0f; } alphaFactor *= blend; } else { alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; if (alphaFactor > 1.0f) { alphaFactor = 1.0f; } } Shader.SetOpacity(alphaFactor); // render polygon VAO.Bind(); VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length); VAO.UnBind(); GL.BindTexture(TextureTarget.Texture2D, 0); RestoreBlendFunc(); RestoreAlphaFunc(); } GL.Disable(EnableCap.Texture2D); // normals if (OptionNormals) { Shader.SetIsTexture(false); Shader.SetBrightness(1.0f); Shader.SetOpacity(1.0f); NormalsVAO.Bind(); NormalsVAO.Draw(Shader.VertexLayout, PrimitiveType.Lines, Face.NormalsIboStartIndex, Face.Vertices.Length * 2); NormalsVAO.UnBind(); } // finalize if (material.BlendMode == MeshMaterialBlendMode.Additive) { RestoreBlendFunc(); } }
public void RenderFace(Shader Shader, FaceState State, Vector3 EyePosition, bool IsDebugTouchMode = false) { RenderFace(Shader, State.Object, State.Face, EyePosition, IsDebugTouchMode); }
/// <summary>Applies a power and / or brake notch to this train</summary> /// <param name="PowerValue">The power notch value</param> /// <param name="PowerRelative">Whether this is relative to the current notch</param> /// <param name="BrakeValue">The brake notch value</param> /// <param name="BrakeRelative">Whether this is relative to the current notch</param> internal void ApplyNotch(int PowerValue, bool PowerRelative, int BrakeValue, bool BrakeRelative) { // determine notch int p = PowerRelative ? PowerValue + Handles.Power.Driver : PowerValue; if (p < 0) { p = 0; } else if (p > Handles.Power.MaximumNotch) { p = Handles.Power.MaximumNotch; } int b = BrakeRelative ? BrakeValue + Handles.Brake.Driver : BrakeValue; if (b < 0) { b = 0; } else if (b > Handles.Brake.MaximumNotch) { b = Handles.Brake.MaximumNotch; } // power sound if (p < Handles.Power.Driver) { if (p > 0) { // down (not min) Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.MasterControllerDown.Buffer; if (buffer != null) { Vector3 pos = Cars[DriverCar].Sounds.MasterControllerDown.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } else { // min Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.MasterControllerMin.Buffer; if (buffer != null) { Vector3 pos = Cars[DriverCar].Sounds.MasterControllerMin.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } else if (p > Handles.Power.Driver) { if (p < Handles.Power.MaximumNotch) { // up (not max) Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.MasterControllerUp.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.MasterControllerUp.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } else { // max Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.MasterControllerMax.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.MasterControllerMax.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } // brake sound if (b < Handles.Brake.Driver) { // brake release Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.Brake.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.Brake.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } if (b > 0) { // brake release (not min) buffer = Cars[DriverCar].Sounds.BrakeHandleRelease.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleRelease.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } else { // brake min buffer = Cars[DriverCar].Sounds.BrakeHandleMin.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleMin.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } else if (b > Handles.Brake.Driver) { // brake Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleApply.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleApply.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } // apply notch if (Handles.SingleHandle) { if (b != 0) { p = 0; } } Handles.Power.Driver = p; Handles.Brake.Driver = b; Game.AddBlackBoxEntry(Game.BlackBoxEventToken.None); // plugin if (Plugin != null) { Plugin.UpdatePower(); Plugin.UpdateBrake(); } }
// constructors /// <summary>Creates a new instance of this structure.</summary> /// <param name="spatialCoordinates">The spatial coordinates.</param> /// <param name="normal">The surface normal.</param> /// <param name="textureCoordinates">The texture coordinates.</param> /// <param name="reflectiveColor">The reflective color.</param> /// <param name="tag">A field to convey intermediate information.</param> public Vertex(Math.Vector3 spatialCoordinates, Math.Vector2 textureCoordinates, Math.Vector3 normal, Color.ColorRGBA reflectiveColor, int tag) { this.SpatialCoordinates = spatialCoordinates; this.TextureCoordinates = textureCoordinates; this.Normal = normal; this.ReflectiveColor = reflectiveColor; this.Tag = tag; }
public override void PlayMicSound(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance) { Program.Sounds.PlayMicSound(position, backwardTolerance, forwardTolerance); }
/// <summary>Plays a sound.</summary> /// <param name="buffer">The sound buffer.</param> /// <param name="pitch">The pitch change factor.</param> /// <param name="volume">The volume change factor.</param> /// <param name="position">The position. If a train car is specified, the position is relative to the car, otherwise absolute.</param> /// <param name="parent">The parent object the sound is attached to, or a null reference.</param> /// <param name="looped">Whether to play the sound in a loop.</param> /// <returns>The sound source.</returns> public virtual object PlaySound(SoundHandle buffer, double pitch, double volume, OpenBveApi.Math.Vector3 position, object parent, bool looped) { return(null); }
public void SetLightPosition(Vector3 LightPosition) { GL.ProgramUniform3(handle, UniformLayout.LightPosition, (float)LightPosition.X, (float)LightPosition.Y, (float)LightPosition.Z); }
/// <summary>Applies the emergency brake</summary> internal void ApplyEmergencyBrake() { // sound if (!Handles.EmergencyBrake.Driver) { Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleMax.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleMax.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } for (int i = 0; i < Cars.Length; i++) { buffer = Cars[DriverCar].Sounds.EmrBrake.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[i].Sounds.EmrBrake.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } // apply ApplyNotch(0, !Handles.SingleHandle, Handles.Brake.MaximumNotch, true); ApplyAirBrakeHandle(AirBrakeHandleState.Service); Handles.EmergencyBrake.Driver = true; Handles.HoldBrake.Driver = false; Specs.CurrentConstSpeed = false; if (Handles.EmergencyBrake.Driver) { switch (Handles.EmergencyBrake.OtherHandlesBehaviour) { case EbHandleBehaviour.PowerNeutral: if (!Handles.SingleHandle) { ApplyNotch(0, false, 0, true); } break; case EbHandleBehaviour.ReverserNeutral: ApplyReverser(0, false); break; case EbHandleBehaviour.PowerReverserNeutral: if (!Handles.SingleHandle) { ApplyNotch(0, false, 0, true); } ApplyReverser(0, false); break; } } // plugin if (Plugin == null) { return; } Plugin.UpdatePower(); Plugin.UpdateBrake(); }
/// <summary>Moves the air brake handle to the specified state</summary> /// <param name="State">The state</param> internal void ApplyLocoAirBrakeHandle(AirBrakeHandleState State) { if (Handles.LocoBrake is LocoAirBrakeHandle) { if ((int)State != Handles.LocoBrake.Driver) { // sound when moved to service if (State == AirBrakeHandleState.Service) { Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.Brake.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.Brake.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } // sound if ((int)State < (int)Handles.Brake.Driver) { // brake release if ((int)State > 0) { // brake release (not min) Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleRelease.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleRelease.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } else { // brake min Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleMin.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleMin.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } } else if ((int)State > (int)Handles.LocoBrake.Driver) { // brake Sounds.SoundBuffer buffer = Cars[DriverCar].Sounds.BrakeHandleApply.Buffer; if (buffer != null) { OpenBveApi.Math.Vector3 pos = Cars[DriverCar].Sounds.BrakeHandleApply.Position; Sounds.PlaySound(buffer, 1.0, 1.0, pos, this, DriverCar, false); } } // apply Handles.LocoBrake.Driver = (int)State; Handles.LocoBrake.Actual = (int)State; //TODO: FIXME Game.AddBlackBoxEntry(Game.BlackBoxEventToken.None); // plugin if (Plugin != null) { Plugin.UpdatePower(); Plugin.UpdateBrake(); } } } }
public void SetLightPosition(Vector3 LightPosition) { GL.Uniform3(UniformLayout.LightPosition, new OpenTK.Vector3((float)LightPosition.X, (float)LightPosition.Y, (float)LightPosition.Z)); }
public int CreateStaticObject(StaticObject Prototype, Transformation AuxTransformation, Matrix4D Rotate, Matrix4D Translate, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness) { if (Prototype == null) { return(-1); } float startingDistance = float.MaxValue; float endingDistance = float.MinValue; if (AccurateObjectDisposal) { foreach (VertexTemplate vertex in Prototype.Mesh.Vertices) { Vector3 Coordinates = new Vector3(vertex.Coordinates); Coordinates.Rotate(AuxTransformation); if (Coordinates.Z < startingDistance) { startingDistance = (float)Coordinates.Z; } if (Coordinates.Z > endingDistance) { endingDistance = (float)Coordinates.Z; } } startingDistance += (float)AccurateObjectDisposalZOffset; endingDistance += (float)AccurateObjectDisposalZOffset; } const double minBlockLength = 20.0; if (BlockLength < minBlockLength) { BlockLength *= Math.Ceiling(minBlockLength / BlockLength); } if (AccurateObjectDisposal) { startingDistance += (float)TrackPosition; endingDistance += (float)TrackPosition; double z = BlockLength * Math.Floor(TrackPosition / BlockLength); StartingDistance = Math.Min(z - BlockLength, startingDistance); EndingDistance = Math.Max(z + 2.0 * BlockLength, endingDistance); startingDistance = (float)(BlockLength * Math.Floor(StartingDistance / BlockLength)); endingDistance = (float)(BlockLength * Math.Ceiling(EndingDistance / BlockLength)); } else { startingDistance = (float)StartingDistance; endingDistance = (float)EndingDistance; } StaticObjectStates.Add(new ObjectState { Prototype = Prototype, Translation = Translate, Rotate = Rotate, Brightness = Brightness, StartingDistance = startingDistance, EndingDistance = endingDistance }); foreach (MeshFace face in Prototype.Mesh.Faces) { switch (face.Flags & MeshFace.FaceTypeMask) { case MeshFace.FaceTypeTriangles: InfoTotalTriangles++; break; case MeshFace.FaceTypeTriangleStrip: InfoTotalTriangleStrip++; break; case MeshFace.FaceTypeQuads: InfoTotalQuads++; break; case MeshFace.FaceTypeQuadStrip: InfoTotalQuadStrip++; break; case MeshFace.FaceTypePolygon: InfoTotalPolygon++; break; } } return(StaticObjectStates.Count - 1); }
internal ObjectGroup() { this.List = new ObjectList(); this.OpenGlDisplayList = 0; this.OpenGlDisplayListAvailable = false; this.WorldPosition = new Vector3(0.0, 0.0, 0.0); this.Update = true; }
// constructors /// <summary>Creates a new instance of this structure.</summary> /// <param name="segment">The physical track segment the point lies on.</param> /// <param name="position">The position.</param> /// <param name="orientation">The orientation, either with or without factoring in the Roll parameter.</param> /// <param name="orientationIncludesRoll">Whether the Orientation has the Roll parameter factored in.</param> /// <param name="roll">The roll expressed as an angle.</param> public SegmentPoint(PhysicalSegment segment, Math.Vector3 position, Math.Orientation3 orientation, bool orientationIncludesRoll, double roll) { this.Segment = segment; this.Position = position; if (orientationIncludesRoll) { this.OrientationWithRoll = orientation; this.OrientationWithoutRoll = Math.Orientation3.RotateAroundZAxis(orientation, System.Math.Cos(roll), -System.Math.Sin(roll)); } else { this.OrientationWithoutRoll = orientation; this.OrientationWithRoll = Math.Orientation3.RotateAroundZAxis(orientation, System.Math.Cos(roll), System.Math.Sin(roll)); } this.Roll = roll; }
/// <summary>Register the position to play microphone input.</summary> /// <param name="position">The position.</param> /// <param name="backwardTolerance">allowed tolerance in the backward direction</param> /// <param name="forwardTolerance">allowed tolerance in the forward direction</param> public virtual void PlayMicSound(OpenBveApi.Math.Vector3 position, double backwardTolerance, double forwardTolerance) { }
/// <summary>Draws a 3D cube</summary> /// <param name="Position">The position in world-space</param> /// <param name="Direction">The direction vector</param> /// <param name="Up">The up vector</param> /// <param name="Side">The side vector</param> /// <param name="Size">The size of the cube in M</param> /// <param name="Camera">The camera position</param> /// <param name="TextureIndex">The texture to apply</param> public void Draw(OpenBveApi.Math.Vector3 Position, OpenBveApi.Math.Vector3 Direction, OpenBveApi.Math.Vector3 Up, OpenBveApi.Math.Vector3 Side, double Size, OpenBveApi.Math.Vector3 Camera, Texture TextureIndex) { Draw(Position, Direction, Up, Side, new OpenBveApi.Math.Vector3(Size, Size, Size), Camera, TextureIndex); }
// render scene internal void RenderScene(double TimeElapsed) { ReleaseResources(); // initialize ResetOpenGlState(); if (OptionWireFrame) { if (Program.CurrentRoute.CurrentFog.Start < Program.CurrentRoute.CurrentFog.End) { const float fogDistance = 600.0f; float n = (fogDistance - Program.CurrentRoute.CurrentFog.Start) / (Program.CurrentRoute.CurrentFog.End - Program.CurrentRoute.CurrentFog.Start); float cr = n * inv255 * Program.CurrentRoute.CurrentFog.Color.R; float cg = n * inv255 * Program.CurrentRoute.CurrentFog.Color.G; float cb = n * inv255 * Program.CurrentRoute.CurrentFog.Color.B; GL.ClearColor(cr, cg, cb, 1.0f); } else { GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); } } GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // set up camera CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); TransformedLightPosition.Transform(CurrentViewMatrix); if (!AvailableNewRenderer) { GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)TransformedLightPosition.X, (float)TransformedLightPosition.Y, (float)TransformedLightPosition.Z, 0.0f }); } Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } // fog double fd = Program.CurrentRoute.NextFog.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition; if (fd != 0.0) { float fr = (float)((CameraTrackFollower.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition) / fd); float frc = 1.0f - fr; Program.CurrentRoute.CurrentFog.Start = Program.CurrentRoute.PreviousFog.Start * frc + Program.CurrentRoute.NextFog.Start * fr; Program.CurrentRoute.CurrentFog.End = Program.CurrentRoute.PreviousFog.End * frc + Program.CurrentRoute.NextFog.End * fr; Program.CurrentRoute.CurrentFog.Color.R = (byte)(Program.CurrentRoute.PreviousFog.Color.R * frc + Program.CurrentRoute.NextFog.Color.R * fr); Program.CurrentRoute.CurrentFog.Color.G = (byte)(Program.CurrentRoute.PreviousFog.Color.G * frc + Program.CurrentRoute.NextFog.Color.G * fr); Program.CurrentRoute.CurrentFog.Color.B = (byte)(Program.CurrentRoute.PreviousFog.Color.B * frc + Program.CurrentRoute.NextFog.Color.B * fr); if (!Program.CurrentRoute.CurrentFog.IsLinear) { Program.CurrentRoute.CurrentFog.Density = (byte)(Program.CurrentRoute.PreviousFog.Density * frc + Program.CurrentRoute.NextFog.Density * fr); } } else { Program.CurrentRoute.CurrentFog = Program.CurrentRoute.PreviousFog; } // render background GL.Disable(EnableCap.DepthTest); Program.CurrentRoute.UpdateBackground(TimeElapsed, false); if (OptionEvents) { RenderEvents(); } // fog float aa = Program.CurrentRoute.CurrentFog.Start; float bb = Program.CurrentRoute.CurrentFog.End; if (aa < bb & aa < Program.CurrentRoute.CurrentBackground.BackgroundImageDistance) { OptionFog = true; Fog.Start = aa; Fog.End = bb; Fog.Color = Program.CurrentRoute.CurrentFog.Color; Fog.Density = Program.CurrentRoute.CurrentFog.Density; Fog.IsLinear = Program.CurrentRoute.CurrentFog.IsLinear; Fog.SetForImmediateMode(); } else { OptionFog = false; } // world layer // opaque face if (AvailableNewRenderer) { //Setup the shader for rendering the scene DefaultShader.Activate(); if (OptionLighting) { DefaultShader.SetIsLight(true); DefaultShader.SetLightPosition(TransformedLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); DefaultShader.SetLightModel(Lighting.LightModel); } if (OptionFog) { DefaultShader.SetIsFog(true); DefaultShader.SetFog(Fog); } DefaultShader.SetTexture(0); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } ResetOpenGlState(); foreach (FaceState face in VisibleObjects.OpaqueFaces) { face.Draw(); } // alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.AlphaFaces) { face.Draw(); } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { face.Draw(); } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } face.Draw(); } else { if (additive) { SetAlphaFunc(); additive = false; } face.Draw(); } } } // render overlays if (AvailableNewRenderer) { DefaultShader.Deactivate(); } ResetOpenGlState(); OptionLighting = false; OptionFog = false; UnsetAlphaFunc(); GL.Disable(EnableCap.DepthTest); SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); //FIXME: Remove when text switches between two renderer types RenderOverlays(); OptionLighting = true; }
/// <summary>Draws a 3D cube</summary> /// <param name="Position">The position in world-space</param> /// <param name="Direction">The direction vector</param> /// <param name="Up">The up vector</param> /// <param name="Side">The side vector</param> /// <param name="Size">A 3D vector describing the size of the cube</param> /// <param name="Camera">The camera position</param> /// <param name="TextureIndex">The texture to apply</param> public void Draw(OpenBveApi.Math.Vector3 Position, OpenBveApi.Math.Vector3 Direction, OpenBveApi.Math.Vector3 Up, OpenBveApi.Math.Vector3 Side, OpenBveApi.Math.Vector3 Size, OpenBveApi.Math.Vector3 Camera, Texture TextureIndex) { Draw(defaultVAO, Position, Direction, Up, Side, Size, Camera, TextureIndex); }