Scale in blender and three js

hi guys,I want to design an interior space in Blender, but I’m not sure what scale to use so that the dimensions of the walls, ceiling, and so on don’t get messed up in Three.js. I’d appreciate your guidance.

Three.js renders in meters. So if you create your Blender interior space in meters, you will not have to do any scaling.

Otherwise, three.js is pretty flexible. I have mountains that I created in Blender that are only 1 meter square. Three.js scales them up nicely.

thank you so much for your reply.

I don’t think this is true, three is unit agnostic.

Yep, it is mostly unit agnostic, but there are aspects that force us to think in specific units:

  • some lights are based on physical values and assume distances are in meters
  • if the scene is to be viewed in VR/AR/XR, all distances/sizes must be in meters
  • when interoperability is considered, it depends on the other system (Blender defaults to meters, Maya to centimeters, 3D printing to millimeters, maybe some astronomy software would prefer AU, ly, or pc)

[EDIT:

Most of my comments and the responses that follow are due to my mistaken idea that “agnostic units” meant that people would be inserting objects drawn in different scales into scenes and expecting them to appear the same. But that is not what is being said or what people do. So unless you are a glutton for punishment, you can skip to the end of this discussion for the final answer.

If others don’t care, I wouldn’t have a problem with deleting all the messages starting with this down to PavelBoytchev’s last message.]

=================

That’s interesting. When I google this question I get both answers - that the “official units” are meters and that three.js is unitless.

But don’t units matter for purposes of computing 3D perspective? For example, if the official units are meters, a stick that is 1 meter long will appear to be about 0.1 meters long at 1 meter away and 0.6 meters long at 10 meters away. But if units don’t matter and I am working with units that are 1 centimeter, then it doesn’t make sense to me that a stick that is 1 centimeter long will appear to be 0.1 centimeter long at 1 centimeter away and 0.6 centimeters long at 10 centimeters away.

So while while you can design something in a unitless framework, you need to convert it to the appropriate framework (e.g. 1 unit = 1 meter) for it to render correctly in 3D.

Let me know if my logic is flawed.

ALSO

Units also appear to matter for purpose of computing things like the reduction of light from a light source or the reduction of sound from a sound source.

In three.js, 1 unit = 1 meter is the convention, but the engine itself has no inherent units—it just uses arbitrary unitless numbers that you must scale consistently.

more consider points are

Coordinate system: right-handed, with Y-up (like Blender).
1 unit maps to whatever scale you choose. The convention is 1 unit = 1 meter for physically-based lighting (lights, shadows, fog, camera exposure all assume meter-ish scales).
Use THREE.Mesh position/scale/geometry sizes in these units (e.g., a person ≈ 1.7 units tall).
THREE.Raycaster, physics engines (Cannon.js, Rapier), and glTF assets all rely on this same convention.
so, pick a scale (meters is standard) and be consistent—three.js won’t enforce it.

No. But it does for what @PavelBoytchev listed. Like light decay, possibly XR stuff

Why not? This is exactly how it works.

If a 1 meter stick appears to be 0.1 meters (10% as big) at 1 meter away, then a 1 centimeter stick should also appear to be 0.1 centimeters (10% as big) at 1 meter away. It should not appear to be 0.1 centimeters (10% as big) at only 1 centimeter away.

As you note, as fixed scale is needed for light decay because IRL light decays as a certain rate per meter. Sound does the same thing.

All I am pointing out is that vision works this way too. An object will decrease in apparent size at a certain rate per meter. If you want to switch to a different measure, such as centimeters, then you need to convert the rate of decrease. In the case of centimeters, the rate of decrease will be 1/100th of the rate of decrease per meter.

Unless three.js is using a special formula that somehow converts from different scales, then everything needs to be rendered using a 1 meter scale to get things right.

Does that make sense?

How about a 1.01m stick?

It absolutely should. You should definitely try to make this with three. Make two lines. Scale one by 1/100 (m to cm) and then bring it closer to the camera by 100x.

I think projections do not care about units. Projections, including the perspective projection, are implemented by matrix multiplication. The matrix values are unitless. So, if coordinates are in meters, the result is in meters. If coordinates are in km, the result is in km.

A thing that could interfere is when operations are done GPU-size. GPU numeric precision is not great, so sometimes it is possible to switch units just to make the numbers more comfortable for the GPU.

I have to admit im confused by @phil_crowther wording with the percentage example.

I think this makes little sense:

appears to be 0.1 meters (10% as big)

It’s perspective projection. You could be watching it in a theater, or you could be drawing on a tiny piece of paper. It can be whatever size you want.

Right, it should be bigger.

My brain melted from all this. I misunderstood how it was written. I think everything is correct in this statement, but it doesn’t prove that anything here depends on the scale. Could be light years, could be apples, perspective still works the same.

These are probably incompatible numbers, maybe its not 1m, or maybe its not 80%, but this is the gist of it. Use trigonometry to figure out the exact proportions, FOV etc

I think lets take a FOV of 90deg. a horizontal 1m stick 1m from the camera is going to 50% of the width of the frame. At 10m, 5% (at 10m, the width of the frame is 20m so 1/20)

Totally fair, but the example/confusion was not about precision, but about how perspective behaves. And as we know, this predates computers and bits and numerical precision. Heres Durer raytracing 500 years ago:

Withwhat appears to be the equivalent of a tilt-shift lens, or a skewed perspective.

Here is a rough graphic which I hope illustrates my point:

Say that the cube on the left is a transparent 10x10x10 cube that you are drawing in dimensionless units and it is 50 units away (so the front is 45 units away and the back is 55 units away).

If it turns out that the units are 1 meter and you placed the object 50 meters away, it will look exactly the same. But if the units are only 1/2 meter and you place the object 50 meters away, it will be about 1/2 the size and will look more like the figure on the right.. Here is a CodePen example which shows this result.

However, playing with the CodePen example also showed me that you can make the 5 meter cube appear identical to the the 10 meter cube if you reduce the distance to 25 units. I guess the reason is that if you are bringing the object in closer, smaller changes in distance will have a bigger visual effect.

Because of this later recognition, I now agree that, in the abstract, computations of perspective are dimensionless.

Nevertheless, because of other factors - such as decay in light and sound - shouldn’t we be using meters? Or are those items also dimensionless?

I think you best model all this in threejs. Make sure you change the FOV to see how it acts. I find your mental model very confusing.

Even in this screenshot, it’s the same exact shape, regardless of the unit.

I think Blender is actually Z-up by default.. The GLTF export defaults to swapping Z and Y during export, so things come into threejs oriented as expected.

r.e. unit/unit-less .. earlier threejs versions were more unit agnostic, but with the adoption of more realistic “physical” and pbr materials and lighting, the implicit world unit became meters, for things like light transmission to work in proper physical units.

1 unit == 1 meter is pretty standard across a lot of engines/components, since its usable range happens to map pretty well to floating point. Most/all physics engines I’ve used standardize on meters for instance.

If you have some kind of non-meter based dimensional constraint or input path you have to handle, threejs makes it pretty easy to abstract this away. You can just nest the data underneath a rescaling node, resolving into a world that is 1 unit == 1 meter.

Just to clarify that unit mapping applies to not only sizes, but also to distances.

Assume the initial configuration is: object 10x10x10 units at distance 50 units. The following should produce the same images:

  • 1 unit = 1 meter, object size 10x10x10 meters and the distance is 50 meters
  • 1 unit = 1/2 meters, object size 5x5x5 meters and the distance is 25 meters
  • 1 unit = 0.1 meters, object size 1x1x1 meters and the distance is 5 meters

And a second clarification. Perspective projection is just approximation of how human eyes work. The projection uses flat surface, while for the eye the projection plane (retina) is curved. Additionally, there is refraction happening in the eye (cornea, lens, vitreous).

Fortunately, at small angles, when objects are near the center of the vision field, the perspective projection is very close to what we see. But for peripheral objects that are far away from the center, the perspective projection becomes unnatural. You may have seen this with wide FOVs – a sphere’s projection distorts into ellipse.