Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Rotating the view in 3D program
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
Wolf_Destiny




PostPosted: 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
Sponsor
sponsor
zylum




PostPosted: 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 Wink

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




PostPosted: 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




PostPosted: 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



3d.zip
 Description:

Download
 Filename:  3d.zip
 Filesize:  268.27 KB
 Downloaded:  169 Time(s)

zylum




PostPosted: Mon Nov 06, 2006 6:40 pm   Post subject: (No subject)

you do know that many people have created 3d engines in turing and posted their source right? you didn't have to visit any other site than this one to get your answers.

homer
http://www.compsci.ca/v2/viewtopic.php?p=63501&sid=f741b838b792073cc6af5d24fef7e9cf

catalyst
http://www.compsci.ca/v2/viewtopic.php?t=1479&view=next&sid=07b920f43263cbb3dff7b0f17c1c4aa7

zylum (probably the best one of the bunch Wink )
http://compsci.ca/v2/viewtopic.php?t=9639&highlight=
Carey




PostPosted: 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
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 6 Posts ]
Jump to:   


Style:  
Search: