Photonic3D icon indicating copy to clipboard operation
Photonic3D copied to clipboard

How to extract JavaScript Mask Parameters from Projector Mask Creator

Open jmkao opened this issue 9 years ago • 10 comments

The JavaScript function for the Projector Gradient seems to have 4 key parameters: bulbCenter, bulbFocus, totalSizeOfGradient, and a % intensity which is 4th parameter to the instantiation of the java.awt.Color object.

These seem to match the controls available in the Projector Mask Creator in the Slice Browser, but I cannot seem to find a way to make the Slice Browser output those values once I have the mask looking the way I need it.

How do I read the necessary values out of the Slice Browser?

jmkao avatar Jan 17 '16 02:01 jmkao

Awesome, just the question I was waiting to hear. I'll see if I can make a button for this tomorrow, but I'd like some information from you in exchange.

  1. What makes you believe you have the perfect mask for your projector?
  2. For performance reasons alone, don't you think that the "% intensity" parameter should be a function of the total build area in mm square?
  3. If those parameters are a function instead of statics(as I mentioned above), how is that going to affect the exposure time and lift speeds?
  4. All of this can be calculated with the functionality that we already have. Should it?

I realize that this is way past what other software is doing, but it seems like adding a projector mask has the potential to really slow down the print. I'd be curious as to you opinions...

WesGilster avatar Jan 17 '16 04:01 WesGilster

Up until today, I wouldn't have had a good way to get an idea of what the intensity mask should look like without some complex rig involving a tripod, DSLR, and perhaps a neutral density filter to perfectly photograph a projected white image.

However, today, I was able to produce a pretty accurate exposure map of my projector's light output like: image using some inexpensive solar print paper (https://www.amazon.com/gp/product/B001FD86EI/) sandwiched between the build plate and the vat floor to keep it flat. This procedure should be doable with any bottom-up DLP based printer.

Using the Slice Browser, I created an intensity map that closely matched what was imaged on the solar paper that I believe should represent the intensity variation across my projected area. There is a question, however, as to how big the variation is between the most and least intense spot. Based on trial-and-error printing large parts, it seems to be around 60%, meaning the exposure necessary to begin curing the dimmest part is a bit over double the exposure necessary to begin curing the brightest part.

Since all of the parameters are based on the physical focus properties of the lamp, I do not believe that the intensity map would vary based on the total build area. I've previously experimented with using simple multiply masks based on crudely guessed gradients based on exposure behavior and gotten passable results.

My feeling is that a projector mask shouldn't necessarily slow down the print, since it can be a static multiply mask applied to every layer. The function that generates the mask wouldn't need to be recomputed on each layer so long as there is enough memory to store a 1920x1080 array of floats that contain the pre-computed multiply values, or maybe in an precomputed image that could be applied using java.awt.AlphaComposite.

I do think that using a function to represent the mask may itself be unnecessary compared to just taking a PNG file that represented the multiply values, especially if someone wanted to simply use a Photoshop normalized image from an experimentally measured intensity map.

jmkao avatar Jan 17 '16 06:01 jmkao

Very cool, it would be much easier to compute the mask once before each print, but I had assumed the following:

  1. UV light is distributed unevenly over the surface of the build platform due to the curvature of the bulb and some other factors.
  2. Uneven UV exposure causes differing exposure times for a single layer of resin, thus, printer masks are required, other wise large build surfaces will warp when cooled.
  3. Applying a printer mask will reduce the amount of UV light that reaches the resin.
  4. Reducing the amount of UV light that reaches the resin increases exposure times.
  5. On a small enough parts, the mask wouldn't need to be as intense because there isn't enough UV exposure variance over the build area to cause any warping effect.

With the procedure you have just described, it would seem that controlling these variables would be much more efficient from within the CWH application itself to ensure the solar paper is completely uniform with these parameters...

WesGilster avatar Jan 17 '16 14:01 WesGilster

The function will now print to sysout every time it is applied. Not very exciting but should do the trick for you. I also increased the performance by using the built-in arctan function of the RadialGradient rather than doing it myself. I was playing around with the idea of computing the fractions and color references myself because I could control the math function that was used. I really don't think anyone is going to understand how to utilize that feature so I reclaimed the performance back until the need arises.

Fixed in cwh-0.201

WesGilster avatar Jan 17 '16 15:01 WesGilster

Sorry to bother here also :$ I haven't found the menu where we can create this mask but I would prefer en PNG mask also. Mainly because I'm planning to design a low budget device which could help with creating this mask ;) And also because most people I found use an camera method and some photoshop to create this png and some other people I saw measure some points and make from that values also an png ;)! So if we could use both you would serve a lot more people I guess :)!

kloknibor avatar Jan 18 '16 09:01 kloknibor

I see, I misunderstood what what you meant by "intense". It's true that for small parts, if they're centered around the brightest area, that amount of difference you need to make up is less, and the amount of the image you need to traverse to apply the mask is also less.

RIght now, since we don't have the ability to position the STL on the plate, the optimization here is probably moot since it wouldn't be possible to position the object in the brightest "sweet spot" and then optimize the light output for that area. Also, projectors are no uniformly in focus, so in same cases, optimizing for the brightest areas might not be desirable if that will place an object in a less focused part of the projection field.

I think with an accurate mask function and the STL file, we do have enough information to eventually produce an algorithmic "optimized for speed" automatic positioning of the STL file along with the minimum necessary mask. However, I think that just having a manual "always on, always even" mask is more than sufficient for some time to come.

I did try the new Slice Browser and verified that it prints to sysout every time it's applied. My intention is to verify this end to end by applying the function into the CWH template and then doing a test exposure onto the solar paper with the mask applied to see if the net effect evens out the field. Hopefully I'll complete that early this week.

jmkao avatar Jan 19 '16 05:01 jmkao

Close, just one minor issue with the bulb mask function generator.

The output given from the slice browser was:

var bulbCenter = new Packages.java.awt.geom.Point2D.Double(${buildPlatformXPixels} * 0.4271694, ${buildPlatformYPixels} * 0.630394)
var bulbFocus = new Packages.java.awt.geom.Point2D.Double(${buildPlatformXPixels} * 0.33832644628099173, ${buildPlatformYPixels} * 0.4080675422138837)
var colors = [new Packages.java.awt.Color(0.0, 0.0, 0.0, 0.58), new Packages.java.awt.Color(0.0, 0.0, 0.0, 0.0)];
var fractions = [0.0, 1.0];
var totalSizeOfGradient = $buildPlatformXPixels > $buildPlatformYPixels?$buildPlatformXPixels:$buildPlatformYPixels;
new Packages.java.awt.RadialGradientPaint(bulbCenter, totalSizeOfGradient * 0.42407024, bulbFocus, fractions, colors, java.awt.MultipleGradientPaint.CycleMethod.NO_CYCLE);

The bulbCenter and bulbFocus lines reference $buildPlatformXPixels and $buildPlatformYPixels as ${buildPlatformXPixels} and ${buildPlatformYPixels}. The {} don't parse properly in the function tester, but when I remove them to match the way variables are referenced everywhere else, the function works.

I was a little confused at first about the box, but I realize now that the positioning of the points is relative to the screen size of the PC, not fixed within the window. I'll write some docs for this now that I have the gist of it.

jmkao avatar Feb 28 '16 02:02 jmkao

Oops, I fixed those bad variable names, and they will be in my next release. It sounds like you already knew that ${name} isn't valid javascript syntax.

I hate to see you spend a ton of time documenting those developer tools. I certainly want them to work and will fix every relevant bug. On the other hand, they are poorly designed slop and will change on a whim. Honestly they are there just to help me(and someday maybe other people) visualize how slicing is performed.

WesGilster avatar Feb 28 '16 03:02 WesGilster

The mask is super useful and unique. Creation Workshop masks only work when it is controlling the printer. The mask isn't applied to the PNGs output in the CWS file, it's only applied in real time. Projectlayer doesn't support masks. NanoDLP supports PNG masks like CW, but making those is kind of time consuming in Photoshop, and even then you can only do simple circular gradients easily.

I actually think that even with the kind of developer-ish flow, the overall steps to getting a mask are easier with what the CWH tools do today compared to almost any other way.

I got this my first try eyeballing:

image

Tuning it to reduce the intensity a little won't require me to go back and re-create the mask in Photoshop, I can just tweak a coefficient in the web UI itself.

jmkao avatar Feb 28 '16 03:02 jmkao

Wow, that's great progress. Yeah, I can't imagine the retune/upload png/apply workflow that has to be put together for a photoshop process. Ultimately, I feel like the mask creator really needs to be a part of the CWH software though. Your mask creation experience it just what's needed to put together a decent workflow and suggest how this could be integrated.

WesGilster avatar Feb 28 '16 05:02 WesGilster