Hello Brian
hows' going? how's the progress of your PB 64bit compiler?
Hello Chris. If you like programming in SDK... consider it 99% complete.
The work i am doing right now, is regarding stock code for automating some tasks like sorting parsing and stuff. I plan to keep adding features, i dont want to make it just a wrapper, but adding functionality not easily made in high level.
i have made fairly complex projects with it, and everything works fine. Im sure a big group of programmers will manage to find more issues than i have imy tests, but nothing that cant be fixed. :)
Very good news, Brian have you tried converting PB GRAPHICS statements and OPENGL stuff ?
OpenGL and graphics, XPRINT can be drawcards to your compiler
No, but you will be able to.
PluriBASIC already supports all their syntaxes, but the stock code is missing. Anybody will be able to code it in and even share.
XPRINT syntax is supported as well. But the internal code is also missing. I think at some point it will be an interesting project
for everyone else.
Quotehave you tried converting PB GRAPHICS statements and OPENGL stuff
PB's 24-bit GRAPHIC is totaly obsolete, 32-bit is a mandatory.
About OpenGL, the latest drivers and shader (using C syntax) are meant to work in 64-bit only (BTW, we added shadertoy animations in OR).
GLSL also requires the learning of C...
Learning the low level API rather than using the GRAPHIC proprietary syntax, would help for the sake of code portability :)
Hello Patrice. :) All that can be done. And portability will be no issue, you will later see what i mean.
We have some classical graphics adapted to OpenGl, primarily for making graphs and diagrams:
examples/OpenGl/DataGraphs/
move
rotate
scale
color
line
thickness
point
pointsize
fan
print
etc.
These could be useful for an XPRINT implementation.
Good to hear that Thanxx Charles
QuoteThese could be useful for an XPRINT implementation.
XPRINT is proprietary, what about writing to a printer DC ;)
Sure, no problem. In the other thread i posted an example for a game, that writes directly to a Window DC.
Writinig to a printer DC should be no problem.
Our o2 Opengl framework uses GDI+ both for loading textures and producing image files.
Currently, the opengl buffer bits are transferred pixel by pixel into a gdi+ bitmap. Though I wonder if there is a more efficient way of making the transfer, bearing in mind that the red and blue colors of each pixel have to be swapped.
Sending GDI+ to a printer looks simple enough:
https://docs.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-sending-gdi-output-to-a-printer-use
From ObjReader, to print the OpenGL display...
// 05-22-2015
long SendToPrinter() {
long nRet = 0;
RECT rc = { 0 };
GetWindowRect(gP.hMain, &rc);
long Wdth = ((rc.right - rc.left) - 438) / 2 - 48;
long Hght = ((rc.bottom - rc.top) - 314) / 2 - 52;
long X = rc.left + Wdth;
long Y = rc.top + Hght;
HWND hTmp = CreateWindowEx(0, L"STATIC", $NULL, WS_POPUP, X, Y, 0, 0, gP.hMain, 0, gP.hInstance, NULL);
// Setup the print common dialog
PRINTDLG pd;
pd.lStructSize = sizeof(pd);
pd.hwndOwner = hTmp;
pd.hDevMode = NULL;
pd.hDevNames = NULL;
pd.nFromPage = 0;
pd.nToPage = 0;
pd.nMinPage = 0;
pd.nMaxPage = 0;
pd.nCopies = 0;
pd.hInstance = gP.hInstance;
pd.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_PRINTSETUP;
pd.lpfnSetupHook = NULL;
pd.lpSetupTemplateName = NULL;
pd.lpfnPrintHook = NULL;
pd.lpPrintTemplateName = NULL;
if (PrintDlg(&pd)) {
long hSize = GetDeviceCaps(pd.hDC, HORZSIZE);
long vSize = GetDeviceCaps(pd.hDC, VERTSIZE);
long hRes = GetDeviceCaps(pd.hDC, HORZRES);
long vRes = GetDeviceCaps(pd.hDC, VERTRES);
WCHAR PathName[MAX_PATH] = { 0 };
WCHAR FilName[MAX_PATH] = { 0 };
zSplitN(zExeName(), &PathName[0], &FilName[0]);
Add_Str(FilName, L"_output");
DOCINFO dinfo;
dinfo.cbSize = sizeof(dinfo);
dinfo.lpszDocName = &FilName[0];
dinfo.lpszOutput = NULL;
// Detect printer orientation mode
long Landscape = -1; if (vSize > hSize) { Landscape = 0; }
// Compute the printing size
long offsetX, offsetY;
if (Landscape) {
offsetX = 60; offsetY = 0;
} else {
offsetX = 15; offsetY = 60;
}
LONG_PTR img = 0;
GetClientRect(gP.hGL, &rc);
// 07-17-2017 respect boundary alignment
rc.right = (rc.right / 4) * 4;
rc.bottom = (rc.bottom / 4) * 4;
BYTE* buffer = new BYTE[rc.right * rc.bottom * 3];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, rc.right, rc.bottom, GL_BGR, GL_UNSIGNED_BYTE, &buffer[0]);
if (GdipCreateBitmapFromScan0(rc.right, rc.bottom, rc.right * 3, PixelFormat24bppRGB, &buffer[0], img) == 0) {
if (img) {
if (GdipImageRotateFlip(img, 6) == 0) {
HBITMAP hPrintBitmap = 0; long background = 0;
if (GdipCreateHBITMAPFromBitmap(img, hPrintBitmap, background) == 0) {
float rCoef = min((float)((hRes - (offsetX * 2)) / (float)rc.right), (float)((vRes - (offsetY * 2)) / (float)rc.bottom));
long fxSize = (long)(rc.right * rCoef);
long fySize = (long)(rc.bottom * rCoef);
long xTop = (hRes - fxSize) / 2 + offsetX;
long yTop = (vRes - fySize) / 2 + offsetY;
if (StartDoc(pd.hDC, &dinfo) > 0) {
if (StartPage(pd.hDC) > 0) {
// Paint the DIB bitmap
PrintBitmap(hPrintBitmap, pd.hDC, xTop, yTop, fxSize, fySize);
nRet = EndPage(pd.hDC);
if (nRet > 0) {
nRet = -1;
EndDoc(pd.hDC);
} else {
nRet = 0;
}
}
}
DeleteObject(hPrintBitmap);
}
}
GdipDisposeImage(img);
}
}
delete[] buffer;
DeleteDC(pd.hDC);
}
DestroyWindow(hTmp);
return nRet;
}
See the attachment of my current
Work
In
Progress, that 3D model should be completed soon.
I have to add some more stickers, extra ambient occlusion, lighting, and ground shadow...
Patrice, do you have a PowerBASIC example that i can try to compile here?
Brian
Here it is:
sub PrintBitmap(byval hPrintBitmap as dword, byval hDCprint as dword, byval xTop as long, byval yTop as long, byval fxSize as long, byval fySize as long)
local bm as BITMAP
local dcBitmap as dword
dcBitmap = CreateCompatibleDC(%NULL)
GetObject(hPrintBitmap, sizeof(bm), bm)
local bi as BITMAPINFO
bi.bmiHeader.biSize = sizeof(bi.bmiHeader)
bi.bmiHeader.biWidth = bm.bmWidth
bi.bmiHeader.biHeight = bm.bmHeight
bi.bmiHeader.biPlanes = 1
bi.bmiHeader.biBitCount = bm.bmBitsPixel
bi.bmiHeader.biCompression = %BI_RGB
'// Calculate space needed for the dib bits
local nBufSize as long
nBufSize = (bi.bmiHeader.biWidth + 1) * (bi.bmiHeader.biBitCount / 8)
nBufSize = ((nBufSize + 3) / 4) * 4
nBufSize *= bi.bmiHeader.biHeight
local ghnd, gptr as dword
ghnd = GlobalAlloc(%GMEM_MOVEABLE, nBufSize)
gptr = GlobalLock(ghnd)
local nDI as long
nDI = GetDIBits(dcBitmap, hPrintBitmap, 0, bm.bmHeight, byval gptr, bi, %DIB_RGB_COLORS)
'// Use this to print a full bitmap
nDI = StretchDIBits(hDCprint, xTop, yTop, fxSize, fySize, 0, 0, bm.bmWidth, bm.bmHeight, BYVAL gptr, bi, %DIB_RGB_COLORS, %SRCCOPY)
GlobalUnlock(ghnd)
GlobalFree(ghnd)
DeleteDC(dcBitmap)
end sub
function SendToPrinter() as long
local nRet, Wdth, Hght, X, Y, hSize, vSize, hRes, vRes, Landscape as long
local hTmp as dword
local sFilName as string
local rc as RECT
GetWindowRect (gP.hMain, rc)
Wdth = ((rc.nRight - rc.left) - 438) / 2 - 48
Hght = ((rc.nBottom - rc.top) - 314) / 2 - 52
X = rc.left + Wdth
Y = rc.top + Hght
hTmp = CreateWindowEx(0, "STATIC", "", %WS_POPUP, X, Y, 0, 0, gP.hMain, 0, gP.hinstance, byval %NULL)
'// Setup the print common dialog
local pd as PRINTDLGAPI
pd.lStructSize = sizeof(pd)
pd.hwndOwner = hTmp
pd.hDevMode = 0
pd.hDevNames = 0
pd.nFromPage = 0
pd.nToPage = 0
pd.nMinPage = 0
pd.nMaxPage = 0
pd.nCopies = 0
pd.hInstance = gP.hinstance
pd.Flags = %PD_RETURNDC or %PD_NOPAGENUMS or %PD_PRINTSETUP
pd.lpfnSetupHook = 0
pd.lpPrintSetupTemplateName = 0
pd.lpfnPrintHook = 0
pd.lpPrintTemplateName = 0
if (PrintDlg(pd)) then
hSize = GetDeviceCaps(pd.hDC, %HORZSIZE)
vSize = GetDeviceCaps(pd.hDC, %VERTSIZE)
hRes = GetDeviceCaps(pd.hDC, %HORZRES)
vRes = GetDeviceCaps(pd.hDC, %VERTRES)
sFilName = EXE.Name$ + "_output"
local dinfo as DOCINFO
dinfo.cbSize = sizeof(dinfo)
dinfo.lpszDocName = strptr(sFilName)
dinfo.lpszOutput = 0
'// Detect printer orientation mode
Landscape = -1: if (vSize > hSize) then Landscape = 0
'// Compute the printing size
local offsetX, offsetY as long
if (Landscape) then
offsetX = 60: offsetY = 0
else
offsetX = 15: offsetY = 60
end if
local img as dword
GetClientRect(gP.hGL, rc)
dim buffer(rc.nRight * rc.nBottom * 3) as byte
glPixelStorei(GL_PACK_ALIGNMENT, 1)
glReadPixels(0, 0, rc.nRight, rc.nBottom, GL_BGR, GL_UNSIGNED_BYTE, byval varptr(buffer(0)))
if (GdipCreateBitmapFromScan0(rc.nRight, rc.nBottom, rc.nRight * 3, %PixelFormat24bppRGB, buffer(0), img) = 0) then
if (img) then
if (GdipImageRotateFlip(img, 6) = 0) then
local hPrintBitmap as dword
local background as long
if (GdipCreateHBITMAPFromBitmap(img, hPrintBitmap, background) = 0) then
local rCoef as single
rCoef = min((hRes - (offsetX * 2)) / rc.nRight, (vRes - (offsetY * 2)) / rc.nBottom)
local fxSize, fySize, xTop, yTop as long
fxSize = (rc.nRight * rCoef)
fySize = (rc.nBottom * rCoef)
xTop = (hRes - fxSize) \ 2 + offsetX
yTop = (vRes - fySize) \ 2 + offsetY
if (StartDoc(pd.hDC, dinfo) > 0) then
if (StartPage(pd.hDC) > 0) then
'// Paint the DIB bitmap
PrintBitmap(hPrintBitmap, pd.hDC, xTop, yTop, fxSize, fySize)
if (EndPage(pd.hDC) > 0) then
nRet = -1
EndDoc(pd.hDC)
end if
end if
end if
DeleteObject(hPrintBitmap)
end if
end if
GdipDisposeImage(img)
end if
end if
DeleteDC(pd.hDC)
end if
DestroyWindow(hTmp)
function = nRet
end function
The complete source code of the PowerBASIC version (discontinued since may 2016) is available on my private forum there:
http://www.objreader.com/index.php?topic=268.0
in the section named "Post Your Questions & Comments Here".
Many thanks for your code, Patrice. That will be very useful, and easily ported to o2.
Regarding your fine collection of vehicles, I suspect that 90% of the effort goes into the final 10% of each project, as in many works of art.
I suspect that 90% of the effort goes into the final 10% of each project
Yes, Charles, you guess it right :)
When dealing with 3D art work, we must be very meticulous especially with the details, because we can inspect each mesh very closely. Some of the models i have, could easily have taken monthes of work all in one. ???
(On behalf of Patrice and myself: sorry for somewhat hijacking the thread, guys...)Quote from: Charles Pegge on September 03, 2019, 05:28:55 PMOur o2 Opengl framework uses GDI+ both for loading textures and producing image files.
Currently, the opengl buffer bits are transferred pixel by pixel into a gdi+ bitmap.
Hi Charles,
GDI+ API can be (and is) safely used to load and save many common 24- and 32-bit image formats as OpenGL textures in low-end image viewers and simpler engines. But GDI+ is noticeably slow even if compared to GDI routines.
One way to speed up the loading of really large discrete textures and their atlases (multiple textures as single image), say 4Kx4K or 8Kx8K pxs large, is to carefully select a palette of simpler image formats of relatively low level of compression and simpler compression algos (like RLE TGAs and BMPs, 100% JP(E)Gs or full-color GIFs) to support, and maintain one's own library of simplified routines to (de)compress them efficiently in memory as needed. There
are pieces of code available on the net that are compatible with common libraries/algos like e.g. zlib (for jpegs and pngs) while working significantly faster than those.
Another way is to work with Microsoft's DDS (
direct
draw
surface) texture formats that
both OpenGL and Direct3D can load and display
without prior explicit decoding/decompression.
(actually, (de)coding is done automatically by the renderer hardware on the fly when the texture gets bound to the render target)QuoteCurrently, the opengl buffer bits are transferred pixel by pixel into a gdi+ bitmap. Though I wonder if there is a more efficient way of making the transfer, bearing in mind that the red and blue colors of each pixel have to be swapped.
No, you cannot speed up
glReadPixels() which seems to be by far the slowest OpenGL API that's even slower than GDI+ routines. The only way to boost the frame-to-image rendering speed to real on-screen 3D motion capture is use frame- and renderbuffer objects (FBOs/RBOs) in the GLSL hardware-accelerated programmable pipeline. It allows, for instance,
ObjReader to successfully render and capture simple animation (currently rotation/translation/scaling) of arbitrary meshes (pieces/submodel chunks) in a full-screen scene at a speed not less than 30FPS (typically 60+FPS) for scenes as complicated as
10 million polygons (ca. 30 million vertices) and more. FBO hardware-assisted blitting occurs perhaps 100 times faster than regular glReadPixels(), especially for non-antialiased framebuffers.
But the good news is yes,
you can eliminate the need to swap pixels while loading or saving images from or to GDI+. The two major OpenGL APIs you use for creating/saving the textures (or the OpenGL screen pictures) , glTexImage2D() and glReadPixels(), as well as some others, use a parameter called
format (not to be confused with
internalFormat!) that can be typically either
GL_RGBA or
GL_BGRA. Use GL_RGBA with common image formats like BMP or JPG for "straight" color bits order, or GL_BGRA, for "linuxoid" textures like PPM/PGM/PNM or GDI+ PNG image formats. In this case, OpenGL will do R and B byte swapping for you automatically at texture creation/on-disk dumping, leaving the G and A bytes in place. :)
please can someone provide some GDI examples codes in O2?
i really do need some example codes so as to resurrect some interest back into O2
Thanxx to all
Hi Mike,
Thank you! It's definitely time for another round of Opengl :)
I've been looking at some of the documentation concerning FrameBuffer objects, RenderBuffer objects, and so forth, but I'm not yet clear how to transfer the data from these buffers to the client - for instance delivering a rendered bitmap larger than the window client area.
Hi Chris,
There is a folder dedicated to GDI demos (Peter Wirbelauer), which you might find useful: projectsB\GDI. Also ProjectsB\GdiPlus.
correction: ProjectsB
Thanxx a lot Charles
they are actually located in \projectsB\GDI and \projectsB\GDIplus folders
i will try compiling them to look how they can be applicable to my needs
There is some kinda of Lisp programming too in the folder \projectsA\LeanLisp
what does Lisp do? is it similar to AutoLisp ?
Hi Chris,
Yes, ProjectsB, not ProjectsA. Sorry. I think they will need some 64bit attention, but you can see how they work.
There are many LISPS about. LeanLisp is an experimental interpretive LISP with a tokeniser. There is also a standard version of SCHEME ported by Mike Lobanovsky, very similar to LISP, in ProjectsC.
I find this discussion slowly a bit bored it can't be that you convert 32 bit pointers to 64 bits. Why is no one able to create a decent 64 bit version on the PB10 version. There will only be 64 bit versions based on Freebasic. They don't have a good debugger. I think will slowly switch to C++ or Visual Net
What do you mean "it can't be that you convert 32 bit pointers to 64 bits" ?
Oxygen's pointers work very nice for 32/64 bit compilations and AFAIK when coded correctly, they require no conversion to compile for one or the other.
That's what I meant! If the compiler is programmed correctly structured, you set only one directive and the compiler generates 64Bit Pointer Brain instead of 32Bit Pointer!
WinDev uses the SYSTEM INTEGER (short SYSTEM)
automatically adapts to the size supported by the compilation mode (4 bytes for a program compiled in 32 bits, 8 bytes for a program compiled in 64 bits).
Example:
i is system int
In Oxygen it is called sys. In 32bit mode it is 4 byte, in 64bit mode it is 8.
sys hAddress
In PluriBASIC (oxygen based) it is called handle.
LOCAL hAddress AS HANDLE
Yup Brian you are correct
In 64bit O2, handles and pointers must be converted to sys
PB handles conversion to O2
DWORD --> sys
LONG --> sys
sys is mainly applicable to window handles and pointers, while all other variables remain unchange
Pluribasic and OxygenBasic is the way to go 64bit and you can forget about the 32bit Powerless Basic
For a buisiness work, a compiler { that is a strategic choice }, must be not only rock solid, but offer a real guarantee that it will be maintained in the long range, to avoid the single man Zale's syndrom.
Hobbyist, of course, do what ever you want :)
Bob Zale syndrome is difficult to gauge, what we need is a compiler urgently that can do the work for the time being, something
that can translate Powerbasic programs directly, without the steep learning curve such as C++ programming language
Look at Freebasic, which is already dead and so is QuickBasic64 and those other old basic languages are either dead or dying.
We can't afford the time to convert to other languages as business is an ongoing concern.
We can't wait for Drake to put up another compiler for 64bits -- looks like NEVER. Since Drake isn't listening to its own customers
so Pluribasic and OxygenBasic are the only answer now.
Quote from: Anthon Com on December 05, 2019, 12:37:50 AM
Look at Freebasic, which is already dead and so is QuickBasic64 and those other old basic languages are either dead or dying.
please don't state your opinion as a matter of fact, FreeBasic is actively being developed
C / C++ is the way to go... The Drakes are a big disappointment imo. I wonder wether they put any effort in a new pb compiler. But even if, too many years have passed since the last version and I wonder the PB will be able to attrack new customers.
And for hobbyist: Delphi, CBuilder and Visual C, C# are free. There are enough options.
The enterprise I am working switched to Delphi. We never regretted it.
Lets face it: BASIC is dead.
Hello there 2020 and nothing from PB on 64bit
QuoteThe Drakes are a big disappointment imo.
;D this is an absolute truth and that O2 is our only light at the tunnel end
After watching this thread, i thought i should try something. Please see this:
https://forum.powerbasic.com/forum/user-to-user-discussions/third-party-addons/pluribasic/788817-pluribasic-64bit-compilations
If you want to be able to compile PowerBASIC code and even mix it with some of the C++ code... please support. :)
Hello Patrice, The most advanced implementation is for OxygenBASIC, but it also supports C++.
It is not easy to work on both implementations though.
I would not get too excited about the c++ implementation. I only tested with MINGW and im
not sure if i will continue with it's implementation. It is very time consuming working in two
implementations.
I'd rather be exited because the Oxygen implementation supports some c++ directly. Almost nothing
stops you from using the statements that oxygen supports already. Im not ture but i think Oxygen
also supports c++ dlls. Thats why i might drop directly c++ implementation, because it is already
present in Oxygen.
Yes, i contacted Adam Drake, he's a good guy but he is very busy. He kindly granted permission to
promote and sell PluriBASIC in the PowerBASIC forums.
Hi Brian
This is truly a good news, very glad that we have a replacement of old PB in 64bit . The question is how much do we have
to pay for this Beta product of yours , what's the asking minimum pricing per year etc?
> Yes, i contacted Adam Drake, he's a good guy but he is very busy. He kindly granted permission to
promote and sell PluriBASIC in the PowerBASIC forums.
This seems to confirm that he has given up.
Quote from: Patrice Terrier on January 18, 2020, 02:59:03 PMI would avoid to make twice the same error, using a compiler that is based on the work of a single man (Zale's syndrom).
Patrice, PluriBASIC is made in a way that it allows anybody to work on it. For example, I seem to recall there is a bug in one of the DDT statements for
DIALOG END hWnd&, but in PluriBASIC, even if i died, you could just open up the library DIALOG_END.bin and edit the statement yourself. It is pretty straightforward and it even allows to enter code for 32bit or 64 bits in the same library.
I plan to open it a bit more, for the moment all the "official" libraries would need to go trough me, but in the future i may implement a way to share libraries. Of course nothing would stop anobody from sharing libraries via email or something at the moment.
Besides, DDT is a secondary priority ATM. I would like to make it for SDK mostly.
I understand.
However, i havent even hit my 40's so, i doubt you have to worry about me dying before you. ;D
Nah, seriously, I work closely with a friend who also works on PluriBASIC with me, and old PB'er
that acts as a back up for me as i do for him.
Brian.
> As we say here: "Chat échaudé craint l'eau froide"
It is almost identical to the Spanish saying: "Gato escaldado, del agua fría huye".