Fix per vertex normals and colors import #6
No reviewers
Labels
No Label
bug
confirmed
duplicate
enhancement
help wanted
High
known issue
Low
Normal
not a task
question
task
v2.4
wontfix
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: extensions/io_scene_x3d#6
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Hombre57/io_scene_x3d:per-vertex_normals_and_colors"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The 2 attached files can't be loaded properly with per-vertex normals and per-vertex colors. The proposed PR tries to update the code to the actual Blender API. However it might be a partial fix, I'm not used to. The change is inspired from other importer, which explains that the validation process might reorder the vertex list (and I experienced that...). That's why we have to save the normals and colors data to vertices before requiring validation, then move the data to their correct attributes.
The per-vertex color fix also add the shader node now and works fine here. I don't know if it has side effects on other files though.
Could you maybe include the issue numbers or error messages/misbehaviours the PR fixes? Just for documentation purposes...
There was no opened ticket for that, should I've had open one first ?
Nah, that's okay. Just include some details into the PR message or as comment. Ideally you can tell what get's fixed without opening a file :)
Ok, then for the record, the
normals.wrl
file is issued by TopSolid V6 with normals per vertex.colors.wrl
is a truncated file from another ticket I can't get my hand on anymore.normals
loaded with the unpatched code. It comes in Flat shading by defaultnormals
loaded with the patched code. It comes in Smooth shading by default with correct normalscolors
loaded with the unpatched code. The Color Attribute node has been added manually. The colors seems identical to the patched code, but using the same technique the prevent the validation to mess things up is required, IMHO.colors
loaded with the patched code, the Color Attribute node has been automatically set.Adding WIP status because this code probably needs an update of the required Blender version in
__init__.py
, but I don't know which one exactly. This patch works with 4.1.Fix per vertex normals and colors importto WIP: Fix per vertex normals and colors importJust tested in blender 4.2.
The color part works, even though the node gets weirdly placed (but i guess that cannot be influenced, maybe do some research there. Would be great if the placement could be corrected).
About the normals: With your script the file imports with flat shading (unlike stated in your description) and when set to smooth it still gets displayed weirdly (like your image B). Seems to either only work in blender 4.1 or didn't really get fixed yet. Also from the looks of it, it doesn't look like an issue with the normals, but rather marked sharp edges not being present.
Btw how do you know when an object should be shaded smooth or flat? Or is just the corrected normals part relevant?
I couldn't install the extension on 4.2.0 for now, the installation fail ( I already opened an issue ). So yes, it might only work for 4.1 for now.
I shouldn't have delete
node_vertex_color.location = (-200, 300)
after line 2754. The node is correctly placed with this. I've made a patch but can push it because of a connexion error, I'll try again tomorrow.I just discovered some... Blender weirdness, thanks to your comment. In fact, the object has to be displayed "flat" to use the normals per vertex and be displayed smooth. If one want a flat facets display, he has to delete the custom normals data. Is this behavior even documented ? "Shade smooth" does something that I don't understand, really.
I can't answer to that question anymore 😄
I see you've created an issue for https://extensions.blender.org/add-ons/universal-multi-importer/, but here we are talking about https://extensions.blender.org/add-ons/web3d-x3d-vrml2-format/. Does you issue persist when trying to install the extension directly via preference window?
👍
Btw you can also use the online code editor to make quick changes in the code, without relying on any git clients.
Ah okay. So usage of custom normals results in a custom (smooth) shading with blenders flat shade. To sumarize your commit uses custom normals data if present in the .wrl file, whereas the default behaviour is to ignore them. Seems to work then, was just described a bit off.
Small nit picks:
# And delete the temporary attribute
(line 2064 for example) are a bit redundant. I prefer to read the why, rather than the how (which is already there in code)Apply colors per vertex
you havebpymesh.validate()
in the else part (line 2081), but it's already done in line 2053. What's the reason behind it? Just asking for better understanding, haven't tested a change yet.Then after your little node patch and nit pick fixes i think it's okay to get merged.
I spent way too much time on that connexion problem, I finally made the change online, as you suggested @Bujus_Krachus.
The last commit remove the useless comments and only keep one
validate()
call. I initially wanted to keep one without argument when neither normals nor colors per vertex were given, but I managed to wrongly indent the code, so it didn't worked as expected.The default behavior was to import normals too as seen on line 1960 of the original file, but the API seems to have changed. Also, as explained in the doc, isn't Mesh.vertices supposed to be read only ?
Anyway, I looked in other import script on how to handle that and replicated there, so I hope it's fine.
WIP: Fix per vertex normals and colors importto Fix per vertex normals and colors importOne more question : are normals from this file correctly imported ? Seems weird. It comes from the Siemens NX CAD software, using the same Parasolid modeler than TopSolid, so it should be as clean despite the One shape per face export. This VRML file doesn't provide
normalIndex
. The specs says it should usecoordIndex
in that case. Here theFlat
attribute doesn't seem to be set by default.tldr: reinclude line 1960 (as this is unrelated to your changes) and use enforce flat shading when setting custom (split) normals to fix the shading issues by including a check when setting shading for crease angle.
Yes, i believe so. At least the split normals.
That's why i would leave line 1960
bpymesh.vertices.foreach_set("normal", co)
in. This sets the regular vertex normals, whilst your change adds the split normals for better shading control. Split Normals (or custom normals) are an extension of vertex normals and thus do different things. Would be great if you could adjust the comments to rule out any future confusion between split/regular normals.That's also what i noticed with the provided file. Without your changes it looks better in smooth shaded, with your changes far better in flat shaded (due to the correct import of split normals). The only weird behaviour i see is that in the provided
machine.wrl
file after import it's set to smooth shaded, basically discarding the correct custom normals import. Try enforcing flat shading when custom normals per vertex get imported in the check for crease angle in line 3041 of your fork (bpydata.set_sharp_from_angle(angle=creaseAngle)
should not be called for that polygon when using split normals; see below).Yes, according to the specs if normals field is not empty but the normalIndex field is, then coordIndex should be used as normalIndex. However if normals field is empty, then new normals should be generated using creaseAngle. Still, i don't get what you are trying to tell me here unfortunately...
line 1929 gives the answer, as a new mesh gets created within python. And in line 2048 the actual mesh gets updated with the python mesh. So the writing happens in a python only datablock. For convenience however BMesh should usually be used: Mesh Access.
Could be wrong here however, as i'm kinda new to blender scripting xd.
Should probably be a topic for a refactor of the addon to get rid of legacy artifacts from older api versions; but that would probably take a lot of time, as the direct
bpymesh
access gets used in all of the importer.👍
That answer took me far too long to write lol. Hope it helps :)
fyi according to my current latent knowledge you haven't done a fix, but added two features 🥇
see comment above
@Bujus_Krachus I finally had time to work on this. I've added the support of per vertex normals w/o normal index and changed the conditions for setting the polygon smooth.
Depending on the data in the WRL file, it'll either use
normals_split_custom_set
(i.e. per coin) orbpymesh.polygons.foreach_set("normal", co)
(i.e. per face), though I've not tested this one.On the colore side,
bpymesh.vertex_colors.new().data.foreach_set('color', cco)
should be replaced sincevertex_colors
i deprecated. I can look out later on how to replace it.As for the Machine.wrl file, I've investigated why the rendering is so bad. I find out that the lack of precision for the normal is triggering a recompute of the normals, not just their normalisation. You can clearly see that with Plan2.wrl file where the 3 digits normal values has a length of 0.999924 (see image G for the normals). Edit the file and switch to the second normal which has a length of 1.000000, and it will be used as is (see image H). I'll open another ticket for that, as I don't think CAD software will enhance their WRL files for more precision.
Yes it helped a lot and was worth it 🙏.
PS : As for reintroducing line 1960, I've tested that and didn't see any difference. Are you sure it's required since
normals_split_custom_set
does all the job ? Also, shouldn't we usebpymesh.polygon_normals
instead ofbpymesh.vertice
here ?Great to hear. Haven't tested yet with other files than your provided ones, but changes seem mostly valid.
However please revert the changes from
790902323c
for the color part, as now loading your providedcolors.wrl
file will throwKeyError: 'bpy_prop_collection[key]: key "Col" not found'
. Renamingnode_vertex_color.layer_name = "ColorPerCoin"
back tonode_vertex_color.layer_name = "Col"
works, but the material will be black, thus revert all color related changes from that commit or fix it.The custom normals part now works for provided file, due to the added check.
Sure? No, but i believe so, however i'm no expert here. In previous (visual) testing i've found no difference with/without though...
bpymesh.vertices
should probably be correct, as we set the vertex normals. Each face/polygon has multiple vertex normals but only one poly normal.If it works and the old code isn't interfering with the changes i would leave it in if no other reported issues or tasks refer to that code piece, until definetly sure. Otherwise i'd suggest creating a cleanup PR, which removes redundant or legacy code (like that it will be easier to track where stuff breaks if it breaks).
Will approve the PR after the color fix; the
bpymesh.vertices.foreach_set("normal", co)
will be your decision to make, my suggestion is to leave it in.I think it's useless, but I don't know the API enough to decide, so I'll take your conservative advice and leave it in.
The color attribute is fixed, my fault of a half imported patch, sorry.
I think it's ready to merge.
Thanks for the changes, works now and should be ready to merge :)
@Bujus_Krachus The fix for lack of decimals in vector components is pretty simple. I've committed a patch to add the normalization step. The
Machine.wrl
file is correctly imported now, with no penalty in processing time and precision for other files already correct. Tell me if this should be reverted and part of another PR. However it's totally related to normal import, though not only per vertex ones.Well, thanks for the addition. It can stay as now the imported mesh looks even cleaner than ever and though is totally realted to the PR with the suggested demo files.
However you're missing
import mathutils
at the start of the file, probably forgot to include that in the commit.mathutils
import d17730d608Damn ! I'm not used to produce such crappy commits 😶. Back and forth testing and yep, that line was gone. It still works w/o that line here, so that's why I didn't noticed it was gone.
No biggie, happens to all of us ;)
Btw as you seem quite knowledgeble with the wrl format feel free to suggest further bug fixes or code improvements if you want and have some spare time on your hand; contributions are always welcome
Hi, i merged my PRs into main, then attempted yours and saw a quite noticeable difference in shading of the file mentioned in #2. See the screenshots. Would be great if you could take a look at it.
current master without your PR, Color Attribute node added to a few sample objects:
current master with your PR:
notice how the color is far lighter, is that correct how it is?
Also we now have two identical color attributes (maybe reduce to one again, or what's the difference? Most likely caused since
790902323c
):@Bujus_Krachus It looks like that the 2 colors are defined with the sames values but with different result.
when set with
bpymesh.vertex_colors
(a deprecated function), it sets a default color attribute nameCol
showing a darker red.The second image in the originale post of blender/blender-addons#101604 also shows this dark red color, as well as some other VRLM online viewer.
when set with the new color_attributes mechanism, it sets my newly created
ColorPerCorner
attribute showing a lighter red. The color values out of the VRML files are0.84 0.28 0.28
. Setting this value as base color to one shape has identical result than custom vertex colors, so I guess that's the right color.When looking at Blender's code,
vertex_colors
is in linear color space. So the new mechanism behave differently and doesn't convert the color automatically, or I didn't find a setting somewhere to do so. That being said, I'm not sure of the color space used in VRML files. It says in §4.3.3 :So are we supposed to convert all colors to a special color space ?
you are totally right. Using the new API vs legacy API produces different results. This happens due to color space mismatch as seen here:
765b1c6b53
and like you explained above. Thanks for investiagting that so quickly :)In the importer the vertex color
Col
gets saved as linear using the lagcy API, whereasColorPerCorner
gets saved in srgb by the newer API. For now i'd account for that and follow the old scheme, meaning introducing a color space conversion (because other importers/software seem to use linear as well and to not introduce breaking changes to the addon):As a future improvement (as i've read you're interested in doing so), maybe let the users choose on the import which color space to display in.
Also to remove redundancy for users i'd propose this:
note: for consistency it may be good to update that to the newer api as well (including conversion)
future note: there are 2 other occurencies of
vertex_colors.new()
which could be updated -> not related to the current PRs topiccolor_attributes
API c957f6bc57Alright, then ready to merge. Any pending changes?
Done ! Thanks for the patch @Bujus_Krachus 👍
Yes, I'll probably add this options later, after my summer vacations 😉
Ready to merge for me.
Thanks for the contribution, merged.