area515 / Photonic3D

Control software for resin 3D printers
http://photonic3d.com
GNU General Public License v3.0
131 stars 115 forks source link

Preview Caching Interferes with On-Projector Preview #251

Closed jmkao closed 7 years ago

jmkao commented 7 years ago

Using the Customizer params as the query string to cache previous preview positions (from 22142aaf0f72955dab37f45fb89eea15f45312e4) interferes with the on-projector preview.

When the projector preview is enabled, if you are in a position that you have previously previewed or move back to a position you were previously at, the on-projector preview will not update because the browser does not request a preview from the machine.

Probably what needs to be done is for a random based decache parameter to still be appended if the projector preview is enabled, or to separate projector previewing into an entirely separate API rather than a parameter to the current preview API.

WesGilster commented 7 years ago

Yeah the calibration also needs to "reset" that decache parameter as well. It would be a handy feature.

WesGilster commented 7 years ago

I don't want to step on your toes, but I haven't seen a pull request for this. I don't mind fixing this at all if you don't have time.

jmkao commented 7 years ago

I haven't started working on this at all, so go ahead :)

WesGilster commented 7 years ago

This should be done now and I took your suggestion about separating the preview from the onprojector preview.

Essentially the image cache will be allowed to fill up all available memory given to Java and when more memory is required it will start knocking out BufferedImages that are least recently used from the cache. There are only two levels of cache(Browser and Server side) but they are invalidated in quite a few ways. The server builds a SHA1 of the internal state of the customizer including a dependency on any external state. When that external state changes, it changes the cacheId as well. At the moment, "external image affecting state" is rather ambiguous, but simply put, it is the sum of all factors that could affect the state of the image outside of a customizer. Right now I change this every time we browse to the Printables page.

That's not a great idea. What would be better would be to change the value whenever something changes that could affect the display of an image like a calibration or an image upload of a previously cached image.

jmkao commented 7 years ago

Hmm... from a usability perspective I wonder if we need to separate out Flip and Scale. Even though mathematically, they are the same, they're used differently by users.

Conceptually, a user would want to flip in order to handle a bottom-up printer, and scale in order to change the size of the printed object.

We deliberately didn't implement X dimension flip because there's no known use for that, since Y dimension flip is sufficient for all bottom-up cases, and it allows the toggle to be a clear on-off, since users can't easily tell, whether an image is flipped or not from a single 2D slice (which might be symmetric on layer 0, but not symmetric further up).

Now, having it integrated with scaling, you'd have to deal with the effect of the flip on the sign of the scale operation, which requires more math understanding on the part of the users, particularly since in the majority of cases, the user would want to scale up X and Y by the same amount to maintain the proportions of their model.

Is there a use-case you have in mind for X-axis flips that we could break out into a separate control?

WesGilster commented 7 years ago

Actually I don't have a need for an x flip function(or y flip for that matter). I implemented it because it seemed to be missing, and it's basically a throw in feature. So if you don't like it, let's kill it.

However, I do have a need for Rotation and Scaling capabilities since I really hate using external programs to perform quick and dirty manipulations, especially when these features are so incredibly easy to implement now. In a later prod release I'm also going to implement the xyz scaling directly with 3d image files, but I'll have to ensure that the file allows 3d geometry first.

So, what would you like to do? I could add some affine transformation display control options? I wasn't a huge fan of the flip off/flip on functionality because that either forces us to keep additional state in the affinetransform or label a negative scale as somehow "flipped"(as we are doing now). I do understand your use case for basic users now, so if you are attached to the flip off/flip on state being kept, I'd suggest that we stop using negative scale as the determinant for that situation and keep the state information more intuitively in "flipx" & "flipy" variables. That way we don't have to worry about the ambiguous situation of how a negative scale is supposed to be interpreted by the rendering code as one of the following:

  1. Perhaps it means the user flipped it and we should add the height/width of the printer.
  2. Perhaps it retains it's original mathematical interpretation and a negative scale simply means a negative scale.

I'm pretty open to what you want to do with the user interface, but I just want to make sure we are careful about how many "under the cover" transformations we perform on the server side as a result of a negative scale. Consumers of an API should have certain expectations about how the backend would work, and I'm not sure that it's immediately obvious that a negative scale should imply that we also "apply a printer width/height transform".

Thanks, Wes G.

On 9/5/2016 12:06 PM, James Kao wrote:

Hmm... from a usability perspective I wonder if we need to separate out Flip and Scale. Even though mathematically, they are the same, they're used differently by users.

Conceptually, a user would want to flip in order to handle a bottom-up situation, and scale in order to change the size of the printed object.

We deliberately didn't implement X-axis flip because there's no known use for that, since Y-axis flip is sufficient for all bottom-up cases, and it allows the toggle to be a clear on-off, since users can't easy tell, whether an image is flipped or not from a single 2D slice (which might be symmetric on layer 0, but not symmetric further up).

Now, having it integrated with scaling, you'd have to deal with the effect of the flip on the sign of the scale operation, which requires more math understanding on the part of the users, particularly since in the majority of cases, the user would want to scale up X and Y by the same amount to maintain the proportions of their model.

Is there a use-case you have in mind for X-axis flips that we could break out into a separate control?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/area515/Creation-Workshop-Host/issues/251#issuecomment-244787364, or mute the thread https://github.com/notifications/unsubscribe-auth/ACT_NKNMNH9tj48Xm3v0NI3uZ1pSZHzzks5qnEwUgaJpZM4JvAfa.

jmkao commented 7 years ago

Yeah, the negative scale thing was kind of a hack at the time the interns were working on it, but with a full complement of transforms, the overloading of the meaning of the scale factor is not the right thing.

I guess what might make sense is for the customizer to track that flip as a boolean, that will have the behavior of doing a sign-change on Y. Then when the affine transform is generated, this sign change would have to be applied first before doing to the logic that translates the image back to 0,0 after a flip.

My feeling is that whether the intent is flip or negative scale, we would always want to translate the image back to 0,0 before adding on subsequent operations, since I think that sending the image offscreen would be confusing to the user, since that would cause the preview to go offscreen, and you would have no idea how to get the image back. That would also, I think, make sense in combination with rotation, since the center of rotation would then always be the center image in an on-screen coordinate space, rather than at 0,0 or potentially some ofscreen location that would stack up unintuitively when trying to get a result.

This is under the assumption that since the end-goal is to print, you would always want the object you are printing to be on the table somewhere.

The only case I can think of where I would deliberately place part of the image offscreen, is if I had a layout of multiple parts and wanted to do a poor-man's reduction of the number of parts printed. But in this case, I think that I would only use translation to get the parts offscreen. Using rotation or scale to do this would be unintuitive. Although, if there is a case that you can think of where a user would want to rotate or scale a part partially offscreen, maybe the UI for that could do something specific to that case.

WesGilster commented 7 years ago

I don't think that our goals are mutually exclusive:

  1. Your goal is to ensure that an affine transform doesn't result in an inadvertent display of the image offscreen.
  2. My goal is to ensure that the AffineTransformSettings object has an obvious and expected behavior.

To summarize in a simple way, the definition of yflip is not just negative y scale, it is an inseparable transform composed of scaley and translatey before all other transforms.

  1. scaley: -1
  2. translatey: printerlength

However, that flip event is independent of the "true" yscale(perhaps even negative itself) that the user intended to apply and is more aware of. We have to assume that the user knows the ramifications of this second scaling and any accompanying translation because they created it themselves and understand what it takes to keep all or the relevant portion of the image on screen.

For example, I've been printing images which rotate, scale and translate most of the image offscreen to print on a portion of the build vat that hasn't gotten much use. Unless we start comparing white pixels onscreen vs. off screen, I'm not sure we'd be in a place to tell the user they have done something wrong. Such a comparison might server as a pretty good warning in the GUI, but that's kindof the point of the preview in the first place.

WesGilster commented 7 years ago

You know, I suppose we could have a validation on the gui that doesn't allow the user to apply a negative scale, however that wouldn't really stop a developer from sending a negative scale in the AffineTransformSettings object. So we still need to define the behavior of the API, but I think that ultimately accomplishes your goal to ensure there are no offscreen rendering.

WesGilster commented 7 years ago

I had some time today to implement the stuff we talked about:

  1. Persistent on/off tracking of flips.
  2. Not allowing scaling to go negative.

I also threw in another feature to scale the entire 3d file rather than just the X/Y axis since that's kindof a broken feature without syncing all three axis. That automatically also gives us antialiasing on our image like we've never had before.

jmkao commented 7 years ago

Sorry for the lack of reply, super busy now and for the next few weeks. I agree that we should be able to get both friendly UI behavior and a consistent API, and that protection "magic" should not occur at the Java level. I'll take a look at these when I have a chance to get some air. Thanks!

WesGilster commented 7 years ago

Closed in cwh-1.0.0-beta3