Wednesday, August 16, 2017

resizing-a-t-viewport-3d

I have almost finished an application or two. The two applications are using the same technology. Both are Delphi FMX applications which use a TViewport3D as the main component which fills the whole client area of the window, at least most of the time. There have been problems with resizing the component. Note that I am writing a multiplatform HD application, not the 3D application. There is a little difference between the two. I have always been using the HD application where the TViewport3D is a normal component on the form.

This blog post is a summary. I am writing this without looking at the source, no IDE open, and I will not show code. (I have reset the template of this blog to the default without any support for syntax highlighting because the browser complained about using http link to the resources and I do not want that.)

Back to the TViewport3D, and from here on I will just say Viewport. The first problem is obvious when you look at the Resize method. The Viewport will destroy the current context and create a new one whenever the component is resized.

First thing I did was to ensure that the context is not destroyed but kept alive when resizing. This has revealed a bug. I need to set one more buffer resource to nil. It is in method DoResize of TDX11Context. This is where other resources are also set to nil, for example the render target. You want to add FCopyBuffer to the list (RSP-18850).

Then I was looking at the number of times resize is called during a manual resize of the application window with the mouse. I needed to handle a windows message not handled so far and act only when resize has finished (WM_EXITSIZEMOVE, RSP-18851). You will always have a hard time debugging or finally improving something related to resize if you do not have that, I think.

It is important that the Viewport is not aligned to client and automatically resized. Just set the size of it whenever something has finished changing. When I say size, I mean Size. Do not set Width followed by Height, you want to use an instance of TControlSize. I will get back to alignment in a moment.

For some time, focus on application startup. How many times is the Viewport resized when the application starts up. It should be one.

Turns out that Width and Height are set to a default size in the constructor which triggers a resize. I got rid of that (RSP-17296). It felt much better, at that time my application did set the size of the Viewport to an area greater than zero, it was aligned to client area of the parent.

I found out that the second application behaved better than the first and why. In the process, I switched alignment to none which resulted in an interesting situation. Width and Height of the Viewport were initially zero. This means that the context is nil and will stay nil, until you set the size. In my code, there was one location where I needed to test for context nil. I did that and reached the next stage.

It was in the Paint method. If the context is nil, the bitmap is also nil. Paint should test for a nil bitmap and exit immediately without an attempt to draw anything (RSP-18852). With that in place I could start up the application with an empty Viewport. This makes a good test. You should be able to run the application with a Viewport area of zero without a crash. If the test passes you can go on and give it a decent size. Then it will create a context and draw as intended.

As I have said above, it should do this just once when the application starts up. Use a draw counter to check. If it instead will draw a few times during startup this will probably be OK. And if resizing seems to work without problems then this is good for you, but keep in mind there might be a problem.

Back to alignment. Do not align. Then size is not adjusted during a resize. Do this when resize has ended. (Nice that I have the exit resize event.) You will have more confidence that the application will survive wild excessive resizing by the end user, who does not seem to feel the pain.

My application uses a modified context class. I will create and use a special buffer resource on the GPU. There is a show stopper problem when the context is recreated too often. You may not see this in a normal application. But there is a potential problem with resizing a TViewport3D in 10.2.1 and before.

Monday, August 14, 2017

new-sample-data-repo

OK, great news, a new version of the application is available from the Windows 10 Store. And I also have created a sample data repository on GitHub. With the initial commit, I posted some text data files. I know that I will have to fine tune and update these files in the future. At least they are at GitHub now where they belong. The reason why I think they may need an update is that I have many branches of the application with a different set of features. And I had to slightly change samples to work with the feature reduced application.

There is a feature I like very much, you can embed or imprint the model text data into a screenshot of the rendered image. I will just modify the red channel of the pixels in the png image, starting at the top row. Then you can drop the image on the drop target of the application, and the application will load the model data. What you get is the reproduced image, fully alive within the application.

Today I wanted to create new images with imprinted data and post them to the sample-data repository. I used the text data files from the repo, dropped them on the application. Then I resized the application to a 512 pixels square format and executed the CopyImprintedBitmap action, which will put an image into the clipboard. Then I pasted into Microsoft Paint and saved as png with the same name as the text data file. In a way, I ate my own dogfood.

And, you may have guessed it, I am now ready to write about the problems.

In the full application, I have implemented actions that will resize the window to a specific size. Many of the icon sizes and photo formats and mobile device form factor sizes are available, including the 512 pixels square. In the published app, I have removed that feature. I should perhaps say that I have chosen a version for publication which is clean and lean and sandboxed. Yes, the end user running the published app can produce the image with imprinted data. It will have the size of the application window when the action was executed. When the image will be resized in another program, the imprinted data will be lost though. You have to set the size of the application window before you create the image. That is why I used the full featured version to do that. I made a note and will probably add the feature to the published app.

Dropping the imprinted image worked great, for the first two images. The third one did not show as expected. But I found out why. Not sure if I should call it a bug or an issue. I think I will update the published app, so that there is no difference between the full internal and sandboxed published app.

The third image, Herz-01, was using scene 1 instead of scene 3. This means that just one spring is used in the computation. The difference was FaktorEQ. The published app will run all computations on the GPU. It does not contain the code which evaluates the model on the CPU. And that is why FaktorEQ was always the same, and did not change as it usually does when another scene is selected.

FaktorEQ will be used for scaling. It makes sense when it is different for each scene. But it does not have to. There are several ways to compensate for it, to achieve it through different means. The test sample worked perfectly with the published app, but I now remember that I had tweaked it to do so. Obviously, in the future the samples should work everywhere the same. I changed the code and it will be in the next published version.

There have been at least two reasons in the past why samples needed to be tweaked, the other one being the projection. Delphi does not do orthographic projection out of the box. And when you run without a patched version of the FMX library, you do not have it. It is desirable to sometimes run without the patched FMX units. So the issues with a unified set of example data is not always related to internal barriers.

I am starting out with GitHub and I am keeping it simple and I expect to make mistakes. Today I uploaded a new sample data file, Herz-02.txt, instead of changing Herz-01.txt to reflect the latest good version. The odd situation is that I have uploaded an image to the sample-data repository which does not work perfectly with the current app.

Resolution: I will recycle the Herz-01 sample in the future to show another good-looking heart, and maybe add the corresponding image to the imprinted sub-directory.

So, good news, the app is out, the sample data repository is up and running, and a future version of the app will be even better. You can use imprinted samples and you can create them. Try them out, they are cool.

(The text data files are smaller though.)

Friday, October 17, 2014

special-sample-challenge

I have updated the Maxima source for the special sample, made a screenshot, and wrote a draft for a challenge/task in notepad. Perhaps I will post it to the forum. This is certainly not the biggest or most urgent problem to solve, but perhaps also not the smallest or least interesting.

Maxima source code is available.


Here is the text for the challenge/task:

In my other blog post I described a case (screenshot 7) where a function z = f(x, y) has a minimum which just touches the plane z = 0. I made a cross section through the 3D surface, giving a function z = f(x), the equation of which is available in uploaded text files.

The function depends on a parameter L - the original length of the springs in the physical (federgraph) model, all other parameters are kept constant in the special sample.

Question: What exact value of L does correspond with the situation in screenshot 7 where the minimum touches the floor?

Not only do I want to know what the value of L is, I also would like to see how you approach the problem, what tricks you apply, and which software you use.

The Maxima source code is at pastebin.

federgraph-special-sample

The last blog entry was about a special case. Today I am blogging about the special sample, which contains the special case. In the setup of the sample I can change parameter L - the length of all the springs - over the whole interesting range.

Sample Situations

I have identified a number of situations/cases and uploaded two scilab source files to pastebin. It is special-sample-2D with a 2D graph, and special-sample-3D with a 3D plot. These files contain more info about the concrete setup, and can be used to create independent graphical output in scilab.

a) L = -a/2 = -50 (all springs under tension)
b) L = 0 (force cone, Kraftkegel)
c) L = a/2 = 50 (single equilibrium at centroid)
d) L = ro = 57 (circles intersect at centroid)
e) L = w3/(1+w3) = 63 (touch down at corner C)
f) L = 83 (bifurcation)
g) L = h = 86 (special case one, equilibrium at midpoint of side)
h) L = a = 100 (no vertical edge/jump)
i) L = 115 (centroid dome)
j) L = w3/(w3-1) = 237 (delta peak take off)

Screenshot Series

It is difficult to describe in words. Therefore the screenshots are the meat of this blog post - to be used them as a starting point for further exploration. I have included screenshots for intermediate situations in between the special points listed above.

Screenshot 1) L = -50 = negative jump
Screenshot 2) L = 0 = force cone
Screenshot 3) L = 50 = a/2 = circles intersect at mid of triangle side
Screenshot 4) L = 57 = ro = circles intersect at centroid
Screenshot 5) L = 63 = w3/(1+w3) = touch down at point C
Screenshot 6) L = 74
Screenshot 7) L = 83 = touch down of curve
Screenshot 8) L = 86 = h = w3/2 * a = circles touch side
Screenshot 9) L = 100 = a = no jump, only a slope
Screenshot 10) L = 115
Screenshot 11) L = 120
Screenshot 12) L = 140
Screenshot 13) L = 170
Screenshot 14) L = 190
Screenshot 15) L = 210
Screenshot 16) L = 237 = w3/(1-w3) slope vanishes and peak touches floor in point C
Screenshot 17) L = 237 = same as 16, but different perspective
Screenshot 18) L = 300 = delta no longer touches plane
Screenshot 19) L = 490 = curve bends

Screenshot 1 (L = -50)

This is the only screenshot for a negative value of L. Notice the direction of the jump. The 3D graph looks like a top down view, but notice that it is actually viewed bottom up. The 3D surface represents the absolute value of the force, which stretches from possibly zero (around the origin) to positive values everywhere far from the origin, as the 2D graph on the right hand side shows. I decided to let the triangle point to the right. Otherwise the 2D graph would appear rotated 90 degrees, which is the normal case, where the triangle points upwards. Note that the gray circles for the actual length of the springs touch each other. The peak of the yellow curve points down to the centroid of the triangle.

Screenshot 1

Screenshot 2 (L = 0)

This is indeed a special case.The force surface plot is a cone. There is no problem when you move point P over a corner. We only see one equilibrium at the centroid. The force in any of the springs will be positive - tension, not pressure.

Screenshot 2

Screenshot 3 (L = 50)

The circles touch at the midpoint of a side. This is the same as in Screenshot 1, but the spring will be under pressure when point P is moved towards the corner where it is attached. We see a vertical edge exactly where the corners of the triangle are. This is where the direction of the force will turn around. There is still just one equilibrium - where the surface touches plane z = 0.

Screenshot 3

Screenshot 4 (L = 57 = ro)

This is special only because the circles intersect at the centroid.

Screenshot 4

Screenshot 5 (L = 63)

Notice that in this situation the peak will touch the plane at point C - the triangle corner (x3, y3) - which is on the x-axis in this special sample.

Screenshot 5

Screenshot 6 (L = 74)

Notice the slope which is not present in the previous picture. It has appeared, so I thought it is worth a screenshot.

Screenshot 6

Screenshot 7 (L = 83)

The slope is getting bigger, but I want to turn your attention to the fact that the curve has touched the plane. We now have three zeros within the plotted section. Overall we have even more. Until now I have not yet determined the expression for the exact value of L when this happens.

Screenshot 7

Screenshot 8 (L = h = 86 = w3/2 * a)

This is the special case from the last blog post. The curve is touching the plane exactly at the middle of the triangle side.

Screenshot 8

Screenshot 9 (L = 100 = a)

This situation is special because the jump (vertical edge) temporarily disappeared. Also note that the one spot - that was situated on the triangle side in the last screenshot - is now moving closer to the centroid.

Screenshot 9

Screenshot 10 (L = 115)

Close to the centroid the surface smoothly touches the plane and the shape of the surface in that area is almost circular. I still have to find a name for this situation. Also note the six-corner-shape.

Screenshot 10

Screenshot 11 (L = 120)

What seemed to be round in the middle is now looking like a triangle.

Screenshot 11

Screenshot 12 (L = 140)

The mold has appeared again. The shape in the center is looking like a delta. Notice the slope which leads to point C.

Screenshot 12

Screenshot 13 (L = 170)

The delta is taking shape. The slope is getting shorter.

Screenshot 13

Screenshot 14 (L = 190)

For this screenshot I have adjusted the texture parameters - the width and offset of the colored rings. My interest is now focused on the slope.

Screenshot 14

Screenshot 15 (L = 210)

The slope has become very short here. It is about to disappear. This is best seen from the side - so I changed rotation (and zoom).

Screenshot 15

Screenshot 16 (L = 237 = w3/(1-w3) )

Now the slope is gone, and the peak touches down to the plane exactly at point C.

Screenshot 16

Screenshot 17 (L = 237)

This is the same situation as in screenshot 16, but with different view parameters.

Screenshot 17

Screenshot 18 (L = 300)

Notice that the peak no longer touches the plane. Since I increased the plotted range you can see the rim. The six equilibria around the rim are almost sinking into it.

Screenshot 18

Screenshot 19 (L = 490)

Parameter L is now pretty much out of bounds. Notice how the outer slope appears curved.

Screenshot 19

Now imagine how everything will fit if we translate part of the curve, mirror another part of the curve, and how that would simplify the equations.

Thursday, October 2, 2014

federgraph-special-case-number-one

In this blog post, I describe a problem or task. I do not give a solution, but I have already computed values in a simulation, so that you can look at the graphical output, before you start up your computer algebra software to create a new worksheet for the task.

It is about a system of springs. The Federgraph application has already implemented a 3D model of this system. The description of the task should be compatible with the identifiers used in the application, so that the mathematical model can stay in sync with the source code for the graph.

The common case

A common case of a system of springs is given in the following picture. Three springs are attached to the corners of a triangle ABC. I have drawn circles to show the zero-force-length of each spring. The free end of each spring is connected to point P which can freely move within the (x, y) plane (where z = 0). We will consider the absolute value of force F, which keeps point P at a given location. We will also consider the amount of energy E stored within the system, when moved to point P.


Picture 1: A system of springs

There are special locations, where force is zero and energy has a maximum or minimum. These locations are the stable or unstable equilibria, which we want to find as solutions of the equations of the mathematical model for the system. I can help out with some graphics.

Special Case 1

This case is given when the triangle is equilateral, and the zero-length of each spring is equal to the height of the triangle.

As a special situation for special case 1, P shall be located at the midpoint of side AB, as depicted in the following picture.


Picture 2: Schema view of special case 1


It is clear that the forces in two of the springs (AP, BP) cancel each other out, while the force in the third spring (CP) is zero, because the actual length of this spring (h) is equal to its zero-length (h). There happens to be an unstable equilibrium at point P. Think about it, then find A, B, C, and P in the following picture. This picture is a perspective projection, viewed directly from the top.



Picture 3: Top view for special case 1

Question 1: How many equilibria exist? Perhaps it is easier to see in the next picture, which shows the same situation from a different angle.



Picture 4: Side view for special case 1

Special Case 2

Now change the length of the springs, but keep them all at the same length (Parameter L). There is a bifurcation. It is easy to see when I scroll with the mouse wheel, but you should look at the math first. From the equations, you will know what to expect. It is a long time ago that I attended math lessons, I guess you are much better equipped than I am to analyze this stuff.


Picture 5: Parameter L is close to where a bifurcation occurs
Question 2: At what value of parameter L does the bifurcation happen?

I hope that the term bifurcation is correct, not sure, but I leave the explanation of all this to you anyway.



Special Case 3

The center point of the triangle is a special point. An equilibrium can be found there. We still work with the equilateral triangle, but in the following picture, the value of L is different again.

Picture 6: Four solutions combined into one at the center point.
Question 3: For what value of parameter L will the equilibrium at the center merge with three other special points?

Conclusion

It is up to you to make conclusions. I have explored the system of springs, the general model, to some extent and do promise that there are more special cases. It will be fun to see them, once you have set up your worksheet!

This is my first blog post, I still have to find out how to do it properly. Perhaps I should not paste the text from Word, but instead paste clean Html? I will post a link to this blog-entry on my Profile and the Federgraph Page, where comments are enabled.