Well the first thing you need to do is break it down into basics. In 3D you don’t calculate squares or triangles directly, you calculate points. So for what you want, you’d calculate the position of the 4 corners of the square and use them to create the square.
I don’t tend to work from screen space back into world space, that is kinda doing things the wrong way around - you need to manipulate your ‘world’ (IE manipulate values in world space) and then convert to screen space, which is one way of saying taking 3D points and making them into 2D ones on your screen.
An easy-ish way of doing things would be:
-
Stick a group in your app so its origin is in the middle of the screen. This is going to be your reference point.
-
Work out your coordinates system. For now it might be best (although not necessarily the most wildly used) to assume in your 3D world positive X is to the right, positive Y is up and positive Z is *into* the screen (IE so the further something is in front of you, the larger Z value it has)
-
Now you just have to choose useful world points (IE a vector, or 3 element table with x, y and z values. You could do this with { 1, 2, 3 } or { x = 1, y = 2, z = 3} etc.
Now when I mean convert from world coordinates into screen coordinates, you’d essentially do this:
screenX = point.x / point.z * scaleFactor
screenY = -point.y / point.z * scaleFactor
Now you have the screen coordinates for whatever you want, when placed into your centered group. Two things to note:
-
-point.y is because in screen coordinates, positive y is down, but in 3D we often say positive y is up, so I flip it.
-
scaleFactor - this depends entirely on what you are showing, and you can tweak it to make things fit better on screen. It is roughly equivalent to field of view - the larger the scale factor value the lower the field of view and the bigger everything appears on screen.
There’s a few things to be careful of - the smaller the value of Z the closer something is and usually objects get very big. Also, never try to place any objects at z == 0 (ie level with the eye plane) as you’ll get divide by zero errors.
So for a square, I’d have 4 points. let’s say the corners are:
corner1 = { x = -1, y = 1, z = 4 }
corner2 = { x = -1, y = -1, z = 4 }
corner3 = { x = 1, y = -1, z = 4 }
corner4 = { x = 1, y = 1, z = 4 }
Simply pass each point through the above routine and then use these points (maybe stick a single sprite at each location, or draw a polygon connecting them, or use an image and the .path property) to draw something onscreen. To begin with I’d probably set up scaleFactor to be around a quarter of your screen width, that should at least make my randomly picked values above show something (probably).
Now, if you’ve managed to draw a square, and you want to rotate said square, you have to get into a bit of trigonometry, and this is where I can’t really help you with code off the top of my head, as it involves stuff like matrices, but:
What you’d want to do is make your square coordinates based around it’s own origin. So instead of the above you’d have:
corner1 = { x = -1, y = 1, z = 0 }
corner2 = { x = -1, y = -1, z = 0 }
corner3 = { x = 1, y = -1, z = 0 }
corner4 = { x = 1, y = 1, z = 0 }
Note how the Z is 0 in all cases. So how do we stop divide by zero errors? We invent the concept of a camera position. In this example we only need a Z offset, so to be equivalent to the first example, we’d say your camera is at Z = -4 (negative because the camera is *out* of the screen, IE in front of the square.
So now your calculations would become:
screenX = point.x / ( point.z - cameraZ ) * scaleFactor
screenY = -point.y / ( point.z - cameraZ ) * scaleFactor
And you’d end up with the same as above, but with one important difference - you can now manipulate your square and the distance to the camera will remain correct.
So how do you rotate your square? That’s the relatively tricky part. You’d use sin() and cos() to calculate the new X, Y and Z values of the four corners. In general you’d only alter 2 at a time, which is equivalent to rotating around one of the axes. For example if you want the square to rotate around the Y axis, you’d only be changing the X and Z values using sin() and cos(). I can’t go into them right now, but what I’d suggest is you start with just getting a simple square showing onscreen, then maybe try to move it around (adding offsets), and then search for simple 3D point rotation. I doubt I’ll guess correctly but they’ll look something like this:
– Rotate around the y axis
new.x = sin( yAngle ) * old.x + cos( yAngle ) * old.z
new.z = sin( yAngle ) *old.z - cos( yAngle ) * old.x
That is *not* correct, but it should give you an idea if your searching is giving you the right answer
As for the turning in *my* game, it is very much hacked - in fact I can honestly say the game has no concept of corners directly - only offsets. This is why the 3D is only an approximation in these types of games