Backface Culling with Runtimeloader - QtQuick3D / QML
-
wrote 28 days ago last edited by
(Qt 6.9)
I am creating an application using QML / qtquick3d that needs to load .obj files. I have been using the runtimeloader QML type for this, which has worked great so far.
However, the models I need to import are dynamically generated by an external
library, and are "surface" objects (that is, they are a single face rather
than a closed shape).
I am running into an issue where The back face of these models is getting
culled, which is usually easy to remedy by changing the material of the object
to cullMode: Material.NoCulling. This worked when I tried it on a Rectangle
QML type.
The problem is that I can't seem to modify the material of the QQuick3DModel
created by the runtimeloader. I tried to change other properties, such as the
basecolor of the material, which also didn't work.For testing, I have gone back to the qt runtimeloader example
(https://code.qt.io/cgit/qt/qtquick3d.git/tree/examples/quick3d/runtimeloader?h=6.9)I am accessing the material using the following logic:
var model = importNode.data[0]; // Assuming the first child is the model var material = model.materials; if (material[0] instanceof PrincipledMaterial) { material[0].baseColor = "red"; material[0].cullMode = Material.NoCulling; model.materials = material; } else { console.log("No PrincipaledMaterial, or material not found"); }
After doing this, it looks like the material does change, but does not update
visually. Am I somehow not emitting a material changed signal / how could I
get the material to update? Am I totally on the wrong track?Is this something I can accomplish with shaders instead? If so, how?
To show the exact problem I am having, here is the behavior in the
runtimeloader example
compared to the desired behavior (from meshlab)
The object file I am using for these screenshots
-
wrote 22 days ago last edited by
Try this:
RuntimeLoader { function setCullModeRecursively(obj) { if (!obj) return; // Check if it's a PrincipledMaterial if (obj instanceof PrincipledMaterial) { obj.cullMode = PrincipledMaterial.NoCulling; } // Recurse into children if (obj.children) { for (let i = 0; i < obj.children.length; ++i) { setCullModeRecursively(obj.children[i]); } } } id: importNode source: windowRoot.importUrl instancing: instancingButton.checked ? instancing : null onBoundsChanged: helper.updateBounds(bounds) onStatusChanged: { if (status == RuntimeLoader.Success) { setCullModeRecursively(importNode) } } }
-
wrote 21 days ago last edited by
This did it - thank you so much, I've been trying to figure this out forever.
-
1/3