首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Three.js,计算两个BufferGeometry位置状态之间的转换矩阵

Three.js,计算两个BufferGeometry位置状态之间的转换矩阵
EN

Stack Overflow用户
提问于 2020-06-18 22:29:52
回答 1查看 720关注 0票数 1

我正在做一个AR项目,在这个项目中,对象检测AI返回检测到的对象的顶点。

在场景中,我将检测到的对象作为具有BufferGeometry和从AI输出更新的position attributes的父网格,我需要在顶点变化时计算其变换矩阵,并将这些变换应用于其子对象。

如何计算从一个“检测(位置顶点)”到另一个“检测(位置顶点)”的转换矩阵(平移、缩放、旋转)。

这是我的问题的一个简化说明,其中蓝色平面是检测到的对象,红色平面是它的子对象,我需要计算蓝色平面变换,将它们应用到红色平面上,这样它们就可以一起移动:

https://jsfiddle.net/uv76tj89/1/

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2020-06-19 03:12:03

如果知道子几何体的大小将是父几何体的一半,只需应用child.scale.set(0.5, 0.5, 0.5);,然后在更新时指定与父几何体完全相同的顶点位置:

代码语言:javascript
复制
parentGeometry.getAttribute('position').array = parentPositions[posIndex];
parentGeometry.getAttribute('position').needsUpdate = true;
childGeometry.getAttribute('position').array = parentPositions[posIndex];
childGeometry.getAttribute('position').needsUpdate = true;

Three.js引擎将对子顶点应用z轴的1/2比例和+5,因此您不必担心手动进行这些调整。请看下面的演示。

(请注意,作为优化,我在parentPositions[]中创建了Float32Array,这样您就不必在每次更新它们时创建新的数组和新的BufferAttribute。它在只有4个顶点的情况下没有明显的性能提升,但当你有1000个顶点时,它确实有帮助)。

代码语言:javascript
复制
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()
代码语言:javascript
复制
html, body {margin: 0; padding: 0;overflow: hidden;}
代码语言:javascript
复制
<script src="https://cdn.jsdelivr.net/npm/three@0.117.1/build/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r110/examples/js/controls/OrbitControls.js"></script>

我不确定您最初为什么使子PlaneBufferGeometry成为PlaneGeometry,但我必须更改它以匹配父PlaneBufferGeometry

编辑:

我想我现在才开始了解你的问题是什么,你需要计算垂直于平面的向量。您可以从四个顶点中选取任意三个来执行此操作:

您可以使用this answer找出三角形指向的点,然后使用child.lookAt(x, y, z);使child指向该方向

你可以阅读this article,了解更多关于如何获得垂直度的深入解释。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62452357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档