Determine required size for CanvasTexture canvas

Let’s say I want to use a CanvasTexture as the texture for the “side” for a cylinder (so, everything but the top and bottom circle). Is there some way to dynamically (without hardcoding anything about the model) get the required aspect ratio of the canvas?

I have tried getting the aspect ratio from the UV coords, but they are not proportional to the “world space” size. (Using a completely default Blender cylinder. Even though it’s OT I would also be very happy about suggestions for how to approach this from the Blender side of things.)

Any and all suggestions welcome, I have been bashing my head against this for a while now.

Short answer No.

Long answer, yes if you know exactly how the UVs are mapped on the cylinder, and how the cylinder is being scaled for display.

Question:
Can you describe on a higher level what you are trying to make and why you need to do this?

Do you mean the circumference and length of the cylinder? Can you not use a standard texture size (power of 2) and Texture.repeat.set(1, length)?

Thanks a lot for your response! Re your long answer: Could you elaborate a little more? I would prefer making some assumptions about the UV mapping over hardcoding dimensions. Why is scaling for display relevant? The aspect ratio shouldn’t change, and I can always adjust the canvas resolution later.

At a higher level, I would like to use CanvasTextures for (parts of) models. I care a lot about the texture not being stretched/wrapped, so I need to determine exactly how big the canvas needs to be. I got this to work easily enough on a square plane, but extending it to more complex models has been challenging. (I think it’s because I don’t know how to determine the aspect ratio, but I may be missing something.)

In particular, the canvas supports user interaction (passed through from interaction with the threejs canvas), so eg. shapes can be moved around/added/etc.

When assuming that the thing I am using the canvas texture on is rectangular (and just “wrapped around” something like a cylinder) I felt like UVs should help here, but it seems that they are not proportional: eg. for the default Blender cylinder the side UVs have a “circumference”/height ratio of 2, but the actual cylinder has one that is around 3.

Sorry, I should have specified: I do not want the texture to stretch or repeat.

Scaling on only one axis does change the aspect. Uniformly scaling the object won’t.

Can you describe what you are trying to build on a higher level? Because it sounds like you may be focusing on a misunderstood detail of the larger picture?

You can get the worldspace bounds of a mesh via:

let bounds = new THREE.Box3().setFromObject( theMesh );
let center = bounds.getCenter(new THREE.Vector3());
let size = bounds.getSize(new THREE.Vector3());

From that, you could possibly determine the aspect ratio for some shapes.

1 Like

I want to dynamically generate textures for use on various (parts of) shapes, ideally using a HTML canvas. In the example I gave so far that is the side of a cylinder.

In order to correctly display the canvas texture on the model the texture needs to ‘fit onto’ the mesh it is applied to (otherwise you get stretching/etc, as far as I understand it, and this seems logical to me). Right?

Maybe the real question here should be: How do developers usually deal with this case? Is the usual process to just go to the designer, ask them what dimensions that part of the model really has (in my example, asking them what the height and circumference of the cylinder are) and then hard-coding that? To me that seems terribly prone to breaking when minor changes to the model are made (e.g. increasing the height slightly or something).

In the simple case of the side of the cylinder, the world-space bounding box could be used to get the height and to approximate the diameter, and that works reasonably well, but it’s of course not exact since the cylinder is not perfectly smooth. (I should have mentioned that I already tried that, sorry!) This would in principle be good enough but I was sure that there is a ‘nicer’ way of doing this, one that would generalize better. But I am not so convinced anymore.

Edit: I guess the designer could also just make sure that the relevant UVs are proportional to the actual object, then this would not be an issue. But this doesn’t appear to be done usually, and also doesn’t look like it’s very easy to do. So I’m still curious what the usual approach is here.

Edit 2: Nevermind, it looks like proportional unwrapping is pretty easy to do, it seems like this is the way to go.