Simple Perspective program (included) lazarus / 39-Graphics ---------------------------------------------------------------------- speter · 2020-12-16 03:15 Happy Christmas etc everyone Attached is a simple perspective program (which I have written), which might be interesting for anyone who doesn't know how to draw a perspective digitally. It loads a scene file ("hut.per", included in the ZIP); and allows the user to move around. The program uses Cartesian coordinates. The perspective is drawn using a Z-sort system. It doesn't do any lighting calcs; and doesn't include any monsters. I think it is about as comparable to something like the Castle game engine as a bicycle compares to a Ferrari. But, in it is kinda cool. I hope you enjoy it. The scene file format is really simple, open "hut.per" in a text editor... I've tested the program with windows 10 (Laz 2.0.8, FPC 3.0.4); but I don't think there are any windows dependencies, so it should run in other OS's. I'd be interested to hear any feedback you might have (esp if using another OS). cheers S. [Deleted ZIP -author request] ---------------------------------------------------------------------- Handoko · 2020-12-16 03:27 Wow, it works. Just opened and run it on my Linux computer. You must be good in math. You wrote the program without using OpenGL nor DirectX. I ever did such attempt long time ago. It only showed some boxes in wireframe mode and that run very slow on 386 machine. Yours is much better. Awesome. Thank you for sharing the code. Merry Christmas and Happy New Year ! ---------------------------------------------------------------------- trev · 2020-12-16 03:58 Compiled on macOS (aarch64) - the application runs, it loads the file (tested; incorrect filename causes error), coordinates are filled in, but nothing appears in the window. ---------------------------------------------------------------------- speter · 2020-12-16 04:28 Thanks Handoko & trev, @ Handoko: I wrote my first perspective program in 1984 on an Intell 8088 (aka an ancient [pre-IBM) PC; using graphics routines written in assembler (by someone else). It used to take 5 minutes to render a simple scene like the hut. @trev: "incorrect filename causes error" - can you tell me what you mean by this? Wasn't "hut.per" correct (there should be a text file named "hut.per" in the source folder)? Regarding it not drawing (I am assuming you got past the first error); the program basically uses canvas.polygon() to draw the scene - I would have thought that that would be implemented!? If you didn't get past the "incorrect filename" error, then the program wouldn't draw anything. cheers S. ---------------------------------------------------------------------- trev · 2020-12-16 04:38 I resolved the incorrect filename error (macOS cannot locate the file) by dragging it from Finder into the filename edit box at which point it does appear to load as the coordinates appear in the edit boxes, but nothing is drawn and there is no further error and nothing of any consequence in the macOS system logs. I'll try on the Intel macOS machine as soon as it finishes fscking my corrupted 8TB Time Machine backup... it may be a while ---------------------------------------------------------------------- speter · 2020-12-16 06:55 Does anyone out there have experience with drawing on a canvas in macOS? @trev could you please do a little test!? Create a new (application) project and place a paintbox on the form (and optionally set the paintbox property align=alclient). Then add an OnPaint event to the paintbox with the following code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.PaintBox1Paint(Sender: TObject);var  a : integer;  poly : array of tpoint;begin  randomize;  setlength(poly,4);  for a := 0 to 3 do  poly[a] := point(random(paintbox1.width),random(paintbox1.height));  paintbox1.canvas.brush.style := bssolid;  paintbox1.canvas.brush.color := tcolor(random(1 shl 25));  paintbox1.canvas.polygon(poly);end;This code assumes your paintbox is called "paintbox1". This should draw a random 4 sided polygon on the paintbox; and draw a new poly if you resize the application etc. If this works, then it suggests the error is in my program... cheers S. ---------------------------------------------------------------------- trev · 2020-12-16 08:07 Yes! Your basic polygon onpaint application works on macOS. ---------------------------------------------------------------------- speter · 2020-12-16 10:34 Tomorrow, I'll put together a version using the file-open dialog; hopefully that will play-better with the macOS, look for it in about 14 hours. ---------------------------------------------------------------------- speter · 2020-12-17 00:55 G'Day Folks, Attached to this message is a new version of my perspective program. Changes include:     + added Form_info_panel and "Info Panel" checkbox.     + removed scene filename edit box, replaced with "Open (hut)" button.     + added "Open..." button (which uses the File-Open Dialog).           ^^ uses paramstr(0) to set opendialog1.InitialDir     + changed optimisation level from 3, down to 1 I still can't see why trev's Mac was having trouble drawing the scene!? Also, I am unsure whether paramstr(0) works in non Windows' OSs!? So, if you have issues with that, comment out that code - the first line in TForm1.Button_file_openClick(). The first button in the Info Panel is "Summary"; on my computer this gives: QuoteSummary -------------- Description: hut Orig Eye Pt: 10.000 -10.000 5.000 Orig Target Pt: 3.500 2.000 2.000 Current Eye Pt: 10.000 -10.000 5.000 Current Target Pt: 3.500 2.000 2.000 Num Faces: 26 Num Points: 51 Num Screen Pts: 51 Paitnbox (w,h): 774,868 Once "hut.per" is opened all those values should be the same (except maybe the paintbox dimension - if the user has resized the application window or the OS makes the program form a different size etc). All the points should range from (-3, -5, -0.2) - (10, 7, 3.7). The "screen points" should range from (0,0) - (paintbox.width-1, paintbox.height-1). If the program works ok, I'd suggest compiling with optimisation level 2 or 3. I'd really like to hear from macOS folks, about their experiences.  cheers S. Edit: Corrected the points' extents. [Deleted ZIP -author request] ---------------------------------------------------------------------- speter · 2020-12-17 01:59 @Handoko: If you are interested in the math; have a look at scene.draw() - both in sceneu.pas. cheers S. ---------------------------------------------------------------------- Handoko · 2020-12-17 02:24 Of course I will. I can do some simple perspective drawing using OpenGL and DirectX but I always wonder how it can be done manually. Quote from: speter on December 17, 2020, 01:55:07 amAlso, I am unsure whether paramstr(0) works in non Windows' OSs!? Both the open buttons work correctly on Linux. There were some discussions about it, maybe you will be interested: https://forum.lazarus.freepascal.org/index.php/topic,34273.0.html https://forum.lazarus.freepascal.org/index.php/topic,51692.0.html Quote from: speter on December 17, 2020, 01:55:07 am    + changed optimisation level from 3, down to 1 It runs without problem using level 4 optimization on Lazarus 2.0.10 GTK2 Ubuntu 20.04 64-bit, below is the screenshot. One small issue is, Ubuntu use relatively large font by default. You should reduce the font size or make the buttons a bit bigger. ---------------------------------------------------------------------- trev · 2020-12-17 10:51 1. paramstr(0) shouldn't be used for any UNIX or UNIX-like OS for the reasons detailed here. 2. The Open File dialog currently initialises to the folder containing the executable which, because of the macOS application bundle concept is in my case: /Users/trev/Documents/Programming/LAZPROJECTS/laz_persp /persp.app/Contents/MacOS. To locate the bundle folder's folder, see this Wiki page. 3. This time I compiled it on the Intel Mac mini and the result was the same as before on the ARM64 Mac mini - nothing gets drawn on the paintbox. I've included a screen capture with the info panel displayed after loading the file. 4. I noticed a typo (transposition) in the info panel summary "Paitnbox". ---------------------------------------------------------------------- speter · 2020-12-17 11:16 Thanks Handoko & trev for your time and effort. Both of you noted I shouldn't use Paramstr(0). So, I guess I should remove that. @trev: do you have any idea what's happening here!? Does anything get drawn if you check "wire"? I had thought that maybe I hadn't set the length of one of the arrays, but they all seem ok. cheers S. Edit: removed list of screen coords. ---------------------------------------------------------------------- circular · 2020-12-17 11:19 To display something on MacOS (and on Qt) you must draw in the OnPaint event, never outside of it. So when you want to redraw, you can for example call Invalidate and in the OnPaint event call the drawing method. To get the location of your program, you can use Application.ExeName. ---------------------------------------------------------------------- speter · 2020-12-17 11:55 Thanks very much circular! I will need to think that through in the morning. I'll hopefully post a another version in 12 hours or so. When I moved scene.draw() to the paintbox1.onpaint method (and replaced other scene.draw() instances with paintbox1.invalidate), the program endlessly redraws the scene. So (clearly) I am triggering the event again somewhere. cheers S. ---------------------------------------------------------------------- circular · 2020-12-17 13:37 Did you put a call to Invalidate in the OnPaint event? This could make it refresh forever. ---------------------------------------------------------------------- speter · 2020-12-17 14:20 Quote from: circular on December 17, 2020, 02:37:13 pmDid you put a call to Invalidate in the OnPaint event? This could make it refresh forever. No, I had a "refresh" at the start of scene.draw cheers S. ---------------------------------------------------------------------- speter · 2020-12-17 14:27 OK, this time I have two versions of my program! One (at least) should work in macOS. The first (version 1.11b) moves the call to scene.draw into paintbox1paint. The second (version 1.11c) moves the drawing code from the scene and face objects into paintbox1paint. I hope version 1.11b works! Once again, I'd really like to hear people's experiences, especially the poor folk with fruity computers.  cheers S. PS: now I'm really heading off to try to get some sleep on this warm summer night. [Deleted ZIPs -author request] ---------------------------------------------------------------------- circular · 2020-12-17 19:06 Cool  I confirm v1.11b works fine on fruity computers. ---------------------------------------------------------------------- tetrastes · 2020-12-17 20:30 Nice program  Both versions work now on Linux qt5, not only gtk2. But behaviour is different: 1. With qt5 you may keep "move" key pressed, and scene rotates, while with gtk2 you have to press key for each "turn". 2. With qt5 adding data in Info Panel window by pressing buttons does not move list to the end, as it does with gtk2. And you have to rid off the mess of "move" keys with navigation and editing of controls at Panel1. ---------------------------------------------------------------------- winni · 2020-12-17 20:51 Thanx! Nice programm. Not to mention the "transparent gras" Nice feature And about the hot summer night: Only some days to the winter solstice. And then our days are getting longer. And yours getting shorter ... Winni ---------------------------------------------------------------------- trev · 2020-12-17 22:25 Eureka! V1.1b works perfectly on macOS 11.1 (aarch64) and macOS 10.14.6 (Intel). Just one small thing, the far right button "Reset Eye/Tar" is truncated immediately after "Eye". ---------------------------------------------------------------------- speter · 2020-12-18 02:49 G'Day FOlks, My thanks to everyone - especially Handoko, trev & Circular. I've posted a new version of my perspective program here; and will delete the earlier versions (assuming I can delete attachments). 2020-12-18 v.1.12   + moved the "instructions" to the info-panel form   + program now calcs button-width based on caption text   + numbers typed in the Tedit's no longer rotate the view. Quote from: tetrastes on December 17, 2020, 09:30:44 pmNice program  Both versions work now on Linux qt5, not only gtk2. But behaviour is different: 1. With qt5 you may keep "move" key pressed, and scene rotates, while with gtk2 you have to press key for each "turn". 2. With qt5 adding data in Info Panel window by pressing buttons does not move list to the end, as it does with gtk2.@tetrastes: (1) In Windows 10 the user needs to press the move key to rotate (holding it down does nothing). So the performance with qt5 is what I'd expect. (2) I don't know how to scroll a memo to then end (except in Windows via a windows-message); I haven't included any code to scroll to the end of the memo; so again the behaviour with qt5 is what I would expect. cheers S. Edit: I can't work out how to delete the previous ZIP files. ---------------------------------------------------------------------- trev · 2020-12-18 07:13 1. The last button text is truncated. 2. The Open dialog again takes me to the executable folder inside the macOS Application bundle 3. No way to get back the instructions after clearing the Info Panel . It does work very nicely though I've deleted the previous zips for you. ---------------------------------------------------------------------- tetrastes · 2020-12-18 10:18 Quote from: speter on December 18, 2020, 03:49:31 am Quote from: tetrastes on December 17, 2020, 09:30:44 pmNice program  Both versions work now on Linux qt5, not only gtk2. But behaviour is different: 1. With qt5 you may keep "move" key pressed, and scene rotates, while with gtk2 you have to press key for each "turn". 2. With qt5 adding data in Info Panel window by pressing buttons does not move list to the end, as it does with gtk2.@tetrastes: (1) In Windows 10 the user needs to press the move key to rotate (holding it down does nothing). So the performance with qt5 is what I'd expect. (2) I don't know how to scroll a memo to then end (except in Windows via a windows-message); I haven't included any code to scroll to the end of the memo; so again the behaviour with qt5 is what I would expect. I tested your last version in Windows 10, and it behaves like gtk2, not qt5. May be my English is bad... By the way, auto rotation at qt5 looks very nice  In your last version, if you use arrow keys to rotate, sooner or later you come to one of TEdits, and then rotation stops, until you leave TEdit somehow. ---------------------------------------------------------------------- speter · 2020-12-18 10:47 G'Day Folks, @trev: Thanks very much for deleting the old zips. @tetrastes: Thanks for your comments! I am not sure what you mean by your last sentence though (... sooner or later you come to one of Tedits...)? Attached to this message is version 1.13 in persp.zip.   + setting the forms' width to fit all the buttons etc   + added "instructions" button to Info-Panel form.   + adjusting the height of panel1 (the button container) to fit the captions.   + I also tweaked some of the colours in the hut scene. I am not sure how to set the file-open dialog's initial directory, so that it works in Windows, Linux & macOS. cheers S. ---------------------------------------------------------------------- tetrastes · 2020-12-18 11:13 Quote from: speter on December 18, 2020, 11:47:53 am@tetrastes: Thanks for your comments! I am not sure what you mean by your last sentence though (... sooner or later you come to one of Tedits...)? Did you ever notice that pressing arrow keys also navigates through the controls of Panel1? ---------------------------------------------------------------------- trev · 2020-12-18 23:56 Quote from: speter on December 18, 2020, 11:47:53 amI am not sure how to set the file-open dialog's initial directory, so that it works in Windows, Linux & macOS. This works for me: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, Math,  spworld, sceneu, infou  {$IFDEF Darwin}  ,macOSAll  {$ENDIF}  ; Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$IFDEF Dar win}//---------------------------------------------------------- function GetBundlePath(): string;//----------------------------------- -----------------------var  pathRef: CFURLRef;  pathCFStr: CFStringRef;  pathStr: shortstring;  status: Boolean = false;begin  pathRef := CFBundleCopyBundleURL(CFBundleGetMainBundle());  pathCFStr := CFURLCopyFileSystemPath(pathRef, kCFURLPOSIXPathStyle);   status := CFStringGetPascalString(pathCFStr, @pathStr, 255, CFStringGetSystemEncoding());   if(status = true) then    Result := pathStr  else    raise Exception.Create('Error in GetBundlePath()');end;{$ENDIF} Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i //----------------------------------------------------------procedure TForm1.Button_file_openClick(Sender: TObject);//---------------------- ------------------------------------begin  {$IF DEFINED(Windows)}  opendialog1.InitialDir:=ExtractFilePath(ParamStr(0));  {$ELSEIF DEFINED(Darwin)}  opendialog1.InitialDir:=ExtractFilePath(GetBundlePath);  {$ELSEIF DEFINED(UNIX)}  opendialog1.InitialDir:='.';  {$ENDIF}   if opendialog1.execute then    file_open(opendialog1.filename);end;   I've checked macOS but not the rest (my VMs are currently out of action). ---------------------------------------------------------------------- speter · 2020-12-18 23:57 Quote from: tetrastes on December 18, 2020, 12:13:27 pmQuote from: speter on December 18, 2020, 11:47:53 am@tetrastes: Thanks for your comments! I am not sure what you mean by your last sentence though (... sooner or later you come to one of Tedits...)? Did you ever notice that pressing arrow keys also navigates through the controls of Panel1? No! Actually, I don't use "arrow" keys... that's horrible! I guess I'll need to remove the TEdits from the tab-stop sequence. Thanks for letting me know!! cheers S. ---------------------------------------------------------------------- speter · 2020-12-19 04:39 G'Day Folks, Once again, my thanks to everyone for their help in sorting out "features".  In particular:   @trev: a big thank-you for the code to set file-open's initial directory;   @tetrastes: I had no idea Laz (and presumably Delphi) made the arrow keys act like Tab;       also I had no idea setting tabstop=false had so little effect. Attached to this message you will find v1.14 (persp.zip). 2020-12-19 v.1.14   + added code from user 'trev' to set file-open's initial directory   + changed eye / tar Tedits into Tlabel   + "GoTo" button now shows a dialog to set the eye / tar.   + tweaked the GUI - moved GoTo button & eye / tar pos label to separate panel.   + made the program's main-form initial size at bit smaller (1000x750px). cheers S. ---------------------------------------------------------------------- Handoko · 2020-12-19 05:38 Quote from: speter on December 19, 2020, 05:39:05 amI had no idea setting tabstop=false had so little effect. It can be solved by set the Key to 0 in the OnKeyDown event. Tested on Linux GTK2, it works. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState  );begin  if (Key in [37..40, 49..57, 97..105]) then Key := 0;end; ---------------------------------------------------------------------- trev · 2020-12-19 05:59 Quote from: Handoko on December 19, 2020, 06:38:05 amQuote from: speter on December 19, 2020, 05:39:05 amI had no idea setting tabstop=false had so little effect. It can be solved by set the Key to 0 in the OnKeyDown event. Tested on Linux GTK2, it works. Tested on macOS - it works ---------------------------------------------------------------------- speter · 2020-12-19 06:12 Quote from: trev on December 19, 2020, 06:59:42 amQuote from: Handoko on December 19, 2020, 06:38:05 amQuote from: speter on December 19, 2020, 05:39:05 amI had no idea setting tabstop=false had so little effect. It can be solved by set the Key to 0 in the OnKeyDown event. Tested on Linux GTK2, it works. Tested on macOS - it works Tested on Windows 10 - it works there as well. ---------------------------------------------------------------------- ADMGNS · 2022-02-23 01:38 hello all, i am trying to extend this project for making 3D low poly mesh art from a picture. https://www.dropbox.com/sh/xkjbf66tlh609n2/AADInX4QjO32JjxD4aGVAY6fa?d l=0 firstly i've made some modifications especially renaming variables, functions etc.. and mouse support.. secondly i've add a new form that converts a picture to 3D mesh data and exports, so it is able to view with simple perspective program. it is not completed et all. i'm still working on printing section. everything is going well.. but.. mouse support is working good.. however, sometimes it behaves unwanted direction and/or rotating. i couldn't understand the underlying problem. i think, i need a bit help.. thank you ---------------------------------------------------------------------- Handoko · 2022-02-23 03:03 Wow, you really done it without using OpenGL nor DirectX.  It is good for learning but sooner or later you will abandon it because of the performance issue. It runs very slow if I open the converted low-poly of the dog image. After some inspections I found the weird rotation issue is not caused by mouse move nor keyboard input. It is the calculation problem. Try to rotate the screen to only 1 direction using only keypresses, for example pressing several times the down arrow key. As I am not good in matrix calculation, sorry I cannot help but I believe the issue is matrix calculation in the FormKeyUp event. Rewrite it to use OpenGL will give hundreds times of performance improvement and I believe may also solve the rotation issue. ---------------------------------------------------------------------- ADMGNS · 2022-02-23 22:36 hello again, Quote from: Handoko on February 23, 2022, 04:03:47 amIt is good for learning but sooner or later you will abandon it because of the performance issue. It runs very slow if I open the converted low-poly of the dog image. you are right. in the future, it must be rewritten in well known modern technologies. but, to be honest, the performance issue is a secondary subject for now, because, it doesn't need to run real-time and also it's not being used for daily or frequently. Quote from: Handoko on February 23, 2022, 04:03:47 amAfter some inspections I found the weird rotation issue is not caused by mouse move nor keyboard input. It is the calculation problem. Try to rotate the screen to only 1 direction using only keypresses, for example pressing several times the down arrow key. As I am not good in matrix calculation, sorry I cannot help but I believe the issue is matrix calculation in the FormKeyUp event. Rewrite it to use OpenGL will give hundreds times of performance improvement and I believe may also solve the rotation issue. thank you for your effort.. it seems that the perspective unit needs a clean room coding. thanks and regards ---------------------------------------------------------------------- Josh · 2022-02-26 22:45 Hi had a few hours to have a look, and done some alterations, right click change background, progress bar to alter the amount of degrees scene is changed, display render time, all draw done in bitmap buffer and then placed on canvas, also using timage. used sincos function for sin and cos slightly faster, using fixed array for facet drawing, saves having to setlength all the time, used the polygon function with start and howmany point parameters, to allow the fixed array. result, quite a speed increase, project attached. please extract to new folder. some foldrs missing to get into zip ---------------------------------------------------------------------- ADMGNS · 2022-02-27 14:21 Quote from: josh on February 26, 2022, 11:45:27 pmHi had a few hours to have a look, and done some alterations, right click change background, progress bar to alter the amount of degrees scene is changed, display render time, all draw done in bitmap buffer and then placed on canvas, also using timage. used sincos function for sin and cos slightly faster, using fixed array for facet drawing, saves having to setlength all the time, used the polygon function with start and how many point parameters, to allow the fixed array. result, quite a speed increase thank you for your optimization.. actually, for 3d perspective, i had sticked to the original project that belongs to @speter.. regards