Три js: моя точка видна или закрыта?
У меня есть точка в пространстве, выразить вектор в три JS просмотра. К этому пункту прикреплена "HTML-аннотация"
что я хотел бы скрыть, когда точка не видна (за другими поверхностями той же сетки или скрыта другими сетками). Например, на изображении ниже оно должно быть скрыто:
Я использую некоторый код, чтобы проверить, находится ли аннотация в усеченной зоне, как предложено в другом вопросе, но это не совсем работает, так как аннотация исчезает, только когда я поворачиваю объект довольно резко. Смотрите картинку ниже:
Можете ли вы помочь мне решить мою проблему?
Вот мой код до сих пор:
const vector = new THREE.Vector3(x, y, z);
this.aCamera.updateMatrix();
this.aCamera.updateMatrixWorld(true);
let frustum = new THREE.Frustum();
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.aCamera.projectionMatrix, this.aCamera.matrixWorldInverse));
// check if annotation is in view
if (frustum.containsPoint(vector)) {
anAnnotation.css({opacity: 0});
} else {
anAnnotation.css({opacity: 1});
}
1 ответ
Я могу придумать два способа сделать это.
Во-первых, вы можете использовать raycaster (код из памяти, не совсем уверен, что он будет работать на 100% так):
Настройте raycaster лучом, направленным от камеры к вашему маркеру:
// somewhere outside const raycaster = new THREE.Raycaster(); const v = new THREE.Vector3(); // in the animation-loop v.copy(marker.position).sub(camera.position).normalize(); raycaster.set(camera.position, v);
получить объекты, пересекающие этот луч
// you might want to be a bit more specific const intersections = raycaster.intersectObjects(scene, true);
если первое пересечение не является маркером, оно хотя бы частично перекрыто
if (intersections.length > 0 && intersections[0].object !== marker) { // hide marker... }
Это, вероятно, будет хорошо работать для меньшего числа объектов / объектов с ограниченным количеством граней. Для очень сложных объектов raycaster мучительно медленен, и вы можете прибегнуть к использованию предварительно визуализированной карты глубины.
перед рендерингом сцены визуализируйте только окклюдеры в карту глубины (вы можете использовать
object.layers
а такжеcamera.layers
( Layer Docs), чтобы контролировать то, что визуализируется)// outside animation-loop const depthMaterial = new THREE.MeshDepthMaterial({ depthPacking: THREE.RGBADepthPacking }); const depthTarget = new THREE.WebGLRenderTarget( rendererWidth, rendererHeight ); // before rendering scene camera.layers.disable(MARKERS_LAYER); scene.overrideMaterial = depthMaterial; renderer.render(scene, camera, depthTarget); camera.layers.enable(MARKERS_LAYER);
Теперь вы можете проецировать координаты маркера и сравнивать глубину из карты глубины в этой позиции с z-расстоянием маркера. Пожалуйста, посмотрите этот кодовый блок, чтобы узнать, как читать координаты мирового пространства с карты глубины.