-
Notifications
You must be signed in to change notification settings - Fork 250
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
gltfPrimitiveToCesiumGeometry fixes #100
Conversation
@JoshuaStorm One of your tests is failing here and you do have a few jsHint errors. |
@lasalvavida Addressed |
@@ -11,20 +11,24 @@ var positions = new Float64Array([ -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0 | |||
var normals = new Float32Array([ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, | |||
0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, | |||
-1, 0, 0, -1, 0, 0, -1 ]); | |||
var sts = new Float32Array([ 6, 0, 5, 0, 6, 0.9999998807907104, 5, 0.9999998807907104, 4, 0, 5, 0, 4, 1, 5, 1, | |||
2, 0, 1, 0, 2, 1, 1, 1, 3, 0, 4, 0, 3, 1, 4, 1, 3, 0, 2, 0, 3, 1, 2, 1, 0, 0, 0, 0.9999998807907104, 1, 0, 1, | |||
0.9999998807907104 ]); | |||
var indices = new Uint32Array([ 0, 1, 2, 3, 2, 1, 4, 5, 6, 7, 6, 5, 8, 9, 10, 11, 10, 9, 12, 13, 14, 15, 14, 13, 16, 17, | |||
18, 19, 18, 17, 20, 21, 22, 23, 22, 21 ]); | |||
var primitiveType = 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have brought this up before, but instead can you extract these values from the gltf like in line 71-92 of cesiumGeometryToGltfPrimitiveSpec
, just so if the test model changes, the test will still pass.
That's all, looks good to me otherwise. |
Are we sure that we can't just handle all attributes in a generic manner? For the ones where the semantics are know, we can map glTF to Cesium, but for the others, I thought Cesium would allow generic attributes. |
I am not sure what the benefit would be to handling all attributes in a generic manner since only the attributes of known semantics will be changed when we use the geometry pipeline optimizations and our only intention is to use these geometries in intermediate steps of the gltf pipeline. Wouldn't we just be reading attributes to rewrite them exactly the same later? |
For example, look at GeometryPipeline.reorderForPreVertexCache. It moves each attribute. |
Updated. I expect this PR will still need a bit of work after this refactoring, let me know if you think I'm on the right track for what you had in mind @pjcozzi. |
Actually found a bug while doing further testing. Not ready for review, my bad. |
As of now, When putting a geometry through When putting a geometry through However, when putting a gltf through both, it seems to mangle some primitives (see below). If I flip the order of I've tried a few things and double checked that |
Update to the last comment: I believe the bugs are all in my use of the |
@lilleyse can you please help @JoshuaStorm with the Cesium API if needed? |
5f90e2e
to
eddd8c8
Compare
3189b6a
to
f1d3fba
Compare
Had to rebase due to pulling and accidentally pushing from one of Rob's PRs for testing. As Sean and I discussed offline: The scope of this PR is decreasing to just implementing the A brief description of the issue: the pre vertex cache optimization shifts around both the primitive's attributes and primitive's indices. This is fine when only one primitive uses each attributes accessor, but in many cases, when the attributes accessors are shared (when multiple primitives share vertices), the model will get mangled as the shared vertices will be shifted each time a primitive accesses it resulting in indices referring to the wrong vertices. We have a couple ideas for possible solutions, but none of which are perfect and involve quite a bit of work, so Sean and I figured that would be appropriate for another PR. |
@JoshuaStorm, I split off the |
@JoshuaStorm Do you want to try the pre-vertex cache with the new code before I look into this? |
Yeah, I'll give it a shot and let you know when this is good for review |
attributeName = 'normal'; | ||
finalValues = new Float32Array(packed); | ||
break; | ||
case 'TEXCOORD_0': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you take a look at the glTF spec, valid attributes are of the form SEMANTIC
or SEMANTIC_#
. You need to check if the attributeId starts with a semantic, equality won't work for all cases. For example, this could be TEXCOORD
instead of TEXCOORD_0
in a valid glTF file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since Cesium Geometries only directly handle one position
, normal
, and st
, I believe it would be sufficient to just handle equality of SEMANTIC
or SEMANTIC_0
and just allow the default option for generic Geometry attributes.
Is there any circumstance where the first SEMANTIC_#
# wouldn't be 0?
Updated, still seeking thoughts in regards to @lasalvavida's comment:
Since Cesium Geometries only directly handle one Is there any circumstance where the first |
var primitivesOfIndicesId; | ||
if (!dictionary[indicesId]) { | ||
primitivesOfIndicesId = []; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra whitespace
@JoshuaStorm Take a look at the specification. Specifically:
The short answer to your question is yes. Maybe there are two primitives with different materials, and the author decided to make them use TEXCOORD_0 and TEXCOORD_1 to make it easier to tell them apart. That is still valid glTF. There's also nothing stopping someone from making it TEXCOORD_25, or POSITION_3 if they want to. Just doing a check for whether the listed semantic starts with the one you're looking for should be fine for all cases. if (attributeSemantic.indexOf(semantic) === 0) {
...
} |
Updated, I hope I didn't miss anything. I am actually handling semantics a bit differently now to avoid possible issues with different semantic naming schemes. Currently when going from gltf primitive <-> Cesium Geometry, I am just using the first semantic to map accordingly and just having the rest be generic attributes. This works fine for now, but I may need to modify it slightly once I change #82 to use the GeometryPipeline. |
if (attributes.hasOwnProperty(semantic)) { | ||
var accessorId = attributes[semantic]; | ||
if (defined(attributeAccessors[accessorId])) { | ||
if (attributeAccessors[semantic] === attributes[semantic]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this testing for? attributeAccessors
doesn't have semantic
keys. I think just the defined check should be sufficient here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must've accidentally ctrl-zed that back at some pooint, oops.
Aside from a final review, this should be good to go. |
function createIndicesToAttributeDictionary(gltf) { | ||
var dictionary = {}; | ||
var meshes = gltf.meshes; | ||
for (var meshId in meshes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use NodeHelpers.forEachPrimitiveInScene
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this currently in master? I cannot seem to find this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not; it is in the ao branch. I think forego using it for now since it is async and doesn't have a way to notify when it completes currently.
@lasalvavida for your final testing, could you please do some performance testing with a model with a large number of vertices and no textures (like Happy Buddha or the Dragon from http://graphics.stanford.edu/data/3Dscanrep/)? In Cesium, turn off the globe, stars, and sky, (or use the Model Inspector) and see what the FPS is with and without cache optimization. You may need to load several of the same model to notice. A 10% win would be good. It is probably less. For numbers from the original paper, see http://gfx.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/index.php |
@pjcozzi: Before pipeline: Through the pipeline without cache optimization: Through the pipeline with cache optimization:
I've checked triple checked that I'm not making a mistake here, but the performance improvements seem better than we expected. |
@JoshuaStorm Good job, that's awesome! I will try to duplicate soon. |
Despite this being a heavily vertex-bound test case, I still did not expect something this good! |
@JoshuaStorm When I run the chinese dragon model through the pipeline with and without cache optimization enabled, I see no change. Could you please attach the models you used for your test here? |
Odd, here's the model I used: |
@JoshuaStorm I meant can you attach the ones with and without cache optimization? |
Sorry about that: below is the cache optimized, the original input, and the original input through the pipeline without the cache optimization. |
@JoshuaStorm The model I was using had split primitives, which is why there was no change. That is the desired behavior. I tested with the models you provided and got the same results, great job! |
Now handles texture coordinate attribute. See: #90
As of now, it is only handling one set of texture coordinates. I was unable to find a gltf model with multiple texture coordinate sets for one primitive. Do we have any?
Addressed some other small comments from #90 as well.
I'm also wondering where I should be putting the pre and post VS optimizations within the pipeline. I imagine the pre can replace a portion of what is now labeled the
cacheOptimization
step. When do we want to perform the post VS optimization?