Layers and faces

We use SketchUp SDK in our cross-platform app for a couple of years already. In our app user can import different 3D formats, including .skp, then we show 3D scene in OpenGL window, allow to rotate it, change materials’ colors save as 2D image.
Some people complain that they see the scene very different from what it looks like in SketchUp app. So, what happens is that we can’t handle object visibility and layer colors correctly. Like, in this casa.skp file:
Car and (2.7 MB)
there are several layers, they have colors and different visibilities.
When we read this file using similar approach demonstrated in skp2xml project example, calling inheritance_manager_.GetCurrentLayer(); on the lowest level for each face, for most of them we get Layer0. But if you open the scene in SketchUp app it’s clear that they don’t belong to that layer (hiding/showing Layer0 does not affect building walls, for example). So we get wrong visibility and layer color in our app. What do we do wrong? Even if we just call
SUDrawingElementRef drawingEl = SUFaceToDrawingElement(face);
SULayerRef layer = SU_INVALID;
SUDrawingElementGetLayer(drawingEl, &layer);
we get the wrong layer for the walls. It returns Layer0, not even Invalid or 0 value. So, even if the parent objects (groups, instances) have correct layer, we have to ignore them and use the wrong one, returned by each face, since it’s not zero or invalid).

Second question is, when user select “color by layer” and saves the file, when we read it in our app, how can we know that this mode is on?

Also, we tried some tricks - convert .skp to .fbx before opening it, because we handle .fbx much better. First, we couldn’t access the SketchUpModelExporterInterface that easily from skp2fbx.dll internal SketchUp exporter plugin. Then we found that we have to use certain version of Visual Studio and compiler flags, because std::string objects don’t parse correctly. Not clear why ConvertFromSkp from SketchUpModelExporterInterface is made with std string arguments that cause VS version limitations instead of just parsing const char * that can be UTF8. But, anyways, after files are converted to fbx, they also often look different from what they look like in SketchUp app. Even if it’s converted in SketchUp app, faces get wrong materials. Like this attached model car.skp looks wrong after conversion.
So, we had to leave that idea.

And the last question about SUFaceRef and SUMeshHelperCreate.
Is there a way to get normal per vertex from SUFaceRef without using SUMeshHelperCreate ? I mean not just a normal to face, but per vertex that allow to make soft edges. Right now we have to create SUMeshHelperCreate and call SUMeshHelperGetNormals in order to do that. Also, after we create the mesh helper, where is it stored? Does it become attached to the face object somehow? Can we reuse it, like getting it instead of faces if we reread same model? Or is there any global function that would triangulate the whole model before we access each face?

Thank you for your help. It’s very important to us.

You need to check the whole hierarchy for an entity if it’s visible or not - all it’s parent group or components.

This is found under the model’s rendering options. A list of keys can be found here:

Why do you need the vertex normal for this? Can you not use SUEdgeGetSoft and SUEdgeGetSmooth for this?

Of course, that’s what we do. But, as I said, on the lowest level, when I call SUDrawingElementGetLayer for a face, I often get a wrong layer. Like, for the walls in casa.skp that I attached in the first message, I get Layer0, while in SketchUp app they don’t belong to that layer.

Found it, thank you.

We don’t draw edge objects, only faces. So, even if I find a way to access edge objects for each face and get this “soft” or “smooth” flag, then how can I use it in glVertex? I would need to get face normals for attached faces and do some math to find an average value. Is that what MeshHelper does? I just thought that maybe SketchUp saves normals per each vertex in the scene and I could access this array somehow.

Can you show in a screenshot exactly what face that is? (Just so we can be sure to test the same thing.)

Almost all faces. For all that you see red on the picture I get Layer0 after calling:

SUDrawingElementRef drawingEl = SUFaceToDrawingElement(face);
SULayerRef layer = SU_INVALID;
SUDrawingElementGetLayer(drawingEl, &layer);

or even when I use inheritance_manager_->GetCurrentLayer(); from skp2xml sample code.

But those faces are on Layer0…

Only faces I see that are not on Layer0 in your model is the pillars you marked in yellow in your screenshot and the blue fence.

As far as I can see the method return exactly what is expected.

I see that the outer group is on a different layer, but that will not reflect what layer you get from the face. This is where you need to keep track of the parent layer when you traverse the model.

But then why if most faces really belong to Layer0 they don’t disappear in SketchUp app when I hide this layer? (in Layers window)

Ah - right - that’s one of SketchUp’s exception to the rule thing. (I find it annoying, but it’s part of some old compatibility thing.)
Like, if you draw a face on the ground plane SketchUp will force the face orientation to point downward - regardless of the order of the vertices.

So in summary:
What layer entity shows you is the layer the entity belong to. Layer0 has some special handling in terms of visibility in the viewport.

I found that long time ago and work around it by recalculating normals on my own, based on the order of the vertices. But I don’t understand how it’s related to the face visibility. Why does Layer0 visibility in casa.skp example affect some faces and does not affect others? Same for materials - Layer0 has red color. Why some faces that belong to the layer are painted red, while others are not?

You appear to mix materials and layers here. I’m not sure which one you are talking about. From your screenshot it looks like you have Color By Layer enabled.
For entities with on layer0 the parent layers will override it.

Group on Layer1
 > Face on Layer0

The controlling layer (visibility and layer color) will be Layer1.

Group on Layer1
 > Face on Layer2

Here the controlling layer (layer color) will be Layer2.
If you turn on Layer1 the group will hide. If you hide Layer2 the face will hide.

Consider Layer0 to be no layer. Like Materials, entity.material = nil means no material meaning it’ll use the default colors for faces.

When you have layer0 or no material it will inherit from the parent. For materials and layer color it will inherit for the closest parent with a non-layer0 layer (or non-nil material for materials).



So, as I understand, for any entity I should inherit layer material from its closest parent if the current entity belongs to Layer0? If there is no other layer in the face hierarchy besides Layer0, I use Layer0 material and visibility, right?
Then could you explain the behavior of the roof from casa.skp? The roofs faces belong to Layer0 as most others. They are painted brown, not red, because there is another Layer with brown color in the roof’s hierarchy, it’s clear now. But when I hide Layer0, the roof hides too, just like the red ground plan. Why does it happen?

Group on Layer1
 > Face on Layer0

When you hide Layer0 you hide the face itself.
When you hide Layer1 you hide the group that contains the face - so it also becomes hidden.

In general though, dealing with layers are made simpler if you stick to keeping edges and faces on Layer0 at all times. Then place groups and components on layers. This is one of the most common best practices you’ll hear for SketchUp modelling. Once you start mixing it’s harder to keep track of it all.