Некоторые объекты отбраковываются после того, как я изменяю положение вершин их геометрии буфера. Я не хочу устанавливать frustrumCulled = false
и не могу (реально) изменить положение сетки на что-либо другое, кроме (0,0,0). Какие варианты у меня есть здесь? Я ожидаю, что сетки должны вести себя согласованно друг с другом. Я явно что-то здесь упускаю.
Демо:
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>
Да... Я включил создание ограничивающей рамки, но похоже, что вам нужно вычислить и ограничивающую рамку, и сферу. Хотя это есть в документах, и я связался с ним в демо, было бы хорошо уточнить причину, по которой это так.
Я полагаю, так они это реализовали, и мы должны соответствовать. Мы можем проверить в исходном коде 1) что два метода calculateBoundingBox и computeBoundingSphere
независимы (один не вызывает другой) и 2) и bbox, и ограничивающая сфера необходимы, например, в Frustum методах intersectsObject
, intersectsBox
и т. д.
... Действительно интересно исследовать, почему вы можете обойтись без вычисления ограничивающей сферы, если отбраковка отключена, но я полагаю, что в большинстве случаев безопаснее вызывать обе функции.
Ага. Больше ответов здесь. discourse.threejs.org/t/boundingsphere-and-boundingbox/17868/2 Если вы хотите добавить быстрый однострочный ответ, я соглашусь, в противном случае я просто добавлю ответ позже, но очень ценю . Хотя я не использовал threejs для ряда релизов, я не помню ограничивающих сфер, но они есть в документах, и я предположил, что для использования поля нашей сферы требуется out, но, увы, для отбраковки требуются оба
Тогда все в порядке; Пожалуйста, напишите ответ сами.
Как упоминал @kikon, оба
mesh.geometry.computeBoundingBox()
mesh.geometry.computeBoundingSphere()
необходимы. Хотя это явно не указано в этой документации, они оба должны использоваться при обновлении позиций вершин (я сделал неверное предположение, что вы будете использовать либо прямоугольник, либо сферу).
Код для отбраковки усеченного конуса использует ограничивающую сферу, а ограничивающая сфера создается автоматически после первого вызова (отсюда разница в поведении красной и зеленой сетки), и ее необходимо пересчитать, и в этом случае необходимо вызывать оба метода. .
Я думаю, что вы должны добавить
redMesh.geometry.computeBoundingSphere()
после вызоваcomputeBoundingBox
- кажется, это помогает, и это рекомендуется здесь особенно в связи с выбраковкой. Я также нашел актуальным этот старый пост и особенно в «Я нашел проблему» и другие комментарии.