三.js如何在css中定位类似于'contain'的图像纹理?



我的图像纹理相对于3D空间的中心而不是网格定位,我不太明白是什么决定了它的大小。 以下示例显示了同一图像如何定位在不同的网格上: https://i.stack.imgur.com/VL5SF.jpg

我希望图像位于网格的中心,并且它的大小设置类似于 css 中的"包含"。

网格是使用 ShapeBufferGeometry 创建的平面:

const shape = new THREE.Shape( edgePoints );
const geometry = new THREE.ShapeBufferGeometry( shape );

要查看我必须设置的任何图像:texture.repeat.set(0.001, 0.001);

不确定这是否重要,但在创建网格后,我设置其位置和旋转:

mesh.position.copy( position[0] );
mesh.rotation.set( rotation[0], rotation[1], rotation[2] );

我试过设置这些:

mesh.updateMatrixWorld( true );
mesh.geometry.computeBoundingSphere();
mesh.geometry.verticesNeedUpdate = true;
mesh.geometry.elementsNeedUpdate = true;
mesh.geometry.morphTargetsNeedUpdate = true;
mesh.geometry.uvsNeedUpdate = true;
mesh.geometry.normalsNeedUpdate = true;
mesh.geometry.colorsNeedUpdate = true;
mesh.geometry.tangentsNeedUpdate = true;
texture.needsUpdate = true;

我玩过wrapS/wrapT和偏移量。

我已经检查了UV-我还没有完全理解这个概念,但似乎很好。一个网格的UV示例(我知道这些是XY坐标,它们似乎反映了网格的实际角落(:

uv: Float32BufferAttribute
array: Float32Array(8)
0: -208
1: 188
2: 338
3: 188
4: 338
5: 12
6: -208
7: 12

我试过设置:

texture.repeat.set(imgHeight/geometryHeight/1000, imgWidth/geometryWidth/1000);

这是THREE.ShapeGeometry()计算 UV 坐标的方式: https://github.com/mrdoob/three.js/blob/e622cc7890e86663011d12ec405847baa4068515/src/geometries/ShapeGeometry.js#L157

但是您可以重新计算它们,以放入范围[0..1]. 下面是一个示例,单击按钮以重新计算形状几何图形的 uvs:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var grid = new THREE.GridHelper(10, 10);
grid.rotation.x = Math.PI * 0.5;
scene.add(grid);
var points = [
new THREE.Vector2(0, 5),
new THREE.Vector2(-5, 4),
new THREE.Vector2(-3, -3),
new THREE.Vector2(2, -5),
new THREE.Vector2(5, 0)
];
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
var shapeMat = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/uv_grid_opengl.jpg")
});
var mesh = new THREE.Mesh(shapeGeom, shapeMat);
scene.add(mesh);
btnRecalc.addEventListener("click", onClick);
var box3 = new THREE.Box3();
var size = new THREE.Vector3();
var v3 = new THREE.Vector3(); // for re-use
function onClick(event) {

box3.setFromObject(mesh); // get AABB of the shape mesh
box3.getSize(size); // get size of that box

var pos = shapeGeom.attributes.position;
var uv = shapeGeom.attributes.uv;
for (let i = 0; i < pos.count; i++) {
v3.fromBufferAttribute(pos, i);
v3.subVectors(v3, box3.min).divide(size); // cast world uvs to range 0..1
uv.setXY(i, v3.x, v3.y);
}
uv.needsUpdate = true; // set it to true to make changes visible

}
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<button id="btnRecalc" style="position: absolute;">Re-calculate UVs</button>

相关内容

最新更新