You can download my script here:
- http://www.rebol.org/view-script.r?script=r3d2.r
- http://www.rebol.org/view-script.r?script=advanced-r3d.r
Here a very interesting video:
I report here the documentation:
R3D Documentation
Massimiliano Vessi
Contents:
1. Introduction1.1 Test it
2. How it works
2.1 Basic principle
2.2 Basic usage
2.3 Specify objects position and rotation
2.4 Creating models
2.5 Adding images
2.6 Going deep, to know all
3. All function descriptions
4. Models
5. Thanks
1. Introduction
R3D is a library to create and visualize 3D objects; it's cross-platform (works on Widnows, Linux and MacOS) because use just DRAW commands. In order to use it, just copy r3d2.r in your folder script and add:
do %r3d2.r
The main function is render, but there are many other useful functions. If you read the script, the first part contains just functions to operate with matrices 4x4 and 3x1. The second part of the script contains the more interesting functions.
If you want to correct or improve library or documentation, send me an email: maxint@tiscali.it
1.1 Test it
Try this and see the result:do http://www.rebol.org/download-a-script.r?script-name=advanced-r3d.r
result could be this:
2. How it works
3D is a complicated matter and to really understand deeply how all it works, you should study geometry and linear algebra. However I'll explain just how to use and basic principles of this library.
2.1 Basic principle
The basic principles are the followings:
- You create a word with 3D objects
- You put your camera int the the 3D word, giving position of the camera and the point you are looking. This is a very important concept, it is not enough to give camera position. Moreover if you move your camera, it will continue to look at the given point. This is different from human habit, if you walk on the street, you continue to look at 3 meters in front of you. Vice versa the camera, if you don't update also the point you are looking at, it will walk on the street starting looking at the traffic light in front of it; when it'll surpass the traffic light, it will turn back continuing to look at the traffic light, even it can't see the traffic light anymore. So remember to update also the point where the camera is looking when you move it.
- You must give the UP direction. Did you ever notice what happen rotating a camera during recording? Yes, the same way; you must give where is up and down, probably sometime Z axis is not a convenient UP.
2.2 Basic usage
Download r3d3.r and add
do %r3d2.r
to your script.
2.2.1 Populating your world
First of all we create our world:world: copy []
Now we must create (or populate) a world using the cube2-model, every object you put in your world must have:
- model (cube, pyramid, an airplane, ...)
- proportion matrix: this is useful, for example a cube (a dice) can be deformed in a parallelepiped (a tower, a coffin, ...)
- color or image (color or image on the faces)
model: reduce [cube2-model (r3d-scale 100 100 400 ) red ]
now we insert our model in our world:
append world reduce [model]
This way we create a red cube stretched on the Z axis four times that in the other direction (a tower).
Note
R3D contains "ready to use" models, in the next chapter will see how to create our model, now we will use cube2-model.
We can add many objects in our word, but in this first example we'll see only an object. The way used to populate the world is the one correct, since we can add many 3D objects in our world,
like:
R3D contains "ready to use" models, in the next chapter will see how to create our model, now we will use cube2-model.
We can add many objects in our word, but in this first example we'll see only an object. The way used to populate the world is the one correct, since we can add many 3D objects in our world,
like:
world1: [ [only one object] ]
world2: [ [object1] [object2] ]
2.2.2 Installing the camera
This is a very important concept: what will you show of your world?You just created a world, but on a screen you have a 2D window, so you must put in your word a camera that look and show your word on the window.
The camera is just a point, it doesn't have volume, it doesn't occupy space. So you must give:
- camera position
- point that is looking the camera
- UP vector (a 3x1 vector giving where is up)
So our code will be:
camera: r3d-position-object [ 300 300 600] [ 0 0 0] [ 0 0 1]
We must supply as camera a 4x4 camera projection matrix, the quickest way is to use the r3d-position-object function. Modifying the UP position, you'll obtain cool rotation.
2.2.3 Showing all
Now we must decide our window size (for example 300x200) and decide the perspective projection matrix. Don't be scared of these terms, if you don't need some distortion, just use the r3d-perspective giving it a number greater than zero (for example 250 is a good number here).So we put all together and send it to the render function:
my-window: render world camera (r3d-perspective 250) 300x200
Now we can show all in our layout:
view layout [
box 300x200 effect [draw my-window]
]
The result should be this:
2.2.4 Some consideration
You'll notice that all the code to render a 3D world is extremely short and complete at the same time, all the code isdo %r3d2.r
model: reduce [cube2-model (r3d-scale 100 100 400 ) red ]
world: copy []
append world reduce [model]
camera: r3d-position-object [ 300 300 600] [ 0 0 0] [ 0 0 1]
my-window: render world camera (r3d-perspective 250) 300x200
view layout [ box 300x200 effect [draw my-window] ]
No more than 7 lines.
You can play and examine the advanced-r3d.r script to learn how to play with R3D parameters.
2.3 Specify objects position and rotation
The proportion matrix can be of proportion, translation or rotation using the r3d-compose-m4 function. Let's see a dimostration:
do %r3d2.r
model: reduce [cube2-model (r3d-scale 100 100 400 ) red ]
world: copy []
append world reduce [model]
properties: r3d-compose-m4 reduce [r3d-scale 100 100 400 r3d-translate -110 110 0]
model2: reduce [cube2-model properties red ]
append world reduce [model2]
camera: r3d-position-object [ 300 300 600] [ 0 0 0] [ 0 0 1]
my-window: render world camera (r3d-perspective 250) 300x200
view layout [ box 300x200 effect [draw my-window] ]
You'll obtain this:
2.4 Creating models
Models are 3D objects, they are represented by vertexes and faces. For example a cube is made of 8 vertexes and six faces.
A model is made of block containing two blocks:
- vertexes coordinates
- faces made of vertexes, every block is a list of vertexes for that face
Example:
cube2-model: [
; vertexes
[
[ 0 0 0 ] ;vertex 1
[ 1 0 0 ] ;vertex 2
[ 1 1 0 ] ;vertex 3
[ 0 1 0 ] ; vertex 4
[ 0 0 1 ] ;point 5
[ 1 0 1 ] ;point 6
[ 1 1 1 ] ;point 7 and so on...
[ 0 1 1 ]
]
; faces - anticlockwise winding
[
[ 4 3 2 1] ;bottom face made of vertexes 1 2 3 4
[ 5 6 7 8 ] ; upper face
[ 1 5 8 4 ]
[ 1 2 6 5]
[ 2 3 7 6 ]
[ 8 7 3 4 ]
]
]
You can describe a face with a minimum of 3 points (triangular face).
As you can see you can determine a face with any number of vertex, not only triangle (as other 3D programs).
Look at this model:
prysm-8-model: [
;vertices
[
[-0.414 -1 0] ;1
[0.414 -1 0] ;2
[1 -0.414 0 ] ;3
[1 0.414 0 ] ;4
[0.414 1 0] ;5
[-0.414 1 0] ;6
[-1 0.414 0 ] ;7
[-1 -0.414 0 ] ;8
[-0.414 -1 1] ;9
[0.414 -1 1] ;10
[1 -0.414 1 ] ;11
[1 0.414 1 ] ;12
[0.414 1 1] ;13
[-0.414 1 1] ;14
[-1 0.414 1 ] ;15
[-1 -0.414 1 ] ;16
]
; faces
[
[1 2 3 4 5 6 7 8]
[9 10 11 12 13 14 15 16]
[1 2 10 9]
[2 3 11 10]
[3 4 12 11]
[4 5 13 12]
[5 6 14 13]
[6 7 15 14]
[7 8 16 15]
[8 1 9 16]
]
]
It's an octagonal base prysm, you can describe it with just 10 faces: 2 octagons + 8 rectangles! Other old 3D techniques use only triangles, so you had to specify 32 faces. Rebol is the next generation computer graphic!
Using the following code:
model: reduce [prysm-8-model (r3d-scale 100 100 200 ) red ]
world: copy []
append world reduce [model]
camera: r3d-position-object [ 300 300 400] [ 0 0 0] [ 0 0 1]
my-window: render world camera (r3d-perspective 250) 300x200
view layout [ box 300x200 effect [draw my-window]]
this is the result:
2.5 Adding images
If you specify an image as color, you may obtain two different results:
If the face is rectangular (made of exactly 4 vertexes), you have the image attached to the face, for example
do %r3d2.r
img: load-image http://www.rebol.com/view/demos/palms.jpg
model: reduce [cube2-model (r3d-scale 200 200 200 ) img ]
world: copy []
append world reduce [model]
camera: r3d-position-object [ 300 300 300] [ 0 0 0] [ 0 0 1]
my-window: render world camera (r3d-perspective 250) 300x200
view layout [box 300x200 effect [draw my-window] ]
this is the result:
if the face is not rectangular, you have a "transparent effect" of the image beyond the object. The image is repeated in order to fil the window background, for example
cube-model is made of triangles, not of squares:
do %r3d2.r
img: load-image http://www.rebol.com/view/demos/palms.jpg
model: reduce [cube-model (r3d-scale 200 200 200 ) img ]
world: copy []
append world reduce [model]
camera: r3d-position-object [ 300 300 300] [ 0 0 0] [ 0 0 1]
my-window: render world camera (r3d-perspective 250) 300x200
view layout [box 300x200 effect [draw my-window] ]
this is the result:
2.6 Going deep, to know all
If you are interested in geometry and all calculus of the library, you can start reading the basic principles:
- http://en.wikipedia.org/wiki/Transformation_matrix
- http://en.wikipedia.org/wiki/3D_projection#Perspective_projection
- http://en.wikipedia.org/wiki/Camera_matrix
3. All function descriptions
r3d-identity | It's not a function, is just a 4x4 identity matrix (all 1 on the first diagonal). Useful for starting a matrix or resetting a matrix, and much more... | |
r3d-perspective | Create a perspective matrix with a vanishing point d units from the camera | |
r3d-translate | Create a translation matrix | |
r3d-scale | Create a scale matrix | |
r3d-rotateX | Create a rotation matrix around X axis | |
r3d-rotateY | Create a rotation matrix around Y axis | |
r3d-rotateZ | Create a rotation matrix around Z axis | |
r3d-face-direction | ???? | |
r3d-position-object | ??? | |
r3d-m4xm4 | Matrix product between two 4x4 matrices | |
r3d-m4xv3 | Matrix product between a 4x4 matrix and a 4x1 ([A B C 1]) vector. This function will append the last 1 to the vector 3x1 | |
r3d-m4xv3-array | This function return the same block of vertexes, multiplied for the transformation matrix | |
r3d-compose-m4 | Take a block containing 4x4 matrices and multiplicated each other obtaining a single 4x4 matrix | |
r3d-transpose-m4 | Transpose a 4x4 matrix | |
r3d-inverse-m4 | Inverse of a 4x4 matrix | |
r3d-dotproduct | Returns the dot product (a number) between two 3x1 vector | |
r3d-crossproduct | Returns a cross product (vector, 3x1) between 2 vectors (3x1) | |
r3d-length | Returns the distance between origin and a point (3x1) | |
r3d-Add | Add a to b - a and b can be either matrices or vectors but types must match | |
r3d-Subtract | Subtract b from a - a and b can be either matrices or vectors but types must match | |
r3d-Multiply | Multiply a by n - a and b can be either a matrix or vector, n is a number | |
r3d-Divide | Divide a by n - a and b can be either a matrix or vector, n is non-zero number | |
r3d-normalise | Normalize a vector, its module becomes 1 | |
r3d-print-m4 | Debug: Print a 4x4 matrix | |
r3d-print-v3 | Debug: Print a 3x1 vector | |
render | Main function that render 3D objects creating a VID DRAW | |
r3d-CalculateFaceNormals | Calculate face normals to apply light effects??? | |
r3d-Render2dTriangles-Simple | Decide which face to show and the light of the face??? | |
r3d-Load-OFF | Loads OFF files of 3D objects |
4. Models
This is a list of the internal ready to use 3D objects:
cube-model | A cube made of triangle faces | |
cube2-model | A cube made of triangle faces, useful for images | |
pyramid-model | A triangular base pyramid, made of triangles | |
square-pyramid-model | A square base pyramid, made of triangles and a square | |
wall-model | A wall on the X plane, good for images | |
prysm-8-model | A octagonal prism, it shows how to use polygons for faces. |
5. Thanks
Thank to Andrew Hoadley to developed a such beautiful library.
No comments:
Post a Comment