Bug with ChangeQueue

I have a sample scene which freezes Rhino when I try to run our plugin as an interactive viewport renderer.

It seems our ChangeQueue implementation causes the problem, it hangs at the queue.CreateWorld() call.

I see no reason for this, so I tried with other ChangeQueue implementations. There is the sample project “SampleCsRdk”. I have made one small modification on this project in the “rdktest_csPlugIn.cs” file:

from:

public override bool StartRenderer(int w, int h, RhinoDoc doc, ViewInfo view, ViewportInfo viewportInfo, bool forCapture, RenderWindow renderWindow)
{
throw new NotImplementedException();
}

to:

public override bool StartRenderer(int w, int h, RhinoDoc doc, ViewInfo view, ViewportInfo viewportInfo, bool forCapture, RenderWindow renderWindow)
{
var queue=new RdkTestChangeQueue(PlugIn.IdFromName(“RdkTest”), doc.RuntimeSerialNumber, view);
queue.CreateWorld();
}

When I call the the interactive viewport renderer “RdkTest”, it freezes also at queue.CreateWorld();, so I guess something is not OK there.

There is one material inside the scene. This material has texture map on the color and bump channels. If I remove these texture maps, it doesn’t freeze anymore.

And there is a very interesting side-effect(???) bug too (you need the SampleCsRdk plugin to try it):
These are the steps to reproduce it (at least on my computer):
0.) Start Rhino
1.) Open the file “frozen.3dm”
You see this:


2.) write at command line: rdk_test.cs (so start the plugin)
3.) go to the materials panel
4.) select the material and turn off the color or bump channel (click on the check box)
Now you see this(???)

Here I attach the sample filefrozen.3dm (293.2 KB)

frozen.3dm (293.2 KB)

I didn’t further test, but the sphere is because of the custom mesh provider that is part of that sample plug-in:

Sorry, I was not aware it the mesh provider.

In that case only the CreateWorld() issue is the question.

Márton

Hmm, not sure about the SampleCsRdk code, I’ll have to revisit it in the near future.

Here is a better example of how to integrate into the viewport:

Open the solution file one directory up - ignore the README text, all paths have already been set up correctly.

Yes, you are right, I should have started with this code. But anyway, I tested with your MockingBirdViewport project now, and this one hangs at cq.CreateWorld() too.

Márton

Ah, I see. I have been testing with empty scene - here you’ll see how it otherwise works.

Let me check what goes on here.

edit: not sure what is going on there. When the debugger is attached the example works as expected. I’ll investigated more next week.

Thanks!

This is actually a highly simplified scene and maybe triggering this issue is not so easy now?
Should I attach the original scene?

Márton

It seems this bug is rather elusive.

Testing the same scene I have attached doesn’t cause freezing under the OSX version of the plugin, but the original scene still freezes it.
So here is the link to the orig scene.

And also I attach the Mac hang log, maybe it tells something. (The hang happens after trying to read the png file?)
Rhinoceros_2020-01-28-092621_MacBook-Pro.zip (109.6 KB)

Márton

Nathan,

Have you had time to check this issue?

Márton

Sorry, I haven’t had proper time yet to check. Looking now.

@marton.parlagh, the problem with the sample code locking is the usage of RhinoApp.WriteLine from a separate thread. The reason it works with debugger attached is that timings are a bit different, so messages are being better pumped and handled. In release build without debugger attached we get into a race condition.

I committed a small example of how you should use RhinoApp.WriteLine from a separate thread - or really anything that accesses the UI.

Let me know if that helps you.

Hello Nathan, (thanks for checking it)

I think it is not the real source of the problem. Have you tried with the full sample scene? https://www.dropbox.com/s/kgwmf548afxbs7m/frozen_full.3dm?dl=0

Here I tested it after deleting all the WriteLine parts from the mocking sample, and still it freezes.

Márton

I had not tested with this particular file, only with a set of large files I use to check Raytraced works still ok. Some of the files were bigger (around 200MB). Anyway, it looks like the baking of textures here is the problem. I don’t know how much texture baking you need for your renderer, but Raytraced doesn’t hang, meaning you could probably be ok with the same BakeFor() override as it:

I have logged a bug for the baking problem when all functions are enabled

https://mcneel.myjetbrains.com/youtrack/issue/RH-57091

Ahhh you are right.
It seems BakingFunctions.WcsBasedMappings freezes it.

Thanks!

By the way, how does this automatic baking works?

Where does it store the baked textures?
Is this the same as if I was calling texture.SimulatedTexture… manually? Or is it something more advanced?

Márton

Hey @marton.parlagh

After some more testing even your frozen_full.3dm loads. The baking of all textures just takes a really long time. I just timed one session: 13 minutes.

Baking of textures is the evaluation of the texture on the surface of an object. Just UV coordinates aren’t enough for high quality mapping.

Consider this example:

In Rendered mode. Simple plane that has only 4 vertices. Have a material on with a bitmap that is set to mapping channel 1. Add a torus. Select the plane and add a Custom mapping, using torus as the custom object. Hide the torus and select the plane. Show the mapping widget. Select the mapping widget and move it around. Pay attention to how the texture looks like while you are moving the mapping widget. Because there is only information on the 4 vertices with the original, unbaked, texture the mapping result looks weird. When you let go of the widget the texture gets backed such that the texture is properly evaluated using the custom mapping object. This baked texture is then used for display.

In video form:

The texture is under the temp dir somewhere saved as well. The SimulatedTexture does not do this.

When you evaluate the texture using the TextureEvaluator you’ll be accessing the baked texture, if baking was requested for that BakingFunction in your ChangeQueue implementation.

Thanks for the explanation!

One more connected question.
From Queue I get the mesh (Rhino.Render.ChangeQueue.Mesh)

and the sub-meshes
mesh.GetMeshes();

And texture coordinates from sub-mesh
subMesh.TextureCoordinates

But this contains only one channel (it seems). What if I want uv coordinates for all the channels?

I see this function:
mesh.GetCachedTextureCoordinates

Is it the right direction? Or should I force-generate the caches maybe?

Márton

I’m not entirely sure since I haven’t used this myself yet, but here is what I think you can do. (Cq is shorthand for ChangeQueue):

  1. CqMesh.Mapping will give you access to channels.
  2. iterate over the channels to access each mapping channel
  3. on a mapping channel you’ll find the texture mapping.
  4. Use the Id of this as Guid to mesh.GetCachedTextureCoordinates

Again, I haven’t used this before myself, so I’m guessing here. Hopefully it will get you started.

something similar was my guess too, but with a little concern about cached coordinates.
Are the cached coordinates always ready during renderQueue? Or do I have to force-make them?
By the why the one channel what I can read directly from the mesh, is it the top-most channel or what is the logic?

Márton

I think it’ll be the top one, but to be honest, I am not sure.

You can set texture coordinates yourself like this:

Again, I have myself used only ever one set, so you may have to do some tinkering and testing.