在我的项目中,我有一个玩家环游世界。地球不仅是一个球体,而且还有山脉和山谷,因此我需要玩家的z位置进行更改。为此,我从玩家的位置向单个物体(地球)发出光线,然后得到它们相交的点并相应地更改玩家的位置。我只是在播放器移动时发出光线,而不是在每一帧上播放。
对于一个复杂的对象,它需要永远的时间。具有约1m个多边形(面)(1024x512分段球面)的对象大约需要200毫秒。光线投射会投射到每个人的脸上吗?
是否有传统的快速方法可以在三个时间内实现这一目标,例如某种加速结构(八叉树?bvh?-来自我的google搜索的tbh,我似乎没有发现这样的东西包含在三个中)或其他一些思考方式-开箱即用(无射线投射)方法?
var dir = g_Game.earthPosition.clone();
var startPoint = g_Game.cubePlayer.position.clone();
var directionVector = dir.sub(startPoint.multiplyScalar(10));
g_Game.raycaster.set(startPoint, directionVector.clone().normalize());
var t1 = new Date().getTime();
var rayIntersects = g_Game.raycaster.intersectObject(g_Game.earth, true);
if (rayIntersects[0]) {
var dist = rayIntersects[0].point.distanceTo(g_Game.earthPosition);
dist = Math.round(dist * 100 + Number.EPSILON) / 100;
g_Player.DistanceFromCenter = dist + 5;
}
var t2 = new Date().getTime();
console.log(t2-t1);
提前谢谢
答案 0 :(得分:7)
请勿使用three.js Raycaster。
考虑提供function intersectTriangle(a, b, c, backfaceCulling, target)
的{{3}}
建议的优化
如果玩家从某个已知位置开始⇒您必须知道他的初始身高,−无需进行射线投射(或只进行一次全网格慢速交点)
如果玩家以较小的步伐移动⇒下一次光线投射将最有可能与同一张脸相交。
优化#1 -记住前一张脸,然后进行光线投射。
优化#2 -建立缓存,以便在给定人脸idx的情况下,您可以在O(1)时间内检索相邻的人脸。
如果您的星球不是实时生成的,则可能会从文件中加载此缓存。
因此,按照我的做法,您可以从缓存和raycast 1-6面执行O(1)读取操作。
赢!
答案 1 :(得分:6)
我认为,假设地形不是动态的,您应该将地球的高度图预渲染为纹理。将所有内容读取到一个类型化的数组中,然后只要播放器移动,您只需将其坐标反向投影到该纹理中,对其进行查询,偏移和相乘即可,您应该在O(1)时间内得到所需的内容。 / p>
由您决定如何生成该高度图。实际上,如果您有一个凹凸不平的地球,那么您可能应该首先从高度图开始,然后在顶点着色器中使用它来渲染地球(输入球完美平滑)。然后,您可以使用相同的高度图查询玩家的 Z 。
答案 2 :(得分:4)
对于一个复杂的对象,它需要永远的时间。具有约1m个多边形(面)(1024x512分段球面)的对象大约需要200毫秒。光线投射会投射到每个人的脸上吗?
开箱即用THREE.js 在对网格执行raycast时检查每个三角形,并且没有内置任何加速结构。
尽管如此,我已经与其他人一起研究了三目bvh软件包(github,npm),以帮助解决此问题,这可能有助于您加快寻找的速度。使用方法如下:
import * as THREE from 'three';
import { MeshBVH, acceleratedRaycast } from 'three-mesh-bvh';
THREE.Mesh.prototype.raycast = acceleratedRaycast;
// ... initialize the scene...
globeMesh.geometry.boundsTree = new MeshBVH(globeMesh.geometry);
// ... initialize raycaster...
// Optional. Improves the performance of the raycast
// if you only need the first collision
raycaster.firstHitOnly = true;
const intersects = raycaster.intersectObject(globeMesh, true);
// do something with the intersections
自述文件中提到了一些注意事项,因此请记住这些注意事项(修改了网格索引,仅支持非动画化的BufferGeometry等)。还有一些内存优化可以完成,但是有一些可调整的选项可以帮助您进行调整。
我很想听听这对您的运作方式!也可以就如何改进该软件包的问题发表反馈意见。希望有帮助!