Guest User

Space Engineers 3D Cube Example

a guest
Jan 4th, 2015
846
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.54 KB | None | 0 0
  1. //Simple 3D Cube rendering example - by CJay
  2. //For an example on how to set up the display for this, check out my other workshop submissions.
  3. ///////////////////////////
  4.  
  5. //tiny vector math library
  6. //I tried to use the VRageMath functions, but those seem to be broken in scripts
  7. //Instead I copied the parts I needed into here.
  8.  
  9. public struct Vector3 {
  10.     public float X;
  11.     public float Y;
  12.     public float Z;
  13.    
  14.     public Vector3(float x, float y, float z)
  15.     {
  16.         this.X = x;
  17.         this.Y = y;
  18.         this.Z = z;
  19.     }
  20.    
  21.     public static Vector3 operator +(Vector3 value1, Vector3 value2)
  22.     {
  23.         Vector3 result;
  24.         result.X = value1.X + value2.X;
  25.         result.Y = value1.Y + value2.Y;
  26.         result.Z = value1.Z + value2.Z;
  27.         return result;
  28.     }
  29.    
  30.     public static Vector3 operator -(Vector3 value1, Vector3 value2)
  31.     {
  32.         Vector3 result;
  33.         result.X = value1.X - value2.X;
  34.         result.Y = value1.Y - value2.Y;
  35.         result.Z = value1.Z - value2.Z;
  36.         return result;
  37.     }
  38.    
  39.     //tiny hack - this converts the vector from device space (-1 .. +1) to screen space ( 0 .. 31 )
  40.     public void Shift(float size) {
  41.         this.X = ((this.X + 1f) * 0.5f) * size;
  42.         this.Y = ((this.Y + 1f) * 0.5f) * size;
  43.         this.Z = ((this.Z + 1f) * 0.5f) * size;
  44.     }
  45.    
  46.     public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result)
  47.     {
  48.         float num = (float)((double)position.X * (double)matrix.M11 + (double)position.Y * (double)matrix.M21 + (double)position.Z * (double)matrix.M31) + matrix.M41;
  49.         float num2 = (float)((double)position.X * (double)matrix.M12 + (double)position.Y * (double)matrix.M22 + (double)position.Z * (double)matrix.M32) + matrix.M42;
  50.         float num3 = (float)((double)position.X * (double)matrix.M13 + (double)position.Y * (double)matrix.M23 + (double)position.Z * (double)matrix.M33) + matrix.M43;
  51.         float num4 = 1f / (position.X * matrix.M14 + position.Y * matrix.M24 + position.Z * matrix.M34 + matrix.M44);
  52.         result.X = num * num4;
  53.         result.Y = num2 * num4;
  54.         result.Z = num3 * num4;
  55.     }
  56. }
  57.  
  58. public struct Matrix {
  59.     public float M11; public float M12; public float M13; public float M14;
  60.     public float M21; public float M22; public float M23; public float M24;
  61.     public float M31; public float M32; public float M33; public float M34;
  62.     public float M41; public float M42; public float M43; public float M44;
  63.    
  64.     public static Matrix operator *(Matrix matrix1, Matrix matrix2)
  65.     {
  66.         Matrix result;
  67.         result.M11 = (float)((double)matrix1.M11 * (double)matrix2.M11 + (double)matrix1.M12 * (double)matrix2.M21 + (double)matrix1.M13 * (double)matrix2.M31 + (double)matrix1.M14 * (double)matrix2.M41);
  68.         result.M12 = (float)((double)matrix1.M11 * (double)matrix2.M12 + (double)matrix1.M12 * (double)matrix2.M22 + (double)matrix1.M13 * (double)matrix2.M32 + (double)matrix1.M14 * (double)matrix2.M42);
  69.         result.M13 = (float)((double)matrix1.M11 * (double)matrix2.M13 + (double)matrix1.M12 * (double)matrix2.M23 + (double)matrix1.M13 * (double)matrix2.M33 + (double)matrix1.M14 * (double)matrix2.M43);
  70.         result.M14 = (float)((double)matrix1.M11 * (double)matrix2.M14 + (double)matrix1.M12 * (double)matrix2.M24 + (double)matrix1.M13 * (double)matrix2.M34 + (double)matrix1.M14 * (double)matrix2.M44);
  71.         result.M21 = (float)((double)matrix1.M21 * (double)matrix2.M11 + (double)matrix1.M22 * (double)matrix2.M21 + (double)matrix1.M23 * (double)matrix2.M31 + (double)matrix1.M24 * (double)matrix2.M41);
  72.         result.M22 = (float)((double)matrix1.M21 * (double)matrix2.M12 + (double)matrix1.M22 * (double)matrix2.M22 + (double)matrix1.M23 * (double)matrix2.M32 + (double)matrix1.M24 * (double)matrix2.M42);
  73.         result.M23 = (float)((double)matrix1.M21 * (double)matrix2.M13 + (double)matrix1.M22 * (double)matrix2.M23 + (double)matrix1.M23 * (double)matrix2.M33 + (double)matrix1.M24 * (double)matrix2.M43);
  74.         result.M24 = (float)((double)matrix1.M21 * (double)matrix2.M14 + (double)matrix1.M22 * (double)matrix2.M24 + (double)matrix1.M23 * (double)matrix2.M34 + (double)matrix1.M24 * (double)matrix2.M44);
  75.         result.M31 = (float)((double)matrix1.M31 * (double)matrix2.M11 + (double)matrix1.M32 * (double)matrix2.M21 + (double)matrix1.M33 * (double)matrix2.M31 + (double)matrix1.M34 * (double)matrix2.M41);
  76.         result.M32 = (float)((double)matrix1.M31 * (double)matrix2.M12 + (double)matrix1.M32 * (double)matrix2.M22 + (double)matrix1.M33 * (double)matrix2.M32 + (double)matrix1.M34 * (double)matrix2.M42);
  77.         result.M33 = (float)((double)matrix1.M31 * (double)matrix2.M13 + (double)matrix1.M32 * (double)matrix2.M23 + (double)matrix1.M33 * (double)matrix2.M33 + (double)matrix1.M34 * (double)matrix2.M43);
  78.         result.M34 = (float)((double)matrix1.M31 * (double)matrix2.M14 + (double)matrix1.M32 * (double)matrix2.M24 + (double)matrix1.M33 * (double)matrix2.M34 + (double)matrix1.M34 * (double)matrix2.M44);
  79.         result.M41 = (float)((double)matrix1.M41 * (double)matrix2.M11 + (double)matrix1.M42 * (double)matrix2.M21 + (double)matrix1.M43 * (double)matrix2.M31 + (double)matrix1.M44 * (double)matrix2.M41);
  80.         result.M42 = (float)((double)matrix1.M41 * (double)matrix2.M12 + (double)matrix1.M42 * (double)matrix2.M22 + (double)matrix1.M43 * (double)matrix2.M32 + (double)matrix1.M44 * (double)matrix2.M42);
  81.         result.M43 = (float)((double)matrix1.M41 * (double)matrix2.M13 + (double)matrix1.M42 * (double)matrix2.M23 + (double)matrix1.M43 * (double)matrix2.M33 + (double)matrix1.M44 * (double)matrix2.M43);
  82.         result.M44 = (float)((double)matrix1.M41 * (double)matrix2.M14 + (double)matrix1.M42 * (double)matrix2.M24 + (double)matrix1.M43 * (double)matrix2.M34 + (double)matrix1.M44 * (double)matrix2.M44);
  83.         return result;
  84.     }
  85.    
  86.     public void CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
  87.     {
  88.         float num = 1f / (float)Math.Tan((double)fieldOfView * 0.5);
  89.         float m = num / aspectRatio;
  90.         this.M11 = m;
  91.         this.M12 = (this.M13 = (this.M14 = 0f));
  92.         this.M22 = num;
  93.         this.M21 = (this.M23 = (this.M24 = 0f));
  94.         this.M31 = (this.M32 = 0f);
  95.         this.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
  96.         this.M34 = -1f;
  97.         this.M41 = (this.M42 = (this.M44 = 0f));
  98.         this.M43 = (float)((double)nearPlaneDistance * (double)farPlaneDistance / ((double)nearPlaneDistance - (double)farPlaneDistance));
  99.     }
  100.    
  101.     public void CreateRotationX(float radians)
  102.     {
  103.         float num = (float)Math.Cos((double)radians);
  104.         float num2 = (float)Math.Sin((double)radians);
  105.         this.M11 = 1f;
  106.         this.M12 = 0f;
  107.         this.M13 = 0f;
  108.         this.M14 = 0f;
  109.         this.M21 = 0f;
  110.         this.M22 = num;
  111.         this.M23 = num2;
  112.         this.M24 = 0f;
  113.         this.M31 = 0f;
  114.         this.M32 = -num2;
  115.         this.M33 = num;
  116.         this.M34 = 0f;
  117.         this.M41 = 0f;
  118.         this.M42 = 0f;
  119.         this.M43 = 0f;
  120.         this.M44 = 1f;
  121.     }
  122.    
  123.     public void CreateRotationY(float radians)
  124.     {
  125.         float num = (float)Math.Cos((double)radians);
  126.         float num2 = (float)Math.Sin((double)radians);
  127.         this.M11 = num;
  128.         this.M12 = 0f;
  129.         this.M13 = -num2;
  130.         this.M14 = 0f;
  131.         this.M21 = 0f;
  132.         this.M22 = 1f;
  133.         this.M23 = 0f;
  134.         this.M24 = 0f;
  135.         this.M31 = num2;
  136.         this.M32 = 0f;
  137.         this.M33 = num;
  138.         this.M34 = 0f;
  139.         this.M41 = 0f;
  140.         this.M42 = 0f;
  141.         this.M43 = 0f;
  142.         this.M44 = 1f;
  143.     }
  144.    
  145.     public void CreateTranslation(float xPosition, float yPosition, float zPosition)
  146.     {
  147.         this.M11 = 1f;
  148.         this.M12 = 0f;
  149.         this.M13 = 0f;
  150.         this.M14 = 0f;
  151.         this.M21 = 0f;
  152.         this.M22 = 1f;
  153.         this.M23 = 0f;
  154.         this.M24 = 0f;
  155.         this.M31 = 0f;
  156.         this.M32 = 0f;
  157.         this.M33 = 1f;
  158.         this.M34 = 0f;
  159.         this.M41 = xPosition;
  160.         this.M42 = yPosition;
  161.         this.M43 = zPosition;
  162.         this.M44 = 1f;
  163.     }
  164. }
  165.  
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169.  
  170. //This class is what talks to the display
  171. public class DisplayController {
  172.     public int ResX, ResY;
  173.     Program prog;
  174.  
  175.     List<IMyTerminalBlock> lights;
  176.  
  177.     public DisplayController(int rx, int ry, Program p, List<IMyTerminalBlock> l) {
  178.         prog = p;
  179.         ResX = rx;
  180.         ResY = ry;
  181.         lights = l;
  182.     }
  183.  
  184.     public void Flush() {
  185.         for(int i = 0; i < lights.Count; i++) {
  186.             if (((IMyFunctionalBlock)lights[i]).Enabled) {
  187.                 lights[i].GetActionWithName("OnOff_Off").Apply(lights[i]);
  188.             }
  189.         }
  190.     }
  191.  
  192.     public void SetPixel(int x, int y, bool state) {
  193.         int number = x * ResY + y;
  194.  
  195.         /*
  196.         if (number < 0) {
  197.             throw new Exception("Pixel index below zero! (" + number);
  198.         }
  199.        
  200.         if (number >= (lights.Count - 1)) {
  201.             throw new Exception("Pixel index exceeds pixel count! (" + number + " , " + lights.Count);
  202.         }
  203.         */
  204.        
  205.         if ((number >= 0) && (number < lights.Count)) {
  206.             if (state) {
  207.                 lights[number].GetActionWithName("OnOff_On").Apply(lights[number]);
  208.             } else {
  209.                 lights[number].GetActionWithName("OnOff_Off").Apply(lights[number]);
  210.             }
  211.         }
  212.     }
  213. }
  214.  
  215. public class Renderer {
  216.     //I'd prefer to have every line as its own object - but it won't work for some reason
  217.     List<Vector3> startPoints = new List<Vector3>();
  218.     List<Vector3> endPoints = new List<Vector3>();
  219.    
  220.     Matrix mvp = new Matrix();
  221.     Matrix model = new Matrix();
  222.     Matrix view = new Matrix();
  223.     Matrix projection = new Matrix();
  224.    
  225.     public Vector3 campos = new Vector3(0f,  0f, 2.25f);
  226.    
  227.     public Renderer(DisplayController dc) {
  228.         //Prepare the projection matrix - this essentially sets the camera parameters
  229.         projection.CreatePerspectiveFieldOfView(
  230.             1.7f, //Field of view, in radians (1.7 is about 97°)
  231.             1f,   //Aspect ratio
  232.             0.1f, //Near clip, ie something 0.1 units away from the camera will be at Z position -1 in device space
  233.             100f  //Far clip,  ie something 100 units away from the camera will be at Z position +1 in device space
  234.         );
  235.         display = dc;
  236.     }
  237.  
  238.     public DisplayController display;
  239.  
  240.     //borrowed and butchered from http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm
  241.     private void Swap(ref int lhs, ref int rhs) { int temp; temp = lhs; lhs = rhs; rhs = temp; }
  242.    
  243.     public void Line(int x0, int y0, int x1, int y1, bool set) {
  244.         bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
  245.         if (steep) { Swap(ref x0, ref y0); Swap(ref x1, ref y1); }
  246.         if (x0 > x1) { Swap(ref x0, ref x1); Swap(ref y0, ref y1); }
  247.         int dX = (x1 - x0), dY = Math.Abs(y1 - y0), err = (dX / 2), ystep = (y0 < y1 ? 1 : -1), y = y0;
  248.  
  249.         for (int x = x0; x <= x1; ++x)
  250.         {
  251.             if (steep) {
  252.                 display.SetPixel(y, x, set);
  253.             } else {
  254.                 display.SetPixel(x, y, set);
  255.             }
  256.                
  257.             err = err - dY;
  258.             if (err < 0) { y += ystep;  err += dX; }
  259.         }
  260.     }
  261.    
  262.     public void AddLine(Vector3 start, Vector3 end) {
  263.         startPoints.Add(start);
  264.         endPoints.Add(end);
  265.     }
  266.    
  267.     public void PreProcess(float t) {
  268.         //This functions prepares the transformation matrix used during rendering.
  269.        
  270.         //First we make a temporary rotation matrix around the X axis
  271.         Matrix trot = new Matrix();
  272.         trot.CreateRotationX(t);
  273.        
  274.         //Then we set our model matrix to a rotation matrix around the Y axis
  275.         model.CreateRotationY(t);
  276.        
  277.         //Now we combine both into the model matrix. Now the model matrix rotates around both axis.
  278.         model = model * trot;
  279.        
  280.         //Now we create the view matrix from the camera position
  281.         view.CreateTranslation(campos.X, campos.Y, campos.Z);
  282.  
  283.         //Lastly we compute the Model-View-Projection (MVP) matrix.
  284.         //It combines the model position, view position and perspective distortion into one matrix.
  285.         mvp = model * view * projection;
  286.     }
  287.    
  288.     public void Render(bool set) {
  289.         //Iterate through every line
  290.         for (int i = 0; i < startPoints.Count; ++i) {
  291.             //These vectors will hold the transformed values later
  292.             Vector3 tr_s = new Vector3(0f, 0f, 0f);
  293.             Vector3 tr_e = new Vector3(0f, 0f, 0f);
  294.            
  295.             //Get the object-space coordinates
  296.             Vector3 s = startPoints[i];
  297.             Vector3 e = endPoints[i];
  298.            
  299.             //Apply the transformation matrix
  300.             Vector3.Transform(ref s, ref mvp, out tr_s);
  301.             Vector3.Transform(ref e, ref mvp, out tr_e);
  302.            
  303.             //shift it into screen space
  304.             tr_s.Shift(display.ResX);
  305.             tr_e.Shift(display.ResX);
  306.            
  307.             //Now draw the line!
  308.             try {
  309.                 Line(Convert.ToInt32(tr_s.X), Convert.ToInt32(tr_s.Y), Convert.ToInt32(tr_e.X), Convert.ToInt32(tr_e.Y), set);
  310.             } catch (Exception ex) {
  311.                 throw new Exception("error while drawing line");
  312.             }
  313.         }
  314.     }
  315. }
  316.  
  317. bool init = false;
  318. bool preprocess = true;
  319.  
  320. float t = 0.0f;
  321. DisplayController dc;
  322. Renderer renderer;
  323.  
  324. int DISP_WIDTH = 32;
  325. int DISP_HEIGHT = 32;
  326.  
  327. Vector3 cpos = new Vector3(0f, 0f, 2.25f);
  328.  
  329. void Main()
  330. {
  331.     if (!init) {
  332.         List<IMyTerminalBlock> l = new List<IMyTerminalBlock>();
  333.         GridTerminalSystem.GetBlocksOfType<IMyThrust>(l);
  334.         dc = new DisplayController(DISP_WIDTH, DISP_HEIGHT, this, l);
  335.         //dc.Flush();
  336.         renderer = new Renderer(dc);
  337.         init = true;
  338.        
  339.         //This defines all the corners of our cube.
  340.         Vector3 p1 = new Vector3(-1f, -1f, -1f);
  341.         Vector3 p2 = new Vector3( 1f, -1f, -1f);
  342.         Vector3 p3 = new Vector3(-1f, -1f,  1f);
  343.         Vector3 p4 = new Vector3( 1f, -1f,  1f);
  344.         Vector3 p5 = new Vector3(-1f,  1f, -1f);
  345.         Vector3 p6 = new Vector3( 1f,  1f, -1f);
  346.         Vector3 p7 = new Vector3(-1f,  1f,  1f);
  347.         Vector3 p8 = new Vector3( 1f,  1f,  1f);
  348.        
  349.         //Now we tell the renderer which points to connect with a line
  350.         renderer.AddLine(p1, p2);
  351.         renderer.AddLine(p3, p4);
  352.         renderer.AddLine(p5, p6);
  353.         renderer.AddLine(p7, p8);
  354.        
  355.         renderer.AddLine(p1, p3);
  356.         renderer.AddLine(p2, p4);
  357.         renderer.AddLine(p5, p7);
  358.         renderer.AddLine(p6, p8);
  359.        
  360.         renderer.AddLine(p1, p5);
  361.         renderer.AddLine(p2, p6);
  362.         renderer.AddLine(p3, p7);
  363.         renderer.AddLine(p4, p8);
  364.     }
  365.    
  366.     //I was hitting the performance limit for scripts - so I split the matrix computation into an extra pass.
  367.     if (preprocess) {
  368.         renderer.PreProcess(t);
  369.     } else {
  370.         dc.Flush();
  371.         renderer.Render(true);
  372.         t += 0.05f;
  373.     }
  374.    
  375.     preprocess = !preprocess;
  376. }
Advertisement
Add Comment
Please, Sign In to add comment