Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIN and JSON cached files #115

Open
morawi opened this issue May 22, 2020 · 6 comments
Open

BIN and JSON cached files #115

morawi opened this issue May 22, 2020 · 6 comments

Comments

@morawi
Copy link

morawi commented May 22, 2020

I would like to read the generated BIN and JSON (when cache=True) directly via simple function into a Wavefront object. That is, I would like to read these two files myself and feed them to Wavefront constructor. I wonder if this can be done via some auxiliary function?

@einarf
Copy link
Member

einarf commented May 22, 2020

It does already load from cached files if they exist and the cache parameter is True

@morawi
Copy link
Author

morawi commented May 23, 2020

@einarf that's totally correct, but I would like to use those streams in my application (stream of bytes and not as a file); in fact, I would like to store them in a single file with some other data; then when I read the file I would like to construct the OBJ from those streams. One way to do this is to load those BIN and JSON file and store them into my file, then, at the time of loading; save them as BIN and JSON files and construct the object with cache=True, but that would be cumbersome.
Anyways, could you please guide me where in the code the loading happens? Maybe I can tweak it to my case.

@einarf
Copy link
Member

einarf commented May 23, 2020

I don't think you can fully reconstruct the obj from the bin/json file. They are mainly made so users can easily dump them into graphics memory.

I do have a library overriding the cache loader that just uploads the byte streams directly to the gpu instead of reconstructing the obj itself (much faster)
https://github.com/moderngl/moderngl-window/blob/4c3cd385718517a8055e8c271195f9100eaf2a66/moderngl_window/loaders/scene/wavefront.py#L52-L69

Cache loading triggers from this :

if self.cache:
self.load_cache()
if not self.cache_loaded:
super(ObjParser, self).parse()

Loader and saver is here : https://github.com/pywavefront/PyWavefront/blob/master/pywavefront/cache.py

@morawi
Copy link
Author

morawi commented May 23, 2020

What I wanted is to pass data instead of reading it via data = json.loads(fd.read()) (line 193) and other info red via file handler fd = gzip.open(str(cache_name(self.file_name)), 'rb') (lines 109-119) to the class constructor, but I guess that would disrupt the integrity of PyWavefront.

Hence, the best way to do this by allowing my application to save the cached files (BIN and JSON), same for the .mtl file if used, before calling PyWavefront (I am thus removing the original .obj file, and). I did a few tests and it worked even after xx.obj file has been removed, as long as cache=True and xx.obj.bin and xx.obj.json are available.

@einarf
Copy link
Member

einarf commented May 23, 2020

Yup. that seems reasonable. You can even replace the cache loader / saver classes here if you need more flexibility :

cache_loader_cls = CacheLoader
cache_writer_cls = CacheWriter

To make things future proof I would check the version in the json file. I had plans to extend this feature by adding pre-computed bounding boxes for example, but that might not break compatibility.

@morawi
Copy link
Author

morawi commented May 25, 2020

Thanks you for the heads up! I don't think I need to do this now, but maybe later.
The only concern, although trivial, is that when the original file OBJ is cached and then removed, one still needs to use its name when constructing the wavefront .. i.e. via
pywavefront.Wavefront('earth.obj', ...)
Not sure if it would be a good practice to remove the .obj extension from the name, and then to be added later inside Wavefront class if it is not there. In this case, as an example with earth file, one can either use,
pywavefront.Wavefront('earth', ...)
or
pywavefront.Wavefront('earth.obj', ...)

to construct the object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants