I ve been having an issue where under some circumstances when I write out the texture of a narrow/thin face, SU will output the whole PhotoMatch material instead. This is consistent on using both the ruby API as well as extracting a .dae.
To reproduce it open the attached skp file, and either extract to Collada, or run the below:
face = Sketchup.active_model.entities.detect{|ent| ent.is_a? Sketchup::Face}
temp_cutout = Tempfile.new(['cutout','.jpg'])
temp_cutout.close
texture_writer = Sketchup.create_texture_writer
texture_writer.load(face, true)
texture_writer.write(face, true, temp_cutout.path)
puts "#{temp_cutout.path} has the full image, instead of a thin vertical segment"
I think this is a bug of SU, but would love to hear what you think. texture_bug.skp (520.6 KB)
Hi @gpavlidi,
The API is behaving as expected. TextureWriter will always output the full image, regardless of how the texture is mapped on to the face. If you want a narrow strip of the image, youâd need to extract it from the full image using the texture coordinates on the face.
Hi @bugra,
thanks for looking into this.
I dont think the API is behaving as expected, as TextureWriter is supposed to output the undistorted cutout of the face (at least thats what itâs doing for 99% of faces in the models I work with)
In fact if I reproject the PhotoMatch photo in the same narrow face and tweak it with Texture->Position it works fine and the output is a narrow strip. You can try it in the below skp file, running the same ruby code as above.
So I guess something in the mapping of the first skp file is throwing TextureWriter off and makes it output the full image, whereas in the second skp it works as expected (for me at least).
Seems like the post was moved to Ruby API by @Geo
Wouldnt want this to be perceived as an API question, ruby code is there just to reproduce it easily, you can run on the same behavior if you File->Export->Collada .
I think itâs a bug and should be under âTechnical Problemsâ, just so it has better chances getting the necessary attention from SU devs too.
Thatâs almost correct - the exception is when the mapping onto the face is produce UVQ values where the Q value is not 1.0.
Lets have a quick look at the various ways a texture can be mapped on to a face:
All the three first cases will produce UVQ mapping where the Q value is 1.0 - this means the texture mapping plane is planar to the face.
In the last case the texture plane is different from the faceâs plane - and you will see values of Q that is not 1.0.
Many file formats doesnât support the Q value - and thatâs where the TextureWriter comes in. When you feed the Texture writer a face where the texture plane is different from the face it will generate a new texture and new UV coordinates. This allows exporters to export SketchUp models which is visually accurate.
(Some exporters take the approach of dividing U and V by Q - but thatâs just an approximation and visual deviation will occur. However some exporters prefer this over generating a large amount of unique textures.)
When applying projected textures you often end up with perspective mapping because the source texture mapping normal will be different from the target facesâ normal.
Unfortunately the documentation for the TextureWriter doesnât explain this behaviour very well. We have an open issue to improve this. But thatâs the original intent for it. It has never been intended to always crop and create new unique textures.
The Ruby API Sketchup::TextureWriter class is a thin wrapper on top of our internal C++ TextureWriter class which our exporters use. When you observe that an export - or any usage of TextureWriter - produce a mix of cropped and non-cropped textures, that is intended behaviour. Our exporters prefer to export original texture files - but will fall back to creating unique ones only when needed to preserve visual appearance of the exported mesh.
One common requests we have from developers is to export all textures in a model without cropping. I think this is the first time Iâve heard itâs desired to see the behaviour for all faces.
If you can provide us with an use-case for why you want all textures for all faces to be cropped like this I can file a feature request.
thanks for the very detailed explanation, it definitely makes more sense. I can confirm that in my case the desired cutouts are generated only for perspective transforms.
Hereâs my use case:
Lets say you have a cube, and 4 PhotoMatch photos (8MP), one for each side of the cube. If I texture each of the 4 faces with a photo with a non-perspective mapping, and then export a Collada or kmz, the full 8MP images will be included in the model, when in fact you only need 4 512x512 cutouts for example, raising the filesize significantly. Also if u needed to atlas the cutouts for further optimization, you d need to crop them first from the full size images and adjust uvs to the new size, adding more post-processing.
The ideal thing for my use case would be to add something like a âforce_new_texturesâ flag to Sketchup::TextureWriter that would let you have more control on exported textures etc. and thus size of output model.
Not sure if this is going to work, as I think this will also capture 3d geometry, axes etc.
I guess I could hide them first, but then i need to figure out the optimal position of the view.camera for each face.
What I ended up doing is, whenever I get a non-perspective transform, I just add 0.001 pixel to one of the uvs. That usually makes it perspective enough so that SU is generating a unique cutout. Pretty ugly hack but havent noticed any significant visual artifact of the +0.001.
Or maybe something like exposing the Make Unique Texture functionality:
?
Itâs not likely that the Ruby API itself will offer general image manipulation functionality - thatâs rather out of the scope. Youâd be better off looking for such libraries either in Ruby - or probably better, C libraries which you can integrate via Ruby C Extensions.
This would work although it would âpolluteâ Sketchup.active_model.materials adding all these cutouts when exporting. The good thing about TextureWriter is that it only affects a given output file.
I hear you about image manipulation, at least after this thread itâs clear how TextureWriter works so I should be able to crop the cutout myself. Having said that, I would definitely welcome a âforce_new_texturesâ kind of functionality, as it ll result in significantly lighter models in some cases, but until then Image Magick might be the way to go.