Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2019-09

Calculating Pixels to represent 3D coordinates

15 messages · 10 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

James Richters

I'm curious if Freepascal has any package available that would calculate X,Y screen pixels based on 3D X,Y,Z data at some given rotations. I'm using Agg-Pas with PTC-Graph in a console application on Windows. I'm not sure what the technical term is for figuring out what pixels are used to represent 3D coordinates on a 2D screen, but I'm hoping maybe there is something that just does the calculations that I can use in conjunction with Agg-Pas and PTC-Graph instead of moving to a complete graphics package.

James

Reply by email

Sven Barth
to James Richters

James Richters schrieb am Di., 17. Sep.
2019, 16:15:

Show quoted text 8 lines
I'm curious if Freepascal has any package available that would calculate X,Y screen pixels based on 3D X,Y,Z data at some given rotations. I'm using Agg-Pas with PTC-Graph in a console application on Windows. I'm not sure what the technical term is for figuring out what pixels are used to represent 3D coordinates on a 2D screen, but I'm hoping maybe there is something that just does the calculations that I can use in conjunction with Agg-Pas and PTC-Graph instead of moving to a complete graphics package.

You're essentially looking for a software renderer/rasterizer. Lookup things like projection matrix and model view matrix.

You can also take a look at the "Ray Tracing in one weekend" books ( https://github.com/RayTracing/raytracing.github.io ) to get a feeling for what's required.

In the end you might be better served to use a graphics package or at least OpenGL.

Regards,
Sven

Reply by email

Mgr. Janusz Chmiel
to Sven Barth

Please would somebody of us try to tell Me, if Android API functions can detect how many fingers have been used to touch The display even while Talkback screen reader work ane Explore by touch service is communicating with display? I do not want to use graphical mode, since it require that Talkback screen reader must be turned off. One developer, who have used Java language used some technique, which could detect how many fingers have been used to shift from down to up. If one or two. Thank you very much for yours tips how to detect this specific touch events when Talkback is running.

Reply by email

Thomas Young
to Mgr. Janusz Chmiel

Hi,
Years ago I had a career as a technical illustrator. First analog then digital. Perhaps the following code I developed back around 1992 might be helpful to you.

H = Horizontal coordinate on picture plane.

V = Vertical coordinate on picture plane.

XYZ = 3D coordinate.

distance = "camera" distance from the model:
a range of values [0..15000] (logrithmic).

height = "camera" height from 0 ground plane.

H := scale * (X * distance / (Y + distance)) + H_offset;
V := scale * ((Z - height) * D / (Y + distance)) + Y_offset;

Thomas Young
330-256-7064
Sent from my iPhone

Show quoted text 7 lines
On Sep 17, 2019, at 11:20 AM, Mgr. Janusz Chmiel wrote: Please would somebody of us try to tell Me, if Android API functions can detect how many fingers have been used to touch The display even while Talkback screen reader work ane Explore by touch service is communicating with display? I do not want to use graphical mode, since it require that Talkback screen reader must be turned off. One developer, who have used Java language used some technique, which could detect how many fingers have been used to shift from down to up. If one or two. Thank you very much for yours tips how to detect this specific touch events when Talkback is running. _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Graeme Geldenhuys
to James Richters: I'm curious if Freepascal has any package available that would calculate X,Y screen…
James Richters wrote
I'm not sure what the technical term is for figuring out what pixels are used to represent 3D coordinates on a 2D screen, but I'm hoping maybe there is something that just does the calculations that I can use

https://en.wikipedia.org/wiki/Ray_tracing_(graphics)

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Ryan Joseph
to James Richters: I'm curious if Freepascal has any package available that would calculate X,Y screen…

What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space?

On Sep 17, 2019, at 10:10 AM, James Richters wrote: I'm curious if Freepascal has any package available that would calculate X,Y screen pixels based on 3D X,Y,Z data at some given rotations. I'm using Agg-Pas with PTC-Graph in a console application on Windows. I'm not sure what the technical term is for figuring out what pixels are used to represent 3D coordinates on a 2D screen, but I'm hoping maybe there is something that just does the calculations that I can use in conjunction with Agg-Pas and PTC-Graph instead of moving to a complete graphics package.

Regards,
Ryan Joseph

Reply by email

James Richters
to Ryan Joseph
What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space?

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.

James

Reply by email

Gustavo Enrique Jimenez
to James Richters

A simple transformation is:

P3D=(X,Y,Z)
P2D=(x,y)

x=X+Y*0.707
y=Y*0.707+Z

I did not tried it, but I think that this is the transformation that you are looking for.

Gustavo

James Richters wrote 9 lines
>What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space? 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. James _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Thomas Young
to Gustavo Enrique Jimenez
This is an isometric projection I use:
var H1 = (Y - X) * 0.86602 + ScreenOrgin_H;
var V1 = (X + Y) * 0.5 - Z + ScreenOrgin_V;

Thomas Young
330-256-7064
Sent from my iPhone

Show quoted text 30 lines
On Sep 17, 2019, at 4:53 PM, Gustavo Enrique Jimenez wrote: A simple transformation is: P3D=(X,Y,Z) P2D=(x,y) x=X+Y*0.707 y=Y*0.707+Z I did not tried it, but I think that this is the transformation that you are looking for. Gustavo El mar., 17 sept. 2019 a las 17:37, James Richters () escribió: > >> What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space? > > 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. > > James > _______________________________________________ > fpc-pascal maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Wolf
to James Richters: I'm curious if Freepascal has any package available that would calculate X,Y screen…

What you are trying to do is write a very simple CAD program. Have a look at this link
<https://www2.mathematik.tu-darmstadt.de/~ehartmann/cdgen0104.pdf>, which gives the basic formulae and also Pascal routines to do it.

Wolf

James Richters wrote 6 lines
I'm curious if Freepascal has any package available that would calculate X,Y screen pixels based on 3D X,Y,Z data at some given rotations. I'm using Agg-Pas with PTC-Graph in a console application on Windows. I'm not sure what the technical term is for figuring out what pixels are used to represent 3D coordinates on a 2D screen, but I'm hoping maybe there is something that just does the calculations that I can use in conjunction with Agg-Pas and PTC-Graph instead of moving to a complete graphics package. James _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Karoly Balogh (Charlie/SGR
to James Richters: What I'm trying to do is much simpler than rendering a 3D object.. All I'm trying to do…

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. :) )

Reply by email

James Richters
to Thomas Young: This is an isometric projection I use: var H1 = (Y - X) * 0.86602 + ScreenOrgin_H; var V1…

Thank you for the help and suggestions with this. After playing with the suggested formulas I was able to figure out how they work... The solution to this is probably somewhere but I ended up just doing it myself.

I realized that Thomas' formula
var H1 = (Y - X) * 0.86602 + ScreenOrgin_H; var V1 = (X + Y) * 0.5 - Z + ScreenOrgin_V; was multipying by the cosine of 30 degrees for H1 and the Sine of 30 degrees for V1....

and Gustavo's forumla was basically the same thing but multiplying by the cosine and sine of 45 degrees...

so I realized that all I really want to do has nothing to do with camera angles, or projections or anythng else... I just strictly need do the 3D rotations then just display the resulting X, and Y coordinate and ignore Z. My original 2D representaion showing only X and Y is as if I am looking perfectly straight down at it.. so I can't see the Z only lines, but after I perform the 3D rotations now I can see the Z component as they end up being represented on the X and Y axis.... but I still act like I am still looking straight down at it, so I only plot X and Y. I checked the results of my formula against my CAD program everything looks EXACTLY the same no matter how I change the rotations, so this must be what the CAD program is doing as well.

Here are the formula I came up with that allows me to adjust the 3 possible rotations, A - rotating around the X axis, B rotating around the Y axis, and C rotating around the Z axis.

X1 - initial X coordinate
Y1 - initial Y coordinate
Z1 - initial Z coordinate
X2 - output X coordinate
Y2 - output Y coordinate

//XY Rotation - only rotates X and Y around the Z axis (C Rotation)
  XC_Point := ((CoSine(C_Angle) * (X1-XC_Center)) - (Sine(C_Angle) * (Y1-YC_Center) )) + XC_Center;
  YC_Point := ((CoSine(C_Angle) * (Y1-YC_Center)) + (Sine(C_Angle) * (X1-XC_Center) )) + YC_Center;
  ZC_Point :=Z1;
//XZ Rotation - only rotates X and Z around the Y axis (B Rotation)
  XB_Point := ((CoSine(B_Angle) * (XC_Point-XB_Center)) + (Sine(B_Angle) * (ZC_Point-ZB_Center) )) + XB_Center;
  YB_Point := YC_Point;
  ZB_Point :=  ((CoSine(B_Angle) * (ZC_Point-ZB_Center)) - (Sine(B_Angle) * (XC_Point-XB_Center) )) + ZB_Center;
//YZ Rotation  - only rotates Y and Z around the X axis (A Rotation)
  XA_Point := XB_Point;
  YA_Point := ((CoSine(A_Angle) * (YB_Point-YA_Center)) - (Sine(A_Angle) * (ZB_Point-ZA_Center) )) ;
  ZA_Point := ((CoSine(A_Angle) * (XB_Point-XA_Center)) + (Sine(A_Angle) * (ZB_Point-ZA_Center) )) + XA_Center;     // useless to plot point, just for information
X2 := Scale * XA_Point+X_Offset;
Y2 := Scale * YA_Point+Y_Offset;

Notes:

My fuctions CoSine and Sine convert the angle to radians from given degrees.

I have my 0,0 located in the lower left hand corner, but PTC-Graph has it in the upper left corner.. I used the above formula before the section that takes care of getting it on the screen, I don't know if some adjustment would be nessecary for use on direct screen coordinates... things might end up upside down, or the rotations might need to be reversed by switching the + and - between CoSine and Sine because of this..

Thank you again for all the help and suggestions. I also found the websites and books on the subject very interesting as well.

James

Earlier message 45 lines
-----Original Message----- From: fpc-pascal On Behalf Of Thomas Young via fpc-pascal Sent: Tuesday, September 17, 2019 5:00 PM To: FPC-Pascal users discussions Cc: Thomas Young Subject: Re: [fpc-pascal] Calculating Pixels to represent 3D coordinates This is an isometric projection I use: var H1 = (Y - X) * 0.86602 + ScreenOrgin_H; var V1 = (X + Y) * 0.5 - Z + ScreenOrgin_V; Thomas Young 330-256-7064 Sent from my iPhone > On Sep 17, 2019, at 4:53 PM, Gustavo Enrique Jimenez wrote: > > A simple transformation is: > > P3D=(X,Y,Z) > P2D=(x,y) > > x=X+Y*0.707 > y=Y*0.707+Z > > I did not tried it, but I think that this is the transformation that > you are looking for. > > > Gustavo > > El mar., 17 sept. 2019 a las 17:37, James Richters > () escribió: >> >>> What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space? >> >> 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. >> >> James >> _______________________________________________ >> fpc-pascal maillist - >> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > _______________________________________________ > fpc-pascal maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Thomas Young
to James Richters

James, are you not applying the rotation universally to all coordinates? If so, you are better off pre-calculating your directional sines and cosines. For example:
TH: REAL; {ROTATIONS (in degrees) AROUND Z-AXIS BY theta, LEFTRIGHT-> turn its back to us}

PHI: REAL; {ROTATIONS (in degrees) AROUND X-AXIS BY phi, UPDOWN-> a nod}

PSI: REAL; {ROTATIONS (in degrees) AROUND Y-AXIS BY psi, SPIN-> a clock face} P
STH: REAL;{SIN(TH * (PI / 180)), CONVERT DEGREES TO RADIANS} CTH: REAL;{COS(TH * (PI / 180)), CONVERT DEGREES TO RADIANS} STI: REAL;{SIN(PHI * (PI / 180)), CONVERT DEGREES TO RADIANS} CTI: REAL;{COS(PHI * (PI / 180)), CONVERT DEGREES TO RADIANS} STS: REAL;{SIN(PSI * (PI / 180)), CONVERT DEGREES TO RADIANS} CTS: REAL;{COS(PSI * (PI / 180)), CONVERT DEGREES TO RADIANS}

Thomas Young
330-256-7064
Sent from my iPhone

Show quoted text 98 lines
On Sep 19, 2019, at 12:38 PM, James Richters wrote: Thank you for the help and suggestions with this. After playing with the suggested formulas I was able to figure out how they work... The solution to this is probably somewhere but I ended up just doing it myself. I realized that Thomas' formula var H1 = (Y - X) * 0.86602 + ScreenOrgin_H; var V1 = (X + Y) * 0.5 - Z + ScreenOrgin_V; was multipying by the cosine of 30 degrees for H1 and the Sine of 30 degrees for V1.... and Gustavo's forumla was basically the same thing but multiplying by the cosine and sine of 45 degrees... so I realized that all I really want to do has nothing to do with camera angles, or projections or anythng else... I just strictly need do the 3D rotations then just display the resulting X, and Y coordinate and ignore Z. My original 2D representaion showing only X and Y is as if I am looking perfectly straight down at it.. so I can't see the Z only lines, but after I perform the 3D rotations now I can see the Z component as they end up being represented on the X and Y axis.... but I still act like I am still looking straight down at it, so I only plot X and Y. I checked the results of my formula against my CAD program everything looks EXACTLY the same no matter how I change the rotations, so this must be what the CAD program is doing as well. Here are the formula I came up with that allows me to adjust the 3 possible rotations, A - rotating around the X axis, B rotating around the Y axis, and C rotating around the Z axis. X1 - initial X coordinate Y1 - initial Y coordinate Z1 - initial Z coordinate X2 - output X coordinate Y2 - output Y coordinate //XY Rotation - only rotates X and Y around the Z axis (C Rotation) XC_Point := ((CoSine(C_Angle) * (X1-XC_Center)) - (Sine(C_Angle) * (Y1-YC_Center) )) + XC_Center; YC_Point := ((CoSine(C_Angle) * (Y1-YC_Center)) + (Sine(C_Angle) * (X1-XC_Center) )) + YC_Center; ZC_Point :=Z1; //XZ Rotation - only rotates X and Z around the Y axis (B Rotation) XB_Point := ((CoSine(B_Angle) * (XC_Point-XB_Center)) + (Sine(B_Angle) * (ZC_Point-ZB_Center) )) + XB_Center; YB_Point := YC_Point; ZB_Point := ((CoSine(B_Angle) * (ZC_Point-ZB_Center)) - (Sine(B_Angle) * (XC_Point-XB_Center) )) + ZB_Center; //YZ Rotation - only rotates Y and Z around the X axis (A Rotation) XA_Point := XB_Point; YA_Point := ((CoSine(A_Angle) * (YB_Point-YA_Center)) - (Sine(A_Angle) * (ZB_Point-ZA_Center) )) ; ZA_Point := ((CoSine(A_Angle) * (XB_Point-XA_Center)) + (Sine(A_Angle) * (ZB_Point-ZA_Center) )) + XA_Center; // useless to plot point, just for information X2 := Scale * XA_Point+X_Offset; Y2 := Scale * YA_Point+Y_Offset; Notes: My fuctions CoSine and Sine convert the angle to radians from given degrees. I have my 0,0 located in the lower left hand corner, but PTC-Graph has it in the upper left corner.. I used the above formula before the section that takes care of getting it on the screen, I don't know if some adjustment would be nessecary for use on direct screen coordinates... things might end up upside down, or the rotations might need to be reversed by switching the + and - between CoSine and Sine because of this.. Thank you again for all the help and suggestions. I also found the websites and books on the subject very interesting as well. James -----Original Message----- From: fpc-pascal On Behalf Of Thomas Young via fpc-pascal Sent: Tuesday, September 17, 2019 5:00 PM To: FPC-Pascal users discussions Cc: Thomas Young Subject: Re: [fpc-pascal] Calculating Pixels to represent 3D coordinates This is an isometric projection I use: var H1 = (Y - X) * 0.86602 + ScreenOrgin_H; var V1 = (X + Y) * 0.5 - Z + ScreenOrgin_V; Thomas Young 330-256-7064 Sent from my iPhone > On Sep 17, 2019, at 4:53 PM, Gustavo Enrique Jimenez wrote: > > A simple transformation is: > > P3D=(X,Y,Z) > P2D=(x,y) > > x=X+Y*0.707 > y=Y*0.707+Z > > I did not tried it, but I think that this is the transformation that > you are looking for. > > > Gustavo > > El mar., 17 sept. 2019 a las 17:37, James Richters > () escribió: >> >>> What exactly are you trying to do? Usually if you’re doing 3D this all happens on the GPU and you get back a color/depth buffer. Maybe you need to know where a 2D coordinate is in 3D space? >> >> 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. >> >> James >> _______________________________________________ >> fpc-pascal maillist - >> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > _______________________________________________ > fpc-pascal maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

James Richters
to Jean SUZINEAU

Thanks for the Tip! I had no idea there was a single function that would return both sine and cosine.

Earlier message 12 lines
-----Original Message----- From: fpc-pascal On Behalf Of Jean SUZINEAU Sent: Friday, September 20, 2019 8:01 PM To: Subject: Re: [fpc-pascal] Calculating Pixels to represent 3D coordinates Tip: if you need Sin(A) and Cos(A), it can be faster to make a single call to SinCos instead of two separated calls to Sin and Cos: https://www.freepascal.org/docs-html/rtl/math/sincos.html It was efficient 20 years ago when I was developing a sky map software, may be the gain is negligible today.

Reply by email