三个js如何手动将三角形添加到BufferGeometry [英] Three js how to add triangle to BufferGeometry manually
问题描述
我一直在尝试寻找最快的方法来使用three.js更改网格的顶点.我发现,如果我更改了mesh.geometry.attributes.position.array的一部分,然后设置mesh.geometry.attributes.position.needsUpdate = true,则效果很好,并且无需重建数组或重新创建opengl缓冲区.我发现needsUpdate = true会更改属性的版本号,并使它将属性顶点数组重新发送到opengl缓冲区.
I've been trying to find the fastest way to change a mesh's vertices with three.js. I found that if I change parts of mesh.geometry.attributes.position.array, then set mesh.geometry.attributes.position.needsUpdate=true, it works well and doesn't have to rebuild arrays or recreate opengl buffers. I found that needsUpdate=true changes the version number of the attribute and that makes it resend the attributes vertices array to the opengl buffer.
因此,我尝试自己执行此操作,而不是先调用gl.bindBuffer()然后再调用gl.bufferData(),但是在执行完每个循环一段时间之后,它在我调用new Float32Array()时崩溃了.这很奇怪,因为当我检查内存使用情况时,在崩溃之前我只使用了4MB.我意识到这不是在每个循环中分配/重新分配数组以使其稍大一些的最佳方法,当我可以在数组满时将数组的大小加倍时,使它稍大一些,但是我想了解为什么这样做会导致崩溃.
So I tried doing that myself instead by calling gl.bindBuffer() then gl.bufferData() but then after doing that every loop for a while it crashes on my call to new Float32Array(). Which is weird because when I check my memory usage I'm only using 4MB right before it crashes. I realize it's not the best way to be deallocating/reallocating the array every loop just to make it slightly bigger when I could be doubling the size of the array when it gets full, but I want to understand why it's crashing when done this way.
https://jsfiddle.net/q1txL19c/3/在20秒内崩溃. 但是,如果我将if(0)更改为if(1),那么它将起作用.
https://jsfiddle.net/q1txL19c/3/ Crashes in 20 seconds. But if I change the if(0) to if(1) it works.
Three.js的不同之处是使它不会崩溃?根据分析器,当没有用完太多的JavaScript内存时,为什么新的Float32Array()会失败?
What is three.js doing differently that makes it not crash? Why does new Float32Array() fail when not much javascript memory has been used up according to the profiler?
<!doctype html>
<html>
<body style='margin:0;padding:0'>
<script src="https://threejs.org/build/three.js"></script>
<script>
var camera, scene, renderer, mesh
var triangles = 1
init()
function init()
{
scene = new THREE.Scene()
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, .1, 10000)
camera.position.z = 15
scene.add(camera)
var geometry = new THREE.BufferGeometry()
var material = new THREE.MeshBasicMaterial( {side: THREE.FrontSide, transparent:false, vertexColors: THREE.VertexColors} )
mesh = new THREE.Mesh(geometry, material)
var positions = new Float32Array([1,1,0, 0,1,0, 0,0,0])
geometry.addAttribute('position', new THREE.BufferAttribute(positions,3))
var colors = new Float32Array([0,0,1, 0,0,0, 0,0,0])
geometry.addAttribute('color', new THREE.BufferAttribute(colors,3))
scene.add(mesh)
renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setClearColor( 0x6699DD )
document.body.appendChild(renderer.domElement)
loop()
}
function addTriangle(geometry)
{
// Make 3 new vertices, each with x,y,z. 9 total positions.
var newVertices = []
for(var i=0; i<9; i++)
newVertices[i] = Math.random()*10-5
appendArrayToAttribute(geometry.attributes.position, newVertices)
// Make 3 new colors, 1 for each new vertex, each with r,g,b. 9 total slots.
var newColors = []
for(var i=0; i<9; i++)
newColors[i] = Math.random()
appendArrayToAttribute(geometry.attributes.color, newColors)
}
function appendArrayToAttribute(attribute, arrayToAppend)
{
// Make a new array for the geometry to fit the 9 extra positions at the end, since you can't resize Float32Array
try
{
var newArray = new Float32Array(attribute.array.length + arrayToAppend.length)
}
catch(e)
{
console.log(e)
if(!window.alerted)
{
alert("out of memory!? can't allocate array size="+(attribute.array.length + arrayToAppend.length))
window.alerted = true
}
return false
}
newArray.set(attribute.array)
newArray.set(arrayToAppend, attribute.array.length)
attribute.setArray(newArray)
if(0)
{
attribute.needsUpdate = true
}
else
{
// Have the geometry use the new array and send it to opengl.
var gl = renderer.context
gl.bindBuffer(gl.ARRAY_BUFFER, renderer.properties.get(attribute).__webglBuffer)
gl.bufferData(gl.ARRAY_BUFFER, attribute.array, gl.STATIC_DRAW)
}
}
function loop()
{
requestAnimationFrame(loop)
mesh.rotation.x += 0.01
mesh.rotation.y += 0.02
renderer.render(scene, camera)
for(var i=0;i<10;i++)
{
addTriangle(mesh.geometry)
triangles++
}
if(Math.random()<.03)
{
console.log("triangles="+triangles)
var gl = renderer.context
console.log("gl buffer size="+gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE))
}
}
</script>
</body>
</html>
推荐答案
您可以在第一次渲染后将面添加到BufferGeometry
,但是必须预先分配几何attribute
缓冲区以使其足够大,因为它们可以不能调整大小.
You can add faces to BufferGeometry
after the first render, but you must pre-allocate your geometry attribute
buffers to be large enough, as they can't be resized.
此外,您将更新数组值,而不是实例化新数组.
Also, you will be updating array values, not instantiating new arrays.
您可以像这样更新要渲染的面数:
You can update the number of faces to render like so:
geometry.setDrawRange( 0, 3 * numFacesToDraw ); // 3 vertices for each face
请参见此相关答案和演示.
three.js r.84
three.js r.84
这篇关于三个js如何手动将三角形添加到BufferGeometry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!