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)