[tutorial] 3D matrix (rotation,translation,scaling, rotation around an arbitrary axis)
Author |
Message |
Homer_simpson
|
Posted: Fri Jan 16, 2009 11:12 pm Post subject: [tutorial] 3D matrix (rotation,translation,scaling, rotation around an arbitrary axis) |
|
|
Matrix mathematics can be very useful, for now i've only shown you how to use them for rotation,scaling and translation, i'll update this with rotation around an arbitrary axis. I'll also show you how to multiply matrices.
Quote:
type dot :
record
x, y, z : real
end record
type cam :
record
axy, axz, ayz, cx, cy, cz, zoom : real
end record
var camera : cam
camera.cx := -1
camera.cy := -1
camera.cz := -10
camera.axy := 0
camera.axz := 0
camera.ayz := 0
camera.zoom := 1000
proc draw3dline (d1, d2 : dot)
if d1.z + 2 not= 0 and d2.z + 2 not= 0 then
var xx : array 1 .. 3 of int
var yy : array 1 .. 3 of int
xx (1) := round ((d1.x - camera.cx) / ((d1.z + 2 - camera.cz) / camera.zoom)) + 320
xx (2) := round ((d2.x - camera.cx) / ((d2.z + 2 - camera.cz) / camera.zoom)) + 320
yy (1) := round ((d1.y - camera.cy) / ((d1.z + 2 - camera.cz) / camera.zoom)) + 200
yy (2) := round ((d2.y - camera.cy) / ((d2.z + 2 - camera.cz) / camera.zoom)) + 200
Draw.FillOval (xx (1), yy (1), 2, 2, 9)
Draw.Line (xx (1), yy (1), xx (2), yy (2), 12)
Draw.Dot (xx (2), yy (2), white)
end if
end draw3dline
proc draw3ddot (d1 : dot)
if d1.z + 2 not= 0 then
var xx : array 1 .. 3 of int
var yy : array 1 .. 3 of int
xx (1) := round ((d1.x - camera.cx) / ((d1.z + 2 - camera.cz) / camera.zoom)) + 320
yy (1) := round ((d1.y - camera.cy) / ((d1.z + 2 - camera.cz) / camera.zoom)) + 200
Draw.Dot (xx (1), yy (1), white)
end if
end draw3ddot
colorback (black)
cls
color (white)
View.Set ("offscreenonly")
type matrix : array 1 .. 3, 1 .. 4 of real
var rotationmatrix:matrix
procedure translate(x,y,z:real,var m:matrix)
m(1,1):=1 m(1,2):=0 m(1,3):=0 m(1,4):=x
m(2,1):=0 m(2,2):=1 m(2,3):=0 m(2,4):=y
m(3,1):=0 m(3,2):=0 m(3,3):=1 m(3,4):=z
end translate
procedure scale(x,y,z:real,var m:matrix)
m(1,1):=x m(1,2):=0 m(1,3):=0 m(1,4):=0
m(2,1):=0 m(2,2):=y m(2,3):=0 m(2,4):=0
m(3,1):=0 m(3,2):=0 m(3,3):=z m(3,4):=0
end scale
procedure rotateXY(a:real,var m:matrix)
m(1,1):=cosd(a) m(1,2):=-sind(a) m(1,3):=0 m(1,4):=0
m(2,1):=sind(a) m(2,2):=cosd(a) m(2,3):=0 m(2,4):=0
m(3,1):=0 m(3,2):=0 m(3,3):=1 m(3,4):=0
end rotateXY
procedure rotateYZ(a:real,var m:matrix)
m(1,1):=1 m(1,2):=0 m(1,3):=0 m(1,4):=0
m(2,1):=0 m(2,2):=cosd(a) m(2,3):=-sind(a) m(2,4):=0
m(3,1):=0 m(3,2):=sind(a) m(3,3):=cosd(a) m(3,4):=0
end rotateYZ
procedure rotateXZ(a:real,var m:matrix)
m(1,1):=cosd(a) m(1,2):=0 m(1,3):=sind(a) m(1,4):=0
m(2,1):=0 m(2,2):=1 m(2,3):=0 m(2,4):=0
m(3,1):=-sind(a) m(3,2):=0 m(3,3):=cosd(a) m(3,4):=0
end rotateXZ
procedure applymatrix(var x,y,z:real,m:matrix)
var tx := (x * m(1,1)) + (y * m(1,2)) + (z * m(1,3)) + m(1,4)
var ty := (x * m(2,1)) + (y * m(2,2)) + (z * m(2,3)) + m(2,4)
var tz := (x * m(3,1)) + (y * m(3,2)) + (z * m(3,3)) + m(3,4)
x:=tx
y:=ty
z:=tz
end applymatrix
var xy, yz, xz : real := 0
var p1, p2, vp : dot
p1.x := 0
p1.y := 0
p1.z := 0
p2.x := 0
p2.y := 0
p2.z := -1
var chars : array char of boolean
loop
Input.KeyDown (chars)
if chars (KEY_LEFT_ARROW) then
rotateXZ(1,rotationmatrix)
applymatrix(p2.x,p2.y,p2.z,rotationmatrix)
end if
if chars (KEY_RIGHT_ARROW) then
rotateXZ(-1,rotationmatrix)
applymatrix(p2.x,p2.y,p2.z,rotationmatrix)
end if
if chars (KEY_UP_ARROW) then
rotateYZ(-1,rotationmatrix)
applymatrix(p2.x,p2.y,p2.z,rotationmatrix)
end if
if chars (KEY_DOWN_ARROW) then
rotateYZ(1,rotationmatrix)
applymatrix(p2.x,p2.y,p2.z,rotationmatrix)
end if
for i : 1 .. 360
vp.x := sind (i)
vp.y := cosd (i)
vp.z := 0
draw3ddot (vp)
vp.x := sind (i)
vp.z := cosd (i)
vp.y := 0
draw3ddot (vp)
vp.y := sind (i)
vp.z := cosd (i)
vp.x := 0
draw3ddot (vp)
end for
draw3dline (p1, p2)
View.Update
delay (5)
cls
end loop
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
saltpro15
|
Posted: Fri Jan 16, 2009 11:32 pm Post subject: RE:[tutorial] 3D matrix (rotation,translation,scaling, rotation around an arbitrary axis) |
|
|
Have I mentioned I love you. I've learned more in your last 2 posts than I have in 3 months of Computer Science classes. I want to do an fps with raycasting, I'm not sure how to go about making the target appear on the screen and respond to mouse clicks, any ideas? no wait, if you do have an idea pm me, that topic isn't really covered by this thread. |
|
|
|
|
|
Tyr_God_Of_War
|
Posted: Sat Mar 28, 2009 12:18 am Post subject: Re: [tutorial] 3D matrix (rotation,translation,scaling, rotation around an arbitrary axis) |
|
|
Here, I added some camera movement to the numpad. You cam.axy(..ect.) does nothing at the moment.
I also simplified the matrices, and removed some unused variables. I might have shuffled it around a bit to.
Turing: |
type dot :
record
x, y, z : real
end record
type cam :
record
axy, axz, ayz, cx, cy, cz, zoom : real
end record
type matrix : array 1 .. 3, 1 .. 4 of real
var camera : cam
camera.cx := - 1
camera.cy := - 1
camera.cz := - 10
camera.axy := 0
camera.axz := 0
camera.ayz := 0
camera.zoom := 1000
proc draw3dline (d1, d2 : dot )
if d1.z + 2 not= 0 and d2.z + 2 not= 0 then
var xx : array 1 .. 3 of int
var yy : array 1 .. 3 of int
xx (1) := round ((d1.x - camera.cx ) / ((d1.z + 2 - camera.cz ) / camera.zoom )) + 320
xx (2) := round ((d2.x - camera.cx ) / ((d2.z + 2 - camera.cz ) / camera.zoom )) + 320
yy (1) := round ((d1.y - camera.cy ) / ((d1.z + 2 - camera.cz ) / camera.zoom )) + 200
yy (2) := round ((d2.y - camera.cy ) / ((d2.z + 2 - camera.cz ) / camera.zoom )) + 200
Draw.FillOval (xx (1), yy (1), 2, 2, 9)
Draw.Line (xx (1), yy (1), xx (2), yy (2), 12)
Draw.Dot (xx (2), yy (2), white)
end if
end draw3dline
proc draw3ddot (d1 : dot )
if d1.z + 2 not= 0 then
var xx : array 1 .. 3 of int
var yy : array 1 .. 3 of int
xx (1) := round ((d1.x - camera.cx ) / ((d1.z + 2 - camera.cz ) / camera.zoom )) + 320
yy (1) := round ((d1.y - camera.cy ) / ((d1.z + 2 - camera.cz ) / camera.zoom )) + 200
Draw.Dot (xx (1), yy (1), white)
end if
end draw3ddot
fcn translate (x, y, z : real) : matrix
var m : matrix
m (1, 1) := 1
m (1, 2) := 0
m (1, 3) := 0
m (1, 4) := x
m (2, 1) := 0
m (2, 2) := 1
m (2, 3) := 0
m (2, 4) := y
m (3, 1) := 0
m (3, 2) := 0
m (3, 3) := 1
m (3, 4) := z
result m
end translate
fcn scale (x, y, z : real) : matrix
var m : matrix
m (1, 1) := x
m (1, 2) := 0
m (1, 3) := 0
m (1, 4) := 0
m (2, 1) := 0
m (2, 2) := y
m (2, 3) := 0
m (2, 4) := 0
m (3, 1) := 0
m (3, 2) := 0
m (3, 3) := z
m (3, 4) := 0
result m
end scale
fcn rotateXY (a : real) : matrix
var m : matrix
m (1, 1) := cosd (a )
m (1, 2) := - sind (a )
m (1, 3) := 0
m (1, 4) := 0
m (2, 1) := sind (a )
m (2, 2) := cosd (a )
m (2, 3) := 0
m (2, 4) := 0
m (3, 1) := 0
m (3, 2) := 0
m (3, 3) := 1
m (3, 4) := 0
result m
end rotateXY
fcn rotateYZ (a : real) : matrix
var m : matrix
m (1, 1) := 1
m (1, 2) := 0
m (1, 3) := 0
m (1, 4) := 0
m (2, 1) := 0
m (2, 2) := cosd (a )
m (2, 3) := - sind (a )
m (2, 4) := 0
m (3, 1) := 0
m (3, 2) := sind (a )
m (3, 3) := cosd (a )
m (3, 4) := 0
result m
end rotateYZ
fcn rotateXZ (a : real) : matrix
var m : matrix
m (1, 1) := cosd (a )
m (1, 2) := 0
m (1, 3) := sind (a )
m (1, 4) := 0
m (2, 1) := 0
m (2, 2) := 1
m (2, 3) := 0
m (2, 4) := 0
m (3, 1) := - sind (a )
m (3, 2) := 0
m (3, 3) := cosd (a )
m (3, 4) := 0
result m
end rotateXZ
procedure applymatrix (var x, y, z : real, m : matrix )
const tx := (x * m (1, 1)) + (y * m (1, 2)) + (z * m (1, 3)) + m (1, 4)
const ty := (x * m (2, 1)) + (y * m (2, 2)) + (z * m (2, 3)) + m (2, 4)
const tz := (x * m (3, 1)) + (y * m (3, 2)) + (z * m (3, 3)) + m (3, 4)
x := tx
y := ty
z := tz
end applymatrix
View.Set ("offscreenonly")
colorback (black)
cls
color (white)
var p1, p2, vp : dot
p1.x := 0
p1.y := 0
p1.z := 0
p2.x := 0
p2.y := 0
p2.z := - 1
var chars : array char of boolean
loop
Input.KeyDown (chars )
if chars (KEY_LEFT_ARROW) xor chars (KEY_RIGHT_ARROW) then
if chars (KEY_LEFT_ARROW) then
applymatrix (p2.x, p2.y, p2.z, rotateXZ (1))
else % right arrow key
applymatrix (p2.x, p2.y, p2.z, rotateXZ (- 1))
end if
end if
if chars (KEY_UP_ARROW) xor chars (KEY_DOWN_ARROW) then
if chars (KEY_UP_ARROW) then
applymatrix (p2.x, p2.y, p2.z, rotateYZ (- 1))
else % if chars (KEY_DOWN_ARROW) then
applymatrix (p2.x, p2.y, p2.z, rotateYZ (1))
end if
end if
if chars ('4') xor chars ('6') then
if chars ('4') then
camera.cx - = 0. 05
else
camera.cx + = 0. 05
end if
end if
if chars ('8') xor chars ('2') then
if chars ('8') then
camera.cy + = 0. 05
else
camera.cy - = 0. 05
end if
end if
if chars ('/') xor chars ('*') then
if chars ('/') then
camera.cz - = 0. 05
else
camera.cz + = 0. 05
end if
end if
% if chars ('7') xor chars ('9') then % axy does nothing?
% if chars ('7') then
% camera.axy += 100.05
% else
% camera.axy -= 100.05
% end if
% end if
for i : 1 .. 360
vp.x := sind (i )
vp.y := cosd (i )
vp.z := 0
draw3ddot (vp )
vp.x := sind (i )
vp.y := 0
vp.z := cosd (i )
draw3ddot (vp )
vp.x := 0
vp.y := sind (i )
vp.z := cosd (i )
draw3ddot (vp )
end for
draw3dline (p1, p2 )
View.Update
delay (5)
cls
end loop
|
|
|
|
|
|
|
|
|