Hi,
James Richters wrote 8 lines
What I'm trying to do is much simpler than rendering a 3D object.. All
I'm trying to do is display a 3D line drawing or wireframe on the
screen. I don't need it to dynamically rotate or anything, and it
doesn't need to show any surfaces, textures, lighting, reflections, or
shadows, just give a representation of the XYZ points and lines
connecting 2 pair of XYZ coordinates on the screen. The purpose of this
is to show a 3D representation of a CNC tool path including the Z
movements.
Well, it all boils down to the projection you want to make while you transform from your coordinates from 3D to 2D. For the most simple "isometric" projection with no perspective, you just throw away one of the XYZ coordinates, and use the other two - this will result in a simple "camera" which views at your object from either the front (XY), side (YZ) or from the top (XZ). (Actually, this also depends on wether in your coordinate system Y or Z represents depth, 3D editors/engines don't even agree on this one, the code below assumes "Z" is depth.)
For a simple "perspective" projection, you can use a simplistic formula, something like:
{ untested pseudocode }
procedure perspective_vertex(const v: T3DVertex; ZCenter: single;
out X, Y: single);
var
rdist1: single;
begin
zdist1:=1.0 / (v.z - zcenter);
X:=(v.x * zcenter) * zdist1;
Y:=(v.y * zcenter) * zdist1;
end;
This will put some sort of "perspective" on your 3D vertex, depending on its Z coordinate. The ZCenter should be larger than the maximum dimension of your object facing the "camera". Note that this formula is massively simplified, but serves as the most simple perspective projection.
After this, you can use x/y coordinates to feed the wireframe drawer using whatever drawing unit you see fit. You might need to do inc(x,width/2); and inc(y,height/2); and/or multiply your values with a certain scale-factor, depending on the size of your object, and how its coordinates map to your 2D resolution.
All of the above methods assume that your object's 3D center resides at the origo (center of the coordinate system). Anything more complicated would require some proper matrices to be set up and calculate a full series of model, view, and projection matrices, as others have already mentioned, or would require pre-processing your 3D coordinates in a certain way, so this simplistic formula can work.
Hope this helps,
Charlie
(Ps: actually, the FPC Packages contain two similar examples of a rotating
3D cube, for PalmOS and Atari, both written by me, to showcase the m68k
code generator and the units for these retro/niche OSes. They're at (SVN
trunk):
- packages/tosunits/examples/gemcube.pas
- packages/palmunits/examples/palmcube.pas
Showcased here (with video):
https://twitter.com/chainq/status/945010617672523777
https://twitter.com/chainq/status/948865605209387010
These show this most simplistic form of 3D calculation, and they also use
fixed point math, as that fit the only a few mhz fast 68000 CPUs in these
machines. But the basic algo and formula is the same with float and on
faster platforms. Now I'm quite tempted to make a ptc-graph version. :) )