Conversation
|
Fixes #2 - power plant converts with the |
Can you elaborate on this? Because even without out-of-core processing, this seems like an architectural issue somewhere in the code. |
|
Yes maybe, I'm doing some more tests but the actual numbers do look better than that. |
|
Maybe obj size isn't the best metric, but I ran through two highly tessellated spheres, one with smooth normals and one with face normals, both 3.2 GB. The first one converts while the second has enough indices that the index array exceeds the maximum allowable typed array length. This could be solved by splitting primitives, something I was trying to avoid - also maybe future work because I want to get these changes in pretty soon. I actually don't think I have any "real" objs that fail at the moment, @shehzan10 had one that I still need to try out sometime tomorrow. |
|
Thanks, that makes sense and sounds like a perfectly fine limitation until we need to handle massive obj files. |
|
@likangning93 can you please review this? |
|
41956dd allows @shehzan10's model to be converted, but |
|
Ready now. |
likangning93
left a comment
There was a problem hiding this comment.
Looking at obj.js and spec to start off.
| var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float | ||
| var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float | ||
| var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float | ||
| var facePattern1 = /f( +-?\d+)\/?( +-?\d+)\/?( +-?\d+)\/?( +-?\d+)?\/?/; // f vertex vertex vertex ... |
There was a problem hiding this comment.
I'm pretty inexperienced with regexes, so I could have used a note that the facePattern regexes return something like [generatedVertexID, position, texCoord, Normal]
There was a problem hiding this comment.
oh wait, actually just saw the comments to the side... nevermind.
| } | ||
|
|
||
| function useMaterial(name) { | ||
| // Look to see if this material has already been used by a primitive in the mesh |
There was a problem hiding this comment.
Would it be better to use a per-Mesh dictionary for materials?
There was a problem hiding this comment.
Yeah I could have done a material -> primitive dictionary. Since nodes and meshes are also arrays I just wanted to keep it consistent.
| for (var i = 0; i < primitivesLength; ++i) { | ||
| primitive = primitives[i]; // Sets the active primitive in case of returning early | ||
| if (primitive.material === material) { | ||
| return; |
There was a problem hiding this comment.
clearer to do
primitive = primitives[i]; // Sets the active primitive in case of returning early
here, does that break anything?
There was a problem hiding this comment.
Yes that is clearer.
| .then(function(materials) { | ||
| var imagePaths = getImagePaths(materials); | ||
| return loadImages(imagePaths, objPath) | ||
| .then(function(images) { |
There was a problem hiding this comment.
less indentation:
return loadMaterials(...)
.then(function(materials) {
///
})
.then(function(images) {
///
});
There was a problem hiding this comment.
The downside here is then materials is not in the closure of the final return (without a helper var).
There was a problem hiding this comment.
ah that's right... ok.
| // Collect all the image files from the materials | ||
| var images = []; | ||
| function getImagePaths(materials) { | ||
| var imagePaths = []; |
There was a problem hiding this comment.
Does indexOf do a linear search? Maybe a dictionary would be better here for an .obj with a huge number of textures.
There was a problem hiding this comment.
Yup, will fix that.
|
|
||
| describe('obj', function() { | ||
| it('loads obj with positions, normals, and uvs', function(done) { | ||
| expect(loadObj(objUrl) |
There was a problem hiding this comment.
Out of curiosity, is there a difference between wrapping in expect(...).toResolve() and something like:
loadObj(..)
.then(function(data)) {
///
done();
});
There was a problem hiding this comment.
In that way if the promise failed it wouldn't reach done(). The test would still fail due to a timeout, but the version in objSpec would fail faster.
| }), done).toResolve(); | ||
| }); | ||
|
|
||
| it('loads obj with triangle faces', function(done) { |
There was a problem hiding this comment.
duplicate, was this supposed to be quads?
There was a problem hiding this comment.
Ah, good catch. The other tests all use quads.
| .then(function(data) { | ||
| var extension = path.extname(imagePath); | ||
| var uriType = getUriType(extension); | ||
| var uri = uriType + ';base64,' + data.toString('base64'); |
There was a problem hiding this comment.
Should this include a check on the buffer length for large textures? Otherwise, maybe we should add a troubleshooting section in the README.md with things to try, like writing out separate images if there's a buffer.toString error.
There was a problem hiding this comment.
Yeah a common check like this could be in a few places.
| info.format = getFormat(channels); | ||
|
|
||
| if (channels === 4) { | ||
| // Need to do a finer grained check over the pixels to see if the image is actually transparent |
There was a problem hiding this comment.
As discussed offline, a lot of images may be 4-channel PNGs that don't have any transparent pixels. I wonder if it's okay to just make transparency a flag option, since a full pixel level check might be kind of slow.
There was a problem hiding this comment.
Good idea for adding an option for this.
There was a problem hiding this comment.
With one model I noticed a difference from 200 ms to 6000 ms just by checking this. (It had lots of textures though).
|
Updated. The uri handling is better now. |
| }); | ||
|
|
||
| it('bypassPipeline flag bypasses gltf-pipeline', function(done) { | ||
| var spy1 = spyOn(convert, '_outputJson'); |
There was a problem hiding this comment.
No need to create these variables, just call spyOn.
| expect(convert(objPath, gltfPath, options) | ||
| .then(function() { | ||
| expect(spy1.calls.count()).toBe(1); | ||
| expect(spy2.calls.count()).toBe(0); |
There was a problem hiding this comment.
This is better written as expect(GltfPipeline.processJSONToDisk).not.toHaveBeenCalled();
| }; | ||
| expect(convert(objPath, gltfPath, options) | ||
| .then(function() { | ||
| expect(spy1.calls.count()).toBe(1); |
There was a problem hiding this comment.
This is better written as expect(convert._outputJson).toHaveBeenCalled();
| }), done).toResolve(); | ||
| }); | ||
|
|
||
| it('uses a custom logger', function(done) { |
There was a problem hiding this comment.
This test isn't really useful (and is also fragile if we change what we're logging). We should be testing for specific log messages in each instance we expect one to be generated, not just running something and seeing if the logger gets called.
There was a problem hiding this comment.
Removed this.
I checked and the all the actually places things are logged are accounted for.
| var fsExtra = require('fs-extra'); | ||
| var path = require('path'); | ||
| var Promise = require('bluebird'); | ||
| var clone = require('../../lib/clone.js'); |
There was a problem hiding this comment.
Remove .js from these requires.
| var diffuseTexture; | ||
| var transparentDiffuseTexture; | ||
|
|
||
| beforeAll(function(done) { |
There was a problem hiding this comment.
Change this to a beforeEach and get rid of all of the clone usage. You can then delete the clone.js.
| var defaultValue = Cesium.defaultValue; | ||
| var WebGLConstants = Cesium.WebGLConstants; | ||
|
|
||
| module.exports = loadImage; |
There was a problem hiding this comment.
Filename and function name don't match. Shouldn't the file be called loadImage?
There was a problem hiding this comment.
This is a problem with most of the files in lib. They should all be fixed. We can do that in a quick separate PR after this is merged if you want, but please write up an issue.
| * @private | ||
| */ | ||
| function loadImage(imagePath, options) { | ||
| options = defaultValue(options, defaultValue.EMPTY_OBJECT); |
There was a problem hiding this comment.
This function should check if imagePath is a string and throw a DeveloperError before doing anything else (also add a test for it).
| return path.normalize(path.join(path.dirname(objPath), relativePath)); | ||
| } | ||
|
|
||
| describe('mtl', function() { |
There was a problem hiding this comment.
Can be a separate PR, but there are no tests here for how we handle invalid mtl files and we don't do any sort of parameter validation either. Please write up an issue to review all functions for error handling and parameter validation.
|
OK, that's all I have for the first go around. Given the size of this PR, there are definitely things we should do as separate PRs after this is merged, but let's make sure we write issues so nothing drops on the floor. Thanks @lilleyse! |
|
Thanks for the thorough review @mramato, I'll get to these soon. |
|
I got through a lot of the comments here. I may briefly scan everything again but I believe this is ready. Some things I haven't addressed in this PR but will handle in others:
Breaking change |
|
@lilleyse please make sure there are issues for everything in #49 (comment). |
|
@lilleyse please comment close all the issues in #49 (comment). |
|
@lilleyse when you get a chance, it would be great to publish a new version to npm as well. |
This refactor fixes a few long-standing issues with this project:
To-do:
--bypassPipeline, so there are some issues to look into for gltf-pipeline