
-----------------------------------
richcash
Tue Aug 15, 2006 5:44 pm

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 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).

-----------------------------------
Windsurfer
Tue Aug 15, 2006 8:32 pm


-----------------------------------
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:

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.



%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:


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
Tue Aug 15, 2006 10:40 pm


-----------------------------------
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
Wed Aug 16, 2006 12:14 pm


-----------------------------------
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. 

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
Wed Aug 16, 2006 2:38 pm


-----------------------------------
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
Wed Aug 16, 2006 9:17 pm


-----------------------------------
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).
