Results 1 to 18 of 18

Thread: Drawing 3D Objects in SCAR

  1. #1
    Join Date
    Jan 2007
    Location
    Tennessee
    Posts
    642
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default Drawing 3D Objects in SCAR

    MOD EDIT: Please note that although this tutorial was designed for SCAR, it still applies to Simba. However, you will need to use Simba's alternative debug form canvas drawing methods. Please refer to the Simba documentation as-well as the internal function list.

    This tutorial is on how to make a 3 dimensional point [x, y, z] into a 2 dimensional point [x, y] and rotate it around a given point if needed so that it can be shown on a screen.
    I decided to do this because I searched for days, here and on any other sites I could find, for a tutorial on doing this with not a single result.
    And I wanted to start making 3d SCAR games




    Introduction
    You have to make your 3d points into 2d points because the pixels on your screen are obviously 2 dimensional.
    I think everyone knows about x and y.
    It is left and right, up and down.
    If you don't know what the 3rd dimension, z, is I will try to explain it.
    It is sort of like how far away the point is from you.
    Z can't be mistaken for distance though, because z is independent of the x and y values.
    If you have the point [0, 0, 10], it is a point that has the same x and y values as the viewer, but is 10 pixels in front of the viewer.
    So the distance between you and the pixel is 10.
    Now if you have the point [10, 0, 10], the z has stayed the same but the distance form you to the point has increased to 14 because it has moved 10 pixels to the right.




    Starting your script
    To begin making your script, you will need some new types to add to SCAR so you can make things 3D.
    You will also need a TCanvas to draw your cube on.
    Finally, you need the start of your main procedure to draw the cube and the variables it uses.
    Put the following in your SCAR
    SCAR Code:
    type T3DPoint = record
      x, y, z: integer;
    end;

    type T3DPointArray = array of T3DPoint;
     
    var
      Canvas: TCanvas;


    procedure DrawBox(sx, sy, sz, vx, vy, vz, Height, Width, Depth, xRot, yRot, zRot: integer);
    var
      _2DPoints: TPointArray;
      _3DPoints: T3DPointArray;
      mx, my, mz, i: integer;
      NewPoint: TPoint;
    begin
    end;





    Making the first part of your cube
    Now let's start off with drawing a 2d box. (more like a square)
    You simply take 4 points and draw a line connecting them.
    The first point you will have is the main point, the top left pixel in the box.
    Let's say it is [50, 50, 100] (we will call this [sx, sy, sz])
    We want the box to be 50 x 50 x 50. (we will call this height, width, and depth)

    The next 3 points in the box can be made like this-
    2nd point (top right corner)- [sx + Width, sy, sz]
    3rd point (bottom right corner)- [sx + width, sy + height, sz]
    4th point (bottom left corner)- [x, y + height, sz]

    Let's add this inside the procedure DrawBox-
    SCAR Code:
    SetArrayLength(_3DPoints, 4);
      with _3DPoints[0] do
      begin
        x:= sx;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[1] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[2] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz;
      end;
      with _3DPoints[3] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz;
      end;

    If you draw a line from the 1st to the 2nd to the 3rd to the 4th then back to the 1st and you have the square you wanted.
    Here is a procedure to draw a line from one point to another, add it into your script.
    SCAR Code:
    procedure Line(Point, Point2: TPoint);
    begin
      Canvas.MoveTo(Point.x, Point.y);
      Canvas.LineTo(Point2.x, Point2.y);
    end;
    -







    Making your 3D points 2D
    You have your points all set, but to test out to see if you have made a square you will need to turn your 3D points into 2D points to draw them.
    Use this function to do it-
    SCAR Code:
    function Turn3DTo2D(x, y, z, vx, vy, vz: integer) : TPoint;
    begin
      if (z - vz) < 1 then
      begin
        Result.x:= 0;
        Result.y:= 0;
        Exit;
      end;
      Result.x:= (x - vx) * 256 / (z - vz);
      Result.y:= (y - vy) * 256 / (z - vz);
    end;
    [vx, vy, vz] is the view point, or where your eyes are in the 3d world.
    I will try to explain how this works.
    SCAR Code:
    if (z - vz) < 1 then
      begin
        Result.x:= 0;
        Result.y:= 0;
        Exit;
      end;
    If the z value of the pixel is less than your own z value, the pixel is behind you so it can't even be seen.
    This also makes the script unable to divide by 0 (bad)
    So this part makes the result 0 and exits.
    SCAR Code:
    Result.x:= (x - vx) * 256 / (z - vz);
      Result.y:= (y - vy) * 256 / (z - vz);
    This is how you come up with your result.
    As the vx increases (you move to the right) the x decreases (the object moves to the left)
    Think about it, if you looked at something and you start moving directly to the right, it will
    start moving to the left to you.
    The same with the y values.
    If you are looking ahead at something and climb down a ladder (increasing the vy) the y value of what you are looking at will increase (it will be moving up)
    The same exact thing with z, I won't explain this one too.
    Now that you have the right x y and z values after considering where you are standing, you need to turn them into [x, y]
    We know that the higher the z value the further away the object.
    So as z increases the other values decrease, right?
    Sounds like division to me.
    You divide the x by the z for the final x and divide the y by the z for the final y.
    The higher the number you use to divide a number, the smaller result you will get.
    So it works perfect.
    There is one thing you actually need to do before this though, but I've never been sure how
    to explain it, the multiply by 256 part.
    There is no given number for this, it is used for scaling.
    256 is just the number I use.
    If you don't multiply, your results will be extremely small.
    The higher scaling number you multiply with the larger your objects will be.
    I'm not sure if there is a "right" one.





    Back to making the first part of your cube
    Now set the array length of your 2D points array to 4, and then set the 2D array using the Turn3DTo2D function.
    Then draw the lines that connect the box.
    To do that, add this to the end of DrawBox.
    SCAR Code:
    SetArrayLength(_2DPoints, 4);
      for i:= 0 to 3 do
      _2DPoints[i]:= Turn3DTo2D(_3DPoints[i].x, _3DPoints[i].y, _3DPoints[i].z, vx, vy, vz);
      Line(_2DPoints[0], _2DPoints[1]);
      Line(_2DPoints[1], _2DPoints[2]);
      Line(_2DPoints[2], _2DPoints[3]);
      Line(_2DPoints[3], _2DPoints[0]);

    Now at the end of your script you need to set up your canvas and call for the procedure DrawBox.
    You only need to fill out the arguments in DrawBox that we have covered so far.
    SCAR Code:
    begin
      Canvas:= GetDebugCanvas;
      DisplayDebugImgWindow(500, 500);
      Canvas.Pen.Color:= ClWhite;
      Canvas.Brush.Color:= 0;
      Canvas.Rectangle(-1, -1, 501, 501);
      DrawBox(50, 50, 100, 0, 0, 0, 50, 50, 50, 0, 0, 0);
    end.

    You should now have all of this now, run it and you should have a square-
    SCAR Code:
    type T3DPoint = record
      x, y, z: integer;
    end;

    type T3DPointArray = array of T3DPoint;

    var
      Canvas: TCanvas;


    procedure Line(Point, Point2: TPoint);
    begin
      Canvas.MoveTo(Point.x, Point.y);
      Canvas.LineTo(Point2.x, Point2.y);
    end;




    function Turn3DTo2D(x, y, z, vx, vy, vz: integer) : TPoint;
    begin
      if (z - vz) < 1 then
      begin
        Result.x:= 0;
        Result.y:= 0;
        Exit;
      end;
      Result.x:= (x - vx) * 256 / (z - vz);
      Result.y:= (y - vy) * 256 / (z - vz);
    end;





    procedure DrawBox(sx, sy, sz, vx, vy, vz, Height, Width, Depth, xRot, yRot, zRot: integer);
    var
      _2DPoints: TPointArray;
      _3DPoints: T3DPointArray;
      mx, my, mz, i: integer;
      NewPoint: TPoint;
    begin
      SetArrayLength(_3DPoints, 4);
      with _3DPoints[0] do
      begin
        x:= sx;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[1] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[2] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz;
      end;
      with _3DPoints[3] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz;
      end;
      SetArrayLength(_2DPoints, 4);
      for i:= 0 to 3 do
      _2DPoints[i]:= Turn3DTo2D(_3DPoints[i].x, _3DPoints[i].y, _3DPoints[i].z, vx, vy, vz);
      Line(_2DPoints[0], _2DPoints[1]);
      Line(_2DPoints[1], _2DPoints[2]);
      Line(_2DPoints[2], _2DPoints[3]);
      Line(_2DPoints[3], _2DPoints[0]);
    end;




    begin
      Canvas:= GetDebugCanvas;
      DisplayDebugImgWindow(500, 500);
      Canvas.Pen.Color:= ClWhite;
      Canvas.Brush.Color:= 0;
      Canvas.Rectangle(-1, -1, 501, 501);
      DrawBox(50, 50, 100, 0, 0, 0, 50, 50, 50, 0, 0, 0);
    end.
    -






    Making the 2nd part of your cube
    So far we still have a 2D object, but we want a 3D object.
    If you have ever drawn a cube on paper, I do it just like that.
    Draw two boxes and connect their corresponding vertices and you have a cube.
    So that means we need to make a 2nd box the same way we made the first.


    For our 2nd box we need to draw, it will have all the same x and y values of the first.
    That part is easy, that is just how cubes are shaped.
    But if we leave the z value the same too, we will draw out just two squares on top of each other perfectly and it will still be 2d.
    This is where the depth of your cube comes in.
    Our cube is going to have a depth of 50 pixels.
    So now we make our 2nd square 50 pixels behind the first one by adding on to it's z-
    The first point will be [50, 50, 100 + Depth], and do the same with the other 3 points.
    Set the array length of _3DPoints from 4 to 8, because there are 8 points we will deal with now.
    Then underneath where you set up your first 4 3D points add in the set up for the next 4-
    SCAR Code:
    with _3DPoints[4] do
      begin
        x:= sx;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[5] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[6] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz + Depth;
      end;
      with _3DPoints[7] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz + Depth;
      end;

    To test out your 2nd square do just like what we did with the first one.
    Change the array length of _2DPoints from 4 to 8.
    Then change your for loop from 3 to 7-
    SCAR Code:
    for i:= 0 to 7 do
      _2DPoints[i]:= Turn3DTo2D(_3DPoints[i].x, _3DPoints[i].y, _3DPoints[i].z, vx, vy, vz);
    Then tell DrawBox to draw the lines for the 2nd box.
    Add this in underneath where you put the first Line() procedures in DrawBox-
    SCAR Code:
    Line(_2DPoints[4], _2DPoints[5]);
      Line(_2DPoints[5], _2DPoints[6]);
      Line(_2DPoints[6], _2DPoints[7]);
      Line(_2DPoints[7], _2DPoints[4]);
    Run your script now and you should have 2 squares drawn.







    Making your 2 squares into a CUBE
    So now we still have just two squares, but at least they aren't in the exact same spot.
    Still not 3d yet eh?
    Remember what I said about you have to connect the vertices? (the corners of the cube)
    Just draw in 4 more lines.
    Connect the first point of the first square to the first point of the 2nd square and so on.
    Add this at the end of DrawBox.
    You don't need to set any array lengths this time, because we aren't adding new points, just dealing with the previous ones.
    SCAR Code:
    Line(_2DPoints[0], _2DPoints[4]);
      Line(_2DPoints[1], _2DPoints[5]);
      Line(_2DPoints[2], _2DPoints[6]);
      Line(_2DPoints[3], _2DPoints[7]);

    So here is what you should have for your script now-
    SCAR Code:
    type T3DPoint = record
      x, y, z: integer;
    end;

    type T3DPointArray = array of T3DPoint;

    var
      Canvas: TCanvas;


    procedure Line(Point, Point2: TPoint);
    begin
      Canvas.MoveTo(Point.x, Point.y);
      Canvas.LineTo(Point2.x, Point2.y);
    end;




    function Turn3DTo2D(x, y, z, vx, vy, vz: integer) : TPoint;
    begin
      if (z - vz) < 1 then
      begin
        Result.x:= 0;
        Result.y:= 0;
        Exit;
      end;
      Result.x:= (x - vx) * 256 / (z - vz);
      Result.y:= (y - vy) * 256 / (z - vz);
    end;





    procedure DrawBox(sx, sy, sz, vx, vy, vz, Height, Width, Depth, xRot, yRot, zRot: integer);
    var
      _2DPoints: TPointArray;
      _3DPoints: T3DPointArray;
      mx, my, mz, i: integer;
      NewPoint: TPoint;
    begin
      SetArrayLength(_3DPoints, 8);
      with _3DPoints[0] do
      begin
        x:= sx;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[1] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[2] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz;
      end;
      with _3DPoints[3] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz;
      end;
      with _3DPoints[4] do
      begin
        x:= sx;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[5] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[6] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz + Depth;
      end;
      with _3DPoints[7] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz + Depth;
      end;
      SetArrayLength(_2DPoints, 8);
      for i:= 0 to 7 do
      _2DPoints[i]:= Turn3DTo2D(_3DPoints[i].x, _3DPoints[i].y, _3DPoints[i].z, vx, vy, vz);
      Line(_2DPoints[0], _2DPoints[1]);
      Line(_2DPoints[1], _2DPoints[2]);
      Line(_2DPoints[2], _2DPoints[3]);
      Line(_2DPoints[3], _2DPoints[0]);
      Line(_2DPoints[4], _2DPoints[5]);
      Line(_2DPoints[5], _2DPoints[6]);
      Line(_2DPoints[6], _2DPoints[7]);
      Line(_2DPoints[7], _2DPoints[4]);
      Line(_2DPoints[0], _2DPoints[4]);
      Line(_2DPoints[1], _2DPoints[5]);
      Line(_2DPoints[2], _2DPoints[6]);
      Line(_2DPoints[3], _2DPoints[7]);
    end;




    begin
      Canvas:= GetDebugCanvas;
      DisplayDebugImgWindow(500, 500);
      Canvas.Pen.Color:= ClWhite;
      Canvas.Brush.Color:= 0;
      Canvas.Rectangle(-1, -1, 501, 501);
      DrawBox(50, 50, 100, 0, 0, 0, 50, 50, 50, 0, 0, 0);
    end.
    If you have that, then congratulations, you have just drawn yourself a 3D cube!






    3D Rotation
    The next part of the tutorial gets a little bit tricky, this is what took me a while to figure out.
    What if you want your cube to rotate?
    Or what if you want your view to not be looking perfectly straight, maybe you are looking 45 degrees to the left of the cube? It will look different then.
    To accomplish either of these, the points in your cube have to be rotated around a certain point.


    For rotating the cube, the points will rotate around the very center point of the cube. [mx, my, mz]

    For you turning your head, the points of the cube will rotate around you [vx, vy, vz]

    So we need a way of rotating 3d points around a 3d point.
    When something rotates, as long as it is on a single axis, there is some reference point where only 2 of it's 3 values are changing. (maybe x and y, maybe y and z, etc)
    2 points changing? That means we can use something like [x, y] rather than [x, y, z]





    Axis rotations
    There is x, y, and z axis rotation.
    You can combine them to get other rotations, but they are derived from these 3.
    Here is how you figure out what kind of rotation it is.
    When your object rotates, whatever direction it is, there are center points that don't change, the object is rotating around the set of points.
    If you were to connect all of these stationary points, it would make a straight line.
    If the line is going left and right it is x axis, if the line is up and down it is y axis, if the line is going straight or backwards it is z axis.
    (sorry, I just realized in my 3d cube drawer I messed up which is which, but it will still work fine)







    2D Rotation
    With rotating a point around a given point, a lot of people know how to do this in 2 dimensions.
    Put these functions into your script, you will see later how we will still need to use them.
    SCAR Code:
    function GetAngle(x, y, x2, y2: integer): Extended;
    begin
      Result:= (ArcTan2(y2 - y, x2 - x) * (180 / Pi)) + 90;
      if Result < 0.0 then
      Result:= Result + 360.0;
    end;




    function RotateP(x, y, x2, y2, Angle: integer): TPoint;
    var
      r: integer;
      Ang: Extended;
    begin
      r:= Distance(x, y, x2, y2);
      Ang:= GetAngle(x2, y2, x, y) + Angle;
      Result.x:= Round(Sin(Ang * Pi / 180) * r + x2);
      Result.y:= Round(Cos(Ang * Pi / 180) * -r + y2);
    end;
    I will explain this a little, but it is trigonometry which I have never taken, so it is kinda complicated.
    You need the distances, r, between the two points.
    You need the angle of the two points, GetAngle().
    The next part is very hard to explain, but it has to do with triangle sides lengths and circles, and basically just know that that is how you find a point with a given distance and angle from another point.

    If only 2 of the values of our object are changing, we can plug those values into this, even though it is for 2d points, and get the right answers if we plug in the right values.
    When you rotate a point in 2d it is the equivilant of x axis rotation in 3d.
    So x axis rotation is pretty simple, you rotate the the y and z values around the cube's middle y and z values.
    We know the cube's y and z values, because we made them, but what will the center point be, so we know what we are rotating around?







    Midpoints of 3D rotation
    This part is pretty easy.
    The middle x value is the average between the maximum and the minimum x values of the object.
    mx:= ((MaxX + MinX) / 2);
    The same with y and z.
    my:= ((MaxY + MinY) / 2);
    mz:= ((MaxZ + MinZ) / 2);
    So add this somewhere in your DrawBox procedure-
    SCAR Code:
    mz:= (sz + sz + Depth) / 2;
      mx:= _3DPoints[0].x + (Width / 2);
      my:= _3DPoints[0].y + (Height / 2);
    -







    Back to 3D point rotation
    Now that you have all the info you need, you can rotate your points using RotateP();
    For the x axis rotation you will use RotateP(y, z, my, mz, xRot); (xRot is just how much to rotate it, 180 flips it, 360 fully rotates it back around to where it was)
    Add this underneath where you set [mx, my, mz] and before you set your 2D point array, or it won't rotate the cube-
    SCAR Code:
    for i:= 0 to 7 do
      begin
        NewPoint:= RotateP(_3DPoints[i].y, _3DPoints[i].z, my, mz, xRot);
        _3DPoints[i].y:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
      end;

    Now we have the x axis rotation taken care of, but we also want y and z axis.
    If your object is rotating in reference to your eyes around the y axis, someone else could be standing in another spot, looking at the same object, but see it rotating around the x axis.
    We need to sort of change our view point temporarily so we can really do the same thing we did with x axis rotation to get y axis rotation.
    If you think about it hard enough, and your brain doesn't explode/ melt, you can figure out that y axis rotation will be using the x and z values of the object.
    So just like I said, do the same thing for the x axis but this time you are standing in a different spot, where y axis rotation has turned into x axis rotation.
    So you will use RotateP(x, z, mx, mz, yRot);
    Now where you put that last section of code, add on to the end of it to make it look like this-
    SCAR Code:
    for i:= 0 to 7 do
      begin
        NewPoint:= RotateP(_3DPoints[i].y, _3DPoints[i].z, my, mz, xRot);
        _3DPoints[i].y:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
        NewPoint:= RotateP(_3DPoints[i].x, _3DPoints[i].z, mx, mz, yRot);
        _3DPoints[i].x:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
      end;

    Now for the last one, z axis rotation.
    Not any harder than the first two.
    Again, think about it without your eyes popping out of your head, and you will come up with x and y values as the values used for z axis rotation.
    If you didn't guess already, here's how it is done-
    RotateP(x, y, mx, my, zRot);
    Now in that last section of code again, add your final axis rotation to make it look like this-
    SCAR Code:
    for i:= 0 to 7 do
      begin
        NewPoint:= RotateP(_3DPoints[i].y, _3DPoints[i].z, my, mz, xRot);
        _3DPoints[i].y:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
        NewPoint:= RotateP(_3DPoints[i].x, _3DPoints[i].z, mx, mz, yRot);
        _3DPoints[i].x:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
        NewPoint:= RotateP(_3DPoints[i].x, _3DPoints[i].y, mx, my, zRot);
        _3DPoints[i].x:= NewPoint.x;
        _3DPoints[i].y:= NewPoint.y;
      end;

    So I just explained a very large complicated way of saying that for whatever axis you want to rotate, you use the other two values. (but that is just too easy to say, and doesn't tell you WHY it is like that)
    (x axis = y and z), (y axis = x and z), (z axis = x and y)

    You should now be done making your 3D cube and it should be fully able to rotate!
    Here is the final script (with added comments to make it easier to understand)
    SCAR Code:
    program New;

    type T3DPoint = record
      x, y, z: integer;
    end;

    type T3DPointArray = array of T3DPoint;
     
    var
      Canvas: TCanvas;



    function Turn3DTo2D(x, y, z, vx, vy, vz: integer) : TPoint;
    begin
      if (z - vz) < 1 then
      begin
        Result.x:= 0;
        Result.y:= 0;
        Exit;
      end;
      Result.x:= (x - vx) * 256 / (z - vz);
      Result.y:= (y - vy) * 256 / (z - vz);
    end;




    procedure Line(Point, Point2: TPoint);
    begin
      Canvas.MoveTo(Point.x, Point.y);
      Canvas.LineTo(Point2.x, Point2.y);
    end;




    function GetAngle(x, y, x2, y2: integer): Extended;
    begin
      Result:= (ArcTan2(y2 - y, x2 - x) * (180 / Pi)) + 90;
      if Result < 0.0 then
      Result:= Result + 360.0;
    end;




    function RotateP(x, y, x2, y2, Angle: integer): TPoint;
    var
      r: integer;
      Ang: Extended;
    begin
      r:= Distance(x, y, x2, y2);
      Ang:= GetAngle(x2, y2, x, y) + Angle;
      Result.x:= Round(Sin(Ang * Pi / 180) * r + x2);
      Result.y:= Round(Cos(Ang * Pi / 180) * -r + y2);
    end;





    procedure DrawBox(sx, sy, sz, vx, vy, vz, Height, Width, Depth, xRot, yRot, zRot: integer);
    var
      _2DPoints: TPointArray;
      _3DPoints: T3DPointArray;
      mx, my, mz, i: integer;
      NewPoint: TPoint;
    begin
    //clear the canvas
      Canvas.Rectangle(-1, -1, 501, 501);

    //setting the length of the arrays
      SetArrayLength(_2DPoints, 8);
      SetArrayLength(_3DPoints, 8);
     
    //first square
      with _3DPoints[0] do
      begin
        x:= sx;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[1] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz;
      end;
      with _3DPoints[2] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz;
      end;
      with _3DPoints[3] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz;
      end;

    //2nd square
      with _3DPoints[4] do
      begin
        x:= sx;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[5] do
      begin
        x:= sx + Width;
        y:= sy;
        z:= sz + Depth;
      end;
      with _3DPoints[6] do
      begin
        x:= sx + Width;
        y:= sy + Height;
        z:= sz + Depth;
      end;
      with _3DPoints[7] do
      begin
        x:= sx;
        y:= sy + Height;
        z:= sz + Depth;
      end;
     
    //finding the middle of our cube
      mz:= (sz + sz + Depth) / 2;
      mx:= _3DPoints[0].x + (Width / 2);
      my:= _3DPoints[0].y + (Height / 2);
     
    //rotating the cube
      for i:= 0 to 7 do
      begin
        //x axis rotation
        NewPoint:= RotateP(_3DPoints[i].y, _3DPoints[i].z, my, mz, xRot);
        _3DPoints[i].y:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
        //y axis rotation
        NewPoint:= RotateP(_3DPoints[i].x, _3DPoints[i].z, mx, mz, yRot);
        _3DPoints[i].x:= NewPoint.x;
        _3DPoints[i].z:= NewPoint.y;
        //z axis rotation
        NewPoint:= RotateP(_3DPoints[i].x, _3DPoints[i].y, mx, my, zRot);
        _3DPoints[i].x:= NewPoint.x;
        _3DPoints[i].y:= NewPoint.y;
      end;
     
    //setting the 2d points
      for i:= 0 to 7 do
      _2DPoints[i]:= Turn3DTo2D(_3DPoints[i].x, _3DPoints[i].y, _3DPoints[i].z, vx, vy, vz);

    //drawing on the canvas
    //first square
      Line(_2DPoints[0], _2DPoints[1]);
      Line(_2DPoints[1], _2DPoints[2]);
      Line( _2DPoints[2], _2DPoints[3]);
      Line( _2DPoints[3], _2DPoints[0]);
     
    //2nd square
      Line(_2DPoints[4], _2DPoints[5]);
      Line(_2DPoints[5], _2DPoints[6]);
      Line(_2DPoints[6], _2DPoints[7]);
      Line(_2DPoints[7], _2DPoints[4]);
     
    //connecting vertices
      Line(_2DPoints[0], _2DPoints[4]);
      Line(_2DPoints[1], _2DPoints[5]);
      Line(_2DPoints[2], _2DPoints[6]);
      Line(_2DPoints[3], _2DPoints[7]);
    end;




     
    begin
      Canvas:= GetDebugCanvas;
      DisplayDebugImgWindow(500, 500);
      Canvas.Pen.Color:= ClWhite;
      Canvas.Brush.Color:= 0;
      Canvas.Rectangle(-1, -1, 501, 501);
     
      DrawBox(
      {x, y, z}    50, 50, 100,
      {vx, vy, vz} 0, 0, 0,
      {h, w, d}    50, 50, 50,
      {xr, yr, zr} 0, 0, 0
      );
      { /\ that is the same as DrawBox(50, 50, 100, 0, 0, 0, 50, 50, 50, 0, 0, 0);
      just put in an easier to adjust view}

    end.
    To rotate your cube just change the last 3 arguments around where you call for DrawBox.






    View rotation
    This isn't included in my 3D cube drawer script, but I will still go over how to do it and it wouldn't be too hard to put it in.
    If you got that part down, rotating your view point will be the same thing, but even easier really.
    "Turning your view point" can also be shown as all the points drawn just rotating around YOU.
    If you look to your left, who is to say that evreything in the universe didn't just rotate to the rigth, except for your head?
    You can't really PROVE that didn't happen, because it would look exactly the same either way.
    So that is how we are going to do it.
    Let's assume this is really what happens.
    When you turn your head to the left and "the universe rotates around you to the right", think about what values are changing.
    The objects around you will move either left of right.
    They will also either move forwards or backwards.
    But will their height change? Nope, they didn't get any higher off the ground than they were before (this is all in reference to the viewer).
    Their x and z values will be rotating.
    So to rotate your object around you use the same RotateP(); function-
    RotateP(x, z, vx, vz, TurnRot);
    Again, hopefully I made you think, instead of just saying "use y axis rotation around your point"
    Remember when I said if you connect the points that aren't changing it will show you what axis is rotating?
    The y values are staying the same, so our line will be going up and down, so it is y axis.




    And that concludes my tutorial on 3d object drawing.
    I will be adding things to this as I think of them, because I'm sure I left something out
    in such a big tut.
    Any questions? Feel free to ask me here.

    Keep a look out for my next tut on light in 3d space and how it will effect the color of
    an object at varying distances and angles from the object.
    It will use a lot of this stuff.
    (I haven't been able to figure out a way of scripting this using SCAR yet though)
    Last edited by Daniel; 08-10-2012 at 10:14 AM.

  2. #2
    Join Date
    Sep 2006
    Location
    include srl/srl.scar ( aussie)
    Posts
    2,875
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    good tut, i recomend you paraghaph it a bit more as some people have a hard time read big chunks of writing that that.

  3. #3
    Join Date
    Jul 2008
    Location
    Canada
    Posts
    1,612
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    yea proper indenting would be easier to read.

  4. #4
    Join Date
    Mar 2007
    Posts
    1,700
    Mentioned
    0 Post(s)
    Quoted
    8 Post(s)

    Default

    Maybe format it into sections? And split it into paragraphs please. Maybe pics too? Or perhaps script to sum together what was learned. If you really wanted to make it a great tutorial, you could walk the reader through making a script involving all of the above.

  5. #5
    Join Date
    Jan 2007
    Location
    Tennessee
    Posts
    642
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    If you really wanted to make it a great tutorial, you could walk the reader through making a script involving all of the above.
    Very good idea.
    I just read through it for the first time (yes I read it AFTER I posted it )
    and it is pretty hard to follow.
    I'll break it off into sections and have code examples for each section to show you where you should be with making one of your own.

  6. #6
    Join Date
    Jan 2007
    Posts
    8,876
    Mentioned
    123 Post(s)
    Quoted
    327 Post(s)

    Default

    Wow, thanks for posting this, almost
    Geat work!
    I really want to work with you on the 3D game project!

  7. #7
    Join Date
    Jan 2007
    Location
    Tennessee
    Posts
    642
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    Hey thanks!
    We should make it together, and have the most awesome game SCAR has ever seen.

    To everyone else who posted-
    Is this new format something like what you guys were talking about?
    I took about 2-3 hours re-writing just about the whole tut.

  8. #8
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    well i tried making a 4 sided pyramid, and it seemed to work except the center of rotation was all off. So from what i can see if you were to just make a shape that looked like rooms, then you could navigate yourself through it like and fps.

    A problem i did see in 3D Game v.2 when you were inside the object it make that kind of shape between the center of the screen and the box. Im guessing thats not supposed to be there, but once thats fixed, then all thats really needed is some collision detection. Then you can just add some "enemies" that can be destroyed by "bullets" and you have an fps.

    Once thats working, some relatively simple (for its kind) procedural generation should make it an actually playable type game.
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  9. #9
    Join Date
    Jan 2007
    Location
    Tennessee
    Posts
    642
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    well i tried making a 4 sided pyramid, and it seemed to work except the center of rotation was all off.
    Setting your [mx, my, mz] will be totally different than how I did it with a cube.
    Look at the part where I explain how to find the middle point.
    You will have to take the average of the max and min values of your object.

    A problem i did see in 3D Game v.2 when you were inside the object it make that kind of shape between the center of the screen and the box.
    I don't have a clue what that means really.

  10. #10
    Join Date
    Apr 2007
    Posts
    3,152
    Mentioned
    3 Post(s)
    Quoted
    1 Post(s)

    Default

    Quote Originally Posted by almost View Post
    Setting your [mx, my, mz] will be totally different than how I did it with a cube.
    Look at the part where I explain how to find the middle point.
    You will have to take the average of the max and min values of your object.


    I don't have a clue what that means really.
    if you move the object toward you enough, you'll look like you're inside the object. then if you move the mouse to the outer edges it does something, that i dont think it should do...(make lines to the middle of the screen)
    SCAR Tutorials: The Form Tutorial | Types, Arrays, and Classes
    Programming Projects: NotePad | Tetris | Chess


  11. #11
    Join Date
    Jan 2007
    Posts
    8,876
    Mentioned
    123 Post(s)
    Quoted
    327 Post(s)

    Default

    Quote Originally Posted by Dan Cardin View Post
    if you move the object toward you enough, you'll look like you're inside the object. then if you move the mouse to the outer edges it does something, that i dont think it should do...(make lines to the middle of the screen)
    Yeah, I noticed this too, the lines was really weird.. And sometimes the viewer made the square look like a trapeze (idk how to spell it.. :S)

  12. #12
    Join Date
    Oct 2007
    Location
    #srl
    Posts
    6,102
    Mentioned
    39 Post(s)
    Quoted
    62 Post(s)

    Default

    Wow.
    This really is great, perhaps after Dinner I will see what I can do with it

    Great Job
    rep+

  13. #13
    Join Date
    Jan 2007
    Location
    Tennessee
    Posts
    642
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    The lines going to the center is caused by trying to draw a point that is behind the viewer.
    I explained this some in the tut.
    The script doesn't have anything in it that says "dont draw that point" as of right now though, so the point is just drawn in the middle of the box.

  14. #14
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    3,620
    Mentioned
    5 Post(s)
    Quoted
    0 Post(s)

    Default

    Thanks for that :-).
    Verrekte Koekwous

  15. #15
    Join Date
    Dec 2011
    Posts
    23
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    if there was a way to simplify it you may be able to use it for other 3D games like WOW

  16. #16
    Join Date
    Mar 2012
    Posts
    24
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Pretty advanced, but nice topic. I hope I master this before applying for SRL Membership (A)
    Projects Directory: http://subliment.co.cc/
    Latest News: Working on ZChopper
    ZChopper: The chopper that will chop, bank (or drop), and chop, forever (or till a random pops out)

  17. #17
    Join Date
    Sep 2007
    Location
    British Columbia, Canada
    Posts
    4,047
    Mentioned
    1 Post(s)
    Quoted
    2 Post(s)

    Default

    This is interesting indeed. But you don't need to before you apply for SRL membership

    But if you were able to draw trees or something that would be definitely a bonus.
    Oh Hai Dar

  18. #18
    Join Date
    May 2012
    Location
    VARROCK
    Posts
    47
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Thanks a lot for that tutorial.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. finding objects
    By randy marsh in forum OSR Help
    Replies: 1
    Last Post: 07-02-2008, 09:13 PM
  2. SCAR Paint Drawing Competition
    By Gilbert in forum News and General
    Replies: 27
    Last Post: 11-11-2006, 09:37 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •