I am dealing with a very simple sketchup file and I am suspecting a bad bug in Sketchup 2019.
4 duplicated faces with same texture distortion.skp
Here is the way the file join to this mail has been created created:
- I create a face and apply a brick texture.
- I make a distortion on the texture using Texture > Position
- I then duplicate the face 4 times.
So this should be the same face using the same internal representation texture.
Using the SDK and traversing the 4 faces I get one material and 4 different texture IDs (using SUTextureWriterLoadFace)
When extracting the texture, I got 4 very similar files (same dimension and nearly same content, but not exactly the same).
I can’t figure out why Sketchup is using internally 4 different images (I guess that internally there is 4 SUImageRepRef allocated with there image buffer).
It seems to be a huge waste of memory and performance.
Is it a normal behavior or I do miss something?
Note: SDK methods used to extract textures
SUTextureWriterLoadFace(textureWriter, suface,&frontTextureID, &backTextureID);
SUTextureWriterWriteTexture(textureWriter, frontTextureID, texturePath, false);
Sketchup supports STQ (non-affine) mapping, so internally there is only one texture for all 4 faces.
SUTextureWriter is a special helper for generating textures (unique texture for every face) for faces with STQ. Those unique textures can be used later in systems that doesn’t supports perspective correction.
It’s not a bug, everything works as expected.
This topic greatly overlaps with Sketchup generates too many textures, so it makes sense to continue any further discussion there.
Regarding the API/SDK, you are maybe incorrectly using the texture writer when you don’t need it. If your exporter can handle non-affine textures, you just get the texture coordinates and just once write the complete material’s texture to a file.
Yes I write this post because I found later a way to reproduce the problem out of the SDK context, using the collada exporter which give the same results, meaning that my way of using SUTextureWriter is probably good.
I didn’t find any information on the way to use STQ and perspective correction.
How can I acceed to the perspective correction matrix ?
How can I generate a UV if I have the STQ and the perpective correction matrix ?
Thanks for your help!
SketchUp does not give direct access to the texture projection matrix, only to a helper class (called UVHelper) that provides coordinate conversion
Usually that is sufficient for most purposes. With a lot of effort (and a bit too slow for Ruby) one can reconstruct the matrix and for example do the reverse and find the
XYZ position of a texture pin (red pin:
UV = (0,0)).
Generally, you can convert the
UVQ coordinate returned by
UVHelper into a 2-dimensional
UV coordinate on the plane of the textured face by dividing by the Q coordinate:
def uvq_to_uv(uvq) # mutates arguments
uvq.x /= uvq.z
uvq.y /= uvq.z
uvq.z = 1.0
point_on_face = face.vertices.first.position
uv_helper = face.get_UVHelper(true, true)
uvq = uv_helper.get_front_UVQ(point_on_face)
uv = uvq_to_uv(uvq)
Thanks for this script.
You go far in the analysis !
The problem reported in this post is not the perspective correction.
SUTextureWriter generates distorted textures for us and this is great.
But the problem is that SUTextureWriter writes 4 texture files for 4 same duplicated faces.
It should only write one file as the perspective projection is the same and the output texture file are similar.
So the challenge is to find a way to compare perspective correction between face.
The script pointed by Aerilius might be is a way to get a solution to that problem, because it allows to compare matrix, and to know if generated texture will be the same.
If you are fine with making a new unique texture, there is also a GUI tool that could (probably, I haven’t specifically tested) avoid the generation of 4 unique textures with identical distortion:
Texture Resizer was originally intended to reduce the model file size by optimizing resolution and size of textures. If the actually used area of a texture is smaller than the total texture, it determines all UV coordinates on the texture image and crops the image to the smallest fitting bounding box. If you have four faces with identical texture distortion selected, they should receive the same optimized texture image (instead of four). I’m however currently not sure if it bakes the distortion into the texture or not (but a good feature idea).
I am digging using your script and I succeed to get the projection matrix, thanks to your script.
It can help to reduce the generated texture number but the process is quite heavy.
To be sure that a generated texture output face #1 will be the same than the texture of face #2 you have to compare both:
- matrix between #1 & #2
- UV between #1 & #2
If both are the same, then the output file will be the same.
Trying to find a simpler way, I analyze different situation case and it appears that when SUFaceIsFrontMaterialAffine (or SUFaceIsBackMaterialAffine) is true for a given material, then the front (or back) output texture of this material is always the same.
I am not completely sure if SUTextureWriterLoadFace optimizes the front and back texture id it returns. It seems that different texture id can give the same output texture file, even when affine is true.
Finally I am not completely understand what is the action of the texture id parameter in SUFaceGetUVHelperWithTextureHandle and if it should be used against SUFaceGetUVHelper.
Life is hard with Sketchup texture !
Maybe @thomthom can answer this.
Still a mystery. Seems to provide the same result.
Anyway many thanks for your help Aerilius
Yea, the texture writer is not trivial to work with. To be honest I’m confused by it myself. It was added long before my time at SketchUp so I’m not sure of all the history or rationale behind it. Even documentation is slim. I have a project logged on my todo list to dive deep into this and document better its behaviour.
From what I can tell, you use
SUFaceGetUVHelper when you want the original (possible non-affine) UVs for a face. You use
SUFaceGetUVHelperWithTextureHandle when you use a TextureWriter to create affine textures. The texture writer and the handle is needed to make sure you get correct UVs for the non-affine UV mappings that were texture writer generates new textures.
Looks like it is reusing ids of loaded textures if they are affine or if a texture with similar UV matrix has already been loaded.
It’s still Happening!!!
Running on Sketchup 2020
I uploaded a photo
That looks like from a model that is complex enough so that it is hard to identify the cause. You will spend valuable hours and years of your life without progressing if you don’t take a more analytical approach:
Can you create an “MCVE”, a minimal example where everything irrelevant is removed except what causes the issue (e.g. 1-2 faces with 1 material)? If there is nothing else, it should be easy to spot the cause!
This allows either you to avoid/work-around it or developers to reproduce and fix it.