This article has links to websites or programs outside of Scratch and Wikipedia. Remember to stay safe while using the internet, as we cannot guarantee the safety of other websites. |
This article or section may not have content matching Scratch Wiki editing standards. Please improve it according to Scratch Wiki:Guidelines and Scratch Wiki:Editing Conventions. (August 2021) Reason: does not contain any cap blocks to show when Variables should be set |
This tutorial will explain how to make a three-dimensional project by calculating the position of the 3D object first and then projecting it on to the screen.
Note: | This tutorial is recommended for more experienced Scratchers due to its difficulty. For a simpler 3D project, see Raycaster. |
Three-Dimensional Environment
A 3D environment is a place that involves the common X and Y axes found in Scratch, as well as the additional Z axis. The Z axis is a Cartesian coordinate, which is like the X and Y axes found in Scratch, but the Z axis usually is the axis for depth. In real life, the Z axis exists, but in Scratch, it does not. However, one can incorporate size and movement that causes an illusion of depth in Scratch.
Three-Dimensional Graphics Procedure
The illusion of 3D on a flat surface, such as a computer screen, is achieved by projecting a three-dimensional point onto a two-dimensional surface.
Three-dimensional objects may be manipulated with matrix transformations.
The model also has a "transform" consisting of its translation, rotation and scale. Transformations are a way to describe the movement of shapes.
To implement 3D, one first needs to calculate the model's vertices' positions in the map ("worldspace"). Then, they must determine the worldspace coordinates' positions relative to the viewer by applying the opposite of the camera's transform to the points. Points that are not in the camera's field of vision ("clipspace") may be dropped. Finally, the clipspace coordinates are projected onto the screen.
Preparation
You will need to create these variables which are set to 'for all sprites':
(focal length) (camera x) (camera y) (camera z) (cam roll) (cam pitch) (cam yaw) (scale factor)
You will also need to create these variables which is set to 'for this sprite only' for every sprite that you want to process the vertices.
(size::variables) (x transformation) (y transformation) (z transformation) (angle) (2D x) (2D y) (x) (y) (z) (roll) (temp) (translation x) (translation y) (translation z)
The vertices of models can be to be stored in a list which is set to 'for all sprites', but is not necessary for this tutorial:
(vertices x::list) (vertices y::list) (vertices z::list)
Note: | These variables are used for explanation, but not used in the final script:
(old x) (old y) (old z) (new x) (new y) (new z) (3D x) (3D y) (3D z) |
Data Representation
Representing a 3D object in some variables is a model.^{[citation needed]} A model needs a data representation. Let a "model" consist of an array of vertices and an array of faces. Each vertex has an x, a y and a z component. Each face is an array of vertex indices.
Transformations
There are 3 types of transformations: scale (dilation), translation and rotation. Here are the explanation and code for all 3:
Scale
The scale of a shape is its size. The process of scaling is known as dilation. For example, the set size to () and change size by blocks dilate sprites. In 3D, this code change the scale of a model:
set [new x v] to ((old x) * (size::variables)) set [new y v] to ((old y) * (size::variables)) set [new z v] to ((old z) * (size::variables))
Translation
Translation is the movement of a shape across the coordinate plane. The change x by and change y by blocks translate sprites across the x and y axis respectively. In 3D, this code translates of a model:
set [new x v] to ((old x) + (x transformation)) set [new y v] to ((old y) + (y transformation)) set [new z v] to ((old z) + (z transformation))
Rotation
Rotations are transformations that turn shapes. The turn () degrees blocks rotate sprites.
Rotations in a 3D environment are a bit more complicated. They consist of three components: yaw (rotation around the z axis), pitch (rotation around the x axis) and roll (rotation around the y axis). Each component can be thought of as applying a 2D rotation around an axis.
Trigonometry Angle Addition
Rotations use these trigonometry rules:
^{[1]}
2D Rotations
This code rotates a sprite on a two-dimensional plane:
set [new x v] to (((old x) * ([cos v] of (angle))) - ((old y) * ([sin v] of (angle)))) set [new y v] to (((old x) * ([sin v] of (angle))) + ((old y) * ([cos v] of (angle))))
^{[2]}^{[3]}
Roll
The roll is the rotation around the y-axis.
set [new x v] to (((old x) * ([cos v] of (angle))) - ((old z) * ([sin v] of (angle)))) set [new z v] to (((old x) * ([sin v] of (angle))) + ((old z) * ([cos v] of (angle))))
Pitch
The pitch is the rotation around the x-axis.
set [new y v] to (((old y) * ([cos v] of (angle))) + ((old z) * ([sin v] of (angle)))) set [new z v] to (((-1) * ((old y) * ([sin v] of (angle)))) + ((old z) * ([cos v] of (angle))))
The pitch uses the angle subtraction formula rather than the angle addition formula because the pitch is clockwise, not counterclockwise.
Yaw
The yaw is the rotation around the z-axis.
set [new x v] to (((old x) * ([cos v] of (angle))) - ((old y) * ([sin v] of (angle)))) set [new y v] to (((old x) * ([sin v] of (angle))) + ((old y) * ([cos v] of (angle))))
The order that these transformations are applied is:
Vertex -> Worldspace (Model transform):
1. Scale
2. Rotation
3. Translation
Worldspace -> Clipspace (Camera transform):
1. Translation
2. Rotation
Caution: | When applying the camera's transformations to the worldspace coordinates, do the opposite. (That is, subtract the camera translaion from the processing postion) For example, if the camera's translation is (5, 6, -2), do (x - 5, y - 6, z + 2) instead. |
Projection
The code for projecting a point is:
set [2D x v] to (((3D x)/(3D z))*(focal length)) set [2D y v] to (((3D y)/(3D z))*(focal length))
This code can be thought of as a proportion.
The code for the size of a point is:
set [2D size v] to ((focal length) / (3D z))
To draw bigger points, multiply "2D size" by some number.
Storing Vertices
To store the unprocessed vertices, the following code can be used:
add (x) to [vertices x] add (y) to [vertices y] add (z) to [vertices z]
Putting Everything Together
Now that you understand how to get a point of a model and calculate its position on the computer screen, put everything together.
For this tutorial, you will have a camera move around the world. It will have a translation and rotation. Any translation and rotation applied to the camera should be reversed for world models.
Processing a Vertex
This custom block takes a point on a model and calculates its projected position on the screen by implementing all of the transformations and projection discussed above.
define process vertex set [x v] to ((x) * (scale factor)) //Scale set [y v] to ((y) * (scale factor)) set [z v] to ((z) * (scale factor)) set [temp v] to (x) //Roll set [x v] to (((x) * ([cos v] of (roll))) - ((z) * ([sin v] of (roll))) set [z v] to (((temp) * ([sin v] of (roll))) + ((z) * ([cos v] of (roll))) set [temp v] to (y) //Pitch set [y v] to (((y) * ([cos v] of (roll))) + ((z) * ([sin v] of (roll))) set [z v] to (((-1) * ((temp) * ([sin v] of (angle)))) + ((z) * ([cos v] of (angle)))) set [temp v] to (x) //Yaw set [x v] to (((x) * ([cos v] of (angle))) - ((y) * ([sin v] of (angle)))) set [y v] to (((temp) * ([sin v] of (angle))) + ((y) * ([cos v] of (angle)))) change [x v] by (translation x) //Translation change [y v] by (translation y) change [z v] by (translation z) change [x v] by ((-1) * (camera x)) //Camera translation change [y v] by ((-1) * (camera y)) change [z v] by ((-1) * (camera z)) set [temp v] to (x) //Camera Roll set [x v] to (((x) * ([cos v] of (cam roll))) + ((z) * ([sin v] of (cam roll))) set [z v] to (((-1) * ((temp) * ([sin v] of (cam roll)))) + ((z) * ([cos v] of (cam roll))) set [temp v] to (y) //Camera Pitch set [y v] to (((y) * ([cos v] of (cam pitch))) - ((z) * ([sin v] of (cam pitch))) set [z v] to (((temp) * ([sin v] of (cam pitch))) + ((z) * ([cos v] of (cam pitch))) set [temp v] to (x) //Camera Yaw set [x v] to (((x) * ([cos v] of (cam yaw))) + ((y) * ([sin v] of (cam yaw))) set [y v] to (((-1) * ((temp) * ([sin v] of (cam yaw)))) + ((y) * ([cos v] of (cam yaw))) set [2D x v] to ((x) / (z)) //Projection set [2D y v] to ((y) / (z))
Drawing a Shape
Please expand this section. You can help by adding more information if you are an editor. More information might be found in a section of the talk page. (October 2023) |
To draw a shape, you can connect the points that are edges on the screen.
Example using size to create a 3D effect
Preparation
You will need to create these variables:
(scroll z) (scroll y) (scroll x)
You will not need to create any lists.
Tutorial
This script uses sprites and size change for depth perception:
when green flag clicked set [scroll z v] to [60] set [scroll y v] to [0] set [scroll x v] to [-30] forever set size to ((scroll z) + ((40) * (0)))% set x to ((scroll x) + ((480) * (0))) set y to ((scroll y) + ((360) * (0))) if <key (up arrow v) pressed?> then change [scroll z v] by ((size) / (45)) change [scroll x v] by ((x position) / (55)) end if <key (down arrow v) pressed?> then change [scroll z v] by ((size) / (-45)) change [scroll x v] by ((x position) / (-55)) end if <key (left arrow v) pressed?> then change [scroll x v] by ((size) / (55)) end if <key (right arrow v) pressed?> then change [scroll x v] by ((size) / (-55)) end if < <(scroll z) < [20]> or <(scroll z) > [217]> > then hide else show end
The "scroll x" and "scroll y" variables' value can be changed so the sprite's position can be changed. The "scroll z" variable is rather special. It does not change the sprite's position, but it changes The size of the sprite.
This method of 3D scripting is very rudimentary, and it does not involve any collision detection, and it would not apply to a moving object.
This is one of the ways you can make the illusion of 3D. Scratch doesn't allow you to make three dimensional games, but it allows you to make the illusion of one. The X axis is the sprites position from left to right. The Y axis is the position from top to bottom, and the Z axis is the sprites size, allowing you to make the sprite small or large. As said in the beginning of this article, we can always incorporate size and movement to create the 3D illusion. If you stroll down a street, you will notice that the farther the things are, the smaller they look. If you put this same principle in video games, you will get a 3D effect. A Raycaster is a more efficient way of 3D in Scratch.
Example Using Pen and Layering
This is a slightly more efficient way of making a 3D illusion. This technique uses layering and stamping. Here is the script:
when flag clicked forever erase all go to x(0) y(0) repeat (6) stamp change y by(2) end end when green flag clicked forever point towards (mouse-pointer v) end
This method does not use size to create the 3D effect. It changes the position of the sprite and stamps the sprite on the background. This makes several copies of the same sprite, in different positions. This creates a 3D effect.
See Also
- Raycaster
- Sprite-Based Raycaster Tutorial
- Three Dimensional Project
- How to Create a 3D Sphere with Pen