Three.js绳索/电缆效果-动画粗线 [英] Three.js rope / cable effect - animating thick lines

查看:77
本文介绍了Three.js绳索/电缆效果-动画粗线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Three.js,我想创建对象从电缆或绳索摆动的效果.它不需要真正的物理原理,因为摇摆"对象仅遵循固定的动画.最简单的解决方案是使用THREE.Line,但是问题是THREE.Line只能为1px粗,看上去有点可怕.

With Three.js I want to create the effect of an object swinging from a cable or rope. It doesn't require real physics as the "swinging" object simply follows a fixed animation. The easiest solution is using the THREE.Line, however the problem is that THREE.Line can only be 1px thick and looks kinda awful.

在three.js示例中,有一个胖线"示例:

In the three.js examples there is a "fat lines" example :

https://threejs.org/examples/?q=lines#webgl_lines_fat

但是问题是,一旦我使用LineGeometry()创建了线条,就无法弄清楚如何对其进行动画处理.

however the problem is that once I have created the line using LineGeometry() I cannot figure out how to animate it.

到目前为止,我发现的唯一解决方案是删除然后在每帧中创建新行,这行得通,但似乎是一种非常不经济,优化欠佳的方法.

The only solution I have found so far is to delete then create a new line every single frame, which works but seems like a really uneconomical, poorly optimized way to do it.

有人知道一种更好的方法来动画线几何"而不用删除和替换每一帧吗?还是three.js中还有另一种方法可以让我创建更粗的动画线?

Does anyone know of a better way to either animate Line Geometry without having to delete and replace each frame? Or is there another method within three.js which would allow me to create thicker animated lines?

谢谢!

推荐答案

我实际上有一个小项目,我在其中为沿某些绳索摆动的灯泡设置动画.您可以在此处进行访问,我在下面谈论的功能在helperFns.js.

I actually have a small project where I animate a bulb swinging along some rope. You can access it here, the functions I'm talking about below are in helperFns.js.

实际上,我基本上要做的是分别创建我的附加对象:

Actually, what I basically do is create my attached object separately :

let geometry = new THREE.SphereGeometry( 1, 32, 32 );
var material = new THREE.MeshStandardMaterial({color:0x000000,emissive:0xffffff,emissiveIntensity:lightIntensity});
bulb = new THREE.Mesh( geometry, material );
light = new THREE.PointLight(0xF5DCAF,lightIntensity,Infinity,2)
light.power = lightIntensity*20000
light.position.set(0,length*Math.sin(theta),z0-length*Math.cos(theta))
light.add(bulb)
light.castShadow = true;
hemiLight = new THREE.HemisphereLight( 0xddeeff, 0x0f0e0d, 0.1 );
scene.add(hemiLight)
scene.add(light)

然后我添加一个连接到它的样条线:

I then add a spline connected to it :

// Create the wire linking the bulb to the roof
var curveObject = drawSpline(light.position,{x:0,y:0,z:z0},0xffffff);
scene.add(curveObject)

其中drawSpline是以下函数:

Where drawSpline is the following function :

// Build a spline representing the wire between the roof and the bulb. The new middle point is computed as the middle point shifted orthogonally from the lign by shiftRatio
function drawSpline(beginning,end,clr){
    // Compute y sign to know which way to bend the wire
    let ySign = Math.sign((end.y+beginning.y)/2)
    // Compute the bending strength and multiply per Math.abs(beginning.y) to ensure it decreases as the bulb gets closer to the theta = 0 position, and also to ensure
    // that the shift is null if thete is null (no discontinuity in the wire movement)
    let appliedRatio = -shiftRatio*Math.abs(beginning.y)
    // Compute middle line position vector and the direction vector from the roof to the bulb
    let midVector = new THREE.Vector3( 0, (end.y+beginning.y)/2, (end.z+beginning.z)/2 )
    let positionVector = new THREE.Vector3(0,end.y-beginning.y,end.z-beginning.z)
    // Compute the orthogonal vector to the direction vector (opposite sense to the bending shift)
    let orthogVector = new THREE.Vector3(0,positionVector.z,-positionVector.y).normalize() 


    // Compute the curve passing by the three points
    var curve = new THREE.CatmullRomCurve3( [
        new THREE.Vector3( beginning.x, beginning.y, beginning.z ),
        midVector.clone().addScaledVector(orthogVector,ySign*appliedRatio),
        new THREE.Vector3( end.x, end.y, end.z ),
    ]);

    // Build the curve line object
    var points = curve.getPoints( 20 );
    var geometry = new THREE.BufferGeometry().setFromPoints( points );
    var material = new THREE.LineBasicMaterial( { color : clr } );

    // Create the final object to add to the scene
    var curveObject = new THREE.Line( geometry, material );
    return curveObject;
}

它创建 CatmullRomCurve3 ,对3个点进行插值(一个固定点在(0,0,0),一个中间点进行折弯,以及灯泡位置.实际上,您可以从一个直线,然后尝试计算一些曲线.
为此,您想要使向量与线正交,并沿该向量移动线(在正面).

It creates the CatmullRomCurve3 interpolating the 3 points (one fix end at (0, 0, 0), one middle point to apply the bend, and the bulb position. You can actually start with a straight line, and then try to compute some curve.
To do so, you want to get the vector orthogonal to the line and shift the line (on the good side) along this vector.

最后,在每个animate()调用中,我为灯泡的新位置重新绘制样条线:

And finally, at each animate() call, I redraw the spline for the new position of the bulb :

scene.children[2] = drawSpline(light.position,{x:0,y:0,z:z0},0xffffff)

告诉我您有什么不明白的地方,但这应该可以解决您的问题.

Tell me if there is a point you do not get, but it should help for your problem.

这篇关于Three.js绳索/电缆效果-动画粗线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆