public override byte[] Render(bool toRgbArray = false) { const int SCREEN_WIDTH = 600; const int SCREEN_HEIGHT = 400; float worldWidth = X_THRESHOLD * 2; float scale = SCREEN_WIDTH / worldWidth; float cartY = 100; // TOP OF CART float poleWidth = 10.0f; float poleLen = scale * (2 * LENGTH); float cartWidth = 50.0f; float cartHeight = 30.0f; if (Viewer == null) { Viewer = new Rendering.Viewer(SCREEN_WIDTH, SCREEN_HEIGHT); float l = -cartWidth / 2; float r = cartWidth / 2; float t = cartHeight / 2; float b = -cartHeight / 2; float axleOffset = cartHeight / 4.0f; var cart = new Rendering.FilledPolygon(new List <float[]> { new[] { l, b }, new[] { l, t }, new[] { r, t }, new[] { r, b } }); CartTrans = new Rendering.Transform(); cart.AddAttr(CartTrans); Viewer.AddGeom(cart); l = -poleWidth / 2; r = poleWidth / 2; t = poleLen - poleWidth / 2; b = -poleWidth / 2; Pole = new Rendering.FilledPolygon(new List <float[]> { new[] { l, b }, new[] { l, t }, new[] { r, t }, new[] { r, b } }); Pole.SetColor(.8f, .6f, .4f); PoleTrans = new Rendering.Transform(new[] { 0, axleOffset }); Pole.AddAttr(PoleTrans); Pole.AddAttr(CartTrans); Viewer.AddGeom(Pole); Axle = Rendering.MakeCircle(poleWidth / 2); Axle.AddAttr(PoleTrans); Axle.AddAttr(CartTrans); Axle.SetColor(.5f, .5f, .8f); Viewer.AddGeom(Axle); Track = new Rendering.Line(new [] { 0, cartY }, new [] { SCREEN_WIDTH, cartY }); Track.SetColor(0, 0, 0); Viewer.AddGeom(Track); } if (State == null) { return(null); } { // Edit the pole polygon vertex float l = -poleWidth / 2, r = poleWidth / 2, t = poleLen - poleWidth / 2, b = poleWidth / 2; Pole.Vertices = new List <float[]> { new[] { l, b }, new[] { l, t }, new[] { r, t }, new[] { r, b } }; } var cartX = State[0] * scale + SCREEN_WIDTH / 2.0f; // MIDDLE OF CART CartTrans.SetTranslation(cartX, cartY); PoleTrans.SetRotation(-State[2]); byte[] rgbArray = toRgbArray ? new byte[SCREEN_WIDTH * SCREEN_HEIGHT * 3] : null; Viewer.Render(rgbArray); return(rgbArray); }