public ObjectRenderer(MathboxRenderer mathboxRenderer) { Parent = mathboxRenderer; DisplayListManager = Parent.DisplayListManager; Memory = Parent.Memory; #if WIDESCREEN_STARS // load 123 stars from ROM starfield byte[] table = Parent.Machine.Mathbox.ROM[2]; for (int n = 0; n < 123; n++) { int addr = 0x3140 + n * 8; Int16 x = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2; Int16 y = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2; Int16 z = (Int16)(table[addr & 0x1FFF] * 256 + table[(addr + 1) & 0x1FFF]); addr += 2; Stars[n] = new Vector3(x, y, z); } // fill in the blanks with some more random stars PRNG r = new PRNG(0xDEAD); for (int n = 123; n < Stars.Length;) { const int size = 10000; double theta = 2 * Math.PI * r.NextDouble; double phi = Math.Acos(1 - 2 * r.NextDouble); double x = size * Math.Sin(phi) * Math.Cos(theta); double y = size * Math.Sin(phi) * Math.Sin(theta); double z = size * Math.Abs(Math.Cos(phi)); if (x < -3000 || x > 3500) { Vector3 v = new Vector3((float)x, (float)y, (float)z); v.Normalize(); v *= 10000; Stars[n++] = v; } } #endif }
MathboxRenderer(Machine machine, ScreenManager screenManager) { Machine = machine; Memory = Machine.Mathbox.Memory16; ScreenManager = screenManager; if (!(screenManager.Game is I_Robot.Game game)) { throw new Exception("VideoInterpreter can only be used with I_Robot.Game"); } Game = game; DisplayListManager = new DisplayList.Manager(this); Object = new ObjectRenderer(this); Terrain = new TerrainRenderer(this); // create our scene buffer // this buffer has a z-buffer SceneBuffer = new RenderTarget2D( Game.GraphicsDevice, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, false, Game.GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.None, 8, RenderTargetUsage.DiscardContents); // create our two screen buffers // these buffers do not require depth sorting, they are simply raw bitmaps // however the contents need to be preserved when rendering context is reset for (int n = 0; n < ScreenBuffers.Length; n++) { ScreenBuffers[n] = new RenderTarget2D( Game.GraphicsDevice, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, false, Game.GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); } camTarget = new Vector3(0f, 0f, 0f); camPosition = new Vector3(0f, 0f, -1f); double scaleToMonitor = Emulation.Machine.MonitorAspectRatio / Emulation.Machine.NativeAspectRatio; projectionMatrix = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45f), (float)(Game.GraphicsDevice.Viewport.AspectRatio / scaleToMonitor), 0.1f, 65536f); // it's important to move the projection matrix down a bit, this matches what I, Robot seems to do projectionMatrix = projectionMatrix * Matrix.CreateTranslation(new Vector3(0, -0.1f, 0)); viewMatrix = Matrix.CreateLookAt(camPosition, camTarget, Vector3.Up); worldMatrix = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Down); basicEffect = new BasicEffect(Game.GraphicsDevice); basicEffect.Alpha = 1f; basicEffect.VertexColorEnabled = true; // Want to see the colors of the vertices, this needs to be on // Lighting requires normal information which VertexPositionColor does not have // If you want to use lighting and VPC you need to create a custom def basicEffect.LightingEnabled = false; }
public TerrainRenderer(MathboxRenderer mathboxRenderer) { Parent = mathboxRenderer; Memory = Parent.Memory; DisplayListManager = Parent.DisplayListManager; }