为什么Three.js几何图形会大量丢失精度?

时间:2019-02-15 08:11:02

标签: three.js floating-point precision

我正在尝试在Three.js中绘制此六边形。如果我使用较小的数字,它会很好地绘制。但是,如果我使用大数(看起来很适合加倍而不损失精度),Three.js似乎很难准确地绘制它。我已经在code pen here中进行了演示。它的代码如下。请注意,如果将offsetXoffsetY更改为非常大的数字,则它不会绘制相同的数字。我不太清楚为什么,我想知道是否有人可以帮我了解一下。这些数字似乎都适合double类型...

var scene = new THREE.Scene();

const offsetX = 0;
const offsetY = 0;
// comment the previous two lines or following two lines to see the difference 
// const offsetX = 3031034;
// const offsetY = 4647776;

var camera = new THREE.OrthographicCamera(offsetX-3,offsetX+3,offsetY-3,offsetY+3,1,100);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 400);
document.body.appendChild( renderer.domElement );

var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(offsetX + 1.039688, offsetY + 0.850723, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 0.913957, offsetY + 1.068813, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 0.661409, offsetY + 1.069356, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 0.534591, offsetY + 0.851991, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 0.660321, offsetY + 0.633721, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 0.91287, offsetY + 0.633178, 0));
geometry.vertices.push(new THREE.Vector3(offsetX + 1.039688, offsetY + 0.850723, 0));

var material = new THREE.LineBasicMaterial({ linewidth: 1, color: 0x00ff00 });

var line = new THREE.Line( geometry, material );
scene.add( line );

camera.position.z = 5;

renderer.render(scene, camera);

1 个答案:

答案 0 :(得分:2)

虽然您显示的数字可以用double格式足够精确地表示,以使六边形没有可见的扭曲,但是WebGL似乎在整个操作过程中都没有使用double格式。

>

three.js uses WebGLWebGL uses OpenGL ESWebGLOpenGL ES的文档中有关浮点格式或算术的信息不完整或缺失。我们只能根据文档中的倾斜引用和观察到的行为来非正式地推断使用的格式。

该软件中的某些组件很可能正在使用IEEE-754基本的32位二进制浮点格式。在这种格式中,有效位数 1 具有24位。

使用显示的偏移量(例如4,647,776),必须设置浮点格式的指数,以便有效位数的最高位表示4,194,304,即2 22 。那么最低位是2 −1 或½。

这意味着六边形顶点的所有坐标(.661409,.851991,.633721等)将四舍五入到最接近的½。显然,这会使图形失真。修补其他偏移值可显示与32位二进制浮点精度一致的效果。

脚注

1 浮点数由符号位 s ,有效位 f 和指数 e ,并表示值(−1) s f b e ,其中 b 是格式的基数或基数(二进制为2)。有效数字也称为浮点表示的分数部分,因此 f 表示有效数字。