15
2020
10

babylonjs屏幕坐标世界坐标转换

屏幕坐标世界坐标转换,参考:https://www.babylonjs-playground.com/#1EJNKR#83

网上大多数都是抄的这个。

核心代码,如下:

public screenToWorld(point: Vector2): Vector3 {
  //https://www.babylonjs-playground.com/#1EJNKR#83
  const viewport: Viewport = this.camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight());
  return Vector3.Unproject(new Vector3(point.x, point.y, 0), viewport.width, viewport.height, Matrix.Identity(), this.camera.getViewMatrix(), this.camera.getProjectionMatrix());
}

public worldToSceen(point: Vector3): Vector3 {
  const viewPort: Viewport = this.camera.viewport.toGlobal(this.engine.getRenderWidth(), this.engine.getRenderHeight());
  return Vector3.Project(point, Matrix.Identity(), this.scene.getTransformMatrix(), viewPort);
}

用了Vector3d的Project和Unproject方法。


世界坐标是3维的,屏幕坐标是2维的。2维转3维,必须加个约束,要不转不过去;3维转2维,必须加个约束,要不有无穷多解。

上面的方法,加的约束就是ViewPort对应的平面。

屏幕坐标如何转到指定的平面呢?

比如,拖动地面上的物体,点击屏幕在地面上创建物体等等。

一种是使用pick方法,参见:https://www.babylonjs-playground.com/#12ZRI0#5

核心代码:

public screenToGround(point: Vector2): Vector3 {
  // https://www.babylonjs-playground.com/#12ZRI0#5
  const pickinfo: PickingInfo = this.scene.pick(point.x, point.y, (mesh: Mesh) => { return mesh == this.ground; });
  if (pickinfo.hit) {
    return pickinfo.pickedPoint;
  }
  return null;
}

还有一种是直接计算射线和平面的交点。参考:https://www.babylonjs-playground.com/#1BGF1O#1

核心代码:

public intersectRayPlane(pRay: Ray, pPlane: Plane): Vector3 {
  let tIsecPoint: Vector3 = null;
  const tDot: number = Vector3.Dot(pRay.direction, pPlane.normal);
  if (tDot !== 0.0) {
    const t: number = -pPlane.signedDistanceTo(pRay.origin) / tDot;
    if (t >= 0.0) {
      const tDirS: Vector3 = pRay.direction.scale(t);
      tIsecPoint = pRay.origin.add(tDirS);
    }
  }
  return tIsecPoint;
}

public screenToPlane(point: Vector2, plane: Plane): Vector3 {
  // https://www.babylonjs-playground.com/#1BGF1O#1
  const tRay: Ray = this.scene.createPickingRay(this.scene.pointerX, this.scene.pointerY,
    BABYLON.Matrix.Identity(), this.camera);
  return this.intersectRayPlane(tRay, plane);
}

以上两个方法的案例都是从这里找到的:https://www.html5gamedevs.com/topic/28075-pick-at-ground-level/

这个也可以看看:https://www.babylonjs-playground.com/#1BGF1O#3



« 上一篇下一篇 »

相关文章:

babylonjs显示坐标轴  (2020-10-15 10:39:55)

Babylonjs加载模型  (2020-10-12 18:9:11)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。