• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Recent posts

#51
Brians Board / Re: Any Good news regarding PB...
Last post by Chris Chancellor - September 09, 2019, 04:58:22 AM
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 ?
#52
Brians Board / Re: Any Good news regarding PB...
Last post by Charles Pegge - September 08, 2019, 11:53:55 AM
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



#53
Brians Board / Re: Any Good news regarding PB...
Last post by Chris Chancellor - September 08, 2019, 05:01:41 AM
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
#54
Brians Board / Re: Any Good news regarding PB...
Last post by Mike Lobanovsky - September 05, 2019, 09:36:46 PM
(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. :)
#55
Brians Board / Re: Any Good news regarding PB...
Last post by Patrice Terrier - September 05, 2019, 03:44:40 PM
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.  ???

#56
Brians Board / Re: Any Good news regarding PB...
Last post by Charles Pegge - September 05, 2019, 11:21:16 AM
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.

#57
Brians Board / Re: Any Good news regarding PB...
Last post by Patrice Terrier - September 04, 2019, 08:52:02 AM
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".





#58
Brians Board / Re: Any Good news regarding PB...
Last post by Brian Alvarez - September 04, 2019, 01:04:00 AM

Patrice, do you have a PowerBASIC example that i can try to compile here?
#59
Brians Board / Re: Any Good news regarding PB...
Last post by Patrice Terrier - September 03, 2019, 11:24:08 PM
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...
#60
Brians Board / Re: Any Good news regarding PB...
Last post by Charles Pegge - September 03, 2019, 05:28:55 PM
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