我可以在渲染过程中使用three.js 在每一帧中合并几何体吗? [英] Can I merge geometry in every frame in rendering process using three.js?
问题描述
我是 Three.js 的新手,刚刚尝试了一些想法.现在的问题是我在场景中创建了一条线,并将其用作克隆和变换的基础.这样克隆出来的就会在场景中显示为一个变换序列.
I'm new to three.js and just tried some ideas. Now the problem is I created a line in the scene and used it as a base to clone and transform. So that the cloned ones will be shown as a sequence of transformation in the scene.
简化后的代码如下:
var line, scene, camera, light, renderer;
var frame = 0;
var random_degree = Math.round(Math.random() * 360);
var container = document.getElementById( 'container' );
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
scene.add( camera );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 200;
var material = new THREE.LineBasicMaterial({
transparent: true,
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( -100, 0, 0 ),
new THREE.Vector3( 0, 100, 0 ),
new THREE.Vector3( 100, 0, 0 )
);
line = new THREE.Line( geometry, material );
//borrowed the code from http://threejs.org/docs/#Reference/Objects/Line
//just wanted to make it simple
}
function animate() {
requestAnimationFrame( animate );
frame ++;
if( frame < 1500){
var newCurve = line.clone();
newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.material.opacity = 0.2;
scene.add(newCurve);
}
renderer.render( scene, camera );
}
和 html 部分只是 <div id='container'></div>
and The html part is just <div id='container'></div>
一切正常,但是正如你所看到的,我只能将新行号限制为 1500,当行号超过 2000 时,我开始出现渲染问题,之后帧率迅速下降,当行数增加.
It is all working well, but as you can see that I can only limit the new line numbers to 1500, when the line number is over 2000, I started to get rendering problem, the the fps drops quickly after then when the number of lines increasing.
我尝试合并:
var totalGeometry = new THREE.Geometry();
....
function init(){
....
for(var i=0; i< 1500; i++){
var newCurve = line.clone();
newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.updateMatrix();
totalGeometry.merge(newCurve.geometry, newCurve.matrix);
}
var totalLine = new THREE.Line(totalGeometry, material);
....
}
但是我只能在init进程中合并,不能在渲染进程中合并.如果我在 function animate()
中使用上面的代码,它只会渲染一行而不是一整组线:
But I can only merge in the init process not in the rendering process. If I use the above code in function animate()
, It only render one line instead of a whole group of lines:
function animate(){
.....
if( frame < 1500){
var newCurve = curve1.clone();
newCurve.rotation.x = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.y = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.rotation.z = ((random_degree + frame * 0.25) % 360) * Math.PI / 180;
newCurve.material.opacity = 0.2;
newCurve.updateMatrix();
totalGeo.merge(newCurve.geometry, newCurve.matrix);
totalMesh = new THREE.Line(totalGeo, newCurve.material);
scene.add(totalMesh);
}
}
有人有建议吗?谢谢.
推荐答案
您可以使用 THREE.BufferGeometry
来更新您的线条几何图形,而无需合并几何图形或向场景中添加新的线条对象.像这样你会节省很多内存,它会让你得到同样的效果.
You can use a THREE.BufferGeometry
to update your line geometry without merging geometries or adding new line objects to your scene. Like this you will save a lot of memory and it will allow you to get the same effect.
我更新了你的小提琴来演示.
I updated your fiddle here to demonstrate.
首先,您需要创建一个缓冲区几何图形(在 getBufferGeometry
函数中完成):
First you need to create a buffer geometry (done in the getBufferGeometry
function):
/**
* Create a buffer geometry
* Positions attribute with 3 vertices per point
*/
function getBufferGeometry() {
var geometry = new THREE.BufferGeometry();
positions = new Float32Array(total * 3);
geometry.addAttribute(
'position', new THREE.BufferAttribute(positions, 3)
);
return geometry;
}
然后奇迹发生在 addLine
函数中:
And then the magic happens here in the addLine
function:
/**
* Add a new line to the geometry on each call
*/
function addLine() {
if (count < total) {
vertices = getVertices();
var index = count * 9;
positions[index] = vertices[0].x;
positions[index++] = vertices[0].y;
positions[index++] = vertices[0].z;
positions[index++] = vertices[1].x;
positions[index++] = vertices[1].y;
positions[index++] = vertices[1].z;
positions[index++] = vertices[2].x;
positions[index++] = vertices[2].y;
positions[index++] = vertices[2].z;
var start = count * 3;
var end = start + 3;
bufferGeometry.addGroup(start, end);
line.geometry.attributes.position.needsUpdate = true
count++;
}
}
此解决方案基于 @WestLangley 他在此处针对另一个相关问题的回答.
This solution is based on @WestLangley his answer on another related question here.
您仍然需要在示例中设置最大点数,此值设置为代码顶部的 total
.
You will still need to set an maximum amount of points in the example this value is set as total
at the top of the code.
这篇关于我可以在渲染过程中使用three.js 在每一帧中合并几何体吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!