ObjReader Community

WIP => WIP => Topic started by: Patrice Terrier on February 11, 2019, 03:08:38 pm

Title: There are many ways to go to Rome.
Post by: Patrice Terrier on February 11, 2019, 03:08:38 pm
Rough video to show you, the use of a GDImage zoom control inside of OR.

It could be either a native child control, or an internal window (the same that you did to embed HH).

At least, this is how i would reuse my existing code, using a GDImage callback to create the point array for Bezier curve or whatever polypolygon in draft or antialias mode.

There are many ways to go to Rome.

 :)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 11, 2019, 03:31:01 pm
Hehehe that's a cool demo Patrice! :D

What does this tiny square do, if at all?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 11, 2019, 06:02:49 pm
This tiny square is specific to the un-skinned zoom control scrollbar, to avoid the nasty empty scrollbar section when Windows redraws the NC area.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 11, 2019, 08:18:49 pm
Patrice,

1. Can the control run completely unskinned including the top and bottom splitters and the top thumbnail strip?
2. Can the little widget with the zoom slider on the right be placed in a separate window (e.g. tool window) together with the other controls of UV editor?
3. Can you add yet another layer (what you call a "sprite") on top of the texture map main display and draw an array of lines in it to demonstrate the synchronicity of both layers' zoom factor as the slider in the little widget is dragged left or right?

(I'm going to the hospital this Thursday morning and won't be able to enjoy the demo before I return in (hopefully) 3 weeks' time but I'd like to at least see the video before I go)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 11, 2019, 10:28:52 pm
Quote
1. Can the control run completely unskinned including the top and bottom splitters and the top thumbnail strip?
Yes, and the top and bottom splitters are indeed custom buttons.

Quote
2. Can the little widget with the zoom slider on the right be placed in a separate window (e.g. tool window) together with the other controls of UV editor?
It is already an anchored tool window, that you can move everywhere.

Quote
3. Can you add yet another layer (what you call a "sprite") on top of the texture map main display and draw an array of lines in it to demonstrate the synchronicity of both layers' zoom factor as the slider in the little widget is dragged left or right?
It could work just the same to what you can do with the GDplus project, see the bottom control using the green open polyline with the red dots that are used as hot spots to change the shape of the polyline, the red dots are indeed an array of x,y locations.
Inside of a GDImage zoom control all the tedious computation work is done transparently and you always refer to the array with ratio 1/1, it means using the real pixel location value.

As i told you already i would cannibalise the gMap64 project, to create the OR specific edit control, because it has already 90% of what we need to do in OR (at least in my understatement of what must be done).

I could customize the code to create the array of point using multiple mouse clicks to setup the hot spot following a specfic UV shape, then ask to create the polypolygon from the array, but the final sprite array will be flatten only when we ask for saving, and untill there we can change everything. Clear as mud?

There is also a specific contextual menu inside of gMap64, and we need it too, see the attached video.
See also the use of the green markers that could be used to create the array of points.

I have added another video to show you the synchronicity, the little widget being also a GDImage control, and the RED rectangle inside of it, is a vectorial polypolygon that i can drag around to move the main view port accordingly ;)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 11, 2019, 11:50:43 pm
Thanks for your efforts Patrice,

The videos are rather comprehensive! The control seems to be gorgeous and rather rich in features. I'd even say it's too rich for our modest purposes.

The arrays of UV points aren't normally created manually but are rather flat 2D projections of mesh 3D vertices on the texture map plane. There can't be an UV pair that doesn't have at least one matching mesh vertex. So, it isn't the UV editor task to create the UV points but rather the task of the mesh vertex editor to create the 3D vertices. The UV editor just uses the existing mesh vertex array to unwrap it on the map's plane algorithmically using planar, cylinder, conic, spherical etc. primitive projections as well as certain more advanced algos like e.g. the one to unwrap facial and other predefined body part projections across the skins of predefined configuration. You've seen and used them in a number of your character and monster models.

If the model is already equipped with UVs, the UV editor's task will be just to draw the UV wireframe overlay over the texture image, denote the mesh vertex UVs with typically 3x3 px boxes, and allow the boxes to be dragged around the texture in order to fine tune their UV coords as may be necessary, e.g. to hide the texture map jaggies. The new UVs may then be optionally written back into the model file. That's what OR's UV editor should be able to do in the first place.

OK we're going to come back to that topic later when I'm back from the hospital. Thanks again for the nice demos, my friend!
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 12, 2019, 11:27:53 am
Quote
If the model is already equipped with UVs, the UV editor's task will be just to draw the UV wireframe overlay over the texture image, denote the mesh vertex UVs with typically 3x3 px boxes, and allow the boxes to be dragged around the texture in order to fine tune their UV coords as may be necessary, e.g. to hide the texture map jaggies

Of course i understand that, just remember that in GDImage the X,Y coordinate of a sprite object (overlay) is always the top left corner, thus in the case of a 3x3 hot spot, there will and offset of 1 (there are API to retrieve the X, Y, width, and height of an object). Due to clone optimization the hot spot bitmap will be stored only once in memory, and we can also have a library of hot spots to select from the floating list on the right, like the green/red one shown on the video. They can have also multiple states (see the video). And we could save the sprite locations within a .gns file for further retrieval.
The contact sheet on the top that could be hidden with the splitter, is to select a specific texture to work on (more visual than selecting from a treeview).

So far my main concern is to guess what would be the best solution to use the zoom control:
- from an internal window (embedding a modified version of the gMap64 application, using WM_COPYDATA to communicate)
- or from a standard GDImage class, as we did for the other controls.

The internal window was what i had in mind when i was speaking of a standalone application (slave application).
This architecture could be used to swap from one module to another, WM_COPYDATA works very well and this is what i am using to mix 32-bit and 64-bit altogether (my OpenGL BassBox visual plugins are a good example of this). It is just like working with multiple threads, the main thing to be aware of, is to make sure that the application is not already running and to kill the slave application when the main one goes down. The slave application could also check peridodically that the main application is still there, and if not then shut down itself.

I am thinking at loud voice again ;)




Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 02:08:00 pm
I am thinking at loud voice again ;)

I like that voice of yours. :)

Is WM_COPYDATA capable of re-mapping data pointers when crossing the process boundaries or rather does it only pass data values one by one? If it does the latter, then it will be too slow to set up a real time "bridge" between the "master" editor and "slave" ObjReader because the amounts of data to be passed are going to be huge.

My intention is to have OR to depict immediately in its high-quality viewport every minute change to the model data that I might be making in whatever editor I happen to be working with.

If I can't do that, then I'll have to re-create a clone of full-featured (if only unskinned) OR as the editor's own main rendering viewport. I want to have a 100%:100% WYSIWYG correspondence between the 3D pictures in the both applications.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 02:54:36 pm
OTOH there's nothing preventing us from compiling each such editor as a DLL plug-in to the main OR app. The DLL can have a single "property getter" that would expose a pointer to the DLL's entire "vtable" in the form of a strucure of FARPROC pointers to the editor procedures, and possibly, editor specific data.

Then if the editor DLLs are available in the installation (which can be polled by a set of simple calls to LoadLibrary()), then OR would reveal the corresponding main menu elements, set up its "vtable" interfaces with the DLLs, and exchange the actual model data with the editors fast and free because the plug-ins and the OR host would share common process memory.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 12, 2019, 03:13:22 pm
WM_COPYDATA is very capable, you can pass a full UDT in one single call.
See my post there
http://www.jose.it-berater.org/smfforum/index.php?topic=4932.msg20600#msg20600

Note: BB64 process the audio signal in real time, and call a 32-bit application bridge to sync with the BassBox plugins.
See the attached video showing the use of WM_COPYDATA in context.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 03:32:17 pm
:-* 8)

I can't notice any perceptible lag between the sound and visual response via WM_COPYDATA. I think such a speed of data interchange will be sufficient for "slave" OR's real time response to the model data changes in the "master" editor application.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 12, 2019, 03:34:30 pm
I am experimenting right now to create a container on the right part of the slider to host the editor(s).
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 12, 2019, 03:38:27 pm
Quote
I can't notice any perceptible lag between the sound and visual response via WM_COPYDATA.
The whole Windows paradigm is based on the message pump, and sendmessage is the basic and fastest way to use for IPC.
And the WM_COPYDATA message has a high priority.

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 03:50:09 pm
No, I can't agree with that statement. Everything that's based on the window message processing pump is turtle slow, computation wise. That's because MS Windows has got its own idea of task priorities and tends to block and kill the apps that don't agree to play by its rules.

BTW where's that:
Quote
Note: The source code is provided to help those wanting to learn more about low level SDK programming in C++, and to get the most of WinLIFT and GDImage.
? ? ? ;)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 03:54:47 pm
How would you live for three weeks without a computer close to you  :o  ;)

Oh Patrice,

Don't you say that! I'm in panic and everything keeps falling out of my hands. I'm not actually scared as I know I need that treatment anyway and I can't avoid it.

But I hate losing three weeks of my life for that sick and silly hospital environment of decay and entropy... :'(
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 12, 2019, 04:14:14 pm
Thank you, my friend! Now I've got me something to play with tonight. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 12, 2019, 04:23:50 pm
Forgot to say how to use it:

Use drag and drop of one or several folder(s) with audio files.
click with the left or right mouse button to switch from one plugin to another (when plugin is enabled, or it will change the background).
To move from one song to another press on the auto/hide arrow (sprite object).
To move within the song use the small yellow animation seek pointer.
To adjust the audio level click on the dot line above the word BASSBOX.
You can setup the equalizer from the popup menu.

BB64 was my first real GDImage/WinLIFT 64-bit application ever written in C++ with Visual Studio.

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 13, 2019, 06:18:44 pm
What are the icons you would like to see on the rubber band?
Just give me their tooltip description, i shall take care of the icons myself.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 20, 2019, 10:12:03 am
Current status:

02-20-2019
The merging of Tor inside of OR has been done, now i have to let them coexist peacefully …

02-21-2019
See the attached screen shot to better figure how it looks in split mode.

02-24-2019
I have added the toolwindow icon selector, anchored to the right side of gP.hMain, but i don't know yet if we will have a real use of it.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 24, 2019, 04:25:58 pm
(http://www.i2symbol.com/pictures/emojis/a/f/f/2/aff22723ab391b694c9bcae65ee2da76_256.png)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 25, 2019, 07:48:32 pm
02-25-2019
It begins to smell good…

And now i shall have to wait for your return for the next step(s).  8)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 26, 2019, 06:00:44 pm
03-26-2019
Working on the ZIP file with all the latest goodies, and the new graphic components.

Tor added 37 Kb to the OR binary, that is not that much when looking at the massive amount of C++ source code that has been moved in.

Added:
The zip file with all my changes is attached to this post...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 26, 2019, 08:12:42 pm
Thank you very much, Patrice!

I'll be able to look into your code tomorrow afternoon. See you soon! :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 26, 2019, 09:49:49 pm
Welcome back my friend!

Note: There are still some more issues that i have to fix in the code, for example the (F2) color picker drag and drop is broken.
I shall fix them in the next coming days, indeed... you come back too early  ;D

Added:
02-27-2019 at 11:20 am
The GDImageCallback problem causing the havoc with both F1 and F2 has been solved.
Looking now for two other minor problems.

02-27-2019 at 3:11 pm
Here is the patch to solve the problems i have detected.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 27, 2019, 07:34:28 pm
Done assimilating the new mods, my friend! Isn't that a great job you've done!

My OR now looks like a Christmas tree full of yummies, wonders , and magic! :D

With just one note: we absolutely must have immediate access to the mesh list (or rather treeviewlist) at all times to be able to select an individual mesh (and ultimately, a group of vertices) to work on immediately.

Do you think we can still squeeze it in the current tor setup?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 27, 2019, 07:50:29 pm
Quote
we absolutely must have immediate access to the mesh list (or rather treeviewlist) at all times to be able to select an individual mesh
See the attached video.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on February 27, 2019, 07:59:28 pm
!!! OH MY GAWWWWWD !!! :o :o :o :o

!!! THIS IS AWESOME !!!
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on February 28, 2019, 07:01:27 pm
Mike

Here is a code example, to show you how to create on the fly a complex GDImage polypolygon, and add it to gT.hZoomCtrl, just the same than using drag and drop from gT.hMarkerParent.

Code: [Select]
void UsaMap() {
    // USA map xy coordinates
    POINTS xy[] = {146,218,166,224,168,230,162,235,168,240,175,236,175,224,175,206,244,216,350,222,
                   468,210,500,203,518,210,529,205,546,210,573,207,554,235,566,232,570,236,577,233,
                   585,243,591,243,606,240,616,253,618,259,613,265,618,262,622,291,629,299,628,310,
                   637,317,644,308,644,287,637,272,633,253,641,250,639,242,647,229,663,233,670,242,
                   673,250,666,259,666,266,673,271,678,261,683,258,691,272,687,283,686,295,691,298,
                   703,297,730,269,733,259,731,248,747,240,755,237,759,220,766,198,792,188,810,176,
                   814,161,812,138,813,131,829,128,842,147,855,152,852,168,840,176,841,185,833,189,
                   833,203,830,214,838,218,833,227,844,228,851,224,852,231,846,236,840,236,840,244,
                   831,251,837,254,830,265,814,277,816,291,813,304,802,306,809,314,814,325,810,329,
                   811,337,807,343,804,336,806,328,796,319,791,306,788,305,786,319,794,324,792,329,
                   800,336,801,345,795,347,802,352,806,349,813,352,815,359,811,368,823,370,818,383,
                   811,381,812,389,818,388,821,390,809,399,803,412,795,416,794,423,791,435,775,459,
                   775,464,776,478,772,489,781,497,783,513,797,531,809,545,819,567,820,575,814,592,
                   809,592,803,588,801,581,791,576,772,557,770,547,767,546,763,531,747,517,735,517,
                   727,526,719,525,703,517,682,523,677,525,673,520,669,523,661,527,652,535,649,540,
                   656,541,652,549,663,557,662,559,648,552,645,553,649,557,640,560,634,560,622,551,
                   614,551,611,556,603,559,599,552,589,554,581,559,574,555,567,555,563,558,572,560,
                   574,564,555,585,547,584,548,593,536,600,534,613,531,616,537,630,538,639,516,636,
                   506,626,502,613,502,608,494,608,475,583,457,573,450,576,440,590,429,592,418,581,
                   411,565,385,543,383,541,358,542,354,547,340,546,309,548,253,526,254,522,212,522,
                   206,505,189,489,168,480,148,442,150,431,144,426,147,421,149,421,150,415,141,414,
                   130,392,128,380,129,364,134,347,132,328,133,314,145,291,151,259,153,237,147,226};
    short XYcount = (sizeof(xy) / sizeof(xy[0]));
    long K = 0;
    short BorderSize = 5, minx = 9999, miny = 9999, maxx = -9999, maxy = -9999;
    for (K = 0; K < XYcount; K++) {
        minx = min(xy[K].x, minx);
        miny = min(xy[K].y, miny);
        maxx = max(xy[K].x, maxx);
        maxy = max(xy[K].y, maxy);
    }
    long nW = maxx - minx, nH = maxy - miny;
    for (K = 0; K < XYcount; K++) {
        xy[K].x -= minx; xy[K].x += BorderSize / 2;
        xy[K].y -= miny; xy[K].y += BorderSize / 2;
    }
    nW += BorderSize; nH += BorderSize;

    const long nCount = 2;
    ZOBJECT arrayobj[nCount]; ClearMemory(&arrayobj[0], sizeof(arrayobj));
    ZI_CreatePolyLineObject (arrayobj[0], &xy[0], XYcount, ZD_ColorARGB(128, RGB(128,0,0)), BorderSize, ZS_VISIBLE | ZS_DRAFT, ZD_DRAW_FILLED, 0);
    ZI_CreatePolyLineObject (arrayobj[1], &xy[0], XYcount, ZD_ColorARGB(255, RGB(100,250,150)), BorderSize, ZS_VISIBLE | ZS_DRAFT, ZD_DRAW_OUTLINE, 0);
    WCHAR zFile[MAX_PATH]; ClearMemory(zFile, sizeof(zFile));
    Path_Combine(zFile, zGetTempPath(), L"zBidon.png");
    ZI_CreateImageComposited(zFile, nW, nH, arrayobj, nCount);

    HBITMAP hBitmap = ZI_CreateBitmapFromFile(zFile, nW, nH);

    if (hBitmap) {

        long top_left_X = 100, top_left_Y = 100;

        WCHAR szDrive[_MAX_DRIVE] = {0}, szDir[MAX_PATH] = {0}, szName[_MAX_FNAME] = {0}, szExt[_MAX_EXT] = {0};
        wsplitpath(zFile, szDrive, szDir, szName, szExt);
        long newID = IncrID(); // Increment ID and ga_Sprite array
        // In order to save memory, we detect if we have used already the same sprite
        long nIDtoClone = 0;
        long nSpriteCount = UBOUND(ga_Sprite) - 1;
        for (K = 0; K < nSpriteCount; K++) {
            if (_wcsicmp(ga_Sprite[K].filename, zFile) == 0) {
                if (ga_Sprite[K].clone == 0) {
                    if (ga_Sprite[K].id) { // We found one
                        nIDtoClone = ga_Sprite[K].id; break;
                    }
                }
            }
        }
        if (nIDtoClone) { // Get rid of the bitmap to save memory, and clone nIDtoClone.
            DeleteObject(hBitmap);
            CloneObject(newID, $NULL, top_left_X, top_left_Y, nIDtoClone);
            // Because this is a clone, assign a new set of properties to it (else we inherit everyting from the original).
            ZD_SetObjectRotation(newID, 0);
            ZD_SetObjectFlipMode(newID, 0);
            ZD_SetObjectAngle(newID, 0, 0);
            ZD_SetObjectScale(newID, 0);
            ZD_SetObjectAlpha(newID, 255, FALSE);
            ZD_SetObjectFlipMode(newID, ZD_GetObjectFlipMode(newID));
            ZD_SetObjectVisibility(newID, ZS_VISIBLE);
        } else { // We must use this bitmap.
            ZD_DrawBitmapToCtrl(gT.hZoomCtrl, top_left_X, top_left_Y, hBitmap, ZD_ColorARGB(255, 0), newID, ZS_VISIBLE);
        }
        ZD_SetObjectImageLabel(newID, szName);

        ZD_SetObjectScroll(newID, TRUE);
        ZD_SetObjectQuality(newID, gT.UseQuality, FALSE);
        SpriteArrayInit(newID, gT.szdropname);     // Initialize the global Sprite array
        ZI_UpdateWindow(gT.hZoomCtrl, FALSE);      // Show new sprite
//        ShowSaveButton();
    }
    zKillFile(zFile);
}

We could use each xy[] POINTS as hot spot to redraw the polypolygon on the fly.

If you want i can send you a Tor.cpp with a TEST button to try it out.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 06:47:34 am
Quote
If you want i can send you a Tor.cpp with a TEST button to try it out.

Please do. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 09:16:37 am
Here it is…

Note:
You must select a texture from the contact sheet, before pressing the new [Test] button.


Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 09:37:16 am
The ZI_CreatrImageComposited API returns directly a HBITMAP if the the file name is empty, however for the purpose of the demo i used a file name in case you want to inspect the resulting png file with PSD.

For further details see the GDImage.chm help file.

The composited polypolygon is made of 2 overlapped objects using the same coordinates to ease the sprite move hover the texture (ZD_DRAW_FILLED).

The composited image always use the real size (ratio 1/1), thus that should be easy to replace the xy[] array with real UV coordinates.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 10:28:13 am
I m thinking to embed all the controls on the right side of the main window into a single "rightpanel" control, to let them work like a TABed control.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 11:11:14 am
That looks very impressive and real smooth, Patrice!

However,

1. We need a much much deeper zoom. Why? Because the overlapping projections onto the same tex map region of, say, two 3D quads may have their corner vertices so close to each other that we won't be able to select just one of them with the mouse pointer and drag it around as necessary if the zoom ratio is too low. In terms of real UV values, we should be able to always depict easily a difference of approx. 0.001f between the UVs of two vertices.

2. We will need many more "toolbar" controls than the existing 3 (+1 "test") buttons to operate even the simplest UV mapper efficiently. I 'm going to provide you with a list of what we might need for the starters and then please think over how we could arrange them all in the existing bottom space.

3. Tex maps designed as CLAMP_TO_EDGE often have many mesh UV sets layered over one another in one and the same map (UVs are all within [0.f,1.f] rather than cloned across 1.f/2.f/3.f/N.f boundaries). In other words, there are often too much vertex UV data within the same [0.f,1.f] map for the mouse pointer to work with. Do you think it will be possible to clone the same tex map image along U and/or V to separate the mesh UV sets each into its own map clone, e.g. like below:
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 11:27:31 am
Mike

Once a sprite object has the focus, it could be moved with the arrow keys by pixel units, this is more accurate than with the mouse.
And you can select several sprites with the CTRL key and move them all with the mouse.

So far i think it would be easier to work with "quad" rather than "triangle", or even only peripherical dots (hot spot).
Once a shape is selected, we could display the hot spots, because they use the same xy coordinates.
However the ultimate precision will be always 1 pixel unit for the resulting image…

(thinking at loud voice)



Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 11:51:24 am
I m thinking to embed all the controls on the right side of the main window into a single "rightpanel" control, to let them work like a TABed control.

Perhaps it will also be handy to make the draggable zoom and thumbnail windows (do we need the latter at all?) "sticky" windows. Such windows tend to optionally "snap" (as if magnetized) to the main window if they are moved close to its sides and/or corners. When "snapped" and the main window is dragged around by its caption bar, the satellite windows are moved as well keeping "attracted" to their respective sides/corners. 8)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 12:08:34 pm
Yes i could snap the floating windows (this is what i am doing with gMap64, that was used to create the single Tor Template).

Except when working in maximized mode, in this case they should work the same than now.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 12:24:07 pm
Once a sprite object has the focus, it could be moved with the arrow keys by pixel units, this is more accurate than with the mouse.

That's all right but in real practice, still a lot can be done by picking the vertex projection rect (in fact its UV point) with LMB and dragging it around with the mouse. We do not always need pixel-perfect placement. We must have a choice of working either with the mouse or arrow keys at our own option.

Quote
However the ultimate precision will be always 1 pixel unit, as long as a texture is concerned…

That is not correct. ;) The ultimate precision will always be 1 texel which is 1 texture pixel times the texture zoom ratio times the OpenGL current texture screen space projection mini- or magnification factor times sub-pixel stretch due to i) multisampling, ii) anisotropic correction, and iii) color interpolation across OpenGL viewport screen pixels.

That's why I insist on being able to see the results of my UV work in real time immediately in the main render window. :)

Quote
And you can select several sprites with the CTRL key and move them all with the mouse.

The notion of "sprites" is alien to my ears in this context.

I am going to work with vertex UVs which are point projections of 3D vertices onto the flat tex map plane. I need to be able to pick a point (a pair of UV coords) or a group of points by mouse pointing-and-clicking, or freehand rect and/or lasso area selection. Point selection is done by sensing if the mouse pointer hits the UV box color (cyan in the snapshots I provided) under the mouse. The UVs will be stored in 2D UV arrays.

Where do you want to squeeze your "sprites" (layers?) in this scenario?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 02:43:22 pm
Here are 2 videos, showing you the use of a {sprite hot spot} to change the shape of a polyline.

Remember, a sprite hot spot can be as small as one single pixel, and we can give the focus to the sprite we want, just like when selecting it with the mouse.

After moving one or several of our sprite hot spots, we can redraw the wole polyline on demand (video2).

Thus what could be done, is to select a specific mesh in the listview, then create and array of XY UV, that will be used to display the hot spots (we could use larger dot sprites of say 5x5 or even more) to easily move them around, and add a new button to redraw the UV polyline on demand.

Is that clear enough?

Quote
The notion of "sprites" is alien to my ears in this context.
A GDImage sprite, is anything floating above the background that could be moved up or down along the object z-order.
Just like regular controls inside of the same window (and they have almost the same scope of properties).


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 05:37:22 pm
Excellent! :) I think I got you idea finally, Patrice, thank you!

So, what you suggest is to use a memory array of hot spots to represent the set of mesh vertex UVs, and a matching array of sprites (e.g. red bullets/circles), to visualize the hot spots against the tex map background -- plus one more sprite (= layer) to draw the polyline that would interconnect the hot spots in a wireframe fashion, isn't it?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 05:49:20 pm
Yes you got the picture ;)

Provide me with just an array of XY POINTS matching a specific mesh, that is the first step to move from...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 06:24:11 pm
Take my copy of Astellia-dragon below (I love this model and I think it should go into the Collection). It has 1 mesh ("body") with 16934 vertices that all map into the [0.f,1.f] range. Loop through its vertex array, build a matching set of UV hot spots from the "body" mesh vertex structure MobjVertexT.texCoord[2] member fields, and project it onto the tex map plane using the smallest one of your bullet sprites and optionally interconnecting them with a polyline to emulate the wireframe. If your hot spots/sprites use texel  units rather than real UVs then multiply the hot spot array elements by the tex map actual width and height when populating the hot spot array.

The "body" mesh is a very lightweight "sample" of real world meshes we're going to deal with in our heavyweight models.

If Tor's speed of redrawing this "net" of UVs as the bullets are being dragged around appears smooth and fast enough, we will proceed with your vision of bending Tor's built in features to our needs. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 08:00:45 pm
Quote
Loop through its vertex array, build a matching set of UV hot spots from the "body" mesh vertex structure MobjVertexT.texCoord[2] member fields, and project it onto the tex map plane using the smallest one of your bullet sprites and optionally interconnecting them with a polyline to emulate the wireframe.
This is exactly where i need your help, i need a function that would create the right XY[] POINTS pixel array, from the mesh vertex structure MobjVertexT.texCoord[2] member fields. I have never worked with UV projection myself.

gP.bTexUV ?

Could you do that for me?

I shall probably have to write a custom code to process large array, to create the composited bitmap on the fly.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 08:52:40 pm
Quote
Could you do that for me?

No problem though I'll need a little time to do that.

I think we'll simplify the task a little by first drawing the hot spots/bullets array only. A true wireframe will require one more elaborate array of 2D vertices (UVs) organized by triples according to their indices in the mesh to form up the actual array of triangles, and a PolyPolygon(hDC, triarray, 3, numoftris) WinAPI call to draw the entire wireframe by three points to a poly. (OR re-triangulates the mesh by triangles automatically at all times even if it deals with a quad-coded model file)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 08:55:09 pm
This is how UV coordinates are created in C4D when saving into a .psd file (see the red overlay)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 09:07:16 pm
My friend

if you have already a working solution, then we can go for it, if you prefer.
However avoid to draw directly onto the texture, but unto a transparent bitmap of the same size.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 01, 2019, 09:17:25 pm
This is how UV coordinates are created in C4D when saving into a .psd file (see the red overlay)...

... only in case the mesh is quadrangulated where possible, rather than triangulated. OR only uses glDrawElements (GL_TRIANGLES, ...) to draw the surfaces and/or wireframes, and thus it always re-triangulates the model in its Mobj_importGeometrySecondPass() at model load time. This is what we'll see in our OR UV mapper in the end too except the wireframe will be made up of tris rather than quads, and the tri corners will be marked with bullets for easier point-and-dragging around the tex map.

if you have already a working solution, then we can go for it, if you prefer.
However avoid to draw directly onto the texture, but unto a transparent bitmap of the same size.

I only have a working Vertex Color Editor (with many associated features of a UV map editor) in my Xandreale game engine project I wrote ca. 10 years ago in FBSL BASIC, C, and 32-bit Asm. This is what you saw in my snapshots earlier in this thread. I will have to rewrite it in equivalent 64-bit CPP where possible (alas, 64-bit MS VC++ has no inline assembler available). I would have done it if only you weren't promoting your Tor solution at all costs. ;)

Let's finish off with your Tor protégé first, and I'll switch back to my simpler solution if Tor fails to do what we need. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 01, 2019, 10:20:21 pm
Quote
I would have done it if only you weren't promoting your Tor solution at all costs.
I am not promoting it at all costs, it is just one of the many ways to go to Rome…

However this one is based on the code that already exist in the GDImage64.dll, and thus something i could help with.
But there is no guarantee that my way would be better than yours. ;)

The important point in Tor.cpp, was the GUI interface that has been tailored to fit inside of OR asside of the splitter.
This part was already a huge work, and i like the result.
The use of a zoom window is also serving us well, to deal with the view port size that follows the splitter move.


Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 02, 2019, 02:08:59 pm
Here is an example of the Dragon's UV map exported from Blender (Don't ask me how i was able to produce it with their complex GUI interface, because i couldn't do it twice).

And as far as i understand what to do, we are concerned only by the red border surrounding the shadowed polypolygons.

It is quite a challenging work to create the correct POINTS array  :o


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 03, 2019, 02:33:22 pm
Quote
(Don't ask me how i was able to produce it with their complex GUI interface, because i couldn't do it twice)
;D ;D ;D ;D

Blender is a Linuxoid product. Linuxoids do not have GUI design skills or tradition, and GUIs of Blender level of complexity are certainly beyond their capabilities. And it is a real pity because functionally, Blender is a 100% professional software suite and a very good one at it.

Someone should do a great service to the humanity and go down in history by reworking Blender's crooked GUI to follow the principles of ergonomics and user-friendliness implemented in other similar editing environments like, say, Autodesk 3ds Max or Adobe Photoshop. The Blender source code is open to everyone, after all. :)

Quote
... we are concerned only by the red border ...

No, not in the least, my friend.

On the contrary, we are concerned by every line intersection point you're seeing in your upper UV map. These points (called UVs, or UV pairs) are the projections of model 3D vertices onto the texture map plane, and each flat triangle you're seeing is consequently the projection of a corresponding 3D mesh polygon (triangular rather than quadric in our case) onto the same plane. U stands for the plane X coordinate in a more customary high-school notation while V stands for the Y coordinate. Seldom used 3D textures also distinguish a third W coordinate to denote the texture "depth" level similar to the Z coordinate in our customary 3D space. 3D textures are sometimes used to efficiently colorize virtual volumes like sky clouds, or clouds of smoke, or street light volumes ("shafts").

In the most general case, a jaggie (or any other unwanted artifact) may occur at any point within the texture map borders. So, we should be able to drag an arbitrary triangular wireframe intersection point (i.e. some polygon corner or apex a.k.a. "vertex" in traditional 3D lingo), or some of them, manually a little around the nearby portions of texture map to try and hide the artifact from direct view if at all possible.

You've been evidently misled by the visible similarity of wireframe "islands" in the lower texture map with your USA outlines in your Tor demo video. :)

There's absolutely no problem to "project" the UVs written in the OBJ file and stored in their corresponding OR 3D vertex structures onto the texture plane. The UV (or XY, if you prefer) coordinates have already been pre-calculated and normalized to the [0.f,1.0f] range for you at model design time in the model designer's UV unwrapper software. All you have to do is multiply the floating-point U value by the texture pixel width, and V value, by the texture pixel height, and plot the resulting pixel point (a.k.a. apex, corner, vertex, UV, UV pair) in the texture map or against it if it is just a background "layer". However in practice it appears easier to denote the UVs as 3x3 px large boxes rather than just pixels (texels) in both 2D and 3D to be able to easily aim at them and select them for manual dragging as shown below.

(In Xandreale, I can select the UVs of interest (shown in red) in both 3D and 2D viewports whichever I find the easiest. What cannot be done in the existing 3D editing software but can be done in Xandreale is that you can walk up to any object of interest in the 3D viewport using the FPS (first-person-shooter) camera and mark manually any single vertex in the scene that you would like to work with in your current scene editor.)

OTOH drawing the associated wireframe map is more difficult in 2D GDI where I need to prepare a special UV (vertex, apex, etc) array in triples following the vertex indices that OpenGL uses to draw its GL_TRIANGLES (or GL_QUADS) based on the VBA or VBO data, and use a series of Polygon() API calls (or asingle  PolyPolygon() call) to draw the GDI equivalent of OpenGL wireframe projection on the texture map plane. Practice shows that drawing 30K of UVs using Polygon() is too slow due to the function call overhead while one single call to PolyPolygon() is almost as fast as its OpenGL glDrawElements(GL_TRIANGLES, ...) equivalent is for a VBA of polygons.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 03, 2019, 07:57:51 pm
Quote
However in practice it appears easier to denote the UVs as 3x3 px large boxes rather than just pixels (texels)
My idea was to mimic the PSD brush size for the hot spot, and the real pixel location would be always the width and height size divided by 2, indeed any odd square size value could be used to compute the correct pixel/texel location.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 04, 2019, 01:29:21 pm
Indeed, the hot spot itself could be a square polypolygon that could be resized on the fly, to always look the same (whatever the zoom being used).
We coul also create a region of interest to limit the size of the working area, there is already a Tor function to create such a section (search for TOR_CROP within the code).

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 13, 2019, 09:38:09 am
Because we are going on with Tor.

I shall post a new update with the latest change i have done (region of interest).
I have first to save the resulting region into a file, but to be really useful, we should save the x,y,w,h, coordinates to later put back the modified region at the correct location.
Working on a region of interest would limit the amount of points to render, and speed up the display.

Added:
The latest project is attached to this post.
Search for gT.nCropZoom, for the zoom factor to use with the region of interest.
See the video attached to the previous post on how to use the new crop button.

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 13, 2019, 02:27:00 pm
Working on a region of interest would limit the amount of points to render, and speed up the display.

That's a good idea! Don't you think that once selected, the region should replace the whole texture in both the Tor main view and selection thumbnail (where the red view rectangle is usually seen) in order to be able to further select a yet smaller region if needed?

Quote
See the video attached to the previous post on how to use the new crop button.

Looks good indeed!

1. There are two artifacts in the selection quadrangle -- a missing dot on the left, and an extra dot, on the right sides of it.

2. I think we should add a menu entry to be able to disallow sound notifications altogether. (though I like them; they add some charme to OR ;D)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 13, 2019, 02:59:42 pm
Quote
That's a good idea! Don't you think that once selected, the region should replace the whole texture in both the Tor main view and selection thumbnail (where the red view rectangle is usually seen) in order to be able to further select a yet smaller region if needed?
This is just a prototype, everything is possible. So far the zoom of the "region of interest" could be adjusted from a slider or a gauge.
If you run the program you will see that the selection thumbnail is already updated, and an arbitrary ratio of 4 is applied to the region of interest.

What i really need now is to get the correct UV's X,Y POINTs array, to move on.  ???
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 18, 2019, 10:46:22 pm
Hi Patrice,

I've implemented three nice additions to OR:I will send you my code tomorrow. I have yet to sort out which files have been modified in the process of implementation...

Stay tuned! 8)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 19, 2019, 09:57:12 am
Ok, looking forward for the new changes... and what about the long awaited XY point array  ;D

I am upgrading from C4D R17 to version R20
that should let me import Solidworks, STEP, Catia, JT and IGES CAD
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 19, 2019, 12:15:18 pm
Ok, looking forward for the new changes...

I'll clean up and upload the code after my lunch (it's 2 pm here now).

Quote
and what about the long awaited XY point array  ;D

Frankly, I don't understand what prevents you from building the arrays yourself; I think I've described a detailed algo a few times already. ;) OK I'll write the relevant code but you'll have to integrate it with Tor yourself because I'm reluctant to study its current functionality -- just as you are reluctant to read up on UV unwrapping and projection theory and practice. ;D

Quote
I am upgrading from C4D R17 to version R20
that should let me import Solidworks, STEP, Catia, JT and IGES CAD

I'm still nominally an employee at Serge's software company, so I've been able to use their corporate license to upgrade legally to Autodesk 3ds Max version 2018. I also installed their Autodesk Maya 2017 and am now able to read, edit, export, and convert .MA files.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 19, 2019, 04:09:18 pm
Here are the mods I was talking of. (Tor arrays will come later)

Please let me know if they work well for you.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 19, 2019, 05:01:50 pm
Downloaded, thank you!

I shall come back to you later.

Added:
The new VSYNC off mode, seems to work well by me, even with huge models.
Note: FPS count is always visible when VSYNC is off.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 19, 2019, 06:20:29 pm
The new VSYNC off mode, seems to work well by me, even with huge models.

That's good to hear! What about the other two features (gP.hGL redraw on WM_PAINT to avoid an empty viewport and GL_FLAT rendering in all shaders including fancy and design mode ones)?

Quote
Note: FPS count is always visible when VSYNC is off.

That's natural because we disable VSYNC to know the maximum FPS rate our video cards are able to achieve in an unconstrained continuous rendering mode. It's yet another indirect way to evaluate both the model complexity and the OR renderer efficiency. There's no other reason to switch VSYNC off.

Use VSYNC OFF with caution to avoid overheating your laptop video chip!
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 19, 2019, 06:47:00 pm
The GL_FLAT option does work well, even if useless with high poly models.
Quote
gP.hGL redraw on WM_PAINT to avoid an empty viewport
I have never seen an empty viewport on my gamer laptop, but that could make sense for other config, and the splitter redraw seems to be better when using double click on it to close/open.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 19, 2019, 07:07:23 pm
Watch the video below to see what I'd been seeing (or rather NOT seeing) all the time before I added the case WM_PAINT: handler to gl_WndProc():


[ADD]

The GL_FLAT option does work well, even if useless with high poly models.

I never add useless options to ObjReader, Patrice. Do you remember the times when you used to call the entire multi-texture PPL effort a useless and artistically barbaric stuff? ;)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 19, 2019, 08:58:07 pm
I couldn't duplicate the behavior by me, perhaps another difference between Windows 7 and 10.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 20, 2019, 11:02:42 am
I have upgraded my C4D R17 to version R20 PRIME
unfortunatly the import of: Solidworks, STEP, Catia, JT and IGES CAD are only available in the STUDIO version that is much more expensive! :(

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 21, 2019, 04:15:18 pm
Texture editor white paper:

1 - We must first select the mesh to work with (because the same texture could be used by several meshes)

2 - We must select the material to work with:
colorMapID
ambiMapID
bumpMapID
dispMapID
emitMapID
glossMapID

3 - Then select the correct mesh and material:
MobjMesh* pMesh = &gtm_meshes[select];
MobjMat* pMaterial = pMesh->pMaterial;


4 - Build the UV's array:
float* UVs = NULL;
GLuint index = pMesh->startIndex;
for (int j = 0; j < pMesh->triangleCount * 3; j++, index++) {
    UVs = gtm_vertexBuffer[gnm_indexBuffer[index]].texCoord;
    // The array must be set here
    // but i am unsure on how to convert UVs to texel/pixel POINTs coordinates
}

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 21, 2019, 08:04:51 pm
This is my vision of the same. :) (not actually tested; may contain bugs but the idea should be clear)


Texture editor white paper:

1 - We must first select the mesh to work with (because the same texture could be used by several meshes)

2 - Then select the correct mesh and material:

MobjMesh* pMesh = &gtm_meshes[select];
MobjMat* pMaterial = pMesh->pMaterial;


3 - We must select the tex map to work with from pMesh->pMaterial: (in many cases, any texture will do as they all have the same UVs for now)

colorMapID;  // these are OpenGL numeric texture "names" (IDs)
ambiMapID;
bumpMapID;
specMapID;
dispMapID;   // MLL 08-08-2018: heightmap ID
emitMapID;   // MLL 10-18-2018: map_Ke ID
glossMapID;   // MLL 10-18-2018: map_Ns ID
//(reflMapID UVs are generated automatically!)


4 - Build the selected mesh's UV and wireframe arrays. (those are different arrays!)

Building an array of Tor's unique tex map UVs/sprites/hotspots/bullets/whatever is not trivial because there's currently insufficient data in our existing structures. So for now, we'll start with drawing only the wireframe proper in the hDC of the bottom-most layer immediately above the texture image but below the sprites/hotspots/etc. so that they are not obscured by the wireframe lines.

The following is global code:

// TODO: Tor UVs/sprites/hotspots/bullets/whatever
// static FOO* torUVs = NULL; // any data type suitable for Tor sprite positioning
// Tor wireframe only
static POINT* torWireFrame = NULL; // array of wireframe vertex POINTs
static long* torVertCountPerPoly = NULL; // array of vert counts in each wireframe poly (actually 3 for all polies; see PolyPolygon() specs)


Now, the following goes into a dedicated procedure:

GLuint* index = &gnm_indexBuffer[pMesh->startIndex]];
int vertsTotal = pMesh->triangleCount * 3;
// TODO: Tor UVs/sprites/hotspots/bullets/whatever
// if (torUVs)
//     free(torUVs);
// torUVs = (FOO*)malloc(bar);
// Tor wireframe only
if (torWireFrame)
    free(torWireFrame);
torWireFrame = (POINT*)malloc(vertsTotal * sizeof(POINT));
if (torVertCountPerPoly)
    free(torVertCountPerPoly);
torVertCountPerPoly = (long*)malloc(pMesh->triangleCount * sizeof(long));

for (int j = 0; j < vertsTotal; j++, index++) {
    MobjVertexT* vertex = &gtm_vertexBuffer[gnm_indexBuffer[*index]];
    // We will have to keep track of images' actual pixel
    // sizes on model load or else use the ones from Tor
    torWireFrame[j].x = selTexWidthInPixels * fmod(vertex->texCoord[0], 1.0f); // OpenGL tex coords may be a multiple of 1.0f if GL_REPEATed
    torWireFrame[j].y = selTexHeightInPixels * fmod(vertex->texCoord[1], 1.0f); // ditto
}

for (int j = 0; j < pMesh->triangleCount; j++)
    torVertCountPerPoly[j] = 3; // three POINTs to each polygon (i.e. triangle)


5 - Whenever necessary, (re)draw the entire wireframe in the Tor bottom-most layer's hDC in one PolyPolygon() call using 1-pixel wide selectable-color pen and BS_HOLLOW brush:

PolyPolygon(bottomLayerHdc, torWireFrame, torVertCountPerPoly, gtm_meshes[select].triangleCount);

Hope this helps. :)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 21, 2019, 10:45:15 pm
In the above torWireFrame[j].y calc, the 3D tex coord may need to be flipped because of the differences in OpenGL and GDI coord origins, like so:

........
    torWireFrame[j].y = selTexHeightInPixels * (1.0f - fmod(vertex->texCoord[1], 1.0f)); // ditto
........
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 09:37:23 am
Thanks for the white paper feedback, now i shall try to turn it into real code, testing with a simple square surface (made of 8 triangles, 9 points) to work in debug mode.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 10:14:30 am
... and to compare the UV's map with the one created with Blender.

No, the Tor unwrapped wireframe on the flat 2D texture will look exactly like it looks wrapped over the 3D surface of the model as shown in ObjReader's Inspect->Wireframe overlay mode.

OR doesn't re-unwrap the UVs, it just uses the ones that have been written in the model's vertex data at model creation time. Tor should display the dragon's body UV wireframe against its diffuse map something like below: (picture generated in LithUnwrap)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 10:44:04 am
Dragon is too complex for now, i am trying with a simple flat square made of 8 triangles (9 points)

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 11:29:20 am
Here is the test project i have done to check the coordinnates


Code: [Select]
void CreatePointArray(IN long selected) { // 03-20-2019
    MobjMesh* pMesh = &gtm_meshes[selected];
    long* index = &gnm_indexBuffer[pMesh->startIndex];
    long vertsTotal = pMesh->triangleCount * 3;
    //if (gT.wireframe) { free(gT.wireframe); }
    //gT.wireframe = (POINT*)malloc(pMesh->triangleCount * sizeof(POINT));
    long x, y;
    long selTexWidthInPixels = 255, selTexHeightInPixels = 255;
    WCHAR zAf[64] = { 0 };
       
for (int j = 0; j < vertsTotal; j++, index++) {
    MobjVertexT* vertex = &gtm_vertexBuffer[gnm_indexBuffer[*index]];
    // We will have to keep track of images' actual pixel
    // sizes on model load or else use the ones from Tor
    x = selTexWidthInPixels * fmod(vertex->texCoord[0], 1.0f); // OpenGL tex coords may be a multiple of 1.0f if GL_REPEATed
    y = selTexHeightInPixels * fmod(vertex->texCoord[1], 1.0f); // ditto
    StringCchPrintf(zAf, strSize(zAf), L"x = %2d, y = %2d", x, y);
    zTrace(zAf);
}
}
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 01:05:26 pm
... i am trying with a simple flat square made of 8 triangles (9 points)

Here is the test project i have done to check the coordinnates

I believe you understand that your simple flat square model must have valid UVs unwrapped in a 3D editor and exported in the model OBJ file as vt directives?

[UPD] Oh, I see you attached your test square model and it has been UV unwrapped.

Quote
long selTexWidthInPixels = 255, selTexHeightInPixels = 255;

I'd expect both width and height to be 256/P.O.T. pixels each, not just 255... ::)

Quote
y = selTexHeightInPixels * fmod(vertex->texCoord[1], 1.0f);

It should be (1.0f - fmod(vertex->texCoord[1], 1.0f)) because OpenGL and GDI use different origins of their respective coordinate systems (bottom left and top left).
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 01:18:44 pm
So, what's the typical output of your test code in zTrace, please?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 01:36:38 pm
Here is the output in zTrace for a texture size of 256x256

x = 128, y = 128
x =  0, y = 128
x =  0, y = 256
x =  0, y = 256
x = 128, y = 128
x = 128, y = 128
x = 128, y = 128
x = 128, y = 256
x =  0, y = 128
x = 128, y = 128
x =  0, y = 256
x = 128, y = 128
x = 128, y = 128
x =  0, y = 128
x = 128, y = 128
x = 128, y = 128
x =  0, y = 256
x = 128, y = 256
x =  0, y = 256
x =  0, y = 128
x = 128, y = 128
x =  0, y = 256
x = 128, y = 128
x = 128, y = 128

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 03:23:21 pm
Looks very much true. Now let's hope the image in Tor will be close to the following: (only with 1-pixel wide lines everywhere)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 03:54:36 pm
No, the X,Y coordinates computation is wrong, see the red dots on the attached screen shot

Here is the code i am using to compute the X,Y dot location based on your suggestion.


void CreatePointArray(IN long selected) { // 03-20-2019
    MobjMesh* pMesh = &gtm_meshes[selected];
    long* index = &gnm_indexBuffer[pMesh->startIndex];
    long vertsTotal = pMesh->triangleCount * 3;

    long x = 0, y = 0, w = 0, h = 0, nW = 0, nH = 0, newID = 0, nIDtoClone = 0, nSpriteCount = 0;

    ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);

    WCHAR zMarker[MAX_PATH] = { 0 };
    Path_Combine(zMarker, MarkerPath(), L"dot_8.png");
    HBITMAP hBitmap = ZI_CreateBitmapFromFile(zMarker, w, h);
    long nCount = w / h; if ((nCount * h) != w) { nCount = 1; } else { w = h; }
    w /= 2;
    h /= 2;

    WCHAR zAf[64] = { 0 };
       
    for (int j = 0; j < vertsTotal; j++, index++) {
        MobjVertexT* vertex = &gtm_vertexBuffer[gnm_indexBuffer[*index]];

        x = (long) (nW * fmod(vertex->texCoord[0], 1.0f)) - w; // OpenGL tex coords may be a multiple of 1.0f if GL_REPEATed
        y = (long) (nH * (1.0f - fmod(vertex->texCoord[1], 1.0f))) - h; // ditto

        StringCchPrintf(zAf, strSize(zAf), L"x = %2d, y = %2d", x, y);
        zTrace(zAf);

        newID = IncrID(); // Increment ID and ga_Sprite array
        if (nIDtoClone) { // Clone the dot object (the same bitmap is used by all the hot spots)
            CloneObject(newID, $NULL, x, y, nIDtoClone);
            // Comme c'est un clone, il faut réinitialiser les propriétés de l'objet GDImage.
            ZD_SetObjectRotation(newID, 0);
            ZD_SetObjectFlipMode(newID, 0);
            ZD_SetObjectAngle(newID, 0, 0);
            ZD_SetObjectScale(newID, 0);
            ZD_SetObjectAlpha(newID, 255, FALSE);
            ZD_SetObjectFlipMode(newID, ZD_GetObjectFlipMode(newID));
            ZD_SetObjectVisibility(newID, ZS_VISIBLE);
        } else {                 // We must use this bitmap.
            ZD_DrawBitmapToCtrl(gT.hZoomCtrl, x, y, hBitmap, ZD_ColorARGB(255, 0), newID, ZS_VISIBLE);
            nIDtoClone = newID;
        }
        if (nCount > 1) {
            ZD_SetObjectFrameCount(newID, (BYTE) nCount); // <---- Sprite multi-state.
            ZD_SetObjectFrameToUse(newID, 1, FALSE);
        }
        ZD_SetObjectScroll(newID, TRUE);
        ZD_SetObjectQuality(newID, gT.UseQuality, FALSE);
        SpriteArrayInit(newID, zMarker);     // Initialize the global Sprite array
    }
    ZI_UpdateWindow(gT.hZoomCtrl, FALSE);
}
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 03:55:06 pm
No, the wireframe UVs aren't correct because 1.0f * 256 should yield 256 and not 0 which is due to fmod. Please remove the fmod() call. It should be omitted in the simplest case or replaced with if (vertex->texCoord[0|1] > 1.0f) etc. in GL_REPEAT cases (which might even be faster than fmod BTW...)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 04:02:38 pm
Patrice,

These ARE NOT bullet coords! These are wireframe triangle coords! Do not use them for bullets but only for the PolyPolygon() call!

The bullet array will be different; there will be only 9 UVs/bullets/sprites in it -- exactly how many distinct vertices there are in the model (actually, mesh)!
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 04:45:26 pm
So far all i want is the good algo to compute the correct DOT x,y location.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 04:55:21 pm
If by DOT you mean a bullet/sprite/whatever-you-call-those-red-circles-in-your-snapshots, then let me tell you that it WILL NOT help you draw the wireframe over the texture map. ;)

Those are two distinct problems, and wireframe is the easiest of the two. Let's do first things first. I've given you all the details how to implement it. Now just do it, please.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 07:09:58 pm
In the .obj file the texture coordinates are stored like this:

vt 0 0 0
vt 0 0.5 0
vt 0.5 0.5 0
vt 0.5 0 0
vt 1 0 0
vt 0 1 0
vt 0.5 1 0
vt 1 1 0
vt 1 0.5 0
# 9 texture coordinates

            case 't': // vt
                fscanf(pFile, "%f %f",
                    &grm_textureCoords[2 * numTexCoords],
                    &grm_textureCoords[2 * numTexCoords + 1]);
                ++numTexCoords;
                break;

This is exactly what i am looking for, to display my hot spots.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 08:30:42 pm
I have been able to display the hot spots, however it encompasses the internal GDImage maximum capacity, thus i have to think to another solution (perhaps point in triangle).
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 08:41:42 pm
Quote
This is exactly what i am looking for, to display my hot spots.

This is just your lucky chance, your very special case! :D

But where are they stored this way among the many meshes in your process memory in a general case -- after two rounds of Mobj_importGeometry? Especially if you're through with yet a hundred more rounds of editing your geometry and thus cannot simply read them up from the old .OBJ file... ;)

That is the question! (c) W.Shakespeare ;D
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 08:46:55 pm
I have been able to display the hot spots, however it encompasses the internal GDImage maximum capacity, thus i have to think to another solution (perhaps point in triangle).

Remember we're just exploring the limits of Tor. If it fails, we will simply revert to my Xandreale GDI code that can cope simultaneously with at least 30,000 UVs per mesh! (I just don't have .XAN models with larger meshes because they all come from a real console game we cracked with another French friend of mine about a decade ago)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 09:16:20 pm
Quote
Remember we're just exploring the limits of Tor. If it fails, we will simply revert to my Xandreale GDI code that can cope simultaneously with at least 30,000 UVs per mesh

Perhaps we can use your Xandreale code to create the transparent bitmap overlay, and use it within the zoom control ?


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 09:24:03 pm
... the transparent bitmap overlay ...

What exactly do you mean by this term? Please describe its content and function within Tor.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 09:34:17 pm
See the attached video.

Do you have a video or a working example of what your Xandreale code does ?
Is it able to produce 32-bit bitmap (with alpha channel) ?
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 10:05:55 pm
See the attached video.

Now I see, thank you.

Quote
Is it able to produce 32-bit bitmap (with alpha channel) ?

My Xandreale GDI code draws into the backbuffer where the texture image has first been drawn as the background. The entire backbuffer is then blitted on screen as necessary.

There's currently nothing to drag around or show the video of. 32-bit color transparency is not supported because it is unnecessary for the above technique. Neither is it available in the 24-bit GDI context at all.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 10:22:18 pm
Here's what I have. It's rough but it can can give you a general idea. The texture image is zoomable and so are the flat 1 px wide yellow wireframe/3x3 px cyan UV boxes.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 22, 2019, 11:09:19 pm
Thank you for the video, great piece of work, congratulation!





Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 22, 2019, 11:23:13 pm
Thank you! :)

This is a vertex color, not UV, editor so the UV boxes aren't draggable because the vertices stay put. But there's nothing to prevent us from making them draggable and redraw their position (and the associated wireframe triangles, and the associated tex map looks) in real time to immediately see the changes in both 3D and 2D viewports. 8)

The 2D UVs/3D vertices are selectable in the area mode (through the respective selection boxes as shown in the video clip) or one-by-one through point-and-click. The cursor shape changes according to the current selection mode. The video shows the cursors changing randomly but this is not how it looks in reality. (there was obviously a glitch in the obsolete video caption software I was using a decade ago)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 10:11:33 am
Quote
But there's nothing to prevent us from making them draggable and redraw their position (and the associated wireframe triangles, and the associated tex map looks) in real time to immediately see the changes in both 3D and 2D viewports.
This is what i wanted to do, but so far i was unable to build the correct XY array, i am able to retrieve the correct hot spot location (the triangle corners), but the polypolygon drawing is not correct because of the XY array order.
This is the main problem i have to sort out. My goal is to produce the transparent overlay shown on my video, and fulfill each of the triangle with a unique transparent color ranging from 1 to 16581375 (255x255x255) to ease the triangle detection. About GDI32 all drawing must be done in 32-bit to support the alpha channel, this is a mandatory when working in composited mode (Pandora internally works with 32-bit DIB bitmap to encompass the 16 GB limitation).
I shall have to try another approach to render correctly the transparent UV's map (overlay).
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 23, 2019, 11:43:03 am
... the polypolygon drawing is not correct because of the XY array order.

:o

Can you please illustrate this statement in some simple way, perhaps using that initial square test mesh?

The correct order of triangle corners for PolyPolygon is derived in POINT triplets transparently from the discrete vertex array (the one you're also using for the red bullets) based on the OpenGL index array -- the way we did it in our initial messages ## 65 through 76. The index array stores the indices of discrete vertex array elements (and hence, also their UVs) in triplets, duplicating/cloning the indices of unique vertices/UVs as needed to reuse them in individual triangles.

And that's also exactly how OpenGL draws its texture and wireframe triangles but using floating-point coords instead of PolyPolygon's literal integer POINTs.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 23, 2019, 11:52:42 am
Re. "transparency" in 24-bit GDI, it can be emulated by bit-blitting the 24-bit black-background wireframe over the 24-bit texture image using some raster op that's more advanced than the usual simple SRCCOPY (like SRCPAINT or SRCAND) to create the effect of combining the two "layers" in what Photoshop would call the "SCREEN" overlay mode in 32 bits.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 12:29:45 pm
I can provide a valid pandora DC to draw on, like this:

    HDC hIC = zDisplayDC();
    HBITMAP hBitmap = zCreateDIBSection(hIC, nW, nH, 32);
    HDC hDC = CreateCompatibleDC(hIC);
    SelectObject(hDC, hBitmap);
    DeleteDC(hIC);

draw polygon to DC

    then assign the hBitmap as an overlay into the zoom control

    DeleteDC(hDC);


I can also provide a dedicated gpDrawPoygon, build upon the GdipDrawPolygonI API (working with graphics).

Give me some time to write the correct code with the simple test.obj (Wife needs some attention first).


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 23, 2019, 01:09:41 pm
If you're planning to draw the wireframe to a transparent overlay, then it's probably more reasonable to use GdipDrawPolygonI(). OTOH some basic GDI graphics primitives are hardware accelerated while GDI+ is not, and PolyPolygon may arguably be significantly faster than its GDI+ GdipDrawPolygonI counterpart. ???
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 03:06:30 pm
Quote
and PolyPolygon may arguably be significantly faster than its GDI+ GdipDrawPolygonI counterpart.
This is not the case with the current OS, anyway here is a patch to let you try with the simple Test.obj model.

Look at the wip CreateUVmap subroutine, and see what happens with the triangle drawing.
(select the texture on the contact sheet to display the corresponding UV's map overlay).

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 05:54:16 pm
if you try it with dragon.obj, please add the code shown in red at the end of the subroutine.

    GdipDeletePen(pen);
    GdipDeleteGraphics(graphics);
    DeleteDC(hDC);
    newID = IncrID();
    ZD_DrawBitmapToCtrl(gT.hZoomCtrl, 0, 0, hBitmap, ZD_ColorARGB(255, 0), newID, ZS_VISIBLE);
    ZD_SetObjectScroll(newID, TRUE);
    ZI_UpdateWindow(gT.hZoomCtrl, FALSE);
}

This is to apply the same scrolling to the UV's map overlay than the underlaying texture when zooming.

Note: This array problem is what i have been asking to you, since the first Tor release, because i was unable to get the correct XY point location to draw each triangle polygon correctly :(

...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 23, 2019, 07:22:37 pm
Actually, indexing appeared easier than I thought. But anyway, I warned you there might be bugs in the untested code, didn't I? ;)

Use the following code in void CreateUVmap():


void CreateUVmap(IN long selected) { // 03-20-2019
    MobjMesh* pMesh = &gtm_meshes[selected];
    long index = gnm_indexBuffer[pMesh->startIndex];
    long vertsTotal = pMesh->triangleCount * 3;

    long x = 0, y = 0, w = 0, h = 0, nW = 0, nH = 0, newID = 0, nIDtoClone = 0, nSpriteCount = 0, color = 0;

    ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);

    HDC hIC = zDisplayDC();
    HBITMAP hBitmap = zCreateDIBSection(hIC, nW, nH, 32);
    HDC hDC = CreateCompatibleDC(hIC);
    SelectObject(hDC, hBitmap);
    DeleteDC(hIC);

    POINT pt[3] = { 0 };
    LONG_PTR graphics = 0, pen = 0, brush = 0;
    GdipCreateFromHDC(hDC, graphics);
    // Create a pen to draw with
    GdipCreatePen1(ZD_ColorARGB(255, RGB(255,0,0)), 1.0f, UnitPixel, pen);

    WCHAR zAf[64] = { 0 };
    long count = 0;
    for (int j = 0; j < vertsTotal; j++, index++) {
        MobjVertexT* vertex = &gtm_vertexBuffer[gnm_indexBuffer[index]];

        pt[count].x = x = (long) ((nW - 1) * vertex->texCoord[0]);
        pt[count].y = y = (long) ((nH - 1) * (1.0f - vertex->texCoord[1]));
        count++;
        if (count == 3) {
            // MLL: This is equivalent to GDI Polygon(), not PolyPolygon(), and is quite
            // slow to redraw large meshes in real time due to function call overhead... :(
            GdipCreateSolidFill(ZD_ColorARGB(32, color), brush); color++; // Use a unique color for each triangle
            GdipFillPolygon2I(graphics, brush, pt[0], count);
            GdipDeleteBrush(brush);

            GdipDrawPolygonI(graphics, pen, pt[0], count);
            count = 0;
        }

        //StringCchPrintf(zAf, strSize(zAf), L"%d: %f, %f   x = %2d, y = %2d", j+1, vertex->texCoord[0], vertex->texCoord[1], x, y);
        //zTrace(zAf);
    }

    GdipDeletePen(pen);
    GdipDeleteGraphics(graphics);
    DeleteDC(hDC);
    newID = IncrID();
    ZD_DrawBitmapToCtrl(gT.hZoomCtrl, 0, 0, hBitmap, ZD_ColorARGB(255, 0), newID, ZS_VISIBLE);
    ZD_SetObjectScroll(newID, TRUE);
    ZI_UpdateWindow(gT.hZoomCtrl, FALSE);
}


and enjoy your UV wireframes! :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 07:32:57 pm
Thank you very much my friend!

In the final version, the overlay shall be locked, to avoid unwanted move.

GdipFillPolygon2I is for test purpose only.

Now that we have the correct coordinates, we can try with polypolygon, to check for speed.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 23, 2019, 07:44:23 pm
Due to re-triangulation in Mobj_importGeometry2ndPass(), our index array also appeared to be indexed linearly starting with pMesh->startIndex! So, my initial pointer-based indexing was yielding indices into the index array, rather than indices into the vertex array... :D
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 23, 2019, 09:49:46 pm
I am happy, because now we can move on, without throwing the baby out with the bathwater.  8)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 24, 2019, 12:19:32 pm
Mike

What is the purpose of pMaterial->dispMapFilename ?

and pMaterial->dispMapFilename (d or dis) VS pMaterial->colorMapFilename (map_Kd) ?

To compute the correct mesh index for CreateUVmap(nMes), i am using this
nMesh = TorUVmesh();
if (nMesh > -1) {
    CreateUVmap(nMesh);
}


Code: [Select]
long TorUVmesh() {
    long nRet = -1, nI = 0;
    MobjMesh* pMesh;
    MobjMat* pMaterial;
    char zTex[MAX_PATH] = { 0 };
    WideCharToMultiByte(CP_ACP, 0, gT.zTex, -1, zTex, MAX_PATH, 0, 0);
    for (nI = 0; nI < gM.numberOfMeshes; ++nI) {
        pMesh = &gtm_meshes[nI];
        pMaterial = pMesh->pMaterial;
        if (_stricmp(zTex, (char*)pMaterial->colorMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->bumpMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->ambiMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->specMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        //if (_stricmp(zTex, (char*)pMaterial->reflMapFilename.c_str()) == 0) {
        //    nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->dispMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->emitMapFilename.c_str()) == 0) {
            nRet = nI; break; }
        if (_stricmp(zTex, (char*)pMaterial->glossMapFilename.c_str()) == 0) {
            nRet = nI; break; }
    }
    return nRet;
}

Does that is fine with you?

Note: there is still a bug in CreateUVmap when selecting a mesh greater than 0 (we must compute the correct index offset)

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 24, 2019, 01:48:22 pm
What is the purpose of pMaterial->dispMapFilename ?

The displacement (or height) map is a map that, in OR's context, is supposed to work in conjunction with the normal map to implement the parallax and/or bent normals effects. Both effects still need fixes but they will be eventually operable as expected.

Quote
... (d or dis) ...

It's neither d nor dis but disp in the material file.

Quote
Does that is fine with you?

If it works flawlessly for your purposes then it's perfectly OK with me.

Quote
Note: there is still a bug in CreateUVmap when selecting a mesh greater than 0 (we must compute the correct index offset)

Try this:

void CreateUVmap(IN long selected) { // 03-20-2019
    MobjMesh* pMesh = &gtm_meshes[selected];
    long index = pMesh->startIndex; // gnm_indexBuffer[pMesh->startIndex];
    long vertsTotal = pMesh->triangleCount * 3;
........


and tell me if it allows for correct selection of meshes > 0.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 24, 2019, 02:36:03 pm
Quote
and tell me if it allows for correct selection of meshes > 0.
Yes, now it retrieves the correct location, thank you!

In TorUVmesh(), there is no need to check for ambiMapFilename (dito reflMapFilename).

I think to add a button to save the UV's map (could be handy when reworking material with PSD), your thought ?

Now, i shall have to go outside to work in the garden for a couple hours (sculpting trees to make them look like bonzaï)  :D
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 24, 2019, 06:19:45 pm
1. Très bon ! The easier the better! :)

2. What do you mean? ambiMapFilename is the name of our AO maps that may cause the need for UV correction in the first place! But I agree, reflection maps are useless here because their UVs are generated automatically in both pipelines and thus can't be edited manually.

3. By all means go ahead and add it! You should use every possibility to add as many tools as you only can to OR to make your model design efforts easier. That's what its editing functions are for. :)

4.  :-* :-* :-* :-*
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 24, 2019, 08:12:14 pm
Here is the patch with the last changes.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 25, 2019, 08:03:11 pm
What is your preference, to display behind transparent texture:
a PSD like checkerboard, or the new uvcheck.png
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 25, 2019, 10:08:25 pm
:-*

IMO there should be 3 options: (in the preferred order)Also, the red color should be reserved for the UVs ("bullets") and the associated wireframe areas that have been explicitly selected for modification. Deselected items should have a different color to be chosen optionally so as to look prominent against the current texture map background.


(Note we will eventually need much much more free space for the UV editor options and settings than the current "toolbar"...)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 25, 2019, 11:14:33 pm
Re. your latest patch, when a mesh is (re)selected in a multi-mesh model, the user shouldn't have access to the tex maps that don't belong to that mesh's material. The top strip with the maps available for the current mesh should be updated in real time in response to the focus change in the mesh list.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 26, 2019, 01:59:06 pm
About CreateUVmap
Code: [Select]
void CreateUVmap(IN long selected) { // 03-20-2019
    MobjMesh* pMesh = &gtm_meshes[selected];
    long index = pMesh->startIndex; // gnm_indexBuffer[pMesh->startIndex];
    long vertsTotal = pMesh->triangleCount * 3;

    long x = 0, y = 0, w = 0, h = 0, nW = 0, nH = 0, nIDtoClone = 0, nSpriteCount = 0, color = 0;

    ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);

    HDC hIC = zDisplayDC();
    HBITMAP hBitmap = zCreateDIBSection(hIC, nW, nH, 32);
    HDC hDC = CreateCompatibleDC(hIC);
    SelectObject(hDC, hBitmap);
    DeleteDC(hIC);

                    //// Create a GDI32 transparent brush, to clear the bitmap background.
                    //HBRUSH hBrush = CreateSolidBrush(NULL);
                    //RECT r; SetRect(&r, 0, 0, nW, nH);
                    //FillRect(hDC, &r, hBrush);
                    //DeleteObject(hBrush);

    POINT pt[3] = { 0 };
    LONG_PTR graphics = 0, pen = 0, brush = 0;
    GdipCreateFromHDC(hDC, graphics);
    // Create a pen to draw with
    GdipCreatePen1(ZD_ColorARGB(128, RGB(0,0,0)), 1.0f, UnitPixel, pen); // Do not use RGB(255,0,255), this is reserved for transparent GIF color.

    //GdipCreateSolidFill(ZD_ColorARGB(64, RGB(225,225,225)), brush);

    //WCHAR zAf[64] = { 0 };
    long count = 0;

    for (int j = 0; j < vertsTotal; j++, index++) {
        MobjVertexT* vertex = &gtm_vertexBuffer[gnm_indexBuffer[index]];

        pt[count].x = x = (long) ((nW - 1) * vertex->texCoord[0]);
        pt[count].y = y = (long) ((nH - 1) * (1.0f - vertex->texCoord[1]));

        count++;
        if (count == 3) {

            //GdipCreateSolidFill(ZD_ColorARGB(32, color), brush); color++; // Use a unique color for each triangle
            //GdipFillPolygon2I(graphics, brush, pt[0], count);
            //GdipDeleteBrush(brush);

            GdipDrawPolygonI(graphics, pen, pt[0], count);
            count = 0;
        }

        //StringCchPrintf(zAf, strSize(zAf), L"%d: %f, %f   x = %2d, y = %2d", j+1, vertex->texCoord[0], vertex->texCoord[1], x, y);
        //zTrace(zAf);

    }

    //GdipDeleteBrush(brush);

    GdipDeletePen(pen);
    GdipDeleteGraphics(graphics);
    DeleteDC(hDC);
    gT.MapID = IncrID();
    ZD_DrawBitmapToCtrl(gT.hZoomCtrl, 0, 0, hBitmap, ZD_ColorARGB(255, 0), gT.MapID, ZS_VISIBLE);
    ZD_SetObjectScroll(gT.MapID, TRUE);
    SpriteArrayInit(gT.MapID, gT.MapFileName);
    ZI_UpdateWindow(gT.hZoomCtrl, FALSE);
}

pMesh->triangleCount, reports the whole number of triangles in the mesh, but the UV's triangle count could be much smaller than that.

In the attached example, there are 440 triangles in the mesh, but only two in the corresponding UV flat projection.

What do you think is the best solution to draw only once the two triangles matching the UV's flat projection?


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 26, 2019, 04:23:58 pm
pMesh->triangleCount, reports the whole number of triangles in the mesh, but the UV's triangle count could be much smaller than that.
No, it couldn't. There should be exactly as many UV tris as there are 3D mesh tris.

Quote
In the attached example, there are 440 triangles in the mesh, but only two in the corresponding UV flat projection.
No, the UV projection contains 440 flat tris, and this is correct. It is just that the 3D mesh tris reuse the same portions of (actually, the entire) texture map rather than form up so called "UV islands" on a much larger map such as seen e.g. in the dragon's UV wireframe. Generally, reusing/sharing/overlaying portions of mesh texture maps is considered bad practice in modern 3D design because it prohibits generation of correctly matching light, shadow (AO), and height maps that by the very definition of visual phenomena they are intended to emulate simply cannot be shared among individual polies or meshes.

That said,
Quote
What do you think is the best solution to draw only once the two triangles matching the UV's flat projection?
there is no solution because in fact, the flat projection contains not 2 but 440 tris.

In order to be able to select and adjust the UVs of every quad in the mesh as may be necessary, the tri corner UVs should be made slightly different in each quad at model design time. Then, the resolution/magnification of UV editor (such as Tor) should be made sufficient to visualize those differences in both wireframe layout and "bullet" positions to be able to select and drag the right "bullets" and adjust the looks of each quad as necessary if needed.

If the UVs of all the quads are exactly the same, then you are in big trouble in case you need to adjust only one, or a few, of the quads. Then whatever resolution Tor or any other UV editor has, you won't be able to point-and-drag the correct bullet(s). :)

Do you understand what I mean?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 26, 2019, 05:11:22 pm
If you look at the VT section within fur.obj


vt 1 1 0
vt 0 1 0
vt 0 0 0
vt 1 0 0
# 4 texture coordinates

you will see the original coordinates, my thought was to use them to compute the correct UV's map triangles, and in the case of "fur" using only 2 triangles rather than 440...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 26, 2019, 05:51:05 pm
There should have been 220, rather than 4, UV pairs* with slightly different values. Then the model modder (such as you) would've been able to readjust them in case his mod needs it.

Those are not the "original" coords. Those are the evidence of model author's goofiness (if he doesn't know what I'm telling you) or evil intent (if he knows and has done it on purpose to disallow others to mod this mesh). ;)

The "correct UV map triangles" (as well as normals and positions) are those 440 ones that are drawn in accordance with the mesh's actual 3D geometry coded in the face section of .OBJ file through f directives but not those that are written in the .OBJ file's reusable and "depersonalized" v, vt, and/or vn caches!

How can you foretell you (or yet another modder) won't ever want, or need, to remap one or more UV pairs of this mesh in the future to some other places within some other, perhaps artistically much better, map instead of this simple fur.png? ;)

My friend, you're seeing (seeking) things (to optimize) that aren't there.


_______________________________________
* BTW why does your SW generate an empty 3rd UV coord in each pair? Can you turn that annoying option off?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 26, 2019, 06:59:32 pm
Quote
BTW why does your SW generate an empty 3rd UV coord in each pair? Can you turn that annoying option off?
No, i couldn't.

Having the same triangle that could be drawn several time at the same location is a real problem, i have been fighting with this for 2 days  :-\

I have added the PSD checkerboard.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 26, 2019, 10:09:23 pm
No, i couldn't.
That's a pity!

I was planning to eventually use the 3rd and 4th columns in the UV (i.e. vt) statements as an alternative set of UV coordinates to be able to optionally utilize light maps that usually have a UV layout different from the other maps in a given material.

Quote
Having the same triangle that could be drawn several time at the same location is a real problem, i have been fighting with this for 2 days  :-\
My friend, next time before you decide to fight with something in OpenGL, please consult with me first. That's because it's highly likely going to be kind of windmill fighting to the detriment of planned functionality.

Tell you more: not only are we supposed to draw all the 440 triangles in that wireframe, but we are also going to put as many as 880 bullets (4 stacks by 220 bullets each) on top of their corners to be able to adjust the location of every corner in each triangle in case we'd so wish. It is not our concern or fault that all the UVs are originally the same. We should still be able to drag the four topmost bullets aside to get access to the 2nd layer of bullets, and then drag away that layer's bullets aside as well to get access to the 3rd layer of bullets, and then drag it away ... to get access to the 220th bottom-most layer and adjust its bullets' positions according to our design plans. Then we will go back up the stacked layers to restore or readjust their respective triangle corner bullet positions as we want or need. :)

Quote
I have added the PSD checkerboard.
Thank you!

If you want, we can generate such a texture purely programmatically similar to the checkerboard for the viewport stage.


P.S. What about my remarks in Reply #109?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 26, 2019, 11:23:31 pm
Quote
What about my remarks in Reply #109?
Because that was unclear to me, so far i was only dealing with the content of the contact sheet, and trying to figure the best way to store/retrieve the triangle hot spots. I have also to solve an array bound error, and a few other things before i could move on.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 27, 2019, 06:31:22 am
... an array bound error ...

Where's that?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 27, 2019, 10:14:39 am
This is an error in my checkerboard code.
I am fixing it.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 27, 2019, 08:10:11 pm
This is a backup version, with the new checker.png (see TilePaint), to display the checkerboard behind transparent png.

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 28, 2019, 04:32:45 am
My dear friend,

It looks very neat indeed and is fun to play with. :-*

But alas, it is very impractical to work with, at least in its present state. :-\

The major problem is that the wireframe/bullet overlay seems to be drawn only once and is then simply zoomed into/out of together with the texture image. This makes it impossible to either clearly see the wireframe or zero in on a bullet and drag it — at any zoom level other than the maximum/deepest one.

This isn't how it should be. A wireframe line should remain exactly one non-AA pixel thick, and a bullet, 3x3 non-AA pixels large, regardless of zoom level. This means the overlay should not be zoomed but rather redrawn each time the zoom depth is changed with the aid of the slider, or the zoom rectangle, dragged in the zoom widget.

The portion of the wireframe image to be drawn in the overlay should be enlarged according to the current zoom depth and clipped to within the zoom rectangle as seen in the zoom widget. This will dramatically reduce the number of wireframe tris and bullets to be drawn at any zoom level other than the full view, and drawing may arguably become significantly faster.

This tactics will enable the user to see, and work with, the UV mesh confidently at any zoom level rather than at the current deepest level only. The user then won't have to lose time adjusting the zoom just to make the wireframe visible, or dive to the deepest zoom to be able to drag one or two bullets around.

Do you think you can re-implement what I'm trying to describe?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 28, 2019, 10:17:32 am
I am well aware that it is not practical like this, so far i have been fighting with something else, and now that it has been solved i can move on (as i said it was just a backup for security purpose).

My idea was to work with a delimited section (region of interrest), and/or with a mouse hover to detect the red dots and display a marker that could be moved to change the underlaying UV's coordinate(s)

Using a bitmap with the red dot coordinates is the only pratical way to detect fast, a specific XY location, without scanning everytime a whole array.
The other way would be to save the triangle coordinates, and perform a PtInTriangle detection (working like PtInRect).

I am also trying from my best to reuse the existing Pandora's code to avoid code duplication, and use the existing mechanisms.

Because of the spring work i have to do for the house, my wife is exercing a hard pressure on the time i could spend on programming, thus slowing doing my progress and ruining my concentration  ::)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 28, 2019, 11:42:49 am
Thank you for the heads-up on your strategy! I'm looking forward to your progress in that direction. :)

Quote
Because of the spring work i have to do for the house, my wife is exercing a hard pressure on the time i could spend on programming ...

I understand those seasonal/rural factors perfectly well as I used to both have a wife and own a country cottage myself in the past as well. It is only too good you don't have to also plow your land in spring and shovel manure in summer to gather your harvest in autumn. :D

What regards me and my progress, I think we're going to see ObjReader's first practical FBO renders some time this week, most probably this weekend.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 28, 2019, 06:20:19 pm
Quote
What regards me and my progress, I think we're going to see ObjReader's first practical FBO renders some time this week, most probably this weekend.
Great news my friend!

Do you have a preference using

long dimDot  = (nW * nH) / 8;

between the new
long* Dot = new long[dimDot]; // Delete [] Dot
and the old
long* Dot = (long*) malloc(dimDot); // free(lDot);

to be used with BitSet and BitGet, to easily detect the triangle Dot locations without wasting memory.
BitGet(UsingLongArray(Dot), y * nH + x)

Note: nH is the stride value
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 28, 2019, 06:50:54 pm
1. Personally, I'd prefer to see long dimDot  = (nW * nH) >> 3;

2. If the Dot[] array isn't going to use CPP advanced features like quicksort or mapping, then I'd prefer to use long* Dot = (long*) malloc(dimDot); // free(Dot);. Our coding style is procedural ANSI C, not CPP, and it should look like one.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 28, 2019, 06:55:22 pm
OK, thank you!
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 30, 2019, 11:11:07 pm
I'm working, I'm working!!! :D
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 31, 2019, 03:06:59 pm
I finally found what was causing me the array bound error in CreateUVmap

I am using a bit array and a bitmap of the same size than the original texture size (nW = width, nH = height)

then i compute the x,y coordinate like this

x = (long) ((nW - 1) * vertex->texCoord[0]);
y = (long) ((nH - 1) * (1.0f - vertex->texCoord[1]));

to bitset a single bit at location y * nH + x
however both x and y computation could result in a value much larger than the nW width or the nH height.

Thus to protect from array bound error, i have used this

        // Detect unique dot
        if ((x < nW) && (y < nH)) {
            dotXY = y * nH + x;
            if (BitGet(Dot, dotXY) == 0) {
                BitSet(Dot, dotXY);
                ++dotCount; // Unique dot count
            }
        }


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 31, 2019, 03:31:13 pm
Thanks for the array bounds fixes! But I do not have any code in my Tor.cpp that would actually use either BitGet() or BitSet(). I've got only their implementations. ::)

Re. FBO, OR doesn't work for me either under my nVidia+W10 or ATi Radeon+W7. :(

I will need more time to check and fix the glitches. (everything's perfectly fine for me under my dev W7  :-\ )
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 31, 2019, 08:12:38 pm
I'm trying to isolate the cause of failure. But I'm almost certain it is a driver problem. Are you sure you have the latest driver for your nVidia card?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on March 31, 2019, 08:54:34 pm
I have the latest driver version 419.67 from 03-25-2019.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on March 31, 2019, 09:07:13 pm
Good.

I think it is not the FBO code that causes the failure. When it's removed, OR still tends to crash on my AMD/ATi box... :(

OK that's enough for today; I'm a bit tired...
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 01, 2019, 10:05:01 am
Most probably the problem is in gl_Init() (PixelFormat ?).
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 01, 2019, 11:03:13 am
No, my previous build (without the Tor and FBO code) enhanced with the new OpenGL 3.0 GL_ARB_framebuffer_object extension initialization in gl2.cpp and selection of simple pixel format in Mobj_choosePixelFormat() in mobj.h works flawlessly under both W10 and ATi/W7... ???

I need more time to check the code flow historically step by step to spot which mod exactly started to cause the OR crash.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 03, 2019, 06:41:14 pm
I have been fighting with a difference of behavior between VS2010 and VS2017 in GDimage64.dll, that was causing a problem when using WM_MOVING to move the Splitter.

This was because BitSet and BitGet are not working the same into the two compilers.  >:(

I have replaced the function calls with their define counterparts, and bingo that solve my problem.
#define BitSet(Array, BitPos)   ( Array[(BitPos >> 5)] |= (1 << (BitPos % 32)) )
#define BitReset(Array, BitPos) ( Array[(BitPos >> 5)] &= ~(1 << (BitPos % 32)) )
#define BitGet(Array, BitPos)   ( Array[(BitPos >> 5)] & (1 << (BitPos % 32)) )
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 04, 2019, 08:55:20 am
You could also try to split each expression into a series of equivalent arith operations. The way they are now is compact to write but difficult for the compiler to resolve. Such shit happens every now and then in any compiler, especially when some optimization mode is on.

For example, GCC which is also a mighty professional tool has difficulty to resolve the following expression and crashes the app:

drawMode = ++drawMode % 3; // !!! MLL: throws warning !!!

but compiles and runs OK when split into the following:

drawMode++; drawMode %= 3;

Go figure... ???
Title: Procrastination
Post by: Patrice Terrier on April 05, 2019, 01:59:51 pm
I think i have been hit by the same syndrome…  :-[
Title: Re: Procrastination
Post by: Michael Lobko-Lobanovsky on April 05, 2019, 03:30:14 pm
Hehe, it may also be what is called "blank page syndrome". That's when you can't make yourself do the work that has to be done from scratch/ground up, and you know in advance that it isn't going to be a piece of cake. (re. your Tor-based UV editor) ;)

Another probable cause may be your fatigue from your spring garden exercises.

And of course, my own alleged procrastination (actually, there isn't any; it's just that I've quite unexpectedly got a hellofalot of orders to work on for a living and I'm reluctant to reject any of them) has set a bad example for you. :)

To stir you to life just a little, let me tell you I was able to fix my ATi Radeon W7 rendering. Actually the crash wasn't caused so much by the FBO code but rather by my earlier GLSL flat shading fixes. The toon, X-ray and microscope shaders were failing to compile by the ATi GLSL compiler due to the differences with nVidia in its functional implementation. ATi GLSL forbids reassignment/reuse of varyings (i.e. inter-shader global vars) in the fragment shader. Contrary to nVidia GLSL, ATi regards them as constants and crashes at shader compile time. One more difference under my Radeon is that it allows only up to 8x MSAA for the FBO while my GTX 1060 supports 32x.

Unfortunately W10 still refuses to launch OR for operation as if it is an XP program that W10 doesn't provide a forcible compatibility mode for... :(
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 05, 2019, 05:26:39 pm
Quote
Hehe, it may also be what is called "blank page syndrome". That's when you can't make yourself do the work that has to be done from scratch/ground up, and you know in advance that it isn't going to be a piece of cake. (re. your Tor-based UV editor)

Indeed i am limited to 1024 objects/sprites/overlays/layers per graphic control, while i could extend this limitation it is not practical to extend it to more than 2048 that is still too few to render all the dots from a large UV's texture.

The only workable solution is to use a region of interrest, to stay within the 1024 limit, and consider only the UV's dots that are within the delimited section (PntInRect).

But my real problem, i that i am unsure that this is something that i would use myself to work with UV. However being able to create the UV's map transparent overlay is handy, because it allows me to use it as a helper to edit the texture in... PSD.

And i have a hard time to figure the other features that would make my 3D design easier than working directly with C4D.  :-X
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 05, 2019, 09:44:55 pm
Indeed i am limited to 1024 objects/sprites/overlays/layers per graphic control, while i could extend this limitation it is not practical to extend it to more than 2048 that is still too few to render all the dots from a large UV's texture.
Indeed those are very limiting factors.

Quote
And i have a hard time to figure the other features that would make my 3D design easier than working directly with C4D.  :-X
My friend, we can revert the code to pre-Tor state (actually, my test version I'm working with to debug the ATi/W10 glitch has no traces of Tor) and drop that matter till I translate my own FBSL code to CPP to implement a UV editor. Probably then you will be able to see the benefits of being able to fix the model UVs directly in OR.
____________________________________________________________

In the mean time, I have a suspicion that there may be compatibility issues between the VS 2008 DLLs I'm using and the VS 2013 OR that I generate. Every time I recompile the solution and have a new OR exe, its first launch for execution crashes under both nVidia and ATi W7's. Then, the OS throws a warning that it has set a compatibility mode for the program, and thereafter the exe starts and runs successfully on both video cards. Unfortunately, unlike W10, W7 doesn't notify me which compatibility mode exactly it has set.

My pandora code is very old and seems not compatible with the modern Splitter component. The OR binary throws an error on missing skButtonFoo/Bar/Baz entry points and aborts execution.

Can you provide me with fresher copies of pandora sources for me to be able to recompile usable VS 2013/2017 DLLs to try and resolve the compatibility issues? Probably it can help me resolve the W10/FBO collision too...

(Quote Patrice: AtiFbo.png (439.56 kB, 1189x755 - viewed 0 times.Unquote Patrice
Why wouldn't you even have a look at the screenie? I spent 7 hours rolling on my chair between the three PC boxes to make it work at least for ATi...  ??? :-\ :-[ :'()
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 05, 2019, 10:52:51 pm
Quote
Indeed those are very limiting factors.
No they aren't, it is just the constant value that i am using at compile time.

struct ZIMAGEPROP {
    HWND     hWnd;
    LONG     anchor;
    RECT     rc;
    HBITMAP  tiledBitmap;
    CHAR     order[2048]; // 2048 for 1024 objects
    LONG     ordersize;
    LONG     WMBit[32];
    LONG_PTR WMCodePtr[1024];
    LONG     centerx;
    LONG     centery;
    LONG     composited;
} ;


1024 is the value that i am using to sort out the z-order.

I shall attach the latest pandora version to this post (the one that is compatible with VS2017)

Quote
AtiFbo.png, why wouldn't you even have a look at the screenie?
Because i couldn't figure anything of what you have done from this static picture, that i have seen already on my Galaxy Note 3.  :-[

You know what to do with the attachment once downloaded...

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 05, 2019, 11:09:28 pm
Because i couldn't figure anything of what you have done from this static picture, that i have seen already on my Galaxy Note 3.  :-[
It displays an ATi logo to verify it's been taken on a Radeon GPU, and a vignette shader to prove FBO PP is now working on this HW platform too. Nothing much, really...

I shall attach the latest pandora version to this post (the one that is compatible with VS2017)
Muchas gracias, amigo.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 06, 2019, 10:29:38 am
So far i have an extra parameter: ZoomFactor, to increase the zooming and decrease the size of the region of interrest, the red rectangle shown on the top right thumb control.
I am also using a unique color to draw each dots, matching exactly each of the coordinates within the array indices.

What could be done with this:
is to display a sprite at the same x,y location, and drag it to the new coordinates, then press a button to redraw the UVmap and update the vertex->texCoord accordingly.

However we should find a convenient way to create a close relation between the vertex->texCoord and the unique dot location that could match indeed several overlapped triangles. You probably had to solve the same problem with what you have done in FSBL, and we could use the same.

Clear as mud?
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 06, 2019, 05:10:12 pm
Why no, on the contrary, clear and concise! :)

Quote
I am also using a unique color to draw each dots, matching exactly each of the coordinates within the array indices.
You're obviously doing this in order not to lose time searching the UV array to compare the cursor coords against the vertices. But you're seeing only a few dozens of thousands mesh UV bullets at the most. Even a linear search of such a relatively small array should be blazing fast at today's CPU clock speeds even if done on the FPU let alone integer comparisons.

Rainbow colors of bullets is another no-no IMHO.

Quote
... press a button to redraw the UVmap and update the vertex->texCoord accordingly.
No. The selected bullet position (i.e. mesh vertex UV pair) should change immediately on each cursor move, and the associated wireframe tris should be redrawn along with it.

Quote
You probably had to solve the same problem with what you have done in FSBL, and we could use the same.
Ten years ago I dealt with game levels (see below) that consisted of polygon groups. You may regard them as static models and meshes, respectively. The total size of a model varied between 50 to 250K polies with ca. 500 to 2200 meshes and ca. 850 to 2500 textures. So, an individual mesh size was on the order of a few thousand polies at the most. Therefore I used a linear search directly through the mesh vertices. The search procedures however were written in hand-optimized floating point assembly. I never experienced any visible lag to redraw the viewports when dragging a bullet or even a group of area-selected bullets.

Hopefully the same may be done for today's much larger meshes given our much faster modern CPUs. Let's be practical: your huge heavily subdivided meshes like hulls or shells usually don't use direct texturing except perhaps refl maps. Other textured meshes are usually up to 100K polies large, and character models are only a fraction of even that. I think wireframe redraws may well appear even slower than the associated linear search through an integer array. Note the search to determine the vertex index should be done only once at the first LMB down on the bullet you want to drag around.

All this should of course be tested and proven true or false.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 11, 2019, 07:44:19 pm
I am working back on Tor.  8)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 11, 2019, 08:05:20 pm
This sounds very encouraging indeed. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 15, 2019, 12:25:22 pm
Because UV's are unique to a specific material (newmtl), i couldn't see the point to render one for every texture size used with this material.

And because the textures are used only for a guidance, an UV's map of 2048x2048 should be quite enough to work with.

When editing the UV's to remove AO artefacts, that would also impact the other textures, thus extrem care must be used when changing the texCoord.
This is definitly not for the novice.

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 15, 2019, 01:11:31 pm
Because UV's are unique to a specific material (newmtl), i couldn't see the point to render one for every texture size used with this material.
..........................
When editing the UV's to remove AO artefacts, that would also impact the other textures, thus extrem care must be used when changing the texCoord.
This is definitly not for the novice.
I agree absolutely, on all the above points.

1. There's only one UV set in an OBJ file mesh. All the mesh textures can reuse it because UVs aren't expressed in absolute coords but rather in fractions of texture size (from 0.0 to 1.0). Very clever, I'd say! (but alas, not suitable for lightmaps that require a separate UV set because their topology differs from all the other textures)

2. But then, who said OR's editing modes (lighting editor included) are meant for the noobs? ;)

Quote
And because the textures are used only for a guidance, an UV's map of 2048x2048 should be quite enough to work with.
This statement needs proof. It denies precision in case the texture is huge but the details in it are still minute.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 15, 2019, 02:34:43 pm
Quote
This statement needs proof. It denies precision in case the texture is huge but the details in it are still minute.
The ultime precision is always one pixel, nothing more, nothing less, and due to rounding error when converting textcoord float to pixel, 2048x2048 seem to be a good compromise.

This is how i compute the final texcoord from the new pixel tx,ty texture location.

gtm_vertexBuffer[gnm_indexBuffer[mtl_index]].texCoord[0] = float(tx / float(bitmapWidth - 1));
gtm_vertexBuffer[gnm_indexBuffer[mtl_index]].texCoord[1] = float(1.0f - double(ty / float(bitmapHeight - 1)));
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 15, 2019, 05:03:01 pm
Hmm, isn't 1.0f - double(...) going to throw a warning about possible loss of precision? ???
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 15, 2019, 05:09:14 pm
you must read float instead of double, this was a survival of one of my many tests ;)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 15, 2019, 06:50:45 pm
No, I'm not talking about type propagation to achieve correct rounding precedence. I'm talking about an attempt to perform direct arith on different-precision values. It normally causes a warning by the C/C++ compiler unless one of the operands is explicitly cast to match the type of the other one.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 16, 2019, 08:53:35 pm
Here is a quick video preview to show you the Tor UV's editor in action.

The keyboard arrows are used to move up, down, left, and right, pixel by pixel.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 16, 2019, 10:01:18 pm
That looks cool indeed! 8)

I'm starting to believe the project is feasible, after all... :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 17, 2019, 11:31:10 am
For speed purpose i took the option to work with bit pointer directly within the UV's map memory bitmap.

I shall post a trial version later on, for you to test for speed on your computers if you are available?

Note 1: textcoord is updated in real time, thus in theory the changes should be visible when moving the splitter  ;)

Note 2: The .obj file is not updated yet, because i haven't thought yet on how to save the changes, this a point we must discuss together based on your futur plans.


Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 17, 2019, 11:56:32 am
... if you are available?
I'm always available for testing.

Quote
The .obj file is not updated yet, because i haven't thought yet on how to save the changes...
The file should be re-saved as Wavefront Object Specs-compliant in its entirety even if you change just one UV pair by just one pixel.

This means the entire model-loading tool chain should be re-created backwards to be able to reconstruct the OBJ file contents down to our metacommands based on the actual state of model data in the process memory as of the moment the Save button is pressed.

Sounds like it isn't going to be a piece of cake at all, doesn't it? ::)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 17, 2019, 03:54:09 pm
My friend.

Here is the new Tor, for test purpose.

We don't need anymore the extra "Marker" folder, because we do not use them.
My plan is to select a specific mesh from the  IDC_CHECKLIST to populate the contact sheet (not done yet), and hide all other controls from the right panel as long as Tor is visible.

Adjust the slider zoom to increase magnification and ease the hot spot selection (perhaps this could be done automatically).

Quote
Sounds like it isn't going to be a piece of cake at all, doesn't it?
So far the "save" button becomes visible when needed, but the ShallWeSave is empty ;)

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 17, 2019, 07:34:20 pm
My friend,

My sources have been severely affected by my FBO/PP WIP in general, and FBO W10/ATi compatibility issues in particular. So, they aren't now compatible with your project to an extent where I could just add those three files and proceed with testing. In fact, my sources are now completely devoid of Tor as a safety measure to make sure I'm using only rock-solid time-proven code for my experimentation to narrow down the bug-prone area in my FBO/PP efforts. :-[

Can you please supply me with a full set of your OR sources so I could roll back safely and test your recent Tor mods in an isolated environment?

TIA
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 17, 2019, 08:50:37 pm
Here it is…
(source code only)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 17, 2019, 11:38:46 pm
Haha thank you! :D

It works for me exactly as shown in your recent video! :)

I'm seeing bugs trying to also depict the current UV changes in gP.hGL in real time. I'll report on those later.

Good job, my friend! :D
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 18, 2019, 10:26:48 am
looks like you remove your latest message that i have seen only on my Galaxy note?
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 18, 2019, 10:36:28 am
(Yes, I did because here follows my full report)

Patrice,

1. BUG: please change the ptInCircle declaration to BOOL ptInCircle(...).

2. FEATURE: use the texture below to know your exact disposition in both 2D and 3D, and add the following code to your long CALLBACK CallBack_ZoomCtrl(...):

........
    case WM_KEYDOWN:
........
            // WE UPDATE THE UV texCoord HERE
            gtm_vertexBuffer[gnm_indexBuffer[gT.wasIndex]].texCoord[0] = float(gT.wasX / float(nW - 1));
            gtm_vertexBuffer[gnm_indexBuffer[gT.wasIndex]].texCoord[1] = float(1.0f - float(gT.wasY / float(nH - 1)));
            CreateUVmap(gT.meshselected, gT.wasIndex);

            wcscopy(sAf, STRL(gT.wasX)); Add_Str(sAf, L" ");
            SetWindowText(GetDlgItem(gT.hPanel, TOR_ID_COORD_X), sAf);
            SetWindowText(GetDlgItem(gT.hPanel, TOR_ID_COORD_Y), STRL(gT.wasY));
            ShowSaveButton();

            // MLL 04-18-2019: update VBO and redraw immediately
            long idx = gnm_indexBuffer[gT.wasIndex];
            glBindBuffer(GL_ARRAY_BUFFER, gP.nVBO);
            glBufferSubData(GL_ARRAY_BUFFER, idx * sizeof(MobjVertexT),
                sizeof(MobjVertexT), &gtm_vertexBuffer[idx]);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            gP.bRedraw = TRUE; gl_DrawScene();
        }
        break;
........


Now watch how different the OpenGL viewport events look from what we see in the GDI+ zoom control window. :D

This is exactly why I've always insisted on every change being immediately reflected in the 3D viewport. WYSIWYG is the key to success in visual design activities. 8)

3. BUG: if the texture is small enough like e.g. our neutral_bump.png, zooming it in the zoom control actually minifies it till it flips at zero size and then starts to grow to its original size.

4. BUG: Tor still doesn't reliably select and build the UV map for meshes other than the 0th one. In some models it does, but in many many others it doesn't. For instance, take a simple carousel.obj model and see that it doesn't build the UV map for any mesh in it other than center (OR logo)... :'(

5. BUG: Tor doesn't handle .TGA or .DDS textures.

6. FEATURE?: those blurry lines and bullets "are driving me slightly mad"(c) ... ;)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 18, 2019, 11:20:23 am
ptInCircle, is currently not used, it is there to remind me on how to do it.

Thanks for the texture!

Quote
Tor doesn't handle .TGA or .DDS textures.
I didn't even thought of those ;)


Quote
Tor still doesn't reliably select and build the UV map for meshes other than the 0th one.
Did you try to click on the check ListView to select a specific mesh?

Quote
those blurry lines and bullets "are driving me slightly mad"(c)
I did try to use something visible hover any texture background, but if you have another preference this is not a problem for me, except using RGB(255,0,255) that is a reserved color to achieve transparency with indexed color (mainly GIF).

About small texture size, i did not focuse on that problem, because until now my main concern was to find a relying way to move the hot spot in real time.

Now that texcoord update is solved, we can start to add bells and whistles.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 18, 2019, 11:30:11 am
Quote
Now watch how different the OpenGL viewport events look from what we see in the GDI+ zoom control window.
This is because the coordinates are inverted, we have to figure the best way to work around this problem into CreateUVmap.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 18, 2019, 12:40:16 pm
That's what I thought too when I first saw that "animation". ;)

Now take another, simpler chance with, say, the top left (LT) bullet and think deeper whether what you're seeing in 3D is correct. Account for the geometric vertex staying put where it is with only its UVs moving, say, down in 2D. Is the coloration of the two immobile 3D tris associated with that vertex correct given where the borders of their animated UV counterparts are sliding to in 2D?

Making the same two 3D tris occupy a smaller portion of their texture as their UV values grow smaller is equivalent to upscaling the texture visually larger. This is exactly what you're seeing in your 3D viewport. 8)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 18, 2019, 01:21:28 pm
ptInCircle, is currently not used, it is there to remind me on how to do it.
All silly 1-byte large bools have been changed throughout the entire OR sources to 4-byte BOOLs to ensure proper alignment of structure members on DWORD boundaries.

Quote
Thanks for the texture!
You're welcome! Alternatively, you can as well use the UV checker texture or, in fact, anything that helps maintain a clear view of your whereabouts.

Quote
I didn't even thought of those ;)
Frankly, I thought you should've incorporated .TGAs and .DDS's directly into your GDImage long ago. They are no worse than your beloved .PNG or .TIF formats that GDImage handles intrinsically.

Quote
Did you try to click on the check ListView to select a specific mesh?
Naturally, I did. Nothing happens in either carousel.obj or many more other meshes even if I manage to select a correct texture thumbnail in the list of textures irrelevant to the given mesh material. ;)

Quote
I did try to use something visible hover any texture background...
I'm not talking about the wireframe or bullet colors but rather about their blurriness (out-of-focus-ness) as the zoom-in ratio increases towards its maximum. I still insist that the thickness and size of lines and bullets at any magnification should stay 1 px and 3x3 pxs, respectively.

Quote
About small texture size, i did not focuse on that problem, because until now my main concern was to find a relying way to move the hot spot in real time.
Hopefully, you'll come back to that issue (I believe it is inherent in GDImage's implementation of Tor's inner functionality) when you have time for scheduled GDImage code maintenance.

Quote
Now that texcoord update is solved, we can start to add bells and whistles.
(https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/thumbs-up.png)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 18, 2019, 02:34:22 pm
looks like we have to find the good algo to convert correctly 3D coordinates into 2D coordinates…

Quote
I'm not talking about the wireframe or bullet colors but rather about their blurriness (out-of-focus-ness) as the zoom-in ratio increases towards its maximum. I still insist that the thickness and size of lines and bullets at any magnification should stay 1 px and 3x3 pxs, respectively
.
This is because i had to make a choice between speed and quality, speed means stretching the same bitmap what ever the zoom being used, that is of course causing the blur effect.  :-\

I have some urgent home work to perform first, before i could work more for my hobby.  ::)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 18, 2019, 10:02:56 pm
Quote
I thought you should've incorporated .TGAs and .DDS's directly into your GDImage long ago

I am working on it...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 08:07:54 am
Excellent! :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 19, 2019, 08:21:44 am
I shall post a Pandora's update today to let Tor be OR compliant :).
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 08:25:33 am
I'm looking forward to testing it against some of my TGA/DDS models! :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 19, 2019, 10:01:44 am
Here is pandora to test with your DDS/TGA models (with the updated source).

I only checked with TGA (Lion).

Next step, we must figure what to do to render correctly the 2D changes into the 3D view  :-\
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 12:41:27 pm
Here is pandora to test with your DDS/TGA models (with the updated source).
It works correctly for both .TGA and .DDS for me, thanks! Can the TGA and DDS code be now excluded (at least partially) from the OR code proper?

Quote
Next step, we must figure what to do to render correctly the 2D changes into the 3D view  :-\
Obviously you failed to get the meaning of my hints correctly... (which is of course entirely my own fault)

The 2D UV changes are rendered OK in the 3D viewport now. What you're seeing below is an absolutely correct effect of making the UV quadrangle occupy a twice smaller area in its texture. The LT/RT/RB/LB tags have drifted out of, and beyond, the 3D mesh borders, each in its respective direction.

Dragging the textured quadrangle hot spots towards its center to make it smaller in 2D is equivalent to dragging them away from its center making it larger in 3D. That's why the movement of a bullet in 2D and 3D is perceived to be taking place in opposite directions.

The four corners of the mesh in the 3D viewport is not the same thing as the four corners of its texture in the UV editor!!! :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 19, 2019, 01:44:29 pm
Quote
Can the TGA and DDS code be now excluded (at least partially) from the OR code proper?
I have to export them, and i did change the name from LoadTGATexture and LoadDDSTexture, to LoadTGA /LoadDDS.
I shall do this first thing.

Quote
Obviously you failed to get the meaning of my hints correctly…
The four corners of the mesh in the 3D viewport is not the same thing as the four corners of its texture in the UV editor!!! :)
I still have to figure what to do exactly :-[

I have also to check for small texture size...
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 01:57:05 pm
I still have to figure what to do exactly :-[

Please do not hesitate to ask in case anything is still not clear to you regarding the differences in 2D and 3D views. I know you must feel a bit dizzy till you get fully accustomed to considering the UV coords (and UV wireframe!) in 2D space as something different from, and not related to, the vertex geo coords and vertex wireframe in 3D space. And I know it takes time. :)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 02:06:21 pm
Tell you what, Patrice.

We must have a system-wide unlimited undo-redo stack in ObjReader similar to what you see in your C4D, and I see in all my 3D editors, in order to be able to revert some of, or discard entirely, our changes to UVs, or vertex positions (when we have a vertex editor), or lighting colors, to any depth at any time before we save our changes to disk. The stack must be universal to store efficiently any kind of data affected by our possible changes.

In case you just don't know what to do next with Tor, do you think you could design and implement such a stack?
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 02:27:46 pm
Tor's another very handy feature could be as follows.

(I think the zoom control should not rely on mouse hover on the hot spot to select it automatically. Selection should instead be done manually in response to an LMB down on the hot spot of interest only.)

So, when the LMB down occurs anywhere within the zoom control other than on a hot spot, it should be used (as the cursor shape currently suggests!) for clutching the zoom control viewport and dragging it around within the texture bounds similar to how the red square can now be dragged in the zoom widget. Then the user won't have to lose time aiming at the scroll bars to drag the 2D viewport here or there just a bit. Let the scroll bars stay for those who don't care about their time but also allow those who do care to be able to work in the 2D viewport more efficiently. :)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 02:44:59 pm
In the same vein, arrow keys are OK to control the selected bullet in test mode but generally, bullet repositioning should be done by LMB down and drag. It is much faster and handier and intuitive than what we have now.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 19, 2019, 06:43:01 pm
Here is a dual patch.

pandora.zip with new exported functions
C_IMPORT long      ZI_IsFileImage(IN WCHAR* zFileName);
C_IMPORT long      ZI_LoadTGA(IN WCHAR* ImgName, OUT LONG_PTR* img);
C_IMPORT long      ZI_LoadDDS(IN WCHAR* ImgName, OUT LONG_PTR* img, OUT LONG* nSwapColors);

Tor.zip (all DDS/TGA code removed)
Tor.cpp, Main.cpp, mobj.h, globals.h, GDImage.h, Tools.h

The 2D to 3D texCoord problem is still not solved, search in Tor.cpp for
// SetTexCoordinate

Solving TexCoordinate is the priority, i have to search on Google for a source of inspiration on how to convert efficiently 2D coordinates to 3D UV's (except if you remember what you did in your old FSBL code).

Quote
(I think the zoom control should not rely on mouse hover on the hot spot to select it automatically. Selection should instead be done manually in response to an LMB down on the hot spot of interest only.)
This is the purpose of ptInCircle to create a tolerance when selecting a hot spot with the mouse rather than mouse hover.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 07:50:54 pm
Thanks for the mods, Patrice! They fit in my .DDS and .TGA arsenal perfectly.

Can you please give me an exact description in your own words (don't mind the English grammar or do it in French if you find it easier) of what seems so problematic to you in your current implementation of 2D<->3D transform? What bad effects exactly the existing transform produces in the respective viewports?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 19, 2019, 09:15:29 pm
See the attached video.

This is the texture that fooled me at first, but now i understand that, Indeed, the mapping is absolutly correct.
As you said it is very important to look at the 3D view and the 2D's altogether to fine tune the map. and do some abstraction to understand how mapping is going on.

Once understood, the problem is solved, sorry for the confusion  :-[

Now i can move on, and make the use of the editor more intuitive.

Quote
Thanks for the mods, Patrice! They fit in my .DDS and .TGA arsenal perfectly.
Pandora's version is slighty different to preserve the pixels allocation, thus i am using a g_Pixels BYTE vector that is much more easy to deal with. And FlipY has also been changed to deal with the new vector array.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 19, 2019, 10:51:07 pm
See the attached video ... it is very important to look at the 3D view and the 2D's altogether to fine tune the map. and do some abstraction to understand how mapping is going on.

EXACTLY!!! The hot spot (bullet) you're dragging is definitely the wrong one to start with. There's so much going on in the bunch of affected tris that your mind simply refuses to analyze and accept the obvious. But once itemized into simpler events in just one or two tris, it suddenly dawns on you how it all works, and you start to feel yourself enlightened and in full control of this very important piece of knowledge and skill in your everyday design work! :D

Quote
... sorry for the confusion  :-[

You've got nothing to be ashamed of, my friend! It took me months to figure out the same things without assistance and formulate the importance of being able to simultaneously see the effect of my actions in THE BOTH viewports. And I'm glad I was around to reduce this fuzzy period to just a few hours in your case. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 21, 2019, 07:30:46 pm
My friend

What to do if the texCoord are not within the range 0.0f to 1.0f
See the attachment, when trying to display the Harley Quinn model

example of vt from the HQ.obj
vt -0.05420000106096 1.62569999694824 0
vt -0.08179999887943 1.60469996929169 0
vt -0.07450000196695 1.651899933815 0
vt -0.02749999985099 1.64749991893768 0
vt -0.11209999769926 1.63160002231598 0
vt -0.04580000042915 1.68409991264343 0

vt 1.3798999786377 1.87689995765686 0
vt 1.36230003833771 1.85829997062683 0
vt 1.38380002975464 1.85710000991821 0
vt 1.3643000125885 1.83739995956421 0
vt 1.38769996166229 1.83589994907379 0
vt 1.36619997024536 1.81639993190765 0
vt 1.39160001277924 1.81459999084473 0
# 2258 texture coordinates

Of course the computation of the resulting x,y coordinates are totaly wrong  ???
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 22, 2019, 02:28:49 am
Patrice,

This will require yet more effort on your behalf, my friend. Tor's zoom control must have the ability to not only zoom into the existing texture, but to also tile it, cross-wise, in any of the four directions while zooming, as many times as there are whole integer parts in the extreme floating-point UV coordinates of the mesh. (Think of how many of them would be cleared out if fmod() were applied). Then the offending UV coords would fit into the boundaries of their respective tiles, and the tris that are using those UVs would protrude in the correct directions as far as they should, again ultimately passing through as many tiles on their way as there are whole integer parts in the extreme UV floating point coords of a given mesh.

Then, when the pixel width and height of the texture involved in the calculation is multiplied times the number of whole integer parts in the extreme floating-point UVs, the calculations will return to normal again. But the zoom control should be prepared to depict those extended areas correctly in its 2D viewport too. You cannot simply wrap (map) the extended UVs to the same tile by fmod()'ing out the whole integer parts because then the tris associated with the extended UVs will not protrude in the correct directions.

Look again at the attachment to this message (http://www.objreader.com/index.php?topic=222.msg4710#msg4710) to see how Xandreale used to implement it in its vertex color editor.

Such mesh UVs occur quite often in tiled (GL_REPEATed) textures, but I think you should first get your one-tile (GL_CLAMPed_TO_EDGE) implementation straightened out and then proceed to that general-case extended solution... ???
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 22, 2019, 02:48:32 am
On giving it a second thought, in order to protect Tor against attempts to display what it currently can't do, the floating point UVs should be evaluated for fitting in the 0.f to 1.f range. Those UVs (and their associated tris!) that fall outside those extrema should be discarded when drawing the UV map.

It's going to narrow the visible and serviceable part of the UV map display but it will also definitely help to avoid meaningless smear in the 2D viewport, straighten out the calc, and preclude possible memory crashes.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 22, 2019, 11:26:49 am
I think i got it to work, crossing my fingers  :-X

To ease UV mapping every texture smaller than 1024, is now resized to 1024 (while preserving the real size of the disk file). Of course, resizing the 8x8 "neutral_bump.png" to 1024, would cause bluring on edges, but that's the best way to work with such a small texture in Tor.

I plan to add a tolerance to select a specific dot with the MLB, then i shall put a sprite at the selected x,y location to easily change the coordinates, just like what i am doing with a marker in gMap64.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 22, 2019, 09:43:14 pm
Patrice,

The tolerance should be +/-1 px with respect to the hot spot, i.e. 3x3 pxs all in all as I've been telling you all the time. Hopefully, the red sprite is going to be exactly that size?

Re. texture resizing, OK let's live and see how it works in practice.

Any further comments on what exactly have you got to work? Is it texture tiling for the protruding UV coords?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 22, 2019, 11:12:08 pm
i got "harley queen" VT to work in both 2d and 3d view.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 23, 2019, 12:16:49 am
May I ask how you managed to do that?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 23, 2019, 10:34:03 am
Here is the Tor.zip able to render VT texCoord that are out of the 0-1 range.
(see the attached harley_quinn.mp4 video)

Search for rxCoord, ryCoord

This version is also able to deal with small textures, look for the comment:
// Resize everything to at least 1024, to ease working with UV's map

Note: tolerance + LMB selection not done yet in this version.

But, our biggest challenge is to update the .obj file with the updated VT texCoord  :(
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 23, 2019, 12:18:20 pm
Thanks for the update, Patrice! Is the video supposed to carry your voice record? Unlike your former videos, this one only produces a few unintelligible sounds on all my players... :-\

I'll inspect your code and submit my review later as I have to attend to some real life duties first.


(our biggest and most immediate challenge is a full scale unlimited undo-redo stack to avoid possible irreparable damage to our model files likely to occur while debugging the .OBJ file save routines)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 23, 2019, 03:04:30 pm
No, there was no recorded voice of me in the video.

Quote
(our biggest and most immediate challenge is a full scale unlimited undo-redo stack to avoid possible irreparable damage to our model files likely to occur while debugging the .OBJ file save routines)
That's the easy part, first thing would be to create a .bak of the .obj when saving.
And as long as we test it, working on a copy rather than the original.

For undo-redo, a dynamic global vector array is what i would use, with a structure like this.

struct UNDO_REDO {
    long idx;
    float texCoord[2];
}
to save the
gtm_vertexBuffer[idx].texCoord[0]
gtm_vertexBuffer[idx].texCoord[1]
and two new buttons for undo, redo, and perhaps a third one to restore everything.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 23, 2019, 08:23:53 pm
Since you refuse to describe verbally your train of thought while implementing your patch, I'll base my comments on what I could gather from the mods.

Here is the Tor.zip able to render VT texCoord that are out of the 0-1 range.
No, this Tor is only able to discard the UVs and tris that are at least partially out of the 0-1 range.

Quote
Search for rxCoord, ryCoord
These two functions are in fact your custom implementation of fast fmod(coord, 1.f) used to actually discard the UV coords that exceed the 0-1 range. If Tor doesn't entirely discard the tris in the areas that it can't draw, then it's going to draw them incorrectly. Consider the picture below. Tor can't draw the ABC tri because the C apex belongs to Tile 1 and is thus out of Tor's reach. If the entire tri isn't discarded from the drawing process, then on fmod()'ing its C apex down to C', the tri will be drawn as ABC', which is totally wrong.

This solution will help us survive for the time being. But it doesn't allow us to work with textures that are tiled (GL_REPEATed) purposefully in order to map some UVs, or triangles, or even the entire mesh across tiles 0, 1, 2, ..., etc. or arbitrarily in any of these tiles at the model designer's option.

Am I correct in my deductions?
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 23, 2019, 08:40:53 pm
For undo-redo, a dynamic global vector array is what i would use, with a structure like this.

struct UNDO_REDO {
    long idx;
    float texCoord[2];
}
to save the
gtm_vertexBuffer[idx].texCoord[0]
gtm_vertexBuffer[idx].texCoord[1]

This isn't sufficient. The stack should handle all data modifications that OR's editors are able to offer. ObjReader currently has 2 editors (lighting and texture) but your UNDO_REDO handles separate UVs only. It should be augmented with a flag to indicate what type of undo/redo operation exactly the current entry actually describes, and a union that would host any structure types we might need to restore the OR states (lights, texture UVs, vertex geo coords, etc.) arbitrarily step by step or across or over a number of steps.

Also consider group selection modes whereby an arbitrary number of indices with various associated data should be stored in one step...
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 23, 2019, 09:41:56 pm
Quote
This isn't sufficient. The stack should handle all data modifications that OR's editors are able to offer.
I am walking one step after another, and so far UV map is my first editor's step.

About tiled texture i have to search a model from my collection to experiment with, because so far i couldn't remember of any.

To create the UV projection, most Google suggestions were based on the use of matrix, or the use of gluProject/gluUnProject to map object coordinates to window coordinates (also based on matrix).
https://docs.microsoft.com/en-us/windows/desktop/opengl/gluproject

https://www.khronos.org/opengl/wiki/GluProject_and_gluUnProject_code

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 05:51:54 am
I am walking one step after another, and so far UV map is my first editor's step.
OK probably I'm running too fast. My idea was to try and design a viable universal undo/redo scheme right from the start, so that each new editing feature we're adding wouldn't require reshuffling lots of earlier code to adapt to new functionality.

But no, your first editor was the lighting editor. So now you have two editors to cater for in one undo/redo stack and you're likely to have still more of them in the future. ;)

Quote
About tiled texture i have to search a model from my collection to experiment with, because so far i couldn't remember of any.
I'll try to create a simple test model+texture for you this afternoon with one set of UVs shifted to cross the border of two tiles midways (like in my previous elementary example), and yet another one, shifted entirely to, say, tile 3 or 4 absolutely out of Tor's current reach. Tor will have to cope with both UV sets and allow us to control their map bullets/hot spots in their natural environment as easily as it currently does entirely within the boundaries of tile 0. We shouldn't simply discard the whole integer part of UVs to narrow them down to tile 0, but rather extend Tor's display area to be able to draw the virtual tiles when needed, and its hot spot overlay, to draw the entire matching UV wireframe in its true UV coords.

I believe there is absolutely no other way to implement it efficiently in the zoom control viewport other than by tiling the texture cross-wise in the direction(s) where the UVs actually protrude.

Quote
To create the UV projection ...
We do not need to create projections. They have already been created for us by the people who designed the model textures and stored their projected VT values in the model files. We need only to remap those values from their relative FPU representations to the textures' true pixel widths and heights. We can now do this for tile 0 but we have to also be able to do it for the virtual widths and heights of the entire rows of tiles where the model UVs actually protrude.

And Tor should also be made ready to display not only tile 0, but also the entire cross of tiles with the UV map extending from physical tile 0 into the surrounding virtual tiles. Think of how your physical desktop window coordinates on your primary monitor are extended into the virtual desktop on your adjacent secondary monitors.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 08:02:06 am
My friend

As you know it, i am reworking all the models without exception before posting them on our forum, thus if one doesn't fit into our existing paradigm is doesn't figure into the collection.
Quote
And Tor should also be made ready to display not only tile 0, but also the entire cross of tiles with the UV map extending from physical tile 0 into the surrounding virtual tiles.
About Harley-quinn, the original UV map is preserved even after editing the texCoord (or the changes won't work), thus i don't think that we must spend too much time on this, as long as the editor allows us to edit the WYSIWYG part.

As you can see in the code below, i am restoring the floor part of the textCoord before updating.

            // WE UPDATE THE UV texCoord HERE
            long idx = gnm_indexBuffer[gT.wasIndex];
            // SetTexCoordinate
            rx = gtm_vertexBuffer[idx].texCoord[0] - rxCoord(idx);
            ry = gtm_vertexBuffer[idx].texCoord[1] - ryCoord(idx);
            gtm_vertexBuffer[idx].texCoord[0] = rx + float(gT.wasX / float(nW - 1));
            gtm_vertexBuffer[idx].texCoord[1] = ry + float(1.0f - float(gT.wasY / float(nH - 1)));



I made these changes to use your fast_fmodf, but i can't see any measurable speed enhancement  :-[
float rxCoord(IN long idx) {
    return gtm_vertexBuffer[idx].texCoord[0] - ((int)(gtm_vertexBuffer[idx].texCoord[0] / 1.0f)) * 1.0f;
    //return gtm_vertexBuffer[idx].texCoord[0] - floor(gtm_vertexBuffer[idx].texCoord[0]);
}

float ryCoord(IN long idx) {
   return gtm_vertexBuffer[idx].texCoord[1] - ((int)(gtm_vertexBuffer[idx].texCoord[1] / 1.0f)) * 1.0f;
    //return gtm_vertexBuffer[idx].texCoord[1] - floor(gtm_vertexBuffer[idx].texCoord[1]);
}
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 08:48:03 am
My friend,

Do you realize and acknowledge that currently, Tor isn't able to display the correct disposition of the triangle ABC as per my earlier message (http://www.objreader.com/index.php?topic=222.msg4990#msg4990)? It isn't even aware that the coords of C are in fact located in Tile 1 rather than Tile 0 because all it sees is the castrated fmod'ed coords of Cprime. Therefore, it is 100% going to distort the UV map by drawing the triangle as ABCprime. How are we then to know that what we're seeing in the zoom control viewport is exactly what happens in the mesh texture mapping, and how are we to locate the correct hot spots, and where to drag the "virtual" Cprime hot spot even if in the end we're somehow able to guess that Cprime is in fact the misplaced C apex? ::)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 09:14:01 am
Michael

In the case of Harley_quinn, i have checked the UV map produced by Tor and C4D's, they are both the same except a little offset of 1 pixel on both X,Y (the pen size), that is easy to fix.

To say the truth i can't aknowledge anything without experimentation, because it sounds a little like Hebrew to me.  :-[

A model example is the only thing that could help me to figure what to do, after comparison with the UV map produced on it by C4D, that was my leading edge reference.

And as far as i can imagine, tiling mode is NEVER used to create AO's texture.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 11:48:28 am
Quote
And as far as i can imagine, tiling mode is NEVER used to create AO's texture.
That's correct, but AO is the only texture that can't be tiled because no two parts of the same mesh may have one and the same shadow pattern. Therefore, the use of AO in an .OBJ model requires that the mesh's all other textures be generated similar to AO as clamped to edge, and host the mesh's entire UV topology without overlapping regions. But it only applies to those model formats that support only one UV set per mesh. There are however many formats that support from two to an infinite number of UV sets per mesh.

Re. acknowledgment, I'm hoping to demonstrate it on my test model later today or tonight. :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 11:57:07 am
Quote
and host the mesh's entire UV topology without overlapping regions
Yes, overlapping regions is a terrible mess when working with AO's, forcing me to split the mesh into distinct individual pieces within C4D.

I have learned this the hard way ::)

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 12:05:51 pm
See the overlapping sections when creating the UV's map for the "harley_quinn" colants material.

To solve this, the crossed legs must be splitted into two distinct meshes.
Because the editor couldn't help in such a case.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 07:04:42 pm
Here is what i have done so far to select/move the hot spot with the LMB (and to complete arrow keys move).

Tell me what you think of the selection tolerance (line 734).
Note: we could replace PtInRect from line 737 with ptInCircle.

Make sure to put the new "dot.png" into the "Reader" folder.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 07:15:26 pm
Yes Patrice,

I understand all the implications clearly. Probably C4D's AO ray tracer algo can't cope with such situations without texture remapping, and her collants were ray-traced for AO in a better editor or were hand-painted altogether.

In the meantime, I can't yet spare much time for 3D design but I found a relatively simple and very amateurish MilkShape .MS3D model with all the tex mapping horrors in its Detail2 mesh you could only imagine. Its conversion to an .OBJ went well, so now you can see for yourself that Tor's UV map has nothing in common with the original UV map (screened below at 0.15 and 1.0 magnification) as seen in MilkShape's texture editor:

.... <snip> ....
vt -2.0832 0.5766
vt -2.0832 0.6574
vt -2.0819 0.6114
vt -2.0819 0.7019
vt -2.0802 -1.6344
vt -2.0802 -0.4796
vt -2.0802 0.5114
vt -2.0802 1.6662
vt -2.079 0.1397
vt -2.079 0.4164
vt -2.0775 -0.9489
.... <snip> ....


though those are the correct values that map well into the model if I load the new .OBJ back into MilkShape. (it can load a ton of old 3D formats but is limited only to 64K verts or tris, whichever is the highest)

P.S. Thanks for the update!
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 07:49:53 pm
The tolerance seems OK for the bullet this size. However, the cursor fist seems to obscure the exact location where I might want to drop the bullet at. And one more thing: when I'm dropping the bullet by releasing the LMB, the tri(s) seem(s) to redraw at a slightly different location than they were drawn when last dragged. Which means that, when I am to decide if I should drop the bullet at a given location or not, I'm still not seeing exactly what the wireframe will look like when I release the LMB.

(Nice work, my friend! I still don't know what's going to come out of it in the end but I certainly like the process even if it might be somewhat too laborious for you) :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 08:57:41 pm
For the mouse cursor you can try this in the CallBack_ZoomCtrl

    //case WM_SETCURSOR:
    //    GetWindowRect(hWnd, &rw);
    //    GetClientRect(hWnd, &lpr);
    //    GetCursorPos(&p);
    //    if ((p.y < rw.top + lpr.bottom) && (p.x < rw.left + lpr.right)) {
    //        SetCursor(LoadCursor(NULL, IDC_CROSS));
    //        nRet = 1;
    //    }
    //    break;
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 09:55:37 pm
Do we really need a cursor at all when we're dragging the bullet that's already a cursor in itself all right?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 10:01:04 pm
I have checked StarFury (thanks for the download), this is a model that i would have reworked totaly in C4D before using it in OR.

Currently i am focusing on textures that are AO compatible, because this is a mandatory to produce state of the art OR 3D models, everything else is not on my schedule for now.  8)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 24, 2019, 10:16:31 pm
Got it.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 24, 2019, 10:29:05 pm
Quote
Do we really need a cursor at all when we're dragging the bullet that's already a cursor in itself all right?

I am using a sprite/marker to rely on the existing GDImage default processing.
And because a sprite could have multiple states, to match different purposes.

About the mouse cursor itself we can use a custom one if you prefer, rather than the standard arrow.

Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 25, 2019, 09:56:35 am
Is that any better to select a specific dot?

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 25, 2019, 11:01:13 am
Patrice,

1. Red color is the color reserved for selection. Can the UV hot spots be normally colored with some different clear color, say, cyan or white?

2. When at low zoom levels, both the cross and the fist obscure the entire bullet and texture area beneath it so that the user can't clearly see the exact spot to drop the bullet on. Can there be no cursor seen at all while the bullet is in the process of dragging?

3. When the LMB is released and the bullet is dropped, the zoom control redraws the wireframe tris associated with the hot spot being dragged, at a position slightly different from what it was when the mouse stopped right before the LMB was released. This means the hot spot being dragged always lags one step behind the red bullet while dragging. I don't think that's logically correct. Instead, the hot spot should always be exactly beneath the red bullet all the way while dragged.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 30, 2019, 02:36:32 pm
I will be delighted to test it. It will hopefully bring me back to work. Spring time is so distracting... :)
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 30, 2019, 05:13:53 pm
Here it is…

If that works, then we will have to figure what to do, for updating the .obj file.
This is where the work you have done 10 years ago could come to rescue   8)
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 30, 2019, 05:36:58 pm
Here it is…
Downloaded, thanks!

Quote
This is where the work you have done 10 years ago could come to rescue   8)
Yes, we had a plugin that was able, to an extent, to export some .XAN binary data to a simplified .OBJ file. .XANs used to have features unsupported by the Wavefront specs. I can't recollect now exactly how good or bad the exporter was. But it can certainly serve as a starting point for adding this feature to ObjReader.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on April 30, 2019, 11:35:53 pm
OK Patrice,

That's a good start for the Undo/Redo stack indeed! My observations follow below:

0. What's the big idea behind changing all the literal #defines in the file to const ints?

1. The current stack is too granular, hence excessive in the number of events to store. Instead, it should follow a pattern like this:2. The stack should be able to branch and clear/release the steps that become unreachable due to an alternative later action taken somewhere along the current branch, for example like this:3. It would be terrific to have a visual representation of Undo/Redo stack in a windowed list view like in the Paint.NET screenie below. There you can see a short series of actions taken on a loaded image. Following the Eraser action, the stack is rolled back by clicking Rectangle Select again, and the actions undone below it are grayed out. If we now take an alternative branch of actions, say, move the selection instead of erasing it, all the grayed actions will disappear from the list view, and the entire actual list of actions on the stack will turn to i) Open Image, ii) Rectangle Select, and iii) Move Selection.

Do you see my points and do you think you'll be able to implement such an ideal vision of what the point-and-click Undo/Redo stack should be like?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on April 30, 2019, 11:44:47 pm
The huge granularity is because of the use of arrow keys, that move one pixel at a time.
But in case of mouse move, we could just consider the mouse down and up event.

The use of "const int" is to follow the current VS recommendation, that is even more enforced on VS 2019 that complaints everytime it encounters a "define".

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 01, 2019, 12:12:08 am
The huge granularity is because of the use of arrow keys, that move one pixel at a time.
But in case of mouse move, we could just consider the mouse down and up event.
No! No compromises, my friend!!

Keyboard key auto-repeat generates a series of WM_KEYDOWN messages only without matching key-ups until the key is physically released. Technically speaking, there is no difference between handling arrow keys and LMB presses, so the both options should be handled identically.

Quote
The use of "const int" is to follow the current VS recommendation, that is even more enforced on VS 2019 that complaints everytime it encounters a "define".
The current VS recommendation pertains to the current C++ compiler and may very well be sub-optimal for earlier compiler builds. Please #ifdef/#if defined(...) (or similar) your VS2019 bells and whistles for other compilers to generate solid code based on their own code of conduct. Or simply suppress your VS2019 warning code altogether.

const ints are initialized memory objects while #defines are mere PP substitutions that don't eat up process memory at run time.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 01, 2019, 02:15:30 pm
To please you, #define has been restored.

There is a new parameter gT.UpDown (IsUp/IsDown) that is used to reduce the stack granularity.

Note: Using the button "Save tex UV", clears the stack history.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 01, 2019, 07:16:30 pm
Thanks, this one seems better, granularity-wise. Not perfect though:

1. When I first home on a hot spot with the cross and press the LMB to drag the red bullet, I can't do it: it won't move. I have to first release the LMB and then press it again to start dragging. These two events go on the UR stack as two separate actions, so that when I unwind the stack to its beginning, the very last action (immediately before the Undo button goes gray) doesn't move the bullet anywhere as it's already at its origin where dragging started. This "empty" LMB down/up may however be somehow (although with a considerable stretch) classified as a distinct "hot-spot selection" event, and as such may have a (weak) reason to live.

2. But the above "empty" LMB down/up also occurs any time I release the LMB and then press it again to resume dragging to a new location. When unwound by one action, the stack brings me to the previous location, then yet one more action unwound, the bullet just stays where it is, and then unwound for the third time, the stack moves finally to the yet farther previous location.

This glitch is unjustifiable because the hot spot (and bullet position) was already selected and hasn't yet changed. Which means the stack is still almost double-oversized against what it should be.

3. This unwanted phenomenon doesn't occur when dragging the bullet by arrow key auto-repeat, and that in fact is good.

Note: the stack still isn't brancheable and stores the entire sequence of actions not partially cleared regardless of my unwinding it to some previous state and taking a different route for dragging the bullet from that midpoint. Thus, when I start to Redo the actions again, I'm still brought to all the locations I used to visit despite my having taken an alternative midway action that should've cancelled the locations visited after that midpoint had been visited for the first time.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 02, 2019, 11:07:13 am
Quote
Also, please acknowledge that you understand fully my stack branching/clearing concerns that I'm trying to describe to you in my numerous notes to my recent messages.
Yes, i understood them perfectly well, i just have to figure the best way to do it.
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 02, 2019, 06:58:28 pm
ID_DOT drag, is now performed asap during WM_LBUTTONDOWN rather than WM_MOUSEMOVE, to bypass the default GDImage click and drag processing.

Undo/Redo action has been revisited to avoid storing twice the same coordinates
        // Save for UnDo/ReDo action
        if (MoveDOT) {
            if (gT.UpDown) {
                if ((lastX != x) || (lastY != y)) {
                    nItem = UBOUND(g_UR);
                    g_UR.resize(nItem + 1);
                    g_UR[nItem].idx = idx;
                    g_UR[nItem].index = gT.wasIndex;
                    g_UR[nItem].wasX = gT.wasX;
                    g_UR[nItem].wasY = gT.wasY;
                    g_UR[nItem].rx = gtm_vertexBuffer[idx].texCoord[0];
                    g_UR[nItem].ry = gtm_vertexBuffer[idx].texCoord[1];
                    if (!IsWindowEnabled(GetDlgItem(gT.hPanel, TOR_UNDO))) { EnableUndo(TRUE); }
                    gT.UpDown = 0;
                    lastX = x; lastY = y;
                }
            }
        }


Quote
stack branching/clearing
Has not been done yet !
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 02, 2019, 09:31:32 pm
Quote
ID_DOT drag, is now performed asap during WM_LBUTTONDOWN rather than WM_MOUSEMOVE
This is causing extra redraw problems, if holding the mouse down for too long, i shall have to find another solution…
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 02, 2019, 09:46:42 pm
Yes Patrice, I've also noticed it. Looks like some window freezing problem... ???

But as far as the stack is concerned, this implementation seems to be better than the previous one. Yet we can only be 100% sure of it when (if?) we see what (and how many) events really go onto a Paint.NET-like visual representation of stack...
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 03, 2019, 01:46:21 pm
With this version, i hope i have twisted the neck of the beast, without side effect.

Do a WinMerge to see what has been changed to avoid the conflict between scrolling the background with the mouse (now disabled), and dragging the hot spot.

The main problem is that WM_MOUSEMOVE is a high priority message, while redrawing the map in CreateUVmap is a rather lengthy process compared to the mouse movement.

Search for "stack clear/release", for the new Undo/Redo erase action.
However i am unsure of the indices being used.
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 03, 2019, 06:37:20 pm
Thanks for the update!

But no, still no branching on the stack. Let me explain it one more time.

When the bullet has traveled several locations and is brought back by Undo to some previous intermediate location, all the subsequent locations should be marked for deletion but not yet deleted. If then the bullet is propagated to the next known (already visited) location by Redo, that location should be unmarked for deletion (i.e. re-validated). But all the subsequent known locations should still stay marked for deletion. If all the subsequent already-visited locations are re-visited one by one in a similar manner using the Redo button, they all get re-validated one by one, finally re-validating the entire stack to its full depth. The stack stays as if you didn't press Undo then Redo at all.

OTOH if at some previous location Redo pressing stops and the bullet is instead moved to a completely new location by mouse or arrow key, then all the earlier locations that are still marked for deletion up to the very end of the UR array get completely discarded (cleared) from the stack (array memory) and thus forgotten forever. The new move that has just been made by mouse or arrow key goes on the UR stack and becomes the latest UR action and the last element in the UR array.

Is the branching mechanism clear for you this time or still not very?
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 03, 2019, 06:53:07 pm
There was an error in case TOR_UNDO, please use this one.
        case TOR_UNDO:
            UB = UBOUND(g_UR);
            if (gT.URidx < 0) { gT.URidx = UB - 1; }
            gT.URidx = max(gT.URidx - 1, -1);
            if (gT.URidx > -1) {
                g_UR[gT.URidx + 1].action = UR_UNDO; // Stack clear/release
                ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);
                idx = g_UR[gT.URidx].idx;
                gtm_vertexBuffer[idx].texCoord[0] = g_UR[gT.URidx].rx;
                gtm_vertexBuffer[idx].texCoord[1] = g_UR[gT.URidx].ry;
                gT.wasX = g_UR[gT.URidx].wasX;
                gT.wasY = g_UR[gT.URidx].wasY;
                gT.wasIndex = g_UR[gT.URidx].index;;
                UpdateUVMAP(FALSE);
                if (!IsWindowEnabled(GetDlgItem(gT.hPanel, TOR_REDO))) { EnableRedo(TRUE); }
                if (gT.URidx == 0) { EnableUndo(FALSE); }
            }
            SetFocus(gT.hZoomCtrl);
            break;

I obviously did it wrong, because i am deleting the g_UR[K].action == UR_UNDO in WM_LBUTTONDOWN
Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 03, 2019, 08:09:15 pm
No, that doesn't work either. It doesn't follow my description in my previous Reply #225. It looks like nothing gets cleared from at least the Redo stack when a completely new route to move the bullet is taken from one of the intermediate locations that you have just reached by Undo or Redo. The stack still remembers all the locations visited since the hot spot was first selected for moving, and new locations along the new route are simply appended to the end of stack. :-\

Where is the code located that's responsible for clearing all the old array elements up to the very end of UR array which should become unreachable for both Undo and Redo the very moment when a new alternative route is taken to move the bullet at some intermediate location along the old route, please?

Where is the code located that re-validates, i.e. clears UR_UNDO/UR_REDO/whatever flags from, the location which has been reached by Undo and then left by subsequent Redo, please? UR_UNDO followed by UR_REDO should leave the location in a virgin state, as if it has never been revisited by walking the stack...
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 03, 2019, 09:01:43 pm
I put the code at line 867, but it has been disabled until i could work back on it.

    case WM_LBUTTONDOWN:
        if (lstrlen(gT.zTex)) {
            DisplayMouseXY(hWnd, LOINT(lParam), HIINT(lParam)); // This is there that gT.x and gT.y are being set

            //// Stack clear/release
            //if (gT.URidx > -1) {
            //    UB = UBOUND(g_UR) -1;
            //    for (K = UB; K >= gT.URidx; K--) {
            //        if (g_UR[K].action == UR_UNDO) {
            //            g_UR.erase(g_UR.begin() + K);
            //        }
            //    }
            //}

            gT.UpDown = IS_DOWN;
            MouseMap();

            if (gT.wasIndex > -1) {
                if (ZI_GetObjectFocusID() != ID_DOT) {
                    ZI_SetObjectFocusID(ID_DOT);
                }
                if (ZI_IsLButtonDown()) {
                    DotMove = TRUE;
                }
            }
        }
        break;


see also line 1823 and 1842

        case TOR_UNDO:
            UB = UBOUND(g_UR);
            if (gT.URidx < 0) { gT.URidx = UB - 1; }
            gT.URidx = max(gT.URidx - 1, -1);
            if (gT.URidx > -1) {
                g_UR[gT.URidx + 1].action = UR_UNDO; // Stack clear/release
                ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);
                idx = g_UR[gT.URidx].idx;
                gtm_vertexBuffer[idx].texCoord[0] = g_UR[gT.URidx].rx;
                gtm_vertexBuffer[idx].texCoord[1] = g_UR[gT.URidx].ry;
                gT.wasX = g_UR[gT.URidx].wasX;
                gT.wasY = g_UR[gT.URidx].wasY;
                gT.wasIndex = g_UR[gT.URidx].index;;
                UpdateUVMAP(TRUE);
                if (!IsWindowEnabled(GetDlgItem(gT.hPanel, TOR_REDO))) { EnableRedo(TRUE); }
                if (gT.URidx == 0) { EnableUndo(FALSE); }
            }
            SetFocus(gT.hZoomCtrl);
            break;
        case TOR_REDO:
            UB = UBOUND(g_UR);
            if (gT.URidx < UB - 1) {
                gT.URidx++;
                g_UR[gT.URidx].action = UR_REDO; // Stack clear/release
                ZI_GetImageSizeFromControl(gT.hZoomCtrl, nW, nH);
                idx = g_UR[gT.URidx].idx;
                gtm_vertexBuffer[idx].texCoord[0] = g_UR[gT.URidx].rx;
                gtm_vertexBuffer[idx].texCoord[1] = g_UR[gT.URidx].ry;
                gT.wasX = g_UR[gT.URidx].wasX;
                gT.wasY = g_UR[gT.URidx].wasY;
                gT.wasIndex = g_UR[gT.URidx].index;;
                UpdateUVMAP(TRUE);
                if (!IsWindowEnabled(GetDlgItem(gT.hPanel, TOR_UNDO))) { EnableUndo(TRUE); }
                if (gT.URidx == UB - 1) { EnableRedo(FALSE); }
            }
            SetFocus(gT.hZoomCtrl);
            break;

Title: Re: There are many ways to go to Rome.
Post by: Michael Lobko-Lobanovsky on May 04, 2019, 10:36:49 pm
Patrice, I think I suddenly realized what's wrong with the UR stack. :o

There seems to be no matching stack branching/array clearing implemented for the arrow key moves yet. Therefore mixed mouse/key control seems broken as far as the UR stack is concerned...
Title: Re: There are many ways to go to Rome.
Post by: Patrice Terrier on May 17, 2019, 02:36:20 pm
This is a small Tor fix

float rxCoord(IN long idx) {
    float ret = gtm_vertexBuffer[idx].texCoord[0];
    if ((ret < 0.0f) || (ret > 1.0f)) ret -= ((int)(ret / 1.0f)) * 1.0f;
    return ret;
}

float ryCoord(IN long idx) {
    float ret = gtm_vertexBuffer[idx].texCoord[1];
    if ((ret < 0.0f) || (ret > 1.0f)) ret -= ((int)(ret / 1.0f)) * 1.0f;
    return ret;
}

We should not floor the texcoord, if they are already within the correct 0-1 range.