Меши, отобранные после обновления позиций вершин буферной геометрии

Некоторые объекты отбраковываются после того, как я изменяю положение вершин их геометрии буфера. Я не хочу устанавливать frustrumCulled = false и не могу (реально) изменить положение сетки на что-либо другое, кроме (0,0,0). Какие варианты у меня есть здесь? Я ожидаю, что сетки должны вести себя согласованно друг с другом. Я явно что-то здесь упускаю.

Демо:

  • 2 сетки, одна зеленая, одна красная
  • Зеленая сетка инициализируется с позицией 0,0,0 с вершинами вокруг 0,10,0
  • Красная сетка инициализируется с позицией 0,0,0 с вершинами вокруг 0,0,0, но через 2 секунды вершины обновляются примерно до 0,10,0
  • Элементы управления орбитой позволяют масштабировать (просто увеличьте масштаб, чтобы увидеть фактическое поведение)
  • Ожидаемое поведение: обе сетки видны, когда я масштабирую/двигаю камеру. Или, по крайней мере, они оба ведут себя одинаково
  • Фактическое поведение, зеленая сетка ведет себя так, как ожидалось, красная сетка иногда отбрасывается.

const OrbitControls = THREE.OrbitControls // CDN shim

// Helper to create mesh with buffer geom
const createGeo = (initialY, color) => {
  const geometry = new THREE.BufferGeometry()
  const vertices = new Float32Array([
    0, initialY, 0,
    0, initialY + 1, 0,
    0, initialY, 1,
    0, initialY, 0,
    0, initialY + 1, 0,
    1, initialY, 0
  ])
  geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
  const material = new THREE.MeshBasicMaterial({
    color: color,
    side: THREE.DoubleSide
  })
  mesh = new THREE.Mesh(geometry, material)
  // Note: Setting frustumCulled to false always allows this to be seen, but I don't this object to always be seen
  // mesh.frustumCulled = false

  scene.add(mesh)
  return mesh
}

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 100)
let controls
const greenMesh = createGeo(10, 0x00FF00) // Set Green at 0,10,0
const redMesh = createGeo(0, 0xFF0000) // Set red at 0,0,0, then update to 0,10,0

const renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(() => {
  controls.update()
  greenMesh.rotation.y += 0.1
  redMesh.rotation.y -= 0.1
  renderer.render(scene, camera)
})
document.body.appendChild(renderer.domElement)

controls = new OrbitControls(camera, renderer.domElement)
camera.position.set(15, -20, 15)
controls.target.set(0, 10, 0)
window.onresize = function() {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}

scene.add(new THREE.AxesHelper(100))

// Update red mesh to same position as green mesh
setTimeout(() => {
  redMesh.geometry.attributes.position.setXYZ(0, 0, 10, 0)
  redMesh.geometry.attributes.position.setXYZ(1, 0, 11, 0)
  redMesh.geometry.attributes.position.setXYZ(2, 0, 10, 1)
  redMesh.geometry.attributes.position.setXYZ(3, 0, 10, 0)
  redMesh.geometry.attributes.position.setXYZ(4, 0, 11, 0)
  redMesh.geometry.attributes.position.setXYZ(5, 1, 10, 0)

  // As per - https://threejs.org/docs/#manual/en/introduction/How-to-update-things
  redMesh.geometry.attributes.position.needsUpdate = true
  redMesh.geometry.computeBoundingBox()
  // When zooming / panning, red mesh is not always visible
}, 2000)
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.min.js"></script>

Я думаю, что вы должны добавить redMesh.geometry.computeBoundingSphere() после вызова computeBoundingBox - кажется, это помогает, и это рекомендуется здесь особенно в связи с выбраковкой. Я также нашел актуальным этот старый пост и особенно в «Я нашел проблему» и другие комментарии.

kikon 15.01.2023 16:37

Да... Я включил создание ограничивающей рамки, но похоже, что вам нужно вычислить и ограничивающую рамку, и сферу. Хотя это есть в документах, и я связался с ним в демо, было бы хорошо уточнить причину, по которой это так.

dangarfield 15.01.2023 17:50

Я полагаю, так они это реализовали, и мы должны соответствовать. Мы можем проверить в исходном коде 1) что два метода calculateBoundingBox и computeBoundingSphere независимы (один не вызывает другой) и 2) и bbox, и ограничивающая сфера необходимы, например, в Frustum методах intersectsObject, intersectsBox и т. д.

kikon 15.01.2023 18:30

... Действительно интересно исследовать, почему вы можете обойтись без вычисления ограничивающей сферы, если отбраковка отключена, но я полагаю, что в большинстве случаев безопаснее вызывать обе функции.

kikon 15.01.2023 18:32

Ага. Больше ответов здесь. discourse.threejs.org/t/boundingsphere-and-boundingbox/17868‌​/2 Если вы хотите добавить быстрый однострочный ответ, я соглашусь, в противном случае я просто добавлю ответ позже, но очень ценю . Хотя я не использовал threejs для ряда релизов, я не помню ограничивающих сфер, но они есть в документах, и я предположил, что для использования поля нашей сферы требуется out, но, увы, для отбраковки требуются оба

dangarfield 15.01.2023 18:52

Тогда все в порядке; Пожалуйста, напишите ответ сами.

kikon 15.01.2023 19:02
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминал @kikon, оба

mesh.geometry.computeBoundingBox()
mesh.geometry.computeBoundingSphere()

необходимы. Хотя это явно не указано в этой документации, они оба должны использоваться при обновлении позиций вершин (я сделал неверное предположение, что вы будете использовать либо прямоугольник, либо сферу).

Код для отбраковки усеченного конуса использует ограничивающую сферу, а ограничивающая сфера создается автоматически после первого вызова (отсюда разница в поведении красной и зеленой сетки), и ее необходимо пересчитать, и в этом случае необходимо вызывать оба метода. .

Другие вопросы по теме