Will this 3d plotting procedure work?
Author |
Message |
richcash
|
Posted: Tue Aug 15, 2006 5:44 pm Post subject: Will this 3d plotting procedure work? |
|
|
Well, I've been trying to figure out the best way to plot 3d points on a 2d screen, and I was directed to this page by Delos and [Gandalf].
http://freespace.virgin.net/hugo.elias/routines/3d_to_2d.htm
(I'm not really working on this right now, but it's good to know for when I do.)
Well, there were some variable names used on that web site that I didn't really understand, and no one could seem to explain them to me. (For my original topic and more background info : http://www.compsci.ca/v2/viewtopic.php?t=13184)
However, looking at Catalyst's 3d particle engine, I derived this procedure from it and it seems to work for plotting 3d points. I'm not too sure if it works accurately though, so if anyone can tell me if this works or not (maybe it doesn't always work?).
code: | var Camx, Camy, Camz, CamzFrame : int
proc DrawParticle (x, y, z : int)
var xD, yD : int
if z < Camz then
xD := round ((CamzFrame - (z - (((z - Camz) / ((x - Camx) + 0.001)) * x))
/ ((z - Camz) / ((x - Camx) + 0.001))))
yD := round ((CamzFrame * ((y - Camy) / ((z - Camz) + 0.001))) + (y -
(((y - Camy) / ((z - Camz) + 0.001)) * z)))
end if
drawdot (xD, yD, 7)
end DrawParticle |
Also, on an unrelated note, if I have 3d structures connected by points, how can I avoid drawing everything behind the structure (for optimization). |
|
|
|
|
|
Sponsor Sponsor
|
|
|
Windsurfer
|
Posted: Tue Aug 15, 2006 8:32 pm Post subject: (No subject) |
|
|
It does work, but it's very complex. Start off from the simple stuff first. The basis of this type of 3D -> 3D proc is this:
code: |
var draw_x : int := x div z
var draw_y : int := y div z
|
Yes, it's that simple. Divide X and Y by Z.
Well, to begin with.
Then you have to add everyhting else in, like making the camera centered, rotating it, adjustments for Field-of-view, ect.
For a slightly more simplified version of this (and perhaps more usable? i don't know) I came up with a function that converts 3D stuff. I created all this from scratch, btw, so it may be wrong in some ways.
code: |
%this is the size of the screen
% i suppose i could have used maxx and maxy instead.
const X_SCREEN := 1024
const Y_SCREEN := 768
%middle of the screen in the X and Y axis so that the camera is centered
const SCR_W := X_SCREEN div 2
const SCR_H := Y_SCREEN div 2
%this is the "key dividor" amount... it makes something at a z coordinate
%perfectly align with the screen... just don't touch it
%I got to this value by experimentation
const Z_KEY_DIV := 350
var rotate_x, rotate_y, rotate_z : real := 0
var camera_pan_x, camera_pan_y, camera_pan_z : real := 0
%this rotates a 3D point( x1, y1, z1) around another point (origin) by a cetain number of degrees in each axis (xy, zy, zx).
%Keep in mind that this modifies the point. (uses var)
procedure Rotate_Point_3D (var x1 : real, var y1 : real, var z1 : real,
origin_x, origin_y, origin_z, xy, zy, zx : real)
var temp_x : real := x1 - origin_x
var temp_y : real := y1 - origin_y
var temp_z : real := z1 - origin_z
% zx plane
x1 := temp_x * cosd (zx) - temp_z * sind (zx) + origin_x
z1 := temp_x * sind (zx) + temp_z * cosd (zx) + origin_z
temp_x := x1 - origin_x
temp_z := z1 - origin_z
% zy plane
z1 := temp_z * cosd (zy) - temp_y * sind (zy) + origin_z
y1 := temp_z * sind (zy) + temp_y * cosd (zy) + origin_y
temp_z := z1 - origin_z
temp_y := y1 - origin_y
% xy plane
x1 := temp_x * cosd (xy) - temp_y * sind (xy) + origin_x
y1 := temp_x * sind (xy) + temp_y * cosd (xy) + origin_y
end Rotate_Point_3D
%this converts a 3D point into a 2D one and returns true if the conversion was successful
%xt and yt are the 2D coordinates
function Make3D (x1, y1, z1 : real, var xt, yt : int) : boolean
%create duplicate variables of the point and pan it
var x2 : real := x1 + camera_pan_x
var y2 : real := y1 + camera_pan_y
var z2 : real := z1 + camera_pan_z
Rotate_Point_3D (x2, y2, z2, SCR_W, SCR_H, 0, rotate_x, rotate_y, rotate_z)
if z2 > 1 then
xt := round ((x2 - SCR_W) / (z2 / Z_KEY_DIV) + SCR_W)
yt := round ((y2 - SCR_H) / (z2 / Z_KEY_DIV) + SCR_H)
result true %3d was successful
else
xt := 100
yt := 100
result false %3d was not successful
end if
end Make3D
|
This is fun because if you want to draw a black dot at a point, say 500,500,0, you just make a proc that does this:
code: |
var temp_x, temp_y : int
if Make_3D(500,500,0, temp_x, temp_y) then
drawdot(temp_x, temp_y, black)
end if
|
note: untested.
Simple, no? All rotations and panning is taken care of. Of course, there is then dealing with madifying the values accociated with that... maybe i should make a tutorial on this, considering so many people are interested... or maybe there already is one? hmm..... |
|
|
|
|
|
richcash
|
Posted: Tue Aug 15, 2006 10:40 pm Post subject: (No subject) |
|
|
Thanks, Windsurfer, you explained it very well. It seems to work great. Now, when I need to use 3d I'll just have to learn how to use your system to rotate and move the camera. As I said, I'm not really working on this just yet.
A tutorial would be great if we don't already have one, I think 3d is an interesting thing that is possible in Turing, but not too many people end up working with it! |
|
|
|
|
|
iker
|
Posted: Wed Aug 16, 2006 12:14 pm Post subject: (No subject) |
|
|
I've found this semi-simple algorithm to rotate a point in Zylums 3D engine, but had to refine it a bit to work for the 3d project I'm working on. This rotates the points from the camera's POV. pntX, pntY and pntZ are the original xyz points, then rotX, rotY, rotZ are the xyz points. xR yR and zR are the angles of rotation (0 .. 359). I haven't 100% figured out whats going on, but what I do know is that Zylum used 3D addition. Hopefully this helps, maby if someone wanted to expand on it a bit.
code: |
rotY := pntY * cosd (yR) - pntZ * sind (yR)
rotZ := pntZ * cosd (yR) + pntY * sind (yR)
temp := rotZ
rotZ := temp * cosd (xR) - pntX * sind (xR)
rotX := pntX * cosd (xR) + temp * sind (xR)
temp := rotX
rotX := temp * cosd (zR) - rotY * sind (zR)
rotY := rotY * cosd (zR) + temp * sind (zR)
pntX := rotX
pntY := rotY
pntZ := rotZ
|
|
|
|
|
|
|
richcash
|
Posted: Wed Aug 16, 2006 2:38 pm Post subject: (No subject) |
|
|
That's a fairly good algorithm, iker, I really like how you're rotating in 3 dimensions (or at least I think so). Perhaps I could combine yours and Windsurfer's, though they are very similar. I didn't even know zylum made a 3d particle engine, now I have more resources! I think I'm finally understanding these types of systems and the mathematics behind them, thanks for your input! |
|
|
|
|
|
Windsurfer
|
Posted: Wed Aug 16, 2006 9:17 pm Post subject: (No subject) |
|
|
richcash wrote: That's a fairly good algorithm, iker, I really like how you're rotating in 3 dimensions (or at least I think so). Perhaps I could combine yours and Windsurfer's, though they are very similar.
Yes, they are very similar... in fact, i think they're the same, apart from the fact that mine rotates around an origin, and not just (0,0,0). |
|
|
|
|
|
|
|