使用three.js在三维模型之间转换顶点
我试图实现多边形吹扫和重组效果,类似于:使用three.js在三维模型之间转换顶点,three.js,glsl,shader,buffer-geometry,Three.js,Glsl,Shader,Buffer Geometry,我试图实现多边形吹扫和重组效果,类似于: 在这两个示例中,您可以看到它们如何将顶点从一个三维模型变形/转换到另一个三维模型,从而产生非常酷的效果。我有一些类似的工作,但我无法理解它们如何使用速度偏移来转换顶点(请参考第一个链接,了解粒子如何不简单地映射并轻松移动到新位置,而是使用一些角度偏移): 因此,我在Three.js中导入我的两个模型,取一个具有较大顶点数的模型并复制其几何体,同时将第二个模型的模型数据作为属性附加: class CustomGeometry extends TH
class CustomGeometry extends THREE.BufferGeometry {
constructor (geometry1, geometry2) {
super()
let { count } = geometry1.attributes.position
// this will hold
let targetArr = new Float32Array(count * 3)
let morphFactorArr = new Float32Array(count)
for (let i = 0; i < count; i += 3) {
targetArr[i + 0] = geometry2.attributes.position.array[i + 0] || 0
targetArr[i + 1] = geometry2.attributes.position.array[i + 1] || 0
targetArr[i + 2] = geometry2.attributes.position.array[i + 2] || 0
let rand = Math.random()
morphFactorArr[i + 0] = rand
morphFactorArr[i + 1] = rand
morphFactorArr[i + 2] = rand
}
this.addAttribute('a_target', new THREE.BufferAttribute(targetArr, 3))
this.addAttribute('a_morphFactor', new THREE.BufferAttribute(morphFactorArr, 1))
this.addAttribute('position', geometry1.attributes.position)
}
}
这是可行的,但真的很无聊。顶点只是从一个模型映射到另一个模型,没有任何偏移,没有重力或任何你想加入混合的东西
此外,由于如果顶点数不匹配,我会将0附加到一个位置,因此未使用的位置只会缩放到vec4(0.0、0.0、0.0、1.0),这同样会导致单调乏味的效果(这里是兔子和大象模型之间的变形)
(请注意,未使用的兔子顶点如何简单地缩小到0)
如何处理这样的问题
另外,在未来,他们是如何做到这一点的
THREE.BoxBufferGeometry()
:
var sideLenght = 10;
var sideDivision = 50;
var cubeGeom = new THREE.BoxBufferGeometry(sideLenght, sideLenght, sideLenght, sideDivision, sideDivision, sideDivision);
var attrPhi = new Float32Array( cubeGeom.attributes.position.count );
var attrTheta = new Float32Array( cubeGeom.attributes.position.count );
var attrSpeed = new Float32Array( cubeGeom.attributes.position.count );
var attrAmplitude = new Float32Array( cubeGeom.attributes.position.count );
var attrFrequency = new Float32Array( cubeGeom.attributes.position.count );
for (var attr = 0; attr < cubeGeom.attributes.position.count; attr++){
attrPhi[attr] = Math.random() * Math.PI * 2;
attrTheta[attr] = Math.random() * Math.PI * 2;
attrSpeed[attr] = THREE.Math.randFloatSpread(6);
attrAmplitude[attr] = Math.random() * 5;
attrFrequency[attr] = Math.random() * 5;
}
cubeGeom.addAttribute( 'phi', new THREE.BufferAttribute( attrPhi, 1 ) );
cubeGeom.addAttribute( 'theta', new THREE.BufferAttribute( attrTheta, 1 ) );
cubeGeom.addAttribute( 'speed', new THREE.BufferAttribute( attrSpeed, 1 ) );
cubeGeom.addAttribute( 'amplitude', new THREE.BufferAttribute( attrAmplitude, 1 ) );
cubeGeom.addAttribute( 'frequency', new THREE.BufferAttribute( attrFrequency, 1 ) );
如您所见,所有的魔法都发生在顶点着色器及其rtp2xyz()
函数中
最后,动画功能的代码:
var clock = new THREE.Clock();
var timeVal = 0;
render();
function render(){
timeVal += clock.getDelta();
requestAnimationFrame(render);
uniforms.time.value = timeVal;
uniforms.interpolation.value = slider.value;
renderer.render(scene, camera);
}
哦,是的,我们的页面中有一个滑块控件:
<input id="slider" type="range" min="0" max="1" step="0.01" value="0.5" style="position:absolute;width:300px;">
FYI:适用于所有支持WebGLhey的浏览器,非常感谢您提供的详细答案!我的大脑在思考如何做new\u position=vec3(某物)
,然后在下一行为它添加另一个值。。。因为我在上面的一行用=
符号设置它。然后,我看到您实际上也在rtp2xyz()
中使用了插值值,它开始变得有意义了。。。。基本上,只要我使用插值
值作为偏移量,我就可以对位置做任何事情,添加柏林噪声、向量场等等。。正确吗?另外,请您详细说明一下:sin(a_=factor*3.1415926)*2.0
?为什么我们要乘以π?因为sin(0)
和sin(PI)
等于0(当a_变形因子从0到1时),当a_变形因子
为0.5时,sin处的半径最大(PI*0.5)。谢谢你的帮助,我想我现在真的得到了!已经有东西在运行了
var clock = new THREE.Clock();
var timeVal = 0;
render();
function render(){
timeVal += clock.getDelta();
requestAnimationFrame(render);
uniforms.time.value = timeVal;
uniforms.interpolation.value = slider.value;
renderer.render(scene, camera);
}
<input id="slider" type="range" min="0" max="1" step="0.01" value="0.5" style="position:absolute;width:300px;">