Rotating the view in 3D program
Author |
Message |
Wolf_Destiny
|
Posted: Thu Oct 26, 2006 5:37 pm Post subject: Rotating the view in 3D program |
|
|
Okay so I've been working on a 3d program. In its most basic form it makes a grid 3 by 3 and 2 deep of cubes. These cubes can move towards the screen, or away from it. (I'll be posting the full program tomorrow)
The code used to draw the 3d objects is fairly simple:
Quote: With Point 1: x1,y1,z1
and Point 2: x2,y2,z2
and center of screen: a,b
It draws a line between (a + (x1/z1),b + (y1/z1),a + (x2/z2),b + (y2/z2),colour)
The actual code is:
code: | %Code by: S. Lyon
procedure drawLine (x1, y1, z1, x2, y2, z2, c, center_x, center_y : real)
drawline (round (center_x + (x1/z1)),round (center_y + (y1/z1))
,round (center_x + (x2/z2)),round (center_y + (y2/z2)),round (c))
end drawLine |
So the code for drawing a cube:
code: | %Code by: S. Lyon
%Code to draw a line in 3d:
procedure drawLine (x1, y1, z1, x2, y2, z2, c, center_x, center_y : real)
drawline (round (center_x + (x1/z1)),round (center_y + (y1/z1)),round (center_x + (x2/z2)),round (center_y + (y2/z2)),round (c))
end drawLine
%Front Square of Cube
drawLine (-100,-100,2,-100,100,2,1,maxx/2,maxy/2)
drawLine (-100,100,2,100,100,2,1,maxx/2,maxy/2)
drawLine (100,100,2,100,-100,2,1,maxx/2,maxy/2)
drawLine (100,-100,2,-100,-100,2,1,maxx/2,maxy/2)
%Back Square of Cube
drawLine (-100,-100,3,-100,100,3,1,maxx/2,maxy/2)
drawLine (-100,100,3,100,100,3,1,maxx/2,maxy/2)
drawLine (100,100,3,100,-100,3,1,maxx/2,maxy/2)
drawLine (100,-100,3,-100,-100,3,1,maxx/2,maxy/2)
%Connecting Lines of Cube's Corners
drawLine (-100,-100,2,-100,-100,3,1,maxx/2,maxy/2)
drawLine (-100,100,2,-100,100,3,1,maxx/2,maxy/2)
drawLine (100,-100,2,100,-100,3,1,maxx/2,maxy/2)
drawLine (100,100,2,100,100,3,1,maxx/2,maxy/2) |
So you may have noticed that I've used the center of the screen as a "vanishing point" for the 3d objects. I've then used that as a "relative point" in that all coordinates passed to drawLine are drawn relative to the position of "center_x" and "center_y"
This method has so far worked well for the application I've put it to. It could draw complex 3d meshes given coordinates. However, I have no way of rotating anything drawn by this program. If the user is said to be facing "EAST" or 0 degrees, then this is what they see. However if I wanted the user to be able to turn, to the left or right, it has no way of doing that.
What would be ideal is to have an angle passed to a procedure or function, which would then change the view to reflect that angle. Possibly by editing the coordinates of a given point one at a time? Maybe changing a boolean draw_or_not variable if the point shouldn't be visable (behind user). My thought right now is that the vanishing point shouldn't change since the horizon stays the same. Though I could be wrong.
Anyways, I've looked on the internet, but I couldn't really find any equations for doing this, and I don't really know what I'm looking for anyways. I'm new to this whole 3d thing. I've only started with it this week. I am however experienced in Turing, and yes, I can use classes. I just don't know the physics behind creating a 3d view on a 2d plane. The only reason I knew the x/z and y/z bit was from a helpful comment to a question I posted in general programming (made by richcash) which led me to a tutorial that told me that bit. (run-on sentence...) Unfortuanatly it didn't tell me how to rotate the view, nor did it give me any hints or the like.
So if anyone already knows how to rotate the view, or knows a good website or equation, anything really! I would really appreciate the help!
(And I haven't posted the program I've got yet because it's at school. But the drawLine code I already posted is identical to the inner workings of the program I've got. Maybe spaced better.)
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
zylum
|
Posted: Thu Oct 26, 2006 8:36 pm Post subject: (No subject) |
|
|
first lets deal with 2D rotation:
so there are a couple of identities in trigonometry which includes the summation of angles in the equations. these are:
code: | cos(A+B) = cos(A)cos(B) - sin(A)sin(B)
sin(A+B) = cos(A)sin(B) + sin(A)cos(B) |
now if we have a point on a unit circle (centred on the origin) at some angle alpha, we can describe its position parametrically like so:
code: | x = cos(alpha)
y = sin(alpha) |
if we wanted to rotate this point by beta degrees, the new position of this point would be described like so:
code: | x' = cos(alpha + beta)
y' = sin(alpha + beta) |
looks familiar huh? now if we sub everything back into the two identities stated earlier we get:
code: | x' = x*cos(beta) - y*sin(beta)
y' = x*sin(beta) + y*cos(beta) |
now this also works for points that are not on a unit circle. say your point is d units from the origin, it would be described as:
code: | x = cos(alpha)*d
y = sin(alpha)*d |
and your rotated point will be:
code: | x' = cos(alpha + beta)*d
y' = sin(alpha + beta)*d |
if you multiply both sides of the equations we just derived by d, you get:
code: | x'*d = x*d*cos(beta) - y*d*sin(beta)
y'*d = x*d*sin(beta) + y*d*cos(beta) |
but
code: | x*d = cos(alpha)*d
y*d = cos(alpha)*d |
and
code: | x'*d = cos(alpha + beta)*d
y'*d = sin(alpha + beta)*d |
this proves that the equations
code: | x' = x*cos(beta) - y*sin(beta)
y' = x*sin(beta) + y*cos(beta) |
can be used to rotate any point around the origin by beta degrees.
now if youre points to be rotated are not centred at the origin, you simply translate it there, do the rotation and translate back. a simpler approach would be to store your points relative to the objects origin. this way you can rotate your object more easily. when it comes to drawing the object, you simply add the objects centre coordinate to all the points.
the concepts covered above can also be extended to 3D purposes. in 3D, you generally rotate an object about each of the 3 coordinate axis. what we did above was rotate about the z axis (or in the x-y plane) but the exact same ideas apply for the x and y axis.
hope that helps. this was actually an excerpt from a 3d tutorial i am currently writing. if you are interested, stay tuned
oh and heres some example code:
code: | View.Set ("offscreenonly,nobuttonbar")
type Vector :
record
i, j : real
end record
var c, p, pp : Vector
c.i := Rand.Int (maxx div 3, maxx * 2 div 3)
c.j := Rand.Int (maxy div 3, maxy * 2 div 3)
p.i := Rand.Int (-maxx div 4, maxx div 4)
p.j := Rand.Int (-maxy div 4, maxy div 4)
for ang : 1 .. 360
pp.i := p.i * cosd (ang) - p.j * sind (ang) + c.i
pp.j := p.j * cosd (ang) + p.i * sind (ang) + c.j
Draw.Oval (round (pp.i), round (pp.j), 2, 2, red)
Draw.Oval (round (c.i), round (c.j), 2, 2, grey)
Draw.Oval (round (p.i + c.i), round (p.j + c.j), 2, 2, green)
View.Update
cls
delay (20)
end for |
|
|
|
|
|
|
Wolf_Destiny
|
Posted: Sat Oct 28, 2006 4:50 pm Post subject: (No subject) |
|
|
I can't wait for that tutorial! I've so far got the XY rotation figured out...
code: | %Code to draw a line in 3d:
procedure drawLine (x1, y1, z1, x2, y2, z2, c, center_x, center_y : real)
var check1 : boolean := z1 < -0.0001 or z1 > 0.0001 %to prevent integer overflow
var check2 : boolean := z2 < -0.0001 or z2 > 0.0001 %to prevent integer overflow
if z1 not= 0 and z2 not= 0 and check1 and check2 then
drawline (round (center_x + (x1/z1)),round (center_y + (y1/z1)),round (center_x + (x2/z2)),round (center_y + (y2/z2)),round (c))
end if
end drawLine
var X : array 1..8 of real := init (
-100,-100,100,100,
-100,-100,100,100,
)
var Y : array 1..8 of real := init (
-100,100,100,-100,
-100,100,100,-100,
)
var Z : array 1..8 of real := init (
2,2,2,2,
3,3,3,3,
)
const X1 : array 1..8 of real := init ( %original values
-100,-100,100,100,
-100,-100,100,100,
)
const Y1 : array 1..8 of real := init ( %original values
-100,100,100,-100,
-100,100,100,-100,
)
const Z1 : array 1..8 of real := init ( %original values
2,2,2,2,
3,3,3,3,
)
type Vector :
record
x, y, z : real
end record
var origin, p, pp : Vector
origin.x := 0
origin.y := 0
origin.z := 0
procedure rotateXY (var X_,Y_:real,angle:real,p_x,p_y:real)
X_ := p_x * cosd (angle) - p_y * sind (angle) + origin.x
Y_ := p_y * cosd (angle) + p_x * sind (angle) + origin.y
end rotateXY
procedure rotateXZ (var X_,Z_:real,angle:real,p_x,p_z:real)
X_ := p_x * cosd (angle) + p_z * sind (angle) + origin.x
Z_ := p_z * cosd (angle) - p_x * sind (angle) + origin.z
end rotateXZ
procedure rotateYZ (var Y_,Z_:real,angle:real,p_y,p_z:real)
Y_ := p_y * cosd (angle) - p_z * sind (angle) + origin.y
Z_ := p_z * cosd (angle) + p_y * sind (angle) + origin.z
end rotateYZ
procedure draw
%Front Square of Cube
drawLine (X (1),Y (1),Z (1),X (2),Y (2),Z (2),1,maxx/2,maxy/2)
drawLine (X (2),Y (2),Z (2),X (3),Y (3),Z (3),1,maxx/2,maxy/2)
drawLine (X (3),Y (3),Z (3),X (4),Y (4),Z (4),1,maxx/2,maxy/2)
drawLine (X (4),Y (4),Z (4),X (1),Y (1),Z (1),1,maxx/2,maxy/2)
%Back Square of Cube
drawLine (X (5),Y (5),Z (5),X (6),Y (6),Z (6),1,maxx/2,maxy/2)
drawLine (X (6),Y (6),Z (6),X (7),Y (7),Z (7),1,maxx/2,maxy/2)
drawLine (X (7),Y (7),Z (7),X (8),Y (8),Z (8),1,maxx/2,maxy/2)
drawLine (X (8),Y (8),Z (8),X (5),Y (5),Z (5),1,maxx/2,maxy/2)
%Connecting Lines of Cube's Corners
drawLine (X (1),Y (1),Z (1),X (5),Y (5),Z (5),1,maxx/2,maxy/2)
drawLine (X (2),Y (2),Z (2),X (6),Y (6),Z (6),1,maxx/2,maxy/2)
drawLine (X (3),Y (3),Z (3),X (7),Y (7),Z (7),1,maxx/2,maxy/2)
drawLine (X (4),Y (4),Z (4),X (8),Y (8),Z (8),1,maxx/2,maxy/2)
end draw
for ang : 1..360
for b : 1..8
rotateXY (X(b),Y(b),ang,X1(b),Y1(b))
end for
draw
View.Update
delay (100)
cls
end for
|
According to the rules:
Quote: Rotatation about the x axis:
x' = x
y' = (cos é * y) - (sin é * z)
z' = (sin é * y) + (cos é * z)
Rotation about the y axis:
x' = (cos é * x) + (sin é * z)
y' = y
z' = -(sin é * x) + (cos é * z)
Rotation about the z axis:
x' = (cos é * x) - (sin é * y)
y' = (sin é * x) + (cos é * y)
z' = z
from http://www.geocities.com/SiliconValley/2151/math3d.html my procedures rotateXY, rotate XZ and rotate YZ should all work. But only rotate XY does...(and I do know that my use of procedures to change the values of variables passed to them is bad, and I'll change it later, but right now it's easier for me to read.)
so when I try the code:
code: | %Code to draw a line in 3d:
procedure drawLine (x1, y1, z1, x2, y2, z2, c, center_x, center_y : real)
var check1 : boolean := z1 < -0.0001 or z1 > 0.0001 %to prevent integer overflow
var check2 : boolean := z2 < -0.0001 or z2 > 0.0001 %to prevent integer overflow
if z1 not= 0 and z2 not= 0 and check1 and check2 then
drawline (round (center_x + (x1/z1)),round (center_y + (y1/z1)),round (center_x + (x2/z2)),round (center_y + (y2/z2)),round (c))
end if
end drawLine
var X : array 1..8 of real := init (
-100,-100,100,100,
-100,-100,100,100,
)
var Y : array 1..8 of real := init (
-100,100,100,-100,
-100,100,100,-100,
)
var Z : array 1..8 of real := init (
2,2,2,2,
3,3,3,3,
)
const X1 : array 1..8 of real := init ( %original values
-100,-100,100,100,
-100,-100,100,100,
)
const Y1 : array 1..8 of real := init ( %original values
-100,100,100,-100,
-100,100,100,-100,
)
const Z1 : array 1..8 of real := init ( %original values
2,2,2,2,
3,3,3,3,
)
type Vector :
record
x, y, z : real
end record
var origin, p, pp : Vector
origin.x := 0
origin.y := 0
origin.z := 0
procedure rotateXY (var X_,Y_:real,angle:real,p_x,p_y:real)
X_ := p_x * cosd (angle) - p_y * sind (angle) + origin.x
Y_ := p_y * cosd (angle) + p_x * sind (angle) + origin.y
end rotateXY
procedure rotateXZ (var X_,Z_:real,angle:real,p_x,p_z:real)
X_ := p_x * cosd (angle) + p_z * sind (angle) + origin.x
Z_ := p_z * cosd (angle) - p_x * sind (angle) + origin.z
end rotateXZ
procedure rotateYZ (var Y_,Z_:real,angle:real,p_y,p_z:real)
Y_ := p_y * cosd (angle) - p_z * sind (angle) + origin.y
Z_ := p_z * cosd (angle) + p_y * sind (angle) + origin.z
end rotateYZ
procedure draw
%Front Square of Cube
drawLine (X (1),Y (1),Z (1),X (2),Y (2),Z (2),1,maxx/2,maxy/2)
drawLine (X (2),Y (2),Z (2),X (3),Y (3),Z (3),1,maxx/2,maxy/2)
drawLine (X (3),Y (3),Z (3),X (4),Y (4),Z (4),1,maxx/2,maxy/2)
drawLine (X (4),Y (4),Z (4),X (1),Y (1),Z (1),1,maxx/2,maxy/2)
%Back Square of Cube
drawLine (X (5),Y (5),Z (5),X (6),Y (6),Z (6),1,maxx/2,maxy/2)
drawLine (X (6),Y (6),Z (6),X (7),Y (7),Z (7),1,maxx/2,maxy/2)
drawLine (X (7),Y (7),Z (7),X (8),Y (8),Z (8),1,maxx/2,maxy/2)
drawLine (X (8),Y (8),Z (8),X (5),Y (5),Z (5),1,maxx/2,maxy/2)
%Connecting Lines of Cube's Corners
drawLine (X (1),Y (1),Z (1),X (5),Y (5),Z (5),1,maxx/2,maxy/2)
drawLine (X (2),Y (2),Z (2),X (6),Y (6),Z (6),1,maxx/2,maxy/2)
drawLine (X (3),Y (3),Z (3),X (7),Y (7),Z (7),1,maxx/2,maxy/2)
drawLine (X (4),Y (4),Z (4),X (8),Y (8),Z (8),1,maxx/2,maxy/2)
end draw
for ang : 1..360
for b : 1..8
rotateXZ (X(b),Z(b),ang,X1(b),Z1(b))
end for
draw
View.Update
delay (100)
cls
end for |
It doesn't work...(rotateYZ doesn't work either)...and I don't really know why that is. I'm going to keep working on it, but any help would be greatly appreciated!
|
|
|
|
|
|
Wolf_Destiny
|
Posted: Mon Nov 06, 2006 4:34 pm Post subject: Yay! |
|
|
Well, I've finally gotten it! After a long battle with how to plot 3d points, and then the actual rotation of them, and some algorithms that didn't work, ect. I've got a working 3d engine complete with rotation! I haven't yet added polygons, but that shouldn't take too long.
If anyone else is trying to make a 3d something or other (could be a game like me, or something else) I recommend not trying unless you like frustration! But actually what really helped me finally make the breakthrough was this snippet of code:
code: | // x-axis rotation
rx1 = x
ry1 = y * cos a - z * sin a
rz1 = y * sin a + z * cos a
// y-axis rotation
rx2 = rx1 * cos b + rz1 * sin b
ry2 = ry1
rz2 = rx1 * -sin b + rz1 * cos b
// z-axis rotation
rx3 = rx2 * cos c - ry2 * sin c
ry3 = rx2 * sin c + ry2 * cos c
rz3 = rz2 |
It's originally code from a flash tutorial, but it has the general algorithms for rotation in it. Good luck to anyone else that wants to attempt it!
I've attached my program which so far only rotates a square. That said, it actually correctly rotates said square.
Thanks to all that helped me out with this!
~Wolf_Destiny
Description: |
|
Download |
Filename: |
3d.zip |
Filesize: |
268.27 KB |
Downloaded: |
169 Time(s) |
|
|
|
|
|
|
zylum
|
|
|
|
|
Carey
|
Posted: Thu Apr 05, 2007 9:20 am Post subject: Re: Rotating the view in 3D program |
|
|
The link you have to catalysts engine actually goes to rizzix's one. The actual file has been removed though...
Catalyst's engine is here
|
|
|
|
|
|
|
|