其实这是非常容易实现的。
- 要创建可更新网格,必须在调用CreateXXX()方法时将其可更新参数设置为true 。
- 要更新现有的参数形状,我们只需使用与构造它相同的CreateXXX方法。
- 只有现有网格和与新位置相关的数据(路径、路径数组、点数组)必须传递给此方法,其他参数将被忽略。
- 如果我们想变形网格,我们然后在渲染循环中使用CreateXXX()方法。
在这种情况下,重要的是不要在每帧分配新内存:我们通过索引访问我们的数组,只是更改值而不是创建新数组,我们访问现有对象而不是实例化新对象等。我们还关注权重每个对象的数量(边数、顶点数等)。
例:如果我们需要在渲染循环中更新一个Lines网格,也就是说每帧更新points数组,最好改变每个数组元素的值(points[i].x = newXValue; points[i] .y = newYValue; points[i].z = newZValue; ) 在for循环中,而不是实例化一个新的points数组。
//第一步,x,z的顶点数组
var pathFun=k=>{
let path=[]
for(let i=0;i<60;i++){
path.push(new BABYLON.Vector3(i-30,0,k))
}
return path
}
//第二布,创建y的顶点数组,k作为动态更新的参数
var updatePath=function(path,k){
//alert(path.lenght)
for(let i=0;i<path.length;i++){
path[i].x=path[i].x
path[i].y=20*Math.sin(k+i/10)
path[i].z=path[i].z
}
}
//第三步,创建网,创建丝带
var pathArry=[]
for(let i=-20;i<20;i++){
pathArry.push(pathFun(i*2))
}
let mesh=BABYLON.Mesh.CreateRibbon('rib',pathArry,false,
false,0,scene,true,BABYLON.Mesh.BACKSIDE)
mesh.material=mat
//第四步,在渲染循环中更新k的值,然后改变丝带的数据
scene.registerBeforeRender(()=>{
for(let i=0;i<pathArry.length;i++){
updatePath(pathArry[i],k)
}
mesh=BABYLON.Mesh.CreateRibbon(null,pathArry,
null,null,null,null,null,null,mesh)
k+=0.05
)}
当然更新网格还可以使用meshBuilder,这样显得简洁:
mesh = BABYLON.MeshBuilder.CreateRibbon(null,
{pathArray: pathArray, instance: mesh});
曲线也是一样的道理:
let path=[]
for(let i=-100;i<100;i++){
path.push(new BABYLON.Vector3(i/10,0,0))
}
let lines = BABYLON.Mesh.CreateLines("lines",path,scene,true);
lines.color=new BABYLON.Color3.Red()
function updateline(path,k){
for(let i=0;i<path.length;i++){
path[i].x=path[i].x
path[i].y=Math.sin(i/10+k)
path[i].z=Math.cos(i/10+k)
}
return path
}
let k=0
camera.setTarget(new BABYLON.Vector3(0,0,0))
//第四步,在渲染循环中更新k的值,然后改变丝带的数据
scene.registerBeforeRender(()=>{
updateline(path,k)
lines=BABYLON.Mesh.CreateLines(null,path,null,null,lines);
k+=0.1
})
管子示例:
let path=[]
for(let i=0;i<20;i++){
path.push(new BABYLON.Vector3(i*2,0,0))
}
let mesh=BABYLON.Mesh.CreateTube('tube',path,5,16,null,0,scene,true)
let updatePath=function(path,k){
for (var i = 0; i < path.length; i++) {
path[i].y =5*Math.sin(i/10+k*2);
}
}
let k=0
scene.registerBeforeRender(()=>{
let rad1=function(){
return 2*Math.sin(k)
}
var rad2= function(i,distance) {
return 1+2*Math.sin(i/2 +k);
};
updatePath(path,k)
mesh=BABYLON.Mesh.CreateTube(null,path,rad1,null,rad2,
null,null,null,null,mesh);
k+=0.01
})
对于盒子之类:
需要在更新顶点位置后使用updateMeshPositions()方法:
var box = BABYLON.Mesh.CreateBox("box", 50, scene, true);
box.material = mat;
var angle = 0;
scene.registerBeforeRender(function () {
var updatePositions = function (positions) {
var delta = angle;
for (var idx = 0; idx < positions.length; idx += 3) {
positions[idx + 0] += Math.sin(positions[idx + 1] / 6 + delta);
positions[idx + 2] += Math.sin(positions[idx + 0] / 12 + delta);
delta += 0.00005;
}
};
pl.position = camera.position;
box.updateMeshPositions(updatePositions);
angle += 0.5;
});
以前的CreateXXX()更新函数尝试尽可能多地优化以在渲染循环中快速运行。
但是,您可能出于任何原因需要更高的速度(例如,具有数十万个顶点的巨大网格)。
因此,如果您的网格不需要反射光(例如仅发射颜色),您可以跳过法线重新计算,这是一个消耗 CPU 的过程。
然后在创建网格后使用freezeNormals()方法需要重新设置法线计算过程,请使用一次unfreezeNormals()方法。
本文含有隐藏内容,请 开通VIP 后查看