我正在做一个AR项目,其中一个对象检测AI返回检测对象的顶点。
在场景中,我将检测到的对象作为父网格,并在场景中设置了一个叫做 BufferGeometry
和 position attributes
当顶点发生变化时,我需要计算它的变换矩阵,并将这些变换应用到它的子代。
我如何计算一个 "检测(位置顶点)"到另一个 "检测(位置顶点)"的变换矩阵(转换、缩放、旋转)。
这里是我的问题的一个简化的例子,蓝色的平面是被检测到的对象,红色的是它的子对象,我需要计算蓝色的平面从它的前一个位置的变换,把它们应用到红色的,这样它们就可以一起移动。
谢谢,我正在做一个AR项目。
如果你知道子几何体要比父几何体大一半,只需应用 child.scale.set(0.5, 0.5, 0.5);
然后在更新时指定与父节点完全相同的顶点位置。
parentGeometry.getAttribute('position').array = parentPositions[posIndex];
parentGeometry.getAttribute('position').needsUpdate = true;
childGeometry.getAttribute('position').array = parentPositions[posIndex];
childGeometry.getAttribute('position').needsUpdate = true;
Three.js引擎会将12个比例和Z轴的+5应用到子顶点上,所以你不必担心手动进行这些调整。请看下面的演示。
(注意我创建了 Float32Array
内 parentPositions[]
作为优化,这样你就不用再做一个新的数组和一个新的 BufferAttribute
每次更新它们时,都会有明显的性能提升。在只有4个顶点的情况下,性能提升并不明显,但当你有1000个顶点时,它确实有帮助)。)
var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 1000 );
var renderer = new THREE.WebGLRenderer({antialias : true});
renderer.setClearColor(0x444444);
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.z = 100;
new THREE.OrbitControls( camera, renderer.domElement );
/* Helpers */
// Grid helper
var width = 100;
var height = 100;
var gridHelper = new THREE.GridHelper(width * 2, 10, 0x999999, 0x000000);
gridHelper.position.y = -height / 2;
scene.add(gridHelper)
// Axes helper
scene.add(new THREE.AxesHelper(50));
/* parent Mesh */
var parentGeometry = new THREE.PlaneBufferGeometry(width, height);
var parentMaterial = new THREE.MeshBasicMaterial( { color: 0x209ad6} );
var parent = new THREE.Mesh( parentGeometry, parentMaterial );
scene.add(parent);
/* Child mesh */
var childGeometry = new THREE.PlaneBufferGeometry(width, height);
var childMaterial = new THREE.MeshBasicMaterial( {color: 0xFF0000} );
var child = new THREE.Mesh( childGeometry, childMaterial );
parent.add(child);
// Apply desired transformations to the child Mesh
child.position.z = 5;
child.scale.set(0.5, 0.5, 0.5);
/* Parent positions */
// Make all position arrays Float32Array
// so we don't have to create a new one each frame.
var parentPositions = [
//Reference point
new Float32Array([
-50, 50, 0,
50, 50, 0,
-50, -50, 0,
50, -50, 0
]),
//Variations
new Float32Array([
-50, 50, 50,
50, 50, 50,
-50, -50, -50,
50, -50, -50
]),
new Float32Array([
-75, 75, -25,
75, 75, -25,
-75, -75, 25,
75, -75, 25
]),
new Float32Array([
0, 75, -25,
75, 0, -25,
-75, 0, 25,
0, -75, 25,
]),
//... random positions
];
var lastTime = 0;
var posIndex = 0;
function render(currentTime) {
requestAnimationFrame( render );
// Update position attributes
// Instead of making a new attribute on each update
if (currentTime >= lastTime + 1000) {
parentGeometry.getAttribute('position').array = parentPositions[posIndex];
parentGeometry.getAttribute('position').needsUpdate = true;
childGeometry.getAttribute('position').array = parentPositions[posIndex];
childGeometry.getAttribute('position').needsUpdate = true;
lastTime = currentTime;
posIndex = posIndex === 3 ? 0 : posIndex + 1;
}
renderer.render( scene, camera );
}
render()
html, body {margin: 0; padding: 0;overflow: hidden;}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r110/examples/js/controls/OrbitControls.js"></script>
我不知道为什么你原来把子节点做成了一个 PlaneGeometry
但我不得不把它改成与母体相匹配的。PlaneBufferGeometry
.
我想我现在才开始明白你的问题是什么 你需要计算垂直于你的平面面的矢量。你可以从四个顶点中任选三个来做这件事。
你可以用 本回答 来计算出三角形指向的是哪一点,然后你就可以进行 child
指向 child.lookAt(x, y, z);
您可以阅读 本文 对于如何获得该垂直度的更深入的解释。