Mon, 08/30/2021 - 00:10
Hi!
I have spent a lot of time, trying to figure this one out - with no success...
I'm using OpenCascade.js, so the code is in JavaScript. But it works more or less the same way as in C++.
First, I create a polygon shape.
const makePolygon = () => {
const path = [[-50, 0, 0], [50, 0, 0], [50, 100, 0]].map(([x, y, z]) => new oc.gp_Pnt_3(x, y, z));
const wire = new oc.BRepBuilderAPI_MakePolygon_3(path[0], path[1], path[2], true).Wire();
return new oc.BRepBuilderAPI_MakeFace_15(wire, false).Shape();
}
Next, I want to export my shape into a GLB file.
const exportShape = (s: TopoDS_Shape) => {
// create doc, add shape label...
const doc = new oc.TDocStd_Document(new oc.TCollection_ExtendedString_1());
const theChild = doc.Main().NewChild();
const st = oc.XCAFDoc_ShapeTool.Set(theChild).get();
const shapeLabel = st.NewShape();
st.SetShape(shapeLabel, s);
// trying to define visualization material...
const vmtool = oc.XCAFDoc_VisMaterialTool.Set(shapeLabel);
const m = new oc.XCAFDoc_VisMaterial();
const pbrm = new oc.XCAFDoc_VisMaterialPBR();
pbrm.BaseColor.SetValues(1, 0, 0, 1);
m.SetPbrMaterial(pbrm);
const matLabel = vmtool.get().AddMaterial_1(new oc.Handle_XCAFDoc_VisMaterial_2(m), new oc.TCollection_AsciiString_2("myMatName"));
vmtool.get().SetShapeMaterial_1(shapeLabel, matLabel);
// triangulate and export
new oc.BRepMesh_IncrementalMesh_2(s, 0.1, false, 0.1, false);
const cafWriter = new oc.RWGltf_CafWriter(new oc.TCollection_AsciiString_2("./file.glb"), true);
cafWriter.Perform_2(new oc.Handle_TDocStd_Document_2(doc), new oc.TColStd_IndexedDataMapOfStringString_1(), new oc.Message_ProgressRange_1());
}
// ...
exportShape(makePolygon());
The export works without errors. But the material definition doesn't get picked up in the GLTF export. And my polygon shows up always in white.
What can I do to have my material exported correctly?
Any help would be greatly appreciated!
Attachments:
Mon, 08/30/2021 - 10:55
Make sure to set XCAFDoc_VisMaterialPBR::IsDefined flag to TRUE, as it is FALSE by default. Maybe it wasn't a good idea setting it to FALSE by default...
Mon, 08/30/2021 - 15:22
Thanks for your help!
However, adding the line
doesn't seem to make a difference. Polygon is still white.
Mon, 08/30/2021 - 16:02
It might be also helpful dumping an XBF file (TDocStd_Application::SaveAs) to be able to traverse it's structure and see if materials are displayed before glTF export.
Mon, 08/30/2021 - 15:28
...I'm also still on version 7.5.2. Can that be part of the problem? I will make the update and post my results here.
Mon, 08/30/2021 - 21:23
Where have you found such a weird pattern for working with Tools? XCAFDoc Tools are not expected to be placed randomly in the document - they should lie on specific labels in the document created by XCAFDoc_DocumentTool and returned by static methods XCAFDoc_DocumentTool::VisMaterialTool() / XCAFDoc_DocumentTool::ShapeTool() and others.
I guess XCAFDoc_DocumentTool::Set() and similar methods are declared public by mistake.
Don't how this should look correctly in JavaScript:
Mon, 08/30/2021 - 23:37
I guess, I was just trying different things. Thanks for clarifying how to use those classes.
I updated my code with your recommendations, which took a while, since I was missing some bindings. The code now looks like this:
The resulting glb file seems to be unchanged. My polygon is still plain white. The exported xbf file is attached - it shows that no material definition is attached. This is still done with version 7.5.2 - a build for 7.5.3. will finish soon.
I'm pretty sure that I'm probably just attaching / defining the material in an incorrect way. Do you (or anyone else) know a good reference with an example on how to do this correctly?
Thanks a lot for your help!
Tue, 08/31/2021 - 00:09
My previous comment was not quite accurate: The material name actually shows up in CAD Assistant. The fact that the color is not exported correctly seems more like a OpenCascade.js - related problem (not one of OpenCascade)...
Tue, 08/31/2021 - 11:53
Indeed, your XBF file contains myMatName material with PBR enabled, but it defines a WHITE color. So probably XCAFDoc_VisMaterialPBR modification code doesn't work as expected in JavaScript wrapper. Maybe you may try something like this:
Wed, 09/01/2021 - 00:02
Thanks a lot for your help, Kirill.
Your suggested JavaScript code seems to solve the issue.
Having another look at this line...
...I think what happens is that the part
(pbrm as any).BaseColor
actually calls theget
handler of an Emscripten-generated JavaScript proxy, which calls C++ code that creates a copy of that property. The call toSetValues
then operates on that copy. I think this situation should only happen for properties (for which Emscripten auto-generatesget
andset
handlers) - not for regular function calls.It's definitely a bit unintuitive (at least for me), but since it's Emscripten's default behavior, I think I will keep the functionality as it is, for the moment.
For completeness (and if someone else has a similar problem in the future), here is my code, which now works.
Thanks again!
Wed, 09/01/2021 - 13:53
This kind of issue happens from time to time with language wrapping layers (to C#, Java too), as it is tricky to work with structures with mixed by reference / by copy meaning - something natural to C++, but not to (some) other languages. Just need to know where them to expect within particular binding to avoid writing a broken code.